static void insert_characters(bit ** const bits, struct text const lp, struct font * const fontP, int const topmargin, int const leftmargin, float const intercharacter_space, int const lspace) { /*---------------------------------------------------------------------------- Render the text 'lp' into the image 'bits' using font *fontP and putting 'intercharacter_space' pixels between characters and 'lspace' pixels between the lines. -----------------------------------------------------------------------------*/ int line; /* Line number in input text */ for (line = 0; line < lp.lineCount; ++line) { int row; /* row in image of top of current typeline */ int leftcol; /* Column in image of left edge of current glyph */ int cursor; /* cursor into a line of input text */ float accumulated_ics; /* accumulated intercharacter space so far in the line we are building. Because the intercharacter space might not be an integer, we accumulate it here and realize full pixels whenever we have more than one pixel. */ row = topmargin + line * (fontP->maxheight + lspace); leftcol = leftmargin; accumulated_ics = 0.0; /* initial value */ for (cursor = 0; lp.textArray[line][cursor] != '\0'; ++cursor) { unsigned int const glyphIndex = (unsigned char)lp.textArray[line][cursor]; struct glyph* glyph; /* the glyph for this character */ glyph = fontP->glyph[glyphIndex]; if (glyph != NULL) { const int toprow = row + fontP->maxheight + fontP->y - glyph->height - glyph->y; /* row number in image of top row in glyph */ insert_character(glyph, toprow, leftcol, bits); leftcol += glyph->xadd; { /* handle extra intercharacter space (-space option) */ int full_pixels; /* integer part of accumulated_ics */ accumulated_ics += intercharacter_space; full_pixels = (int) accumulated_ics; if (full_pixels > 0) { leftcol += full_pixels; accumulated_ics -= full_pixels; } } } } } }
void main(int argc) { char input = 0; read(); while (1) { input = read_key(); /* blocking */ if (insert_mode == 1) { switch (input) { case '\n': insert_character(input); break_line(); break; case 0x7f: if (current_column > 0) { int current_char = 0; current_column -= 1; current_char = buffer[C(current_line, current_column)]; if (current_column >= 0 && current_char != EOF && current_char != EOL) { move_memory(buffer + C(current_line, current_column), -1, COLS - current_column - 1); buffer[C(current_line, COLS-1)] = 0; } } break; case 27: // esc insert_mode = 0; // set_string(notifications, "COMMAND"); break; default: if (input != 0) { insert_character(input); } break; } } else { if (interpret_command(input) == 1) { return 0; } } // update_notification_line(); send_display(buffer); /* give pointer to assembly function */ display(C(current_line, current_column), '_'); } }
static void history_restore(){ FILE *f; int len, i; if((f = fopen(history_file, "r")) == NULL) return; while(1){ text_clear(line); if((len = fget_rune(f)) == EOF) break; for(i = 0; i<len; i++) insert_character(fget_rune(f), NULL, 0); history_save(); history_add(); hist_first++; } fclose(f); }
/* Handler for control sequencie introducer, "ESC [" */ static void control_escape_csi(char ch) { switch (ch) { case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': console->params[console->param_count] = 10 * console->params[console->param_count] + (ch - '0'); break; case ';': if (console->param_count + 1 == CONSOLE_MAX_PARAMS) log_error("Too many console parameters.\n"); else console->param_count++; break; case 'A': /* CUU */ move_up(console->params[0]? console->params[0]: 1); console->processor = NULL; break; case 'B': /* CUD */ case 'e': /* VPR */ move_down(console->params[0]? console->params[0]: 1); console->processor = NULL; break; case 'C': /* CUF */ case 'a': /* HPR */ move_right(console->params[0]? console->params[0]: 1); console->processor = NULL; break; case 'D': /* CUB */ move_left(console->params[0]? console->params[0]: 1); console->processor = NULL; break; case 'd': /* VPA */ { int y = console->params[0]? console->params[0]: 1; if (y > console->height) y = console->height; set_pos(console->x, y - 1); console->processor = NULL; break; } case 'G': /* CHA */ case '`': /* HPA */ { int x = console->params[0] ? console->params[0] : 1; if (x > console->width) x = console->width; set_pos(x - 1, console->y); console->processor = NULL; break; } case 'H': case 'f': /* Zero or one both represents the first row/column */ if (console->params[0] > 0) console->params[0]--; if (console->params[1] > 0) console->params[1]--; if (console->origin_mode) set_pos(console->params[1], console->scroll_top + console->params[0]); else set_pos(console->params[1], console->params[0]); console->processor = NULL; break; case 'h': if (console->private_mode) change_private_mode(console->params[0], 1); else change_mode(console->params[0], 1); console->processor = NULL; break; case 'J': erase_screen(console->params[0]); console->processor = NULL; break; case 'K': erase_line(console->params[0]); console->processor = NULL; break; case 'l': if (console->private_mode) change_private_mode(console->params[0], 0); else change_mode(console->params[0], 0); console->processor = NULL; break; case 'L': /* IL */ insert_line(console->params[0]? console->params[0]: 1); console->processor = NULL; break; case 'M': /* DL */ delete_line(console->params[0]? console->params[0]: 1); console->processor = NULL; break; case '@': /* ICH */ insert_character(console->params[0]? console->params[0]: 1); console->processor = NULL; break; case 'P': /* DCH */ delete_character(console->params[0]? console->params[0]: 1); console->processor = NULL; break; case 'm': for (int i = 0; i <= console->param_count; i++) { switch (console->params[i]) { case 0: /* Reset */ console->bright = 0; console->reverse = 0; console->foreground = 7; console->background = 0; break; case 1: console->bright = 1; break; case 2: console->bright = 0; break; case 7: console->reverse = 1; break; case 27: console->reverse = 0; break; case 30: case 31: case 32: case 33: case 34: case 35: case 36: case 37: console->foreground = console->params[i] - 30; break; case 40: case 41: case 42: case 43: case 44: case 45: case 46: case 47: console->background = console->params[i] - 40; break; default: log_error("Unknown console attribute: %d\n", console->params[i]); } } /* Set updated text attribute */ SetConsoleTextAttribute(console->out, get_text_attribute(console)); console->processor = NULL; break; case 'r': if (console->params[0] == 0) console->params[0] = 1; if (console->params[1] == 0) console->params[1] = console->height; console->scroll_full_screen = (console->params[0] == 1 && console->params[1] == console->height); console->scroll_top = console->params[0] - 1; console->scroll_bottom = console->params[1] - 1; set_pos(0, 0); console->processor = NULL; break; case 'S': /* SU */ scroll_up(console->params[0]? console->params[0]: 1); console->processor = NULL; break; case '?': console->private_mode = 1; break; default: log_error("control_escape_csi(): Unhandled character %c\n", ch); console->processor = NULL; } }
void outputter(SCREEN_Screen* scr, int terminator, GetCharFunction getf) { while (1) { unsigned char c = getf(); if (c == terminator) { return; } switch (c) { case '\a': break; // TODO: alert? case '\t': tab(scr); break; case '\n': cursor_down(scr); break; case '\b': cursor_left(scr); break; case '\r': carriage_return(scr); break; case 0x1b: { c = getf(); switch (c) { case '[': { int x; if (getnum(getf, &x, &c)) { if (x == 1 && c == 'K') { clr_bol(scr); } else { switch (c) { case 'm': mode(scr, x); break; case 'A': parm_up_cursor(scr, x); break; case 'B': parm_down_cursor(scr, x); break; case 'C': parm_right_cursor(scr, x); break; case 'D': parm_left_cursor(scr, x); break; case 'G': column_address(scr, (x-1)); break; case 'L': parm_insert_line(scr, x); break; case 'M': parm_delete_line(scr, x); break; case 'P': parm_dch(scr, x); break; case 'S': parm_index(scr, x); break; case 'T': parm_rindex(scr, x); break; case 'X': erase_chars(scr, x); break; case '@': parm_ich(scr, x); break; case 'd': row_address(scr, (x-1)); break; case ';': { int y; if (getnum(getf, &y, &c)) { switch (c) { case 'm': mode(scr, x); mode(scr, y); break; case 'H': cursor_address(scr, mkpos(y-1, x-1)); break; default: fprintf(stderr, "unhandled: ESC[%i;%i%c\n", x, y, c); break; } } else { fprintf(stderr, "unhandled: ESC[%i;%c\n", x, c); } } break; default: fprintf(stderr, "unahndled: ESC[%i%c\n", x, c); break; } } } else { switch (c) { case '@': insert_character(scr); break; case 'A': cursor_up(scr); break; case 'B': cursor_down(scr); break; case 'C': cursor_right(scr); break; case 'D': cursor_left(scr); break; case 'H': cursor_home(scr); break; case 'I': tab(scr); break; case 'J': clr_eos(scr); break; case 'K': clr_eol(scr); break; case 'L': insert_line(scr); break; case 'M': delete_line(scr); break; case 'P': delete_character(scr); break; case 'm': exit_attribute_mode(scr); break; default: fprintf(stderr, "unhandled: ESC[%c\n", c); break; } } } break; case 'M': scroll_reverse(scr); break; default: fprintf(stderr, "unhandled: ESC%c\n", c); break; } } break; default: { wchar_t wc; if ((c & 0x80) == 0x00) { wc = c; } else if ((c & 0xE0) == 0xC0) { char c1 = 0x1F & c; char c2 = 0x3F & getf(); wc = (c1 << 6) | c2; } else if ((c & 0xF0) == 0xE0) { char c1 = 0x0F & c; char c2 = 0x3F & getf(); char c3 = 0x3F & getf(); wc = (c1 << 12) | (c2 << 6) | c3; } else if ((c & 0xF8) == 0xF0) { char c1 = 0x07 & c; char c2 = 0x3F & getf(); char c3 = 0x3F & getf(); char c4 = 0x3F & getf(); wc = (c1 << 18) | (c2 << 12) | (c3 << 6) | c4; } else if ((c & 0xFC) == 0xF8) { char c1 = 0x03 & c; char c2 = 0x3F & getf(); char c3 = 0x3F & getf(); char c4 = 0x3F & getf(); char c5 = 0x3F & getf(); wc = (c1 << 24) | (c2 << 18) | (c3 << 12) | (c4 << 6) | c5; } else if ((c & 0xFE) == 0xFC) { char c1 = 0x01 & c; char c2 = 0x3F & getf(); char c3 = 0x3F & getf(); char c4 = 0x3F & getf(); char c5 = 0x3F & getf(); char c6 = 0x3F & getf(); wc = (c1 << 30) | (c2 << 24) | (c3 << 18) | (c4 << 12) | (c5 < 6) | c6; } else { fprintf(stderr, "bad utf-8 sequence: c=0x%02x\n", c); wc = '\0'; } put_char(scr, wc); } break; } } }