X-Git-Url: https://git.distorted.org.uk/u/mdw/putty/blobdiff_plain/6c50d42155442e8dc23bff3965b51614144d7683..0ec4b50ff9d82409f851ea04b6587c42f97f1bdb:/terminal.c diff --git a/terminal.c b/terminal.c index 93879d60..f3b2c8a3 100644 --- a/terminal.c +++ b/terminal.c @@ -381,6 +381,9 @@ Terminal *term_init(Config *mycfg, struct unicode_data *ucsdata, term->rows = term->cols = -1; power_on(term); term->beephead = term->beeptail = NULL; +#ifdef OPTIMISE_SCROLL + term->scrollhead = term->scrolltail = NULL; +#endif /* OPTIMISE_SCROLL */ term->nbeeps = 0; term->lastbeep = FALSE; term->beep_overloaded = FALSE; @@ -474,8 +477,9 @@ void term_size(Terminal *term, int newrows, int newcols, int newsavelines) } else { line = smalloc(TSIZE * (newcols + 2)); line[0] = newcols; - for (j = 0; j <= newcols; j++) + for (j = 0; j < newcols; j++) line[j + 1] = ERASE_CHAR; + line[newcols + 1] = LATTR_NORM; } addpos234(term->screen, line, 0); } @@ -504,8 +508,9 @@ void term_size(Terminal *term, int newrows, int newcols, int newsavelines) for (i = 0; i < newrows; i++) { line = smalloc(TSIZE * (newcols + 2)); line[0] = newcols; - for (j = 0; j <= newcols; j++) + for (j = 0; j < newcols; j++) line[j + 1] = term->erase_char; + line[newcols + 1] = LATTR_NORM; addpos234(newalt, line, i); } if (term->alt_screen) { @@ -742,7 +747,7 @@ static void scroll(Terminal *term, int topline, int botline, int lines, int sb) line = resizeline(line, term->cols); for (i = 0; i < term->cols; i++) line[i + 1] = term->erase_char; - line[term->cols + 1] = 0; + line[term->cols + 1] = LATTR_NORM; addpos234(term->screen, line, botline); /* @@ -793,6 +798,35 @@ static void scroll(Terminal *term, int topline, int botline, int lines, int sb) #ifdef OPTIMISE_SCROLL /* + * Add a scroll of a region on the screen into the pending scroll list. + * `lines' is +ve for scrolling forward, -ve for backward. + * + * If the scroll is on the same area as the last scroll in the list, + * merge them. + */ +static void save_scroll(Terminal *term, int topline, int botline, int lines) +{ + struct scrollregion *newscroll; + if (term->scrolltail && + term->scrolltail->topline == topline && + term->scrolltail->botline == botline) { + term->scrolltail->lines += lines; + } else { + newscroll = smalloc(sizeof(struct scrollregion)); + newscroll->topline = topline; + newscroll->botline = botline; + newscroll->lines = lines; + newscroll->next = NULL; + + if (!term->scrollhead) + term->scrollhead = newscroll; + else + term->scrolltail->next = newscroll; + term->scrolltail = newscroll; + } +} + +/* * Scroll the physical display, and our conception of it in disptext. */ static void scroll_display(Terminal *term, int topline, int botline, int lines) @@ -818,7 +852,7 @@ static void scroll_display(Terminal *term, int topline, int botline, int lines) for (i = 0; i < distance; i++) start[i] |= ATTR_INVALID; } - do_scroll(term->frontend, topline, botline, lines); + save_scroll(term, topline, botline, lines); } #endif /* OPTIMISE_SCROLL */ @@ -972,10 +1006,14 @@ static void erase_lots(Terminal *term, ldata = lineptr(start.y); while (poslt(start, end)) { - if (start.x == term->cols && !erase_lattr) - ldata[start.x] &= ~(LATTR_WRAPPED | LATTR_WRAPPED2); - else + if (start.x == term->cols) { + if (!erase_lattr) + ldata[start.x] &= ~(LATTR_WRAPPED | LATTR_WRAPPED2); + else + ldata[start.x] = LATTR_NORM; + } else { ldata[start.x] = term->erase_char; + } if (incpos(start) && start.y < term->rows) ldata = lineptr(start.y); } @@ -2281,6 +2319,20 @@ void term_out(Terminal *term) term->curr_attr |= (term->esc_args[i] - 30)<curr_attr &= ~ATTR_FGMASK; + term->curr_attr |= + ((term->esc_args[i] - 90 + 16) + << ATTR_FGSHIFT); + break; case 39: /* default-foreground */ term->curr_attr &= ~ATTR_FGMASK; term->curr_attr |= ATTR_DEFFG; @@ -2298,6 +2350,20 @@ void term_out(Terminal *term) term->curr_attr |= (term->esc_args[i] - 40)<curr_attr &= ~ATTR_BGMASK; + term->curr_attr |= + ((term->esc_args[i] - 100 + 16) + << ATTR_BGSHIFT); + break; case 49: /* default-background */ term->curr_attr &= ~ATTR_BGMASK; term->curr_attr |= ATTR_DEFBG; @@ -3053,6 +3119,9 @@ static void do_paint(Terminal *term, Context ctx, int may_optimise) char ch[1024]; long cursor_background = ERASE_CHAR; unsigned long ticks; +#ifdef OPTIMISE_SCROLL + struct scrollregion *sr; +#endif /* OPTIMISE_SCROLL */ /* * Check the visual bell state. @@ -3115,6 +3184,18 @@ static void do_paint(Terminal *term, Context ctx, int may_optimise) } term->dispcurs = NULL; +#ifdef OPTIMISE_SCROLL + /* Do scrolls */ + sr = term->scrollhead; + while (sr) { + struct scrollregion *next = sr->next; + do_scroll(ctx, sr->topline, sr->botline, sr->lines); + sfree(sr); + sr = next; + } + term->scrollhead = term->scrolltail = NULL; +#endif /* OPTIMISE_SCROLL */ + /* The normal screen data */ for (i = 0; i < term->rows; i++) { unsigned long *ldata; @@ -3175,9 +3256,7 @@ static void do_paint(Terminal *term, Context ctx, int may_optimise) /* 'Real' blinking ? */ if (term->blink_is_real && (tattr & ATTR_BLINK)) { if (term->has_focus && term->tblinker) { - tchar = ' '; - tattr &= ~CSET_MASK; - tattr |= ATTR_ACP; + tchar = term->ucsdata->unitab_line[(unsigned char)' ']; } tattr &= ~ATTR_BLINK; } @@ -4015,12 +4094,14 @@ void term_key(Terminal *term, Key_Sym keysym, wchar_t *text, size_t tlen, char output[10]; char *p = output; int prependesc = FALSE; +#if 0 int i; fprintf(stderr, "keysym = %d, %d chars:", keysym, tlen); for (i = 0; i < tlen; i++) - fprintf(stderr, " %04x", text[i]); + fprintf(stderr, " %04x", (unsigned)text[i]); fprintf(stderr, "\n"); +#endif /* XXX Num Lock */ if ((flags & PKF_REPEAT) && term->repeat_off) @@ -4067,8 +4148,8 @@ void term_key(Terminal *term, Key_Sym keysym, wchar_t *text, size_t tlen, if (keysym == PK_NULL && (modifiers & PKM_CONTROL) && tlen == 1 && text[0] >= 0x20 && text[0] <= 0x7e) { /* ASCII chars + Control */ - if (text[0] >= 0x40 && text[0] <= 0x5f || - text[0] >= 0x61 && text[0] <= 0x7a) + if ((text[0] >= 0x40 && text[0] <= 0x5f) || + (text[0] >= 0x61 && text[0] <= 0x7a)) text[0] &= 0x1f; else { /* @@ -4107,6 +4188,7 @@ void term_key(Terminal *term, Key_Sym keysym, wchar_t *text, size_t tlen, case PK_KP7: c = 'y'; break; case PK_KP8: c = 'k'; break; case PK_KP9: c = 'u'; break; + default: break; /* else gcc warns `enum value not used' */ } if (c != 0) { if (c != '.') { @@ -4137,6 +4219,7 @@ void term_key(Terminal *term, Key_Sym keysym, wchar_t *text, size_t tlen, case PK_PF2: xkey = 'Q'; break; case PK_PF3: xkey = 'R'; break; case PK_PF4: xkey = 'S'; break; + default: break; /* else gcc warns `enum value not used' */ } } if (term->app_keypad_keys && !term->cfg.no_applic_k) { @@ -4153,6 +4236,7 @@ void term_key(Terminal *term, Key_Sym keysym, wchar_t *text, size_t tlen, case PK_KP9: xkey = 'y'; break; case PK_KPDECIMAL: xkey = 'n'; break; case PK_KPENTER: xkey = 'M'; break; + default: break; /* else gcc warns `enum value not used' */ } if (term->cfg.funky_type == FUNKY_XTERM && tlen > 0) { /* @@ -4187,6 +4271,7 @@ void term_key(Terminal *term, Key_Sym keysym, wchar_t *text, size_t tlen, break; case PK_KPMINUS: xkey = 'm'; break; case PK_KPCOMMA: xkey = 'l'; break; + default: break; /* else gcc warns `enum value not used' */ } } } @@ -4213,6 +4298,7 @@ void term_key(Terminal *term, Key_Sym keysym, wchar_t *text, size_t tlen, case PK_KP7: keysym = PK_HOME; break; case PK_KP8: keysym = PK_UP; break; case PK_KP9: keysym = PK_PAGEUP; break; + default: break; /* else gcc warns `enum value not used' */ } } } @@ -4251,6 +4337,7 @@ void term_key(Terminal *term, Key_Sym keysym, wchar_t *text, size_t tlen, *p++ = 0x0a; goto done; } + default: break; /* else gcc warns `enum value not used' */ } /* SCO function keys and editing keys */ @@ -4275,6 +4362,7 @@ void term_key(Terminal *term, Key_Sym keysym, wchar_t *text, size_t tlen, case PK_END: xkey = 'F'; break; case PK_PAGEUP: xkey = 'I'; break; case PK_PAGEDOWN: xkey = 'G'; break; + default: break; /* else gcc warns `enum value not used' */ } p += sprintf((char *) p, "\x1B[%c", xkey); } @@ -4292,6 +4380,7 @@ void term_key(Terminal *term, Key_Sym keysym, wchar_t *text, size_t tlen, case PK_END: keysym = PK_PAGEUP; break; case PK_PAGEUP: keysym = PK_DELETE; break; case PK_PAGEDOWN: keysym = PK_PAGEDOWN; break; + default: break; /* else gcc warns `enum value not used' */ } } @@ -4316,6 +4405,7 @@ void term_key(Terminal *term, Key_Sym keysym, wchar_t *text, size_t tlen, case PK_END: xkey = 'E'; break; case PK_PAGEUP: xkey = 'I'; break; case PK_PAGEDOWN: xkey = 'G'; break; + default: break; /* else gcc warns `enum value not used' */ } p += sprintf((char *) p, "\x1B%c", xkey); goto done; @@ -4328,6 +4418,7 @@ void term_key(Terminal *term, Key_Sym keysym, wchar_t *text, size_t tlen, case PK_END: code = 4; break; case PK_PAGEUP: code = 5; break; case PK_PAGEDOWN: code = 6; break; + default: break; /* else gcc warns `enum value not used' */ } p += sprintf((char *) p, "\x1B[%d~", code); goto done; @@ -4371,6 +4462,7 @@ void term_key(Terminal *term, Key_Sym keysym, wchar_t *text, size_t tlen, case PK_RIGHT: xkey = 'C'; break; case PK_LEFT: xkey = 'D'; break; case PK_REST: xkey = 'G'; break; /* centre key on number pad */ + default: break; /* else gcc warns `enum value not used' */ } if (term->vt52_mode) p += sprintf((char *) p, "\x1B%c", xkey); @@ -4410,23 +4502,27 @@ void term_key(Terminal *term, Key_Sym keysym, wchar_t *text, size_t tlen, term_seen_key_event(term); if (prependesc) { +#if 0 fprintf(stderr, "sending ESC\n"); +#endif ldisc_send(term->ldisc, "\x1b", 1, 1); } if (p > output) { +#if 0 fprintf(stderr, "sending %d bytes:", p - output); for (i = 0; i < p - output; i++) fprintf(stderr, " %02x", output[i]); fprintf(stderr, "\n"); - +#endif ldisc_send(term->ldisc, output, p - output, 1); } else if (tlen > 0) { +#if 0 fprintf(stderr, "sending %d unichars:", tlen); for (i = 0; i < tlen; i++) - fprintf(stderr, " %04x", text[i]); + fprintf(stderr, " %04x", (unsigned) text[i]); fprintf(stderr, "\n"); - +#endif luni_send(term->ldisc, text, tlen, 1); } } @@ -4506,7 +4602,7 @@ int term_ldisc(Terminal *term, int option) /* * from_backend(), to get data from the backend for the terminal. */ -int from_backend(void *vterm, int is_stderr, char *data, int len) +int from_backend(void *vterm, int is_stderr, const char *data, int len) { Terminal *term = (Terminal *)vterm;