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