ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/rxvt-unicode/src/command.C
Revision: 1.93
Committed: Thu Apr 8 20:31:45 2004 UTC (20 years, 1 month ago) by pcg
Content type: text/plain
Branch: MAIN
CVS Tags: rel-2_8
Changes since 1.90: +34 -34 lines
Log Message:
*** empty log message ***

File Contents

# User Rev Content
1 pcg 1.1 /*--------------------------------*-C-*---------------------------------*
2 pcg 1.93 * File: command.C
3 pcg 1.1 *----------------------------------------------------------------------*
4     *
5     * All portions of code are copyright by their respective author/s.
6     * Copyright (c) 1992 John Bovey, University of Kent at Canterbury <jdb@ukc.ac.uk>
7     * - original version
8     * Copyright (c) 1994 Robert Nation <nation@rocket.sanders.lockheed.com>
9     * - extensive modifications
10     * Copyright (c) 1995 Garrett D'Amore <garrett@netcom.com>
11     * - vt100 printing
12     * Copyright (c) 1995 Steven Hirsch <hirsch@emba.uvm.edu>
13     * - X11 mouse report mode and support for
14     * DEC "private mode" save/restore functions.
15     * Copyright (c) 1995 Jakub Jelinek <jj@gnu.ai.mit.edu>
16     * - key-related changes to handle Shift+function
17     * keys properly.
18     * Copyright (c) 1997 MJ Olesen <olesen@me.queensu.ca>
19     * - extensive modifications
20     * Copyright (c) 1997 Raul Garcia Garcia <rgg@tid.es>
21     * - modification and cleanups for Solaris 2.x
22     * and Linux 1.2.x
23     * Copyright (c) 1997,1998 Oezguer Kesim <kesim@math.fu-berlin.de>
24     * Copyright (c) 1998-2001 Geoff Wing <gcw@pobox.com>
25     * - extensive modifications
26     * Copyright (c) 1998 Alfredo K. Kojima <kojima@windowmaker.org>
27     * Copyright (c) 2001 Marius Gedminas
28     * - Ctrl/Mod4+Tab works like Meta+Tab (options)
29     * Copyright (c) 2003 Rob McMullen <robm@flipturn.org>
30 pcg 1.49 * Copyright (c) 2003-2004 Marc Lehmann <pcg@goof.com>
31 pcg 1.1 *
32     * This program is free software; you can redistribute it and/or modify
33     * it under the terms of the GNU General Public License as published by
34     * the Free Software Foundation; either version 2 of the License, or
35     * (at your option) any later version.
36     *
37     * This program is distributed in the hope that it will be useful,
38     * but WITHOUT ANY WARRANTY; without even the implied warranty of
39     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
40     * GNU General Public License for more details.
41     *
42     * You should have received a copy of the GNU General Public License
43     * along with this program; if not, write to the Free Software
44     * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
45     *----------------------------------------------------------------------*/
46    
47     /*{{{ includes: */
48     #include "../config.h" /* NECESSARY */
49     #include "rxvt.h" /* NECESSARY */
50     #include "version.h"
51     #include "command.h"
52    
53 pcg 1.20 #include <wchar.h>
54    
55 pcg 1.1 /*----------------------------------------------------------------------*/
56    
57 pcg 1.81 #define IS_CONTROL(ch) !((ch) & 0xffffff60UL)
58    
59     // exception thrown when the command parser runs out of input data
60     class out_of_input { } out_of_input;
61    
62 pcg 1.1 /*{{{ Convert the keypress event into a string */
63     void
64 pcg 1.38 rxvt_term::lookup_key (XKeyEvent &ev)
65 pcg 1.1 {
66 pcg 1.49 int ctrl, meta, shft, len;
67     unsigned int newlen;
68     KeySym keysym;
69 pcg 1.1 #ifdef DEBUG_CMD
70 pcg 1.49 static int debug_key = 1; /* accessible by a debugger only */
71 pcg 1.1 #endif
72 pcg 1.49 int valid_keysym;
73 pcg 1.36 unsigned char kbuf[KBUFSZ];
74 pcg 1.1
75 pcg 1.36 /*
76     * use Num_Lock to toggle Keypad on/off. If Num_Lock is off, allow an
77     * escape sequence to toggle the Keypad.
78     *
79     * Always permit `shift' to override the current setting
80     */
81 pcg 1.38 shft = (ev.state & ShiftMask);
82     ctrl = (ev.state & ControlMask);
83     meta = (ev.state & ModMetaMask);
84 pcg 1.14
85 pcg 1.38 if (numlock_state || (ev.state & ModNumLockMask))
86 pcg 1.36 {
87 pcg 1.38 numlock_state = (ev.state & ModNumLockMask);
88 pcg 1.43 PrivMode ((!numlock_state), PrivMode_aplKP);
89 pcg 1.36 }
90 pcg 1.14
91 pcg 1.36 kbuf[0] = 0;
92 pcg 1.14
93 pcg 1.1 #ifdef USE_XIM
94 pcg 1.36 if (Input_Context)
95     {
96     Status status_return;
97 pcg 1.1
98 pcg 1.81 #if 0
99 pcg 1.1 #ifdef X_HAVE_UTF8_STRING
100 pcg 1.48 if (enc_utf8 && 0) // currently disabled, doesn't seem to work, nor is useful
101 pcg 1.38 len = Xutf8LookupString (Input_Context, &ev, (char *)kbuf,
102 pcg 1.36 KBUFSZ, &keysym, &status_return);
103     else
104 pcg 1.20 #endif
105 pcg 1.81 #endif
106 pcg 1.36 {
107     wchar_t wkbuf[KBUFSZ + 1];
108    
109     // the XOpenIM manpage lies about hardcoding the locale
110     // at the point of XOpenIM, so temporarily switch locales
111     if (rs[Rs_imLocale])
112     SET_LOCALE (rs[Rs_imLocale]);
113     // assume wchar_t == unicode or better
114 pcg 1.38 len = XwcLookupString (Input_Context, &ev, wkbuf,
115 pcg 1.36 KBUFSZ, &keysym, &status_return);
116     if (rs[Rs_imLocale])
117     SET_LOCALE (locale);
118 pcg 1.17
119 pcg 1.36 if (status_return == XLookupChars
120 pcg 1.49 || status_return == XLookupBoth)
121 pcg 1.36 {
122 pcg 1.55 /* make sure the user can type ctrl-@, i.e. NUL */
123     if (len == 1 && *wkbuf == 0)
124     {
125     kbuf[0] = 0;
126     len = 1;
127     }
128     else
129     {
130     wkbuf[len] = 0;
131     len = wcstombs ((char *)kbuf, wkbuf, KBUFSZ);
132     if (len < 0)
133     len = 0;
134     }
135 pcg 1.36 }
136     else
137     len = 0;
138     }
139 pcg 1.20
140 pcg 1.36 valid_keysym = status_return == XLookupKeySym
141 pcg 1.49 || status_return == XLookupBoth;
142 pcg 1.36 }
143     else
144 pcg 1.14 #endif
145 pcg 1.36 {
146 pcg 1.38 len = XLookupString (&ev, (char *)kbuf, KBUFSZ, &keysym, &compose);
147 pcg 1.49 valid_keysym = keysym != NoSymbol;
148 pcg 1.36 }
149    
150     if (valid_keysym)
151     {
152     if (TermWin.saveLines)
153     {
154 pcg 1.1 #ifdef UNSHIFTED_SCROLLKEYS
155 pcg 1.36 if (!ctrl && !meta)
156     {
157 pcg 1.1 #else
158 pcg 1.36 if (IS_SCROLL_MOD)
159     {
160 pcg 1.1 #endif
161 pcg 1.49 int lnsppg;
162 pcg 1.1
163     #ifdef PAGING_CONTEXT_LINES
164 pcg 1.36 lnsppg = TermWin.nrow - PAGING_CONTEXT_LINES;
165 pcg 1.1 #else
166 pcg 1.36 lnsppg = TermWin.nrow * 4 / 5;
167 pcg 1.1 #endif
168 pcg 1.36 if (keysym == XK_Prior)
169     {
170     scr_page (UP, lnsppg);
171     return;
172     }
173     else if (keysym == XK_Next)
174     {
175     scr_page (DN, lnsppg);
176     return;
177     }
178     }
179 pcg 1.1 #ifdef SCROLL_ON_UPDOWN_KEYS
180 pcg 1.36 if (IS_SCROLL_MOD)
181     {
182     if (keysym == XK_Up)
183     {
184     scr_page (UP, 1);
185     return;
186     }
187     else if (keysym == XK_Down)
188     {
189     scr_page (DN, 1);
190     return;
191     }
192     }
193 pcg 1.1 #endif
194     #ifdef SCROLL_ON_HOMEEND_KEYS
195 pcg 1.36 if (IS_SCROLL_MOD)
196     {
197     if (keysym == XK_Home)
198     {
199     scr_move_to (0, 1);
200     return;
201     }
202     else if (keysym == XK_End)
203     {
204     scr_move_to (1, 0);
205     return;
206     }
207     }
208     #endif
209     }
210    
211     if (shft)
212     {
213     /* Shift + F1 - F10 generates F11 - F20 */
214     if (keysym >= XK_F1 && keysym <= XK_F10)
215     {
216     keysym += (XK_F11 - XK_F1);
217     shft = 0; /* turn off Shift */
218     }
219     else if (!ctrl && !meta && (PrivateModes & PrivMode_ShiftKeys))
220     {
221     switch (keysym)
222     {
223     /* normal XTerm key bindings */
224     case XK_Insert: /* Shift+Insert = paste mouse selection */
225 pcg 1.38 selection_request (ev.time, 0, 0);
226 pcg 1.36 return;
227     /* rxvt extras */
228     case XK_KP_Add: /* Shift+KP_Add = bigger font */
229 pcg 1.51 change_font (FONT_UP);
230 pcg 1.36 return;
231     case XK_KP_Subtract: /* Shift+KP_Subtract = smaller font */
232 pcg 1.51 change_font (FONT_DN);
233 pcg 1.36 return;
234     }
235     }
236     }
237 pcg 1.1 #ifdef PRINTPIPE
238 pcg 1.36 if (keysym == XK_Print)
239     {
240     scr_printscreen (ctrl | shft);
241     return;
242     }
243 pcg 1.1 #endif
244    
245 pcg 1.36 if (keysym >= 0xFF00 && keysym <= 0xFFFF)
246     {
247 pcg 1.1 #ifdef KEYSYM_RESOURCE
248 pcg 1.43 if (! (shft | ctrl) && Keysym_map[keysym & 0xFF] != NULL)
249 pcg 1.36 {
250     unsigned int l;
251     const unsigned char *kbuf0;
252 pcg 1.1
253 pcg 1.36 kbuf0 = (Keysym_map[keysym & 0xFF]);
254     l = (unsigned int)*kbuf0++;
255 pcg 1.1
256 pcg 1.36 /* escape prefix */
257 pcg 1.68 if (meta
258 pcg 1.1 # ifdef META8_OPTION
259 pcg 1.68 && meta_char == C0_ESC
260 pcg 1.1 # endif
261 pcg 1.68 )
262     {
263     const unsigned char ch = C0_ESC;
264 pcg 1.36 tt_write (&ch, 1);
265 pcg 1.68 }
266    
267 pcg 1.36 tt_write (kbuf0, l);
268     return;
269     }
270     else
271     #endif
272     {
273     newlen = 1;
274     switch (keysym)
275     {
276 pcg 1.1 #ifndef NO_BACKSPACE_KEY
277 pcg 1.36 case XK_BackSpace:
278     if (PrivateModes & PrivMode_HaveBackSpace)
279     {
280 pcg 1.43 kbuf[0] = (!! (PrivateModes & PrivMode_BackSpace)
281 pcg 1.36 ^ !!ctrl) ? '\b' : '\177';
282     kbuf[1] = '\0';
283     }
284     else
285 pcg 1.43 STRCPY (kbuf, key_backspace);
286 pcg 1.36 break;
287 pcg 1.1 #endif
288     #ifndef NO_DELETE_KEY
289 pcg 1.36 case XK_Delete:
290 pcg 1.43 STRCPY (kbuf, key_delete);
291 pcg 1.36 break;
292 pcg 1.1 #endif
293 pcg 1.36 case XK_Tab:
294     if (shft)
295 pcg 1.43 STRCPY (kbuf, "\033[Z");
296 pcg 1.36 else
297     {
298 pcg 1.1 #ifdef CTRL_TAB_MAKES_META
299 pcg 1.36 if (ctrl)
300     meta = 1;
301 pcg 1.1 #endif
302     #ifdef MOD4_TAB_MAKES_META
303 pcg 1.38 if (ev.state & Mod4Mask)
304 pcg 1.36 meta = 1;
305 pcg 1.1 #endif
306 pcg 1.36 newlen = 0;
307     }
308     break;
309 pcg 1.1
310     #ifdef XK_KP_Left
311 pcg 1.36 case XK_KP_Up: /* \033Ox or standard */
312     case XK_KP_Down: /* \033Or or standard */
313     case XK_KP_Right: /* \033Ov or standard */
314     case XK_KP_Left: /* \033Ot or standard */
315     if ((PrivateModes & PrivMode_aplKP) ? !shft : shft)
316     {
317 pcg 1.43 STRCPY (kbuf, "\033OZ");
318 pcg 1.46 kbuf[2] = "txvr"[keysym - XK_KP_Left];
319 pcg 1.36 break;
320     }
321     else
322     /* translate to std. cursor key */
323     keysym = XK_Left + (keysym - XK_KP_Left);
324     /* FALLTHROUGH */
325     #endif
326     case XK_Up: /* "\033[A" */
327     case XK_Down: /* "\033[B" */
328     case XK_Right: /* "\033[C" */
329     case XK_Left: /* "\033[D" */
330 pcg 1.43 STRCPY (kbuf, "\033[Z");
331 pcg 1.47 kbuf[2] = "DACB"[keysym - XK_Left];
332 pcg 1.36 /* do Shift first */
333     if (shft)
334 pcg 1.47 kbuf[2] = "dacb"[keysym - XK_Left];
335 pcg 1.36 else if (ctrl)
336     {
337     kbuf[1] = 'O';
338 pcg 1.47 kbuf[2] = "dacb"[keysym - XK_Left];
339 pcg 1.36 }
340     else if (PrivateModes & PrivMode_aplCUR)
341     kbuf[1] = 'O';
342     break;
343 pcg 1.1
344     #ifndef UNSHIFTED_SCROLLKEYS
345     # ifdef XK_KP_Prior
346 pcg 1.36 case XK_KP_Prior:
347     /* allow shift to override */
348     if ((PrivateModes & PrivMode_aplKP) ? !shft : shft)
349     {
350 pcg 1.43 STRCPY (kbuf, "\033Oy");
351 pcg 1.36 break;
352     }
353     /* FALLTHROUGH */
354 pcg 1.1 # endif
355 pcg 1.36 case XK_Prior:
356 pcg 1.43 STRCPY (kbuf, "\033[5~");
357 pcg 1.36 break;
358 pcg 1.1 # ifdef XK_KP_Next
359 pcg 1.36 case XK_KP_Next:
360     /* allow shift to override */
361     if ((PrivateModes & PrivMode_aplKP) ? !shft : shft)
362     {
363 pcg 1.43 STRCPY (kbuf, "\033Os");
364 pcg 1.36 break;
365     }
366     /* FALLTHROUGH */
367 pcg 1.1 # endif
368 pcg 1.36 case XK_Next:
369 pcg 1.43 STRCPY (kbuf, "\033[6~");
370 pcg 1.36 break;
371     #endif
372     case XK_KP_Enter:
373     /* allow shift to override */
374     if ((PrivateModes & PrivMode_aplKP) ? !shft : shft)
375     {
376 pcg 1.43 STRCPY (kbuf, "\033OM");
377 pcg 1.36 }
378     else
379     {
380     kbuf[0] = '\r';
381     kbuf[1] = '\0';
382     }
383     break;
384 pcg 1.1
385     #ifdef XK_KP_Begin
386 pcg 1.36 case XK_KP_Begin:
387 pcg 1.43 STRCPY (kbuf, "\033Ou");
388 pcg 1.36 break;
389    
390     case XK_KP_Insert:
391 pcg 1.43 STRCPY (kbuf, "\033Op");
392 pcg 1.36 break;
393    
394     case XK_KP_Delete:
395 pcg 1.43 STRCPY (kbuf, "\033On");
396 pcg 1.36 break;
397     #endif
398     case XK_KP_F1: /* "\033OP" */
399     case XK_KP_F2: /* "\033OQ" */
400     case XK_KP_F3: /* "\033OR" */
401     case XK_KP_F4: /* "\033OS" */
402 pcg 1.43 STRCPY (kbuf, "\033OP");
403 pcg 1.36 kbuf[2] += (keysym - XK_KP_F1);
404     break;
405    
406     case XK_KP_Multiply: /* "\033Oj" : "*" */
407 pcg 1.49 case XK_KP_Add: /* "\033Ok" : "+" */
408 pcg 1.36 case XK_KP_Separator: /* "\033Ol" : "," */
409     case XK_KP_Subtract: /* "\033Om" : "-" */
410     case XK_KP_Decimal: /* "\033On" : "." */
411     case XK_KP_Divide: /* "\033Oo" : "/" */
412     case XK_KP_0: /* "\033Op" : "0" */
413     case XK_KP_1: /* "\033Oq" : "1" */
414     case XK_KP_2: /* "\033Or" : "2" */
415     case XK_KP_3: /* "\033Os" : "3" */
416     case XK_KP_4: /* "\033Ot" : "4" */
417     case XK_KP_5: /* "\033Ou" : "5" */
418     case XK_KP_6: /* "\033Ov" : "6" */
419     case XK_KP_7: /* "\033Ow" : "7" */
420     case XK_KP_8: /* "\033Ox" : "8" */
421     case XK_KP_9: /* "\033Oy" : "9" */
422     /* allow shift to override */
423     if ((PrivateModes & PrivMode_aplKP) ? !shft : shft)
424     {
425 pcg 1.43 STRCPY (kbuf, "\033Oj");
426 pcg 1.36 kbuf[2] += (keysym - XK_KP_Multiply);
427     }
428     else
429     {
430     kbuf[0] = ('*' + (keysym - XK_KP_Multiply));
431     kbuf[1] = '\0';
432     }
433     break;
434    
435     case XK_Find:
436 pcg 1.43 STRCPY (kbuf, "\033[1~");
437 pcg 1.36 break;
438     case XK_Insert:
439 pcg 1.43 STRCPY (kbuf, "\033[2~");
440 pcg 1.36 break;
441 pcg 1.1 #ifdef DXK_Remove /* support for DEC remove like key */
442 pcg 1.36 case DXK_Remove:
443     /* FALLTHROUGH */
444 pcg 1.1 #endif
445 pcg 1.36 case XK_Execute:
446 pcg 1.43 STRCPY (kbuf, "\033[3~");
447 pcg 1.36 break;
448     case XK_Select:
449 pcg 1.43 STRCPY (kbuf, "\033[4~");
450 pcg 1.36 break;
451 pcg 1.1 #ifdef XK_KP_End
452 pcg 1.36 case XK_KP_End:
453     /* allow shift to override */
454     if ((PrivateModes & PrivMode_aplKP) ? !shft : shft)
455     {
456 pcg 1.43 STRCPY (kbuf, "\033Oq");
457 pcg 1.36 break;
458     }
459     /* FALLTHROUGH */
460     #endif
461     case XK_End:
462 pcg 1.43 STRCPY (kbuf, KS_END);
463 pcg 1.36 break;
464 pcg 1.1 #ifdef XK_KP_Home
465 pcg 1.36 case XK_KP_Home:
466     /* allow shift to override */
467     if ((PrivateModes & PrivMode_aplKP) ? !shft : shft)
468     {
469 pcg 1.43 STRCPY (kbuf, "\033Ow");
470 pcg 1.36 break;
471     }
472     /* FALLTHROUGH */
473     #endif
474     case XK_Home:
475 pcg 1.43 STRCPY (kbuf, KS_HOME);
476 pcg 1.36 break;
477 pcg 1.1
478     #define FKEY(n, fkey) \
479 pcg 1.43 sprintf ((char *)kbuf,"\033[%2d~", (int) ((n) + (keysym - fkey)))
480 pcg 1.1
481 pcg 1.36 case XK_F1: /* "\033[11~" */
482     case XK_F2: /* "\033[12~" */
483     case XK_F3: /* "\033[13~" */
484     case XK_F4: /* "\033[14~" */
485     case XK_F5: /* "\033[15~" */
486 pcg 1.43 FKEY (11, XK_F1);
487 pcg 1.36 break;
488     case XK_F6: /* "\033[17~" */
489     case XK_F7: /* "\033[18~" */
490     case XK_F8: /* "\033[19~" */
491     case XK_F9: /* "\033[20~" */
492     case XK_F10: /* "\033[21~" */
493 pcg 1.43 FKEY (17, XK_F6);
494 pcg 1.36 break;
495     case XK_F11: /* "\033[23~" */
496     case XK_F12: /* "\033[24~" */
497     case XK_F13: /* "\033[25~" */
498     case XK_F14: /* "\033[26~" */
499 pcg 1.43 FKEY (23, XK_F11);
500 pcg 1.36 break;
501     case XK_F15: /* "\033[28~" */
502     case XK_F16: /* "\033[29~" */
503 pcg 1.43 FKEY (28, XK_F15);
504 pcg 1.36 break;
505     case XK_Help: /* "\033[28~" */
506 pcg 1.43 FKEY (28, XK_Help);
507 pcg 1.36 break;
508     case XK_Menu: /* "\033[29~" */
509 pcg 1.43 FKEY (29, XK_Menu);
510 pcg 1.36 break;
511     case XK_F17: /* "\033[31~" */
512     case XK_F18: /* "\033[32~" */
513     case XK_F19: /* "\033[33~" */
514     case XK_F20: /* "\033[34~" */
515     case XK_F21: /* "\033[35~" */
516     case XK_F22: /* "\033[36~" */
517     case XK_F23: /* "\033[37~" */
518     case XK_F24: /* "\033[38~" */
519     case XK_F25: /* "\033[39~" */
520     case XK_F26: /* "\033[40~" */
521     case XK_F27: /* "\033[41~" */
522     case XK_F28: /* "\033[42~" */
523     case XK_F29: /* "\033[43~" */
524     case XK_F30: /* "\033[44~" */
525     case XK_F31: /* "\033[45~" */
526     case XK_F32: /* "\033[46~" */
527     case XK_F33: /* "\033[47~" */
528     case XK_F34: /* "\033[48~" */
529     case XK_F35: /* "\033[49~" */
530 pcg 1.43 FKEY (31, XK_F17);
531 pcg 1.36 break;
532 pcg 1.1 #undef FKEY
533 pcg 1.36 default:
534     newlen = 0;
535     break;
536     }
537     if (newlen)
538 pcg 1.43 len = STRLEN (kbuf);
539 pcg 1.36 }
540 pcg 1.68
541 pcg 1.36 /*
542     * Pass meta for all function keys, if 'meta' option set
543     */
544 pcg 1.1 #ifdef META8_OPTION
545 pcg 1.36 if (meta && (meta_char == 0x80) && len > 0)
546     kbuf[len - 1] |= 0x80;
547 pcg 1.1 #endif
548 pcg 1.36
549     }
550     else if (ctrl && keysym == XK_minus)
551     {
552     len = 1;
553     kbuf[0] = '\037'; /* Ctrl-Minus generates ^_ (31) */
554     }
555     else
556     {
557 pcg 1.1 #ifdef META8_OPTION
558 pcg 1.36 /* set 8-bit on */
559     if (meta && (meta_char == 0x80))
560     {
561     unsigned char *ch;
562    
563     for (ch = kbuf; ch < kbuf + len; ch++)
564     *ch |= 0x80;
565 pcg 1.68
566 pcg 1.36 meta = 0;
567     }
568 pcg 1.1 #endif
569 pcg 1.36 /* nil */ ;
570     }
571     }
572 pcg 1.1
573 pcg 1.36 if (len <= 0)
574     return; /* not mapped */
575 pcg 1.1
576 pcg 1.36 if (Options & Opt_scrollTtyKeypress)
577     if (TermWin.view_start)
578     {
579     TermWin.view_start = 0;
580     want_refresh = 1;
581     }
582 pcg 1.1
583 pcg 1.36 /*
584     * these modifications only affect the static keybuffer
585     * pass Shift/Control indicators for function keys ending with `~'
586     *
587     * eg,
588     * Prior = "ESC[5~"
589     * Shift+Prior = "ESC[5$"
590     * Ctrl+Prior = "ESC[5^"
591     * Ctrl+Shift+Prior = "ESC[5@"
592     * Meta adds an Escape prefix (with META8_OPTION, if meta == <escape>).
593     */
594     if (kbuf[0] == C0_ESC && kbuf[1] == '[' && kbuf[len - 1] == '~')
595     kbuf[len - 1] = (shft ? (ctrl ? '@' : '$') : (ctrl ? '^' : '~'));
596 pcg 1.1
597 pcg 1.36 /* escape prefix */
598     if (meta
599 pcg 1.1 #ifdef META8_OPTION
600 pcg 1.55 && meta_char == C0_ESC
601 pcg 1.1 #endif
602 pcg 1.36 )
603     {
604     const unsigned char ch = C0_ESC;
605 pcg 1.43 tt_write (&ch, 1);
606 pcg 1.1 }
607 pcg 1.55
608     #if defined(DEBUG_CMD)
609     /* Display keyboard buffer contents */
610     unsigned char *p;
611     int i;
612    
613     fprintf (stderr, "key 0x%04X [%d]: `", (unsigned int)keysym, len);
614     for (i = 0, p = kbuf; i < len; i++, p++)
615     fprintf (stderr, (*p >= ' ' && *p < '\177' ? "%c" : "\\%03o"), *p);
616     fprintf (stderr, "'\n");
617 pcg 1.1 #endif /* DEBUG_CMD */
618 pcg 1.36 tt_write (kbuf, (unsigned int)len);
619 pcg 1.1 }
620     /*}}} */
621    
622     #if (MENUBAR_MAX)
623 pcg 1.43 /*{{{ rxvt_cmd_write (), rxvt_cmd_getc () */
624 pcg 1.1 /* attempt to `write' count to the input buffer */
625     unsigned int
626 pcg 1.34 rxvt_term::cmd_write (const unsigned char *str, unsigned int count)
627 pcg 1.1 {
628 pcg 1.81 unsigned int n, s;
629 pcg 1.1
630 pcg 1.36 n = cmdbuf_ptr - cmdbuf_base;
631 pcg 1.81 s = cmdbuf_base + CBUFSIZ - 1 - cmdbuf_endp;
632 pcg 1.57
633 pcg 1.36 if (n > 0 && s < count)
634     {
635 pcg 1.43 MEMMOVE (cmdbuf_base, cmdbuf_ptr,
636     (unsigned int) (cmdbuf_endp - cmdbuf_ptr));
637 pcg 1.36 cmdbuf_ptr = cmdbuf_base;
638     cmdbuf_endp -= n;
639     s += n;
640     }
641 pcg 1.57
642 pcg 1.36 if (count > s)
643     {
644 pcg 1.81 rxvt_warn ("data loss: cmd_write too large, continuing.\n");
645 pcg 1.36 count = s;
646     }
647 pcg 1.57
648 pcg 1.36 for (; count--;)
649     *cmdbuf_endp++ = *str++;
650 pcg 1.57
651     cmd_parse ();
652    
653 pcg 1.36 return 0;
654 pcg 1.1 }
655     #endif /* MENUBAR_MAX */
656    
657 pcg 1.3 void
658 pcg 1.11 rxvt_term::flush ()
659     {
660     #ifdef TRANSPARENT
661     if (want_full_refresh)
662     {
663     want_full_refresh = 0;
664 pcg 1.22 scr_clear ();
665     scr_touch (false);
666 pcg 1.11 want_refresh = 1;
667     }
668     #endif
669    
670     if (want_refresh)
671     {
672 pcg 1.22 scr_refresh (refresh_type);
673 pcg 1.34 scrollbar_show (1);
674 pcg 1.11 #ifdef USE_XIM
675 pcg 1.34 IMSendSpot ();
676 pcg 1.11 #endif
677     }
678    
679 pcg 1.42 display->flush ();
680 pcg 1.11 }
681    
682     void
683     rxvt_term::check_cb (check_watcher &w)
684     {
685     SET_R (this);
686 pcg 1.19 SET_LOCALE (locale);
687 pcg 1.11
688     flush ();
689     }
690    
691 pcg 1.27 #ifdef CURSOR_BLINK
692 pcg 1.3 void
693 pcg 1.31 rxvt_term::cursor_blink_cb (time_watcher &w)
694 pcg 1.5 {
695     hidden_cursor = !hidden_cursor;
696     want_refresh = 1;
697 pcg 1.28
698     w.start (w.at + BLINK_INTERVAL);
699 pcg 1.5 }
700 pcg 1.27 #endif
701 pcg 1.5
702 pcg 1.31 #ifdef TEXT_BLINK
703     void
704     rxvt_term::text_blink_cb (time_watcher &w)
705     {
706     if (scr_refresh_rend (RS_Blink, RS_Blink))
707     {
708     hidden_text = !hidden_text;
709     want_refresh = 1;
710     w.start (w.at + TEXT_BLINK_INTERVAL);
711     }
712     }
713     #endif
714    
715 pcg 1.4 bool
716 pcg 1.8 rxvt_term::pty_fill ()
717 pcg 1.4 {
718     ssize_t n = cmdbuf_endp - cmdbuf_ptr;
719    
720 pcg 1.93 if (CBUFSIZ == n)
721     {
722     rxvt_warn ("pty_fill on full buffer, draining input, continuing.\n");
723     n = 0;
724     }
725    
726 pcg 1.4 memmove (cmdbuf_base, cmdbuf_ptr, n);
727     cmdbuf_ptr = cmdbuf_base;
728     cmdbuf_endp = cmdbuf_ptr + n;
729 pcg 1.36
730 pcg 1.81 n = read (cmd_fd, cmdbuf_endp, CBUFSIZ - n);
731 pcg 1.4
732     if (n > 0)
733     {
734     cmdbuf_endp += n;
735     return true;
736     }
737 pcg 1.13 else if (n < 0 && errno != EAGAIN)
738     destroy ();
739 pcg 1.57
740 pcg 1.13 return false;
741 pcg 1.4 }
742    
743 pcg 1.3 void
744     rxvt_term::pty_cb (io_watcher &w, short revents)
745     {
746 pcg 1.9 SET_R (this);
747 pcg 1.19 SET_LOCALE (locale);
748 pcg 1.9
749 pcg 1.10 if (revents & EVENT_WRITE)
750     tt_write (0, 0);
751     else if (revents & EVENT_READ)
752 pcg 1.93 // loop, but don't allow a single term to monopolize us
753     while (pty_fill ())
754     if (cmd_parse ())
755     break;
756 pcg 1.57 }
757    
758 pcg 1.29 #ifdef POINTER_BLANK
759 pcg 1.6 void
760     rxvt_term::pointer_unblank ()
761     {
762 pcg 1.38 XDefineCursor (display->display, TermWin.vt, TermWin_cursor);
763 pcg 1.19 recolour_cursor ();
764 pcg 1.7
765 pcg 1.6 hidden_pointer = 0;
766 pcg 1.1
767 pcg 1.7 if (Options & Opt_pointerBlank)
768     pointer_ev.start (NOW + pointerBlankDelay);
769 pcg 1.1 }
770    
771     void
772 pcg 1.6 rxvt_term::pointer_blank ()
773 pcg 1.1 {
774 pcg 1.43 if (! (Options & Opt_pointerBlank))
775 pcg 1.6 return;
776    
777 pcg 1.38 XDefineCursor (display->display, TermWin.vt, blank_cursor);
778     XFlush (display->display);
779 pcg 1.1
780 pcg 1.6 hidden_pointer = 1;
781 pcg 1.1 }
782    
783     void
784 pcg 1.6 rxvt_term::pointer_cb (time_watcher &w)
785 pcg 1.1 {
786 pcg 1.9 SET_R (this);
787 pcg 1.19 SET_LOCALE (locale);
788 pcg 1.9
789 pcg 1.6 pointer_blank ();
790 pcg 1.1 }
791     #endif
792    
793     void
794 pcg 1.56 rxvt_term::mouse_report (XButtonEvent &ev)
795 pcg 1.1 {
796 pcg 1.56 int button_number, key_state = 0;
797     int x, y;
798 pcg 1.36
799 pcg 1.38 x = ev.x;
800     y = ev.y;
801 pcg 1.36 pixel_position (&x, &y);
802    
803     if (MEvent.button == AnyButton)
804     {
805     button_number = 3;
806     }
807     else
808     {
809     button_number = MEvent.button - Button1;
810     /* add 0x3D for wheel events, like xterm does */
811     if (button_number >= 3)
812     button_number += (64 - 3);
813     }
814 pcg 1.1
815 pcg 1.36 if (PrivateModes & PrivMode_MouseX10)
816     {
817     /*
818     * do not report ButtonRelease
819     * no state info allowed
820     */
821     key_state = 0;
822     if (button_number == 3)
823     return;
824     }
825     else
826     {
827     /* XTerm mouse reporting needs these values:
828     * 4 = Shift
829     * 8 = Meta
830     * 16 = Control
831     * plus will add in our own Double-Click reporting
832     * 32 = Double Click
833     */
834     key_state = ((MEvent.state & ShiftMask) ? 4 : 0)
835     + ((MEvent.state & ModMetaMask) ? 8 : 0)
836     + ((MEvent.state & ControlMask) ? 16 : 0);
837 pcg 1.1 #ifdef MOUSE_REPORT_DOUBLECLICK
838 pcg 1.36 key_state += ((MEvent.clicks > 1) ? 32 : 0);
839 pcg 1.1 #endif
840 pcg 1.36
841 pcg 1.1 }
842    
843     #ifdef DEBUG_MOUSEREPORT
844 pcg 1.43 fprintf (stderr, "Mouse [");
845 pcg 1.36 if (key_state & 16)
846 pcg 1.43 fputc ('C', stderr);
847 pcg 1.36 if (key_state & 4)
848 pcg 1.43 fputc ('S', stderr);
849 pcg 1.36 if (key_state & 8)
850 pcg 1.43 fputc ('A', stderr);
851 pcg 1.36 if (key_state & 32)
852 pcg 1.43 fputc ('2', stderr);
853     fprintf (stderr, "]: <%d>, %d/%d\n",
854 pcg 1.36 button_number,
855     x + 1,
856     y + 1);
857 pcg 1.1 #else
858 pcg 1.43 tt_printf ("\033[M%c%c%c",
859 pcg 1.36 (32 + button_number + key_state),
860     (32 + x + 1),
861     (32 + y + 1));
862 pcg 1.1 #endif
863     }
864    
865     #ifdef USING_W11LIB
866     void
867 pcg 1.43 rxvt_W11_process_x_event (XEvent *ev)
868 pcg 1.1 {
869 pcg 1.43 rxvt_t *r = rxvt_get_r ();
870 pcg 1.1
871 pcg 1.38 x_cb (*ev);
872 pcg 1.1 }
873     #endif
874    
875     /*{{{ process an X event */
876     void
877 pcg 1.38 rxvt_term::x_cb (XEvent &ev)
878 pcg 1.1 {
879 pcg 1.38 SET_R (this);
880     SET_LOCALE (locale);
881    
882     #if defined(CURSOR_BLINK)
883     if ((Options & Opt_cursorBlink) && ev.type == KeyPress)
884     {
885     if (hidden_cursor)
886     {
887     hidden_cursor = 0;
888     want_refresh = 1;
889     }
890    
891     cursor_blink_ev.start (NOW + BLINK_INTERVAL);
892     }
893     #endif
894    
895     #if defined(POINTER_BLANK)
896     if ((Options & Opt_pointerBlank) && pointerBlankDelay > 0)
897     {
898     if (ev.type == MotionNotify
899     || ev.type == ButtonPress
900     || ev.type == ButtonRelease)
901     if (hidden_pointer)
902     pointer_unblank ();
903    
904     if (ev.type == KeyPress && hidden_pointer == 0)
905     pointer_blank ();
906     }
907     #endif
908    
909     #ifdef USE_XIM
910     if (XFilterEvent (&ev, None))
911     return;
912     #endif
913    
914 pcg 1.36 Window unused_root, unused_child;
915     int unused_root_x, unused_root_y;
916     unsigned int unused_mask;
917 pcg 1.3
918 pcg 1.1 #ifdef DEBUG_X
919 pcg 1.36 const char *const eventnames[] =
920 pcg 1.1 { /* mason - this matches my system */
921 pcg 1.36 "",
922     "",
923     "KeyPress",
924     "KeyRelease",
925     "ButtonPress",
926     "ButtonRelease",
927     "MotionNotify",
928     "EnterNotify",
929     "LeaveNotify",
930     "FocusIn",
931     "FocusOut",
932     "KeymapNotify",
933     "Expose",
934     "GraphicsExpose",
935     "NoExpose",
936     "VisibilityNotify",
937     "CreateNotify",
938     "DestroyNotify",
939     "UnmapNotify",
940     "MapNotify",
941     "MapRequest",
942     "ReparentNotify",
943     "ConfigureNotify",
944     "ConfigureRequest",
945     "GravityNotify",
946     "ResizeRequest",
947     "CirculateNotify",
948     "CirculateRequest",
949     "PropertyNotify",
950     "SelectionClear",
951     "SelectionRequest",
952     "SelectionNotify",
953     "ColormapNotify",
954     "ClientMessage",
955     "MappingNotify"
956 pcg 1.1 };
957     #endif
958    
959     #ifdef DEBUG_X
960 pcg 1.36 struct timeval tp;
961     struct tm *ltt;
962 pcg 1.43 (void)gettimeofday (&tp, NULL);
963     ltt = localtime (& (tp.tv_sec));
964     D_X ((stderr, "Event: %-16s %-7s %08lx (%4d-%02d-%02d %02d:%02d:%02d.%.6ld) %s %lu", eventnames[ev.type], (ev.xany.window == TermWin.parent[0] ? "parent" : (ev.xany.window == TermWin.vt ? "vt" : (ev.xany.window == scrollBar.win ? "scroll" : (ev.xany.window == menuBar.win ? "menubar" : "UNKNOWN")))), (ev.xany.window == TermWin.parent[0] ? TermWin.parent[0] : (ev.xany.window == TermWin.vt ? TermWin.vt : (ev.xany.window == scrollBar.win ? scrollBar.win : (ev.xany.window == menuBar.win ? menuBar.win : 0)))), ltt->tm_year + 1900, ltt->tm_mon + 1, ltt->tm_mday, ltt->tm_hour, ltt->tm_min, ltt->tm_sec, tp.tv_usec, ev.xany.send_event ? "S" : " ", ev.xany.serial));
965 pcg 1.1 #endif
966    
967 pcg 1.38 switch (ev.type)
968 pcg 1.36 {
969     case KeyPress:
970 pcg 1.38 lookup_key (ev.xkey);
971 pcg 1.36 break;
972 pcg 1.1
973     #if defined(MOUSE_WHEEL) && defined(MOUSE_SLIP_WHEELING)
974 pcg 1.36 case KeyRelease:
975     {
976 pcg 1.43 if (! (ev.xkey.state & ControlMask))
977 pcg 1.36 mouse_slip_wheel_speed = 0;
978     else
979     {
980     KeySym ks;
981    
982 pcg 1.43 ks = XKeycodeToKeysym (display->display, ev.xkey.keycode, 0);
983 pcg 1.36 if (ks == XK_Control_L || ks == XK_Control_R)
984     mouse_slip_wheel_speed = 0;
985     }
986     break;
987     }
988     #endif
989    
990     case ButtonPress:
991 pcg 1.38 button_press (ev.xbutton);
992 pcg 1.36 break;
993    
994     case ButtonRelease:
995 pcg 1.38 button_release (ev.xbutton);
996 pcg 1.36 break;
997    
998     case ClientMessage:
999 pcg 1.38 if (ev.xclient.format == 32
1000     && (Atom)ev.xclient.data.l[0] == xa[XA_WMDELETEWINDOW])
1001 pcg 1.34 destroy ();
1002 pcg 1.1 #ifdef OFFIX_DND
1003 pcg 1.36 /* OffiX Dnd (drag 'n' drop) protocol */
1004 pcg 1.38 else if (ev.xclient.message_type == xa[XA_DNDPROTOCOL]
1005     && (ev.xclient.data.l[0] == DndFile
1006     || ev.xclient.data.l[0] == DndDir
1007     || ev.xclient.data.l[0] == DndLink))
1008 pcg 1.36 {
1009     /* Get Dnd data */
1010 pcg 1.93 Atom ActualType;
1011     int ActualFormat;
1012     unsigned char *data;
1013     unsigned long Size, RemainingBytes;
1014 pcg 1.36
1015 pcg 1.43 XGetWindowProperty (display->display, display->root,
1016 pcg 1.36 xa[XA_DNDSELECTION],
1017     0L, 1000000L,
1018     False, AnyPropertyType,
1019     &ActualType, &ActualFormat,
1020     &Size, &RemainingBytes,
1021     &data);
1022 pcg 1.43 XChangeProperty (display->display, display->root,
1023 pcg 1.36 XA_CUT_BUFFER0, XA_STRING,
1024     8, PropModeReplace,
1025 pcg 1.43 data, STRLEN (data));
1026 pcg 1.93 XFree (data);
1027 pcg 1.38 selection_paste (display->root, XA_CUT_BUFFER0, True);
1028 pcg 1.43 XSetInputFocus (display->display, display->root, RevertToNone, CurrentTime);
1029 pcg 1.36 }
1030 pcg 1.1 #endif /* OFFIX_DND */
1031 pcg 1.36 break;
1032 pcg 1.1
1033 pcg 1.36 case MappingNotify:
1034 pcg 1.43 XRefreshKeyboardMapping (& (ev.xmapping));
1035 pcg 1.36 break;
1036    
1037     /*
1038     * XXX: this is not the _current_ arrangement
1039     * Here's my conclusion:
1040     * If the window is completely unobscured, use bitblt's
1041     * to scroll. Even then, they're only used when doing partial
1042     * screen scrolling. When partially obscured, we have to fill
1043     * in the GraphicsExpose parts, which means that after each refresh,
1044     * we need to wait for the graphics expose or Noexpose events,
1045     * which ought to make things real slow!
1046     */
1047     case VisibilityNotify:
1048 pcg 1.38 switch (ev.xvisibility.state)
1049 pcg 1.8 {
1050     case VisibilityUnobscured:
1051 pcg 1.34 refresh_type = FAST_REFRESH;
1052 pcg 1.8 break;
1053     case VisibilityPartiallyObscured:
1054 pcg 1.34 refresh_type = SLOW_REFRESH;
1055 pcg 1.8 break;
1056     default:
1057 pcg 1.34 refresh_type = NO_REFRESH;
1058 pcg 1.8 break;
1059     }
1060 pcg 1.36 break;
1061 pcg 1.1
1062 pcg 1.36 case FocusIn:
1063     if (!TermWin.focus)
1064     {
1065     TermWin.focus = 1;
1066     want_refresh = 1;
1067 pcg 1.1 #ifdef USE_XIM
1068 pcg 1.36 if (Input_Context != NULL)
1069 pcg 1.43 XSetICFocus (Input_Context);
1070 pcg 1.1 #endif
1071 pcg 1.5 #ifdef CURSOR_BLINK
1072 pcg 1.34 if (Options & Opt_cursorBlink)
1073     cursor_blink_ev.start (NOW + BLINK_INTERVAL);
1074 pcg 1.5 #endif
1075 pcg 1.1
1076 pcg 1.36 }
1077     break;
1078    
1079     case FocusOut:
1080     if (TermWin.focus)
1081     {
1082     TermWin.focus = 0;
1083     want_refresh = 1;
1084 pcg 1.1 #ifdef USE_XIM
1085 pcg 1.36 if (Input_Context != NULL)
1086 pcg 1.43 XUnsetICFocus (Input_Context);
1087 pcg 1.5 #endif
1088     #ifdef CURSOR_BLINK
1089 pcg 1.34 if (Options & Opt_cursorBlink)
1090     cursor_blink_ev.stop ();
1091     hidden_cursor = 0;
1092 pcg 1.1 #endif
1093    
1094 pcg 1.36 }
1095     break;
1096    
1097     case ConfigureNotify:
1098 pcg 1.38 if (ev.xconfigure.window == TermWin.parent[0])
1099 pcg 1.36 {
1100 pcg 1.38 int height, width;
1101 pcg 1.36
1102     do
1103     { /* Wrap lots of configures into one */
1104 pcg 1.38 width = ev.xconfigure.width;
1105     height = ev.xconfigure.height;
1106 pcg 1.43 D_SIZE ((stderr, "Size: ConfigureNotify: %4d x %4d", width, height));
1107 pcg 1.36 }
1108 pcg 1.43 while (XCheckTypedWindowEvent (display->display, ev.xconfigure.window, ConfigureNotify, &ev));
1109 pcg 1.38
1110 pcg 1.36 if (szHint.width != width || szHint.height != height)
1111     {
1112 pcg 1.43 D_SIZE ((stderr, "Size: Resizing from: %4d x %4d", szHint.width, szHint.height));
1113 pcg 1.36 resize_all_windows (width, height, 1);
1114     }
1115 pcg 1.1 #ifdef DEBUG_SIZE
1116 pcg 1.36 else
1117     {
1118 pcg 1.43 D_SIZE ((stderr, "Size: Not resizing"));
1119 pcg 1.36 }
1120 pcg 1.1 #endif
1121     #ifdef TRANSPARENT /* XXX: maybe not needed - leave in for now */
1122 pcg 1.36 if (Options & Opt_transparent)
1123     {
1124     check_our_parents ();
1125     if (am_transparent)
1126     want_full_refresh = 1;
1127     }
1128     #endif
1129     }
1130     break;
1131    
1132     case SelectionClear:
1133 pcg 1.81 selection_clear ();
1134 pcg 1.36 break;
1135    
1136     case SelectionNotify:
1137     if (selection_wait == Sel_normal)
1138 pcg 1.38 selection_paste (ev.xselection.requestor,
1139     ev.xselection.property, True);
1140 pcg 1.36 break;
1141    
1142     case SelectionRequest:
1143 pcg 1.38 selection_send (ev.xselectionrequest);
1144 pcg 1.36 break;
1145 pcg 1.1
1146 pcg 1.36 case UnmapNotify:
1147     TermWin.mapped = 0;
1148 pcg 1.31 #ifdef TEXT_BLINK
1149 pcg 1.34 text_blink_ev.stop ();
1150 pcg 1.31 #endif
1151 pcg 1.36 break;
1152 pcg 1.1
1153 pcg 1.36 case MapNotify:
1154     TermWin.mapped = 1;
1155 pcg 1.31 #ifdef TEXT_BLINK
1156 pcg 1.34 text_blink_ev.start (NOW + TEXT_BLINK_INTERVAL);
1157 pcg 1.31 #endif
1158 pcg 1.36 break;
1159 pcg 1.1
1160     #ifdef TRANSPARENT
1161 pcg 1.36 case ReparentNotify:
1162 pcg 1.38 rootwin_cb (ev);
1163     break;
1164 pcg 1.1 #endif /* TRANSPARENT */
1165    
1166 pcg 1.36 case GraphicsExpose:
1167     case Expose:
1168 pcg 1.38 if (ev.xany.window == TermWin.vt)
1169 pcg 1.36 {
1170 pcg 1.1 #ifdef NO_SLOW_LINK_SUPPORT
1171 pcg 1.38 scr_expose (ev.xexpose.x, ev.xexpose.y,
1172     ev.xexpose.width, ev.xexpose.height, False);
1173 pcg 1.1 #else
1174     // don't understand this, so commented it out
1175 pcg 1.38 scr_expose (ev.xexpose.x, ev.xexpose.y,
1176     ev.xexpose.width, ev.xexpose.height, False);
1177     //scr_expose (ev.xexpose.x, 0,
1178     // ev.xexpose.width, TermWin.height, False);
1179 pcg 1.36 #endif
1180     want_refresh = 1;
1181     }
1182     else
1183     {
1184 pcg 1.38 XEvent unused_event;
1185 pcg 1.36
1186 pcg 1.43 while (XCheckTypedWindowEvent (display->display, ev.xany.window,
1187 pcg 1.36 Expose,
1188 pcg 1.38 &unused_event)) ;
1189 pcg 1.43 while (XCheckTypedWindowEvent (display->display, ev.xany.window,
1190 pcg 1.36 GraphicsExpose,
1191 pcg 1.38 &unused_event)) ;
1192 pcg 1.43 if (isScrollbarWindow (ev.xany.window))
1193 pcg 1.36 {
1194 pcg 1.43 scrollBar.setIdle ();
1195 pcg 1.36 scrollbar_show (0);
1196     }
1197 pcg 1.1 #ifdef MENUBAR
1198 pcg 1.43 if (menubar_visible () && isMenuBarWindow (ev.xany.window))
1199 pcg 1.36 menubar_expose ();
1200 pcg 1.1 #endif
1201 pcg 1.36 }
1202     break;
1203    
1204     case MotionNotify:
1205 pcg 1.1 #ifdef POINTER_BLANK
1206 pcg 1.36 if (hidden_pointer)
1207     pointer_unblank ();
1208 pcg 1.1 #endif
1209     #if MENUBAR
1210 pcg 1.43 if (isMenuBarWindow (ev.xany.window))
1211 pcg 1.36 {
1212 pcg 1.56 menubar_control (ev.xbutton);
1213 pcg 1.36 break;
1214     }
1215     #endif
1216 pcg 1.43 if ((PrivateModes & PrivMode_mouse_report) && ! (bypass_keystate))
1217 pcg 1.36 break;
1218    
1219 pcg 1.38 if (ev.xany.window == TermWin.vt)
1220 pcg 1.36 {
1221 pcg 1.38 if ((ev.xbutton.state & (Button1Mask | Button3Mask)))
1222 pcg 1.36 {
1223 pcg 1.38 while (XCheckTypedWindowEvent (display->display, TermWin.vt, MotionNotify, &ev))
1224     ;
1225    
1226 pcg 1.43 XQueryPointer (display->display, TermWin.vt,
1227 pcg 1.36 &unused_root, &unused_child,
1228     &unused_root_x, &unused_root_y,
1229 pcg 1.43 & (ev.xbutton.x), & (ev.xbutton.y),
1230 pcg 1.36 &unused_mask);
1231 pcg 1.1 #ifdef MOUSE_THRESHOLD
1232 pcg 1.36 /* deal with a `jumpy' mouse */
1233 pcg 1.38 if ((ev.xmotion.time - MEvent.time) > MOUSE_THRESHOLD)
1234 pcg 1.36 {
1235 pcg 1.1 #endif
1236 pcg 1.38 selection_extend ((ev.xbutton.x), (ev.xbutton.y),
1237     (ev.xbutton.state & Button3Mask) ? 2 : 0);
1238 pcg 1.1 #ifdef SELECTION_SCROLLING
1239 pcg 1.38 if (ev.xbutton.y < TermWin.int_bwidth
1240 pcg 1.43 || Pixel2Row (ev.xbutton.y) > (TermWin.nrow-1))
1241 pcg 1.36 {
1242     int dist;
1243    
1244     pending_scroll_selection=1;
1245    
1246     /* don't clobber the current delay if we are
1247     * already in the middle of scrolling.
1248     */
1249     if (scroll_selection_delay<=0)
1250     scroll_selection_delay=SCROLLBAR_CONTINUOUS_DELAY;
1251    
1252     /* save the event params so we can highlight
1253     * the selection in the pending-scroll loop
1254     */
1255 pcg 1.38 selection_save_x=ev.xbutton.x;
1256     selection_save_y=ev.xbutton.y;
1257 pcg 1.36 selection_save_state=
1258 pcg 1.38 (ev.xbutton.state & Button3Mask) ? 2 : 0;
1259 pcg 1.36
1260     /* calc number of lines to scroll */
1261 pcg 1.38 if (ev.xbutton.y<TermWin.int_bwidth)
1262 pcg 1.36 {
1263     scroll_selection_dir = UP;
1264 pcg 1.38 dist = TermWin.int_bwidth - ev.xbutton.y;
1265 pcg 1.36 }
1266     else
1267     {
1268     scroll_selection_dir = DN;
1269 pcg 1.38 dist = ev.xbutton.y -
1270 pcg 1.36 (TermWin.int_bwidth + TermWin.height);
1271     }
1272 pcg 1.43 scroll_selection_lines= (Pixel2Height (dist)/
1273 pcg 1.36 SELECTION_SCROLL_LINE_SPEEDUP)+1;
1274 pcg 1.43 MIN_IT (scroll_selection_lines,
1275 pcg 1.36 SELECTION_SCROLL_MAX_LINES);
1276     }
1277     else
1278     {
1279     /* we are within the text window, so we
1280     * shouldn't be scrolling
1281     */
1282     pending_scroll_selection = 0;
1283     }
1284 pcg 1.1 #endif
1285     #ifdef MOUSE_THRESHOLD
1286 pcg 1.36
1287     }
1288 pcg 1.1 #endif
1289 pcg 1.36
1290     }
1291     }
1292 pcg 1.43 else if (isScrollbarWindow (ev.xany.window) && scrollbar_isMotion ())
1293 pcg 1.36 {
1294 pcg 1.43 while (XCheckTypedWindowEvent (display->display, scrollBar.win,
1295 pcg 1.38 MotionNotify, &ev)) ;
1296 pcg 1.43 XQueryPointer (display->display, scrollBar.win,
1297 pcg 1.36 &unused_root, &unused_child,
1298     &unused_root_x, &unused_root_y,
1299 pcg 1.43 & (ev.xbutton.x), & (ev.xbutton.y),
1300 pcg 1.36 &unused_mask);
1301 pcg 1.43 scr_move_to (scrollbar_position (ev.xbutton.y) - csrO,
1302     scrollbar_size ());
1303 pcg 1.36 scr_refresh (refresh_type);
1304     refresh_limit = 0;
1305     scrollbar_show (1);
1306     }
1307     break;
1308     }
1309     }
1310 pcg 1.1
1311     void
1312 pcg 1.38 rxvt_term::rootwin_cb (XEvent &ev)
1313     {
1314     SET_R (this);
1315     SET_LOCALE (locale);
1316    
1317 pcg 1.40 switch (ev.type)
1318 pcg 1.38 {
1319 pcg 1.40 case PropertyNotify:
1320     if (ev.xproperty.atom == xa[XA_VT_SELECTION])
1321     {
1322     if (ev.xproperty.state == PropertyNewValue)
1323     selection_property (ev.xproperty.window, ev.xproperty.atom);
1324     break;
1325     }
1326     #ifdef TRANSPARENT
1327     else
1328     {
1329     /*
1330     * if user used some Esetroot compatible prog to set the root bg,
1331     * use the property to determine the pixmap. We use it later on.
1332     */
1333     if (xa[XA_XROOTPMAPID] == 0)
1334 pcg 1.43 xa[XA_XROOTPMAPID] = XInternAtom (display->display, "_XROOTPMAP_ID", False);
1335 pcg 1.38
1336 pcg 1.40 if (ev.xproperty.atom != xa[XA_XROOTPMAPID])
1337     return;
1338     }
1339 pcg 1.38
1340 pcg 1.40 /* FALLTHROUGH */
1341     case ReparentNotify:
1342 pcg 1.90 if ((Options & Opt_transparent) && check_our_parents () && am_transparent)
1343     want_full_refresh = 1;
1344 pcg 1.40 break;
1345     #endif
1346 pcg 1.38 }
1347     }
1348    
1349     void
1350 pcg 1.56 rxvt_term::button_press (XButtonEvent &ev)
1351 pcg 1.1 {
1352 pcg 1.36 int reportmode = 0, clickintime;
1353 pcg 1.1
1354 pcg 1.38 bypass_keystate = ev.state & (ModMetaMask | ShiftMask);
1355 pcg 1.36 if (!bypass_keystate)
1356 pcg 1.43 reportmode = !! (PrivateModes & PrivMode_mouse_report);
1357 pcg 1.36 /*
1358     * VT window processing of button press
1359     */
1360 pcg 1.38 if (ev.window == TermWin.vt)
1361 pcg 1.36 {
1362 pcg 1.50 clickintime = ev.time - MEvent.time < MULTICLICK_TIME;
1363     if (reportmode)
1364 pcg 1.36 {
1365 pcg 1.50 /* mouse report from vt window */
1366     /* save the xbutton state (for ButtonRelease) */
1367     MEvent.state = ev.state;
1368     #ifdef MOUSE_REPORT_DOUBLECLICK
1369     if (ev.button == MEvent.button && clickintime)
1370 pcg 1.36 {
1371 pcg 1.50 /* same button, within alloted time */
1372     MEvent.clicks++;
1373     if (MEvent.clicks > 1)
1374 pcg 1.36 {
1375 pcg 1.50 /* only report double clicks */
1376     MEvent.clicks = 2;
1377 pcg 1.36 mouse_report (ev);
1378 pcg 1.50
1379     /* don't report the release */
1380     MEvent.clicks = 0;
1381     MEvent.button = AnyButton;
1382 pcg 1.36 }
1383 pcg 1.50 }
1384     else
1385     {
1386     /* different button, or time expired */
1387     MEvent.clicks = 1;
1388 pcg 1.38 MEvent.button = ev.button;
1389 pcg 1.36 mouse_report (ev);
1390 pcg 1.50 }
1391     #else
1392     MEvent.button = ev.button;
1393     mouse_report (ev);
1394 pcg 1.1 #endif /* MOUSE_REPORT_DOUBLECLICK */
1395 pcg 1.36
1396 pcg 1.50 }
1397     else
1398     {
1399     if (ev.button != MEvent.button)
1400     MEvent.clicks = 0;
1401     switch (ev.button)
1402 pcg 1.36 {
1403 pcg 1.50 case Button1:
1404     /* allow shift+left click to extend selection */
1405     if (ev.state & ShiftMask && ! (PrivateModes & PrivMode_mouse_report))
1406     {
1407     if (MEvent.button == Button1 && clickintime)
1408     selection_rotate (ev.x, ev.y);
1409     else
1410     selection_extend (ev.x, ev.y, 1);
1411     }
1412     else
1413     {
1414     if (MEvent.button == Button1 && clickintime)
1415     MEvent.clicks++;
1416 pcg 1.36 else
1417 pcg 1.50 MEvent.clicks = 1;
1418 pcg 1.21
1419 pcg 1.50 selection_click (MEvent.clicks, ev.x, ev.y);
1420     }
1421 pcg 1.21
1422 pcg 1.50 MEvent.button = Button1;
1423     break;
1424 pcg 1.1
1425 pcg 1.50 case Button3:
1426     if (MEvent.button == Button3 && clickintime)
1427     selection_rotate (ev.x, ev.y);
1428     else
1429     selection_extend (ev.x, ev.y, 1);
1430     MEvent.button = Button3;
1431     break;
1432 pcg 1.36 }
1433     }
1434 pcg 1.50 MEvent.time = ev.time;
1435     return;
1436 pcg 1.36 }
1437 pcg 1.1
1438 pcg 1.36 /*
1439     * Scrollbar window processing of button press
1440     */
1441 pcg 1.43 if (isScrollbarWindow (ev.window))
1442 pcg 1.36 {
1443     scrollBar.setIdle ();
1444     /*
1445     * Rxvt-style scrollbar:
1446     * move up if mouse is above slider
1447     * move dn if mouse is below slider
1448     *
1449     * XTerm-style scrollbar:
1450     * Move display proportional to pointer location
1451     * pointer near top -> scroll one line
1452     * pointer near bot -> scroll full page
1453     */
1454 pcg 1.1 #ifndef NO_SCROLLBAR_REPORT
1455 pcg 1.36 if (reportmode)
1456     {
1457     /*
1458     * Mouse report disabled scrollbar:
1459     * arrow buttons - send up/down
1460     * click on scrollbar - send pageup/down
1461     */
1462     if ((scrollBar.style == R_SB_NEXT
1463 pcg 1.43 && scrollbarnext_upButton (ev.y))
1464 pcg 1.36 || (scrollBar.style == R_SB_RXVT
1465 pcg 1.43 && scrollbarrxvt_upButton (ev.y)))
1466     tt_printf ("\033[A");
1467 pcg 1.36 else if ((scrollBar.style == R_SB_NEXT
1468 pcg 1.43 && scrollbarnext_dnButton (ev.y))
1469 pcg 1.36 || (scrollBar.style == R_SB_RXVT
1470 pcg 1.43 && scrollbarrxvt_dnButton (ev.y)))
1471     tt_printf ("\033[B");
1472 pcg 1.36 else
1473 pcg 1.38 switch (ev.button)
1474 pcg 1.36 {
1475     case Button2:
1476 pcg 1.43 tt_printf ("\014");
1477 pcg 1.36 break;
1478     case Button1:
1479 pcg 1.43 tt_printf ("\033[6~");
1480 pcg 1.36 break;
1481     case Button3:
1482 pcg 1.43 tt_printf ("\033[5~");
1483 pcg 1.36 break;
1484     }
1485     }
1486     else
1487 pcg 1.1 #endif /* NO_SCROLLBAR_REPORT */
1488    
1489 pcg 1.36 {
1490     char upordown = 0;
1491    
1492     if (scrollBar.style == R_SB_NEXT)
1493     {
1494 pcg 1.43 if (scrollbarnext_upButton (ev.y))
1495 pcg 1.36 upordown = -1; /* up */
1496 pcg 1.43 else if (scrollbarnext_dnButton (ev.y))
1497 pcg 1.36 upordown = 1; /* down */
1498     }
1499     else if (scrollBar.style == R_SB_RXVT)
1500     {
1501 pcg 1.43 if (scrollbarrxvt_upButton (ev.y))
1502 pcg 1.36 upordown = -1; /* up */
1503 pcg 1.43 else if (scrollbarrxvt_dnButton (ev.y))
1504 pcg 1.36 upordown = 1; /* down */
1505     }
1506     if (upordown)
1507     {
1508 pcg 1.1 #ifndef NO_SCROLLBAR_BUTTON_CONTINUAL_SCROLLING
1509 pcg 1.36 scroll_arrow_delay = SCROLLBAR_INITIAL_DELAY;
1510 pcg 1.1 #endif
1511 pcg 1.36 if (scr_page (upordown < 0 ? UP : DN, 1))
1512     {
1513     if (upordown < 0)
1514     scrollBar.setUp ();
1515     else
1516     scrollBar.setDn ();
1517     }
1518     }
1519     else
1520 pcg 1.38 switch (ev.button)
1521 pcg 1.36 {
1522     case Button2:
1523     switch (scrollbar_align)
1524     {
1525     case R_SB_ALIGN_TOP:
1526     csrO = 0;
1527     break;
1528     case R_SB_ALIGN_CENTRE:
1529     csrO = (scrollBar.bot - scrollBar.top) / 2;
1530     break;
1531     case R_SB_ALIGN_BOTTOM:
1532     csrO = scrollBar.bot - scrollBar.top;
1533     break;
1534     }
1535     if (scrollBar.style == R_SB_XTERM
1536 pcg 1.43 || scrollbar_above_slider (ev.y)
1537     || scrollbar_below_slider (ev.y))
1538     scr_move_to ( scrollbar_position (ev.y) - csrO,
1539     scrollbar_size ());
1540 pcg 1.36 scrollBar.setMotion ();
1541     break;
1542    
1543     case Button1:
1544     if (scrollbar_align == R_SB_ALIGN_CENTRE)
1545 pcg 1.38 csrO = ev.y - scrollBar.top;
1546 pcg 1.36 /* FALLTHROUGH */
1547    
1548     case Button3:
1549     if (scrollBar.style != R_SB_XTERM)
1550     {
1551 pcg 1.43 if (scrollbar_above_slider (ev.y))
1552 pcg 1.1 # ifdef RXVT_SCROLL_FULL
1553 pcg 1.36 scr_page (UP, TermWin.nrow - 1);
1554 pcg 1.1 # else
1555 pcg 1.36 scr_page (UP, TermWin.nrow / 4);
1556 pcg 1.1 # endif
1557 pcg 1.43 else if (scrollbar_below_slider (ev.y))
1558 pcg 1.1 # ifdef RXVT_SCROLL_FULL
1559 pcg 1.36 scr_page (DN, TermWin.nrow - 1);
1560 pcg 1.1 # else
1561 pcg 1.36 scr_page (DN, TermWin.nrow / 4);
1562 pcg 1.1 # endif
1563 pcg 1.36 else
1564     scrollBar.setMotion ();
1565     }
1566     else
1567     {
1568 pcg 1.38 scr_page ((ev.button == Button1 ? DN : UP),
1569 pcg 1.36 (TermWin.nrow
1570 pcg 1.43 * scrollbar_position (ev.y)
1571     / scrollbar_size ()));
1572 pcg 1.36 }
1573     break;
1574     }
1575     }
1576     return;
1577 pcg 1.1 }
1578     #if MENUBAR
1579 pcg 1.36 /*
1580     * Menubar window processing of button press
1581     */
1582 pcg 1.43 if (isMenuBarWindow (ev.window))
1583 pcg 1.36 menubar_control (ev);
1584 pcg 1.1 #endif
1585     }
1586    
1587     void
1588 pcg 1.56 rxvt_term::button_release (XButtonEvent &ev)
1589 pcg 1.1 {
1590 pcg 1.38 int reportmode = 0;
1591 pcg 1.1
1592 pcg 1.36 csrO = 0; /* reset csr Offset */
1593     if (!bypass_keystate)
1594 pcg 1.43 reportmode = !! (PrivateModes & PrivMode_mouse_report);
1595 pcg 1.36
1596 pcg 1.43 if (scrollbar_isUpDn ())
1597 pcg 1.36 {
1598     scrollBar.setIdle ();
1599     scrollbar_show (0);
1600 pcg 1.1 #ifndef NO_SCROLLBAR_BUTTON_CONTINUAL_SCROLLING
1601 pcg 1.36 refresh_type &= ~SMOOTH_REFRESH;
1602 pcg 1.1 #endif
1603 pcg 1.36
1604 pcg 1.1 }
1605     #ifdef SELECTION_SCROLLING
1606 pcg 1.36 pending_scroll_selection=0;
1607 pcg 1.1 #endif
1608 pcg 1.38 if (ev.window == TermWin.vt)
1609 pcg 1.36 {
1610 pcg 1.50 if (reportmode)
1611 pcg 1.36 {
1612 pcg 1.50 /* mouse report from vt window */
1613     /* don't report release of wheel "buttons" */
1614     if (ev.button >= 4)
1615     return;
1616     #ifdef MOUSE_REPORT_DOUBLECLICK
1617     /* only report the release of 'slow' single clicks */
1618     if (MEvent.button != AnyButton
1619     && (ev.button != MEvent.button
1620     || (ev.time - MEvent.time
1621     > MULTICLICK_TIME / 2)))
1622 pcg 1.36 {
1623 pcg 1.50 MEvent.clicks = 0;
1624 pcg 1.36 MEvent.button = AnyButton;
1625     mouse_report (ev);
1626 pcg 1.50 }
1627     #else /* MOUSE_REPORT_DOUBLECLICK */
1628     MEvent.button = AnyButton;
1629     mouse_report (ev);
1630 pcg 1.1 #endif /* MOUSE_REPORT_DOUBLECLICK */
1631 pcg 1.50 return;
1632     }
1633     /*
1634     * dumb hack to compensate for the failure of click-and-drag
1635     * when overriding mouse reporting
1636     */
1637     if (PrivateModes & PrivMode_mouse_report
1638     && bypass_keystate
1639     && ev.button == Button1 && MEvent.clicks <= 1)
1640     selection_extend (ev.x, ev.y, 0);
1641    
1642     switch (ev.button)
1643     {
1644     case Button1:
1645     case Button3:
1646     selection_make (ev.time);
1647     break;
1648     case Button2:
1649     selection_request (ev.time, ev.x, ev.y);
1650     break;
1651     #ifdef MOUSE_WHEEL
1652     case Button4:
1653     case Button5:
1654 pcg 1.36 {
1655 pcg 1.50 int i;
1656     page_dirn v;
1657 pcg 1.36
1658 pcg 1.50 v = (ev.button == Button4) ? UP : DN;
1659     if (ev.state & ShiftMask)
1660     i = 1;
1661     else if ((Options & Opt_mouseWheelScrollPage))
1662     i = TermWin.nrow - 1;
1663     else
1664     i = 5;
1665 pcg 1.1 # ifdef MOUSE_SLIP_WHEELING
1666 pcg 1.50 if (ev.state & ControlMask)
1667     {
1668     mouse_slip_wheel_speed += (v ? -1 : 1);
1669     mouse_slip_wheel_delay = SCROLLBAR_CONTINUOUS_DELAY;
1670     }
1671 pcg 1.1 # endif
1672     # ifdef JUMP_MOUSE_WHEEL
1673 pcg 1.50 scr_page (v, i);
1674     scr_refresh (SMOOTH_REFRESH);
1675     scrollbar_show (1);
1676     # else
1677     while (i--)
1678     {
1679     scr_page (v, 1);
1680 pcg 1.36 scr_refresh (SMOOTH_REFRESH);
1681     scrollbar_show (1);
1682 pcg 1.50 }
1683 pcg 1.1 # endif
1684 pcg 1.36
1685 pcg 1.50 }
1686     break;
1687 pcg 1.1 #endif
1688 pcg 1.36
1689     }
1690     }
1691 pcg 1.1 #ifdef MENUBAR
1692 pcg 1.43 else if (isMenuBarWindow (ev.window))
1693 pcg 1.36 menubar_control (ev);
1694 pcg 1.1 #endif
1695     }
1696    
1697 pcg 1.90 #ifdef TRANSPARENT
1698     #if TINTING
1699     /* shading taken from eterm-0.9.2 */
1700     /* RGB 15 */
1701    
1702     static void
1703     shade_ximage_15(void *data, int bpl, int w, int h, int rm, int gm, int bm)
1704     {
1705     unsigned char *ptr;
1706     int x, y;
1707    
1708     ptr = (unsigned char *)data + (w * sizeof(uint16_t));
1709     if ((rm <= 256) && (gm <= 256) && (bm <= 256)) {
1710     /* No saturation */
1711     for (y = h; --y >= 0;) {
1712     for (x = -w; x < 0; x++) {
1713     int r, g, b;
1714    
1715     b = ((uint16_t *) ptr)[x];
1716     r = (b & 0x7c00) * rm;
1717     g = (b & 0x3e0) * gm;
1718     b = (b & 0x1f) * bm;
1719     ((uint16_t *) ptr)[x] = ((r >> 8) & 0x7c00)
1720     | ((g >> 8) & 0x3e0)
1721     | ((b >> 8) & 0x1f);
1722     }
1723     ptr += bpl;
1724     }
1725     } else {
1726     for (y = h; --y >= 0;) {
1727     for (x = -w; x < 0; x++) {
1728     int r, g, b;
1729    
1730     b = ((uint16_t *) ptr)[x];
1731     r = (b & 0x7c00) * rm;
1732     g = (b & 0x3e0) * gm;
1733     b = (b & 0x1f) * bm;
1734     r |= (!(r >> 15) - 1);
1735     g |= (!(g >> 10) - 1);
1736     b |= (!(b >> 5) - 1);
1737     ((uint16_t *) ptr)[x] = ((r >> 8) & 0x7c00)
1738     | ((g >> 8) & 0x3e0)
1739     | ((b >> 8) & 0x1f);
1740     }
1741     ptr += bpl;
1742     }
1743     }
1744     }
1745    
1746     /* RGB 16 */
1747     static void
1748     shade_ximage_16(void *data, int bpl, int w, int h, int rm, int gm, int bm)
1749     {
1750     unsigned char *ptr;
1751     int x, y;
1752    
1753     ptr = (unsigned char *)data + (w * sizeof(uint16_t));
1754     if ((rm <= 256) && (gm <= 256) && (bm <= 256)) {
1755     /* No saturation */
1756     for (y = h; --y >= 0;) {
1757     for (x = -w; x < 0; x++) {
1758     int r, g, b;
1759    
1760     b = ((uint16_t *) ptr)[x];
1761     r = (b & 0xf800) * rm;
1762     g = (b & 0x7e0) * gm;
1763     b = (b & 0x1f) * bm;
1764     ((uint16_t *) ptr)[x] = ((r >> 8) & 0xf800)
1765     | ((g >> 8) & 0x7e0)
1766     | ((b >> 8) & 0x1f);
1767     }
1768     ptr += bpl;
1769     }
1770     } else {
1771     for (y = h; --y >= 0;) {
1772     for (x = -w; x < 0; x++) {
1773     int r, g, b;
1774    
1775     b = ((uint16_t *) ptr)[x];
1776     r = (b & 0xf800) * rm;
1777     g = (b & 0x7e0) * gm;
1778     b = (b & 0x1f) * bm;
1779     r |= (!(r >> 16) - 1);
1780     g |= (!(g >> 11) - 1);
1781     b |= (!(b >> 5) - 1);
1782     ((uint16_t *) ptr)[x] = ((r >> 8) & 0xf800)
1783     | ((g >> 8) & 0x7e0)
1784     | ((b >> 8) & 0x1f);
1785     }
1786     ptr += bpl;
1787     }
1788     }
1789     }
1790    
1791     /* RGB 24 */
1792     static void
1793     shade_ximage_24(void *data, int bpl, int w, int h, int rm, int gm, int bm)
1794     {
1795     unsigned char *ptr;
1796     int x, y;
1797    
1798     ptr = (unsigned char *)data + (w * 3);
1799     if ((rm <= 256) && (gm <= 256) && (bm <= 256)) {
1800     /* No saturation */
1801     for (y = h; --y >= 0;) {
1802     for (x = -(w * 3); x < 0; x += 3) {
1803     int r, g, b;
1804    
1805     if (byteorder.big_endian()) {
1806     r = (ptr[x + 0] * rm) >> 8;
1807     g = (ptr[x + 1] * gm) >> 8;
1808     b = (ptr[x + 2] * bm) >> 8;
1809     ptr[x + 0] = r;
1810     ptr[x + 1] = g;
1811     ptr[x + 2] = b;
1812     } else {
1813     r = (ptr[x + 2] * rm) >> 8;
1814     g = (ptr[x + 1] * gm) >> 8;
1815     b = (ptr[x + 0] * bm) >> 8;
1816     ptr[x + 2] = r;
1817     ptr[x + 1] = g;
1818     ptr[x + 0] = b;
1819     }
1820     }
1821     ptr += bpl;
1822     }
1823     } else {
1824     for (y = h; --y >= 0;) {
1825     for (x = -(w * 3); x < 0; x += 3) {
1826     int r, g, b;
1827    
1828     if (byteorder.big_endian()) {
1829     r = (ptr[x + 0] * rm) >> 8;
1830     g = (ptr[x + 1] * gm) >> 8;
1831     b = (ptr[x + 2] * bm) >> 8;
1832    
1833     r |= (!(r >> 8) - 1);
1834     g |= (!(g >> 8) - 1);
1835     b |= (!(b >> 8) - 1);
1836    
1837     ptr[x + 0] = r;
1838     ptr[x + 1] = g;
1839     ptr[x + 2] = b;
1840     } else {
1841     r = (ptr[x + 2] * rm) >> 8;
1842     g = (ptr[x + 1] * gm) >> 8;
1843     b = (ptr[x + 0] * bm) >> 8;
1844    
1845     r |= (!(r >> 8) - 1);
1846     g |= (!(g >> 8) - 1);
1847     b |= (!(b >> 8) - 1);
1848    
1849     ptr[x + 2] = r;
1850     ptr[x + 1] = g;
1851     ptr[x + 0] = b;
1852     }
1853     }
1854     ptr += bpl;
1855     }
1856     }
1857     }
1858    
1859     /* RGB 32 */
1860     static void
1861     shade_ximage_32(void *data, int bpl, int w, int h, int rm, int gm, int bm)
1862     {
1863     unsigned char *ptr;
1864     int x, y;
1865    
1866     ptr = (unsigned char *)data + (w * 4);
1867     if ((rm <= 256) && (gm <= 256) && (bm <= 256)) {
1868     /* No saturation */
1869     for (y = h; --y >= 0;) {
1870     if (byteorder.big_endian()) {
1871     for (x = -(w * 4); x < 0; x += 4) {
1872     int r, g, b;
1873    
1874     r = (ptr[x + 1] * rm) >> 8;
1875     g = (ptr[x + 2] * gm) >> 8;
1876     b = (ptr[x + 3] * bm) >> 8;
1877     ptr[x + 1] = r;
1878     ptr[x + 2] = g;
1879     ptr[x + 3] = b;
1880     }
1881     } else {
1882     for (x = -(w * 4); x < 0; x += 4) {
1883     int r, g, b;
1884    
1885     r = (ptr[x + 2] * rm) >> 8;
1886     g = (ptr[x + 1] * gm) >> 8;
1887     b = (ptr[x + 0] * bm) >> 8;
1888     ptr[x + 2] = r;
1889     ptr[x + 1] = g;
1890     ptr[x + 0] = b;
1891     }
1892     }
1893     ptr += bpl;
1894     }
1895     } else {
1896     for (y = h; --y >= 0;) {
1897     for (x = -(w * 4); x < 0; x += 4) {
1898     int r, g, b;
1899    
1900     if (byteorder.big_endian()) {
1901     r = (ptr[x + 1] * rm) >> 8;
1902     g = (ptr[x + 2] * gm) >> 8;
1903     b = (ptr[x + 3] * bm) >> 8;
1904    
1905     r |= (!(r >> 8) - 1);
1906     g |= (!(g >> 8) - 1);
1907     b |= (!(b >> 8) - 1);
1908    
1909     ptr[x + 1] = r;
1910     ptr[x + 2] = g;
1911     ptr[x + 3] = b;
1912     } else {
1913     r = (ptr[x + 2] * rm) >> 8;
1914     g = (ptr[x + 1] * gm) >> 8;
1915     b = (ptr[x + 0] * bm) >> 8;
1916    
1917     r |= (!(r >> 8) - 1);
1918     g |= (!(g >> 8) - 1);
1919     b |= (!(b >> 8) - 1);
1920    
1921     ptr[x + 2] = r;
1922     ptr[x + 1] = g;
1923     ptr[x + 0] = b;
1924     }
1925     }
1926     ptr += bpl;
1927     }
1928     }
1929     }
1930    
1931     #endif
1932 pcg 1.1
1933     /*
1934     * Check our parents are still who we think they are.
1935     * Do transparency updates if required
1936     */
1937     int
1938 pcg 1.34 rxvt_term::check_our_parents ()
1939 pcg 1.1 {
1940 pcg 1.90 int i, pchanged, aformat, have_pixmap, rootdepth;
1941     unsigned long nitems, bytes_after;
1942     Atom atype;
1943     unsigned char *prop = NULL;
1944     Window root, oldp, *list;
1945     Pixmap rootpixmap = None;
1946 pcg 1.36 XWindowAttributes wattr, wrootattr;
1947    
1948     pchanged = 0;
1949    
1950 pcg 1.90 if (!(Options & Opt_transparent))
1951 pcg 1.36 return pchanged; /* Don't try any more */
1952    
1953 pcg 1.43 XGetWindowAttributes (display->display, display->root, &wrootattr);
1954 pcg 1.36 rootdepth = wrootattr.depth;
1955    
1956 pcg 1.43 XGetWindowAttributes (display->display, TermWin.parent[0], &wattr);
1957 pcg 1.90
1958 pcg 1.36 if (rootdepth != wattr.depth)
1959     {
1960     if (am_transparent)
1961     {
1962     pchanged = 1;
1963 pcg 1.90 XSetWindowBackground (display->display, TermWin.vt, PixColors[Color_bg]);
1964 pcg 1.36 am_transparent = am_pixmap_trans = 0;
1965     }
1966 pcg 1.90
1967 pcg 1.36 return pchanged; /* Don't try any more */
1968 pcg 1.1 }
1969    
1970 pcg 1.36 /* Get all X ops out of the queue so that our information is up-to-date. */
1971 pcg 1.43 XSync (display->display, False);
1972 pcg 1.1
1973 pcg 1.36 /*
1974     * Make the frame window set by the window manager have
1975     * the root background. Some window managers put multiple nested frame
1976     * windows for each client, so we have to take care about that.
1977     */
1978 pcg 1.90 i = (xa[XA_XROOTPMAPID]
1979     && XGetWindowProperty (display->display, display->root, xa[XA_XROOTPMAPID],
1980 pcg 1.36 0L, 1L, False, XA_PIXMAP, &atype, &aformat,
1981 pcg 1.90 &nitems, &bytes_after, &prop) == Success);
1982    
1983     if (!i || prop == NULL)
1984     i = (xa[XA_XSETROOTID]
1985     && XGetWindowProperty (display->display, display->root, xa[XA_XSETROOTID],
1986     0L, 1L, False, XA_PIXMAP, &atype, &aformat,
1987     &nitems, &bytes_after, &prop) == Success);
1988    
1989 pcg 1.36 if (!i || prop == NULL)
1990     have_pixmap = 0;
1991     else
1992     {
1993     have_pixmap = 1;
1994 pcg 1.93 rootpixmap = *(Pixmap *)prop;
1995 pcg 1.43 XFree (prop);
1996 pcg 1.1 }
1997 pcg 1.90
1998 pcg 1.36 if (have_pixmap)
1999     {
2000     /*
2001 pcg 1.38 * Copy display->root pixmap transparency
2002 pcg 1.36 */
2003 pcg 1.67 int sx, sy, nx, ny;
2004     unsigned int nw, nh;
2005     Window cr;
2006     XImage *image;
2007     GC gc;
2008     XGCValues gcvalue;
2009 pcg 1.36
2010 pcg 1.43 XTranslateCoordinates (display->display, TermWin.parent[0], display->root,
2011 pcg 1.90 0, 0, &sx, &sy, &cr);
2012 pcg 1.36 nw = (unsigned int)szHint.width;
2013     nh = (unsigned int)szHint.height;
2014     nx = ny = 0;
2015 pcg 1.67
2016 pcg 1.36 if (sx < 0)
2017     {
2018     nw += sx;
2019     nx = -sx;
2020     sx = 0;
2021     }
2022 pcg 1.67
2023 pcg 1.36 if (sy < 0)
2024     {
2025     nh += sy;
2026     ny = -sy;
2027     sy = 0;
2028     }
2029 pcg 1.67
2030 pcg 1.43 MIN_IT (nw, (unsigned int) (wrootattr.width - sx));
2031     MIN_IT (nh, (unsigned int) (wrootattr.height - sy));
2032 pcg 1.36 allowedxerror = -1;
2033 pcg 1.90 image = XGetImage (display->display, rootpixmap, sx, sy, nw, nh, AllPlanes, ZPixmap);
2034    
2035 pcg 1.36 /* XXX: handle BadMatch - usually because we're outside the pixmap */
2036     /* XXX: may need a delay here? */
2037     allowedxerror = 0;
2038 pcg 1.90
2039 pcg 1.36 if (image == NULL)
2040     {
2041     if (am_transparent && am_pixmap_trans)
2042     {
2043     pchanged = 1;
2044     if (TermWin.pixmap != None)
2045     {
2046 pcg 1.43 XFreePixmap (display->display, TermWin.pixmap);
2047 pcg 1.36 TermWin.pixmap = None;
2048     }
2049     }
2050 pcg 1.90
2051 pcg 1.36 am_pixmap_trans = 0;
2052     }
2053     else
2054     {
2055     if (TermWin.pixmap != None)
2056 pcg 1.43 XFreePixmap (display->display, TermWin.pixmap);
2057 pcg 1.90
2058     #if TINTING
2059     if (ISSET_PIXCOLOR (Color_tint))
2060     {
2061     unsigned short shade, rm, gm, bm;
2062    
2063     PixColors[Color_tint].get (display, rm, gm, bm);
2064    
2065     rm >>= 8; gm >>= 8; bm >>= 8; // not 100% correct, but...
2066    
2067     /* Determine bitshift and bitmask values */
2068     switch (image->bits_per_pixel)
2069     {
2070     case 15: shade_ximage_15 (image->data, image->bytes_per_line, image->width, image->height, rm, gm, bm); break;
2071     case 16: shade_ximage_16 (image->data, image->bytes_per_line, image->width, image->height, rm, gm, bm); break;
2072     case 24: shade_ximage_24 (image->data, image->bytes_per_line, image->width, image->height, rm, gm, bm); break;
2073     case 32: shade_ximage_32 (image->data, image->bytes_per_line, image->width, image->height, rm, gm, bm); break;
2074     }
2075     }
2076     #endif
2077    
2078 pcg 1.43 TermWin.pixmap = XCreatePixmap (display->display, TermWin.vt,
2079 pcg 1.90 szHint.width, szHint.height, image->depth);
2080 pcg 1.43 gc = XCreateGC (display->display, TermWin.vt, 0UL, &gcvalue);
2081     XPutImage (display->display, TermWin.pixmap, gc, image, 0, 0,
2082 pcg 1.90 nx, ny, image->width, image->height);
2083 pcg 1.43 XFreeGC (display->display, gc);
2084     XDestroyImage (image);
2085     XSetWindowBackgroundPixmap (display->display, TermWin.vt,
2086 pcg 1.36 TermWin.pixmap);
2087 pcg 1.90
2088 pcg 1.36 if (!am_transparent || !am_pixmap_trans)
2089     pchanged = 1;
2090 pcg 1.90
2091 pcg 1.36 am_transparent = am_pixmap_trans = 1;
2092     }
2093 pcg 1.1 }
2094 pcg 1.67
2095 pcg 1.36 if (!am_pixmap_trans)
2096     {
2097 pcg 1.90 unsigned int n;
2098 pcg 1.36 /*
2099     * InheritPixmap transparency
2100     */
2101 pcg 1.43 D_X ((stderr, "InheritPixmap Seeking to %08lx", display->root));
2102 pcg 1.90 for (i = 1; i < (int) (sizeof (TermWin.parent) / sizeof (Window)); i++)
2103 pcg 1.36 {
2104     oldp = TermWin.parent[i];
2105 pcg 1.43 XQueryTree (display->display, TermWin.parent[i - 1], &root,
2106 pcg 1.90 &TermWin.parent[i], &list, &n);
2107 pcg 1.43 XFree (list);
2108     D_X ((stderr, "InheritPixmap Parent[%d] = %08lx", i, TermWin.parent[i]));
2109 pcg 1.90
2110 pcg 1.38 if (TermWin.parent[i] == display->root)
2111 pcg 1.36 {
2112     if (oldp != None)
2113     pchanged = 1;
2114 pcg 1.90
2115 pcg 1.36 break;
2116     }
2117 pcg 1.90
2118 pcg 1.36 if (oldp != TermWin.parent[i])
2119     pchanged = 1;
2120     }
2121 pcg 1.67
2122 pcg 1.36 n = 0;
2123 pcg 1.67
2124 pcg 1.36 if (pchanged)
2125     {
2126     for (; n < (unsigned int)i; n++)
2127     {
2128 pcg 1.43 XGetWindowAttributes (display->display, TermWin.parent[n], &wattr);
2129     D_X ((stderr, "InheritPixmap Checking Parent[%d]: %s", n, (wattr.depth == rootdepth && wattr.class != InputOnly) ? "OK" : "FAIL"));
2130 pcg 1.36 if (wattr.depth != rootdepth || wattr.c_class == InputOnly)
2131     {
2132 pcg 1.43 n = (int) (sizeof (TermWin.parent) / sizeof (Window)) + 1;
2133 pcg 1.36 break;
2134     }
2135     }
2136     }
2137 pcg 1.67
2138 pcg 1.90 if (n > (int) (sizeof (TermWin.parent) / sizeof (TermWin.parent[0])))
2139 pcg 1.36 {
2140 pcg 1.43 D_X ((stderr, "InheritPixmap Turning off"));
2141 pcg 1.90 XSetWindowBackground (display->display, TermWin.parent[0], PixColors[Color_fg]);
2142     XSetWindowBackground (display->display, TermWin.vt, PixColors[Color_bg]);
2143 pcg 1.36 am_transparent = 0;
2144     /* XXX: also turn off Opt_transparent? */
2145     }
2146     else
2147     {
2148 pcg 1.90 #if WAIT_FOR_WM
2149 pcg 1.36 /* wait (an arbitrary period) for the WM to do its thing
2150     * needed for fvwm2.2.2 (and before?) */
2151 pcg 1.43 sleep (1);
2152 pcg 1.90 #endif
2153 pcg 1.43 D_X ((stderr, "InheritPixmap Turning on (%d parents)", i - 1));
2154 pcg 1.36 for (n = 0; n < (unsigned int)i; n++)
2155 pcg 1.90 XSetWindowBackgroundPixmap (display->display, TermWin.parent[n], ParentRelative);
2156    
2157     XSetWindowBackgroundPixmap (display->display, TermWin.vt, ParentRelative);
2158 pcg 1.36 am_transparent = 1;
2159     }
2160 pcg 1.67
2161 pcg 1.43 for (; i < (int) (sizeof (TermWin.parent) / sizeof (Window)); i++)
2162 pcg 1.36 TermWin.parent[i] = None;
2163 pcg 1.1 }
2164 pcg 1.90
2165 pcg 1.36 return pchanged;
2166 pcg 1.1 }
2167     #endif
2168    
2169     /*}}} */
2170    
2171 pcg 1.81 bool
2172     rxvt_term::cmd_parse ()
2173     {
2174     bool flag = false;
2175     unicode_t ch = NOCHAR;
2176     unsigned char *seq_begin; // remember start of esc-sequence here
2177    
2178     for (;;)
2179     {
2180     if (ch == NOCHAR)
2181     {
2182     seq_begin = cmdbuf_ptr;
2183     ch = next_char ();
2184     }
2185    
2186     if (ch == NOCHAR) // TODO: improve
2187     break;
2188    
2189 pcg 1.93 if (!IS_CONTROL (ch) || ch == C0_LF || ch == C0_CR || ch == C0_HT)
2190 pcg 1.81 {
2191     /* Read a text string from the input buffer */
2192     unicode_t buf[UBUFSIZ];
2193     bool refreshnow = false;
2194     int nlines = 0;
2195     unicode_t *str = buf;
2196    
2197     *str++ = ch;
2198    
2199     for (;;)
2200     {
2201     seq_begin = cmdbuf_ptr;
2202     ch = next_char ();
2203    
2204 pcg 1.93 if (ch == NOCHAR || (IS_CONTROL (ch) && ch != C0_LF && ch != C0_CR && ch != C0_HT))
2205 pcg 1.81 break;
2206    
2207     *str++ = ch;
2208    
2209 pcg 1.93 if (ch == C0_LF)
2210 pcg 1.81 {
2211     nlines++;
2212     refresh_count++;
2213    
2214     if (! (Options & Opt_jumpScroll)
2215     || (refresh_count >= (refresh_limit * (TermWin.nrow - 1))))
2216     {
2217     refreshnow = true;
2218     flag = true;
2219     ch = NOCHAR;
2220     break;
2221     }
2222    
2223     // scr_add_lines only works for nlines < TermWin.nrow - 1.
2224     if (nlines >= TermWin.nrow - 1)
2225     {
2226     scr_add_lines (buf, nlines, str - buf);
2227     nlines = 0;
2228     str = buf;
2229     }
2230     }
2231    
2232     if (str >= buf + UBUFSIZ)
2233     {
2234     ch = NOCHAR;
2235     break;
2236     }
2237     }
2238    
2239     scr_add_lines (buf, nlines, str - buf);
2240    
2241     /*
2242     * If there have been a lot of new lines, then update the screen
2243     * What the heck I'll cheat and only refresh less than every page-full.
2244     * the number of pages between refreshes is refresh_limit, which
2245     * is incremented here because we must be doing flat-out scrolling.
2246     *
2247     * refreshing should be correct for small scrolls, because of the
2248     * time-out
2249     */
2250     if (refreshnow)
2251     {
2252     if ((Options & Opt_jumpScroll) && refresh_limit < REFRESH_PERIOD)
2253     refresh_limit++;
2254 pcg 1.93 else
2255     scr_refresh (refresh_type);
2256 pcg 1.81 }
2257    
2258     }
2259     else
2260     {
2261     try
2262     {
2263     process_nonprinting (ch);
2264     }
2265     catch (const class out_of_input &o)
2266     {
2267     // we ran out of input, retry later
2268     cmdbuf_ptr = seq_begin;
2269     break;
2270     }
2271    
2272     ch = NOCHAR;
2273     }
2274     }
2275    
2276     return flag;
2277     }
2278    
2279     // read the next character
2280     unicode_t
2281     rxvt_term::next_char ()
2282     {
2283     while (cmdbuf_ptr < cmdbuf_endp)
2284     {
2285     // assume 7-bit to be ascii ALWAYS
2286     if (*cmdbuf_ptr <= 0x7f && *cmdbuf_ptr != 0x1b)
2287     return *cmdbuf_ptr++;
2288    
2289     wchar_t wc;
2290     size_t len = mbrtowc (&wc, (char *)cmdbuf_ptr, cmdbuf_endp - cmdbuf_ptr, mbstate);
2291    
2292     if (len == (size_t)-2)
2293     {
2294     // the mbstate stores incomplete sequences. didn't know this :/
2295     cmdbuf_ptr = cmdbuf_endp;
2296     break;
2297     }
2298    
2299     if (len == (size_t)-1)
2300     return *cmdbuf_ptr++; // the _occasional_ latin1 character is allowed to slip through
2301    
2302     // assume wchar == unicode
2303     cmdbuf_ptr += len;
2304     return wc;
2305     }
2306    
2307     return NOCHAR;
2308     }
2309    
2310     /* rxvt_cmd_getc () - Return next input character */
2311     /*
2312     * Return the next input character after first passing any keyboard input
2313     * to the command.
2314     */
2315     unicode_t
2316     rxvt_term::cmd_getc ()
2317     {
2318     unicode_t c = next_char ();
2319    
2320     if (c == NOCHAR)
2321     throw out_of_input;
2322    
2323     return c;
2324     }
2325    
2326 pcg 1.1 /*{{{ print pipe */
2327     /*----------------------------------------------------------------------*/
2328     #ifdef PRINTPIPE
2329 pcg 1.34 FILE *
2330     rxvt_term::popen_printer ()
2331 pcg 1.1 {
2332 pcg 1.67 FILE *stream = popen (rs[Rs_print_pipe], "w");
2333 pcg 1.1
2334 pcg 1.36 if (stream == NULL)
2335 pcg 1.81 rxvt_warn ("can't open printer pipe, not printing.\n");
2336    
2337 pcg 1.36 return stream;
2338 pcg 1.1 }
2339    
2340     int
2341 pcg 1.34 rxvt_term::pclose_printer (FILE *stream)
2342 pcg 1.1 {
2343 pcg 1.11 fflush (stream);
2344     return pclose (stream);
2345 pcg 1.1 }
2346    
2347     /*
2348     * simulate attached vt100 printer
2349     */
2350     void
2351 pcg 1.34 rxvt_term::process_print_pipe ()
2352 pcg 1.1 {
2353 pcg 1.81 int done;
2354     FILE *fd;
2355 pcg 1.36
2356     if ((fd = popen_printer ()) == NULL)
2357     return;
2358    
2359     /*
2360     * Send all input to the printer until either ESC[4i or ESC[?4i
2361     * is received.
2362     */
2363     for (done = 0; !done;)
2364     {
2365 pcg 1.81 unsigned char buf[8];
2366     unicode_t ch;
2367     unsigned int i, len;
2368 pcg 1.1
2369 pcg 1.36 if ((ch = cmd_getc ()) != C0_ESC)
2370     {
2371 pcg 1.43 if (putc (ch, fd) == EOF)
2372 pcg 1.36 break; /* done = 1 */
2373     }
2374     else
2375     {
2376     len = 0;
2377     buf[len++] = ch;
2378 pcg 1.1
2379 pcg 1.36 if ((buf[len++] = cmd_getc ()) == '[')
2380     {
2381     if ((ch = cmd_getc ()) == '?')
2382     {
2383     buf[len++] = '?';
2384     ch = cmd_getc ();
2385     }
2386     if ((buf[len++] = ch) == '4')
2387     {
2388     if ((buf[len++] = cmd_getc ()) == 'i')
2389     break; /* done = 1 */
2390     }
2391     }
2392 pcg 1.81
2393 pcg 1.36 for (i = 0; i < len; i++)
2394 pcg 1.43 if (putc (buf[i], fd) == EOF)
2395 pcg 1.36 {
2396     done = 1;
2397     break;
2398     }
2399     }
2400 pcg 1.1 }
2401 pcg 1.81
2402 pcg 1.36 pclose_printer (fd);
2403 pcg 1.1 }
2404     #endif /* PRINTPIPE */
2405     /*}}} */
2406    
2407     /* *INDENT-OFF* */
2408     enum {
2409 pcg 1.36 C1_40 = 0x40,
2410 pcg 1.90 C1_41 , C1_BPH, C1_NBH, C1_44 , C1_NEL, C1_SSA, C1_ESA,
2411 pcg 1.36 C1_HTS, C1_HTJ, C1_VTS, C1_PLD, C1_PLU, C1_RI , C1_SS2, C1_SS3,
2412     C1_DCS, C1_PU1, C1_PU2, C1_STS, C1_CCH, C1_MW , C1_SPA, C1_EPA,
2413 pcg 1.90 C1_SOS, C1_59 , C1_SCI, C1_CSI, CS_ST , C1_OSC, C1_PM , C1_APC,
2414 pcg 1.1 };
2415     /* *INDENT-ON* */
2416    
2417     /*{{{ process non-printing single characters */
2418     void
2419 pcg 1.81 rxvt_term::process_nonprinting (unicode_t ch)
2420 pcg 1.1 {
2421 pcg 1.36 switch (ch)
2422     {
2423 pcg 1.81 case C0_ESC:
2424     process_escape_seq ();
2425     break;
2426 pcg 1.36 case C0_ENQ: /* terminal Status */
2427     if (rs[Rs_answerbackstring])
2428 pcg 1.90 tt_write ((const unsigned char *)rs[Rs_answerbackstring],
2429     (unsigned int)STRLEN (rs[Rs_answerbackstring]));
2430 pcg 1.36 else
2431 pcg 1.43 tt_write ((unsigned char *)VT100_ANS,
2432 pcg 1.90 (unsigned int)STRLEN (VT100_ANS));
2433 pcg 1.36 break;
2434     case C0_BEL: /* bell */
2435     scr_bell ();
2436     break;
2437     case C0_BS: /* backspace */
2438     scr_backspace ();
2439     break;
2440     case C0_HT: /* tab */
2441     scr_tab (1);
2442     break;
2443     case C0_CR: /* carriage return */
2444     scr_gotorc (0, 0, R_RELATIVE);
2445     break;
2446     case C0_VT: /* vertical tab, form feed */
2447     case C0_FF:
2448     case C0_LF: /* line feed */
2449     scr_index (UP);
2450     break;
2451     case C0_SO: /* shift out - acs */
2452     scr_charset_choose (1);
2453     break;
2454     case C0_SI: /* shift in - acs */
2455     scr_charset_choose (0);
2456     break;
2457 pcg 1.81
2458     // 8-bit controls
2459     case 0x90: /* DCS */
2460     process_dcs_seq ();
2461     break;
2462     case 0x9b: /* CSI */
2463     process_csi_seq ();
2464     break;
2465     case 0x9d: /* CSI */
2466     process_osc_seq ();
2467     break;
2468 pcg 1.1 }
2469     }
2470     /*}}} */
2471    
2472    
2473     /*{{{ process VT52 escape sequences */
2474     void
2475 pcg 1.81 rxvt_term::process_escape_vt52 (unicode_t ch)
2476 pcg 1.1 {
2477 pcg 1.36 int row, col;
2478    
2479     switch (ch)
2480     {
2481     case 'A': /* cursor up */
2482     scr_gotorc (-1, 0, R_RELATIVE | C_RELATIVE);
2483     break;
2484     case 'B': /* cursor down */
2485     scr_gotorc (1, 0, R_RELATIVE | C_RELATIVE);
2486     break;
2487     case 'C': /* cursor right */
2488     scr_gotorc (0, 1, R_RELATIVE | C_RELATIVE);
2489     break;
2490     case 'D': /* cursor left */
2491     scr_gotorc (0, -1, R_RELATIVE | C_RELATIVE);
2492     break;
2493     case 'H': /* cursor home */
2494     scr_gotorc (0, 0, 0);
2495     break;
2496     case 'I': /* cursor up and scroll down if needed */
2497     scr_index (DN);
2498     break;
2499     case 'J': /* erase to end of screen */
2500     scr_erase_screen (0);
2501     break;
2502     case 'K': /* erase to end of line */
2503     scr_erase_line (0);
2504     break;
2505     case 'Y': /* move to specified row and col */
2506     /* full command is 'ESC Y row col' where row and col
2507     * are encoded by adding 32 and sending the ascii
2508     * character. eg. SPACE = 0, '+' = 13, '0' = 18,
2509     * etc. */
2510     row = cmd_getc () - ' ';
2511     col = cmd_getc () - ' ';
2512     scr_gotorc (row, col, 0);
2513     break;
2514     case 'Z': /* identify the terminal type */
2515 pcg 1.43 tt_printf ("\033/Z"); /* I am a VT100 emulating a VT52 */
2516 pcg 1.1 break;
2517 pcg 1.36 case '<': /* turn off VT52 mode */
2518 pcg 1.43 PrivMode (0, PrivMode_vt52);
2519 pcg 1.36 break;
2520     case 'F': /* use special graphics character set */
2521     case 'G': /* use regular character set */
2522     /* unimplemented */
2523     break;
2524     case '=': /* use alternate keypad mode */
2525     case '>': /* use regular keypad mode */
2526     /* unimplemented */
2527     break;
2528 pcg 1.1 }
2529     }
2530     /*}}} */
2531    
2532    
2533     /*{{{ process escape sequences */
2534     void
2535 pcg 1.34 rxvt_term::process_escape_seq ()
2536 pcg 1.1 {
2537 pcg 1.81 unicode_t ch = cmd_getc ();
2538 pcg 1.36
2539     if (PrivateModes & PrivMode_vt52)
2540     {
2541     process_escape_vt52 (ch);
2542     return;
2543     }
2544 pcg 1.1
2545 pcg 1.36 switch (ch)
2546     {
2547     /* case 1: do_tek_mode (); break; */
2548     case '#':
2549     if (cmd_getc () == '8')
2550     scr_E ();
2551     break;
2552 pcg 1.44 case '(':
2553 pcg 1.36 scr_charset_set (0, (unsigned int)cmd_getc ());
2554     break;
2555     case ')':
2556     scr_charset_set (1, (unsigned int)cmd_getc ());
2557     break;
2558     case '*':
2559     scr_charset_set (2, (unsigned int)cmd_getc ());
2560     break;
2561     case '+':
2562     scr_charset_set (3, (unsigned int)cmd_getc ());
2563     break;
2564 pcg 1.1 #ifndef NO_FRILLS
2565 pcg 1.36 case '6':
2566     scr_backindex ();
2567     break;
2568     #endif
2569     case '7':
2570     scr_cursor (SAVE);
2571     break;
2572     case '8':
2573     scr_cursor (RESTORE);
2574     break;
2575 pcg 1.1 #ifndef NO_FRILLS
2576 pcg 1.36 case '9':
2577     scr_forwardindex ();
2578     break;
2579     #endif
2580     case '=':
2581     case '>':
2582 pcg 1.43 PrivMode ((ch == '='), PrivMode_aplKP);
2583 pcg 1.36 break;
2584    
2585     case C1_40:
2586     cmd_getc ();
2587     break;
2588     case C1_44:
2589     scr_index (UP);
2590     break;
2591 pcg 1.1
2592 pcg 1.36 /* 8.3.87: NEXT LINE */
2593     case C1_NEL: /* ESC E */
2594 pcg 1.1 {
2595 pcg 1.93 unicode_t nlcr[] = { C0_LF, C0_CR };
2596 pcg 1.34 scr_add_lines (nlcr, 1, 2);
2597 pcg 1.1 }
2598 pcg 1.36 break;
2599    
2600     /* kidnapped escape sequence: Should be 8.3.48 */
2601     case C1_ESA: /* ESC G */
2602     process_graphics ();
2603     break;
2604    
2605     /* 8.3.63: CHARACTER TABULATION SET */
2606     case C1_HTS: /* ESC H */
2607     scr_set_tab (1);
2608     break;
2609    
2610     /* 8.3.105: REVERSE LINE FEED */
2611     case C1_RI: /* ESC M */
2612     scr_index (DN);
2613     break;
2614    
2615     /* 8.3.142: SINGLE-SHIFT TWO */
2616 pcg 1.90 /*case C1_SS2: scr_single_shift (2); break; */
2617 pcg 1.36
2618     /* 8.3.143: SINGLE-SHIFT THREE */
2619 pcg 1.90 /*case C1_SS3: scr_single_shift (3); break; */
2620 pcg 1.36
2621     /* 8.3.27: DEVICE CONTROL STRING */
2622     case C1_DCS: /* ESC P */
2623     process_dcs_seq ();
2624     break;
2625    
2626     /* 8.3.110: SINGLE CHARACTER INTRODUCER */
2627     case C1_SCI: /* ESC Z */
2628 pcg 1.43 tt_write ((const unsigned char *)ESCZ_ANSWER,
2629     (unsigned int) (sizeof (ESCZ_ANSWER) - 1));
2630 pcg 1.36 break; /* steal obsolete ESC [ c */
2631    
2632     /* 8.3.16: CONTROL SEQUENCE INTRODUCER */
2633     case C1_CSI: /* ESC [ */
2634     process_csi_seq ();
2635     break;
2636 pcg 1.1
2637 pcg 1.36 /* 8.3.90: OPERATING SYSTEM COMMAND */
2638     case C1_OSC: /* ESC ] */
2639     process_osc_seq ();
2640     break;
2641    
2642     /* 8.3.106: RESET TO INITIAL STATE */
2643     case 'c':
2644 pcg 1.90 mbstate.reset ();
2645 pcg 1.36 scr_poweron ();
2646     scrollbar_show (1);
2647     break;
2648    
2649     /* 8.3.79: LOCKING-SHIFT TWO (see ISO2022) */
2650     case 'n':
2651     scr_charset_choose (2);
2652     break;
2653    
2654     /* 8.3.81: LOCKING-SHIFT THREE (see ISO2022) */
2655     case 'o':
2656     scr_charset_choose (3);
2657     break;
2658 pcg 1.1 }
2659     }
2660     /*}}} */
2661    
2662     /*{{{ process CONTROL SEQUENCE INTRODUCER (CSI) sequences `ESC[' */
2663     /* *INDENT-OFF* */
2664     enum {
2665 pcg 1.36 CSI_ICH = 0x40,
2666     CSI_CUU, CSI_CUD, CSI_CUF, CSI_CUB, CSI_CNL, CSI_CPL, CSI_CHA,
2667     CSI_CUP, CSI_CHT, CSI_ED , CSI_EL , CSI_IL , CSI_DL , CSI_EF , CSI_EA ,
2668     CSI_DCH, CSI_SEE, CSI_CPR, CSI_SU , CSI_SD , CSI_NP , CSI_PP , CSI_CTC,
2669     CSI_ECH, CSI_CVT, CSI_CBT, CSI_SRS, CSI_PTX, CSI_SDS, CSI_SIMD, CSI_5F,
2670     CSI_HPA, CSI_HPR, CSI_REP, CSI_DA , CSI_VPA, CSI_VPR, CSI_HVP, CSI_TBC,
2671     CSI_SM , CSI_MC , CSI_HPB, CSI_VPB, CSI_RM , CSI_SGR, CSI_DSR, CSI_DAQ,
2672     CSI_70 , CSI_71 , CSI_72 , CSI_73 , CSI_74 , CSI_75 , CSI_76 , CSI_77 ,
2673     CSI_78 , CSI_79 , CSI_7A , CSI_7B , CSI_7C , CSI_7D , CSI_7E , CSI_7F
2674 pcg 1.1 };
2675    
2676     #define make_byte(b7,b6,b5,b4,b3,b2,b1,b0) \
2677     (((b7) << 7) | ((b6) << 6) | ((b5) << 5) | ((b4) << 4) \
2678     | ((b3) << 3) | ((b2) << 2) | ((b1) << 1) | (b0))
2679     #define get_byte_array_bit(array, bit) \
2680 pcg 1.43 (!! ((array)[ (bit) / 8] & (128 >> ((bit) & 7))))
2681 pcg 1.1
2682 pcg 1.36 const unsigned char csi_defaults[] =
2683     {
2684 pcg 1.43 make_byte (1,1,1,1,1,1,1,1), /* @, A, B, C, D, E, F, G, */
2685     make_byte (1,1,0,0,1,1,0,0), /* H, I, J, K, L, M, N, O, */
2686     make_byte (1,0,1,1,1,1,1,0), /* P, Q, R, S, T, U, V, W, */
2687     make_byte (1,1,1,0,0,0,1,0), /* X, Y, Z, [, \, ], ^, _, */
2688     make_byte (1,1,1,0,1,1,1,0), /* `, a, b, c, d, e, f, g, */
2689     make_byte (0,0,1,1,0,0,0,0), /* h, i, j, k, l, m, n, o, */
2690     make_byte (0,0,0,0,0,0,0,0), /* p, q, r, s, t, u, v, w, */
2691 pcg 1.90 make_byte (0,0,0,0,0,0,0,0), /* x, y, z, {, |, }, ~, */
2692 pcg 1.36 };
2693 pcg 1.1 /* *INDENT-ON* */
2694    
2695     void
2696 pcg 1.34 rxvt_term::process_csi_seq ()
2697 pcg 1.1 {
2698 pcg 1.81 unicode_t ch, priv, i;
2699     unsigned int nargs, p;
2700     int n, ndef;
2701     int arg[ESC_ARGS];
2702 pcg 1.36
2703     for (nargs = ESC_ARGS; nargs > 0;)
2704     arg[--nargs] = 0;
2705    
2706     priv = 0;
2707     ch = cmd_getc ();
2708     if (ch >= '<' && ch <= '?')
2709     { /* '<' '=' '>' '?' */
2710     priv = ch;
2711     ch = cmd_getc ();
2712     }
2713 pcg 1.81
2714 pcg 1.36 /* read any numerical arguments */
2715     for (n = -1; ch < CSI_ICH; )
2716     {
2717 pcg 1.43 if (isdigit (ch))
2718 pcg 1.36 {
2719     if (n < 0)
2720     n = ch - '0';
2721     else
2722     n = n * 10 + ch - '0';
2723     }
2724     else if (ch == ';')
2725     {
2726     if (nargs < ESC_ARGS)
2727     arg[nargs++] = n;
2728     n = -1;
2729     }
2730 pcg 1.81 else if (IS_CONTROL (ch))
2731     process_nonprinting (ch);
2732    
2733 pcg 1.36 ch = cmd_getc ();
2734     }
2735 pcg 1.1
2736 pcg 1.36 if (ch > CSI_7F)
2737     return;
2738 pcg 1.1
2739 pcg 1.36 if (nargs < ESC_ARGS)
2740     arg[nargs++] = n;
2741    
2742     i = ch - CSI_ICH;
2743 pcg 1.43 ndef = get_byte_array_bit (csi_defaults, i);
2744 pcg 1.36 for (p = 0; p < nargs; p++)
2745     if (arg[p] == -1)
2746     arg[p] = ndef;
2747 pcg 1.1
2748     #ifdef DEBUG_CMD
2749 pcg 1.43 fprintf (stderr, "CSI ");
2750 pcg 1.36 for (p = 0; p < nargs; p++)
2751 pcg 1.43 fprintf (stderr, "%d%s", arg[p], p < nargs - 1 ? ";" : "");
2752     fprintf (stderr, "%c\n", ch);
2753 pcg 1.1 #endif
2754    
2755 pcg 1.36 /*
2756     * private mode handling
2757     */
2758     if (priv)
2759     {
2760     switch (priv)
2761     {
2762     case '>':
2763     if (ch == CSI_DA) /* secondary device attributes */
2764 pcg 1.43 tt_printf ("\033[>%d;%-.8s;0c", 'R', VSTRING);
2765 pcg 1.36 break;
2766     case '?':
2767     if (ch == 'h' || ch == 'l' || ch == 'r' || ch == 's' || ch == 't')
2768     process_terminal_mode (ch, priv, nargs, arg);
2769     break;
2770     }
2771     return;
2772 pcg 1.1 }
2773    
2774 pcg 1.36 switch (ch)
2775     {
2776     /*
2777 pcg 1.43 * ISO/IEC 6429:1992 (E) CSI sequences (defaults in parentheses)
2778 pcg 1.36 */
2779 pcg 1.1 #ifdef PRINTPIPE
2780 pcg 1.36 case CSI_MC: /* 8.3.83: (0) MEDIA COPY */
2781     switch (arg[0])
2782     {
2783     case 0: /* initiate transfer to primary aux device */
2784     scr_printscreen (0);
2785     break;
2786     case 5: /* start relay to primary aux device */
2787     process_print_pipe ();
2788     break;
2789     }
2790     break;
2791     #endif
2792 pcg 1.1
2793 pcg 1.36 case CSI_CUU: /* 8.3.22: (1) CURSOR UP */
2794     case CSI_VPR: /* 8.3.161: (1) LINE POSITION FORWARD */
2795     arg[0] = -arg[0];
2796     /* FALLTHROUGH */
2797     case CSI_CUD: /* 8.3.19: (1) CURSOR DOWN */
2798     case CSI_VPB: /* 8.3.160: (1) LINE POSITION BACKWARD */
2799     scr_gotorc (arg[0], 0, RELATIVE);
2800     break;
2801    
2802     case CSI_CUB: /* 8.3.18: (1) CURSOR LEFT */
2803     case CSI_HPB: /* 8.3.59: (1) CHARACTER POSITION BACKWARD */
2804 pcg 1.1 #ifdef ISO6429
2805 pcg 1.36 arg[0] = -arg[0];
2806 pcg 1.1 #else /* emulate common DEC VTs */
2807 pcg 1.36 arg[0] = arg[0] ? -arg[0] : -1;
2808 pcg 1.1 #endif
2809 pcg 1.36 /* FALLTHROUGH */
2810     case CSI_CUF: /* 8.3.20: (1) CURSOR RIGHT */
2811     case CSI_HPR: /* 8.3.60: (1) CHARACTER POSITION FORWARD */
2812 pcg 1.1 #ifdef ISO6429
2813 pcg 1.36 scr_gotorc (0, arg[0], RELATIVE);
2814 pcg 1.1 #else /* emulate common DEC VTs */
2815 pcg 1.36 scr_gotorc (0, arg[0] ? arg[0] : 1, RELATIVE);
2816 pcg 1.1 #endif
2817 pcg 1.36 break;
2818    
2819     case CSI_CPL: /* 8.3.13: (1) CURSOR PRECEDING LINE */
2820     arg[0] = -arg[0];
2821     /* FALLTHROUGH */
2822     case CSI_CNL: /* 8.3.12: (1) CURSOR NEXT LINE */
2823     scr_gotorc (arg[0], 0, R_RELATIVE);
2824     break;
2825    
2826     case CSI_CHA: /* 8.3.9: (1) CURSOR CHARACTER ABSOLUTE */
2827     case CSI_HPA: /* 8.3.58: (1) CURSOR POSITION ABSOLUTE */
2828     scr_gotorc (0, arg[0] - 1, R_RELATIVE);
2829     break;
2830    
2831     case CSI_VPA: /* 8.3.159: (1) LINE POSITION ABSOLUTE */
2832     scr_gotorc (arg[0] - 1, 0, C_RELATIVE);
2833     break;
2834    
2835     case CSI_CUP: /* 8.3.21: (1,1) CURSOR POSITION */
2836     case CSI_HVP: /* 8.3.64: (1,1) CHARACTER AND LINE POSITION */
2837     scr_gotorc (arg[0] - 1, nargs < 2 ? 0 : (arg[1] - 1), 0);
2838     break;
2839 pcg 1.1
2840 pcg 1.36 case CSI_CBT: /* 8.3.7: (1) CURSOR BACKWARD TABULATION */
2841     arg[0] = -arg[0];
2842     /* FALLTHROUGH */
2843     case CSI_CHT: /* 8.3.10: (1) CURSOR FORWARD TABULATION */
2844     scr_tab (arg[0]);
2845     break;
2846    
2847     case CSI_ED: /* 8.3.40: (0) ERASE IN PAGE */
2848     scr_erase_screen (arg[0]);
2849     break;
2850    
2851     case CSI_EL: /* 8.3.42: (0) ERASE IN LINE */
2852     scr_erase_line (arg[0]);
2853     break;
2854    
2855     case CSI_ICH: /* 8.3.65: (1) INSERT CHARACTER */
2856     scr_insdel_chars (arg[0], INSERT);
2857     break;
2858    
2859     case CSI_IL: /* 8.3.68: (1) INSERT LINE */
2860     scr_insdel_lines (arg[0], INSERT);
2861     break;
2862    
2863     case CSI_DL: /* 8.3.33: (1) DELETE LINE */
2864     scr_insdel_lines (arg[0], DELETE);
2865     break;
2866    
2867     case CSI_ECH: /* 8.3.39: (1) ERASE CHARACTER */
2868     scr_insdel_chars (arg[0], ERASE);
2869     break;
2870    
2871     case CSI_DCH: /* 8.3.26: (1) DELETE CHARACTER */
2872     scr_insdel_chars (arg[0], DELETE);
2873     break;
2874    
2875     case CSI_SD: /* 8.3.114: (1) SCROLL DOWN */
2876     arg[0] = -arg[0];
2877     /* FALLTHROUGH */
2878     case CSI_SU: /* 8.3.148: (1) SCROLL UP */
2879     scr_scroll_text (screen.tscroll, screen.bscroll, arg[0], 0);
2880     break;
2881    
2882     case CSI_DA: /* 8.3.24: (0) DEVICE ATTRIBUTES */
2883 pcg 1.43 tt_write ((const unsigned char *)VT100_ANS,
2884     (unsigned int) (sizeof (VT100_ANS) - 1));
2885 pcg 1.36 break;
2886    
2887     case CSI_SGR: /* 8.3.118: (0) SELECT GRAPHIC RENDITION */
2888     process_sgr_mode (nargs, arg);
2889     break;
2890    
2891     case CSI_DSR: /* 8.3.36: (0) DEVICE STATUS REPORT */
2892     switch (arg[0])
2893     {
2894     case 5: /* DSR requested */
2895 pcg 1.43 tt_printf ("\033[0n");
2896 pcg 1.36 break;
2897     case 6: /* CPR requested */
2898     scr_report_position ();
2899     break;
2900     case 7: /* unofficial extension */
2901 pcg 1.90 if (Options & Opt_insecure)
2902     tt_printf ("%-.250s\n", rs[Rs_display_name]);
2903 pcg 1.36 break;
2904     case 8: /* unofficial extension */
2905 pcg 1.90 process_xterm_seq (XTerm_title, RESNAME "-" VERSION, CHAR_ST);
2906 pcg 1.36 break;
2907     }
2908     break;
2909 pcg 1.1
2910 pcg 1.36 case CSI_TBC: /* 8.3.155: (0) TABULATION CLEAR */
2911     switch (arg[0])
2912     {
2913     case 0: /* char tab stop cleared at active position */
2914     scr_set_tab (0);
2915     break;
2916     /* case 1: */ /* line tab stop cleared in active line */
2917     /* case 2: */ /* char tab stops cleared in active line */
2918     case 3: /* all char tab stops are cleared */
2919     /* case 4: */ /* all line tab stops are cleared */
2920     case 5: /* all tab stops are cleared */
2921     scr_set_tab (-1);
2922     break;
2923     }
2924     break;
2925    
2926     case CSI_CTC: /* 8.3.17: (0) CURSOR TABULATION CONTROL */
2927     switch (arg[0])
2928     {
2929     case 0: /* char tab stop set at active position */
2930     scr_set_tab (1);
2931     break; /* = ESC H */
2932     /* case 1: */ /* line tab stop set at active line */
2933     case 2: /* char tab stop cleared at active position */
2934     scr_set_tab (0);
2935     break; /* = ESC [ 0 g */
2936     /* case 3: */ /* line tab stop cleared at active line */
2937     /* case 4: */ /* char tab stops cleared at active line */
2938     case 5: /* all char tab stops are cleared */
2939     scr_set_tab (-1);
2940     break; /* = ESC [ 3 g */
2941     /* case 6: */ /* all line tab stops are cleared */
2942     }
2943     break;
2944    
2945     case CSI_RM: /* 8.3.107: RESET MODE */
2946     if (arg[0] == 4)
2947     scr_insert_mode (0);
2948     break;
2949    
2950     case CSI_SM: /* 8.3.126: SET MODE */
2951     if (arg[0] == 4)
2952     scr_insert_mode (1);
2953     break;
2954    
2955     /*
2956     * PRIVATE USE beyond this point. All CSI_7? sequences here
2957     */
2958     case CSI_72: /* DECSTBM: set top and bottom margins */
2959     if (nargs == 1)
2960     scr_scroll_region (arg[0] - 1, MAX_ROWS - 1);
2961     else if (nargs == 0 || arg[0] >= arg[1])
2962     scr_scroll_region (0, MAX_ROWS - 1);
2963     else
2964     scr_scroll_region (arg[0] - 1, arg[1] - 1);
2965     break;
2966    
2967     case CSI_73:
2968     scr_cursor (SAVE);
2969     break;
2970     case CSI_75:
2971     scr_cursor (RESTORE);
2972     break;
2973 pcg 1.1
2974     #ifndef NO_FRILLS
2975 pcg 1.36 case CSI_74:
2976     process_window_ops (arg, nargs);
2977     break;
2978 pcg 1.1 #endif
2979    
2980 pcg 1.36 case CSI_78: /* DECREQTPARM */
2981     if (arg[0] == 0 || arg[0] == 1)
2982 pcg 1.43 tt_printf ("\033[%d;1;1;128;128;1;0x", arg[0] + 2);
2983 pcg 1.81 break;
2984 pcg 1.1
2985 pcg 1.36 default:
2986     break;
2987 pcg 1.1 }
2988     }
2989     /*}}} */
2990    
2991     #ifndef NO_FRILLS
2992     /* ARGSUSED */
2993     void
2994 pcg 1.34 rxvt_term::process_window_ops (const int *args, unsigned int nargs)
2995 pcg 1.1 {
2996 pcg 1.81 int x, y;
2997 pcg 1.36 XWindowAttributes wattr;
2998 pcg 1.81 Window wdummy;
2999 pcg 1.1
3000 pcg 1.36 if (nargs == 0)
3001     return;
3002 pcg 1.81
3003 pcg 1.36 switch (args[0])
3004     {
3005 pcg 1.81 /*
3006     * commands
3007     */
3008 pcg 1.36 case 1: /* deiconify window */
3009 pcg 1.43 XMapWindow (display->display, TermWin.parent[0]);
3010 pcg 1.36 break;
3011     case 2: /* iconify window */
3012 pcg 1.43 XIconifyWindow (display->display, TermWin.parent[0],
3013     DefaultScreen (display->display));
3014 pcg 1.36 break;
3015     case 3: /* set position (pixels) */
3016 pcg 1.43 XMoveWindow (display->display, TermWin.parent[0], args[1], args[2]);
3017 pcg 1.36 break;
3018     case 4: /* set size (pixels) */
3019     set_widthheight ((unsigned int)args[2], (unsigned int)args[1]);
3020     break;
3021     case 5: /* raise window */
3022 pcg 1.43 XRaiseWindow (display->display, TermWin.parent[0]);
3023 pcg 1.36 break;
3024     case 6: /* lower window */
3025 pcg 1.43 XLowerWindow (display->display, TermWin.parent[0]);
3026 pcg 1.36 break;
3027     case 7: /* refresh window */
3028     scr_touch (true);
3029     break;
3030     case 8: /* set size (chars) */
3031 pcg 1.43 set_widthheight ((unsigned int) (args[2] * TermWin.fwidth),
3032     (unsigned int) (args[1] * TermWin.fheight));
3033 pcg 1.36 break;
3034 pcg 1.81
3035     //case 9: NYI, TODO, restore maximized window or maximize window
3036 pcg 1.36 default:
3037     if (args[0] >= 24) /* set height (chars) */
3038     set_widthheight ((unsigned int)TermWin.width,
3039 pcg 1.43 (unsigned int) (args[1] * TermWin.fheight));
3040 pcg 1.36 break;
3041 pcg 1.81
3042    
3043     /*
3044     * reports - some output format copied from XTerm
3045     */
3046 pcg 1.36 case 11: /* report window state */
3047 pcg 1.43 XGetWindowAttributes (display->display, TermWin.parent[0], &wattr);
3048     tt_printf ("\033[%dt", wattr.map_state == IsViewable ? 1 : 2);
3049 pcg 1.36 break;
3050     case 13: /* report window position */
3051 pcg 1.43 XGetWindowAttributes (display->display, TermWin.parent[0], &wattr);
3052     XTranslateCoordinates (display->display, TermWin.parent[0], wattr.root,
3053 pcg 1.90 -wattr.border_width, -wattr.border_width,
3054     &x, &y, &wdummy);
3055 pcg 1.43 tt_printf ("\033[3;%d;%dt", x, y);
3056 pcg 1.36 break;
3057     case 14: /* report window size (pixels) */
3058 pcg 1.43 XGetWindowAttributes (display->display, TermWin.parent[0], &wattr);
3059     tt_printf ("\033[4;%d;%dt", wattr.height, wattr.width);
3060 pcg 1.36 break;
3061 pcg 1.81 case 18: /* report text area size (chars) */
3062 pcg 1.43 tt_printf ("\033[8;%d;%dt", TermWin.nrow, TermWin.ncol);
3063 pcg 1.36 break;
3064 pcg 1.81 case 19: /* report window size (chars) */
3065     tt_printf ("\033[9;%d;%dt", TermWin.nrow, TermWin.ncol);
3066     break;
3067 pcg 1.36 case 20: /* report icon label */
3068 pcg 1.90 if (Options & Opt_insecure)
3069     {
3070     char *s;
3071     XGetIconName (display->display, TermWin.parent[0], &s);
3072     tt_printf ("\033]L%-.200s\234", s ? s : ""); /* 8bit ST */
3073     }
3074 pcg 1.36 break;
3075     case 21: /* report window title */
3076 pcg 1.90 if (Options & Opt_insecure)
3077     {
3078     char *s;
3079     XFetchName (display->display, TermWin.parent[0], &s);
3080     tt_printf ("\033]l%-.200s\234", s ? s : ""); /* 8bit ST */
3081     }
3082 pcg 1.36 break;
3083 pcg 1.1 }
3084     }
3085     #endif
3086    
3087     /*----------------------------------------------------------------------*/
3088     /*
3089     * get input up until STRING TERMINATOR (or BEL)
3090 pcg 1.93 * ends_how is terminator used. returned input must be free()'d
3091 pcg 1.1 */
3092 pcg 1.81 unsigned char *
3093     rxvt_term::get_to_st (unicode_t &ends_how)
3094 pcg 1.1 {
3095 pcg 1.81 int seen_esc = 0; /* seen escape? */
3096     unsigned int n = 0;
3097     unsigned char *s;
3098     unicode_t ch;
3099     unsigned char string[STRING_MAX];
3100 pcg 1.36
3101 pcg 1.81 while ((ch = cmd_getc ()))
3102 pcg 1.36 {
3103 pcg 1.90 if (ch == C0_BEL || ch == CHAR_ST)
3104 pcg 1.36 break;
3105 pcg 1.81
3106 pcg 1.90 if (seen_esc)
3107     if (ch == 0x5c) /* 7bit ST */
3108     break;
3109     else
3110     return NULL;
3111    
3112 pcg 1.36 if (ch == C0_ESC)
3113     {
3114     seen_esc = 1;
3115     continue;
3116     }
3117 pcg 1.93 else if (ch == C0_HT)
3118 pcg 1.36 ch = ' '; /* translate '\t' to space */
3119 pcg 1.93 else if (ch < 0x20 && (ch != C0_LF && ch != C0_CR))
3120 pcg 1.36 return NULL; /* other control character - exit */
3121 pcg 1.81
3122 pcg 1.90 if (n >= sizeof (string) - 1)
3123     // stop at some sane length
3124     return NULL;
3125 pcg 1.81
3126 pcg 1.90 string[n++] = ch;
3127 pcg 1.36 seen_esc = 0;
3128     }
3129 pcg 1.81
3130 pcg 1.36 string[n++] = '\0';
3131 pcg 1.81
3132 pcg 1.43 if ((s = (unsigned char *)rxvt_malloc (n)) == NULL)
3133 pcg 1.36 return NULL;
3134 pcg 1.81
3135     ends_how = (ch == 0x5c ? C0_ESC : ch);
3136 pcg 1.43 STRNCPY (s, string, n);
3137 pcg 1.36 return s;
3138 pcg 1.1 }
3139    
3140     /*----------------------------------------------------------------------*/
3141     /*
3142     * process DEVICE CONTROL STRING `ESC P ... (ST|BEL)' or `0x90 ... (ST|BEL)'
3143     */
3144     void
3145 pcg 1.34 rxvt_term::process_dcs_seq ()
3146 pcg 1.1 {
3147 pcg 1.81 unsigned char *s;
3148     unicode_t eh;
3149    
3150 pcg 1.36 /*
3151     * Not handled yet
3152     */
3153 pcg 1.81 s = get_to_st (eh);
3154 pcg 1.36 if (s)
3155 pcg 1.43 free (s);
3156 pcg 1.81
3157 pcg 1.36 return;
3158 pcg 1.1 }
3159    
3160     /*----------------------------------------------------------------------*/
3161     /*
3162     * process OPERATING SYSTEM COMMAND sequence `ESC ] Ps ; Pt (ST|BEL)'
3163     */
3164     void
3165 pcg 1.34 rxvt_term::process_osc_seq ()
3166 pcg 1.1 {
3167 pcg 1.81 unicode_t ch, eh;
3168     int arg;
3169 pcg 1.1
3170 pcg 1.36 ch = cmd_getc ();
3171 pcg 1.43 for (arg = 0; isdigit (ch); ch = cmd_getc ())
3172 pcg 1.36 arg = arg * 10 + (ch - '0');
3173 pcg 1.1
3174 pcg 1.36 if (ch == ';')
3175     {
3176 pcg 1.81 unsigned char *s = get_to_st (eh);
3177    
3178 pcg 1.36 if (s)
3179     {
3180 pcg 1.90 process_xterm_seq (arg, (char *)s, eh);
3181     free (s);
3182     }
3183     }
3184     }
3185 pcg 1.81
3186 pcg 1.90 void
3187     rxvt_term::process_color_seq (int report, int color, const char *str, unsigned char resp)
3188     {
3189     if (str[0] == '?' && !str[1])
3190     {
3191     if (Options & Opt_insecure)
3192     {
3193     unsigned short r, g, b;
3194     PixColors[color].get (display, r, g, b);
3195     tt_printf ("\033]%d;rgb:%04x/%04x/%04x%c", report, r, g, b, resp);
3196 pcg 1.36 }
3197 pcg 1.1 }
3198 pcg 1.90 else
3199     set_window_color (color, str);
3200 pcg 1.1 }
3201 pcg 1.90
3202 pcg 1.1 /*
3203     * XTerm escape sequences: ESC ] Ps;Pt (ST|BEL)
3204     * 0 = change iconName/title
3205     * 1 = change iconName
3206     * 2 = change title
3207     * 4 = change color
3208 pcg 1.90 * 10 = change fg color
3209     * 11 = change bg color
3210 pcg 1.1 * 12 = change text color
3211     * 13 = change mouse foreground color
3212     * 17 = change highlight character colour
3213     * 18 = change bold character color
3214     * 19 = change underlined character color
3215     * 46 = change logfile (not implemented)
3216     * 50 = change font
3217     *
3218     * rxvt extensions:
3219     * 20 = bg pixmap
3220     * 39 = change default fg color
3221     * 49 = change default bg color
3222     * 55 = dump scrollback buffer and all of screen
3223 pcg 1.67 * 701 = change locale
3224     * 702 = find font
3225 pcg 1.90 * 703 = menu
3226 pcg 1.1 */
3227     void
3228 pcg 1.90 rxvt_term::process_xterm_seq (int op, const char *str, unsigned char resp)
3229 pcg 1.1 {
3230 pcg 1.81 int changed = 0;
3231     int color;
3232     char *buf, *name;
3233 pcg 1.90 bool query = str[0] == '?' && !str[1];
3234 pcg 1.36
3235 pcg 1.43 assert (str != NULL);
3236 pcg 1.36 switch (op)
3237     {
3238     case XTerm_name:
3239     set_title (str);
3240     /* FALLTHROUGH */
3241     case XTerm_iconName:
3242 pcg 1.81 set_icon_name (str);
3243 pcg 1.36 break;
3244     case XTerm_title:
3245     set_title (str);
3246     break;
3247 pcg 1.90 case XTerm_property:
3248     if (str[0] == '?')
3249     {
3250     Atom prop = XInternAtom (display->display, str + 1, True);
3251     Atom actual_type;
3252     int actual_format;
3253     unsigned long nitems;
3254     unsigned long bytes_after;
3255     unsigned char *value = 0;
3256     const char *str = "";
3257    
3258     if (prop
3259     && XGetWindowProperty (display->display, TermWin.parent[0],
3260     prop, 0, 1<<16, 0, AnyPropertyType,
3261     &actual_type, &actual_format,
3262     &nitems, &bytes_after, &value) == Success
3263     && actual_type != None
3264     && actual_format == 8)
3265     str = (const char *)(value);
3266    
3267     tt_printf ("\033]%d;%s%c", XTerm_property, str, resp);
3268    
3269     XFree (value);
3270     }
3271     else
3272     {
3273     char *eq = strchr (str, '='); // constness lost, but verified to be ok
3274    
3275     if (eq)
3276     {
3277     *eq = 0;
3278     XChangeProperty (display->display, TermWin.parent[0],
3279     display->atom (str), XA_STRING, 8,
3280     PropModeReplace, (unsigned char *)eq + 1,
3281     strlen (eq + 1));
3282     }
3283     else
3284     XDeleteProperty (display->display, TermWin.parent[0],
3285     display->atom (str));
3286     }
3287     break;
3288    
3289 pcg 1.36 case XTerm_Color:
3290     for (buf = (char *)str; buf && *buf;)
3291     {
3292 pcg 1.43 if ((name = STRCHR (buf, ';')) == NULL)
3293 pcg 1.36 break;
3294 pcg 1.81
3295 pcg 1.36 *name++ = '\0';
3296 pcg 1.43 color = atoi (buf);
3297 pcg 1.81
3298 pcg 1.36 if (color < 0 || color >= TOTAL_COLORS)
3299     break;
3300 pcg 1.81
3301 pcg 1.43 if ((buf = STRCHR (name, ';')) != NULL)
3302 pcg 1.36 *buf++ = '\0';
3303 pcg 1.81
3304 pcg 1.90 if (name[0] == '?' && !name[1])
3305     {
3306     if (Options & Opt_insecure)
3307     {
3308     unsigned short r, g, b;
3309     PixColors[color + minCOLOR].get (display, r, g, b);
3310     tt_printf ("\033]%d;%d;rgb:%04x/%04x/%04x%c", XTerm_Color, color, r, g, b, resp);
3311     }
3312     }
3313     else
3314     set_window_color (color + minCOLOR, name);
3315 pcg 1.36 }
3316     break;
3317 pcg 1.90 case XTerm_Color00:
3318     process_color_seq (XTerm_Color00, Color_fg, str, resp);
3319     break;
3320     case XTerm_Color01:
3321     process_color_seq (XTerm_Color00, Color_bg, str, resp);
3322     break;
3323 pcg 1.1 #ifndef NO_CURSORCOLOR
3324 pcg 1.36 case XTerm_Color_cursor:
3325 pcg 1.90 process_color_seq (XTerm_Color_cursor, Color_cursor, str, resp);
3326 pcg 1.36 break;
3327     #endif
3328 pcg 1.90 case XTerm_Color_pointer_fg:
3329     process_color_seq (XTerm_Color_pointer_fg, Color_pointer_fg, str, resp);
3330     break;
3331     case XTerm_Color_pointer_bg:
3332     process_color_seq (XTerm_Color_pointer_bg, Color_pointer_bg, str, resp);
3333 pcg 1.36 break;
3334 pcg 1.1 #ifndef NO_BOLD_UNDERLINE_REVERSE
3335 pcg 1.36 case XTerm_Color_BD:
3336 pcg 1.90 process_color_seq (XTerm_Color_BD, Color_BD, str, resp);
3337 pcg 1.36 break;
3338     case XTerm_Color_UL:
3339 pcg 1.90 process_color_seq (XTerm_Color_UL, Color_UL, str, resp);
3340 pcg 1.36 break;
3341     case XTerm_Color_RV:
3342 pcg 1.90 process_color_seq (XTerm_Color_RV, Color_RV, str, resp);
3343 pcg 1.36 break;
3344 pcg 1.1 #endif
3345    
3346 pcg 1.36 case XTerm_Pixmap:
3347     if (*str != ';')
3348     {
3349 pcg 1.1 #if XPM_BACKGROUND
3350 pcg 1.36 scale_pixmap (""); /* reset to default scaling */
3351     set_bgPixmap (str); /* change pixmap */
3352 pcg 1.1 #endif
3353 pcg 1.36 scr_touch (true);
3354     }
3355 pcg 1.43 while ((str = STRCHR (str, ';')) != NULL)
3356 pcg 1.36 {
3357     str++;
3358 pcg 1.1 #if XPM_BACKGROUND
3359 pcg 1.36 changed += scale_pixmap (str);
3360 pcg 1.1 #endif
3361 pcg 1.36
3362     }
3363     if (changed)
3364     {
3365 pcg 1.1 #ifdef XPM_BACKGROUND
3366 pcg 1.36 resize_pixmap ();
3367 pcg 1.1 #endif
3368 pcg 1.36 scr_touch (true);
3369     }
3370     break;
3371    
3372     case XTerm_restoreFG:
3373     set_window_color (Color_fg, str);
3374     break;
3375     case XTerm_restoreBG:
3376     set_window_color (Color_bg, str);
3377     break;
3378 pcg 1.90
3379 pcg 1.36 case XTerm_logfile:
3380 pcg 1.81 // TODO, when secure mode?
3381 pcg 1.36 break;
3382 pcg 1.90
3383 pcg 1.36 case XTerm_font:
3384 pcg 1.90 if (query)
3385     {
3386     if (Options & Opt_insecure)
3387     tt_printf ("\33]%d;%-.250s%c", XTerm_font,
3388     TermWin.fontset->fontdesc
3389     ? TermWin.fontset->fontdesc
3390     : "",
3391     resp);
3392     }
3393     else
3394     change_font (str);
3395 pcg 1.51 break;
3396 pcg 1.90
3397 pcg 1.60 #ifndef NO_FRILLS
3398 pcg 1.51 case XTerm_locale:
3399 pcg 1.90 if (query)
3400     {
3401     if (Options & Opt_insecure)
3402     tt_printf ("\33]%d;%-.250s%c", XTerm_locale, locale, resp);
3403     }
3404 pcg 1.54 else
3405     {
3406     set_locale (str);
3407 pcg 1.60 # ifdef USE_XIM
3408 pcg 1.54 im_cb ();
3409 pcg 1.60 # endif
3410 pcg 1.54 }
3411 pcg 1.36 break;
3412 pcg 1.90
3413 pcg 1.67 case XTerm_findfont:
3414 pcg 1.90 if (Options & Opt_insecure)
3415     {
3416     int fid = TermWin.fontset->find_font (atoi (str));
3417     tt_printf ("\33]%d;%d;%-.250s%c", XTerm_findfont,
3418     fid, (*TermWin.fontset)[fid]->name, resp);
3419     }
3420 pcg 1.67 break;
3421 pcg 1.60 #endif
3422 pcg 1.90
3423     #ifdef MENUBAR
3424     case XTerm_Menu:
3425     if (Options & Opt_insecure)
3426     menubar_dispatch (const_cast<char *>(str)); // casting away constness is checked
3427     break;
3428     #endif
3429 pcg 1.1 #if 0
3430 pcg 1.36 case XTerm_dumpscreen: /* no error notices */
3431     {
3432 pcg 1.90 int fd;
3433 pcg 1.43 if ((fd = open (str, O_RDWR | O_CREAT | O_EXCL, 0600)) >= 0)
3434 pcg 1.36 {
3435     scr_dump (fd);
3436 pcg 1.43 close (fd);
3437 pcg 1.36 }
3438     }
3439     break;
3440 pcg 1.1 #endif
3441     }
3442     }
3443     /*----------------------------------------------------------------------*/
3444    
3445     /*{{{ process DEC private mode sequences `ESC [ ? Ps mode' */
3446     /*
3447     * mode can only have the following values:
3448     * 'l' = low
3449     * 'h' = high
3450     * 's' = save
3451     * 'r' = restore
3452     * 't' = toggle
3453     * so no need for fancy checking
3454     */
3455     int
3456 pcg 1.34 rxvt_term::privcases (int mode, unsigned long bit)
3457 pcg 1.1 {
3458 pcg 1.81 int state;
3459 pcg 1.1
3460 pcg 1.36 if (mode == 's')
3461     {
3462     SavedModes |= (PrivateModes & bit);
3463     return -1;
3464 pcg 1.1 }
3465 pcg 1.36 else
3466     {
3467     if (mode == 'r')
3468     state = (SavedModes & bit) ? 1 : 0; /* no overlapping */
3469     else
3470 pcg 1.43 state = (mode == 't') ? ! (PrivateModes & bit) : mode;
3471     PrivMode (state, bit);
3472 pcg 1.36 }
3473 pcg 1.81
3474 pcg 1.36 return state;
3475 pcg 1.1 }
3476    
3477     /* we're not using priv _yet_ */
3478     void
3479 pcg 1.43 rxvt_term::process_terminal_mode (int mode, int priv __attribute__ ((unused)), unsigned int nargs, const int *arg)
3480 pcg 1.1 {
3481 pcg 1.81 unsigned int i, j;
3482     int state;
3483    
3484 pcg 1.36 static const struct
3485     {
3486     const int argval;
3487     const unsigned long bit;
3488     }
3489 pcg 1.81
3490 pcg 1.36 argtopriv[] = {
3491     { 1, PrivMode_aplCUR },
3492     { 2, PrivMode_vt52 },
3493     { 3, PrivMode_132 },
3494     { 4, PrivMode_smoothScroll },
3495     { 5, PrivMode_rVideo },
3496     { 6, PrivMode_relOrigin },
3497     { 7, PrivMode_Autowrap },
3498     { 9, PrivMode_MouseX10 },
3499 pcg 1.1 #ifdef menuBar_esc
3500 pcg 1.36 { menuBar_esc, PrivMode_menuBar },
3501 pcg 1.1 #endif
3502     #ifdef scrollBar_esc
3503 pcg 1.36 { scrollBar_esc, PrivMode_scrollBar },
3504 pcg 1.1 #endif
3505 pcg 1.73 // 18, 19 printing-related
3506 pcg 1.36 { 25, PrivMode_VisibleCursor },
3507 pcg 1.73 // 30 show scrollbar rxvt. extension
3508     { 35, PrivMode_ShiftKeys }, // rxvt extension
3509 pcg 1.36 { 40, PrivMode_132OK },
3510 pcg 1.73 // 41 xterm more fixes NYI
3511     // 45 margin bell NYI
3512     // 46 start logging
3513 pcg 1.36 { 47, PrivMode_Screen },
3514     { 66, PrivMode_aplKP },
3515 pcg 1.1 #ifndef NO_BACKSPACE_KEY
3516 pcg 1.36 { 67, PrivMode_BackSpace },
3517 pcg 1.1 #endif
3518 pcg 1.36 { 1000, PrivMode_MouseX11 },
3519 pcg 1.73 // 1001 Use Hilite Mouse Tracking. NYI, TODO
3520     // 1002 Use Cell Motion Mouse Tracking. NYI, TODO
3521     // 1003 Use All Motion Mouse Tracking. NYI, TODO
3522     { 1010, PrivMode_TtyOutputInh }, // rxvt extension
3523     { 1011, PrivMode_Keypress }, // rxvt extension
3524     // 1035 enable modifiers for alt, numlock NYI
3525     // 1036 send ESC for meta keys NYI
3526     // 1037 send DEL for keypad delete NYI
3527 pcg 1.36 { 1047, PrivMode_Screen },
3528 pcg 1.73 // 1048 save and restore cursor
3529 pcg 1.90 { 1049, PrivMode_Screen }, /* xterm extension, clear screen on ti rather than te */
3530 pcg 1.73 // 1051, 1052, 1060, 1061 keyboard emulation NYI
3531 pcg 1.36 };
3532    
3533     if (nargs == 0)
3534     return;
3535    
3536     /* make lo/hi boolean */
3537     if (mode == 'l')
3538     mode = 0; /* reset */
3539     else if (mode == 'h')
3540     mode = 1; /* set */
3541    
3542     for (i = 0; i < nargs; i++)
3543     {
3544     state = -1;
3545    
3546     /* basic handling */
3547 pcg 1.43 for (j = 0; j < (sizeof (argtopriv)/sizeof (argtopriv[0])); j++)
3548 pcg 1.36 if (argtopriv[j].argval == arg[i])
3549     {
3550     state = privcases (mode, argtopriv[j].bit);
3551     break;
3552     }
3553 pcg 1.1
3554 pcg 1.36 /* extra handling for values with state unkept */
3555 pcg 1.73 switch (arg[i])
3556     {
3557     case 1048: /* alternative cursor save */
3558 pcg 1.90 if (Options & Opt_secondaryScreen)
3559     if (mode == 0)
3560     scr_cursor (RESTORE);
3561     else if (mode == 1)
3562     scr_cursor (SAVE);
3563     break;
3564 pcg 1.73 }
3565    
3566     if (state >= 0)
3567     /* extra handling for values with valid 0 or 1 state */
3568 pcg 1.36 switch (arg[i])
3569     {
3570 pcg 1.73 /* case 1: - application cursor keys */
3571     case 2: /* VT52 mode */
3572     /* oddball mode. should be set regardless of set/reset
3573     * parameter. Return from VT52 mode with an ESC < from
3574     * within VT52 mode
3575     */
3576     PrivMode (1, PrivMode_vt52);
3577     break;
3578     case 3: /* 80/132 */
3579     if (PrivateModes & PrivMode_132OK)
3580     set_widthheight (((state ? 132 : 80) * TermWin.fwidth), TermWin.height);
3581     break;
3582     case 4: /* smooth scrolling */
3583     if (state)
3584     Options &= ~Opt_jumpScroll;
3585     else
3586     Options |= Opt_jumpScroll;
3587     break;
3588     case 5: /* reverse video */
3589     scr_rvideo_mode (state);
3590     break;
3591     case 6: /* relative/absolute origins */
3592     scr_relative_origin (state);
3593     break;
3594     case 7: /* autowrap */
3595     scr_autowrap (state);
3596     break;
3597 pcg 1.90 /* case 8: - auto repeat, can't do on a per window basis */
3598 pcg 1.73 case 9: /* X10 mouse reporting */
3599     if (state) /* orthogonal */
3600 pcg 1.81 PrivateModes &= ~PrivMode_MouseX11;
3601 pcg 1.73 break;
3602 pcg 1.1 #ifdef menuBar_esc
3603 pcg 1.73 case menuBar_esc:
3604 pcg 1.1 #ifdef MENUBAR
3605 pcg 1.73 map_menuBar (state);
3606 pcg 1.1 #endif
3607 pcg 1.73 break;
3608 pcg 1.1 #endif
3609     #ifdef scrollBar_esc
3610 pcg 1.73 case scrollBar_esc:
3611     if (scrollbar_mapping (state))
3612     {
3613     resize_all_windows (0, 0, 0);
3614     scr_touch (true);
3615     }
3616     break;
3617 pcg 1.1 #endif
3618 pcg 1.73 case 25: /* visible/invisible cursor */
3619     scr_cursor_visible (state);
3620     break;
3621 pcg 1.90 /* case 35: - shift keys */
3622     /* case 40: - 80 <--> 132 mode */
3623 pcg 1.73 case 47: /* secondary screen */
3624     scr_change_screen (state);
3625     break;
3626 pcg 1.90 /* case 66: - application key pad */
3627     /* case 67: - backspace key */
3628 pcg 1.73 case 1000: /* X11 mouse reporting */
3629     if (state) /* orthogonal */
3630 pcg 1.81 PrivateModes &= ~PrivMode_MouseX10;
3631 pcg 1.73 break;
3632 pcg 1.1 #if 0
3633 pcg 1.73 case 1001:
3634     break; /* X11 mouse highlighting */
3635 pcg 1.1 #endif
3636 pcg 1.73 case 1010: /* scroll to bottom on TTY output inhibit */
3637     if (state)
3638     Options &= ~Opt_scrollTtyOutput;
3639     else
3640     Options |= Opt_scrollTtyOutput;
3641     break;
3642     case 1011: /* scroll to bottom on key press */
3643     if (state)
3644     Options |= Opt_scrollTtyKeypress;
3645     else
3646     Options &= ~Opt_scrollTtyKeypress;
3647     break;
3648 pcg 1.90 case 1047: /* secondary screen w/ clearing last */
3649     if (Options & Opt_secondaryScreen)
3650     if (current_screen != PRIMARY)
3651     scr_erase_screen (2);
3652     scr_change_screen (state);
3653     break;
3654     case 1049: /* secondary screen w/ clearing first */
3655 pcg 1.73 scr_change_screen (state);
3656 pcg 1.90 if (Options & Opt_secondaryScreen)
3657     if (current_screen != PRIMARY)
3658     scr_erase_screen (2);
3659     break;
3660 pcg 1.73 default:
3661     break;
3662     }
3663 pcg 1.1 }
3664     }
3665     /*}}} */
3666    
3667     /*{{{ process sgr sequences */
3668     void
3669 pcg 1.34 rxvt_term::process_sgr_mode (unsigned int nargs, const int *arg)
3670 pcg 1.1 {
3671 pcg 1.81 unsigned int i;
3672     short rendset;
3673     int rendstyle;
3674 pcg 1.36
3675     if (nargs == 0)
3676     {
3677     scr_rendition (0, ~RS_None);
3678     return;
3679     }
3680 pcg 1.81
3681 pcg 1.36 for (i = 0; i < nargs; i++)
3682     {
3683     rendset = -1;
3684     switch (arg[i])
3685     {
3686     case 0:
3687     rendset = 0, rendstyle = ~RS_None;
3688     break;
3689     case 1:
3690     rendset = 1, rendstyle = RS_Bold;
3691     break;
3692     case 4:
3693     rendset = 1, rendstyle = RS_Uline;
3694     break;
3695     case 5:
3696     rendset = 1, rendstyle = RS_Blink;
3697     break;
3698 pcg 1.93 //case 6: // scoansi light background
3699 pcg 1.36 case 7:
3700     rendset = 1, rendstyle = RS_RVid;
3701     break;
3702 pcg 1.73 case 8:
3703     // invisible. NYI
3704     break;
3705 pcg 1.93 //case 10: // scoansi acs off
3706     //case 11: // scoansi acs on
3707     //case 12: // scoansi acs on, |0x80
3708     case 21: // disable bold, blink and invis (some terminals use this)
3709     rendset = 0, rendstyle = RS_Bold | RS_Blink;
3710     break;
3711 pcg 1.36 case 22:
3712     rendset = 0, rendstyle = RS_Bold;
3713     break;
3714     case 24:
3715     rendset = 0, rendstyle = RS_Uline;
3716     break;
3717     case 25:
3718     rendset = 0, rendstyle = RS_Blink;
3719     break;
3720     case 27:
3721     rendset = 0, rendstyle = RS_RVid;
3722     break;
3723 pcg 1.73 case 28:
3724     // visible. NYI
3725     break;
3726 pcg 1.36 }
3727 pcg 1.73
3728 pcg 1.36 if (rendset != -1)
3729     {
3730     scr_rendition (rendset, rendstyle);
3731 pcg 1.43 continue; /* for (;i;) */
3732 pcg 1.36 }
3733    
3734     switch (arg[i])
3735     {
3736     case 30:
3737     case 31: /* set fg color */
3738     case 32:
3739     case 33:
3740     case 34:
3741     case 35:
3742     case 36:
3743     case 37:
3744 pcg 1.73 scr_color ((unsigned int) (minCOLOR + (arg[i] - 30)), Color_fg);
3745 pcg 1.36 break;
3746 pcg 1.1 #ifdef TTY_256COLOR
3747 pcg 1.36 case 38:
3748     if (nargs > i + 2 && arg[i + 1] == 5)
3749     {
3750 pcg 1.73 scr_color ((unsigned int) (minCOLOR + arg[i + 2]), Color_fg);
3751 pcg 1.36 i += 2;
3752     }
3753     break;
3754     #endif
3755     case 39: /* default fg */
3756     scr_color (Color_fg, Color_fg);
3757     break;
3758    
3759     case 40:
3760     case 41: /* set bg color */
3761     case 42:
3762     case 43:
3763     case 44:
3764     case 45:
3765     case 46:
3766     case 47:
3767 pcg 1.73 scr_color ((unsigned int) (minCOLOR + (arg[i] - 40)), Color_bg);
3768 pcg 1.36 break;
3769 pcg 1.1 #ifdef TTY_256COLOR
3770 pcg 1.36 case 48:
3771     if (nargs > i + 2 && arg[i + 1] == 5)
3772     {
3773 pcg 1.73 scr_color ((unsigned int) (minCOLOR + arg[i + 2]), Color_bg);
3774 pcg 1.36 i += 2;
3775     }
3776     break;
3777     #endif
3778     case 49: /* default bg */
3779     scr_color (Color_bg, Color_bg);
3780     break;
3781 pcg 1.1
3782     #ifndef NO_BRIGHTCOLOR
3783 pcg 1.36 case 90:
3784     case 91: /* set bright fg color */
3785     case 92:
3786     case 93:
3787     case 94:
3788     case 95:
3789     case 96:
3790     case 97:
3791 pcg 1.43 scr_color ((unsigned int) (minBrightCOLOR + (arg[i] - 90)),
3792 pcg 1.36 Color_fg);
3793     break;
3794     case 100:
3795     case 101: /* set bright bg color */
3796     case 102:
3797     case 103:
3798     case 104:
3799     case 105:
3800     case 106:
3801     case 107:
3802 pcg 1.43 scr_color ((unsigned int) (minBrightCOLOR + (arg[i] - 100)),
3803 pcg 1.36 Color_bg);
3804     break;
3805 pcg 1.1 #endif
3806 pcg 1.36
3807     }
3808 pcg 1.1 }
3809     }
3810     /*}}} */
3811    
3812 pcg 1.93 /*{{{ (do not) process Rob Nation's own graphics mode sequences */
3813 pcg 1.1 void
3814 pcg 1.34 rxvt_term::process_graphics ()
3815 pcg 1.1 {
3816 pcg 1.81 unicode_t ch, cmd = cmd_getc ();
3817 pcg 1.1
3818 pcg 1.36 if (cmd == 'Q')
3819     { /* query graphics */
3820 pcg 1.43 tt_printf ("\033G0\n"); /* no graphics */
3821 pcg 1.36 return;
3822     }
3823     /* swallow other graphics sequences until terminating ':' */
3824     do
3825     ch = cmd_getc ();
3826     while (ch != ':');
3827 pcg 1.1 }
3828     /*}}} */
3829    
3830     /* ------------------------------------------------------------------------- */
3831    
3832     /*
3833 pcg 1.43 * Send printf () formatted output to the command.
3834 pcg 1.1 * Only use for small amounts of data.
3835     */
3836     void
3837 pcg 1.10 rxvt_term::tt_printf (const char *fmt,...)
3838 pcg 1.1 {
3839 pcg 1.10 va_list arg_ptr;
3840     unsigned char buf[256];
3841 pcg 1.1
3842 pcg 1.10 va_start (arg_ptr, fmt);
3843     vsnprintf ((char *)buf, 256, fmt, arg_ptr);
3844     va_end (arg_ptr);
3845     tt_write (buf, STRLEN (buf));
3846 pcg 1.1 }
3847    
3848     /* ---------------------------------------------------------------------- */
3849 pcg 1.10 /* Write data to the pty as typed by the user, pasted with the mouse,
3850 pcg 1.1 * or generated by us in response to a query ESC sequence.
3851     */
3852     void
3853 pcg 1.10 rxvt_term::tt_write (const unsigned char *data, unsigned int len)
3854 pcg 1.1 {
3855 pcg 1.10 enum { MAX_PTY_WRITE = 255 }; // minimum MAX_INPUT
3856    
3857     if (len)
3858     {
3859     if (v_buflen == 0)
3860     {
3861 pcg 1.34 ssize_t written = write (cmd_fd, data, min (MAX_PTY_WRITE, len));
3862    
3863     if ((unsigned int)written == len)
3864 pcg 1.10 return;
3865    
3866     data += written;
3867     len -= written;
3868     }
3869    
3870    
3871     v_buffer = (unsigned char *)realloc (v_buffer, v_buflen + len);
3872    
3873     memcpy (v_buffer + v_buflen, data, len);
3874     v_buflen += len;
3875 pcg 1.1 }
3876    
3877 pcg 1.10 for (;;)
3878     {
3879     int written = write (cmd_fd, v_buffer, min (MAX_PTY_WRITE, v_buflen));
3880    
3881     if (written > 0)
3882     {
3883     v_buflen -= written;
3884    
3885     if (v_buflen == 0)
3886     {
3887     free (v_buffer);
3888     v_buffer = 0;
3889     v_buflen = 0;
3890    
3891     pty_ev.set (EVENT_READ);
3892     return;
3893     }
3894 pcg 1.1
3895 pcg 1.10 memmove (v_buffer, v_buffer + written, v_buflen);
3896     }
3897     else if (written != -1 || (errno != EAGAIN && errno != EINTR))
3898     // original code just ignores this...
3899     destroy ();
3900     else
3901     {
3902     pty_ev.set (EVENT_READ | EVENT_WRITE);
3903     return;
3904     }
3905 pcg 1.1 }
3906     }
3907 pcg 1.10
3908 pcg 1.1 /*----------------------- end-of-file (C source) -----------------------*/
3909