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