AnalogTerm2: Add the -g option to support other font sizes.
authorMatthew Mondor <mmondor@pulsar-zone.net>
Sat, 27 May 2023 14:26:40 +0000 (14:26 +0000)
committerMatthew Mondor <mmondor@pulsar-zone.net>
Sat, 27 May 2023 14:26:40 +0000 (14:26 +0000)
mmsoftware/analogterm2/README.txt
mmsoftware/analogterm2/TODO.txt
mmsoftware/analogterm2/src/config.c
mmsoftware/analogterm2/src/config.h
mmsoftware/analogterm2/src/draw.c
mmsoftware/analogterm2/src/font.c
mmsoftware/analogterm2/src/font.h
mmsoftware/analogterm2/src/main.c
mmsoftware/analogterm2/src/screen.c
mmsoftware/analogterm2/src/state.c
mmsoftware/analogterm2/tests/at2-aliases.sh

index fe407e8..acb45a6 100644 (file)
@@ -27,7 +27,7 @@ use.  The monochrome mode can be toggled using a special ATC sequence
 or with the command line option -c.
 
 Future plans include 2x2.5 zoom, better text copy and perhaps
-dynamic window resizing and other font sizes.
+dynamic window resizing.
 
 The main foreground color can be configured using custom "DEC
 Private Mode" ESC sequences or via the command line arguments.  If
@@ -37,6 +37,17 @@ default.  A collection of custom alternative fonts and aliases are
 included in the test/ directory, some are also installed by the
 GNUmakefile.
 
+AnalogTerm 2 uses a 7x9 font matrix by default and includes an
+internal font of that size natively.  It can be started with the
+-g option to support other sizes but it is not dynamic.  When
+started with a smaller font size, the internal font is not activated
+and a font should be loaded in with ATC sequences.  When it is
+started with a larger font matrix, the internal font is still loaded
+but will be smaller than the allocated box for each glyph.  A font
+of the right dimensions should be loaded with ATC sequences to
+fully use the feature.
+
+
 Some ATC sequence examples:
 
 Switch the terminal between color and monochrome modes:
@@ -189,7 +200,7 @@ hand, etc.
 Here is an example to setup a fancy custom statistics display window
 utility.  This also makes use of some of the above aliases.
 
-$ ( atmono; atblue3; atintscan2; atupper; atline; atmixed2; atcurnodisable; cat /usr/local/share/analogterm2/demonseed-font-ansi.txt; atslowscroll; atslowtext4 ) >/tmp/ds-stat-setup.txt
+$ ( atmono; atblue3; atintscan2; atupper; atline; atmixed2; atcurnodisable; cat /usr/local/share/analogterm2/demonseed-font-ansi.txt; atslowscroll; atslowtext5 ) >/tmp/ds-stat-setup.txt
 
 Assuming that ds-stat-setup.txt was also added to
 /usr/local/share/analogterm2/, example custom menu/launcher item
index 3dac72c..ae4a6ed 100644 (file)
@@ -1,3 +1,6 @@
+- When loading custom fonts we may not want to use the internal mappings
+  designed for the internal font.  Perhaps a sequence could activate/disable
+  that automatic mapping.
 - The uses of lastcol in state.c are inconsistent, likely a source of bugs.
 - Interestingly despite our goto implementation attempting to remember to
   update the last and new lines for proper refresh including of the cursor,
@@ -17,6 +20,9 @@
   layout for fast lookup, somewhat like is done with the native font, where
   contiguous blocks are kept together, in case we decide to start blank and
   load a font at startup.
+  VT320 supported soft characters, using sixels.
+  https://www.vt100.net/dec/vt320/soft_characters
+  https://www.vt100.net/dec/vt320/glyphs
 - Eventually provide a way to query terminal specific settings that can be
   altered using sequences and develop a live configuration utility that can
   also store settings.
   modemu, interpreting some AT commands, or directly connected to a real modem
   as a terminal rather than for a shell...
 - Some unicode characters are double-width.  This is not currently supported.
+  Also see:
+  https://en.wikipedia.org/wiki/Double-width_character#In_Unicode
+  https://en.wikipedia.org/wiki/Unicode_character_property
 - Combining unicode characters are not supported.
 - iterm2 has a feature where command-/ highlights the cursor location.
+- Maybe implement VT105 waveform graphics.
+- Maybe Sixel graphics and/or ReGIS graphics.  These are VT330+ features:
+  https://vt100.net/docs/vt3xx-gp/
+  XTerm optionally has partial support for these but is rarely compiled with
+  those features by default.
index 8f1751e..6c1883e 100644 (file)
@@ -70,6 +70,7 @@ bool  cfg_sleep;
 bool   cfg_slowscroll, cfg_smoothscroll;
 int    cfg_sequencetimeout;
 int    cfg_jumpscrolllines, cfg_smoothscrollskip;
+int    cfg_font_width, cfg_font_height;
 int    cfg_leading;
 int    cfg_inputsleep, cfg_inputsleepskip;
 bool   cfg_uppercaseview;
@@ -102,6 +103,9 @@ cfg_setdefaults(void)
        cfg_intscan = INTENSITY_SCAN;
        cfg_intbg = INTENSITY_BG;
 
+       cfg_font_width = FONT_WIDTH;
+       cfg_font_height = FONT_HEIGHT;
+
        cfg_text_width = TEXT_WIDTH;
        cfg_text_height = TEXT_HEIGHT;
        cfg_erasechar = ERASE_CHAR;
index 7742b83..2b3a5d1 100644 (file)
@@ -202,6 +202,17 @@ extern bool cfg_condensed;
 
 
 /*
+ * Font size.  The default is 7x9 for which AnalogTerm supports a native font.
+ * Any other size causes it to be started with an empty set and a font of the
+ * specified size must then be loaded.
+ */
+#define FONT_WIDTH     7
+#define FONT_HEIGHT    9
+
+extern int cfg_font_width, cfg_font_height;
+
+
+/*
  * Size of text screen memory.  If AnalogTerm2 takes a lot of CPU time and is
  * not very responsive when typing ^S/^Q (XOFF/XON) or ^C to control
  * application output, a smaller terminal should help.
@@ -223,7 +234,7 @@ extern bool cfg_condensed;
 #define TEXT_HEIGHT            -1
 #endif
 
-/* Close to 1920x1080 with 2x2 zoom.
+/* Close to 1920x1080 with 2x2 zoom.  With a 7x9 font.
 #define TEXT_WIDTH             137
 #define TEXT_HEIGHT            58
 */
index e0ab30a..9b80271 100644 (file)
@@ -99,12 +99,12 @@ static int          intensity = INTENSITY_MIN;
 static bool            gun_on = false;
 static state_t         *state = NULL;
 static screen_t                *screen = NULL;
-static void            **row_glyphs = NULL;
+static glyph_t         **row_glyphs = NULL;
 static uint32_t                *row_modes = NULL;
 static bool            *row_selected = NULL;
 static int             scanjmp = 0;
 static int             cursor_blink_ticks = 0, text_blink_ticks = 0;
-static uint8_t         empty[FONT_WIDTH];
+static uint8_t         *empty = NULL;
 
 /* Exported as a general utility */
 bool                   draw_cursor_blink_state = true,
@@ -125,7 +125,9 @@ draw_init(state_t *st, screen_t *sc)
                color_lum[i] = luminance_rgb(color_mult[i][MULT_RED],
                    color_mult[i][MULT_GREEN], color_mult[i][MULT_BLUE]);
 
-       (void)memset(empty, 0, FONT_WIDTH);
+       if ((empty = malloc(cfg_font_width)) == NULL)
+               goto err;
+       (void)memset(empty, 0, cfg_font_width);
 
        state = st;
        screen = sc;
@@ -137,7 +139,7 @@ draw_init(state_t *st, screen_t *sc)
        jump_scroll_lines = 0;
 
        /* Allocate row-info arrays */
-       if ((row_glyphs = malloc(cfg_text_width * sizeof(void *))) == NULL)
+       if ((row_glyphs = malloc(cfg_text_width * sizeof(glyph_t *))) == NULL)
                goto err;
        if ((row_modes = malloc(cfg_text_width * sizeof(uint32_t))) == NULL)
                goto err;
@@ -146,9 +148,9 @@ draw_init(state_t *st, screen_t *sc)
 
        /* Compute scanjmp */
        if (cfg_condensed)
-               scanjmp = (int)((cfg_text_width * FONT_WIDTH) * 1.5) + 1;
+               scanjmp = (int)((cfg_text_width * cfg_font_width) * 1.5) + 1;
        else
-               scanjmp = ((cfg_text_width * FONT_WIDTH) * 2) + 1;
+               scanjmp = ((cfg_text_width * cfg_font_width) * 2) + 1;
 
        /* Setup signal handler */
        act.sa_handler = alarm_sighandler;
@@ -185,6 +187,8 @@ draw_cleanup(void)
                free(row_modes);
        if (row_glyphs != NULL)
                free(row_glyphs);
+       if (empty != NULL)
+               free(empty);
 }
 
 /*
@@ -355,10 +359,10 @@ draw_lines(state_t *st, screen_t *sc, int low, int high)
        lum = color_lum[color];
 
        /* Row to underline or strike if the attribute is enabled */
-       srow = (int)ceil(((double)FONT_HEIGHT) / 2.0);
-       urow = (FONT_HEIGHT - 1) + (cfg_leading > 0 ? 1 : 0);
+       srow = (int)ceil(((double)cfg_font_height) / 2.0);
+       urow = (cfg_font_height - 1) + (cfg_leading > 0 ? 1 : 0);
        /* Row to stop cursor at */
-       crow = (FONT_HEIGHT - 1) + (cfg_leading > 2 ? 2 : cfg_leading);
+       crow = (cfg_font_height - 1) + (cfg_leading > 2 ? 2 : cfg_leading);
 
        if (high < low || low < 0 || high >= cfg_text_height) {
                /* Invalid */
@@ -371,8 +375,8 @@ draw_lines(state_t *st, screen_t *sc, int low, int high)
 
        /* Original code without smooth scrolling. */
        /*
-       sc->update_y = low * (FONT_HEIGHT + cfg_leading) * 2;
-       sc->update_h = ((high + 1) * ((FONT_HEIGHT + cfg_leading) * 2))
+       sc->update_y = low * (cfg_font_height + cfg_leading) * 2;
+       sc->update_h = ((high + 1) * ((cfg_font_height + cfg_leading) * 2))
            - sc->update_y;
         */
 
@@ -384,9 +388,9 @@ draw_lines(state_t *st, screen_t *sc, int low, int high)
         * considered to be a bug of the implementation.  It is visible at low
         * refresh rates.
         */
-       sc->update_y = ((low * (FONT_HEIGHT + cfg_leading)) +
+       sc->update_y = ((low * (cfg_font_height + cfg_leading)) +
            st->smoothscroll_offset) * 2;
-       sc->update_h = ((high + 1) * ((FONT_HEIGHT + cfg_leading) * 2))
+       sc->update_h = ((high + 1) * ((cfg_font_height + cfg_leading) * 2))
            - sc->update_y;
 
        /*
@@ -466,7 +470,8 @@ draw_lines(state_t *st, screen_t *sc, int low, int high)
                        else
                                row_selected[col] = false;
                }
-               for (grow = 0; grow < (FONT_HEIGHT + cfg_leading); grow++) {
+               for (grow = 0; grow < (cfg_font_height + cfg_leading);
+                   grow++) {
                        bool lastbg = false;
 
                        scanptr1_next = &scanptr1[scanjmp * 2];
@@ -475,9 +480,8 @@ draw_lines(state_t *st, screen_t *sc, int low, int high)
                        gun_on = false;
 
                        for (col = 0; col < cfg_text_width; col++) {
-                               uint8_t (*cf)[FONT_WIDTH] = row_glyphs[col],
-                                   *cb = (grow < FONT_HEIGHT ? cf[grow] :
-                                         empty),
+                               uint8_t *cb = (grow < cfg_font_height ?
+                                   row_glyphs[col]->rows[grow] : empty),
                                    rev, last = 0;
                                uint32_t m = row_modes[col];
                                int bit, level, olevel, iblink, fgcolor,
@@ -526,7 +530,7 @@ draw_lines(state_t *st, screen_t *sc, int low, int high)
                                        bglum = color_lum[bgcolor];
                                        bgcolor = st->monocolor;
                                }
-                               for (bit = 0; bit < FONT_WIDTH; bit++) {
+                               for (bit = 0; bit < cfg_font_width; bit++) {
                                        bool extra = (cfg_condensed ?
                                            (colpix % 3) == 0 : false);
                                        int p = (cb[bit] != 0 ? 1 : 0);
@@ -562,7 +566,7 @@ draw_lines(state_t *st, screen_t *sc, int low, int high)
                if (cursor_xor == col && grow <= crow &&
                    ((st->cursor_mode == CMODE_BLOCK) ||
                     (st->cursor_mode == CMODE_LINE &&
-                     grow >= (FONT_HEIGHT - 2)) ||
+                     grow >= (cfg_font_height - 2)) ||
                     (st->cursor_mode == CMODE_BAR && bit < 2))) {
                        if (st->cursor_bright) {
                                intensity = INTENSITY_MAX;
index a4dc40c..84e8341 100644 (file)
@@ -33,6 +33,7 @@
 #include <state.h>
 #include <font.h>
 #include <screen.h>
+#include <config.h>
 
 
 /* AnalogTerm font */
@@ -122,36 +123,66 @@ font_load(uint32_t index, char *bits, unsigned int width, unsigned int height)
        XImage *xi;
        font_t *font;
        int c, r, b, nglyphs;
+       size_t gstep;
+       glyph_t *glyphsa = NULL, *gptr;
+       uint8_t *pixels;
 
-       assert(width % FONT_WIDTH == 0 && height == FONT_HEIGHT);
+       gstep = sizeof(glyph_t) + (cfg_font_height * sizeof(uint8_t *));
+       gstep += gstep % sizeof(glyph_t *);
+
+       /* Default width */
        nglyphs = width / FONT_WIDTH;
 
        if (((font = malloc(sizeof(font_t))) == NULL) ||
-           ((font->glyphs = malloc(nglyphs * (FONT_WIDTH * FONT_HEIGHT)))
-            == NULL))
+           ((font->glyphs = malloc(nglyphs * sizeof(glyph_t *))) == NULL) ||
+           ((glyphsa = malloc(nglyphs * gstep)) == NULL) ||
+           ((font->pixels = malloc(nglyphs * cfg_font_width *
+           cfg_font_height)) == NULL))
                err(EXIT_FAILURE, "font_load()");
        font->next = NULL;
        font->start = index;
        font->end = index + nglyphs;
+       (void)memset(font->pixels, 0,
+           nglyphs * cfg_font_width * cfg_font_height);
+
+       /* Glyphs index */
+       pixels = font->pixels;
+       for (gptr = glyphsa, c = 0; c < nglyphs;
+           c++, gptr = (glyph_t *)((uint8_t *)gptr + gstep)) {
+               font->glyphs[c] = gptr;
+               gptr->defined = false;
+               /* Glyph rows index */
+               for (r = 0; r < cfg_font_height; r++) {
+                       gptr->rows[r] = pixels;
+                       pixels += cfg_font_width;
+               }
+       }
+
+       /* If font is smaller, don't load in default font pixels */
+       if (cfg_font_width < FONT_WIDTH || cfg_font_height < FONT_HEIGHT)
+               return font;
+
+       /* Fill in default font data, even if the font is larger. */
 
        pm = XCreatePixmapFromBitmapData(scr->dpy, scr->win, bits, width,
            height, 1, 0, 1);
        xi = XGetImage(scr->dpy, pm, 0, 0, width, height, ~0L, ZPixmap);
        (void)XFreePixmap(scr->dpy, pm);
 
-       /* Fill font data */
        for (c = 0; c < nglyphs; c++) {
+               int s = cfg_font_width - FONT_WIDTH;
+
+               font->glyphs[c]->defined = true;
                for (r = 0; r < FONT_HEIGHT; r++) {
                        for (b = 0; b < FONT_WIDTH; b++)
-                               font->glyphs[c][r][b] = (uint8_t)XGetPixel(xi,
-                                   (c * FONT_WIDTH) + b, r % FONT_HEIGHT);
+                               font->glyphs[c]->rows[r][b + s] =
+                                   (uint8_t)XGetPixel(xi,
+                                   (c * FONT_WIDTH) + b,
+                                   r % FONT_HEIGHT);
                }
        }
 
-       /* Strange freeing procedure */
-       free(xi->data); /* XXX Shouldn't be XFree()? */
-       xi->data = NULL;
-       XDestroyImage(xi);
+       (void)XDestroyImage(xi);
 
        return font;
 }
@@ -166,6 +197,7 @@ font_new(void)
        font->next = NULL;
        font->start = font->end = 0;
        font->glyphs = NULL;
+       font->pixels = NULL;
 
        return font;
 }
@@ -174,8 +206,15 @@ static void
 font_free(font_t *font)
 {
 
-       if (font->glyphs != NULL)
+       if (font->pixels != NULL)
+               free(font->pixels);
+       if (font->glyphs != NULL) {
+               /* Contiguous structures block */
+               if (*font->glyphs != NULL)
+                       free(*font->glyphs);
+               /* Index */
                free(font->glyphs);
+       }
        free(font);
 }
 
@@ -242,42 +281,96 @@ ftable_free(ftable_t *t)
 static void *
 font_glyph_new(state_t *state, uint32_t c)
 {
-       uint8_t (*glyph)[FONT_WIDTH];
-       int index = -1;
+       font_t *font;
+       glyph_t *glyph;
+       int index = -1, i;
+       size_t gstep;
+       glyph_t *gptr;
+       uint8_t *pixels;
+
+       font = state->font_user;
+
+       gstep = sizeof(glyph_t) + (cfg_font_height * sizeof(uint8_t *));
+       gstep += gstep % sizeof(glyph_t *);
 
        /* First user glyph? */
        if (state->ftable_user->code == NULL) {
                /* Allocate first one */
-               if ((state->ftable_user->code = malloc(sizeof(uint32_t))) ==
-                   NULL)
+
+               /* Charcode table */
+               if ((state->ftable_user->code = malloc(sizeof(uint32_t)))
+                   == NULL)
                        err(EXIT_FAILURE, "glyph_new()");
                state->ftable_user->n = 1;
-               if ((state->font_user->glyphs =
-                   malloc(FONT_WIDTH * FONT_HEIGHT)) == NULL)
+
+               /* Glyphs index */
+               if ((font->glyphs = malloc(sizeof(glyph_t *))) == NULL)
+                       err(EXIT_FAILURE, "glyph_new()");
+
+               /* Glyph struct */
+               if ((font->glyphs[0] = malloc(gstep)) == NULL)
+                       err(EXIT_FAILURE, "glyph_new()");
+
+               /* Pixels */
+               if ((font->pixels = malloc(cfg_font_width * cfg_font_height))
+                   == NULL)
                        err(EXIT_FAILURE, "glyph_new()");
+
                index = 0;
        } else {
                /* Allocate new one growing buffers */
                uint32_t *code;
-               uint8_t (*glyphs)[FONT_HEIGHT][FONT_WIDTH];
+               glyph_t **glyphs, *glyphsa;
+               uint8_t *pixels;
                int newsize = state->ftable_user->n + 1;
 
+               /* Charcode table */
                if ((code = realloc(state->ftable_user->code,
                    newsize * sizeof(uint32_t))) == NULL)
                        err(EXIT_FAILURE, "glyph_new()");
                state->ftable_user->code = code;
-               if ((glyphs = realloc(state->font_user->glyphs,
-                   newsize * FONT_WIDTH * FONT_HEIGHT)) == NULL)
+
+               /* Glyphs index */
+               if ((glyphs = realloc(font->glyphs,
+                   newsize * sizeof(glyph_t *))) == NULL)
+                       err(EXIT_FAILURE, "glyph_new()");
+               font->glyphs = glyphs;
+
+               /* Glyph structs */
+               if ((glyphsa = realloc(font->glyphs[0], newsize * gstep))
+                   == NULL)
                        err(EXIT_FAILURE, "glyph_new()");
-               state->font_user->glyphs = glyphs;
+               font->glyphs[0] = glyphsa;
+
+               /* Pixels */
+               if ((pixels = realloc(font->pixels,
+                   newsize * cfg_font_width * cfg_font_height)) == NULL)
+                       err(EXIT_FAILURE, "glyph_new()");
+               font->pixels = pixels;
+
                index = state->ftable_user->n;
                state->ftable_user->n = newsize;
        }
        assert(index != -1);
 
-       /* Clear and link to table */
-       glyph = state->font_user->glyphs[index];
-       (void)memset(glyph, 0, FONT_WIDTH * FONT_HEIGHT);
+       /* Remake pointer indexes, reallocation may have moved objects. */
+       pixels = font->pixels;
+       for (gptr = *(font->glyphs), i = 0;
+           i < state->ftable_user->n;
+           i++, gptr = (glyph_t *)((uint8_t *)gptr + gstep)) {
+               int r;
+
+               font->glyphs[i] = gptr;
+               gptr->defined = true;
+               for (r = 0; r < cfg_font_height; r++) {
+                       gptr->rows[r] = pixels;
+                       pixels += cfg_font_width;
+               }
+       }
+
+       /* Initialize new glyph and link to table */
+       glyph = font->glyphs[index];
+       (void)memset(glyph->rows[0], 0, cfg_font_width * cfg_font_height);
        state->ftable_user->code[index] = c;
        if (c < state->ftable_user->min)
                state->ftable_user->min = c;
@@ -339,6 +432,27 @@ font_init(state_t *state, screen_t *screen)
        state->font->next->next->next->next = font_load(130032,
            analogterm_graphics3_9_bits, analogterm_graphics3_9_width,
            analogterm_graphics3_9_height);
+
+       /*
+        * If font is not the default size, programmatically regenerate
+        * "unknown" glyph.  This is simple, it is a rectangle almost the size
+        * of the box.
+        */
+       if (cfg_font_width != FONT_WIDTH || cfg_font_height != FONT_HEIGHT) {
+               glyph_t *g = state->font_unknown->glyphs[0];
+               int i;
+
+               (void)memset(g->rows[0], 0, cfg_font_width * cfg_font_height);
+               for (i = 1; i < cfg_font_width - 1; i++) {
+                       g->rows[1][i] = 0xff;
+                       g->rows[cfg_font_height - 2][i] = 0xff;
+               }
+               for (i = 1; i < cfg_font_height - 1; i++) {
+                       g->rows[i][1] = 0xff;
+                       g->rows[i][cfg_font_width - 2] = 0xff;
+               }
+               g->defined = true;
+       }
 }
 
 void
@@ -405,15 +519,12 @@ font_reset(state_t *state)
  * But this is simple and avoids using a huge memory array considering the
  * large sparse unicode space.  In theory, subtrees could be used for
  * fixed-time resolution.
- * XXX I somehow never could quiet incompatible types warnings without using
- * void *.  Not working: uint8_t (*)[FONT_WIDTH], uint8_t **, uint8_t *[],
- * uint8_t *[FONT_WIDTH], uint8_t *, ...
  */
 void *
 font_glyph(state_t *state, uint32_t c, bool decgfx, bool raw)
 {
        /* Default to unknown glyph */
-       uint8_t (*glyph)[FONT_WIDTH] = state->font_unknown->glyphs[0];
+       glyph_t *glyph = state->font_unknown->glyphs[0];
        font_t *font;
        ftable_t *table;
 
@@ -423,6 +534,8 @@ font_glyph(state_t *state, uint32_t c, bool decgfx, bool raw)
        /*
         * Map unsupported glyphs to supported ones where relevant.
         * XXX May need a more generic mapping table eventually.
+        * Also, we may want to disable this when not using 7x9 fonts, or when
+        * requested by loading a font, etc.
         */
        switch (c) {
        case 0x00A0:    /* Non-breaking space */
@@ -556,6 +669,8 @@ raw:
        for (font = state->font; font != NULL; font = font->next) {
                if (c < font->end && c >= font->start) {
                        glyph = font->glyphs[c - font->start];
+                       if (!glyph->defined)
+                               glyph = state->font_unknown->glyphs[0];
                        break;
                }
        }
@@ -566,7 +681,8 @@ raw:
 void
 font_edit(state_t *state, uint32_t c, int l, int v)
 {
-       uint8_t (*gl)[FONT_WIDTH]; /* Bytes of one line */ 
+       glyph_t *gl;
+       uint8_t *row;
        int i;
 
        /* Can never be NULL but can be "unknown" */
@@ -578,8 +694,9 @@ font_edit(state_t *state, uint32_t c, int l, int v)
                 */
                gl = font_glyph_new(state, c);
        }
+       row = gl->rows[l];
 
-       for (i = 0; i < FONT_WIDTH; i++)
-               gl[l][(FONT_WIDTH - 1) - i] =
+       for (i = 0; i < cfg_font_width; i++)
+               row[(cfg_font_width - 1) - i] =
                    ((v & (1 << i)) != 0 ? 255 : 0);
 }
index 3a9e6ca..dc8d37b 100644 (file)
 #include <stdint.h>
 
 
+#define ORIG_FONT_WIDTH                7
+#define ORIG_FONT_HEIGHT       9
+
+
+typedef struct glyph_s glyph_t;
 typedef struct font_s font_t;
 typedef struct ftable_s ftable_t;
 
@@ -38,14 +43,16 @@ typedef struct ftable_s ftable_t;
 #include <screen.h>
 
 
-#define FONT_WIDTH     7
-#define FONT_HEIGHT    9
-
+struct glyph_s {
+       bool defined;
+       uint8_t *rows[];        /* Lines index for rows[y][x] */
+};
 
 struct font_s {
        font_t *next;
        uint32_t start, end;    /* nglyphs == end - start */
-       uint8_t (*glyphs)[FONT_HEIGHT][FONT_WIDTH];
+       glyph_t **glyphs;       /* glyphs[n] */
+       uint8_t *pixels;        /* Actual underlaying contiguous memory */
 };
 
 struct ftable_s {
index aa5795f..b90ef2f 100644 (file)
@@ -205,9 +205,9 @@ usage(void)
            "\nUsage: %s [-1 | -2] [-8|-u] [-w <cols>] [-h <rows>] [-E <n>]\n"
            "    [-s] [-C <col>] [-c] [-W] [-b] [-r <ms>]\n"
            "    [-B <ticks>[,<ticks>]] [-j <n>] [-P] [-m <mode>] [-M] [-d]\n"
-           "    [-D] [-S] [-p <parameters>] [-l <pixels>] [-f <delay>]\n"
-           "    [-t] [-T <ticks>[,<ticks>]] [-U] [-z <ms>] [-Z <skip>]\n"
-           "    [-e <command> [<arguments>]]\n\n"
+           "    [-D] [-S] [-p <parameters>] [-g <w>,<h>] [-l <pixels>]\n"
+           "    [-f <delay>] [-t] [-T <ticks>[,<ticks>]] [-U] [-z <ms>]\n"
+           "    [-Z <skip>] [-e <command> [<arguments>]]\n\n"
            "Where:\n"
            " -1 - Activate slow and smooth scrolling at startup.\n"
            "      Also see -j for more details.\n"
@@ -266,6 +266,11 @@ usage(void)
            "      Can also be changed with ESC [?658467;65547;<n>[;<n>]h\n"
            "      This depends on the refresh rate setting, -r.\n"
            " -p - Analog scanline parameters.  These are described below.\n"
+           " -g - Comma separated width and height specifying the font\n"
+           "      glyph box size.  The default is 7,9 in which case an\n"
+           "      internal default font is supplied.  A custom font must be\n"
+           "      defined/loaded with ATC sequences for other sizes.  If the\n"
+           "      new matrix is larger, the internal font is still loaded.\n"
            " -l - Add extra leading pixels between lines.  This will also\n"
            "      affect the vertical connectivity of graphics characters.\n"
            " -f - Number of frames to keep reverse video on for the flash\n"
@@ -335,7 +340,7 @@ main(int argc, char **argv, char **envp)
 
        progname = strdup(argv[0]);
        while ((ch = getopt(argc, argv,
-           "?128uw:h:E:scC:Wr:bB:j:Pm:MdDStT:p:l:f:Uz:Z:e:")) != -1) {
+           "?128uw:h:E:scC:Wr:bB:j:Pm:MdDStT:p:g:l:f:Uz:Z:e:")) != -1) {
                switch (ch) {
                case '1':
                        cfg_slowscroll = cfg_smoothscroll = true;
@@ -466,8 +471,26 @@ main(int argc, char **argv, char **envp)
                case 'p':
                        cfg_setparams(optarg);
                        break;
+               case 'g':
+                       {
+                               char *cols[2], *str;
+                               int w = -1, h = -1;
+
+                               if ((str = strdup(optarg)) == NULL)
+                                       err(EXIT_FAILURE, "strdup()");
+                               if (cfg_strspl(cols, str, 2, ',') == 2) {
+                                       w = atoi(cols[0]);
+                                       h = atoi(cols[1]);
+                               }
+                               free(str);
+                               if ((w > 0 && w < 17) && (h > 0 && h < 17)) {
+                                       cfg_font_width = w;
+                                       cfg_font_height = h;
+                               }
+                       }
+                       break;
                case 'l':
-                       if ((i = atoi(optarg)) >= -1 && i <= FONT_HEIGHT)
+                       if ((i = atoi(optarg)) >= -1 && i <= cfg_font_height)
                                cfg_leading = i;
                        break;
                case 'f':
@@ -531,13 +554,16 @@ endopt:
        winsize.ws_col = cfg_text_width;
        /* XXX Should we set these? */
        if (cfg_condensed)
-               winsize.ws_xpixel = (int)(cfg_text_width * FONT_WIDTH * 1.5);
+               winsize.ws_xpixel = (int)(cfg_text_width * cfg_font_width *
+                   1.5);
        else
-               winsize.ws_xpixel = (cfg_text_width * FONT_WIDTH) * 2;
+               winsize.ws_xpixel = cfg_text_width * cfg_font_width * 2;
 #ifdef EXPAND_Y
-       winsize.ws_ypixel = (int)(cfg_text_height * FONT_HEIGHT * 2.5);
+       winsize.ws_ypixel = (int)(cfg_text_height *
+           (cfg_font_height + cfg_leading) * 2.5);
 #else
-       winsize.ws_ypixel = (cfg_text_height * FONT_HEIGHT) * 2;
+       winsize.ws_ypixel = (cfg_text_height * (cfg_font_height + cfg_leading))
+           * 2;
 #endif
        ttys = tty_shell(envp, &winsize, command);
 
index 61db620..f4f833a 100644 (file)
@@ -179,21 +179,21 @@ screen_init(void)
                err(EXIT_FAILURE, "XGetWindowAttributes()");
        if (cfg_text_width == -1)
                cfg_text_width = ((wattr.width - wattr.border_width) /
-                   (FONT_WIDTH * (cfg_condensed ? 1.5 : 2)) - 6);
+                   (cfg_font_width * (cfg_condensed ? 1.5 : 2)) - 6);
        if (cfg_text_height == -1)
                cfg_text_height = (wattr.height /
-                   ((FONT_HEIGHT + cfg_leading) * 2) - 3);
+                   ((cfg_font_height + cfg_leading) * 2) - 3);
 
        /* Font rendered with 2x/1.5x software zoom */
        if (cfg_condensed)
-               width = ((int)((cfg_text_width * FONT_WIDTH) * 1.5)) + 1;
+               width = ((int)((cfg_text_width * cfg_font_width) * 1.5)) + 1;
        else
-               width = ((cfg_text_width * FONT_WIDTH) * 2) + 1;
+               width = ((cfg_text_width * cfg_font_width) * 2) + 1;
 #ifdef EXPAND_Y
-       height = ((int)((cfg_text_height * (FONT_HEIGHT + cfg_leading)) * 2.5)
-           + 1);
+       height = ((int)((cfg_text_height * (cfg_font_height + cfg_leading))
+           * 2.5) + 1);
 #else
-       height = (cfg_text_height * (FONT_HEIGHT + cfg_leading)) * 2;
+       height = (cfg_text_height * (cfg_font_height + cfg_leading)) * 2;
 #endif
 
        s->pixels_width = width;
index 1a181ac..17b8e75 100644 (file)
@@ -444,10 +444,11 @@ state_scroll_range(state_t *st, int offset)
                         * Activate smooth scrolling offset by one line and
                         * temporarily disable the cursor.
                         */
-                       st->smoothscroll_offset = FONT_HEIGHT + cfg_leading;
+                       st->smoothscroll_offset =
+                           cfg_font_height + cfg_leading;
                        st->cursor_disabled_ticks =
-                          (int)((st->smoothscroll_offset /
-                                 cfg_smoothscrollskip) * 1.5);
+                           (int)((st->smoothscroll_offset /
+                           cfg_smoothscrollskip) * 1.5);
                        state_update_cursor(st);
                }
        } else {
@@ -1229,7 +1230,9 @@ state_emul_printc(state_t *st, uint8_t c)
                                                    st->scroll_slow = true;
                                                cfg_smoothscrollskip = 1;
                                                if (state->csiparam[2] > 0 &&
-                                                   state->csiparam[2] < 5)
+                                                   state->csiparam[2] <
+                                                   ((cfg_font_height +
+                                                   cfg_leading) / 2) + 1)
                                                        cfg_smoothscrollskip =
                                                            state->csiparam[2];
                                        } else if ((state->curparam == 2 ||
@@ -1321,10 +1324,11 @@ state_emul_printc(state_t *st, uint8_t c)
                                                    l = state->csiparam[3],
                                                    b = state->csiparam[4];
 
-                                               if (l < 0 || l > 8)
+                                               if (l < 0 ||
+                                                   l > cfg_font_height - 1)
                                                        goto endh;
                                                if (b < 0 || b >
-                                                   (1 << FONT_WIDTH) - 1)
+                                                   (1 << cfg_font_width) - 1)
                                                        goto endh;
                                                font_edit(st, g, l, b);
                                                st->text_updateall = true;
index 1bd1c58..adc9ef1 100755 (executable)
@@ -17,10 +17,11 @@ alias atfastscroll="printf '\033[?4l\033[?658467;65544h'"
 
 # Text speed
 alias atfasttext="printf '\033[?658467;65548;0h'"
-alias atslowtext1="printf '\033[?658467;65548;1;64h'"
-alias atslowtext2="printf '\033[?658467;65548;1;32h'"
-alias atslowtext3="printf '\033[?658467;65548;1;16h'"
-alias atslowtext4="printf '\033[?658467;65548;1;8h'"
+alias atslowtext1="printf '\033[?658467;65548;1;128h'"
+alias atslowtext2="printf '\033[?658467;65548;1;64h'"
+alias atslowtext3="printf '\033[?658467;65548;1;32h'"
+alias atslowtext4="printf '\033[?658467;65548;1;16h'"
+alias atslowtext5="printf '\033[?658467;65548;1;8h'"
 
 # Color
 alias atcolor="printf '\033[?658467;65536h'"