static int insert; /* insert-mode flag */
static int cset; /* 0 or 1: which char set */
static int save_cset, save_csattr; /* saved with cursor position */
+static int save_utf; /* saved with cursor position */
static int rvideo; /* global reverse video flag */
static int rvbell_timeout; /* for ESC[?5hESC[?5l vbell */
static int cursor_on; /* cursor enabled flag */
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. */
/*
* 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, alt_utf;
static int alt_t, alt_b;
static int alt_which;
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
*/
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;
/* 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);
+ line = newline;
}
return line + 1;
alt_wnext = wrapnext = alt_ins = insert = FALSE;
alt_wrap = wrap = cfg.wrap_mode;
alt_cset = cset = 0;
+ alt_utf = utf = 0;
+ alt_sco_acs = sco_acs = 0;
cset_attr[0] = cset_attr[1] = ATTR_ASCII;
rvideo = 0;
in_vbell = FALSE;
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);
t = cset;
cset = alt_cset;
alt_cset = t;
+ t = utf;
+ utf = alt_utf;
+ alt_utf = t;
+ t = sco_acs;
+ sco_acs = alt_sco_acs;
+ alt_sco_acs = t;
fix_cpos;
}
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;
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;
savecurs = curs;
save_attr = curr_attr;
save_cset = cset;
+ save_utf = utf;
save_csattr = cset_attr[cset];
+ save_sco_acs = sco_acs;
} else {
curs = savecurs;
/* Make sure the window hasn't shrunk since the save */
curr_attr = save_attr;
cset = save_cset;
+ utf = save_utf;
cset_attr[cset] = save_csattr;
+ sco_acs = save_sco_acs;
fix_cpos;
if (use_bce)
- erase_char = (' ' | (curr_attr & (ATTR_FGMASK | ATTR_BGMASK)));
+ erase_char = (' ' | ATTR_ASCII |
+ (curr_attr & (ATTR_FGMASK | ATTR_BGMASK)));
}
}
}
if (!to_end) {
end = curs;
+ incpos(end);
}
check_selection(start, 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;
/* First see about all those translations. */
if (termstate == TOPLEVEL) {
- if (utf)
+ if (in_utf)
switch (utf_state) {
case 0:
if (c < 0x80) {
- /* I know; gotos are evil. This one is really bad!
- * But before you try removing it follow the path of the
- * sequence "0x5F 0xC0 0x71" with UTF and VTGraphics on.
- */
- /*
- if (cfg.no_vt_graph_with_utf8) break;
- */
- goto evil_jump;
+ /* UTF-8 must be stateless so we ignore iso2022. */
+ if (unitab_ctrl[c] != 0xFF)
+ c = unitab_ctrl[c];
+ else c = ((unsigned char)c) | ATTR_ASCII;
+ break;
} else if ((c & 0xe0) == 0xc0) {
utf_size = utf_state = 1;
utf_char = (c & 0x1f);
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]) {
/*
* Linedraw characters are different from 'ESC ( B'
else
c = ((unsigned char) c) | ATTR_ASCII;
break;
+ case ATTR_SCOACS:
+ if (c>=' ') c = ((unsigned char)c) | ATTR_SCOACS;
+ break;
}
}
}
compatibility(VT100);
cset_attr[0] = ATTR_LINEDRW;
break;
+ case ANSI('U', '('):
+ compatibility(OTHER);
+ cset_attr[0] = ATTR_SCOACS;
+ break;
case ANSI('A', ')'):
compatibility(VT100);
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', '%'):
break;
case ANSI('@', '%'):
compatibility(OTHER);
- if (line_codepage != CP_UTF8)
- utf = 0;
+ utf = 0;
break;
}
break;
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;
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;
}
}
if (use_bce)
- erase_char =
- (' ' |
- (curr_attr &
- (ATTR_FGMASK | ATTR_BGMASK |
- ATTR_BLINK)));
+ erase_char = (' ' | ATTR_ASCII |
+ (curr_attr &
+ (ATTR_FGMASK | ATTR_BGMASK)));
}
break;
case 's': /* save cursor */
}
}
break;
+ case 'Z': /* BackTab for xterm */
+ compatibility(OTHER);
+ {
+ int i = def(esc_args[0], 1);
+ pos old_curs = curs;
+
+ for(;i>0 && curs.x>0; i--) {
+ do {
+ curs.x--;
+ } while (curs.x >0 && !tabs[curs.x]);
+ }
+ fix_cpos;
+ check_selection(old_curs, curs);
+ }
+ break;
case ANSI('L', '='):
compatibility(OTHER);
use_bce = (esc_args[0] <= 0);
erase_char = ERASE_CHAR;
if (use_bce)
- erase_char =
- (' ' |
- (curr_attr &
- (ATTR_FGMASK | ATTR_BGMASK)));
+ erase_char = (' ' | ATTR_ASCII |
+ (curr_attr &
+ (ATTR_FGMASK | ATTR_BGMASK)));
break;
case ANSI('E', '='):
compatibility(OTHER);
vt52_bold = FALSE;
curr_attr = ATTR_DEFAULT;
if (use_bce)
- erase_char = (' ' |
- (curr_attr &
- (ATTR_FGMASK | ATTR_BGMASK |
- ATTR_BLINK)));
+ erase_char = (' ' | ATTR_ASCII |
+ (curr_attr &
+ (ATTR_FGMASK | ATTR_BGMASK)));
break;
case 'S':
/* compatibility(VI50) */
curr_attr |= ATTR_BOLD;
if (use_bce)
- erase_char = (' ' |
- (curr_attr &
- (ATTR_FGMASK | ATTR_BGMASK |
- ATTR_BLINK)));
+ erase_char = (' ' | ATTR_ASCII |
+ (curr_attr & (ATTR_FGMASK | ATTR_BGMASK)));
break;
case VT52_BG:
termstate = TOPLEVEL;
curr_attr |= ATTR_BLINK;
if (use_bce)
- erase_char = (' ' |
- (curr_attr &
- (ATTR_FGMASK | ATTR_BGMASK |
- ATTR_BLINK)));
+ erase_char = (' ' | ATTR_ASCII |
+ (curr_attr & (ATTR_FGMASK | ATTR_BGMASK)));
break;
#endif
default: break; /* placate gcc warning about enum use */
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;
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:
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:
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)
{
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();