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