ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/rxvt-unicode/src/command.C
Revision: 1.131
Committed: Fri Aug 13 22:38:57 2004 UTC (19 years, 8 months ago) by root
Content type: text/plain
Branch: MAIN
CVS Tags: rel-3_6
Changes since 1.120: +233 -74 lines
Log Message:
*** empty log message ***

File Contents

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