/* $Id: sixel.c,v 1.9 2007/01/07 17:03:13 tom Exp $ */ #include #include #include #define is_inter(c) ((c) >= 0x20 && ((c) <= 0x2f)) #define is_final(c) ((c) >= 0x30 && ((c) <= 0x7e)) #define L_CURL '{' #define MAX_WIDTH 10 static char *EraseCtl = ""; static char *FontName = ""; static char *StartingCharPtr = ""; static char *TextCell = ""; static char *WidthAttr = ""; static char *font_string = ""; static int FontNumber; static int MatrixHigh; static int MatrixWide; static int StartingCharNum; /* * Lookup the given character 'chr' in the font-string and write a readable * display of the glyph */ static void decode_header(void) { int Pe, Pcms, Pw, Pt; char *s; switch (sscanf(font_string+2, "%d;%d;%d;%d;%d;%d", &FontNumber, &StartingCharNum, &Pe, &Pcms, &Pw, &Pt)) { case 0: FontNumber = 0; /* FALLTHRU */ case 1: StartingCharNum = 0; /* FALLTHRU */ case 2: Pe = 0; /* FALLTHRU */ case 3: Pcms = 0; /* FALLTHRU */ case 4: Pw = 0; /* FALLTHRU */ case 5: Pt = 0; /* FALLTHRU */ case 6: break; } switch (Pcms) { case 1: MatrixWide = 0; MatrixHigh = 0; break; /* illegal */ case 2: MatrixWide = 5; MatrixHigh = 10; break; case 3: MatrixWide = 6; MatrixHigh = 10; break; case 0: case 4: MatrixWide = 7; MatrixHigh = 10; break; default: MatrixWide = Pcms; MatrixHigh = 10; break; /* 5 thru 10 */ } switch (Pe) { case 0: EraseCtl = "this DRCS set"; break; case 1: EraseCtl = "only reloaded chars"; break; case 2: EraseCtl = "all chars in all DRCS sets"; break; default: EraseCtl = "?"; break; } switch (Pw) { case 0: /* FALLTHRU */ case 1: WidthAttr = "80 cols, 24 lines"; break; case 2: WidthAttr = "132 cols, 24 lines"; break; case 11: WidthAttr = "80 cols, 36 lines"; break; case 12: WidthAttr = "132 cols, 36 lines"; break; case 21: WidthAttr = "80 cols, 24 lines"; break; case 22: WidthAttr = "132 cols, 48 lines"; break; default: WidthAttr = "?"; break; } if (Pt == 2) TextCell = "Full Cell"; else TextCell = "Text"; for (s = font_string; *s; s++) { if (*s == L_CURL) { char *t; char tmp[BUFSIZ]; size_t use = 0; for (t = s + 1; *t; t++) { if (is_inter(*t)) { tmp[use++] = *t; } if (is_final(*t)) { tmp[use++] = *t++; tmp[use] = '\0'; FontName = strcpy((char *) malloc(use+1), tmp); StartingCharPtr = t; break; } } break; } } } static char * find_char(int chr) { char *s = StartingCharPtr; chr -= (' ' + StartingCharNum); if (chr < 0) return 0; while (chr > 0) { do { if (*s == '\0') return 0; } while (*s++ != ';'); chr--; } return s; } static void display_head(FILE *fp) { fprintf(fp, "Font %d:%s, Matrix %dx%d (%s, %s)\n", FontNumber, FontName, MatrixWide, MatrixHigh, WidthAttr, TextCell); fprintf(fp, "Start %d, Erase %s\n", StartingCharNum, EraseCtl); } static int display_char(FILE *fp, int chr) { char *s; int bit, n, high; char bits[6][MAX_WIDTH]; s = find_char(chr); if (s != 0) { fprintf(fp, "Glyph '%c'\n", chr); bit = 0; high = 0; do { if (*s >= '?' && *s <= '~') { for (n = 0; n < 6; n++) bits[n][bit] = ((*s - '?') & 1 << n) ? 'O' : '.'; bit++; } else if ((*s == ';' || *s == '/') && bit) { for (n = 0; (n < 6) && (high++ < MatrixHigh); n++) { bits[n][bit] = '\0'; fprintf(fp, "%s\n", bits[n]); } bit = 0; } } while (*s++ != ';'); return TRUE; } return FALSE; } static int tst_DECDLD(MENU_ARGS) { char *s; vt_move(1,1); printf("Working...\n"); for (s = font_string; *s; s++) { putchar(*s); if (*s == '\n') { fflush(stdout); padding(20); } } fflush(stdout); padding(20); printf("...done "); printf("%c*%s", ESC, FontName); /* designate G2 as the DRCS font */ padding(4); fflush(stdout); return MENU_HOLD; } static int tst_display(MENU_ARGS) { int d, c = -1; vt_move(1,1); display_head(stdout); println(""); println("Press any key to display its soft-character. Repeat a key to quit."); set_tty_raw(TRUE); set_tty_echo(FALSE); do { d = c; c = inchar(); vt_move(6,1); vt_clear(0); if (display_char(stdout, c)) { println(""); printf("Render: %cN%c", ESC, c); /* use SS2 to invoke G2 into GL */ } } while (c != d); restore_ttymodes(); return MENU_NOHOLD; } /* * Remove all characters in all DRCS sets (the " @" is a dummy name) */ static int tst_cleanup(MENU_ARGS) { do_dcs("1;1;2%c @", L_CURL); padding(20); return MENU_NOHOLD; } /* * Read a soft-character definition string from a file. Strip off garbage * at the beginning (to accommodate the "font2xx" output format). */ void setup_softchars(char *filename) { FILE *fp; int c; size_t len = 1024; size_t use = 0; char *buffer = (char *) malloc(len); char *s; char *first = 0; char *last = 0; int save_8bits = input_8bits; input_8bits = FALSE; /* use the 7-bit input-parsing */ /* read the file into memory */ if ((fp = fopen(filename, "r")) == 0) { perror(filename); exit(EXIT_FAILURE); } while ((c = fgetc(fp)) != EOF) { if (use+1 >= len) { buffer = (char *) realloc(buffer, len *= 2); } buffer[use++] = (char) c; } buffer[use] = '\0'; fclose(fp); /* find the DCS that begins the control string */ /* and the ST that ends the control string */ for (s = buffer; *s; s++) { if (first == 0) { if (skip_dcs(s) != 0) first = s; } else { if (!strncmp(s, st_input(), 2)) { last = s + 2; *last = '\0'; break; } } } input_8bits = save_8bits; if (first == 0 || last == 0) { fprintf(stderr, "Not a vtXXX font description: %s\n", filename); exit(EXIT_FAILURE); } for (s = buffer; (*s++ = *first++) != '\0'; ) ; if (LOG_ENABLED && first != 0) fprintf(log_fp, "Font String:\n%s\n", buffer); font_string = buffer; decode_header(); } int tst_softchars(MENU_ARGS) { static MENU my_menu[] = { { "Exit", 0 }, { "Download the soft characters", tst_DECDLD }, { "Examine the soft characters", tst_display }, { "Clear the soft characters", tst_cleanup }, { "", 0 } }; vt_move(1,1); if (font_string == 0 || *font_string == 0) { printf("You did not specify a font-file with the -f option\n"); return MENU_HOLD; } do { vt_clear(2); title(0); printf("Soft Character Sets"); title(2); println("Choose test type:"); } while (menu(my_menu)); return MENU_NOHOLD; }