Arguments to ctype functions are required to be either EOF or representable
[u/mdw/putty] / terminal.c
index 956af21..4f0d822 100644 (file)
@@ -65,6 +65,8 @@
 
 #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))
@@ -1184,6 +1186,7 @@ static void power_on(Terminal *term, int clear)
 {
     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;
@@ -1196,18 +1199,22 @@ static void power_on(Terminal *term, int clear)
     }
     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;
@@ -1216,6 +1223,8 @@ static void power_on(Terminal *term, int clear)
     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++)
@@ -1441,7 +1450,7 @@ Terminal *term_init(Config *mycfg, struct unicode_data *ucsdata,
     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;
@@ -1605,6 +1614,8 @@ void term_size(Terminal *term, int newrows, int newcols, int newsavelines)
            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);
@@ -1625,6 +1636,8 @@ void term_size(Terminal *term, int newrows, int newcols, int newsavelines)
            term->tempsblines += 1;
            term->curs.y -= 1;
            term->savecurs.y -= 1;
+           term->alt_y -= 1;
+           term->alt_savecurs.y -= 1;
        }
        term->rows -= 1;
     }
@@ -1684,12 +1697,26 @@ void term_size(Terminal *term, int newrows, int newcols, int newsavelines)
        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;
 
@@ -1715,7 +1742,7 @@ void term_provide_resize_fn(Terminal *term,
 {
     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);
 }
 
@@ -1747,6 +1774,7 @@ static int find_last_nonempty_line(Terminal * term, tree234 * screen)
 static void swap_screen(Terminal *term, int which, int reset, int keep_cur_pos)
 {
     int t;
+    pos tp;
     tree234 *ttr;
 
     if (!which)
@@ -1794,6 +1822,35 @@ static void swap_screen(Terminal *term, int which, int reset, int keep_cur_pos)
        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) {
@@ -2328,11 +2385,11 @@ static void toggle_mode(Terminal *term, int mode, int query, int state)
            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;
@@ -2813,6 +2870,13 @@ static void term_out(Terminal *term)
                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;
@@ -3311,10 +3375,17 @@ static void term_out(Terminal *term)
                        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);
@@ -3707,7 +3778,7 @@ static void term_out(Terminal *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) {
@@ -3719,7 +3790,7 @@ static void term_out(Terminal *term)
                              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;
@@ -3749,8 +3820,11 @@ static void term_out(Terminal *term)
                                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);
@@ -3759,8 +3833,11 @@ static void term_out(Terminal *term)
                                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);
@@ -5865,7 +5942,7 @@ void term_key(Terminal *term, Key_Sym keysym, wchar_t *text, size_t tlen,
                if (modifiers & PKM_CONTROL)
                    c &= 0x1f;
                else if (modifiers & PKM_SHIFT)
-                   c = toupper(c);
+                       c = toupper((unsigned char)c);
            }
            *p++ = c;
            goto done;
@@ -6348,6 +6425,7 @@ char *term_get_ttymode(Terminal *term, const char *mode)
        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);
 }
 
@@ -6391,7 +6469,7 @@ int term_get_userpass_input(Terminal *term, prompts_t *p,
         */
        {
            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);
        }
     }