ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/rxvt-unicode/src/main.C
Revision: 1.31
Committed: Fri Feb 13 12:11:05 2004 UTC (20 years, 3 months ago) by pcg
Content type: text/plain
Branch: MAIN
Changes since 1.30: +2 -0 lines
Log Message:
*** empty log message ***

File Contents

# User Rev Content
1 pcg 1.1 /*--------------------------------*-C-*---------------------------------*
2 pcg 1.3 * File: main.c
3 pcg 1.1 *----------------------------------------------------------------------*
4     *
5     * All portions of code are copyright by their respective author/s.
6     * Copyright (c) 1992 John Bovey, University of Kent at Canterbury <jdb@ukc.ac.uk>
7 pcg 1.3 * - original version
8 pcg 1.1 * Copyright (c) 1994 Robert Nation <nation@rocket.sanders.lockheed.com>
9 pcg 1.3 * - extensive modifications
10 pcg 1.1 * Copyright (c) 1995 Garrett D'Amore <garrett@netcom.com>
11     * Copyright (c) 1997 mj olesen <olesen@me.QueensU.CA>
12 pcg 1.3 * - extensive modifications
13 pcg 1.1 * Copyright (c) 1997,1998 Oezguer Kesim <kesim@math.fu-berlin.de>
14     * Copyright (c) 1998-2001 Geoff Wing <gcw@pobox.com>
15 pcg 1.3 * - extensive modifications
16 pcg 1.1 *
17     * This program is free software; you can redistribute it and/or modify
18     * it under the terms of the GNU General Public License as published by
19     * the Free Software Foundation; either version 2 of the License, or
20     * (at your option) any later version.
21     *
22     * This program is distributed in the hope that it will be useful,
23     * but WITHOUT ANY WARRANTY; without even the implied warranty of
24     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
25     * GNU General Public License for more details.
26     *
27     * You should have received a copy of the GNU General Public License
28     * along with this program; if not, write to the Free Software
29     * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
30     *---------------------------------------------------------------------*/
31    
32 pcg 1.3 #include "../config.h" /* NECESSARY */
33     #include "rxvt.h" /* NECESSARY */
34     #include "main.intpro" /* PROTOS for internal routines */
35 pcg 1.1
36     #include <signal.h>
37    
38     #ifdef TTY_GID_SUPPORT
39     # include <grp.h>
40     #endif
41    
42     #ifdef HAVE_TERMIOS_H
43     # include <termios.h>
44     #endif
45    
46 pcg 1.15 #include <cstring>
47    
48     static char curlocale[128];
49    
50     void
51     rxvt_set_locale (const char *locale)
52     {
53 pcg 1.16 if (locale && STRNCMP (locale, curlocale, 128))
54 pcg 1.15 {
55 pcg 1.16 STRNCPY (curlocale, locale, 128);
56 pcg 1.15 setlocale (LC_CTYPE, curlocale);
57     }
58     }
59    
60 pcg 1.3 void *
61     rxvt_term::operator new (size_t s)
62     {
63     void *p = malloc (s);
64    
65     MEMSET (p, 0, s);
66     return p;
67     }
68    
69     void
70     rxvt_term::operator delete (void *p, size_t s)
71     {
72     free (p);
73     }
74    
75 pcg 1.4 rxvt_term::rxvt_term ()
76 pcg 1.26 :
77 pcg 1.27 rootwin_ev (this, &rxvt_term::rootwin_cb),
78     termwin_ev (this, &rxvt_term::x_cb),
79     vt_ev (this, &rxvt_term::x_cb),
80     #ifdef HAVE_SCROLLBARS
81     scrollbar_ev (this, &rxvt_term::x_cb),
82     #endif
83     #ifdef MENUBAR
84     menubar_ev (this, &rxvt_term::x_cb), fixme
85     #endif
86 pcg 1.5 #ifdef CURSOR_BLINK
87 pcg 1.26 cursor_blink_ev (this, &rxvt_term::cursor_blink_cb),
88 pcg 1.21 #endif
89     #ifdef TEXT_BLINK
90 pcg 1.26 text_blink_ev (this, &rxvt_term::text_blink_cb),
91 pcg 1.5 #endif
92 pcg 1.6 #ifdef POINTER_BLANK
93 pcg 1.26 pointer_ev (this, &rxvt_term::pointer_cb),
94 pcg 1.6 #endif
95 pcg 1.26 check_ev (this, &rxvt_term::check_cb),
96     destroy_ev (this, &rxvt_term::destroy_cb),
97     pty_ev (this, &rxvt_term::pty_cb),
98 pcg 1.29 incr_ev (this, &rxvt_term::incr_cb),
99     #ifdef USE_XIM
100     im_ev (this, &rxvt_term::im_cb)
101     #endif
102 pcg 1.4 {
103     cmdbuf_ptr = cmdbuf_endp = cmdbuf_base;
104     }
105    
106     rxvt_term::~rxvt_term ()
107     {
108 pcg 1.29 if (cmd_fd >= 0)
109     close (cmd_fd);
110    
111 pcg 1.13 scr_release ();
112 pcg 1.8
113 pcg 1.14 free (locale);
114 pcg 1.15 free (codeset);
115    
116 pcg 1.8 #ifndef NO_SETOWNER_TTYDEV
117 pcg 1.22 privileged_ttydev (RESTORE);
118 pcg 1.8 #endif
119     #ifdef UTMP_SUPPORT
120 pcg 1.22 privileged_utmp (RESTORE);
121 pcg 1.8 #endif
122 pcg 1.27
123     // TODO: free pixcolours, colours should become part of rxvt_display
124    
125     delete PixColors;
126 pcg 1.31 delete TermWin.fontset;
127 pcg 1.27
128 pcg 1.29 displays.put (display);
129 pcg 1.4 }
130    
131 pcg 1.8 void
132     rxvt_term::destroy ()
133     {
134 pcg 1.27 if (display)
135     {
136 pcg 1.29 if (TermWin.parent[0])
137     XDestroyWindow (display->display, TermWin.parent[0]);
138    
139 pcg 1.31 rootwin_ev.stop (display);
140 pcg 1.27 termwin_ev.stop (display);
141     vt_ev.stop (display);
142 pcg 1.29
143     #ifdef USE_XIM
144     im_destroy ();
145     im_ev.stop (display);
146     #endif
147 pcg 1.27 #ifdef HAVE_SCROLLBARS
148     scrollbar_ev.stop (display);
149     #endif
150     #ifdef MENUBAR
151     menubar_ev.stop (display);
152     #endif
153     }
154    
155 pcg 1.9 check_ev.stop ();
156 pcg 1.8 pty_ev.stop ();
157     #ifdef CURSOR_BLINK
158 pcg 1.21 cursor_blink_ev.stop ();
159     #endif
160     #ifdef TEXT_BLINK
161     text_blink_ev.stop ();
162 pcg 1.8 #endif
163     #ifdef POINTER_BLANK
164     pointer_ev.stop ();
165     #endif
166    
167     destroy_ev.start (0);
168     }
169    
170     void
171     rxvt_term::destroy_cb (time_watcher &w)
172     {
173     SET_R (this);
174    
175     delete this;
176     }
177    
178 pcg 1.1 /*----------------------------------------------------------------------*/
179     /* rxvt_init() */
180     /* LIBPROTO */
181 pcg 1.3 rxvt_t
182 pcg 1.9 rxvt_init (int argc, const char *const *argv)
183 pcg 1.1 {
184 pcg 1.9 SET_R (new rxvt_term);
185 pcg 1.1
186 pcg 1.22 if (!GET_R->init_vars () || !GET_R->init (argc, argv))
187 pcg 1.3 {
188 pcg 1.22 delete GET_R;
189     SET_R (0);
190 pcg 1.1 }
191    
192 pcg 1.22 return GET_R;
193 pcg 1.4 }
194    
195 pcg 1.27 static int (*old_xerror_handler)(Display *dpy, XErrorEvent *event);
196    
197 pcg 1.8 void
198     rxvt_init_signals ()
199     {
200 pcg 1.26 /* install exit handler for cleanup */
201 pcg 1.8 #if 0
202     #ifdef HAVE_ATEXIT
203     atexit(rxvt_clean_exit);
204     #else
205     #endif
206     #endif
207    
208     struct sigaction sa;
209    
210     sigfillset (&sa.sa_mask);
211     sa.sa_flags = SA_NOCLDSTOP | SA_RESTART;
212 pcg 1.9 sa.sa_handler = SIG_IGN; sigaction (SIGHUP , &sa, 0);
213     sa.sa_handler = SIG_IGN; sigaction (SIGPIPE, &sa, 0);
214 pcg 1.8 sa.sa_handler = rxvt_Exit_signal; sigaction (SIGINT , &sa, 0);
215     sa.sa_handler = rxvt_Exit_signal; sigaction (SIGQUIT, &sa, 0);
216     sa.sa_handler = rxvt_Exit_signal; sigaction (SIGTERM, &sa, 0);
217     sa.sa_handler = rxvt_Child_signal; sigaction (SIGCHLD, &sa, 0);
218    
219 pcg 1.26 /* need to trap SIGURG for SVR4 (Unixware) rlogin */
220     /* signal (SIGURG, SIG_DFL); */
221 pcg 1.8
222 pcg 1.27 old_xerror_handler = XSetErrorHandler ((XErrorHandler) rxvt_xerror_handler);
223 pcg 1.8 //XSetIOErrorHandler ((XErrorHandler) rxvt_xioerror_handler);
224     }
225    
226 pcg 1.4 bool
227     rxvt_term::init (int argc, const char *const *argv)
228     {
229     /*
230     * Save and then give up any super-user privileges
231     * If we need privileges in any area then we must specifically request it.
232     * We should only need to be root in these cases:
233     * 1. write utmp entries on some systems
234     * 2. chown tty on some systems
235     */
236 pcg 1.22 privileges (SAVE);
237     privileges (IGNORE);
238 pcg 1.1
239 pcg 1.15 init_secondary ();
240 pcg 1.1
241 pcg 1.15 const char **cmd_argv = init_resources (argc, argv);
242 pcg 1.3
243 pcg 1.16 set_locale ("");
244    
245 pcg 1.1 #if (MENUBAR_MAX)
246 pcg 1.22 menubar_read (rs[Rs_menu]);
247 pcg 1.1 #endif
248     #ifdef HAVE_SCROLLBARS
249 pcg 1.4 if (Options & Opt_scrollBar)
250 pcg 1.15 scrollBar.setIdle (); /* set existence for size calculations */
251 pcg 1.1 #endif
252    
253 pcg 1.17 create_windows (argc, argv);
254 pcg 1.1
255 pcg 1.15 init_xlocale ();
256 pcg 1.1
257 pcg 1.13 scr_reset (); /* initialize screen */
258 pcg 1.1 #ifdef RXVT_GRAPHICS
259 pcg 1.22 Gr_reset (); /* reset graphics */
260 pcg 1.1 #endif
261    
262     #if 0
263     #ifdef DEBUG_X
264 pcg 1.27 XSynchronize(display->display, True);
265 pcg 1.1 #endif
266     #endif
267    
268     #ifdef HAVE_SCROLLBARS
269 pcg 1.4 if (Options & Opt_scrollBar)
270 pcg 1.17 resize_scrollbar (); /* create and map scrollbar */
271 pcg 1.1 #endif
272     #if (MENUBAR_MAX)
273 pcg 1.4 if (menubar_visible(r))
274 pcg 1.27 XMapWindow (display->display, menuBar.win);
275 pcg 1.1 #endif
276     #ifdef TRANSPARENT
277 pcg 1.4 if (Options & Opt_transparent)
278     {
279 pcg 1.27 XSelectInput (display->display, display->root, PropertyChangeMask);
280 pcg 1.22 check_our_parents ();
281 pcg 1.4 }
282 pcg 1.1 #endif
283 pcg 1.28
284     rootwin_ev.start (display, display->root);
285    
286 pcg 1.27 XMapWindow (display->display, TermWin.vt);
287     XMapWindow (display->display, TermWin.parent[0]);
288 pcg 1.1
289 pcg 1.15 init_env ();
290     init_command (cmd_argv);
291 pcg 1.1
292 pcg 1.4 pty_ev.start (cmd_fd, EVENT_READ);
293 pcg 1.7
294 pcg 1.9 check_ev.start ();
295 pcg 1.10
296 pcg 1.4 return true;
297 pcg 1.1 }
298    
299     /* ------------------------------------------------------------------------- *
300     * SIGNAL HANDLING & EXIT HANDLER *
301     * ------------------------------------------------------------------------- */
302     /*
303     * Catch a SIGCHLD signal and exit if the direct child has died
304     */
305     /* ARGSUSED */
306     /* EXTPROTO */
307     RETSIGTYPE
308 pcg 1.3 rxvt_Child_signal(int sig __attribute__ ((unused)))
309 pcg 1.1 {
310 pcg 1.26 int pid, save_errno = errno;
311     while ((pid = waitpid (-1, NULL, WNOHANG)) == -1 && errno == EINTR)
312     ;
313     errno = save_errno;
314 pcg 1.1
315 pcg 1.8 #if 0
316 pcg 1.26 if (pid == cmd_pid)
317     exit (EXIT_SUCCESS);
318 pcg 1.8 #endif
319 pcg 1.1 }
320    
321     /*
322     * Catch a fatal signal and tidy up before quitting
323     */
324     /* EXTPROTO */
325     RETSIGTYPE
326     rxvt_Exit_signal(int sig)
327     {
328 pcg 1.30 signal (sig, SIG_DFL);
329 pcg 1.1 #ifdef DEBUG_CMD
330 pcg 1.30 rxvt_print_error ("signal %d", sig);
331 pcg 1.1 #endif
332 pcg 1.26 rxvt_clean_exit();
333 pcg 1.30 kill (getpid (), sig);
334 pcg 1.1 }
335    
336 pcg 1.27 /* INTPROTO */
337 pcg 1.1 int
338 pcg 1.27 rxvt_xerror_handler (Display *display, XErrorEvent *event)
339 pcg 1.1 {
340 pcg 1.22 if (GET_R->allowedxerror == -1)
341     GET_R->allowedxerror = event->error_code;
342 pcg 1.8 else
343     {
344 pcg 1.27 old_xerror_handler (display, event);
345 pcg 1.22 GET_R->destroy ();
346 pcg 1.1 }
347 pcg 1.8
348     return 0;
349 pcg 1.1 }
350    
351     /*----------------------------------------------------------------------*/
352     /*
353     * Exit gracefully, clearing the utmp entry and restoring tty attributes
354     * TODO: if debugging, this should free up any known resources if we can
355     */
356     /* EXTPROTO */
357     void
358 pcg 1.8 rxvt_clean_exit ()
359 pcg 1.1 {
360 pcg 1.30 // TODO: rxvtd should clean up all ressources
361     if (GET_R)
362     GET_R->destroy ();
363 pcg 1.1 }
364    
365     /* ------------------------------------------------------------------------- *
366     * MEMORY ALLOCATION WRAPPERS *
367     * ------------------------------------------------------------------------- */
368     /* EXTPROTO */
369     void *
370     rxvt_malloc(size_t size)
371     {
372 pcg 1.26 void *p;
373 pcg 1.1
374 pcg 1.26 p = malloc(size);
375     if (p)
376     return p;
377    
378     fprintf(stderr, APL_NAME ": memory allocation failure. Aborting");
379     rxvt_clean_exit();
380     exit(EXIT_FAILURE);
381     /* NOTREACHED */
382 pcg 1.1 }
383    
384     /* EXTPROTO */
385     void *
386     rxvt_calloc(size_t number, size_t size)
387     {
388 pcg 1.26 void *p;
389 pcg 1.3
390 pcg 1.26 p = calloc(number, size);
391     if (p)
392     return p;
393    
394     fprintf(stderr, APL_NAME ": memory allocation failure. Aborting");
395     rxvt_clean_exit();
396     exit(EXIT_FAILURE);
397     /* NOTREACHED */
398 pcg 1.1 }
399    
400     /* EXTPROTO */
401     void *
402     rxvt_realloc(void *ptr, size_t size)
403     {
404 pcg 1.26 void *p;
405    
406     if (ptr)
407     p = realloc(ptr, size);
408     else
409     p = malloc(size);
410     if (p)
411     return p;
412 pcg 1.1
413 pcg 1.26 fprintf(stderr, APL_NAME ": memory allocation failure. Aborting");
414     rxvt_clean_exit();
415     exit(EXIT_FAILURE);
416     /* NOTREACHED */
417 pcg 1.1 }
418 pcg 1.3
419 pcg 1.1 /* ------------------------------------------------------------------------- *
420     * PRIVILEGED OPERATIONS *
421     * ------------------------------------------------------------------------- */
422     /* take care of suid/sgid super-user (root) privileges */
423     void
424 pcg 1.22 rxvt_term::privileges (int mode)
425 pcg 1.1 {
426     #if ! defined(__CYGWIN32__)
427     # if !defined(HAVE_SETEUID) && defined(HAVE_SETREUID)
428 pcg 1.26 /* setreuid() is the poor man's setuid(), seteuid() */
429 pcg 1.3 # define seteuid(a) setreuid(-1, (a))
430     # define setegid(a) setregid(-1, (a))
431 pcg 1.1 # define HAVE_SETEUID
432     # endif
433     # ifdef HAVE_SETEUID
434 pcg 1.26 switch (mode)
435     {
436     case IGNORE:
437     /*
438     * change effective uid/gid - not real uid/gid - so we can switch
439     * back to root later, as required
440     */
441 pcg 1.3 seteuid(getuid());
442     setegid(getgid());
443     break;
444 pcg 1.26 case SAVE:
445 pcg 1.22 euid = geteuid();
446     egid = getegid();
447 pcg 1.3 break;
448 pcg 1.26 case RESTORE:
449 pcg 1.22 seteuid(euid);
450     setegid(egid);
451 pcg 1.3 break;
452 pcg 1.1 }
453     # else
454 pcg 1.26 switch (mode)
455     {
456     case IGNORE:
457 pcg 1.3 setuid(getuid());
458     setgid(getgid());
459 pcg 1.26 /* FALLTHROUGH */
460     case SAVE:
461     /* FALLTHROUGH */
462     case RESTORE:
463 pcg 1.3 break;
464 pcg 1.1 }
465     # endif
466     #endif
467     }
468    
469     #ifdef UTMP_SUPPORT
470     void
471 pcg 1.22 rxvt_term::privileged_utmp (char action)
472 pcg 1.1 {
473 pcg 1.26 D_MAIN((stderr, "rxvt_privileged_utmp(%c); waiting for: %c (pid: %d)",
474     action, next_utmp_action, getpid()));
475     if (next_utmp_action != action || (action != SAVE && action != RESTORE)
476     || (Options & Opt_utmpInhibit)
477     || ttydev == NULL || *ttydev == '\0')
478     return;
479    
480     privileges (RESTORE);
481     if (action == SAVE)
482     {
483     next_utmp_action = RESTORE;
484     makeutent (ttydev, rs[Rs_display_name]);
485     }
486     else
487     { /* action == RESTORE */
488     next_utmp_action = IGNORE;
489     cleanutent ();
490 pcg 1.1 }
491 pcg 1.26 privileges (IGNORE);
492 pcg 1.1 }
493     #endif
494    
495     #ifndef NO_SETOWNER_TTYDEV
496     void
497 pcg 1.22 rxvt_term::privileged_ttydev (char action)
498 pcg 1.1 {
499 pcg 1.26 D_MAIN((stderr,
500     "privileged_ttydev (%c); waiting for: %c (pid: %d)",
501     action, next_tty_action, getpid()));
502     if (next_tty_action != action || (action != SAVE && action != RESTORE)
503     || ttydev == NULL || *ttydev == '\0')
504     return;
505 pcg 1.1
506 pcg 1.26 privileges (RESTORE);
507 pcg 1.1
508 pcg 1.26 if (action == SAVE)
509     {
510     next_tty_action = RESTORE;
511 pcg 1.1 # ifndef RESET_TTY_TO_COMMON_DEFAULTS
512 pcg 1.26 /* store original tty status for restoration rxvt_clean_exit() -- rgg 04/12/95 */
513     if (lstat(ttydev, &ttyfd_stat) < 0) /* you lose out */
514     next_tty_action = IGNORE;
515     else
516 pcg 1.1 # endif
517 pcg 1.26
518 pcg 1.3 {
519 pcg 1.26 chown(ttydev, getuid(), ttygid); /* fail silently */
520     chmod(ttydev, ttymode);
521 pcg 1.1 # ifdef HAVE_REVOKE
522 pcg 1.26 revoke(ttydev);
523 pcg 1.1 # endif
524 pcg 1.26
525 pcg 1.3 }
526 pcg 1.26 }
527     else
528     { /* action == RESTORE */
529     next_tty_action = IGNORE;
530 pcg 1.1 # ifndef RESET_TTY_TO_COMMON_DEFAULTS
531 pcg 1.26 chmod(ttydev, ttyfd_stat.st_mode);
532     chown(ttydev, ttyfd_stat.st_uid, ttyfd_stat.st_gid);
533 pcg 1.1 # else
534 pcg 1.26 chmod(ttydev,
535     (S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH));
536     chown(ttydev, 0, 0);
537 pcg 1.1 # endif
538 pcg 1.26
539 pcg 1.1 }
540    
541 pcg 1.26 privileges (IGNORE);
542 pcg 1.1
543     # ifndef RESET_TTY_TO_COMMON_DEFAULTS
544 pcg 1.26 D_MAIN((stderr, "%s \"%s\": mode %03o, uid %d, gid %d",
545     action == RESTORE ? "Restoring" : (action ==
546     SAVE ? "Saving" :
547     "UNKNOWN ERROR for"), ttydev,
548     ttyfd_stat.st_mode, ttyfd_stat.st_uid,
549     ttyfd_stat.st_gid));
550 pcg 1.1 # endif
551     }
552     #endif
553    
554     /*----------------------------------------------------------------------*/
555     /*
556     * window size/position calculcations for XSizeHint and other storage.
557     * if width/height are non-zero then override calculated width/height
558     */
559     void
560 pcg 1.17 rxvt_term::window_calc (unsigned int width, unsigned int height)
561 pcg 1.1 {
562 pcg 1.26 short recalc_x, recalc_y;
563     int x, y, sb_w, mb_h, flags;
564     unsigned int w, h;
565     unsigned int max_width, max_height;
566    
567     D_SIZE((stderr, "< Cols/Rows: %3d x %3d ; Width/Height: %4d x %4d",
568     TermWin.ncol, TermWin.nrow, szHint.width,
569     szHint.height));
570     szHint.flags = PMinSize | PResizeInc | PBaseSize | PWinGravity;
571     szHint.win_gravity = NorthWestGravity;
572     /* szHint.min_aspect.x = szHint.min_aspect.y = 1; */
573    
574     recalc_x = recalc_y = 0;
575     flags = 0;
576     if (!parsed_geometry)
577     {
578     parsed_geometry = 1;
579     if (rs[Rs_geometry])
580     flags = XParseGeometry(rs[Rs_geometry], &x, &y, &w, &h);
581     if (flags & WidthValue)
582     {
583     TermWin.ncol = BOUND_POSITIVE_INT16(w);
584     szHint.flags |= USSize;
585 pcg 1.3 }
586 pcg 1.26 if (flags & HeightValue)
587     {
588     TermWin.nrow = BOUND_POSITIVE_INT16(h);
589     szHint.flags |= USSize;
590 pcg 1.3 }
591 pcg 1.26 if (flags & XValue)
592     {
593     szHint.x = x;
594     szHint.flags |= USPosition;
595     if (flags & XNegative)
596     {
597     recalc_x = 1;
598     szHint.win_gravity = NorthEastGravity;
599 pcg 1.3 }
600     }
601 pcg 1.26 if (flags & YValue)
602     {
603     szHint.y = y;
604     szHint.flags |= USPosition;
605     if (flags & YNegative)
606     {
607     recalc_y = 1;
608     if (szHint.win_gravity == NorthEastGravity)
609     szHint.win_gravity = SouthEastGravity;
610     else
611     szHint.win_gravity = SouthWestGravity;
612 pcg 1.3 }
613     }
614 pcg 1.1 }
615 pcg 1.26 /* TODO: BOUNDS */
616     TermWin.width = TermWin.ncol * TermWin.fwidth;
617     TermWin.height = TermWin.nrow * TermWin.fheight;
618     max_width = MAX_COLS * TermWin.fwidth;
619     max_height = MAX_ROWS * TermWin.fheight;
620    
621     szHint.base_width = szHint.base_height = 2 * TermWin.int_bwidth;
622    
623     sb_w = mb_h = 0;
624     window_vt_x = window_vt_y = 0;
625     if (scrollbar_visible ())
626     {
627     sb_w = scrollbar_TotalWidth();
628     szHint.base_width += sb_w;
629     if (!(Options & Opt_scrollBar_right))
630     window_vt_x = sb_w;
631     }
632     if (menubar_visible ())
633     {
634     mb_h = menuBar_TotalHeight();
635     szHint.base_height += mb_h;
636     window_vt_y = mb_h;
637     }
638     szHint.width_inc = TermWin.fwidth;
639     szHint.height_inc = TermWin.fheight;
640     szHint.min_width = szHint.base_width + szHint.width_inc;
641     szHint.min_height = szHint.base_height + szHint.height_inc;
642    
643     if (width && width - szHint.base_width < max_width)
644     {
645     szHint.width = width;
646     TermWin.width = width - szHint.base_width;
647     }
648     else
649     {
650     MIN_IT(TermWin.width, max_width);
651     szHint.width = szHint.base_width + TermWin.width;
652     }
653     if (height && height - szHint.base_height < max_height)
654     {
655     szHint.height = height;
656     TermWin.height = height - szHint.base_height;
657     }
658     else
659     {
660     MIN_IT(TermWin.height, max_height);
661     szHint.height = szHint.base_height + TermWin.height;
662     }
663     if (scrollbar_visible () && (Options & Opt_scrollBar_right))
664     window_sb_x = szHint.width - sb_w;
665    
666     if (recalc_x)
667 pcg 1.27 szHint.x += (DisplayWidth (display->display, DefaultScreen (display->display))
668 pcg 1.26 - szHint.width - 2 * TermWin.ext_bwidth);
669     if (recalc_y)
670 pcg 1.27 szHint.y += (DisplayHeight (display->display, DefaultScreen (display->display))
671 pcg 1.26 - szHint.height - 2 * TermWin.ext_bwidth);
672    
673     TermWin.ncol = TermWin.width / TermWin.fwidth;
674     TermWin.nrow = TermWin.height / TermWin.fheight;
675     D_SIZE((stderr, "> Cols/Rows: %3d x %3d ; Width/Height: %4d x %4d",
676     TermWin.ncol, TermWin.nrow, szHint.width,
677     szHint.height));
678     return;
679 pcg 1.1 }
680    
681     /*----------------------------------------------------------------------*/
682     /*
683     * Tell the teletype handler what size the window is.
684     * Called after a window size change.
685     */
686     void
687 pcg 1.9 rxvt_term::tt_winch ()
688 pcg 1.1 {
689 pcg 1.20 struct winsize ws;
690 pcg 1.9
691     if (cmd_fd < 0)
692     return;
693 pcg 1.1
694 pcg 1.9 ws.ws_col = TermWin.ncol;
695     ws.ws_row = TermWin.nrow;
696     ws.ws_xpixel = ws.ws_ypixel = 0;
697 pcg 1.1 #ifndef DEBUG_SIZE
698 pcg 1.9 (void)ioctl (cmd_fd, TIOCSWINSZ, &ws);
699 pcg 1.1 #else
700 pcg 1.9 if (ioctl (cmd_fd, TIOCSWINSZ, &ws) < 0)
701     D_SIZE((stderr, "Failed to send TIOCSWINSZ to fd %d", fd));
702 pcg 1.1 # ifdef SIGWINCH
703 pcg 1.9 else if (cmd_pid) /* force through to the command */
704     kill (cmd_pid, SIGWINCH);
705 pcg 1.1 # endif
706     #endif
707     }
708    
709     /*----------------------------------------------------------------------*/
710     /* rxvt_change_font() - Switch to a new font */
711     /*
712     * init = 1 - initialize
713     *
714     * fontname == FONT_UP - switch to bigger font
715     * fontname == FONT_DN - switch to smaller font
716     */
717     void
718 pcg 1.22 rxvt_term::change_font (int init, const char *fontname)
719 pcg 1.26 {}
720 pcg 1.1
721     void
722 pcg 1.22 rxvt_term::font_up_down (int n, int direction)
723 pcg 1.26 {}
724 pcg 1.1
725     /*----------------------------------------------------------------------*/
726     /*----------------------------------------------------------------------*/
727     /* xterm sequences - title, iconName, color (exptl) */
728     void
729 pcg 1.22 rxvt_term::set_title (const char *str)
730 pcg 1.1 {
731     #ifndef SMART_WINDOW_TITLE
732 pcg 1.27 XStoreName(display->display, TermWin.parent[0], str);
733 pcg 1.1 #else
734 pcg 1.26 char *name;
735 pcg 1.1
736 pcg 1.27 if (XFetchName(display->display, TermWin.parent[0], &name) == 0)
737 pcg 1.26 name = NULL;
738     if (name == NULL || STRCMP(name, str))
739 pcg 1.27 XStoreName(display->display, TermWin.parent[0], str);
740 pcg 1.26 if (name)
741     XFree(name);
742 pcg 1.1 #endif
743     }
744    
745     void
746 pcg 1.22 rxvt_term::set_iconName (const char *str)
747 pcg 1.1 {
748     #ifndef SMART_WINDOW_TITLE
749 pcg 1.27 XSetIconName(display->display, TermWin.parent[0], str);
750 pcg 1.1 #else
751 pcg 1.26 char *name;
752 pcg 1.1
753 pcg 1.27 if (XGetIconName(display->display, TermWin.parent[0], &name))
754 pcg 1.26 name = NULL;
755     if (name == NULL || STRCMP(name, str))
756 pcg 1.27 XSetIconName(display->display, TermWin.parent[0], str);
757 pcg 1.26 if (name)
758     XFree(name);
759 pcg 1.1 #endif
760     }
761    
762     #ifdef XTERM_COLOR_CHANGE
763     void
764 pcg 1.22 rxvt_term::set_window_color (int idx, const char *color)
765 pcg 1.1 {
766 pcg 1.26 rxvt_color xcol;
767     int i;
768 pcg 1.1
769 pcg 1.26 if (color == NULL || *color == '\0')
770     return;
771 pcg 1.1
772 pcg 1.26 /* handle color aliases */
773     if (isdigit(*color))
774     {
775     i = atoi(color);
776     if (i >= 8 && i <= 15)
777     { /* bright colors */
778     i -= 8;
779 pcg 1.1 # ifndef NO_BRIGHTCOLOR
780 pcg 1.26 PixColors[idx] = PixColors[minBrightCOLOR + i];
781     SET_PIXCOLOR(idx);
782     goto Done;
783 pcg 1.1 # endif
784 pcg 1.26
785 pcg 1.3 }
786 pcg 1.26 if (i >= 0 && i <= 7)
787     { /* normal colors */
788     PixColors[idx] = PixColors[minCOLOR + i];
789     SET_PIXCOLOR(idx);
790     goto Done;
791 pcg 1.3 }
792 pcg 1.1 }
793 pcg 1.26 if (!rXParseAllocColor (& xcol, color))
794     return;
795 pcg 1.27 /* XStoreColor (display->display, XCMAP, XColor*); */
796 pcg 1.1
797 pcg 1.26 /*
798     * FIXME: should free colors here, but no idea how to do it so instead,
799     * so just keep gobbling up the colormap
800     */
801 pcg 1.1 # if 0
802 pcg 1.26 for (i = Color_Black; i <= Color_White; i++)
803     if (PixColors[idx] == PixColors[i])
804     break;
805     if (i > Color_White)
806     {
807     /* fprintf (stderr, "XFreeColors: PixColors [%d] = %lu\n", idx, PixColors [idx]); */
808 pcg 1.27 XFreeColors(display->display, XCMAP, (PixColors + idx), 1,
809     DisplayPlanes(display->display, display->screen));
810 pcg 1.1 }
811     # endif
812    
813 pcg 1.26 PixColors[idx] = xcol;
814     SET_PIXCOLOR(idx);
815 pcg 1.1
816 pcg 1.26 /* XSetWindowAttributes attr; */
817     /* Cursor cursor; */
818     Done:
819     if (idx == Color_bg && !(Options & Opt_transparent))
820 pcg 1.27 XSetWindowBackground(display->display, TermWin.vt,
821 pcg 1.26 PixColors[Color_bg]);
822    
823     /* handle Color_BD, scrollbar background, etc. */
824    
825     set_colorfgbg ();
826     recolour_cursor ();
827     /* the only reasonable way to enforce a clean update */
828     scr_poweron ();
829 pcg 1.1 }
830    
831     #else
832 pcg 1.22 # define set_window_color (idx,color) ((void)0)
833 pcg 1.3 #endif /* XTERM_COLOR_CHANGE */
834 pcg 1.1
835     void
836 pcg 1.15 rxvt_term::recolour_cursor ()
837 pcg 1.1 {
838 pcg 1.15 #if TODO
839 pcg 1.26 rxvt_color xcol[2];
840 pcg 1.1
841 pcg 1.26 xcol[0] = PixColors[Color_pointer];
842     xcol[1] = PixColors[Color_bg];
843 pcg 1.27 XQueryColors (display->display, XCMAP, xcol, 2);
844     XRecolorCursor (display->display, TermWin_cursor, &(xcol[0]), &(xcol[1]));
845 pcg 1.1 #endif
846     }
847    
848     /*----------------------------------------------------------------------*/
849     /*
850     * find if fg/bg matches any of the normal (low-intensity) colors
851     */
852     void
853 pcg 1.22 rxvt_term::set_colorfgbg ()
854 pcg 1.1 {
855 pcg 1.26 unsigned int i;
856     const char *xpmb = "\0";
857     char fstr[sizeof("default") + 1], bstr[sizeof("default") + 1];
858    
859     env_colorfgbg =
860     (char *)rxvt_malloc(sizeof("COLORFGBG=default;default;bg") + 1);
861     STRCPY(fstr, "default");
862     STRCPY(bstr, "default");
863     for (i = Color_Black; i <= Color_White; i++)
864     if (PixColors[Color_fg] == PixColors[i])
865     {
866     sprintf(fstr, "%d", (i - Color_Black));
867     break;
868     }
869     for (i = Color_Black; i <= Color_White; i++)
870     if (PixColors[Color_bg] == PixColors[i])
871     {
872     sprintf(bstr, "%d", (i - Color_Black));
873 pcg 1.1 #ifdef XPM_BACKGROUND
874 pcg 1.26 xpmb = "default;";
875 pcg 1.1 #endif
876 pcg 1.26 break;
877     }
878     sprintf(env_colorfgbg, "COLORFGBG=%s;%s%s", fstr, xpmb, bstr);
879     putenv(env_colorfgbg);
880 pcg 1.1
881     #ifndef NO_BRIGHTCOLOR
882 pcg 1.26 colorfgbg = DEFAULT_RSTYLE;
883     for (i = minCOLOR; i <= maxCOLOR; i++)
884     {
885     if (PixColors[Color_fg] == PixColors[i])
886     colorfgbg = SET_FGCOLOR(colorfgbg, i);
887     if (PixColors[Color_bg] == PixColors[i])
888     colorfgbg = SET_BGCOLOR(colorfgbg, i);
889 pcg 1.1 }
890     #endif
891     }
892    
893     /*----------------------------------------------------------------------*/
894     /*
895     * Colour determination for low colour displays, routine from
896     * Hans de Goede <hans@highrise.nl>
897     */
898    
899     int
900 pcg 1.22 rxvt_term::rXParseAllocColor (rxvt_color *screen_in_out, const char *colour)
901 pcg 1.1 {
902 pcg 1.27 if (!screen_in_out->set (display, colour))
903 pcg 1.26 {
904     rxvt_print_error("can't allocate colour: %s", colour);
905     return false;
906 pcg 1.3 }
907 pcg 1.1
908 pcg 1.26 return true;
909 pcg 1.1 }
910    
911     /* -------------------------------------------------------------------- *
912     * - WINDOW RESIZING - *
913     * -------------------------------------------------------------------- */
914     void
915 pcg 1.17 rxvt_term::resize_all_windows (unsigned int width, unsigned int height, int ignoreparent)
916 pcg 1.1 {
917 pcg 1.17 int fix_screen;
918 pcg 1.3
919     #ifdef SMART_RESIZE
920 pcg 1.17 int old_width = szHint.width, old_height = szHint.height;
921 pcg 1.1 #endif
922    
923 pcg 1.17 window_calc (width, height);
924 pcg 1.27 XSetWMNormalHints (display->display, TermWin.parent[0], &szHint);
925 pcg 1.17 if (!ignoreparent)
926     {
927 pcg 1.3 #ifdef SMART_RESIZE
928 pcg 1.17 /*
929     * resize by Marius Gedminas <marius.gedminas@uosis.mif.vu.lt>
930     * reposition window on resize depending on placement on screen
931     */
932     int x, y, x1, y1;
933     int dx, dy;
934     unsigned int unused_w1, unused_h1, unused_b1, unused_d1;
935     Window unused_cr;
936    
937 pcg 1.27 XTranslateCoordinates (display->display, TermWin.parent[0], display->root,
938 pcg 1.17 0, 0, &x, &y, &unused_cr);
939 pcg 1.27 XGetGeometry (display->display, TermWin.parent[0], &unused_cr, &x1, &y1,
940 pcg 1.17 &unused_w1, &unused_h1, &unused_b1, &unused_d1);
941     /*
942 pcg 1.27 * if display->root isn't the parent window, a WM will probably have offset
943 pcg 1.17 * our position for handles and decorations. Counter it
944     */
945 pcg 1.26 if (x1 != x || y1 != y)
946     {
947 pcg 1.17 x -= x1;
948     y -= y1;
949 pcg 1.26 }
950 pcg 1.17
951 pcg 1.27 x1 = (DisplayWidth (display->display, display->screen) - old_width) / 2;
952     y1 = (DisplayHeight (display->display, display->screen) - old_height) / 2;
953 pcg 1.17 dx = old_width - szHint.width;
954     dy = old_height - szHint.height;
955    
956 pcg 1.26 /* Check position of the center of the window */
957 pcg 1.17 if (x < x1) /* left half */
958 pcg 1.26 dx = 0;
959 pcg 1.17 else if (x == x1) /* exact center */
960 pcg 1.26 dx /= 2;
961 pcg 1.17 if (y < y1) /* top half */
962 pcg 1.26 dy = 0;
963 pcg 1.17 else if (y == y1) /* exact center */
964 pcg 1.26 dy /= 2;
965 pcg 1.3
966 pcg 1.27 XMoveResizeWindow (display->display, TermWin.parent[0], x + dx, y + dy,
967 pcg 1.17 szHint.width, szHint.height);
968 pcg 1.1 #else
969 pcg 1.27 XResizeWindow (display->display, TermWin.parent[0], szHint.width,
970 pcg 1.17 szHint.height);
971 pcg 1.1 #endif
972 pcg 1.26
973 pcg 1.1 }
974    
975 pcg 1.17 fix_screen = (TermWin.ncol != prev_ncol
976     || TermWin.nrow != prev_nrow);
977    
978     if (fix_screen || width != old_width || height != old_height)
979     {
980 pcg 1.22 if (scrollbar_visible ())
981 pcg 1.17 {
982 pcg 1.27 XMoveResizeWindow (display->display, scrollBar.win, window_sb_x,
983 pcg 1.17 0, scrollbar_TotalWidth (), szHint.height);
984     resize_scrollbar ();
985 pcg 1.3 }
986 pcg 1.17
987 pcg 1.22 if (menubar_visible ())
988 pcg 1.27 XMoveResizeWindow (display->display, menuBar.win, window_vt_x,
989 pcg 1.17 0, TermWin_TotalWidth (), menuBar_TotalHeight ());
990    
991 pcg 1.27 XMoveResizeWindow (display->display, TermWin.vt, window_vt_x,
992 pcg 1.17 window_vt_y, TermWin_TotalWidth (),
993     TermWin_TotalHeight ());
994 pcg 1.1 #ifdef RXVT_GRAPHICS
995 pcg 1.17 if (old_height)
996 pcg 1.22 Gr_Resize (old_width - szHint.base_width,
997 pcg 1.26 old_height - szHint.base_height);
998 pcg 1.1 #endif
999 pcg 1.17 scr_clear ();
1000 pcg 1.1 #ifdef XPM_BACKGROUND
1001 pcg 1.22 resize_pixmap ();
1002 pcg 1.1 #endif
1003 pcg 1.26
1004 pcg 1.1 }
1005    
1006 pcg 1.17 if (fix_screen || old_height == 0)
1007     {
1008     int curr_screen = -1;
1009 pcg 1.19 int old_ncol = prev_ncol;
1010 pcg 1.1
1011 pcg 1.17 /* scr_reset only works on the primary screen */
1012     if (old_height) /* this is not the first time through */
1013 pcg 1.19 {
1014     unsigned int ncol = TermWin.ncol;
1015     TermWin.ncol = prev_ncol; // save b/c scr_blank_screen_mem uses this
1016 pcg 1.22 curr_screen = scr_change_screen (PRIMARY);
1017 pcg 1.19 TermWin.ncol = ncol;
1018     }
1019 pcg 1.13
1020 pcg 1.17 scr_reset();
1021 pcg 1.13
1022 pcg 1.17 if (curr_screen >= 0) /* this is not the first time through */
1023     {
1024 pcg 1.22 scr_change_screen (curr_screen);
1025     selection_check (old_ncol != TermWin.ncol ? 4 : 0);
1026 pcg 1.3 }
1027 pcg 1.1 }
1028    
1029 pcg 1.17 old_width = szHint.width;
1030     old_height = szHint.height;
1031 pcg 1.1
1032     #ifdef USE_XIM
1033 pcg 1.22 IMSetStatusPosition ();
1034 pcg 1.1 #endif
1035     }
1036    
1037     /*
1038     * Set the width/height of the vt window in characters. Units are pixels.
1039     * good for toggling 80/132 columns
1040     */
1041     void
1042 pcg 1.22 rxvt_term::set_widthheight (unsigned int width, unsigned int height)
1043 pcg 1.1 {
1044 pcg 1.26 XWindowAttributes wattr;
1045 pcg 1.1
1046 pcg 1.26 if (width == 0 || height == 0)
1047     {
1048 pcg 1.27 XGetWindowAttributes(display->display, display->root, &wattr);
1049 pcg 1.26 if (width == 0)
1050     width = wattr.width - szHint.base_width;
1051     if (height == 0)
1052     height = wattr.height - szHint.base_height;
1053     }
1054     if (width != TermWin.width || height != TermWin.height)
1055     {
1056     width += szHint.base_width;
1057     height += szHint.base_height;
1058     resize_all_windows (width, height, 0);
1059 pcg 1.1 }
1060     }
1061    
1062     /* -------------------------------------------------------------------- *
1063     * - X INPUT METHOD ROUTINES - *
1064     * -------------------------------------------------------------------- */
1065     #ifdef USE_XIM
1066 pcg 1.29
1067 pcg 1.1 void
1068 pcg 1.29 rxvt_term::im_set_size (XRectangle *size)
1069 pcg 1.1 {
1070 pcg 1.17 size->x = TermWin.int_bwidth;
1071     size->y = TermWin.int_bwidth;
1072     size->width = Width2Pixel(TermWin.ncol);
1073     size->height = Height2Pixel(TermWin.nrow);
1074 pcg 1.1 }
1075    
1076     void
1077 pcg 1.29 rxvt_term::im_set_color (unsigned long *fg, unsigned long *bg)
1078 pcg 1.1 {
1079 pcg 1.17 *fg = PixColors[Color_fg];
1080     *bg = PixColors[Color_bg];
1081 pcg 1.1 }
1082    
1083     /* Checking whether input method is running. */
1084 pcg 1.22 bool
1085     rxvt_term::IMisRunning ()
1086 pcg 1.1 {
1087 pcg 1.26 char *p;
1088     Atom atom;
1089     Window win;
1090     char server[IMBUFSIZ];
1091    
1092     /* get current locale modifier */
1093     if ((p = XSetLocaleModifiers(NULL)) != NULL)
1094     {
1095     STRCPY(server, "@server=");
1096     STRNCAT(server, &(p[4]), IMBUFSIZ - 9); /* skip "@im=" */
1097     if ((p = STRCHR(server + 1, '@')) != NULL) /* first one only */
1098     *p = '\0';
1099    
1100 pcg 1.27 atom = XInternAtom(display->display, server, False);
1101     win = XGetSelectionOwner(display->display, atom);
1102 pcg 1.26 if (win != None)
1103     return True;
1104 pcg 1.1 }
1105 pcg 1.26 return False;
1106 pcg 1.1 }
1107    
1108     void
1109 pcg 1.22 rxvt_term::IMSendSpot ()
1110 pcg 1.1 {
1111 pcg 1.26 XPoint spot;
1112     XVaNestedList preedit_attr;
1113 pcg 1.1
1114 pcg 1.26 if (Input_Context == NULL
1115     || !TermWin.focus || !(input_style & XIMPreeditPosition)
1116     || !(event_type == KeyPress
1117     || event_type == Expose
1118     || event_type == NoExpose
1119     || event_type == SelectionNotify
1120     || event_type == ButtonRelease || event_type == FocusIn)
1121     || !IMisRunning ())
1122     return;
1123 pcg 1.1
1124 pcg 1.29 im_set_position (&spot);
1125 pcg 1.1
1126 pcg 1.26 preedit_attr = XVaCreateNestedList(0, XNSpotLocation, &spot, NULL);
1127     XSetICValues(Input_Context, XNPreeditAttributes, preedit_attr, NULL);
1128     XFree(preedit_attr);
1129 pcg 1.1 }
1130    
1131     void
1132 pcg 1.29 rxvt_term::im_set_preedit_area (XRectangle * preedit_rect, XRectangle * status_rect,
1133     XRectangle * needed_rect)
1134 pcg 1.1 {
1135 pcg 1.17 int mbh, vtx = 0;
1136    
1137 pcg 1.22 if (scrollbar_visible () && !(Options & Opt_scrollBar_right))
1138 pcg 1.17 vtx = scrollbar_TotalWidth();
1139 pcg 1.1
1140 pcg 1.22 mbh = menubar_visible () ? menuBar_TotalHeight() : 0;
1141 pcg 1.17 mbh -= TermWin.lineSpace;
1142 pcg 1.1
1143 pcg 1.17 preedit_rect->x = needed_rect->width + vtx;
1144     preedit_rect->y = Height2Pixel(TermWin.nrow - 1) + mbh;
1145 pcg 1.1
1146 pcg 1.17 preedit_rect->width = Width2Pixel(TermWin.ncol + 1) - needed_rect->width + vtx;
1147     preedit_rect->height = Height2Pixel(1);
1148 pcg 1.1
1149 pcg 1.17 status_rect->x = vtx;
1150     status_rect->y = Height2Pixel(TermWin.nrow - 1) + mbh;
1151 pcg 1.1
1152 pcg 1.17 status_rect->width = needed_rect->width ? needed_rect->width : Width2Pixel(TermWin.ncol + 1);
1153     status_rect->height = Height2Pixel(1);
1154 pcg 1.1 }
1155    
1156     void
1157 pcg 1.29 rxvt_term::im_destroy ()
1158     {
1159     if (Input_Context)
1160     {
1161     XDestroyIC (Input_Context);
1162     Input_Context = NULL;
1163     }
1164    
1165     if (input_method)
1166     {
1167     display->put_xim (input_method);
1168     input_method = 0;
1169     }
1170 pcg 1.1 }
1171    
1172     /*
1173     * Try to open a XIM with the current modifiers, then see if we can
1174     * open a suitable preedit type
1175     */
1176 pcg 1.22 bool
1177 pcg 1.29 rxvt_term::IM_get_IC (const char *modifiers)
1178 pcg 1.1 {
1179 pcg 1.26 int i, j, found;
1180     XIM xim;
1181     XPoint spot;
1182     XRectangle rect, status_rect, needed_rect;
1183     unsigned long fg, bg;
1184     const char *p;
1185     char **s;
1186     XIMStyles *xim_styles;
1187     XVaNestedList preedit_attr, status_attr;
1188 pcg 1.29
1189     if (!((p = XSetLocaleModifiers (modifiers)) && *p))
1190     return false;
1191 pcg 1.26
1192     D_MAIN((stderr, "rxvt_IM_get_IC()"));
1193 pcg 1.29 input_method = display->get_xim (locale, modifiers);
1194     if (input_method == NULL)
1195     return false;
1196    
1197     xim = input_method->xim;
1198 pcg 1.26
1199     xim_styles = NULL;
1200     if (XGetIMValues (xim, XNQueryInputStyle, &xim_styles, NULL)
1201     || !xim_styles || !xim_styles->count_styles)
1202     {
1203 pcg 1.29 display->put_xim (input_method);
1204     return false;
1205 pcg 1.26 }
1206    
1207 pcg 1.29 p = rs[Rs_preeditType] ? rs[Rs_preeditType] : "OverTheSpot,OffTheSpot,Root";
1208 pcg 1.26 s = rxvt_splitcommastring(p);
1209     for (i = found = 0; !found && s[i]; i++)
1210     {
1211     if (!STRCMP(s[i], "OverTheSpot"))
1212     input_style = (XIMPreeditPosition | XIMStatusNothing);
1213     else if (!STRCMP(s[i], "OffTheSpot"))
1214     input_style = (XIMPreeditArea | XIMStatusArea);
1215     else if (!STRCMP(s[i], "Root"))
1216     input_style = (XIMPreeditNothing | XIMStatusNothing);
1217    
1218     for (j = 0; j < xim_styles->count_styles; j++)
1219     if (input_style == xim_styles->supported_styles[j])
1220     {
1221     found = 1;
1222     break;
1223     }
1224     }
1225 pcg 1.29
1226 pcg 1.26 for (i = 0; s[i]; i++)
1227 pcg 1.29 free (s[i]);
1228    
1229     free (s);
1230     XFree (xim_styles);
1231 pcg 1.26
1232     if (!found)
1233     {
1234 pcg 1.29 display->put_xim (input_method);
1235     return false;
1236 pcg 1.26 }
1237    
1238     preedit_attr = status_attr = NULL;
1239    
1240     if (input_style & XIMPreeditPosition)
1241     {
1242 pcg 1.29 im_set_size (&rect);
1243     im_set_position (&spot);
1244     im_set_color (&fg, &bg);
1245 pcg 1.26
1246     preedit_attr = XVaCreateNestedList(0, XNArea, &rect,
1247     XNSpotLocation, &spot,
1248     XNForeground, fg, XNBackground, bg,
1249     //XNFontSet, TermWin.fontset,
1250     NULL);
1251 pcg 1.1 }
1252 pcg 1.26 else if (input_style & XIMPreeditArea)
1253     {
1254 pcg 1.29 im_set_color (&fg, &bg);
1255 pcg 1.26
1256     /*
1257     * The necessary width of preedit area is unknown
1258     * until create input context.
1259     */
1260     needed_rect.width = 0;
1261    
1262 pcg 1.29 im_set_preedit_area (&rect, &status_rect, &needed_rect);
1263 pcg 1.1
1264 pcg 1.26 preedit_attr = XVaCreateNestedList(0, XNArea, &rect,
1265     XNForeground, fg, XNBackground, bg,
1266     //XNFontSet, TermWin.fontset,
1267     NULL);
1268     status_attr = XVaCreateNestedList(0, XNArea, &status_rect,
1269     XNForeground, fg, XNBackground, bg,
1270     //XNFontSet, TermWin.fontset,
1271     NULL);
1272     }
1273 pcg 1.29
1274 pcg 1.26 Input_Context = XCreateIC(xim, XNInputStyle, input_style,
1275     XNClientWindow, TermWin.parent[0],
1276     XNFocusWindow, TermWin.parent[0],
1277     preedit_attr ? XNPreeditAttributes : NULL,
1278     preedit_attr,
1279     status_attr ? XNStatusAttributes : NULL,
1280     status_attr, NULL);
1281 pcg 1.29 if (preedit_attr) XFree(preedit_attr);
1282     if (status_attr) XFree(status_attr);
1283    
1284 pcg 1.26 if (Input_Context == NULL)
1285     {
1286     rxvt_print_error("failed to create input context");
1287 pcg 1.29 display->put_xim (input_method);
1288     return false;
1289 pcg 1.26 }
1290 pcg 1.29
1291 pcg 1.26 if (input_style & XIMPreeditArea)
1292     IMSetStatusPosition ();
1293 pcg 1.29
1294 pcg 1.26 D_MAIN((stderr, "rxvt_IM_get_IC() - successful connection"));
1295 pcg 1.29 return true;
1296 pcg 1.16 }
1297    
1298     void
1299 pcg 1.29 rxvt_term::im_cb ()
1300 pcg 1.16 {
1301     int i, found, had_im;
1302     const char *p;
1303     char **s;
1304     char buf[IMBUFSIZ];
1305    
1306 pcg 1.29 im_destroy ();
1307    
1308 pcg 1.16 D_MAIN((stderr, "rxvt_IMInstantiateCallback()"));
1309 pcg 1.29 if (Input_Context)
1310 pcg 1.16 return;
1311    
1312     #if defined(HAVE_XSETLOCALE) || defined(HAVE_SETLOCALE)
1313 pcg 1.29 if (rs[Rs_imLocale])
1314     setlocale (LC_CTYPE, rs[Rs_imLocale]);
1315 pcg 1.16 #endif
1316    
1317 pcg 1.29 p = rs[Rs_inputMethod];
1318 pcg 1.16 if (p && *p)
1319     {
1320     bool found = false;
1321    
1322     s = rxvt_splitcommastring (p);
1323     for (i = 0; s[i]; i++)
1324     {
1325     if (*s[i])
1326     {
1327     STRCPY (buf, "@im=");
1328     STRNCAT (buf, s[i], IMBUFSIZ - 5);
1329 pcg 1.29 if (IM_get_IC (buf))
1330 pcg 1.16 {
1331     found = true;
1332     break;
1333     }
1334     }
1335     }
1336     for (i = 0; s[i]; i++)
1337 pcg 1.26 free(s[i]);
1338 pcg 1.16 free(s);
1339    
1340     if (found)
1341     goto done;
1342     }
1343    
1344 pcg 1.26 /* try with XMODIFIERS env. var. */
1345 pcg 1.29 if (IM_get_IC (""))
1346 pcg 1.16 goto done;
1347    
1348 pcg 1.26 /* try with no modifiers base IF the user didn't specify an IM */
1349 pcg 1.29 if (IM_get_IC ("@im=none"))
1350 pcg 1.16 goto done;
1351    
1352     done:
1353     #if defined(HAVE_XSETLOCALE) || defined(HAVE_SETLOCALE)
1354 pcg 1.29 if (rs[Rs_imLocale])
1355     setlocale (LC_CTYPE, locale);
1356 pcg 1.16 #endif
1357 pcg 1.1 }
1358    
1359     void
1360 pcg 1.22 rxvt_term::IMSetStatusPosition ()
1361 pcg 1.1 {
1362 pcg 1.26 XRectangle preedit_rect, status_rect, *needed_rect;
1363     XVaNestedList preedit_attr, status_attr;
1364 pcg 1.1
1365 pcg 1.26 if (Input_Context == NULL
1366     || !TermWin.focus || !(input_style & XIMPreeditArea)
1367     || !IMisRunning ())
1368     return;
1369 pcg 1.1
1370 pcg 1.26 /* Getting the necessary width of preedit area */
1371     status_attr = XVaCreateNestedList(0, XNAreaNeeded, &needed_rect, NULL);
1372     XGetICValues(Input_Context, XNStatusAttributes, status_attr, NULL);
1373     XFree(status_attr);
1374    
1375 pcg 1.29 im_set_preedit_area (&preedit_rect, &status_rect, needed_rect);
1376 pcg 1.26
1377     preedit_attr = XVaCreateNestedList(0, XNArea, &preedit_rect, NULL);
1378     status_attr = XVaCreateNestedList(0, XNArea, &status_rect, NULL);
1379    
1380     XSetICValues(Input_Context,
1381     XNPreeditAttributes, preedit_attr,
1382     XNStatusAttributes, status_attr, NULL);
1383 pcg 1.1
1384 pcg 1.26 XFree(preedit_attr);
1385     XFree(status_attr);
1386 pcg 1.1 }
1387 pcg 1.3 #endif /* USE_XIM */
1388 pcg 1.1
1389     /*----------------------------------------------------------------------*/
1390 pcg 1.3 rxvt_t rxvt_current_term;
1391 pcg 1.1
1392     /*----------------------- end-of-file (C source) -----------------------*/