X-Git-Url: https://git.distorted.org.uk/u/mdw/putty/blobdiff_plain/f8a28d1f902b5430c33a619094d62ae2f4274f3b..d3cb5465f5c608f1edb1edd56290d4fbcec2bb55:/terminal.c diff --git a/terminal.c b/terminal.c index 119ecaa9..391f0d2d 100644 --- a/terminal.c +++ b/terminal.c @@ -82,7 +82,7 @@ typedef struct { #define poslt(p1,p2) ( (p1).y < (p2).y || ( (p1).y == (p2).y && (p1).x < (p2).x ) ) #define posle(p1,p2) ( (p1).y < (p2).y || ( (p1).y == (p2).y && (p1).x <= (p2).x ) ) #define poseq(p1,p2) ( (p1).y == (p2).y && (p1).x == (p2).x ) -#define posdiff(p1,p2) ( ((p2).y - (p1).y) * (cols+1) + (p2).x - (p1).x ) +#define posdiff(p1,p2) ( ((p1).y - (p2).y) * (cols+1) + (p1).x - (p2).x ) #define incpos(p) ( (p).x == cols ? ((p).x = 0, (p).y++, 1) : ((p).x++, 0) ) #define decpos(p) ( (p).x == 0 ? ((p).x = cols, (p).y--, 1) : ((p).x--, 0) ) @@ -104,6 +104,7 @@ static int tblinker; /* When the blinking text is on */ static int blink_is_real; /* Actually blink blinking text */ static int term_echoing; /* Does terminal want local echo? */ static int term_editing; /* Does terminal want local edit? */ +static int sco_acs, save_sco_acs; /* CSI 10,11,12m -> OEM charset */ static int vt52_bold; /* Force bold on non-bold colours */ static int utf_state; /* Is there a pending UTF-8 character */ static int utf_char; /* and what is it so far. */ @@ -116,7 +117,7 @@ static unsigned long cset_attr[2]; /* * Saved settings on the alternate screen. */ -static int alt_x, alt_y, alt_om, alt_wrap, alt_wnext, alt_ins, alt_cset; +static int alt_x, alt_y, alt_om, alt_wrap, alt_wnext, alt_ins, alt_cset, alt_sco_acs; static int alt_t, alt_b; static int alt_which; @@ -201,15 +202,40 @@ static FILE *lgfp = NULL; static void logtraffic(unsigned char c, int logmode); /* + * Resize a line to make it `cols' columns wide. + */ +unsigned long *resizeline(unsigned long *line, int cols) +{ + int i, oldlen; + unsigned long lineattrs; + + if (line[0] != (unsigned long)cols) { + /* + * This line is the wrong length, which probably means it + * hasn't been accessed since a resize. Resize it now. + */ + oldlen = line[0]; + lineattrs = line[oldlen + 1]; + line = srealloc(line, TSIZE * (2 + cols)); + line[0] = cols; + for (i = oldlen; i < cols; i++) + line[i + 1] = ERASE_CHAR; + line[cols + 1] = lineattrs & LATTR_MODE; + } + + return line; +} + +/* * Retrieve a line of the screen or of the scrollback, according to * whether the y coordinate is non-negative or negative * (respectively). */ unsigned long *lineptr(int y, int lineno) { - unsigned long *line, lineattrs; + unsigned long *line, *newline; tree234 *whichtree; - int i, treeindex, oldlen; + int treeindex; if (y >= 0) { whichtree = screen; @@ -223,20 +249,10 @@ unsigned long *lineptr(int y, int lineno) /* We assume that we don't screw up and retrieve something out of range. */ assert(line != NULL); - if (line[0] != cols) { - /* - * This line is the wrong length, which probably means it - * hasn't been accessed since a resize. Resize it now. - */ - oldlen = line[0]; - lineattrs = line[oldlen + 1]; + newline = resizeline(line, cols); + if (newline != line) { delpos234(whichtree, treeindex); - line = srealloc(line, TSIZE * (2 + cols)); - line[0] = cols; - for (i = oldlen; i < cols; i++) - line[i + 1] = ERASE_CHAR; - line[cols + 1] = lineattrs & LATTR_MODE; - addpos234(whichtree, line, treeindex); + addpos234(whichtree, newline, treeindex); } return line + 1; @@ -263,6 +279,7 @@ static void power_on(void) alt_wnext = wrapnext = alt_ins = insert = FALSE; alt_wrap = wrap = cfg.wrap_mode; alt_cset = cset = 0; + alt_sco_acs = sco_acs = 0; cset_attr[0] = cset_attr[1] = ATTR_ASCII; rvideo = 0; in_vbell = FALSE; @@ -298,11 +315,12 @@ void term_update(void) Context ctx; ctx = get_ctx(); if (ctx) { + if (seen_disp_event) + update_sbar(); if ((seen_key_event && (cfg.scroll_on_key)) || (seen_disp_event && (cfg.scroll_on_disp))) { disptop = 0; /* return to main screen */ seen_disp_event = seen_key_event = 0; - update_sbar(); } do_paint(ctx, TRUE); sys_cursor(curs.x, curs.y - disptop); @@ -520,6 +538,9 @@ static void swap_screen(int which) t = cset; cset = alt_cset; alt_cset = t; + t = sco_acs; + sco_acs = alt_sco_acs; + alt_sco_acs = t; fix_cpos; } @@ -567,6 +588,7 @@ static void scroll(int topline, int botline, int lines, int sb) if (lines < 0) { while (lines < 0) { line = delpos234(screen, botline); + line = resizeline(line, cols); for (i = 0; i < cols; i++) line[i + 1] = erase_char; line[cols + 1] = 0; @@ -609,6 +631,7 @@ static void scroll(int topline, int botline, int lines, int sb) addpos234(scrollback, line, sblen); line = line2; } + line = resizeline(line, cols); for (i = 0; i < cols; i++) line[i + 1] = erase_char; line[cols + 1] = 0; @@ -672,6 +695,7 @@ static void save_cursor(int save) save_attr = curr_attr; save_cset = cset; save_csattr = cset_attr[cset]; + save_sco_acs = sco_acs; } else { curs = savecurs; /* Make sure the window hasn't shrunk since the save */ @@ -683,6 +707,7 @@ static void save_cursor(int save) curr_attr = save_attr; cset = save_cset; cset_attr[cset] = save_csattr; + sco_acs = save_sco_acs; fix_cpos; if (use_bce) erase_char = (' ' | (curr_attr & (ATTR_FGMASK | ATTR_BGMASK))); @@ -717,6 +742,7 @@ static void erase_lots(int line_only, int from_begin, int to_end) } if (!to_end) { end = curs; + incpos(end); } check_selection(start, end); @@ -726,7 +752,7 @@ static void erase_lots(int line_only, int from_begin, int to_end) ldata = lineptr(start.y); while (poslt(start, end)) { - if (start.y == cols && !erase_lattr) + if (start.x == cols && !erase_lattr) ldata[start.x] &= ~LATTR_WRAPPED; else ldata[start.x] = erase_char; @@ -1005,6 +1031,13 @@ void term_out(void) if (c >= 0x10000) c = 0xFFFD; break; + } + /* Are we in the nasty ACS mode? Note: no sco in utf mode. */ + else if(sco_acs && + (c!='\033' && c!='\n' && c!='\r' && c!='\b')) + { + if (sco_acs == 2) c ^= 0x80; + c |= ATTR_SCOACS; } else { evil_jump:; switch (cset_attr[cset]) { @@ -1033,6 +1066,9 @@ void term_out(void) else c = ((unsigned char) c) | ATTR_ASCII; break; + case ATTR_SCOACS: + if (c>=' ') c = ((unsigned char)c) | ATTR_SCOACS; + break; } } } @@ -1464,6 +1500,10 @@ void term_out(void) compatibility(VT100); cset_attr[0] = ATTR_LINEDRW; break; + case ANSI('U', '('): + compatibility(OTHER); + cset_attr[0] = ATTR_SCOACS; + break; case ANSI('A', ')'): compatibility(VT100); @@ -1477,6 +1517,10 @@ void term_out(void) compatibility(VT100); cset_attr[1] = ATTR_LINEDRW; break; + case ANSI('U', ')'): + compatibility(OTHER); + cset_attr[1] = ATTR_SCOACS; + break; case ANSI('8', '%'): /* Old Linux code */ case ANSI('G', '%'): @@ -1520,18 +1564,20 @@ void term_out(void) break; case 'e': /* move down N lines */ compatibility(ANSI); + /* FALLTHROUGH */ case 'B': move(curs.x, curs.y + def(esc_args[0], 1), 1); seen_disp_event = TRUE; break; - case 'a': /* move right N cols */ - compatibility(ANSI); case ANSI('c', '>'): /* report xterm version */ compatibility(OTHER); /* this reports xterm version 136 so that VIM can use the drag messages from the mouse reporting */ ldisc_send("\033[>0;136;0c", 11); break; + case 'a': /* move right N cols */ + compatibility(ANSI); + /* FALLTHROUGH */ case 'C': move(curs.x + def(esc_args[0], 1), curs.y, 1); seen_disp_event = TRUE; @@ -1742,6 +1788,15 @@ void term_out(void) case 7: /* enable reverse video */ curr_attr |= ATTR_REVERSE; break; + case 10: /* SCO acs off */ + compatibility(SCOANSI); + sco_acs = 0; break; + case 11: /* SCO acs on */ + compatibility(SCOANSI); + sco_acs = 1; break; + case 12: /* SCO acs on flipped */ + compatibility(SCOANSI); + sco_acs = 2; break; case 22: /* disable bold */ compatibility2(OTHER, VT220); curr_attr &= ~ATTR_BOLD; @@ -2478,6 +2533,9 @@ static void do_paint(Context ctx, int may_optimise) case ATTR_LINEDRW: tchar = unitab_xterm[tchar & 0xFF]; break; + case ATTR_SCOACS: + tchar = unitab_scoacs[tchar&0xFF]; + break; } tattr |= (tchar & CSET_MASK); tchar &= CHAR_MASK; @@ -2712,6 +2770,9 @@ static void clipme(pos top, pos bottom) case ATTR_ASCII: uc = unitab_line[uc & 0xFF]; break; + case ATTR_SCOACS: + uc = unitab_scoacs[uc&0xFF]; + break; } switch (uc & CSET_MASK) { case ATTR_ACP: @@ -2872,6 +2933,9 @@ static int wordtype(int uc) case ATTR_ASCII: uc = unitab_line[uc & 0xFF]; break; + case ATTR_SCOACS: + uc = unitab_scoacs[uc&0xFF]; + break; } switch (uc & CSET_MASK) { case ATTR_ACP: @@ -2951,6 +3015,54 @@ static void sel_spread(void) incpos(selend); } +void term_do_paste(void) +{ + wchar_t *data; + int len; + + get_clip(&data, &len); + if (data) { + wchar_t *p, *q; + + if (paste_buffer) + sfree(paste_buffer); + paste_pos = paste_hold = paste_len = 0; + paste_buffer = smalloc(len * sizeof(wchar_t)); + + p = q = data; + while (p < data + len) { + while (p < data + len && + !(p <= data + len - sel_nl_sz && + !memcmp(p, sel_nl, sizeof(sel_nl)))) + p++; + + { + int i; + for (i = 0; i < p - q; i++) { + paste_buffer[paste_len++] = q[i]; + } + } + + if (p <= data + len - sel_nl_sz && + !memcmp(p, sel_nl, sizeof(sel_nl))) { + paste_buffer[paste_len++] = '\r'; + p += sel_nl_sz; + } + q = p; + } + + /* Assume a small paste will be OK in one go. */ + if (paste_len < 256) { + luni_send(paste_buffer, paste_len); + if (paste_buffer) + sfree(paste_buffer); + paste_buffer = 0; + paste_pos = paste_hold = paste_len = 0; + } + } + get_clip(NULL, NULL); +} + void term_mouse(Mouse_Button b, Mouse_Action a, int x, int y, int shift, int ctrl) { @@ -3083,50 +3195,7 @@ void term_mouse(Mouse_Button b, Mouse_Action a, int x, int y, selstate = NO_SELECTION; } else if (b == MBT_PASTE && (a == MA_CLICK || a == MA_2CLK || a == MA_3CLK)) { - wchar_t *data; - int len; - - get_clip(&data, &len); - if (data) { - wchar_t *p, *q; - - if (paste_buffer) - sfree(paste_buffer); - paste_pos = paste_hold = paste_len = 0; - paste_buffer = smalloc(len * sizeof(wchar_t)); - - p = q = data; - while (p < data + len) { - while (p < data + len && - !(p <= data + len - sel_nl_sz && - !memcmp(p, sel_nl, sizeof(sel_nl)))) - p++; - - { - int i; - for (i = 0; i < p - q; i++) { - paste_buffer[paste_len++] = q[i]; - } - } - - if (p <= data + len - sel_nl_sz && - !memcmp(p, sel_nl, sizeof(sel_nl))) { - paste_buffer[paste_len++] = '\r'; - p += sel_nl_sz; - } - q = p; - } - - /* Assume a small paste will be OK in one go. */ - if (paste_len < 256) { - luni_send(paste_buffer, paste_len); - if (paste_buffer) - sfree(paste_buffer); - paste_buffer = 0; - paste_pos = paste_hold = paste_len = 0; - } - } - get_clip(NULL, NULL); + term_do_paste(); } term_update();