ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/rxvt-unicode/src/command.C
Revision: 1.90
Committed: Fri Apr 2 19:09:52 2004 UTC (20 years, 1 month ago) by pcg
Content type: text/plain
Branch: MAIN
CVS Tags: rel-2_7
Changes since 1.81: +489 -128 lines
Log Message:
*** empty log message ***

File Contents

# User Rev Content
1 pcg 1.1 /*--------------------------------*-C-*---------------------------------*
2     * File: command.c
3     *----------------------------------------------------------------------*
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 pcg 1.36
678 pcg 1.11 }
679    
680 pcg 1.42 display->flush ();
681 pcg 1.11 }
682    
683     void
684     rxvt_term::check_cb (check_watcher &w)
685     {
686     SET_R (this);
687 pcg 1.19 SET_LOCALE (locale);
688 pcg 1.11
689     flush ();
690     }
691    
692 pcg 1.27 #ifdef CURSOR_BLINK
693 pcg 1.3 void
694 pcg 1.31 rxvt_term::cursor_blink_cb (time_watcher &w)
695 pcg 1.5 {
696     hidden_cursor = !hidden_cursor;
697     want_refresh = 1;
698 pcg 1.28
699     w.start (w.at + BLINK_INTERVAL);
700 pcg 1.5 }
701 pcg 1.27 #endif
702 pcg 1.5
703 pcg 1.31 #ifdef TEXT_BLINK
704     void
705     rxvt_term::text_blink_cb (time_watcher &w)
706     {
707     if (scr_refresh_rend (RS_Blink, RS_Blink))
708     {
709     hidden_text = !hidden_text;
710     want_refresh = 1;
711     w.start (w.at + TEXT_BLINK_INTERVAL);
712     }
713     }
714     #endif
715    
716 pcg 1.4 bool
717 pcg 1.8 rxvt_term::pty_fill ()
718 pcg 1.4 {
719     ssize_t n = cmdbuf_endp - cmdbuf_ptr;
720    
721     memmove (cmdbuf_base, cmdbuf_ptr, n);
722     cmdbuf_ptr = cmdbuf_base;
723     cmdbuf_endp = cmdbuf_ptr + n;
724 pcg 1.36
725 pcg 1.81 n = read (cmd_fd, cmdbuf_endp, CBUFSIZ - n);
726 pcg 1.4
727     if (n > 0)
728     {
729     cmdbuf_endp += n;
730     return true;
731     }
732 pcg 1.13 else if (n < 0 && errno != EAGAIN)
733     destroy ();
734 pcg 1.57
735 pcg 1.13 return false;
736 pcg 1.4 }
737    
738 pcg 1.3 void
739     rxvt_term::pty_cb (io_watcher &w, short revents)
740     {
741 pcg 1.9 SET_R (this);
742 pcg 1.19 SET_LOCALE (locale);
743 pcg 1.9
744 pcg 1.10 if (revents & EVENT_WRITE)
745     tt_write (0, 0);
746     else if (revents & EVENT_READ)
747 pcg 1.12 {
748     // loop, but don't allow a single term to monopolize us
749     // the number of loops is fully arbitrary, and thus wrong
750 pcg 1.81 while (pty_fill ())
751 pcg 1.12 {
752     if (!seen_input)
753     {
754     seen_input = 1;
755     /* once we know the shell is running, send the screen size. Again! */
756 pcg 1.81 // I don't know why, btw.
757 pcg 1.12 tt_winch ();
758     }
759    
760 pcg 1.57 if (cmd_parse ())
761     break;
762     }
763     }
764     }
765    
766 pcg 1.29 #ifdef POINTER_BLANK
767 pcg 1.6 void
768     rxvt_term::pointer_unblank ()
769     {
770 pcg 1.38 XDefineCursor (display->display, TermWin.vt, TermWin_cursor);
771 pcg 1.19 recolour_cursor ();
772 pcg 1.7
773 pcg 1.6 hidden_pointer = 0;
774 pcg 1.1
775 pcg 1.7 if (Options & Opt_pointerBlank)
776     pointer_ev.start (NOW + pointerBlankDelay);
777 pcg 1.1 }
778    
779     void
780 pcg 1.6 rxvt_term::pointer_blank ()
781 pcg 1.1 {
782 pcg 1.43 if (! (Options & Opt_pointerBlank))
783 pcg 1.6 return;
784    
785 pcg 1.38 XDefineCursor (display->display, TermWin.vt, blank_cursor);
786     XFlush (display->display);
787 pcg 1.1
788 pcg 1.6 hidden_pointer = 1;
789 pcg 1.1 }
790    
791     void
792 pcg 1.6 rxvt_term::pointer_cb (time_watcher &w)
793 pcg 1.1 {
794 pcg 1.9 SET_R (this);
795 pcg 1.19 SET_LOCALE (locale);
796 pcg 1.9
797 pcg 1.6 pointer_blank ();
798 pcg 1.1 }
799     #endif
800    
801     void
802 pcg 1.56 rxvt_term::mouse_report (XButtonEvent &ev)
803 pcg 1.1 {
804 pcg 1.56 int button_number, key_state = 0;
805     int x, y;
806 pcg 1.36
807 pcg 1.38 x = ev.x;
808     y = ev.y;
809 pcg 1.36 pixel_position (&x, &y);
810    
811     if (MEvent.button == AnyButton)
812     {
813     button_number = 3;
814     }
815     else
816     {
817     button_number = MEvent.button - Button1;
818     /* add 0x3D for wheel events, like xterm does */
819     if (button_number >= 3)
820     button_number += (64 - 3);
821     }
822 pcg 1.1
823 pcg 1.36 if (PrivateModes & PrivMode_MouseX10)
824     {
825     /*
826     * do not report ButtonRelease
827     * no state info allowed
828     */
829     key_state = 0;
830     if (button_number == 3)
831     return;
832     }
833     else
834     {
835     /* XTerm mouse reporting needs these values:
836     * 4 = Shift
837     * 8 = Meta
838     * 16 = Control
839     * plus will add in our own Double-Click reporting
840     * 32 = Double Click
841     */
842     key_state = ((MEvent.state & ShiftMask) ? 4 : 0)
843     + ((MEvent.state & ModMetaMask) ? 8 : 0)
844     + ((MEvent.state & ControlMask) ? 16 : 0);
845 pcg 1.1 #ifdef MOUSE_REPORT_DOUBLECLICK
846 pcg 1.36 key_state += ((MEvent.clicks > 1) ? 32 : 0);
847 pcg 1.1 #endif
848 pcg 1.36
849 pcg 1.1 }
850    
851     #ifdef DEBUG_MOUSEREPORT
852 pcg 1.43 fprintf (stderr, "Mouse [");
853 pcg 1.36 if (key_state & 16)
854 pcg 1.43 fputc ('C', stderr);
855 pcg 1.36 if (key_state & 4)
856 pcg 1.43 fputc ('S', stderr);
857 pcg 1.36 if (key_state & 8)
858 pcg 1.43 fputc ('A', stderr);
859 pcg 1.36 if (key_state & 32)
860 pcg 1.43 fputc ('2', stderr);
861     fprintf (stderr, "]: <%d>, %d/%d\n",
862 pcg 1.36 button_number,
863     x + 1,
864     y + 1);
865 pcg 1.1 #else
866 pcg 1.43 tt_printf ("\033[M%c%c%c",
867 pcg 1.36 (32 + button_number + key_state),
868     (32 + x + 1),
869     (32 + y + 1));
870 pcg 1.1 #endif
871     }
872    
873     #ifdef USING_W11LIB
874     void
875 pcg 1.43 rxvt_W11_process_x_event (XEvent *ev)
876 pcg 1.1 {
877 pcg 1.43 rxvt_t *r = rxvt_get_r ();
878 pcg 1.1
879 pcg 1.38 x_cb (*ev);
880 pcg 1.1 }
881     #endif
882    
883     /*{{{ process an X event */
884     void
885 pcg 1.38 rxvt_term::x_cb (XEvent &ev)
886 pcg 1.1 {
887 pcg 1.38 SET_R (this);
888     SET_LOCALE (locale);
889    
890     #if defined(CURSOR_BLINK)
891     if ((Options & Opt_cursorBlink) && ev.type == KeyPress)
892     {
893     if (hidden_cursor)
894     {
895     hidden_cursor = 0;
896     want_refresh = 1;
897     }
898    
899     cursor_blink_ev.start (NOW + BLINK_INTERVAL);
900     }
901     #endif
902    
903     #if defined(POINTER_BLANK)
904     if ((Options & Opt_pointerBlank) && pointerBlankDelay > 0)
905     {
906     if (ev.type == MotionNotify
907     || ev.type == ButtonPress
908     || ev.type == ButtonRelease)
909     if (hidden_pointer)
910     pointer_unblank ();
911    
912     if (ev.type == KeyPress && hidden_pointer == 0)
913     pointer_blank ();
914     }
915     #endif
916    
917     #ifdef USE_XIM
918     if (XFilterEvent (&ev, None))
919     return;
920     #endif
921    
922 pcg 1.36 Window unused_root, unused_child;
923     int unused_root_x, unused_root_y;
924     unsigned int unused_mask;
925 pcg 1.3
926 pcg 1.1 #ifdef DEBUG_X
927 pcg 1.36 const char *const eventnames[] =
928 pcg 1.1 { /* mason - this matches my system */
929 pcg 1.36 "",
930     "",
931     "KeyPress",
932     "KeyRelease",
933     "ButtonPress",
934     "ButtonRelease",
935     "MotionNotify",
936     "EnterNotify",
937     "LeaveNotify",
938     "FocusIn",
939     "FocusOut",
940     "KeymapNotify",
941     "Expose",
942     "GraphicsExpose",
943     "NoExpose",
944     "VisibilityNotify",
945     "CreateNotify",
946     "DestroyNotify",
947     "UnmapNotify",
948     "MapNotify",
949     "MapRequest",
950     "ReparentNotify",
951     "ConfigureNotify",
952     "ConfigureRequest",
953     "GravityNotify",
954     "ResizeRequest",
955     "CirculateNotify",
956     "CirculateRequest",
957     "PropertyNotify",
958     "SelectionClear",
959     "SelectionRequest",
960     "SelectionNotify",
961     "ColormapNotify",
962     "ClientMessage",
963     "MappingNotify"
964 pcg 1.1 };
965     #endif
966    
967     #ifdef DEBUG_X
968 pcg 1.36 struct timeval tp;
969     struct tm *ltt;
970 pcg 1.43 (void)gettimeofday (&tp, NULL);
971     ltt = localtime (& (tp.tv_sec));
972     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));
973 pcg 1.1 #endif
974    
975 pcg 1.38 switch (ev.type)
976 pcg 1.36 {
977     case KeyPress:
978 pcg 1.38 lookup_key (ev.xkey);
979 pcg 1.36 break;
980 pcg 1.1
981     #if defined(MOUSE_WHEEL) && defined(MOUSE_SLIP_WHEELING)
982 pcg 1.36 case KeyRelease:
983     {
984 pcg 1.43 if (! (ev.xkey.state & ControlMask))
985 pcg 1.36 mouse_slip_wheel_speed = 0;
986     else
987     {
988     KeySym ks;
989    
990 pcg 1.43 ks = XKeycodeToKeysym (display->display, ev.xkey.keycode, 0);
991 pcg 1.36 if (ks == XK_Control_L || ks == XK_Control_R)
992     mouse_slip_wheel_speed = 0;
993     }
994     break;
995     }
996     #endif
997    
998     case ButtonPress:
999 pcg 1.38 button_press (ev.xbutton);
1000 pcg 1.36 break;
1001    
1002     case ButtonRelease:
1003 pcg 1.38 button_release (ev.xbutton);
1004 pcg 1.36 break;
1005    
1006     case ClientMessage:
1007 pcg 1.38 if (ev.xclient.format == 32
1008     && (Atom)ev.xclient.data.l[0] == xa[XA_WMDELETEWINDOW])
1009 pcg 1.34 destroy ();
1010 pcg 1.1 #ifdef OFFIX_DND
1011 pcg 1.36 /* OffiX Dnd (drag 'n' drop) protocol */
1012 pcg 1.38 else if (ev.xclient.message_type == xa[XA_DNDPROTOCOL]
1013     && (ev.xclient.data.l[0] == DndFile
1014     || ev.xclient.data.l[0] == DndDir
1015     || ev.xclient.data.l[0] == DndLink))
1016 pcg 1.36 {
1017     /* Get Dnd data */
1018     Atom ActualType;
1019     int ActualFormat;
1020     unsigned char *data;
1021     unsigned long Size, RemainingBytes;
1022    
1023 pcg 1.43 XGetWindowProperty (display->display, display->root,
1024 pcg 1.36 xa[XA_DNDSELECTION],
1025     0L, 1000000L,
1026     False, AnyPropertyType,
1027     &ActualType, &ActualFormat,
1028     &Size, &RemainingBytes,
1029     &data);
1030 pcg 1.43 XChangeProperty (display->display, display->root,
1031 pcg 1.36 XA_CUT_BUFFER0, XA_STRING,
1032     8, PropModeReplace,
1033 pcg 1.43 data, STRLEN (data));
1034 pcg 1.38 selection_paste (display->root, XA_CUT_BUFFER0, True);
1035 pcg 1.43 XSetInputFocus (display->display, display->root, RevertToNone, CurrentTime);
1036 pcg 1.36 }
1037 pcg 1.1 #endif /* OFFIX_DND */
1038 pcg 1.36 break;
1039 pcg 1.1
1040 pcg 1.36 case MappingNotify:
1041 pcg 1.43 XRefreshKeyboardMapping (& (ev.xmapping));
1042 pcg 1.36 break;
1043    
1044     /*
1045     * XXX: this is not the _current_ arrangement
1046     * Here's my conclusion:
1047     * If the window is completely unobscured, use bitblt's
1048     * to scroll. Even then, they're only used when doing partial
1049     * screen scrolling. When partially obscured, we have to fill
1050     * in the GraphicsExpose parts, which means that after each refresh,
1051     * we need to wait for the graphics expose or Noexpose events,
1052     * which ought to make things real slow!
1053     */
1054     case VisibilityNotify:
1055 pcg 1.38 switch (ev.xvisibility.state)
1056 pcg 1.8 {
1057     case VisibilityUnobscured:
1058 pcg 1.34 refresh_type = FAST_REFRESH;
1059 pcg 1.8 break;
1060     case VisibilityPartiallyObscured:
1061 pcg 1.34 refresh_type = SLOW_REFRESH;
1062 pcg 1.8 break;
1063     default:
1064 pcg 1.34 refresh_type = NO_REFRESH;
1065 pcg 1.8 break;
1066     }
1067 pcg 1.36 break;
1068 pcg 1.1
1069 pcg 1.36 case FocusIn:
1070     if (!TermWin.focus)
1071     {
1072     TermWin.focus = 1;
1073     want_refresh = 1;
1074 pcg 1.1 #ifdef USE_XIM
1075 pcg 1.36 if (Input_Context != NULL)
1076 pcg 1.43 XSetICFocus (Input_Context);
1077 pcg 1.1 #endif
1078 pcg 1.5 #ifdef CURSOR_BLINK
1079 pcg 1.34 if (Options & Opt_cursorBlink)
1080     cursor_blink_ev.start (NOW + BLINK_INTERVAL);
1081 pcg 1.5 #endif
1082 pcg 1.1
1083 pcg 1.36 }
1084     break;
1085    
1086     case FocusOut:
1087     if (TermWin.focus)
1088     {
1089     TermWin.focus = 0;
1090     want_refresh = 1;
1091 pcg 1.1 #ifdef USE_XIM
1092 pcg 1.36 if (Input_Context != NULL)
1093 pcg 1.43 XUnsetICFocus (Input_Context);
1094 pcg 1.5 #endif
1095     #ifdef CURSOR_BLINK
1096 pcg 1.34 if (Options & Opt_cursorBlink)
1097     cursor_blink_ev.stop ();
1098     hidden_cursor = 0;
1099 pcg 1.1 #endif
1100    
1101 pcg 1.36 }
1102     break;
1103    
1104     case ConfigureNotify:
1105 pcg 1.38 if (ev.xconfigure.window == TermWin.parent[0])
1106 pcg 1.36 {
1107 pcg 1.38 int height, width;
1108 pcg 1.36
1109     do
1110     { /* Wrap lots of configures into one */
1111 pcg 1.38 width = ev.xconfigure.width;
1112     height = ev.xconfigure.height;
1113 pcg 1.43 D_SIZE ((stderr, "Size: ConfigureNotify: %4d x %4d", width, height));
1114 pcg 1.36 }
1115 pcg 1.43 while (XCheckTypedWindowEvent (display->display, ev.xconfigure.window, ConfigureNotify, &ev));
1116 pcg 1.38
1117 pcg 1.36 if (szHint.width != width || szHint.height != height)
1118     {
1119 pcg 1.43 D_SIZE ((stderr, "Size: Resizing from: %4d x %4d", szHint.width, szHint.height));
1120 pcg 1.36 resize_all_windows (width, height, 1);
1121     }
1122 pcg 1.1 #ifdef DEBUG_SIZE
1123 pcg 1.36 else
1124     {
1125 pcg 1.43 D_SIZE ((stderr, "Size: Not resizing"));
1126 pcg 1.36 }
1127 pcg 1.1 #endif
1128     #ifdef TRANSPARENT /* XXX: maybe not needed - leave in for now */
1129 pcg 1.36 if (Options & Opt_transparent)
1130     {
1131     check_our_parents ();
1132     if (am_transparent)
1133     want_full_refresh = 1;
1134     }
1135     #endif
1136     }
1137     break;
1138    
1139     case SelectionClear:
1140 pcg 1.81 selection_clear ();
1141 pcg 1.36 break;
1142    
1143     case SelectionNotify:
1144     if (selection_wait == Sel_normal)
1145 pcg 1.38 selection_paste (ev.xselection.requestor,
1146     ev.xselection.property, True);
1147 pcg 1.36 break;
1148    
1149     case SelectionRequest:
1150 pcg 1.38 selection_send (ev.xselectionrequest);
1151 pcg 1.36 break;
1152 pcg 1.1
1153 pcg 1.36 case UnmapNotify:
1154     TermWin.mapped = 0;
1155 pcg 1.31 #ifdef TEXT_BLINK
1156 pcg 1.34 text_blink_ev.stop ();
1157 pcg 1.31 #endif
1158 pcg 1.36 break;
1159 pcg 1.1
1160 pcg 1.36 case MapNotify:
1161     TermWin.mapped = 1;
1162 pcg 1.31 #ifdef TEXT_BLINK
1163 pcg 1.34 text_blink_ev.start (NOW + TEXT_BLINK_INTERVAL);
1164 pcg 1.31 #endif
1165 pcg 1.36 break;
1166 pcg 1.1
1167     #ifdef TRANSPARENT
1168 pcg 1.36 case ReparentNotify:
1169 pcg 1.38 rootwin_cb (ev);
1170     break;
1171 pcg 1.1 #endif /* TRANSPARENT */
1172    
1173 pcg 1.36 case GraphicsExpose:
1174     case Expose:
1175 pcg 1.38 if (ev.xany.window == TermWin.vt)
1176 pcg 1.36 {
1177 pcg 1.1 #ifdef NO_SLOW_LINK_SUPPORT
1178 pcg 1.38 scr_expose (ev.xexpose.x, ev.xexpose.y,
1179     ev.xexpose.width, ev.xexpose.height, False);
1180 pcg 1.1 #else
1181     // don't understand this, so commented it out
1182 pcg 1.38 scr_expose (ev.xexpose.x, ev.xexpose.y,
1183     ev.xexpose.width, ev.xexpose.height, False);
1184     //scr_expose (ev.xexpose.x, 0,
1185     // ev.xexpose.width, TermWin.height, False);
1186 pcg 1.36 #endif
1187     want_refresh = 1;
1188     }
1189     else
1190     {
1191 pcg 1.38 XEvent unused_event;
1192 pcg 1.36
1193 pcg 1.43 while (XCheckTypedWindowEvent (display->display, ev.xany.window,
1194 pcg 1.36 Expose,
1195 pcg 1.38 &unused_event)) ;
1196 pcg 1.43 while (XCheckTypedWindowEvent (display->display, ev.xany.window,
1197 pcg 1.36 GraphicsExpose,
1198 pcg 1.38 &unused_event)) ;
1199 pcg 1.43 if (isScrollbarWindow (ev.xany.window))
1200 pcg 1.36 {
1201 pcg 1.43 scrollBar.setIdle ();
1202 pcg 1.36 scrollbar_show (0);
1203     }
1204 pcg 1.1 #ifdef MENUBAR
1205 pcg 1.43 if (menubar_visible () && isMenuBarWindow (ev.xany.window))
1206 pcg 1.36 menubar_expose ();
1207 pcg 1.1 #endif
1208 pcg 1.36 }
1209     break;
1210    
1211     case MotionNotify:
1212 pcg 1.1 #ifdef POINTER_BLANK
1213 pcg 1.36 if (hidden_pointer)
1214     pointer_unblank ();
1215 pcg 1.1 #endif
1216     #if MENUBAR
1217 pcg 1.43 if (isMenuBarWindow (ev.xany.window))
1218 pcg 1.36 {
1219 pcg 1.56 menubar_control (ev.xbutton);
1220 pcg 1.36 break;
1221     }
1222     #endif
1223 pcg 1.43 if ((PrivateModes & PrivMode_mouse_report) && ! (bypass_keystate))
1224 pcg 1.36 break;
1225    
1226 pcg 1.38 if (ev.xany.window == TermWin.vt)
1227 pcg 1.36 {
1228 pcg 1.38 if ((ev.xbutton.state & (Button1Mask | Button3Mask)))
1229 pcg 1.36 {
1230 pcg 1.38 while (XCheckTypedWindowEvent (display->display, TermWin.vt, MotionNotify, &ev))
1231     ;
1232    
1233 pcg 1.43 XQueryPointer (display->display, TermWin.vt,
1234 pcg 1.36 &unused_root, &unused_child,
1235     &unused_root_x, &unused_root_y,
1236 pcg 1.43 & (ev.xbutton.x), & (ev.xbutton.y),
1237 pcg 1.36 &unused_mask);
1238 pcg 1.1 #ifdef MOUSE_THRESHOLD
1239 pcg 1.36 /* deal with a `jumpy' mouse */
1240 pcg 1.38 if ((ev.xmotion.time - MEvent.time) > MOUSE_THRESHOLD)
1241 pcg 1.36 {
1242 pcg 1.1 #endif
1243 pcg 1.38 selection_extend ((ev.xbutton.x), (ev.xbutton.y),
1244     (ev.xbutton.state & Button3Mask) ? 2 : 0);
1245 pcg 1.1 #ifdef SELECTION_SCROLLING
1246 pcg 1.38 if (ev.xbutton.y < TermWin.int_bwidth
1247 pcg 1.43 || Pixel2Row (ev.xbutton.y) > (TermWin.nrow-1))
1248 pcg 1.36 {
1249     int dist;
1250    
1251     pending_scroll_selection=1;
1252    
1253     /* don't clobber the current delay if we are
1254     * already in the middle of scrolling.
1255     */
1256     if (scroll_selection_delay<=0)
1257     scroll_selection_delay=SCROLLBAR_CONTINUOUS_DELAY;
1258    
1259     /* save the event params so we can highlight
1260     * the selection in the pending-scroll loop
1261     */
1262 pcg 1.38 selection_save_x=ev.xbutton.x;
1263     selection_save_y=ev.xbutton.y;
1264 pcg 1.36 selection_save_state=
1265 pcg 1.38 (ev.xbutton.state & Button3Mask) ? 2 : 0;
1266 pcg 1.36
1267     /* calc number of lines to scroll */
1268 pcg 1.38 if (ev.xbutton.y<TermWin.int_bwidth)
1269 pcg 1.36 {
1270     scroll_selection_dir = UP;
1271 pcg 1.38 dist = TermWin.int_bwidth - ev.xbutton.y;
1272 pcg 1.36 }
1273     else
1274     {
1275     scroll_selection_dir = DN;
1276 pcg 1.38 dist = ev.xbutton.y -
1277 pcg 1.36 (TermWin.int_bwidth + TermWin.height);
1278     }
1279 pcg 1.43 scroll_selection_lines= (Pixel2Height (dist)/
1280 pcg 1.36 SELECTION_SCROLL_LINE_SPEEDUP)+1;
1281 pcg 1.43 MIN_IT (scroll_selection_lines,
1282 pcg 1.36 SELECTION_SCROLL_MAX_LINES);
1283     }
1284     else
1285     {
1286     /* we are within the text window, so we
1287     * shouldn't be scrolling
1288     */
1289     pending_scroll_selection = 0;
1290     }
1291 pcg 1.1 #endif
1292     #ifdef MOUSE_THRESHOLD
1293 pcg 1.36
1294     }
1295 pcg 1.1 #endif
1296 pcg 1.36
1297     }
1298     }
1299 pcg 1.43 else if (isScrollbarWindow (ev.xany.window) && scrollbar_isMotion ())
1300 pcg 1.36 {
1301 pcg 1.43 while (XCheckTypedWindowEvent (display->display, scrollBar.win,
1302 pcg 1.38 MotionNotify, &ev)) ;
1303 pcg 1.43 XQueryPointer (display->display, scrollBar.win,
1304 pcg 1.36 &unused_root, &unused_child,
1305     &unused_root_x, &unused_root_y,
1306 pcg 1.43 & (ev.xbutton.x), & (ev.xbutton.y),
1307 pcg 1.36 &unused_mask);
1308 pcg 1.43 scr_move_to (scrollbar_position (ev.xbutton.y) - csrO,
1309     scrollbar_size ());
1310 pcg 1.36 scr_refresh (refresh_type);
1311     refresh_limit = 0;
1312     scrollbar_show (1);
1313     }
1314     break;
1315     }
1316     }
1317 pcg 1.1
1318     void
1319 pcg 1.38 rxvt_term::rootwin_cb (XEvent &ev)
1320     {
1321     SET_R (this);
1322     SET_LOCALE (locale);
1323    
1324 pcg 1.40 switch (ev.type)
1325 pcg 1.38 {
1326 pcg 1.40 case PropertyNotify:
1327     if (ev.xproperty.atom == xa[XA_VT_SELECTION])
1328     {
1329     if (ev.xproperty.state == PropertyNewValue)
1330     selection_property (ev.xproperty.window, ev.xproperty.atom);
1331     break;
1332     }
1333     #ifdef TRANSPARENT
1334     else
1335     {
1336     /*
1337     * if user used some Esetroot compatible prog to set the root bg,
1338     * use the property to determine the pixmap. We use it later on.
1339     */
1340     if (xa[XA_XROOTPMAPID] == 0)
1341 pcg 1.43 xa[XA_XROOTPMAPID] = XInternAtom (display->display, "_XROOTPMAP_ID", False);
1342 pcg 1.38
1343 pcg 1.40 if (ev.xproperty.atom != xa[XA_XROOTPMAPID])
1344     return;
1345     }
1346 pcg 1.38
1347 pcg 1.40 /* FALLTHROUGH */
1348     case ReparentNotify:
1349 pcg 1.90 if ((Options & Opt_transparent) && check_our_parents () && am_transparent)
1350     want_full_refresh = 1;
1351 pcg 1.40 break;
1352     #endif
1353 pcg 1.38 }
1354     }
1355    
1356     void
1357 pcg 1.56 rxvt_term::button_press (XButtonEvent &ev)
1358 pcg 1.1 {
1359 pcg 1.36 int reportmode = 0, clickintime;
1360 pcg 1.1
1361 pcg 1.38 bypass_keystate = ev.state & (ModMetaMask | ShiftMask);
1362 pcg 1.36 if (!bypass_keystate)
1363 pcg 1.43 reportmode = !! (PrivateModes & PrivMode_mouse_report);
1364 pcg 1.36 /*
1365     * VT window processing of button press
1366     */
1367 pcg 1.38 if (ev.window == TermWin.vt)
1368 pcg 1.36 {
1369 pcg 1.50 clickintime = ev.time - MEvent.time < MULTICLICK_TIME;
1370     if (reportmode)
1371 pcg 1.36 {
1372 pcg 1.50 /* mouse report from vt window */
1373     /* save the xbutton state (for ButtonRelease) */
1374     MEvent.state = ev.state;
1375     #ifdef MOUSE_REPORT_DOUBLECLICK
1376     if (ev.button == MEvent.button && clickintime)
1377 pcg 1.36 {
1378 pcg 1.50 /* same button, within alloted time */
1379     MEvent.clicks++;
1380     if (MEvent.clicks > 1)
1381 pcg 1.36 {
1382 pcg 1.50 /* only report double clicks */
1383     MEvent.clicks = 2;
1384 pcg 1.36 mouse_report (ev);
1385 pcg 1.50
1386     /* don't report the release */
1387     MEvent.clicks = 0;
1388     MEvent.button = AnyButton;
1389 pcg 1.36 }
1390 pcg 1.50 }
1391     else
1392     {
1393     /* different button, or time expired */
1394     MEvent.clicks = 1;
1395 pcg 1.38 MEvent.button = ev.button;
1396 pcg 1.36 mouse_report (ev);
1397 pcg 1.50 }
1398     #else
1399     MEvent.button = ev.button;
1400     mouse_report (ev);
1401 pcg 1.1 #endif /* MOUSE_REPORT_DOUBLECLICK */
1402 pcg 1.36
1403 pcg 1.50 }
1404     else
1405     {
1406     if (ev.button != MEvent.button)
1407     MEvent.clicks = 0;
1408     switch (ev.button)
1409 pcg 1.36 {
1410 pcg 1.50 case Button1:
1411     /* allow shift+left click to extend selection */
1412     if (ev.state & ShiftMask && ! (PrivateModes & PrivMode_mouse_report))
1413     {
1414     if (MEvent.button == Button1 && clickintime)
1415     selection_rotate (ev.x, ev.y);
1416     else
1417     selection_extend (ev.x, ev.y, 1);
1418     }
1419     else
1420     {
1421     if (MEvent.button == Button1 && clickintime)
1422     MEvent.clicks++;
1423 pcg 1.36 else
1424 pcg 1.50 MEvent.clicks = 1;
1425 pcg 1.21
1426 pcg 1.50 selection_click (MEvent.clicks, ev.x, ev.y);
1427     }
1428 pcg 1.21
1429 pcg 1.50 MEvent.button = Button1;
1430     break;
1431 pcg 1.1
1432 pcg 1.50 case Button3:
1433     if (MEvent.button == Button3 && clickintime)
1434     selection_rotate (ev.x, ev.y);
1435     else
1436     selection_extend (ev.x, ev.y, 1);
1437     MEvent.button = Button3;
1438     break;
1439 pcg 1.36 }
1440     }
1441 pcg 1.50 MEvent.time = ev.time;
1442     return;
1443 pcg 1.36 }
1444 pcg 1.1
1445 pcg 1.36 /*
1446     * Scrollbar window processing of button press
1447     */
1448 pcg 1.43 if (isScrollbarWindow (ev.window))
1449 pcg 1.36 {
1450     scrollBar.setIdle ();
1451     /*
1452     * Rxvt-style scrollbar:
1453     * move up if mouse is above slider
1454     * move dn if mouse is below slider
1455     *
1456     * XTerm-style scrollbar:
1457     * Move display proportional to pointer location
1458     * pointer near top -> scroll one line
1459     * pointer near bot -> scroll full page
1460     */
1461 pcg 1.1 #ifndef NO_SCROLLBAR_REPORT
1462 pcg 1.36 if (reportmode)
1463     {
1464     /*
1465     * Mouse report disabled scrollbar:
1466     * arrow buttons - send up/down
1467     * click on scrollbar - send pageup/down
1468     */
1469     if ((scrollBar.style == R_SB_NEXT
1470 pcg 1.43 && scrollbarnext_upButton (ev.y))
1471 pcg 1.36 || (scrollBar.style == R_SB_RXVT
1472 pcg 1.43 && scrollbarrxvt_upButton (ev.y)))
1473     tt_printf ("\033[A");
1474 pcg 1.36 else if ((scrollBar.style == R_SB_NEXT
1475 pcg 1.43 && scrollbarnext_dnButton (ev.y))
1476 pcg 1.36 || (scrollBar.style == R_SB_RXVT
1477 pcg 1.43 && scrollbarrxvt_dnButton (ev.y)))
1478     tt_printf ("\033[B");
1479 pcg 1.36 else
1480 pcg 1.38 switch (ev.button)
1481 pcg 1.36 {
1482     case Button2:
1483 pcg 1.43 tt_printf ("\014");
1484 pcg 1.36 break;
1485     case Button1:
1486 pcg 1.43 tt_printf ("\033[6~");
1487 pcg 1.36 break;
1488     case Button3:
1489 pcg 1.43 tt_printf ("\033[5~");
1490 pcg 1.36 break;
1491     }
1492     }
1493     else
1494 pcg 1.1 #endif /* NO_SCROLLBAR_REPORT */
1495    
1496 pcg 1.36 {
1497     char upordown = 0;
1498    
1499     if (scrollBar.style == R_SB_NEXT)
1500     {
1501 pcg 1.43 if (scrollbarnext_upButton (ev.y))
1502 pcg 1.36 upordown = -1; /* up */
1503 pcg 1.43 else if (scrollbarnext_dnButton (ev.y))
1504 pcg 1.36 upordown = 1; /* down */
1505     }
1506     else if (scrollBar.style == R_SB_RXVT)
1507     {
1508 pcg 1.43 if (scrollbarrxvt_upButton (ev.y))
1509 pcg 1.36 upordown = -1; /* up */
1510 pcg 1.43 else if (scrollbarrxvt_dnButton (ev.y))
1511 pcg 1.36 upordown = 1; /* down */
1512     }
1513     if (upordown)
1514     {
1515 pcg 1.1 #ifndef NO_SCROLLBAR_BUTTON_CONTINUAL_SCROLLING
1516 pcg 1.36 scroll_arrow_delay = SCROLLBAR_INITIAL_DELAY;
1517 pcg 1.1 #endif
1518 pcg 1.36 if (scr_page (upordown < 0 ? UP : DN, 1))
1519     {
1520     if (upordown < 0)
1521     scrollBar.setUp ();
1522     else
1523     scrollBar.setDn ();
1524     }
1525     }
1526     else
1527 pcg 1.38 switch (ev.button)
1528 pcg 1.36 {
1529     case Button2:
1530     switch (scrollbar_align)
1531     {
1532     case R_SB_ALIGN_TOP:
1533     csrO = 0;
1534     break;
1535     case R_SB_ALIGN_CENTRE:
1536     csrO = (scrollBar.bot - scrollBar.top) / 2;
1537     break;
1538     case R_SB_ALIGN_BOTTOM:
1539     csrO = scrollBar.bot - scrollBar.top;
1540     break;
1541     }
1542     if (scrollBar.style == R_SB_XTERM
1543 pcg 1.43 || scrollbar_above_slider (ev.y)
1544     || scrollbar_below_slider (ev.y))
1545     scr_move_to ( scrollbar_position (ev.y) - csrO,
1546     scrollbar_size ());
1547 pcg 1.36 scrollBar.setMotion ();
1548     break;
1549    
1550     case Button1:
1551     if (scrollbar_align == R_SB_ALIGN_CENTRE)
1552 pcg 1.38 csrO = ev.y - scrollBar.top;
1553 pcg 1.36 /* FALLTHROUGH */
1554    
1555     case Button3:
1556     if (scrollBar.style != R_SB_XTERM)
1557     {
1558 pcg 1.43 if (scrollbar_above_slider (ev.y))
1559 pcg 1.1 # ifdef RXVT_SCROLL_FULL
1560 pcg 1.36 scr_page (UP, TermWin.nrow - 1);
1561 pcg 1.1 # else
1562 pcg 1.36 scr_page (UP, TermWin.nrow / 4);
1563 pcg 1.1 # endif
1564 pcg 1.43 else if (scrollbar_below_slider (ev.y))
1565 pcg 1.1 # ifdef RXVT_SCROLL_FULL
1566 pcg 1.36 scr_page (DN, TermWin.nrow - 1);
1567 pcg 1.1 # else
1568 pcg 1.36 scr_page (DN, TermWin.nrow / 4);
1569 pcg 1.1 # endif
1570 pcg 1.36 else
1571     scrollBar.setMotion ();
1572     }
1573     else
1574     {
1575 pcg 1.38 scr_page ((ev.button == Button1 ? DN : UP),
1576 pcg 1.36 (TermWin.nrow
1577 pcg 1.43 * scrollbar_position (ev.y)
1578     / scrollbar_size ()));
1579 pcg 1.36 }
1580     break;
1581     }
1582     }
1583     return;
1584 pcg 1.1 }
1585     #if MENUBAR
1586 pcg 1.36 /*
1587     * Menubar window processing of button press
1588     */
1589 pcg 1.43 if (isMenuBarWindow (ev.window))
1590 pcg 1.36 menubar_control (ev);
1591 pcg 1.1 #endif
1592     }
1593    
1594     void
1595 pcg 1.56 rxvt_term::button_release (XButtonEvent &ev)
1596 pcg 1.1 {
1597 pcg 1.38 int reportmode = 0;
1598 pcg 1.1
1599 pcg 1.36 csrO = 0; /* reset csr Offset */
1600     if (!bypass_keystate)
1601 pcg 1.43 reportmode = !! (PrivateModes & PrivMode_mouse_report);
1602 pcg 1.36
1603 pcg 1.43 if (scrollbar_isUpDn ())
1604 pcg 1.36 {
1605     scrollBar.setIdle ();
1606     scrollbar_show (0);
1607 pcg 1.1 #ifndef NO_SCROLLBAR_BUTTON_CONTINUAL_SCROLLING
1608 pcg 1.36 refresh_type &= ~SMOOTH_REFRESH;
1609 pcg 1.1 #endif
1610 pcg 1.36
1611 pcg 1.1 }
1612     #ifdef SELECTION_SCROLLING
1613 pcg 1.36 pending_scroll_selection=0;
1614 pcg 1.1 #endif
1615 pcg 1.38 if (ev.window == TermWin.vt)
1616 pcg 1.36 {
1617 pcg 1.50 if (reportmode)
1618 pcg 1.36 {
1619 pcg 1.50 /* mouse report from vt window */
1620     /* don't report release of wheel "buttons" */
1621     if (ev.button >= 4)
1622     return;
1623     #ifdef MOUSE_REPORT_DOUBLECLICK
1624     /* only report the release of 'slow' single clicks */
1625     if (MEvent.button != AnyButton
1626     && (ev.button != MEvent.button
1627     || (ev.time - MEvent.time
1628     > MULTICLICK_TIME / 2)))
1629 pcg 1.36 {
1630 pcg 1.50 MEvent.clicks = 0;
1631 pcg 1.36 MEvent.button = AnyButton;
1632     mouse_report (ev);
1633 pcg 1.50 }
1634     #else /* MOUSE_REPORT_DOUBLECLICK */
1635     MEvent.button = AnyButton;
1636     mouse_report (ev);
1637 pcg 1.1 #endif /* MOUSE_REPORT_DOUBLECLICK */
1638 pcg 1.50 return;
1639     }
1640     /*
1641     * dumb hack to compensate for the failure of click-and-drag
1642     * when overriding mouse reporting
1643     */
1644     if (PrivateModes & PrivMode_mouse_report
1645     && bypass_keystate
1646     && ev.button == Button1 && MEvent.clicks <= 1)
1647     selection_extend (ev.x, ev.y, 0);
1648    
1649     switch (ev.button)
1650     {
1651     case Button1:
1652     case Button3:
1653     selection_make (ev.time);
1654     break;
1655     case Button2:
1656     selection_request (ev.time, ev.x, ev.y);
1657     break;
1658     #ifdef MOUSE_WHEEL
1659     case Button4:
1660     case Button5:
1661 pcg 1.36 {
1662 pcg 1.50 int i;
1663     page_dirn v;
1664 pcg 1.36
1665 pcg 1.50 v = (ev.button == Button4) ? UP : DN;
1666     if (ev.state & ShiftMask)
1667     i = 1;
1668     else if ((Options & Opt_mouseWheelScrollPage))
1669     i = TermWin.nrow - 1;
1670     else
1671     i = 5;
1672 pcg 1.1 # ifdef MOUSE_SLIP_WHEELING
1673 pcg 1.50 if (ev.state & ControlMask)
1674     {
1675     mouse_slip_wheel_speed += (v ? -1 : 1);
1676     mouse_slip_wheel_delay = SCROLLBAR_CONTINUOUS_DELAY;
1677     }
1678 pcg 1.1 # endif
1679     # ifdef JUMP_MOUSE_WHEEL
1680 pcg 1.50 scr_page (v, i);
1681     scr_refresh (SMOOTH_REFRESH);
1682     scrollbar_show (1);
1683     # else
1684     while (i--)
1685     {
1686     scr_page (v, 1);
1687 pcg 1.36 scr_refresh (SMOOTH_REFRESH);
1688     scrollbar_show (1);
1689 pcg 1.50 }
1690 pcg 1.1 # endif
1691 pcg 1.36
1692 pcg 1.50 }
1693     break;
1694 pcg 1.1 #endif
1695 pcg 1.36
1696     }
1697     }
1698 pcg 1.1 #ifdef MENUBAR
1699 pcg 1.43 else if (isMenuBarWindow (ev.window))
1700 pcg 1.36 menubar_control (ev);
1701 pcg 1.1 #endif
1702     }
1703    
1704 pcg 1.90 #ifdef TRANSPARENT
1705     #if TINTING
1706     /* shading taken from eterm-0.9.2 */
1707     /* RGB 15 */
1708    
1709     static void
1710     shade_ximage_15(void *data, int bpl, int w, int h, int rm, int gm, int bm)
1711     {
1712     unsigned char *ptr;
1713     int x, y;
1714    
1715     ptr = (unsigned char *)data + (w * sizeof(uint16_t));
1716     if ((rm <= 256) && (gm <= 256) && (bm <= 256)) {
1717     /* No saturation */
1718     for (y = h; --y >= 0;) {
1719     for (x = -w; x < 0; x++) {
1720     int r, g, b;
1721    
1722     b = ((uint16_t *) ptr)[x];
1723     r = (b & 0x7c00) * rm;
1724     g = (b & 0x3e0) * gm;
1725     b = (b & 0x1f) * bm;
1726     ((uint16_t *) ptr)[x] = ((r >> 8) & 0x7c00)
1727     | ((g >> 8) & 0x3e0)
1728     | ((b >> 8) & 0x1f);
1729     }
1730     ptr += bpl;
1731     }
1732     } else {
1733     for (y = h; --y >= 0;) {
1734     for (x = -w; x < 0; x++) {
1735     int r, g, b;
1736    
1737     b = ((uint16_t *) ptr)[x];
1738     r = (b & 0x7c00) * rm;
1739     g = (b & 0x3e0) * gm;
1740     b = (b & 0x1f) * bm;
1741     r |= (!(r >> 15) - 1);
1742     g |= (!(g >> 10) - 1);
1743     b |= (!(b >> 5) - 1);
1744     ((uint16_t *) ptr)[x] = ((r >> 8) & 0x7c00)
1745     | ((g >> 8) & 0x3e0)
1746     | ((b >> 8) & 0x1f);
1747     }
1748     ptr += bpl;
1749     }
1750     }
1751     }
1752    
1753     /* RGB 16 */
1754     static void
1755     shade_ximage_16(void *data, int bpl, int w, int h, int rm, int gm, int bm)
1756     {
1757     unsigned char *ptr;
1758     int x, y;
1759    
1760     ptr = (unsigned char *)data + (w * sizeof(uint16_t));
1761     if ((rm <= 256) && (gm <= 256) && (bm <= 256)) {
1762     /* No saturation */
1763     for (y = h; --y >= 0;) {
1764     for (x = -w; x < 0; x++) {
1765     int r, g, b;
1766    
1767     b = ((uint16_t *) ptr)[x];
1768     r = (b & 0xf800) * rm;
1769     g = (b & 0x7e0) * gm;
1770     b = (b & 0x1f) * bm;
1771     ((uint16_t *) ptr)[x] = ((r >> 8) & 0xf800)
1772     | ((g >> 8) & 0x7e0)
1773     | ((b >> 8) & 0x1f);
1774     }
1775     ptr += bpl;
1776     }
1777     } else {
1778     for (y = h; --y >= 0;) {
1779     for (x = -w; x < 0; x++) {
1780     int r, g, b;
1781    
1782     b = ((uint16_t *) ptr)[x];
1783     r = (b & 0xf800) * rm;
1784     g = (b & 0x7e0) * gm;
1785     b = (b & 0x1f) * bm;
1786     r |= (!(r >> 16) - 1);
1787     g |= (!(g >> 11) - 1);
1788     b |= (!(b >> 5) - 1);
1789     ((uint16_t *) ptr)[x] = ((r >> 8) & 0xf800)
1790     | ((g >> 8) & 0x7e0)
1791     | ((b >> 8) & 0x1f);
1792     }
1793     ptr += bpl;
1794     }
1795     }
1796     }
1797    
1798     /* RGB 24 */
1799     static void
1800     shade_ximage_24(void *data, int bpl, int w, int h, int rm, int gm, int bm)
1801     {
1802     unsigned char *ptr;
1803     int x, y;
1804    
1805     ptr = (unsigned char *)data + (w * 3);
1806     if ((rm <= 256) && (gm <= 256) && (bm <= 256)) {
1807     /* No saturation */
1808     for (y = h; --y >= 0;) {
1809     for (x = -(w * 3); x < 0; x += 3) {
1810     int r, g, b;
1811    
1812     if (byteorder.big_endian()) {
1813     r = (ptr[x + 0] * rm) >> 8;
1814     g = (ptr[x + 1] * gm) >> 8;
1815     b = (ptr[x + 2] * bm) >> 8;
1816     ptr[x + 0] = r;
1817     ptr[x + 1] = g;
1818     ptr[x + 2] = b;
1819     } else {
1820     r = (ptr[x + 2] * rm) >> 8;
1821     g = (ptr[x + 1] * gm) >> 8;
1822     b = (ptr[x + 0] * bm) >> 8;
1823     ptr[x + 2] = r;
1824     ptr[x + 1] = g;
1825     ptr[x + 0] = b;
1826     }
1827     }
1828     ptr += bpl;
1829     }
1830     } else {
1831     for (y = h; --y >= 0;) {
1832     for (x = -(w * 3); x < 0; x += 3) {
1833     int r, g, b;
1834    
1835     if (byteorder.big_endian()) {
1836     r = (ptr[x + 0] * rm) >> 8;
1837     g = (ptr[x + 1] * gm) >> 8;
1838     b = (ptr[x + 2] * bm) >> 8;
1839    
1840     r |= (!(r >> 8) - 1);
1841     g |= (!(g >> 8) - 1);
1842     b |= (!(b >> 8) - 1);
1843    
1844     ptr[x + 0] = r;
1845     ptr[x + 1] = g;
1846     ptr[x + 2] = b;
1847     } else {
1848     r = (ptr[x + 2] * rm) >> 8;
1849     g = (ptr[x + 1] * gm) >> 8;
1850     b = (ptr[x + 0] * bm) >> 8;
1851    
1852     r |= (!(r >> 8) - 1);
1853     g |= (!(g >> 8) - 1);
1854     b |= (!(b >> 8) - 1);
1855    
1856     ptr[x + 2] = r;
1857     ptr[x + 1] = g;
1858     ptr[x + 0] = b;
1859     }
1860     }
1861     ptr += bpl;
1862     }
1863     }
1864     }
1865    
1866     /* RGB 32 */
1867     static void
1868     shade_ximage_32(void *data, int bpl, int w, int h, int rm, int gm, int bm)
1869     {
1870     unsigned char *ptr;
1871     int x, y;
1872    
1873     ptr = (unsigned char *)data + (w * 4);
1874     if ((rm <= 256) && (gm <= 256) && (bm <= 256)) {
1875     /* No saturation */
1876     for (y = h; --y >= 0;) {
1877     if (byteorder.big_endian()) {
1878     for (x = -(w * 4); x < 0; x += 4) {
1879     int r, g, b;
1880    
1881     r = (ptr[x + 1] * rm) >> 8;
1882     g = (ptr[x + 2] * gm) >> 8;
1883     b = (ptr[x + 3] * bm) >> 8;
1884     ptr[x + 1] = r;
1885     ptr[x + 2] = g;
1886     ptr[x + 3] = b;
1887     }
1888     } else {
1889     for (x = -(w * 4); x < 0; x += 4) {
1890     int r, g, b;
1891    
1892     r = (ptr[x + 2] * rm) >> 8;
1893     g = (ptr[x + 1] * gm) >> 8;
1894     b = (ptr[x + 0] * bm) >> 8;
1895     ptr[x + 2] = r;
1896     ptr[x + 1] = g;
1897     ptr[x + 0] = b;
1898     }
1899     }
1900     ptr += bpl;
1901     }
1902     } else {
1903     for (y = h; --y >= 0;) {
1904     for (x = -(w * 4); x < 0; x += 4) {
1905     int r, g, b;
1906    
1907     if (byteorder.big_endian()) {
1908     r = (ptr[x + 1] * rm) >> 8;
1909     g = (ptr[x + 2] * gm) >> 8;
1910     b = (ptr[x + 3] * bm) >> 8;
1911    
1912     r |= (!(r >> 8) - 1);
1913     g |= (!(g >> 8) - 1);
1914     b |= (!(b >> 8) - 1);
1915    
1916     ptr[x + 1] = r;
1917     ptr[x + 2] = g;
1918     ptr[x + 3] = b;
1919     } else {
1920     r = (ptr[x + 2] * rm) >> 8;
1921     g = (ptr[x + 1] * gm) >> 8;
1922     b = (ptr[x + 0] * bm) >> 8;
1923    
1924     r |= (!(r >> 8) - 1);
1925     g |= (!(g >> 8) - 1);
1926     b |= (!(b >> 8) - 1);
1927    
1928     ptr[x + 2] = r;
1929     ptr[x + 1] = g;
1930     ptr[x + 0] = b;
1931     }
1932     }
1933     ptr += bpl;
1934     }
1935     }
1936     }
1937    
1938     #endif
1939 pcg 1.1
1940     /*
1941     * Check our parents are still who we think they are.
1942     * Do transparency updates if required
1943     */
1944     int
1945 pcg 1.34 rxvt_term::check_our_parents ()
1946 pcg 1.1 {
1947 pcg 1.90 int i, pchanged, aformat, have_pixmap, rootdepth;
1948     unsigned long nitems, bytes_after;
1949     Atom atype;
1950     unsigned char *prop = NULL;
1951     Window root, oldp, *list;
1952     Pixmap rootpixmap = None;
1953 pcg 1.36 XWindowAttributes wattr, wrootattr;
1954    
1955     pchanged = 0;
1956    
1957 pcg 1.90 if (!(Options & Opt_transparent))
1958 pcg 1.36 return pchanged; /* Don't try any more */
1959    
1960 pcg 1.43 XGetWindowAttributes (display->display, display->root, &wrootattr);
1961 pcg 1.36 rootdepth = wrootattr.depth;
1962    
1963 pcg 1.43 XGetWindowAttributes (display->display, TermWin.parent[0], &wattr);
1964 pcg 1.90
1965 pcg 1.36 if (rootdepth != wattr.depth)
1966     {
1967     if (am_transparent)
1968     {
1969     pchanged = 1;
1970 pcg 1.90 XSetWindowBackground (display->display, TermWin.vt, PixColors[Color_bg]);
1971 pcg 1.36 am_transparent = am_pixmap_trans = 0;
1972     }
1973 pcg 1.90
1974 pcg 1.36 return pchanged; /* Don't try any more */
1975 pcg 1.1 }
1976    
1977 pcg 1.36 /* Get all X ops out of the queue so that our information is up-to-date. */
1978 pcg 1.43 XSync (display->display, False);
1979 pcg 1.1
1980 pcg 1.36 /*
1981     * Make the frame window set by the window manager have
1982     * the root background. Some window managers put multiple nested frame
1983     * windows for each client, so we have to take care about that.
1984     */
1985 pcg 1.90 i = (xa[XA_XROOTPMAPID]
1986     && XGetWindowProperty (display->display, display->root, xa[XA_XROOTPMAPID],
1987 pcg 1.36 0L, 1L, False, XA_PIXMAP, &atype, &aformat,
1988 pcg 1.90 &nitems, &bytes_after, &prop) == Success);
1989    
1990     if (!i || prop == NULL)
1991     i = (xa[XA_XSETROOTID]
1992     && XGetWindowProperty (display->display, display->root, xa[XA_XSETROOTID],
1993     0L, 1L, False, XA_PIXMAP, &atype, &aformat,
1994     &nitems, &bytes_after, &prop) == Success);
1995    
1996 pcg 1.36 if (!i || prop == NULL)
1997     have_pixmap = 0;
1998     else
1999     {
2000     have_pixmap = 1;
2001 pcg 1.43 rootpixmap = * ((Pixmap *)prop);
2002     XFree (prop);
2003 pcg 1.1 }
2004 pcg 1.90
2005 pcg 1.36 if (have_pixmap)
2006     {
2007     /*
2008 pcg 1.38 * Copy display->root pixmap transparency
2009 pcg 1.36 */
2010 pcg 1.67 int sx, sy, nx, ny;
2011     unsigned int nw, nh;
2012     Window cr;
2013     XImage *image;
2014     GC gc;
2015     XGCValues gcvalue;
2016 pcg 1.36
2017 pcg 1.43 XTranslateCoordinates (display->display, TermWin.parent[0], display->root,
2018 pcg 1.90 0, 0, &sx, &sy, &cr);
2019 pcg 1.36 nw = (unsigned int)szHint.width;
2020     nh = (unsigned int)szHint.height;
2021     nx = ny = 0;
2022 pcg 1.67
2023 pcg 1.36 if (sx < 0)
2024     {
2025     nw += sx;
2026     nx = -sx;
2027     sx = 0;
2028     }
2029 pcg 1.67
2030 pcg 1.36 if (sy < 0)
2031     {
2032     nh += sy;
2033     ny = -sy;
2034     sy = 0;
2035     }
2036 pcg 1.67
2037 pcg 1.43 MIN_IT (nw, (unsigned int) (wrootattr.width - sx));
2038     MIN_IT (nh, (unsigned int) (wrootattr.height - sy));
2039 pcg 1.36 allowedxerror = -1;
2040 pcg 1.90 image = XGetImage (display->display, rootpixmap, sx, sy, nw, nh, AllPlanes, ZPixmap);
2041    
2042 pcg 1.36 /* XXX: handle BadMatch - usually because we're outside the pixmap */
2043     /* XXX: may need a delay here? */
2044     allowedxerror = 0;
2045 pcg 1.90
2046 pcg 1.36 if (image == NULL)
2047     {
2048     if (am_transparent && am_pixmap_trans)
2049     {
2050     pchanged = 1;
2051     if (TermWin.pixmap != None)
2052     {
2053 pcg 1.43 XFreePixmap (display->display, TermWin.pixmap);
2054 pcg 1.36 TermWin.pixmap = None;
2055     }
2056     }
2057 pcg 1.90
2058 pcg 1.36 am_pixmap_trans = 0;
2059     }
2060     else
2061     {
2062     if (TermWin.pixmap != None)
2063 pcg 1.43 XFreePixmap (display->display, TermWin.pixmap);
2064 pcg 1.90
2065     #if TINTING
2066     if (ISSET_PIXCOLOR (Color_tint))
2067     {
2068     unsigned short shade, rm, gm, bm;
2069    
2070     PixColors[Color_tint].get (display, rm, gm, bm);
2071    
2072     rm >>= 8; gm >>= 8; bm >>= 8; // not 100% correct, but...
2073    
2074     /* Determine bitshift and bitmask values */
2075     switch (image->bits_per_pixel)
2076     {
2077     case 15: shade_ximage_15 (image->data, image->bytes_per_line, image->width, image->height, rm, gm, bm); break;
2078     case 16: shade_ximage_16 (image->data, image->bytes_per_line, image->width, image->height, rm, gm, bm); break;
2079     case 24: shade_ximage_24 (image->data, image->bytes_per_line, image->width, image->height, rm, gm, bm); break;
2080     case 32: shade_ximage_32 (image->data, image->bytes_per_line, image->width, image->height, rm, gm, bm); break;
2081     }
2082     }
2083     #endif
2084    
2085 pcg 1.43 TermWin.pixmap = XCreatePixmap (display->display, TermWin.vt,
2086 pcg 1.90 szHint.width, szHint.height, image->depth);
2087 pcg 1.43 gc = XCreateGC (display->display, TermWin.vt, 0UL, &gcvalue);
2088     XPutImage (display->display, TermWin.pixmap, gc, image, 0, 0,
2089 pcg 1.90 nx, ny, image->width, image->height);
2090 pcg 1.43 XFreeGC (display->display, gc);
2091     XDestroyImage (image);
2092     XSetWindowBackgroundPixmap (display->display, TermWin.vt,
2093 pcg 1.36 TermWin.pixmap);
2094 pcg 1.90
2095 pcg 1.36 if (!am_transparent || !am_pixmap_trans)
2096     pchanged = 1;
2097 pcg 1.90
2098 pcg 1.36 am_transparent = am_pixmap_trans = 1;
2099     }
2100 pcg 1.1 }
2101 pcg 1.67
2102 pcg 1.36 if (!am_pixmap_trans)
2103     {
2104 pcg 1.90 unsigned int n;
2105 pcg 1.36 /*
2106     * InheritPixmap transparency
2107     */
2108 pcg 1.43 D_X ((stderr, "InheritPixmap Seeking to %08lx", display->root));
2109 pcg 1.90 for (i = 1; i < (int) (sizeof (TermWin.parent) / sizeof (Window)); i++)
2110 pcg 1.36 {
2111     oldp = TermWin.parent[i];
2112 pcg 1.43 XQueryTree (display->display, TermWin.parent[i - 1], &root,
2113 pcg 1.90 &TermWin.parent[i], &list, &n);
2114 pcg 1.43 XFree (list);
2115     D_X ((stderr, "InheritPixmap Parent[%d] = %08lx", i, TermWin.parent[i]));
2116 pcg 1.90
2117 pcg 1.38 if (TermWin.parent[i] == display->root)
2118 pcg 1.36 {
2119     if (oldp != None)
2120     pchanged = 1;
2121 pcg 1.90
2122 pcg 1.36 break;
2123     }
2124 pcg 1.90
2125 pcg 1.36 if (oldp != TermWin.parent[i])
2126     pchanged = 1;
2127     }
2128 pcg 1.67
2129 pcg 1.36 n = 0;
2130 pcg 1.67
2131 pcg 1.36 if (pchanged)
2132     {
2133     for (; n < (unsigned int)i; n++)
2134     {
2135 pcg 1.43 XGetWindowAttributes (display->display, TermWin.parent[n], &wattr);
2136     D_X ((stderr, "InheritPixmap Checking Parent[%d]: %s", n, (wattr.depth == rootdepth && wattr.class != InputOnly) ? "OK" : "FAIL"));
2137 pcg 1.36 if (wattr.depth != rootdepth || wattr.c_class == InputOnly)
2138     {
2139 pcg 1.43 n = (int) (sizeof (TermWin.parent) / sizeof (Window)) + 1;
2140 pcg 1.36 break;
2141     }
2142     }
2143     }
2144 pcg 1.67
2145 pcg 1.90 if (n > (int) (sizeof (TermWin.parent) / sizeof (TermWin.parent[0])))
2146 pcg 1.36 {
2147 pcg 1.43 D_X ((stderr, "InheritPixmap Turning off"));
2148 pcg 1.90 XSetWindowBackground (display->display, TermWin.parent[0], PixColors[Color_fg]);
2149     XSetWindowBackground (display->display, TermWin.vt, PixColors[Color_bg]);
2150 pcg 1.36 am_transparent = 0;
2151     /* XXX: also turn off Opt_transparent? */
2152     }
2153     else
2154     {
2155 pcg 1.90 #if WAIT_FOR_WM
2156 pcg 1.36 /* wait (an arbitrary period) for the WM to do its thing
2157     * needed for fvwm2.2.2 (and before?) */
2158 pcg 1.43 sleep (1);
2159 pcg 1.90 #endif
2160 pcg 1.43 D_X ((stderr, "InheritPixmap Turning on (%d parents)", i - 1));
2161 pcg 1.36 for (n = 0; n < (unsigned int)i; n++)
2162 pcg 1.90 XSetWindowBackgroundPixmap (display->display, TermWin.parent[n], ParentRelative);
2163    
2164     XSetWindowBackgroundPixmap (display->display, TermWin.vt, ParentRelative);
2165 pcg 1.36 am_transparent = 1;
2166     }
2167 pcg 1.67
2168 pcg 1.43 for (; i < (int) (sizeof (TermWin.parent) / sizeof (Window)); i++)
2169 pcg 1.36 TermWin.parent[i] = None;
2170 pcg 1.1 }
2171 pcg 1.90
2172 pcg 1.36 return pchanged;
2173 pcg 1.1 }
2174     #endif
2175    
2176     /*}}} */
2177    
2178 pcg 1.81 bool
2179     rxvt_term::cmd_parse ()
2180     {
2181     bool flag = false;
2182     unicode_t ch = NOCHAR;
2183     unsigned char *seq_begin; // remember start of esc-sequence here
2184    
2185     for (;;)
2186     {
2187     if (ch == NOCHAR)
2188     {
2189     seq_begin = cmdbuf_ptr;
2190     ch = next_char ();
2191     }
2192    
2193     if (ch == NOCHAR) // TODO: improve
2194     break;
2195    
2196     if (!IS_CONTROL (ch) || ch == '\t' || ch == '\n' || ch == '\r')
2197     {
2198     /* Read a text string from the input buffer */
2199     unicode_t buf[UBUFSIZ];
2200     bool refreshnow = false;
2201     int nlines = 0;
2202     unicode_t *str = buf;
2203    
2204     *str++ = ch;
2205    
2206     for (;;)
2207     {
2208     seq_begin = cmdbuf_ptr;
2209     ch = next_char ();
2210    
2211     if (ch == NOCHAR || (IS_CONTROL (ch) && ch != '\t' && ch != '\n' && ch != '\r'))
2212     break;
2213    
2214     *str++ = ch;
2215    
2216     if (ch == '\n')
2217     {
2218     nlines++;
2219     refresh_count++;
2220    
2221     if (! (Options & Opt_jumpScroll)
2222     || (refresh_count >= (refresh_limit * (TermWin.nrow - 1))))
2223     {
2224     refreshnow = true;
2225     flag = true;
2226     ch = NOCHAR;
2227     break;
2228     }
2229    
2230     // scr_add_lines only works for nlines < TermWin.nrow - 1.
2231     if (nlines >= TermWin.nrow - 1)
2232     {
2233     scr_add_lines (buf, nlines, str - buf);
2234     nlines = 0;
2235     str = buf;
2236     }
2237     }
2238    
2239     if (str >= buf + UBUFSIZ)
2240     {
2241     ch = NOCHAR;
2242     break;
2243     }
2244     }
2245    
2246     scr_add_lines (buf, nlines, str - buf);
2247    
2248     /*
2249     * If there have been a lot of new lines, then update the screen
2250     * What the heck I'll cheat and only refresh less than every page-full.
2251     * the number of pages between refreshes is refresh_limit, which
2252     * is incremented here because we must be doing flat-out scrolling.
2253     *
2254     * refreshing should be correct for small scrolls, because of the
2255     * time-out
2256     */
2257     if (refreshnow)
2258     {
2259     if ((Options & Opt_jumpScroll) && refresh_limit < REFRESH_PERIOD)
2260     refresh_limit++;
2261    
2262     scr_refresh (refresh_type);
2263     }
2264    
2265     }
2266     else
2267     {
2268     try
2269     {
2270     process_nonprinting (ch);
2271     }
2272     catch (const class out_of_input &o)
2273     {
2274     // we ran out of input, retry later
2275     cmdbuf_ptr = seq_begin;
2276     break;
2277     }
2278    
2279     ch = NOCHAR;
2280     }
2281     }
2282    
2283     return flag;
2284     }
2285    
2286     // read the next character
2287     unicode_t
2288     rxvt_term::next_char ()
2289     {
2290     while (cmdbuf_ptr < cmdbuf_endp)
2291     {
2292     // assume 7-bit to be ascii ALWAYS
2293     if (*cmdbuf_ptr <= 0x7f && *cmdbuf_ptr != 0x1b)
2294     return *cmdbuf_ptr++;
2295    
2296     wchar_t wc;
2297     size_t len = mbrtowc (&wc, (char *)cmdbuf_ptr, cmdbuf_endp - cmdbuf_ptr, mbstate);
2298    
2299     if (len == (size_t)-2)
2300     {
2301     // the mbstate stores incomplete sequences. didn't know this :/
2302     cmdbuf_ptr = cmdbuf_endp;
2303     break;
2304     }
2305    
2306     if (len == (size_t)-1)
2307     return *cmdbuf_ptr++; // the _occasional_ latin1 character is allowed to slip through
2308    
2309     // assume wchar == unicode
2310     cmdbuf_ptr += len;
2311     return wc;
2312     }
2313    
2314     return NOCHAR;
2315     }
2316    
2317     /* rxvt_cmd_getc () - Return next input character */
2318     /*
2319     * Return the next input character after first passing any keyboard input
2320     * to the command.
2321     */
2322     unicode_t
2323     rxvt_term::cmd_getc ()
2324     {
2325     unicode_t c = next_char ();
2326    
2327     if (c == NOCHAR)
2328     throw out_of_input;
2329    
2330     return c;
2331     }
2332    
2333 pcg 1.1 /*{{{ print pipe */
2334     /*----------------------------------------------------------------------*/
2335     #ifdef PRINTPIPE
2336 pcg 1.34 FILE *
2337     rxvt_term::popen_printer ()
2338 pcg 1.1 {
2339 pcg 1.67 FILE *stream = popen (rs[Rs_print_pipe], "w");
2340 pcg 1.1
2341 pcg 1.36 if (stream == NULL)
2342 pcg 1.81 rxvt_warn ("can't open printer pipe, not printing.\n");
2343    
2344 pcg 1.36 return stream;
2345 pcg 1.1 }
2346    
2347     int
2348 pcg 1.34 rxvt_term::pclose_printer (FILE *stream)
2349 pcg 1.1 {
2350 pcg 1.11 fflush (stream);
2351     return pclose (stream);
2352 pcg 1.1 }
2353    
2354     /*
2355     * simulate attached vt100 printer
2356     */
2357     void
2358 pcg 1.34 rxvt_term::process_print_pipe ()
2359 pcg 1.1 {
2360 pcg 1.81 int done;
2361     FILE *fd;
2362 pcg 1.36
2363     if ((fd = popen_printer ()) == NULL)
2364     return;
2365    
2366     /*
2367     * Send all input to the printer until either ESC[4i or ESC[?4i
2368     * is received.
2369     */
2370     for (done = 0; !done;)
2371     {
2372 pcg 1.81 unsigned char buf[8];
2373     unicode_t ch;
2374     unsigned int i, len;
2375 pcg 1.1
2376 pcg 1.36 if ((ch = cmd_getc ()) != C0_ESC)
2377     {
2378 pcg 1.43 if (putc (ch, fd) == EOF)
2379 pcg 1.36 break; /* done = 1 */
2380     }
2381     else
2382     {
2383     len = 0;
2384     buf[len++] = ch;
2385 pcg 1.1
2386 pcg 1.36 if ((buf[len++] = cmd_getc ()) == '[')
2387     {
2388     if ((ch = cmd_getc ()) == '?')
2389     {
2390     buf[len++] = '?';
2391     ch = cmd_getc ();
2392     }
2393     if ((buf[len++] = ch) == '4')
2394     {
2395     if ((buf[len++] = cmd_getc ()) == 'i')
2396     break; /* done = 1 */
2397     }
2398     }
2399 pcg 1.81
2400 pcg 1.36 for (i = 0; i < len; i++)
2401 pcg 1.43 if (putc (buf[i], fd) == EOF)
2402 pcg 1.36 {
2403     done = 1;
2404     break;
2405     }
2406     }
2407 pcg 1.1 }
2408 pcg 1.81
2409 pcg 1.36 pclose_printer (fd);
2410 pcg 1.1 }
2411     #endif /* PRINTPIPE */
2412     /*}}} */
2413    
2414     /* *INDENT-OFF* */
2415     enum {
2416 pcg 1.36 C1_40 = 0x40,
2417 pcg 1.90 C1_41 , C1_BPH, C1_NBH, C1_44 , C1_NEL, C1_SSA, C1_ESA,
2418 pcg 1.36 C1_HTS, C1_HTJ, C1_VTS, C1_PLD, C1_PLU, C1_RI , C1_SS2, C1_SS3,
2419     C1_DCS, C1_PU1, C1_PU2, C1_STS, C1_CCH, C1_MW , C1_SPA, C1_EPA,
2420 pcg 1.90 C1_SOS, C1_59 , C1_SCI, C1_CSI, CS_ST , C1_OSC, C1_PM , C1_APC,
2421 pcg 1.1 };
2422     /* *INDENT-ON* */
2423    
2424     /*{{{ process non-printing single characters */
2425     void
2426 pcg 1.81 rxvt_term::process_nonprinting (unicode_t ch)
2427 pcg 1.1 {
2428 pcg 1.36 switch (ch)
2429     {
2430 pcg 1.81 case C0_ESC:
2431     process_escape_seq ();
2432     break;
2433 pcg 1.36 case C0_ENQ: /* terminal Status */
2434     if (rs[Rs_answerbackstring])
2435 pcg 1.90 tt_write ((const unsigned char *)rs[Rs_answerbackstring],
2436     (unsigned int)STRLEN (rs[Rs_answerbackstring]));
2437 pcg 1.36 else
2438 pcg 1.43 tt_write ((unsigned char *)VT100_ANS,
2439 pcg 1.90 (unsigned int)STRLEN (VT100_ANS));
2440 pcg 1.36 break;
2441     case C0_BEL: /* bell */
2442     scr_bell ();
2443     break;
2444     case C0_BS: /* backspace */
2445     scr_backspace ();
2446     break;
2447     case C0_HT: /* tab */
2448     scr_tab (1);
2449     break;
2450     case C0_CR: /* carriage return */
2451     scr_gotorc (0, 0, R_RELATIVE);
2452     break;
2453     case C0_VT: /* vertical tab, form feed */
2454     case C0_FF:
2455     case C0_LF: /* line feed */
2456     scr_index (UP);
2457     break;
2458     case C0_SO: /* shift out - acs */
2459     scr_charset_choose (1);
2460     break;
2461     case C0_SI: /* shift in - acs */
2462     scr_charset_choose (0);
2463     break;
2464 pcg 1.81
2465     // 8-bit controls
2466     case 0x90: /* DCS */
2467     process_dcs_seq ();
2468     break;
2469     case 0x9b: /* CSI */
2470     process_csi_seq ();
2471     break;
2472     case 0x9d: /* CSI */
2473     process_osc_seq ();
2474     break;
2475 pcg 1.1 }
2476     }
2477     /*}}} */
2478    
2479    
2480     /*{{{ process VT52 escape sequences */
2481     void
2482 pcg 1.81 rxvt_term::process_escape_vt52 (unicode_t ch)
2483 pcg 1.1 {
2484 pcg 1.36 int row, col;
2485    
2486     switch (ch)
2487     {
2488     case 'A': /* cursor up */
2489     scr_gotorc (-1, 0, R_RELATIVE | C_RELATIVE);
2490     break;
2491     case 'B': /* cursor down */
2492     scr_gotorc (1, 0, R_RELATIVE | C_RELATIVE);
2493     break;
2494     case 'C': /* cursor right */
2495     scr_gotorc (0, 1, R_RELATIVE | C_RELATIVE);
2496     break;
2497     case 'D': /* cursor left */
2498     scr_gotorc (0, -1, R_RELATIVE | C_RELATIVE);
2499     break;
2500     case 'H': /* cursor home */
2501     scr_gotorc (0, 0, 0);
2502     break;
2503     case 'I': /* cursor up and scroll down if needed */
2504     scr_index (DN);
2505     break;
2506     case 'J': /* erase to end of screen */
2507     scr_erase_screen (0);
2508     break;
2509     case 'K': /* erase to end of line */
2510     scr_erase_line (0);
2511     break;
2512     case 'Y': /* move to specified row and col */
2513     /* full command is 'ESC Y row col' where row and col
2514     * are encoded by adding 32 and sending the ascii
2515     * character. eg. SPACE = 0, '+' = 13, '0' = 18,
2516     * etc. */
2517     row = cmd_getc () - ' ';
2518     col = cmd_getc () - ' ';
2519     scr_gotorc (row, col, 0);
2520     break;
2521     case 'Z': /* identify the terminal type */
2522 pcg 1.43 tt_printf ("\033/Z"); /* I am a VT100 emulating a VT52 */
2523 pcg 1.1 break;
2524 pcg 1.36 case '<': /* turn off VT52 mode */
2525 pcg 1.43 PrivMode (0, PrivMode_vt52);
2526 pcg 1.36 break;
2527     case 'F': /* use special graphics character set */
2528     case 'G': /* use regular character set */
2529     /* unimplemented */
2530     break;
2531     case '=': /* use alternate keypad mode */
2532     case '>': /* use regular keypad mode */
2533     /* unimplemented */
2534     break;
2535 pcg 1.1 }
2536     }
2537     /*}}} */
2538    
2539    
2540     /*{{{ process escape sequences */
2541     void
2542 pcg 1.34 rxvt_term::process_escape_seq ()
2543 pcg 1.1 {
2544 pcg 1.81 unicode_t ch = cmd_getc ();
2545 pcg 1.36
2546     if (PrivateModes & PrivMode_vt52)
2547     {
2548     process_escape_vt52 (ch);
2549     return;
2550     }
2551 pcg 1.1
2552 pcg 1.36 switch (ch)
2553     {
2554     /* case 1: do_tek_mode (); break; */
2555     case '#':
2556     if (cmd_getc () == '8')
2557     scr_E ();
2558     break;
2559 pcg 1.44 case '(':
2560 pcg 1.36 scr_charset_set (0, (unsigned int)cmd_getc ());
2561     break;
2562     case ')':
2563     scr_charset_set (1, (unsigned int)cmd_getc ());
2564     break;
2565     case '*':
2566     scr_charset_set (2, (unsigned int)cmd_getc ());
2567     break;
2568     case '+':
2569     scr_charset_set (3, (unsigned int)cmd_getc ());
2570     break;
2571 pcg 1.1 #ifndef NO_FRILLS
2572 pcg 1.36 case '6':
2573     scr_backindex ();
2574     break;
2575     #endif
2576     case '7':
2577     scr_cursor (SAVE);
2578     break;
2579     case '8':
2580     scr_cursor (RESTORE);
2581     break;
2582 pcg 1.1 #ifndef NO_FRILLS
2583 pcg 1.36 case '9':
2584     scr_forwardindex ();
2585     break;
2586     #endif
2587     case '=':
2588     case '>':
2589 pcg 1.43 PrivMode ((ch == '='), PrivMode_aplKP);
2590 pcg 1.36 break;
2591    
2592     case C1_40:
2593     cmd_getc ();
2594     break;
2595     case C1_44:
2596     scr_index (UP);
2597     break;
2598 pcg 1.1
2599 pcg 1.36 /* 8.3.87: NEXT LINE */
2600     case C1_NEL: /* ESC E */
2601 pcg 1.1 {
2602 pcg 1.73 unicode_t nlcr[] = { L'\n', L'\r' };
2603 pcg 1.34 scr_add_lines (nlcr, 1, 2);
2604 pcg 1.1 }
2605 pcg 1.36 break;
2606    
2607     /* kidnapped escape sequence: Should be 8.3.48 */
2608     case C1_ESA: /* ESC G */
2609     process_graphics ();
2610     break;
2611    
2612     /* 8.3.63: CHARACTER TABULATION SET */
2613     case C1_HTS: /* ESC H */
2614     scr_set_tab (1);
2615     break;
2616    
2617     /* 8.3.105: REVERSE LINE FEED */
2618     case C1_RI: /* ESC M */
2619     scr_index (DN);
2620     break;
2621    
2622     /* 8.3.142: SINGLE-SHIFT TWO */
2623 pcg 1.90 /*case C1_SS2: scr_single_shift (2); break; */
2624 pcg 1.36
2625     /* 8.3.143: SINGLE-SHIFT THREE */
2626 pcg 1.90 /*case C1_SS3: scr_single_shift (3); break; */
2627 pcg 1.36
2628     /* 8.3.27: DEVICE CONTROL STRING */
2629     case C1_DCS: /* ESC P */
2630     process_dcs_seq ();
2631     break;
2632    
2633     /* 8.3.110: SINGLE CHARACTER INTRODUCER */
2634     case C1_SCI: /* ESC Z */
2635 pcg 1.43 tt_write ((const unsigned char *)ESCZ_ANSWER,
2636     (unsigned int) (sizeof (ESCZ_ANSWER) - 1));
2637 pcg 1.36 break; /* steal obsolete ESC [ c */
2638    
2639     /* 8.3.16: CONTROL SEQUENCE INTRODUCER */
2640     case C1_CSI: /* ESC [ */
2641     process_csi_seq ();
2642     break;
2643 pcg 1.1
2644 pcg 1.36 /* 8.3.90: OPERATING SYSTEM COMMAND */
2645     case C1_OSC: /* ESC ] */
2646     process_osc_seq ();
2647     break;
2648    
2649     /* 8.3.106: RESET TO INITIAL STATE */
2650     case 'c':
2651 pcg 1.90 mbstate.reset ();
2652 pcg 1.36 scr_poweron ();
2653     scrollbar_show (1);
2654     break;
2655    
2656     /* 8.3.79: LOCKING-SHIFT TWO (see ISO2022) */
2657     case 'n':
2658     scr_charset_choose (2);
2659     break;
2660    
2661     /* 8.3.81: LOCKING-SHIFT THREE (see ISO2022) */
2662     case 'o':
2663     scr_charset_choose (3);
2664     break;
2665 pcg 1.1 }
2666     }
2667     /*}}} */
2668    
2669     /*{{{ process CONTROL SEQUENCE INTRODUCER (CSI) sequences `ESC[' */
2670     /* *INDENT-OFF* */
2671     enum {
2672 pcg 1.36 CSI_ICH = 0x40,
2673     CSI_CUU, CSI_CUD, CSI_CUF, CSI_CUB, CSI_CNL, CSI_CPL, CSI_CHA,
2674     CSI_CUP, CSI_CHT, CSI_ED , CSI_EL , CSI_IL , CSI_DL , CSI_EF , CSI_EA ,
2675     CSI_DCH, CSI_SEE, CSI_CPR, CSI_SU , CSI_SD , CSI_NP , CSI_PP , CSI_CTC,
2676     CSI_ECH, CSI_CVT, CSI_CBT, CSI_SRS, CSI_PTX, CSI_SDS, CSI_SIMD, CSI_5F,
2677     CSI_HPA, CSI_HPR, CSI_REP, CSI_DA , CSI_VPA, CSI_VPR, CSI_HVP, CSI_TBC,
2678     CSI_SM , CSI_MC , CSI_HPB, CSI_VPB, CSI_RM , CSI_SGR, CSI_DSR, CSI_DAQ,
2679     CSI_70 , CSI_71 , CSI_72 , CSI_73 , CSI_74 , CSI_75 , CSI_76 , CSI_77 ,
2680     CSI_78 , CSI_79 , CSI_7A , CSI_7B , CSI_7C , CSI_7D , CSI_7E , CSI_7F
2681 pcg 1.1 };
2682    
2683     #define make_byte(b7,b6,b5,b4,b3,b2,b1,b0) \
2684     (((b7) << 7) | ((b6) << 6) | ((b5) << 5) | ((b4) << 4) \
2685     | ((b3) << 3) | ((b2) << 2) | ((b1) << 1) | (b0))
2686     #define get_byte_array_bit(array, bit) \
2687 pcg 1.43 (!! ((array)[ (bit) / 8] & (128 >> ((bit) & 7))))
2688 pcg 1.1
2689 pcg 1.36 const unsigned char csi_defaults[] =
2690     {
2691 pcg 1.43 make_byte (1,1,1,1,1,1,1,1), /* @, A, B, C, D, E, F, G, */
2692     make_byte (1,1,0,0,1,1,0,0), /* H, I, J, K, L, M, N, O, */
2693     make_byte (1,0,1,1,1,1,1,0), /* P, Q, R, S, T, U, V, W, */
2694     make_byte (1,1,1,0,0,0,1,0), /* X, Y, Z, [, \, ], ^, _, */
2695     make_byte (1,1,1,0,1,1,1,0), /* `, a, b, c, d, e, f, g, */
2696     make_byte (0,0,1,1,0,0,0,0), /* h, i, j, k, l, m, n, o, */
2697     make_byte (0,0,0,0,0,0,0,0), /* p, q, r, s, t, u, v, w, */
2698 pcg 1.90 make_byte (0,0,0,0,0,0,0,0), /* x, y, z, {, |, }, ~, */
2699 pcg 1.36 };
2700 pcg 1.1 /* *INDENT-ON* */
2701    
2702     void
2703 pcg 1.34 rxvt_term::process_csi_seq ()
2704 pcg 1.1 {
2705 pcg 1.81 unicode_t ch, priv, i;
2706     unsigned int nargs, p;
2707     int n, ndef;
2708     int arg[ESC_ARGS];
2709 pcg 1.36
2710     for (nargs = ESC_ARGS; nargs > 0;)
2711     arg[--nargs] = 0;
2712    
2713     priv = 0;
2714     ch = cmd_getc ();
2715     if (ch >= '<' && ch <= '?')
2716     { /* '<' '=' '>' '?' */
2717     priv = ch;
2718     ch = cmd_getc ();
2719     }
2720 pcg 1.81
2721 pcg 1.36 /* read any numerical arguments */
2722     for (n = -1; ch < CSI_ICH; )
2723     {
2724 pcg 1.43 if (isdigit (ch))
2725 pcg 1.36 {
2726     if (n < 0)
2727     n = ch - '0';
2728     else
2729     n = n * 10 + ch - '0';
2730     }
2731     else if (ch == ';')
2732     {
2733     if (nargs < ESC_ARGS)
2734     arg[nargs++] = n;
2735     n = -1;
2736     }
2737 pcg 1.81 else if (IS_CONTROL (ch))
2738     process_nonprinting (ch);
2739    
2740 pcg 1.36 ch = cmd_getc ();
2741     }
2742 pcg 1.1
2743 pcg 1.36 if (ch > CSI_7F)
2744     return;
2745 pcg 1.1
2746 pcg 1.36 if (nargs < ESC_ARGS)
2747     arg[nargs++] = n;
2748    
2749     i = ch - CSI_ICH;
2750 pcg 1.43 ndef = get_byte_array_bit (csi_defaults, i);
2751 pcg 1.36 for (p = 0; p < nargs; p++)
2752     if (arg[p] == -1)
2753     arg[p] = ndef;
2754 pcg 1.1
2755     #ifdef DEBUG_CMD
2756 pcg 1.43 fprintf (stderr, "CSI ");
2757 pcg 1.36 for (p = 0; p < nargs; p++)
2758 pcg 1.43 fprintf (stderr, "%d%s", arg[p], p < nargs - 1 ? ";" : "");
2759     fprintf (stderr, "%c\n", ch);
2760 pcg 1.1 #endif
2761    
2762 pcg 1.36 /*
2763     * private mode handling
2764     */
2765     if (priv)
2766     {
2767     switch (priv)
2768     {
2769     case '>':
2770     if (ch == CSI_DA) /* secondary device attributes */
2771 pcg 1.43 tt_printf ("\033[>%d;%-.8s;0c", 'R', VSTRING);
2772 pcg 1.36 break;
2773     case '?':
2774     if (ch == 'h' || ch == 'l' || ch == 'r' || ch == 's' || ch == 't')
2775     process_terminal_mode (ch, priv, nargs, arg);
2776     break;
2777     }
2778     return;
2779 pcg 1.1 }
2780    
2781 pcg 1.36 switch (ch)
2782     {
2783     /*
2784 pcg 1.43 * ISO/IEC 6429:1992 (E) CSI sequences (defaults in parentheses)
2785 pcg 1.36 */
2786 pcg 1.1 #ifdef PRINTPIPE
2787 pcg 1.36 case CSI_MC: /* 8.3.83: (0) MEDIA COPY */
2788     switch (arg[0])
2789     {
2790     case 0: /* initiate transfer to primary aux device */
2791     scr_printscreen (0);
2792     break;
2793     case 5: /* start relay to primary aux device */
2794     process_print_pipe ();
2795     break;
2796     }
2797     break;
2798     #endif
2799 pcg 1.1
2800 pcg 1.36 case CSI_CUU: /* 8.3.22: (1) CURSOR UP */
2801     case CSI_VPR: /* 8.3.161: (1) LINE POSITION FORWARD */
2802     arg[0] = -arg[0];
2803     /* FALLTHROUGH */
2804     case CSI_CUD: /* 8.3.19: (1) CURSOR DOWN */
2805     case CSI_VPB: /* 8.3.160: (1) LINE POSITION BACKWARD */
2806     scr_gotorc (arg[0], 0, RELATIVE);
2807     break;
2808    
2809     case CSI_CUB: /* 8.3.18: (1) CURSOR LEFT */
2810     case CSI_HPB: /* 8.3.59: (1) CHARACTER POSITION BACKWARD */
2811 pcg 1.1 #ifdef ISO6429
2812 pcg 1.36 arg[0] = -arg[0];
2813 pcg 1.1 #else /* emulate common DEC VTs */
2814 pcg 1.36 arg[0] = arg[0] ? -arg[0] : -1;
2815 pcg 1.1 #endif
2816 pcg 1.36 /* FALLTHROUGH */
2817     case CSI_CUF: /* 8.3.20: (1) CURSOR RIGHT */
2818     case CSI_HPR: /* 8.3.60: (1) CHARACTER POSITION FORWARD */
2819 pcg 1.1 #ifdef ISO6429
2820 pcg 1.36 scr_gotorc (0, arg[0], RELATIVE);
2821 pcg 1.1 #else /* emulate common DEC VTs */
2822 pcg 1.36 scr_gotorc (0, arg[0] ? arg[0] : 1, RELATIVE);
2823 pcg 1.1 #endif
2824 pcg 1.36 break;
2825    
2826     case CSI_CPL: /* 8.3.13: (1) CURSOR PRECEDING LINE */
2827     arg[0] = -arg[0];
2828     /* FALLTHROUGH */
2829     case CSI_CNL: /* 8.3.12: (1) CURSOR NEXT LINE */
2830     scr_gotorc (arg[0], 0, R_RELATIVE);
2831     break;
2832    
2833     case CSI_CHA: /* 8.3.9: (1) CURSOR CHARACTER ABSOLUTE */
2834     case CSI_HPA: /* 8.3.58: (1) CURSOR POSITION ABSOLUTE */
2835     scr_gotorc (0, arg[0] - 1, R_RELATIVE);
2836     break;
2837    
2838     case CSI_VPA: /* 8.3.159: (1) LINE POSITION ABSOLUTE */
2839     scr_gotorc (arg[0] - 1, 0, C_RELATIVE);
2840     break;
2841    
2842     case CSI_CUP: /* 8.3.21: (1,1) CURSOR POSITION */
2843     case CSI_HVP: /* 8.3.64: (1,1) CHARACTER AND LINE POSITION */
2844     scr_gotorc (arg[0] - 1, nargs < 2 ? 0 : (arg[1] - 1), 0);
2845     break;
2846 pcg 1.1
2847 pcg 1.36 case CSI_CBT: /* 8.3.7: (1) CURSOR BACKWARD TABULATION */
2848     arg[0] = -arg[0];
2849     /* FALLTHROUGH */
2850     case CSI_CHT: /* 8.3.10: (1) CURSOR FORWARD TABULATION */
2851     scr_tab (arg[0]);
2852     break;
2853    
2854     case CSI_ED: /* 8.3.40: (0) ERASE IN PAGE */
2855     scr_erase_screen (arg[0]);
2856     break;
2857    
2858     case CSI_EL: /* 8.3.42: (0) ERASE IN LINE */
2859     scr_erase_line (arg[0]);
2860     break;
2861    
2862     case CSI_ICH: /* 8.3.65: (1) INSERT CHARACTER */
2863     scr_insdel_chars (arg[0], INSERT);
2864     break;
2865    
2866     case CSI_IL: /* 8.3.68: (1) INSERT LINE */
2867     scr_insdel_lines (arg[0], INSERT);
2868     break;
2869    
2870     case CSI_DL: /* 8.3.33: (1) DELETE LINE */
2871     scr_insdel_lines (arg[0], DELETE);
2872     break;
2873    
2874     case CSI_ECH: /* 8.3.39: (1) ERASE CHARACTER */
2875     scr_insdel_chars (arg[0], ERASE);
2876     break;
2877    
2878     case CSI_DCH: /* 8.3.26: (1) DELETE CHARACTER */
2879     scr_insdel_chars (arg[0], DELETE);
2880     break;
2881    
2882     case CSI_SD: /* 8.3.114: (1) SCROLL DOWN */
2883     arg[0] = -arg[0];
2884     /* FALLTHROUGH */
2885     case CSI_SU: /* 8.3.148: (1) SCROLL UP */
2886     scr_scroll_text (screen.tscroll, screen.bscroll, arg[0], 0);
2887     break;
2888    
2889     case CSI_DA: /* 8.3.24: (0) DEVICE ATTRIBUTES */
2890 pcg 1.43 tt_write ((const unsigned char *)VT100_ANS,
2891     (unsigned int) (sizeof (VT100_ANS) - 1));
2892 pcg 1.36 break;
2893    
2894     case CSI_SGR: /* 8.3.118: (0) SELECT GRAPHIC RENDITION */
2895     process_sgr_mode (nargs, arg);
2896     break;
2897    
2898     case CSI_DSR: /* 8.3.36: (0) DEVICE STATUS REPORT */
2899     switch (arg[0])
2900     {
2901     case 5: /* DSR requested */
2902 pcg 1.43 tt_printf ("\033[0n");
2903 pcg 1.36 break;
2904     case 6: /* CPR requested */
2905     scr_report_position ();
2906     break;
2907     case 7: /* unofficial extension */
2908 pcg 1.90 if (Options & Opt_insecure)
2909     tt_printf ("%-.250s\n", rs[Rs_display_name]);
2910 pcg 1.36 break;
2911     case 8: /* unofficial extension */
2912 pcg 1.90 process_xterm_seq (XTerm_title, RESNAME "-" VERSION, CHAR_ST);
2913 pcg 1.36 break;
2914     }
2915     break;
2916 pcg 1.1
2917 pcg 1.36 case CSI_TBC: /* 8.3.155: (0) TABULATION CLEAR */
2918     switch (arg[0])
2919     {
2920     case 0: /* char tab stop cleared at active position */
2921     scr_set_tab (0);
2922     break;
2923     /* case 1: */ /* line tab stop cleared in active line */
2924     /* case 2: */ /* char tab stops cleared in active line */
2925     case 3: /* all char tab stops are cleared */
2926     /* case 4: */ /* all line tab stops are cleared */
2927     case 5: /* all tab stops are cleared */
2928     scr_set_tab (-1);
2929     break;
2930     }
2931     break;
2932    
2933     case CSI_CTC: /* 8.3.17: (0) CURSOR TABULATION CONTROL */
2934     switch (arg[0])
2935     {
2936     case 0: /* char tab stop set at active position */
2937     scr_set_tab (1);
2938     break; /* = ESC H */
2939     /* case 1: */ /* line tab stop set at active line */
2940     case 2: /* char tab stop cleared at active position */
2941     scr_set_tab (0);
2942     break; /* = ESC [ 0 g */
2943     /* case 3: */ /* line tab stop cleared at active line */
2944     /* case 4: */ /* char tab stops cleared at active line */
2945     case 5: /* all char tab stops are cleared */
2946     scr_set_tab (-1);
2947     break; /* = ESC [ 3 g */
2948     /* case 6: */ /* all line tab stops are cleared */
2949     }
2950     break;
2951    
2952     case CSI_RM: /* 8.3.107: RESET MODE */
2953     if (arg[0] == 4)
2954     scr_insert_mode (0);
2955     break;
2956    
2957     case CSI_SM: /* 8.3.126: SET MODE */
2958     if (arg[0] == 4)
2959     scr_insert_mode (1);
2960     break;
2961    
2962     /*
2963     * PRIVATE USE beyond this point. All CSI_7? sequences here
2964     */
2965     case CSI_72: /* DECSTBM: set top and bottom margins */
2966     if (nargs == 1)
2967     scr_scroll_region (arg[0] - 1, MAX_ROWS - 1);
2968     else if (nargs == 0 || arg[0] >= arg[1])
2969     scr_scroll_region (0, MAX_ROWS - 1);
2970     else
2971     scr_scroll_region (arg[0] - 1, arg[1] - 1);
2972     break;
2973    
2974     case CSI_73:
2975     scr_cursor (SAVE);
2976     break;
2977     case CSI_75:
2978     scr_cursor (RESTORE);
2979     break;
2980 pcg 1.1
2981     #ifndef NO_FRILLS
2982 pcg 1.36 case CSI_74:
2983     process_window_ops (arg, nargs);
2984     break;
2985 pcg 1.1 #endif
2986    
2987 pcg 1.36 case CSI_78: /* DECREQTPARM */
2988     if (arg[0] == 0 || arg[0] == 1)
2989 pcg 1.43 tt_printf ("\033[%d;1;1;128;128;1;0x", arg[0] + 2);
2990 pcg 1.81 break;
2991 pcg 1.1
2992 pcg 1.36 default:
2993     break;
2994 pcg 1.1 }
2995     }
2996     /*}}} */
2997    
2998     #ifndef NO_FRILLS
2999     /* ARGSUSED */
3000     void
3001 pcg 1.34 rxvt_term::process_window_ops (const int *args, unsigned int nargs)
3002 pcg 1.1 {
3003 pcg 1.81 int x, y;
3004 pcg 1.36 XWindowAttributes wattr;
3005 pcg 1.81 Window wdummy;
3006 pcg 1.1
3007 pcg 1.36 if (nargs == 0)
3008     return;
3009 pcg 1.81
3010 pcg 1.36 switch (args[0])
3011     {
3012 pcg 1.81 /*
3013     * commands
3014     */
3015 pcg 1.36 case 1: /* deiconify window */
3016 pcg 1.43 XMapWindow (display->display, TermWin.parent[0]);
3017 pcg 1.36 break;
3018     case 2: /* iconify window */
3019 pcg 1.43 XIconifyWindow (display->display, TermWin.parent[0],
3020     DefaultScreen (display->display));
3021 pcg 1.36 break;
3022     case 3: /* set position (pixels) */
3023 pcg 1.43 XMoveWindow (display->display, TermWin.parent[0], args[1], args[2]);
3024 pcg 1.36 break;
3025     case 4: /* set size (pixels) */
3026     set_widthheight ((unsigned int)args[2], (unsigned int)args[1]);
3027     break;
3028     case 5: /* raise window */
3029 pcg 1.43 XRaiseWindow (display->display, TermWin.parent[0]);
3030 pcg 1.36 break;
3031     case 6: /* lower window */
3032 pcg 1.43 XLowerWindow (display->display, TermWin.parent[0]);
3033 pcg 1.36 break;
3034     case 7: /* refresh window */
3035     scr_touch (true);
3036     break;
3037     case 8: /* set size (chars) */
3038 pcg 1.43 set_widthheight ((unsigned int) (args[2] * TermWin.fwidth),
3039     (unsigned int) (args[1] * TermWin.fheight));
3040 pcg 1.36 break;
3041 pcg 1.81
3042     //case 9: NYI, TODO, restore maximized window or maximize window
3043 pcg 1.36 default:
3044     if (args[0] >= 24) /* set height (chars) */
3045     set_widthheight ((unsigned int)TermWin.width,
3046 pcg 1.43 (unsigned int) (args[1] * TermWin.fheight));
3047 pcg 1.36 break;
3048 pcg 1.81
3049    
3050     /*
3051     * reports - some output format copied from XTerm
3052     */
3053 pcg 1.36 case 11: /* report window state */
3054 pcg 1.43 XGetWindowAttributes (display->display, TermWin.parent[0], &wattr);
3055     tt_printf ("\033[%dt", wattr.map_state == IsViewable ? 1 : 2);
3056 pcg 1.36 break;
3057     case 13: /* report window position */
3058 pcg 1.43 XGetWindowAttributes (display->display, TermWin.parent[0], &wattr);
3059     XTranslateCoordinates (display->display, TermWin.parent[0], wattr.root,
3060 pcg 1.90 -wattr.border_width, -wattr.border_width,
3061     &x, &y, &wdummy);
3062 pcg 1.43 tt_printf ("\033[3;%d;%dt", x, y);
3063 pcg 1.36 break;
3064     case 14: /* report window size (pixels) */
3065 pcg 1.43 XGetWindowAttributes (display->display, TermWin.parent[0], &wattr);
3066     tt_printf ("\033[4;%d;%dt", wattr.height, wattr.width);
3067 pcg 1.36 break;
3068 pcg 1.81 case 18: /* report text area size (chars) */
3069 pcg 1.43 tt_printf ("\033[8;%d;%dt", TermWin.nrow, TermWin.ncol);
3070 pcg 1.36 break;
3071 pcg 1.81 case 19: /* report window size (chars) */
3072     tt_printf ("\033[9;%d;%dt", TermWin.nrow, TermWin.ncol);
3073     break;
3074 pcg 1.36 case 20: /* report icon label */
3075 pcg 1.90 if (Options & Opt_insecure)
3076     {
3077     char *s;
3078     XGetIconName (display->display, TermWin.parent[0], &s);
3079     tt_printf ("\033]L%-.200s\234", s ? s : ""); /* 8bit ST */
3080     }
3081 pcg 1.36 break;
3082     case 21: /* report window title */
3083 pcg 1.90 if (Options & Opt_insecure)
3084     {
3085     char *s;
3086     XFetchName (display->display, TermWin.parent[0], &s);
3087     tt_printf ("\033]l%-.200s\234", s ? s : ""); /* 8bit ST */
3088     }
3089 pcg 1.36 break;
3090 pcg 1.1 }
3091     }
3092     #endif
3093    
3094     /*----------------------------------------------------------------------*/
3095     /*
3096     * get input up until STRING TERMINATOR (or BEL)
3097 pcg 1.81 * ends_how is terminator used. returned input must be free ()d
3098 pcg 1.1 */
3099 pcg 1.81 unsigned char *
3100     rxvt_term::get_to_st (unicode_t &ends_how)
3101 pcg 1.1 {
3102 pcg 1.81 int seen_esc = 0; /* seen escape? */
3103     unsigned int n = 0;
3104     unsigned char *s;
3105     unicode_t ch;
3106     unsigned char string[STRING_MAX];
3107 pcg 1.36
3108 pcg 1.81 while ((ch = cmd_getc ()))
3109 pcg 1.36 {
3110 pcg 1.90 if (ch == C0_BEL || ch == CHAR_ST)
3111 pcg 1.36 break;
3112 pcg 1.81
3113 pcg 1.90 if (seen_esc)
3114     if (ch == 0x5c) /* 7bit ST */
3115     break;
3116     else
3117     return NULL;
3118    
3119 pcg 1.36 if (ch == C0_ESC)
3120     {
3121     seen_esc = 1;
3122     continue;
3123     }
3124     else if (ch == '\t')
3125     ch = ' '; /* translate '\t' to space */
3126 pcg 1.90 else if (ch < 0x20 && (ch != 0x0a && ch != 0x0d))
3127 pcg 1.36 return NULL; /* other control character - exit */
3128 pcg 1.81
3129 pcg 1.90 if (n >= sizeof (string) - 1)
3130     // stop at some sane length
3131     return NULL;
3132 pcg 1.81
3133 pcg 1.90 string[n++] = ch;
3134 pcg 1.36 seen_esc = 0;
3135     }
3136 pcg 1.81
3137 pcg 1.36 string[n++] = '\0';
3138 pcg 1.81
3139 pcg 1.43 if ((s = (unsigned char *)rxvt_malloc (n)) == NULL)
3140 pcg 1.36 return NULL;
3141 pcg 1.81
3142     ends_how = (ch == 0x5c ? C0_ESC : ch);
3143 pcg 1.43 STRNCPY (s, string, n);
3144 pcg 1.36 return s;
3145 pcg 1.1 }
3146    
3147     /*----------------------------------------------------------------------*/
3148     /*
3149     * process DEVICE CONTROL STRING `ESC P ... (ST|BEL)' or `0x90 ... (ST|BEL)'
3150     */
3151     void
3152 pcg 1.34 rxvt_term::process_dcs_seq ()
3153 pcg 1.1 {
3154 pcg 1.81 unsigned char *s;
3155     unicode_t eh;
3156    
3157 pcg 1.36 /*
3158     * Not handled yet
3159     */
3160 pcg 1.81 s = get_to_st (eh);
3161 pcg 1.36 if (s)
3162 pcg 1.43 free (s);
3163 pcg 1.81
3164 pcg 1.36 return;
3165 pcg 1.1 }
3166    
3167     /*----------------------------------------------------------------------*/
3168     /*
3169     * process OPERATING SYSTEM COMMAND sequence `ESC ] Ps ; Pt (ST|BEL)'
3170     */
3171     void
3172 pcg 1.34 rxvt_term::process_osc_seq ()
3173 pcg 1.1 {
3174 pcg 1.81 unicode_t ch, eh;
3175     int arg;
3176 pcg 1.1
3177 pcg 1.36 ch = cmd_getc ();
3178 pcg 1.43 for (arg = 0; isdigit (ch); ch = cmd_getc ())
3179 pcg 1.36 arg = arg * 10 + (ch - '0');
3180 pcg 1.1
3181 pcg 1.36 if (ch == ';')
3182     {
3183 pcg 1.81 unsigned char *s = get_to_st (eh);
3184    
3185 pcg 1.36 if (s)
3186     {
3187 pcg 1.90 process_xterm_seq (arg, (char *)s, eh);
3188     free (s);
3189     }
3190     }
3191     }
3192 pcg 1.81
3193 pcg 1.90 void
3194     rxvt_term::process_color_seq (int report, int color, const char *str, unsigned char resp)
3195     {
3196     if (str[0] == '?' && !str[1])
3197     {
3198     if (Options & Opt_insecure)
3199     {
3200     unsigned short r, g, b;
3201     PixColors[color].get (display, r, g, b);
3202     tt_printf ("\033]%d;rgb:%04x/%04x/%04x%c", report, r, g, b, resp);
3203 pcg 1.36 }
3204 pcg 1.1 }
3205 pcg 1.90 else
3206     set_window_color (color, str);
3207 pcg 1.1 }
3208 pcg 1.90
3209 pcg 1.1 /*
3210     * XTerm escape sequences: ESC ] Ps;Pt (ST|BEL)
3211     * 0 = change iconName/title
3212     * 1 = change iconName
3213     * 2 = change title
3214     * 4 = change color
3215 pcg 1.90 * 10 = change fg color
3216     * 11 = change bg color
3217 pcg 1.1 * 12 = change text color
3218     * 13 = change mouse foreground color
3219     * 17 = change highlight character colour
3220     * 18 = change bold character color
3221     * 19 = change underlined character color
3222     * 46 = change logfile (not implemented)
3223     * 50 = change font
3224     *
3225     * rxvt extensions:
3226     * 20 = bg pixmap
3227     * 39 = change default fg color
3228     * 49 = change default bg color
3229     * 55 = dump scrollback buffer and all of screen
3230 pcg 1.67 * 701 = change locale
3231     * 702 = find font
3232 pcg 1.90 * 703 = menu
3233 pcg 1.1 */
3234     void
3235 pcg 1.90 rxvt_term::process_xterm_seq (int op, const char *str, unsigned char resp)
3236 pcg 1.1 {
3237 pcg 1.81 int changed = 0;
3238     int color;
3239     char *buf, *name;
3240 pcg 1.90 bool query = str[0] == '?' && !str[1];
3241 pcg 1.36
3242 pcg 1.43 assert (str != NULL);
3243 pcg 1.36 switch (op)
3244     {
3245     case XTerm_name:
3246     set_title (str);
3247     /* FALLTHROUGH */
3248     case XTerm_iconName:
3249 pcg 1.81 set_icon_name (str);
3250 pcg 1.36 break;
3251     case XTerm_title:
3252     set_title (str);
3253     break;
3254 pcg 1.90 case XTerm_property:
3255     if (str[0] == '?')
3256     {
3257     Atom prop = XInternAtom (display->display, str + 1, True);
3258     Atom actual_type;
3259     int actual_format;
3260     unsigned long nitems;
3261     unsigned long bytes_after;
3262     unsigned char *value = 0;
3263     const char *str = "";
3264    
3265     if (prop
3266     && XGetWindowProperty (display->display, TermWin.parent[0],
3267     prop, 0, 1<<16, 0, AnyPropertyType,
3268     &actual_type, &actual_format,
3269     &nitems, &bytes_after, &value) == Success
3270     && actual_type != None
3271     && actual_format == 8)
3272     str = (const char *)(value);
3273    
3274     tt_printf ("\033]%d;%s%c", XTerm_property, str, resp);
3275    
3276     XFree (value);
3277     }
3278     else
3279     {
3280     char *eq = strchr (str, '='); // constness lost, but verified to be ok
3281    
3282     if (eq)
3283     {
3284     *eq = 0;
3285     XChangeProperty (display->display, TermWin.parent[0],
3286     display->atom (str), XA_STRING, 8,
3287     PropModeReplace, (unsigned char *)eq + 1,
3288     strlen (eq + 1));
3289     }
3290     else
3291     XDeleteProperty (display->display, TermWin.parent[0],
3292     display->atom (str));
3293     }
3294     break;
3295    
3296 pcg 1.36 case XTerm_Color:
3297     for (buf = (char *)str; buf && *buf;)
3298     {
3299 pcg 1.43 if ((name = STRCHR (buf, ';')) == NULL)
3300 pcg 1.36 break;
3301 pcg 1.81
3302 pcg 1.36 *name++ = '\0';
3303 pcg 1.43 color = atoi (buf);
3304 pcg 1.81
3305 pcg 1.36 if (color < 0 || color >= TOTAL_COLORS)
3306     break;
3307 pcg 1.81
3308 pcg 1.43 if ((buf = STRCHR (name, ';')) != NULL)
3309 pcg 1.36 *buf++ = '\0';
3310 pcg 1.81
3311 pcg 1.90 if (name[0] == '?' && !name[1])
3312     {
3313     if (Options & Opt_insecure)
3314     {
3315     unsigned short r, g, b;
3316     PixColors[color + minCOLOR].get (display, r, g, b);
3317     tt_printf ("\033]%d;%d;rgb:%04x/%04x/%04x%c", XTerm_Color, color, r, g, b, resp);
3318     }
3319     }
3320     else
3321     set_window_color (color + minCOLOR, name);
3322 pcg 1.36 }
3323     break;
3324 pcg 1.90 case XTerm_Color00:
3325     process_color_seq (XTerm_Color00, Color_fg, str, resp);
3326     break;
3327     case XTerm_Color01:
3328     process_color_seq (XTerm_Color00, Color_bg, str, resp);
3329     break;
3330 pcg 1.1 #ifndef NO_CURSORCOLOR
3331 pcg 1.36 case XTerm_Color_cursor:
3332 pcg 1.90 process_color_seq (XTerm_Color_cursor, Color_cursor, str, resp);
3333 pcg 1.36 break;
3334     #endif
3335 pcg 1.90 case XTerm_Color_pointer_fg:
3336     process_color_seq (XTerm_Color_pointer_fg, Color_pointer_fg, str, resp);
3337     break;
3338     case XTerm_Color_pointer_bg:
3339     process_color_seq (XTerm_Color_pointer_bg, Color_pointer_bg, str, resp);
3340 pcg 1.36 break;
3341 pcg 1.1 #ifndef NO_BOLD_UNDERLINE_REVERSE
3342 pcg 1.36 case XTerm_Color_BD:
3343 pcg 1.90 process_color_seq (XTerm_Color_BD, Color_BD, str, resp);
3344 pcg 1.36 break;
3345     case XTerm_Color_UL:
3346 pcg 1.90 process_color_seq (XTerm_Color_UL, Color_UL, str, resp);
3347 pcg 1.36 break;
3348     case XTerm_Color_RV:
3349 pcg 1.90 process_color_seq (XTerm_Color_RV, Color_RV, str, resp);
3350 pcg 1.36 break;
3351 pcg 1.1 #endif
3352    
3353 pcg 1.36 case XTerm_Pixmap:
3354     if (*str != ';')
3355     {
3356 pcg 1.1 #if XPM_BACKGROUND
3357 pcg 1.36 scale_pixmap (""); /* reset to default scaling */
3358     set_bgPixmap (str); /* change pixmap */
3359 pcg 1.1 #endif
3360 pcg 1.36 scr_touch (true);
3361     }
3362 pcg 1.43 while ((str = STRCHR (str, ';')) != NULL)
3363 pcg 1.36 {
3364     str++;
3365 pcg 1.1 #if XPM_BACKGROUND
3366 pcg 1.36 changed += scale_pixmap (str);
3367 pcg 1.1 #endif
3368 pcg 1.36
3369     }
3370     if (changed)
3371     {
3372 pcg 1.1 #ifdef XPM_BACKGROUND
3373 pcg 1.36 resize_pixmap ();
3374 pcg 1.1 #endif
3375 pcg 1.36 scr_touch (true);
3376     }
3377     break;
3378    
3379     case XTerm_restoreFG:
3380     set_window_color (Color_fg, str);
3381     break;
3382     case XTerm_restoreBG:
3383     set_window_color (Color_bg, str);
3384     break;
3385 pcg 1.90
3386 pcg 1.36 case XTerm_logfile:
3387 pcg 1.81 // TODO, when secure mode?
3388 pcg 1.36 break;
3389 pcg 1.90
3390 pcg 1.36 case XTerm_font:
3391 pcg 1.90 if (query)
3392     {
3393     if (Options & Opt_insecure)
3394     tt_printf ("\33]%d;%-.250s%c", XTerm_font,
3395     TermWin.fontset->fontdesc
3396     ? TermWin.fontset->fontdesc
3397     : "",
3398     resp);
3399     }
3400     else
3401     change_font (str);
3402 pcg 1.51 break;
3403 pcg 1.90
3404 pcg 1.60 #ifndef NO_FRILLS
3405 pcg 1.51 case XTerm_locale:
3406 pcg 1.90 if (query)
3407     {
3408     if (Options & Opt_insecure)
3409     tt_printf ("\33]%d;%-.250s%c", XTerm_locale, locale, resp);
3410     }
3411 pcg 1.54 else
3412     {
3413     set_locale (str);
3414 pcg 1.60 # ifdef USE_XIM
3415 pcg 1.54 im_cb ();
3416 pcg 1.60 # endif
3417 pcg 1.54 }
3418 pcg 1.36 break;
3419 pcg 1.90
3420 pcg 1.67 case XTerm_findfont:
3421 pcg 1.90 if (Options & Opt_insecure)
3422     {
3423     int fid = TermWin.fontset->find_font (atoi (str));
3424     tt_printf ("\33]%d;%d;%-.250s%c", XTerm_findfont,
3425     fid, (*TermWin.fontset)[fid]->name, resp);
3426     }
3427 pcg 1.67 break;
3428 pcg 1.60 #endif
3429 pcg 1.90
3430     #ifdef MENUBAR
3431     case XTerm_Menu:
3432     if (Options & Opt_insecure)
3433     menubar_dispatch (const_cast<char *>(str)); // casting away constness is checked
3434     break;
3435     #endif
3436 pcg 1.1 #if 0
3437 pcg 1.36 case XTerm_dumpscreen: /* no error notices */
3438     {
3439 pcg 1.90 int fd;
3440 pcg 1.43 if ((fd = open (str, O_RDWR | O_CREAT | O_EXCL, 0600)) >= 0)
3441 pcg 1.36 {
3442     scr_dump (fd);
3443 pcg 1.43 close (fd);
3444 pcg 1.36 }
3445     }
3446     break;
3447 pcg 1.1 #endif
3448     }
3449     }
3450     /*----------------------------------------------------------------------*/
3451    
3452     /*{{{ process DEC private mode sequences `ESC [ ? Ps mode' */
3453     /*
3454     * mode can only have the following values:
3455     * 'l' = low
3456     * 'h' = high
3457     * 's' = save
3458     * 'r' = restore
3459     * 't' = toggle
3460     * so no need for fancy checking
3461     */
3462     int
3463 pcg 1.34 rxvt_term::privcases (int mode, unsigned long bit)
3464 pcg 1.1 {
3465 pcg 1.81 int state;
3466 pcg 1.1
3467 pcg 1.36 if (mode == 's')
3468     {
3469     SavedModes |= (PrivateModes & bit);
3470     return -1;
3471 pcg 1.1 }
3472 pcg 1.36 else
3473     {
3474     if (mode == 'r')
3475     state = (SavedModes & bit) ? 1 : 0; /* no overlapping */
3476     else
3477 pcg 1.43 state = (mode == 't') ? ! (PrivateModes & bit) : mode;
3478     PrivMode (state, bit);
3479 pcg 1.36 }
3480 pcg 1.81
3481 pcg 1.36 return state;
3482 pcg 1.1 }
3483    
3484     /* we're not using priv _yet_ */
3485     void
3486 pcg 1.43 rxvt_term::process_terminal_mode (int mode, int priv __attribute__ ((unused)), unsigned int nargs, const int *arg)
3487 pcg 1.1 {
3488 pcg 1.81 unsigned int i, j;
3489     int state;
3490    
3491 pcg 1.36 static const struct
3492     {
3493     const int argval;
3494     const unsigned long bit;
3495     }
3496 pcg 1.81
3497 pcg 1.36 argtopriv[] = {
3498     { 1, PrivMode_aplCUR },
3499     { 2, PrivMode_vt52 },
3500     { 3, PrivMode_132 },
3501     { 4, PrivMode_smoothScroll },
3502     { 5, PrivMode_rVideo },
3503     { 6, PrivMode_relOrigin },
3504     { 7, PrivMode_Autowrap },
3505     { 9, PrivMode_MouseX10 },
3506 pcg 1.1 #ifdef menuBar_esc
3507 pcg 1.36 { menuBar_esc, PrivMode_menuBar },
3508 pcg 1.1 #endif
3509     #ifdef scrollBar_esc
3510 pcg 1.36 { scrollBar_esc, PrivMode_scrollBar },
3511 pcg 1.1 #endif
3512 pcg 1.73 // 18, 19 printing-related
3513 pcg 1.36 { 25, PrivMode_VisibleCursor },
3514 pcg 1.73 // 30 show scrollbar rxvt. extension
3515     { 35, PrivMode_ShiftKeys }, // rxvt extension
3516 pcg 1.36 { 40, PrivMode_132OK },
3517 pcg 1.73 // 41 xterm more fixes NYI
3518     // 45 margin bell NYI
3519     // 46 start logging
3520 pcg 1.36 { 47, PrivMode_Screen },
3521     { 66, PrivMode_aplKP },
3522 pcg 1.1 #ifndef NO_BACKSPACE_KEY
3523 pcg 1.36 { 67, PrivMode_BackSpace },
3524 pcg 1.1 #endif
3525 pcg 1.36 { 1000, PrivMode_MouseX11 },
3526 pcg 1.73 // 1001 Use Hilite Mouse Tracking. NYI, TODO
3527     // 1002 Use Cell Motion Mouse Tracking. NYI, TODO
3528     // 1003 Use All Motion Mouse Tracking. NYI, TODO
3529     { 1010, PrivMode_TtyOutputInh }, // rxvt extension
3530     { 1011, PrivMode_Keypress }, // rxvt extension
3531     // 1035 enable modifiers for alt, numlock NYI
3532     // 1036 send ESC for meta keys NYI
3533     // 1037 send DEL for keypad delete NYI
3534 pcg 1.36 { 1047, PrivMode_Screen },
3535 pcg 1.73 // 1048 save and restore cursor
3536 pcg 1.90 { 1049, PrivMode_Screen }, /* xterm extension, clear screen on ti rather than te */
3537 pcg 1.73 // 1051, 1052, 1060, 1061 keyboard emulation NYI
3538 pcg 1.36 };
3539    
3540     if (nargs == 0)
3541     return;
3542    
3543     /* make lo/hi boolean */
3544     if (mode == 'l')
3545     mode = 0; /* reset */
3546     else if (mode == 'h')
3547     mode = 1; /* set */
3548    
3549     for (i = 0; i < nargs; i++)
3550     {
3551     state = -1;
3552    
3553     /* basic handling */
3554 pcg 1.43 for (j = 0; j < (sizeof (argtopriv)/sizeof (argtopriv[0])); j++)
3555 pcg 1.36 if (argtopriv[j].argval == arg[i])
3556     {
3557     state = privcases (mode, argtopriv[j].bit);
3558     break;
3559     }
3560 pcg 1.1
3561 pcg 1.36 /* extra handling for values with state unkept */
3562 pcg 1.73 switch (arg[i])
3563     {
3564     case 1048: /* alternative cursor save */
3565 pcg 1.90 if (Options & Opt_secondaryScreen)
3566     if (mode == 0)
3567     scr_cursor (RESTORE);
3568     else if (mode == 1)
3569     scr_cursor (SAVE);
3570     break;
3571 pcg 1.73 }
3572    
3573     if (state >= 0)
3574     /* extra handling for values with valid 0 or 1 state */
3575 pcg 1.36 switch (arg[i])
3576     {
3577 pcg 1.73 /* case 1: - application cursor keys */
3578     case 2: /* VT52 mode */
3579     /* oddball mode. should be set regardless of set/reset
3580     * parameter. Return from VT52 mode with an ESC < from
3581     * within VT52 mode
3582     */
3583     PrivMode (1, PrivMode_vt52);
3584     break;
3585     case 3: /* 80/132 */
3586     if (PrivateModes & PrivMode_132OK)
3587     set_widthheight (((state ? 132 : 80) * TermWin.fwidth), TermWin.height);
3588     break;
3589     case 4: /* smooth scrolling */
3590     if (state)
3591     Options &= ~Opt_jumpScroll;
3592     else
3593     Options |= Opt_jumpScroll;
3594     break;
3595     case 5: /* reverse video */
3596     scr_rvideo_mode (state);
3597     break;
3598     case 6: /* relative/absolute origins */
3599     scr_relative_origin (state);
3600     break;
3601     case 7: /* autowrap */
3602     scr_autowrap (state);
3603     break;
3604 pcg 1.90 /* case 8: - auto repeat, can't do on a per window basis */
3605 pcg 1.73 case 9: /* X10 mouse reporting */
3606     if (state) /* orthogonal */
3607 pcg 1.81 PrivateModes &= ~PrivMode_MouseX11;
3608 pcg 1.73 break;
3609 pcg 1.1 #ifdef menuBar_esc
3610 pcg 1.73 case menuBar_esc:
3611 pcg 1.1 #ifdef MENUBAR
3612 pcg 1.73 map_menuBar (state);
3613 pcg 1.1 #endif
3614 pcg 1.73 break;
3615 pcg 1.1 #endif
3616     #ifdef scrollBar_esc
3617 pcg 1.73 case scrollBar_esc:
3618     if (scrollbar_mapping (state))
3619     {
3620     resize_all_windows (0, 0, 0);
3621     scr_touch (true);
3622     }
3623     break;
3624 pcg 1.1 #endif
3625 pcg 1.73 case 25: /* visible/invisible cursor */
3626     scr_cursor_visible (state);
3627     break;
3628 pcg 1.90 /* case 35: - shift keys */
3629     /* case 40: - 80 <--> 132 mode */
3630 pcg 1.73 case 47: /* secondary screen */
3631     scr_change_screen (state);
3632     break;
3633 pcg 1.90 /* case 66: - application key pad */
3634     /* case 67: - backspace key */
3635 pcg 1.73 case 1000: /* X11 mouse reporting */
3636     if (state) /* orthogonal */
3637 pcg 1.81 PrivateModes &= ~PrivMode_MouseX10;
3638 pcg 1.73 break;
3639 pcg 1.1 #if 0
3640 pcg 1.73 case 1001:
3641     break; /* X11 mouse highlighting */
3642 pcg 1.1 #endif
3643 pcg 1.73 case 1010: /* scroll to bottom on TTY output inhibit */
3644     if (state)
3645     Options &= ~Opt_scrollTtyOutput;
3646     else
3647     Options |= Opt_scrollTtyOutput;
3648     break;
3649     case 1011: /* scroll to bottom on key press */
3650     if (state)
3651     Options |= Opt_scrollTtyKeypress;
3652     else
3653     Options &= ~Opt_scrollTtyKeypress;
3654     break;
3655 pcg 1.90 case 1047: /* secondary screen w/ clearing last */
3656     if (Options & Opt_secondaryScreen)
3657     if (current_screen != PRIMARY)
3658     scr_erase_screen (2);
3659     scr_change_screen (state);
3660     break;
3661     case 1049: /* secondary screen w/ clearing first */
3662 pcg 1.73 scr_change_screen (state);
3663 pcg 1.90 if (Options & Opt_secondaryScreen)
3664     if (current_screen != PRIMARY)
3665     scr_erase_screen (2);
3666     break;
3667 pcg 1.73 default:
3668     break;
3669     }
3670 pcg 1.1 }
3671     }
3672     /*}}} */
3673    
3674     /*{{{ process sgr sequences */
3675     void
3676 pcg 1.34 rxvt_term::process_sgr_mode (unsigned int nargs, const int *arg)
3677 pcg 1.1 {
3678 pcg 1.81 unsigned int i;
3679     short rendset;
3680     int rendstyle;
3681 pcg 1.36
3682     if (nargs == 0)
3683     {
3684     scr_rendition (0, ~RS_None);
3685     return;
3686     }
3687 pcg 1.81
3688 pcg 1.36 for (i = 0; i < nargs; i++)
3689     {
3690     rendset = -1;
3691     switch (arg[i])
3692     {
3693     case 0:
3694     rendset = 0, rendstyle = ~RS_None;
3695     break;
3696     case 1:
3697     rendset = 1, rendstyle = RS_Bold;
3698     break;
3699     case 4:
3700     rendset = 1, rendstyle = RS_Uline;
3701     break;
3702     case 5:
3703     rendset = 1, rendstyle = RS_Blink;
3704     break;
3705     case 7:
3706     rendset = 1, rendstyle = RS_RVid;
3707     break;
3708 pcg 1.73 case 8:
3709     // invisible. NYI
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     /*{{{ process Rob Nation's own graphics mode sequences */
3813     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