ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/rxvt-unicode/src/command.C
(Generate patch)

Comparing rxvt-unicode/src/command.C (file contents):
Revision 1.73 by pcg, Mon Mar 15 00:08:11 2004 UTC vs.
Revision 1.202 by root, Sat Mar 12 23:35:14 2005 UTC

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

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines