#define has_compat(x) ( ((CL_##x)&term->compatibility_level) != 0 )
+char *EMPTY_WINDOW_TITLE = "";
+
const char sco2ansicolour[] = { 0, 4, 2, 6, 1, 5, 3, 7 };
#define sel_nl_sz (sizeof(sel_nl)/sizeof(wchar_t))
{
term->alt_x = term->alt_y = 0;
term->savecurs.x = term->savecurs.y = 0;
+ term->alt_savecurs.x = term->alt_savecurs.y = 0;
term->alt_t = term->marg_t = 0;
if (term->rows != -1)
term->alt_b = term->marg_b = term->rows - 1;
}
term->alt_om = term->dec_om = term->cfg.dec_om;
term->alt_ins = term->insert = FALSE;
- term->alt_wnext = term->wrapnext = term->save_wnext = FALSE;
+ term->alt_wnext = term->wrapnext =
+ term->save_wnext = term->alt_save_wnext = FALSE;
term->alt_wrap = term->wrap = term->cfg.wrap_mode;
- term->alt_cset = term->cset = term->save_cset = 0;
- term->alt_utf = term->utf = term->save_utf = 0;
+ term->alt_cset = term->cset = term->save_cset = term->alt_save_cset = 0;
+ term->alt_utf = term->utf = term->save_utf = term->alt_save_utf = 0;
term->utf_state = 0;
- term->alt_sco_acs = term->sco_acs = term->save_sco_acs = 0;
- term->cset_attr[0] = term->cset_attr[1] = term->save_csattr = CSET_ASCII;
+ term->alt_sco_acs = term->sco_acs =
+ term->save_sco_acs = term->alt_save_sco_acs = 0;
+ term->cset_attr[0] = term->cset_attr[1] =
+ term->save_csattr = term->alt_save_csattr = CSET_ASCII;
term->rvideo = 0;
term->in_vbell = FALSE;
term->cursor_on = 1;
term->big_cursor = 0;
- term->default_attr = term->save_attr = term->curr_attr = ATTR_DEFAULT;
+ term->default_attr = term->save_attr =
+ term->alt_save_attr = term->curr_attr = ATTR_DEFAULT;
term->term_editing = term->term_echoing = FALSE;
term->app_cursor_keys = term->cfg.app_cursor;
term->app_keypad_keys = term->cfg.app_keypad;
term->erase_char = term->basic_erase_char;
term->alt_which = 0;
term_print_finish(term);
+ term->xterm_mouse = 0;
+ set_raw_mouse_mode(term->frontend, FALSE);
{
int i;
for (i = 0; i < 256; i++)
term->vt52_mode = FALSE;
term->cr_lf_return = FALSE;
term->seen_disp_event = FALSE;
- term->xterm_mouse = term->mouse_is_down = FALSE;
+ term->mouse_is_down = FALSE;
term->reset_132 = FALSE;
term->cblinker = term->tblinker = 0;
term->has_focus = 1;
addpos234(term->screen, line, 0);
term->curs.y += 1;
term->savecurs.y += 1;
+ term->alt_y += 1;
+ term->alt_savecurs.y += 1;
} else {
/* Add a new blank line at the bottom of the screen. */
line = newline(term, newcols, FALSE);
term->tempsblines += 1;
term->curs.y -= 1;
term->savecurs.y -= 1;
+ term->alt_y -= 1;
+ term->alt_savecurs.y -= 1;
}
term->rows -= 1;
}
term->savecurs.y = 0;
if (term->savecurs.y >= newrows)
term->savecurs.y = newrows - 1;
+ if (term->savecurs.x >= newcols)
+ term->savecurs.x = newcols - 1;
+ if (term->alt_savecurs.y < 0)
+ term->alt_savecurs.y = 0;
+ if (term->alt_savecurs.y >= newrows)
+ term->alt_savecurs.y = newrows - 1;
+ if (term->alt_savecurs.x >= newcols)
+ term->alt_savecurs.x = newcols - 1;
if (term->curs.y < 0)
term->curs.y = 0;
if (term->curs.y >= newrows)
term->curs.y = newrows - 1;
if (term->curs.x >= newcols)
term->curs.x = newcols - 1;
+ if (term->alt_y < 0)
+ term->alt_y = 0;
+ if (term->alt_y >= newrows)
+ term->alt_y = newrows - 1;
+ if (term->alt_x >= newcols)
+ term->alt_x = newcols - 1;
term->alt_x = term->alt_y = 0;
term->wrapnext = term->alt_wnext = FALSE;
{
term->resize_fn = resize_fn;
term->resize_ctx = resize_ctx;
- if (term->cols > 0 && term->rows > 0)
+ if (resize_fn && term->cols > 0 && term->rows > 0)
resize_fn(resize_ctx, term->cols, term->rows);
}
static void swap_screen(Terminal *term, int which, int reset, int keep_cur_pos)
{
int t;
+ pos tp;
tree234 *ttr;
if (!which)
t = term->sco_acs;
if (!reset) term->sco_acs = term->alt_sco_acs;
term->alt_sco_acs = t;
+
+ tp = term->savecurs;
+ if (!reset && !keep_cur_pos)
+ term->savecurs = term->alt_savecurs;
+ term->alt_savecurs = tp;
+ t = term->save_cset;
+ if (!reset && !keep_cur_pos)
+ term->save_cset = term->alt_save_cset;
+ term->alt_save_cset = t;
+ t = term->save_csattr;
+ if (!reset && !keep_cur_pos)
+ term->save_csattr = term->alt_save_csattr;
+ term->alt_save_csattr = t;
+ t = term->save_attr;
+ if (!reset && !keep_cur_pos)
+ term->save_attr = term->alt_save_attr;
+ term->alt_save_attr = t;
+ t = term->save_utf;
+ if (!reset && !keep_cur_pos)
+ term->save_utf = term->alt_save_utf;
+ term->alt_save_utf = t;
+ t = term->save_wnext;
+ if (!reset && !keep_cur_pos)
+ term->save_wnext = term->alt_save_wnext;
+ term->alt_save_wnext = t;
+ t = term->save_sco_acs;
+ if (!reset && !keep_cur_pos)
+ term->save_sco_acs = term->alt_save_sco_acs;
+ term->alt_save_sco_acs = t;
}
if (reset && term->screen) {
swap_screen(term, term->cfg.no_alt_screen ? 0 : state, FALSE, FALSE);
term->disptop = 0;
break;
- case 1000: /* xterm mouse 1 */
+ case 1000: /* xterm mouse 1 (normal) */
term->xterm_mouse = state ? 1 : 0;
set_raw_mouse_mode(term->frontend, state);
break;
- case 1002: /* xterm mouse 2 */
+ case 1002: /* xterm mouse 2 (inc. button drags) */
term->xterm_mouse = state ? 2 : 0;
set_raw_mouse_mode(term->frontend, state);
break;
term->wrapnext = FALSE;
seen_disp_event(term);
term->paste_hold = 0;
+
+ if (term->cfg.crhaslf) {
+ if (term->curs.y == term->marg_b)
+ scroll(term, term->marg_t, term->marg_b, 1, TRUE);
+ else if (term->curs.y < term->rows - 1)
+ term->curs.y++;
+ }
if (term->logctx)
logtraffic(term->logctx, (unsigned char) c, LGTYP_ASCII);
break;
}
term->termstate = SEEN_CSI;
} else if (c == ';') {
- if (++term->esc_nargs <= ARGS_MAX)
- term->esc_args[term->esc_nargs - 1] = ARG_DEFAULT;
+ if (term->esc_nargs < ARGS_MAX)
+ term->esc_args[term->esc_nargs++] = ARG_DEFAULT;
term->termstate = SEEN_CSI;
} else if (c < '@') {
if (term->esc_query)
break;
case 'J': /* ED: erase screen or parts of it */
{
- unsigned int i = def(term->esc_args[0], 0) + 1;
- if (i > 3)
- i = 0;
- erase_lots(term, FALSE, !!(i & 2), !!(i & 1));
+ unsigned int i = def(term->esc_args[0], 0);
+ if (i == 3) {
+ /* Erase Saved Lines (xterm)
+ * This follows Thomas Dickey's xterm. */
+ term_clrsb(term);
+ } else {
+ i++;
+ if (i > 3)
+ i = 0;
+ erase_lots(term, FALSE, !!(i & 2), !!(i & 1));
+ }
}
term->disptop = 0;
seen_disp_event(term);
if (term->ldisc)
ldisc_send(term->ldisc,
is_iconic(term->frontend) ?
- "\033[1t" : "\033[2t", 4, 0);
+ "\033[2t" : "\033[1t", 4, 0);
break;
case 13:
if (term->ldisc) {
case 14:
if (term->ldisc) {
get_window_pixels(term->frontend, &x, &y);
- len = sprintf(buf, "\033[4;%d;%dt", x, y);
+ len = sprintf(buf, "\033[4;%d;%dt", y, x);
ldisc_send(term->ldisc, buf, len, 0);
}
break;
break;
case 20:
if (term->ldisc &&
- !term->cfg.no_remote_qtitle) {
- p = get_window_title(term->frontend, TRUE);
+ term->cfg.remote_qtitle_action != TITLE_NONE) {
+ if(term->cfg.remote_qtitle_action == TITLE_REAL)
+ p = get_window_title(term->frontend, TRUE);
+ else
+ p = EMPTY_WINDOW_TITLE;
len = strlen(p);
ldisc_send(term->ldisc, "\033]L", 3, 0);
ldisc_send(term->ldisc, p, len, 0);
break;
case 21:
if (term->ldisc &&
- !term->cfg.no_remote_qtitle) {
- p = get_window_title(term->frontend,FALSE);
+ term->cfg.remote_qtitle_action != TITLE_NONE) {
+ if(term->cfg.remote_qtitle_action == TITLE_REAL)
+ p = get_window_title(term->frontend, FALSE);
+ else
+ p = EMPTY_WINDOW_TITLE;
len = strlen(p);
ldisc_send(term->ldisc, "\033]l", 3, 0);
ldisc_send(term->ldisc, p, len, 0);
term_update(term);
}
+/*
+ * Scroll the scrollback to centre it on the beginning or end of the
+ * current selection, if any.
+ */
+void term_scroll_to_selection(Terminal *term, int which_end)
+{
+ pos target;
+ int y;
+ int sbtop = -sblines(term);
+
+ if (term->selstate != SELECTED)
+ return;
+ if (which_end)
+ target = term->selend;
+ else
+ target = term->selstart;
+
+ y = target.y - term->rows/2;
+ if (y < sbtop)
+ y = sbtop;
+ else if (y > 0)
+ y = 0;
+ term_scroll(term, -1, y);
+}
+
/*
* Helper routine for clipme(): growing buffer.
*/
set = (uc & CSET_MASK);
c = (uc & ~CSET_MASK);
- cbuf[0] = uc;
- cbuf[1] = 0;
+#ifdef PLATFORM_IS_UTF16
+ if (uc > 0x10000 && uc < 0x110000) {
+ cbuf[0] = 0xD800 | ((uc - 0x10000) >> 10);
+ cbuf[1] = 0xDC00 | ((uc - 0x10000) & 0x3FF);
+ cbuf[2] = 0;
+ } else
+#endif
+ {
+ cbuf[0] = uc;
+ cbuf[1] = 0;
+ }
if (DIRECT_FONT(uc)) {
if (c >= ' ' && c != 0x7F) {
selpoint.x = x;
unlineptr(ldata);
- if (raw_mouse) {
+ /*
+ * If we're in the middle of a selection operation, we ignore raw
+ * mouse mode until it's done (we must have been not in raw mouse
+ * mode when it started).
+ * This makes use of Shift for selection reliable, and avoids the
+ * host seeing mouse releases for which they never saw corresponding
+ * presses.
+ */
+ if (raw_mouse &&
+ (term->selstate != ABOUT_TO) && (term->selstate != DRAGGING)) {
int encstate = 0, r, c;
char abuf[16];
term_update(term);
}
+int format_arrow_key(char *buf, Terminal *term, int xkey, int ctrl)
+{
+ char *p = buf;
+
+ if (term->vt52_mode)
+ p += sprintf((char *) p, "\x1B%c", xkey);
+ else {
+ int app_flg = (term->app_cursor_keys && !term->cfg.no_applic_c);
+#if 0
+ /*
+ * RDB: VT100 & VT102 manuals both state the app cursor
+ * keys only work if the app keypad is on.
+ *
+ * SGT: That may well be true, but xterm disagrees and so
+ * does at least one application, so I've #if'ed this out
+ * and the behaviour is back to PuTTY's original: app
+ * cursor and app keypad are independently switchable
+ * modes. If anyone complains about _this_ I'll have to
+ * put in a configurable option.
+ */
+ if (!term->app_keypad_keys)
+ app_flg = 0;
+#endif
+ /* Useful mapping of Ctrl-arrows */
+ if (ctrl)
+ app_flg = !app_flg;
+
+ if (app_flg)
+ p += sprintf((char *) p, "\x1BO%c", xkey);
+ else
+ p += sprintf((char *) p, "\x1B[%c", xkey);
+ }
+
+ return p - buf;
+}
+
void term_key(Terminal *term, Key_Sym keysym, wchar_t *text, size_t tlen,
unsigned int modifiers, unsigned int flags)
{
if (modifiers & PKM_CONTROL)
c &= 0x1f;
else if (modifiers & PKM_SHIFT)
- c = toupper(c);
+ c = toupper((unsigned char)c);
}
*p++ = c;
goto done;
case PK_REST: xkey = 'G'; break; /* centre key on number pad */
default: xkey = 0; break; /* else gcc warns `enum value not used' */
}
- if (term->vt52_mode)
- p += sprintf((char *) p, "\x1B%c", xkey);
- else {
- int app_flg = (term->app_cursor_keys && !term->cfg.no_applic_c);
-
- /* Useful mapping of Ctrl-arrows */
- if (modifiers == PKM_CONTROL)
- app_flg = !app_flg;
-
- if (app_flg)
- p += sprintf((char *) p, "\x1BO%c", xkey);
- else
- p += sprintf((char *) p, "\x1B[%c", xkey);
- }
+ p += format_arrow_key(p, term, xkey, modifiers == PKM_CONTROL);
goto done;
}
val = term->cfg.bksp_is_delete ? "^?" : "^H";
}
/* FIXME: perhaps we should set ONLCR based on cfg.lfhascr as well? */
+ /* FIXME: or ECHO and friends based on local echo state? */
return dupstr(val);
}
*/
{
int i;
- for (i = 0; i < p->n_prompts; i++)
+ for (i = 0; i < (int)p->n_prompts; i++)
memset(p->prompts[i]->result, 0, p->prompts[i]->result_len);
}
}