X-Git-Url: http://git.hcoop.net/bpt/emacs.git/blobdiff_plain/e5074ca4b1fe458019bafebde2fa38284ccd382c..85f487d15cfad983171db939ce68b179a9b166d9:/src/xterm.c diff --git a/src/xterm.c b/src/xterm.c index a5e47d2dac..ccbb59f750 100644 --- a/src/xterm.c +++ b/src/xterm.c @@ -25,6 +25,8 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ */ +/* Xt features made by Fred Pierresteguy. */ + #define NEW_SELECTIONS /* On 4.3 these lose if they come after xterm.h. */ @@ -35,6 +37,10 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ #include +/* Need syssignal.h for various externs and definitions that may be required + by some configurations for calls to signal later in this source file. */ +#include "syssignal.h" + #ifdef HAVE_X_WINDOWS #include "lisp.h" @@ -86,6 +92,11 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ #include "buffer.h" #include "window.h" +#ifdef USE_X_TOOLKIT +extern XtAppContext Xt_app_con; +extern Widget Xt_app_shell; +#endif /* USE_X_TOOLKIT */ + #ifdef HAVE_X11 #define XMapWindow XMapRaised /* Raise them when mapping. */ #else /* ! defined (HAVE_X11) */ @@ -119,7 +130,7 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ #define min(a,b) ((a)<(b) ? (a) : (b)) #define max(a,b) ((a)>(b) ? (a) : (b)) - + /* Nonzero means we must reprint all windows because 1) we received an ExposeWindow event or 2) we received too many ExposeRegion events to record. @@ -137,7 +148,7 @@ static int expose_all_icons; static struct event_queue x_expose_queue; -/* ButtonPressed and ButtonReleased events, when received, +/* ButtonPress and ButtonReleased events, when received, are copied into this queue for later processing. */ struct event_queue x_mouse_queue; @@ -215,6 +226,50 @@ static int highlight; static int curs_x; static int curs_y; +/* Mouse movement. + + In order to avoid asking for motion events and then throwing most + of them away or busy-polling the server for mouse positions, we ask + the server for pointer motion hints. This means that we get only + one event per group of mouse movements. "Groups" are delimited by + other kinds of events (focus changes and button clicks, for + example), or by XQueryPointer calls; when one of these happens, we + get another MotionNotify event the next time the mouse moves. This + is at least as efficient as getting motion events when mouse + tracking is on, and I suspect only negligibly worse when tracking + is off. + + The silly O'Reilly & Associates Nutshell guides barely document + pointer motion hints at all (I think you have to infer how they + work from an example), and the description of XQueryPointer doesn't + mention that calling it causes you to get another motion hint from + the server, which is very important. */ + +/* Where the mouse was last time we reported a mouse event. */ +static FRAME_PTR last_mouse_frame; +static XRectangle last_mouse_glyph; + +/* The scroll bar in which the last X motion event occurred. + + If the last X motion event occurred in a scroll bar, we set this + so XTmouse_position can know whether to report a scroll bar motion or + an ordinary motion. + + If the last X motion event didn't occur in a scroll bar, we set this + to Qnil, to tell XTmouse_position to return an ordinary motion event. */ +static Lisp_Object last_mouse_scroll_bar; + +/* Record which buttons are currently pressed. */ +unsigned int x_mouse_grabbed; + +/* This is a hack. We would really prefer that XTmouse_position would + return the time associated with the position it returns, but there + doesn't seem to be any way to wrest the timestamp from the server + along with the position query. So, we just keep track of the time + of the last movement we received, and return that in hopes that + it's somewhat accurate. */ +static Time last_mouse_movement_time; + #ifdef HAVE_X11 /* `t' if a mouse button is depressed. */ @@ -272,6 +327,7 @@ extern FONT_TYPE *XOpenFont (); static void flashback (); static void redraw_previous_char (); +static unsigned int x_x_to_emacs_modifiers (); #ifndef HAVE_X11 static void dumpqueue (); @@ -322,10 +378,6 @@ XTupdate_end (f) { int mask; - if (updating_frame == 0 - || updating_frame != f) - abort (); - BLOCK_INPUT; #ifndef HAVE_X11 dumpqueue (); @@ -412,7 +464,8 @@ XTcursor_to (row, col) compute_char_face and compute_glyph_face on everything it puts in the display structure, we can assume that the face code on each glyph is a valid index into FRAME_COMPUTED_FACES (f), and the one - to which we can actually apply intern_face. */ + to which we can actually apply intern_face. + Call this function with input blocked. */ #if 1 /* This is the multi-face code. */ @@ -471,11 +524,11 @@ dumpglyphs (f, left, top, gp, n, hl) /* First look at the face of the text itself. */ if (cf != 0) { - /* The face codes on the glyphs must be valid indices into the - frame's face table. */ + /* It's possible for the display table to specify + a face code that is out of range. Use 0 in that case. */ if (cf < 0 || cf >= FRAME_N_COMPUTED_FACES (f) || FRAME_COMPUTED_FACES (f) [cf] == 0) - abort (); + cf = 0; if (cf == 1) face = FRAME_MODE_LINE_FACE (f); @@ -699,7 +752,8 @@ XTclear_end_of_line (first_unused) /* Erase the character (if any) at the position just before X, Y in frame F, then redraw it and the character before it. This is necessary when we erase starting at X, - in case the character after X overlaps into the one before X. */ + in case the character after X overlaps into the one before X. + Call this function with input blocked. */ static void redraw_previous_char (f, x, y) @@ -827,7 +881,7 @@ XTflash (f) { struct timeval wakeup, now; - gettimeofday (&wakeup, (struct timezone *) 0); + EMACS_GET_TIME (wakeup); /* Compute time to wait until, propagating carry from usecs. */ wakeup.tv_usec += 150000; @@ -839,7 +893,7 @@ XTflash (f) { struct timeval timeout; - gettimeofday (&timeout, (struct timezone *)0); + EMACS_GET_TIME (timeout); /* In effect, timeout = wakeup - timeout. Break if result would be negative. */ @@ -867,9 +921,9 @@ XTflash (f) /* Make audible bell. */ #ifdef HAVE_X11 -#define XRINGBELL XBell(x_current_display, 0) +#define XRINGBELL XBell (x_current_display, 0) #else /* ! defined (HAVE_X11) */ -#define XRINGBELL XFeep(0); +#define XRINGBELL XFeep (0); #endif /* ! defined (HAVE_X11) */ XTring_bell () @@ -1094,7 +1148,8 @@ static void clear_cursor (); /* Output into a rectangle of an X-window (for frame F) the characters in f->phys_lines that overlap that rectangle. TOP and LEFT are the position of the upper left corner of the rectangle. - ROWS and COLS are the size of the rectangle. */ + ROWS and COLS are the size of the rectangle. + Call this function with input blocked. */ static void dumprectangle (f, left, top, cols, rows) @@ -1545,6 +1600,30 @@ x_find_modifier_meanings () XFreeModifiermap (mods); } +/* Prepare a menu-event in *RESULT for placement in the input queue. */ + +static Lisp_Object +construct_menu_click (result, event, f) + struct input_event *result; + XButtonEvent *event; + struct frame *f; +{ + /* Make the event type no_event; we'll change that when we decide + otherwise. */ + result->kind = mouse_click; + XSET (result->code, Lisp_Int, event->button - Button1); + result->timestamp = event->time; + result->modifiers = (x_x_to_emacs_modifiers (event->state) + | (event->type == ButtonRelease + ? up_modifier + : down_modifier)); + + { + XFASTINT (result->x) = event->x; + XFASTINT (result->y) = -1; /* special meaning for menubar */ + XSET (result->frame_or_window, Lisp_Frame, f); + } +} /* Convert between the modifier bits X uses and the modifier bits Emacs uses. */ @@ -1593,14 +1672,24 @@ x_is_vendor_fkey (sym) /* Given a pixel position (PIX_X, PIX_Y) on the frame F, return glyph co-ordinates in (*X, *Y). Set *BOUNDS to the rectangle - that the glyph at X, Y occupies, if BOUNDS != 0. */ + that the glyph at X, Y occupies, if BOUNDS != 0. + If NOCLIP is nonzero, do not force the value into range. */ + static void -pixel_to_glyph_coords (f, pix_x, pix_y, x, y, bounds) +pixel_to_glyph_coords (f, pix_x, pix_y, x, y, bounds, noclip) FRAME_PTR f; - register unsigned int pix_x, pix_y; + register int pix_x, pix_y; register int *x, *y; XRectangle *bounds; + int noclip; { + /* Arrange for the division in PIXEL_TO_CHAR_COL etc. to round down + even for negative values. */ + if (pix_x < 0) + pix_x -= FONT_WIDTH ((f)->display.x->font) - 1; + if (pix_y < 0) + pix_y -= FONT_HEIGHT ((f)->display.x->font) - 1; + pix_x = PIXEL_TO_CHAR_COL (f, pix_x); pix_y = PIXEL_TO_CHAR_ROW (f, pix_y); @@ -1612,19 +1701,23 @@ pixel_to_glyph_coords (f, pix_x, pix_y, x, y, bounds) bounds->y = CHAR_TO_PIXEL_ROW (f, pix_y); } - if (pix_x < 0) pix_x = 0; - else if (pix_x > f->width) pix_x = f->width; - - if (pix_y < 0) pix_y = 0; - else if (pix_y > f->height) pix_y = f->height; + if (!noclip) + { + if (pix_x < 0) + pix_x = 0; + else if (pix_x > f->width) + pix_x = f->width; + + if (pix_y < 0) + pix_y = 0; + else if (pix_y > f->height) + pix_y = f->height; + } *x = pix_x; *y = pix_y; } -/* Any buttons grabbed. */ -unsigned int x_mouse_grabbed; - /* Prepare a mouse-event in *RESULT for placement in the input queue. If the event is a button press, then note that we have grabbed @@ -1639,7 +1732,7 @@ construct_mouse_click (result, event, f) /* Make the event type no_event; we'll change that when we decide otherwise. */ result->kind = mouse_click; - XSET (result->code, Lisp_Int, event->button - Button1); + result->code = event->button - Button1; result->timestamp = event->time; result->modifiers = (x_x_to_emacs_modifiers (event->state) | (event->type == ButtonRelease @@ -1652,6 +1745,7 @@ construct_mouse_click (result, event, f) if (! x_mouse_grabbed) Vmouse_depressed = Qt; x_mouse_grabbed |= (1 << event->button); + last_mouse_frame = f; } else if (event->type == ButtonRelease) { @@ -1663,55 +1757,13 @@ construct_mouse_click (result, event, f) { int row, column; - pixel_to_glyph_coords (f, event->x, event->y, &column, &row, NULL); + pixel_to_glyph_coords (f, event->x, event->y, &column, &row, NULL, 0); XFASTINT (result->x) = column; XFASTINT (result->y) = row; XSET (result->frame_or_window, Lisp_Frame, f); } } - - -/* Mouse movement. Rah. - - In order to avoid asking for motion events and then throwing most - of them away or busy-polling the server for mouse positions, we ask - the server for pointer motion hints. This means that we get only - one event per group of mouse movements. "Groups" are delimited by - other kinds of events (focus changes and button clicks, for - example), or by XQueryPointer calls; when one of these happens, we - get another MotionNotify event the next time the mouse moves. This - is at least as efficient as getting motion events when mouse - tracking is on, and I suspect only negligibly worse when tracking - is off. - - The silly O'Reilly & Associates Nutshell guides barely document - pointer motion hints at all (I think you have to infer how they - work from an example), and the description of XQueryPointer doesn't - mention that calling it causes you to get another motion hint from - the server, which is very important. */ - -/* Where the mouse was last time we reported a mouse event. */ -static FRAME_PTR last_mouse_frame; -static XRectangle last_mouse_glyph; - -/* The scroll bar in which the last X motion event occurred. - - If the last X motion event occurred in a scroll bar, we set this - so XTmouse_position can know whether to report a scroll bar motion or - an ordinary motion. - - If the last X motion event didn't occur in a scroll bar, we set this - to Qnil, to tell XTmouse_position to return an ordinary motion event. */ -static Lisp_Object last_mouse_scroll_bar; - -/* This is a hack. We would really prefer that XTmouse_position would - return the time associated with the position it returns, but there - doesn't seem to be any way to wrest the timestamp from the server - along with the position query. So, we just keep track of the time - of the last movement we received, and return that in hopes that - it's somewhat accurate. */ -static Time last_mouse_movement_time; - + /* Function to report a mouse movement to the mainstream Emacs code. The input handler calls this. @@ -1776,7 +1828,7 @@ static void x_scroll_bar_report_motion (); static void XTmouse_position (f, bar_window, part, x, y, time) - FRAME_PTR f; + FRAME_PTR *f; Lisp_Object *bar_window; enum scroll_bar_part *part; Lisp_Object *x, *y; @@ -1784,10 +1836,6 @@ XTmouse_position (f, bar_window, part, x, y, time) { FRAME_PTR f1; - /* If this isn't an X-window frame, quit now. */ - if (!FRAME_X_P (f)) - return; - BLOCK_INPUT; if (! NILP (last_mouse_scroll_bar)) @@ -1832,40 +1880,60 @@ XTmouse_position (f, bar_window, part, x, y, time) int parent_x, parent_y; win = root; - for (;;) + + if (x_mouse_grabbed) { + /* If mouse was grabbed on a frame, give coords for that frame + even if the mouse is now outside it. */ XTranslateCoordinates (x_current_display, - + /* From-window, to-window. */ - root, win, + root, FRAME_X_WINDOW (last_mouse_frame), /* From-position, to-position. */ root_x, root_y, &win_x, &win_y, /* Child of win. */ &child); + f1 = last_mouse_frame; + } + else + { + while (1) + { + XTranslateCoordinates (x_current_display, - if (child == None) - break; + /* From-window, to-window. */ + root, win, - win = child; - parent_x = win_x; - parent_y = win_y; - } + /* From-position, to-position. */ + root_x, root_y, &win_x, &win_y, + + /* Child of win. */ + &child); + + if (child == None) + break; + + win = child; + parent_x = win_x; + parent_y = win_y; + } - /* Now we know that: - win is the innermost window containing the pointer - (XTC says it has no child containing the pointer), - win_x and win_y are the pointer's position in it - (XTC did this the last time through), and - parent_x and parent_y are the pointer's position in win's parent. - (They are what win_x and win_y were when win was child. - If win is the root window, it has no parent, and - parent_{x,y} are invalid, but that's okay, because we'll - never use them in that case.) */ - - /* Is win one of our frames? */ - f1 = x_window_to_frame (win); + /* Now we know that: + win is the innermost window containing the pointer + (XTC says it has no child containing the pointer), + win_x and win_y are the pointer's position in it + (XTC did this the last time through), and + parent_x and parent_y are the pointer's position in win's parent. + (They are what win_x and win_y were when win was child. + If win is the root window, it has no parent, and + parent_{x,y} are invalid, but that's okay, because we'll + never use them in that case.) */ + + /* Is win one of our frames? */ + f1 = x_window_to_frame (win); + } /* If not, is it one of our scroll bars? */ if (! f1) @@ -1886,7 +1954,7 @@ XTmouse_position (f, bar_window, part, x, y, time) and store all the values. */ pixel_to_glyph_coords (f1, win_x, win_y, &win_x, &win_y, - &last_mouse_glyph); + &last_mouse_glyph, x_mouse_grabbed); *bar_window = Qnil; *part = 0; @@ -1936,7 +2004,7 @@ x_window_to_scroll_bar (window_id) ! GC_NILP (bar) || (bar = condemned, condemned = Qnil, ! GC_NILP (bar)); - bar = XSCROLL_BAR(bar)->next) + bar = XSCROLL_BAR (bar)->next) if (SCROLL_BAR_X_WINDOW (XSCROLL_BAR (bar)) == window_id) return XSCROLL_BAR (bar); } @@ -1960,7 +2028,6 @@ x_scroll_bar_create (window, top, left, width, height) { XSetWindowAttributes a; unsigned long mask; - a.background_pixel = frame->display.x->background_pixel; a.event_mask = (ButtonPressMask | ButtonReleaseMask | ButtonMotionMask | PointerMotionHintMask @@ -1969,7 +2036,21 @@ x_scroll_bar_create (window, top, left, width, height) mask = (CWBackPixel | CWEventMask | CWCursor); - SET_SCROLL_BAR_X_WINDOW +#if 0 + + ac = 0; + XtSetArg (al[ac], XtNx, left); ac++; + XtSetArg (al[ac], XtNy, top); ac++; + XtSetArg (al[ac], XtNwidth, width); ac++; + XtSetArg (al[ac], XtNheight, height); ac++; + XtSetArg (al[ac], XtNborderWidth, 0); ac++; + sb_widget = XtCreateManagedWidget ("box", + boxWidgetClass, + frame->display.x->edit_widget, al, ac); + SET_SCROLL_BAR_X_WINDOW + (bar, sb_widget->core.window); +#endif + SET_SCROLL_BAR_X_WINDOW (bar, XCreateWindow (x_current_display, FRAME_X_WINDOW (frame), @@ -2365,7 +2446,7 @@ x_scroll_bar_handle_click (bar, event, emacs_event) abort (); emacs_event->kind = scroll_bar_click; - XSET (emacs_event->code, Lisp_Int, event->xbutton.button - Button1); + emacs_event->code = event->xbutton.button - Button1; emacs_event->modifiers = (x_x_to_emacs_modifiers (event->xbutton.state) | (event->type == ButtonRelease @@ -2560,6 +2641,45 @@ x_scroll_bar_clear (f) 0, 0, 0, 0, True); } +/* This processes Expose events from the menubar specific X event + loop in menubar.c. This allows to redisplay the frame if necessary + when handling menubar or popup items. */ + +void +process_expose_from_menu (event) + XEvent event; +{ + FRAME_PTR f; + + BLOCK_INPUT; + + f = x_window_to_frame (event.xexpose.window); + if (f) + { + if (f->async_visible == 0) + { + f->async_visible = 1; + f->async_iconified = 0; + SET_FRAME_GARBAGED (f); + } + else + { + dumprectangle (x_window_to_frame (event.xexpose.window), + event.xexpose.x, event.xexpose.y, + event.xexpose.width, event.xexpose.height); + } + } + else + { + struct scroll_bar *bar + = x_window_to_scroll_bar (event.xexpose.window); + + if (bar) + x_scroll_bar_expose (bar, &event); + } + + UNBLOCK_INPUT; +} /* The main X event-reading loop - XTread_socket. */ @@ -2675,7 +2795,12 @@ XTread_socket (sd, bufp, numchars, waitp, expected) { if (event.xclient.data.l[0] == Xatom_wm_take_focus) { +#ifdef USE_X_TOOLKIT + /* f = x_any_window_to_frame (event.xclient.window); */ + f = x_window_to_frame (event.xclient.window); +#else f = x_window_to_frame (event.xclient.window); +#endif if (f) x_focus_on_frame (f); /* Not certain about handling scroll bars here */ @@ -2696,9 +2821,17 @@ XTread_socket (sd, bufp, numchars, waitp, expected) struct frame *f = x_window_to_frame (event.xclient.window); if (f) - if (numchars > 0) - { - } + { + if (numchars == 0) + abort (); + + bufp->kind = delete_window_event; + XSET (bufp->frame_or_window, Lisp_Frame, f); + bufp++; + + count += 1; + numchars -= 1; + } } } else if (event.xclient.message_type == Xatom_wm_configure_denied) @@ -2707,22 +2840,40 @@ XTread_socket (sd, bufp, numchars, waitp, expected) else if (event.xclient.message_type == Xatom_wm_window_moved) { int new_x, new_y; - + struct frame *f = x_window_to_frame (event.xclient.window); + new_x = event.xclient.data.s[0]; new_y = event.xclient.data.s[1]; + + if (f) + { + f->display.x->left_pos = new_x; + f->display.x->top_pos = new_y; + } } } break; #ifdef NEW_SELECTIONS case SelectionNotify: +#ifdef USE_X_TOOLKIT + if (x_window_to_frame (event.xselection.requestor)) + x_handle_selection_notify (&event); + else + goto OTHER; +#else /* not USE_X_TOOLKIT */ x_handle_selection_notify (&event); +#endif /* not USE_X_TOOLKIT */ break; -#endif +#endif /* NEW_SELECTIONS */ case SelectionClear: /* Someone has grabbed ownership. */ #ifdef NEW_SELECTIONS { +#ifdef USE_X_TOOLKIT + if (x_window_to_frame (event.xselectionclear.window)) + { +#endif /* USE_X_TOOLKIT */ XSelectionClearEvent *eventp = (XSelectionClearEvent *) &event; if (numchars == 0) @@ -2736,17 +2887,26 @@ XTread_socket (sd, bufp, numchars, waitp, expected) count += 1; numchars -= 1; +#ifdef USE_X_TOOLKIT } -#else + else + goto OTHER; +#endif /* USE_X_TOOLKIT */ + } +#else /* not NEW_SELECTIONS */ x_disown_selection (event.xselectionclear.window, event.xselectionclear.selection, event.xselectionclear.time); -#endif +#endif /* not NEW_SELECTIONS */ break; case SelectionRequest: /* Someone wants our selection. */ #ifdef NEW_SELECTIONS { +#ifdef USE_X_TOOLKIT + if (x_window_to_frame (event.xselectionrequest.owner)) + { +#endif /* USE_X_TOOLKIT */ XSelectionRequestEvent *eventp = (XSelectionRequestEvent *) &event; if (numchars == 0) @@ -2763,16 +2923,28 @@ XTread_socket (sd, bufp, numchars, waitp, expected) count += 1; numchars -= 1; +#ifdef USE_X_TOOLKIT } -#else + else + goto OTHER; +#endif /* USE_X_TOOLKIT */ + } +#else /* not NEW_SELECTIONS */ x_answer_selection_request (event); -#endif +#endif /* not NEW_SELECTIONS */ break; case PropertyNotify: #ifdef NEW_SELECTIONS +#ifdef USE_X_TOOLKIT + if (x_any_window_to_frame (event.xproperty.window)) + x_handle_property_notify (&event); + else + goto OTHER; +#else /* not USE_X_TOOLKIT */ x_handle_property_notify (&event); -#else +#endif /* not USE_X_TOOLKIT */ +#else /* not NEW_SELECTIONS */ /* If we're being told about a root window property, then it's a cut buffer change. */ if (event.xproperty.window == ROOT_WINDOW) @@ -2786,7 +2958,7 @@ XTread_socket (sd, bufp, numchars, waitp, expected) about re-selecting. */ x_send_incremental (event); } -#endif +#endif /* not NEW_SELECTIONS */ break; case ReparentNotify: @@ -2816,9 +2988,13 @@ XTread_socket (sd, bufp, numchars, waitp, expected) { struct scroll_bar *bar = x_window_to_scroll_bar (event.xexpose.window); - + if (bar) - x_scroll_bar_expose (bar, &event); + x_scroll_bar_expose (bar, &event); +#ifdef USE_X_TOOLKIT + else + goto OTHER; +#endif /* USE_X_TOOLKIT */ } break; @@ -2833,6 +3009,10 @@ XTread_socket (sd, bufp, numchars, waitp, expected) event.xgraphicsexpose.width, event.xgraphicsexpose.height); } +#ifdef USE_X_TOOLKIT + else + goto OTHER; +#endif /* USE_X_TOOLKIT */ break; case NoExpose: /* This occurs when an XCopyArea's @@ -2904,10 +3084,17 @@ XTread_socket (sd, bufp, numchars, waitp, expected) if (FRAME_VISIBLE_P (f) || FRAME_ICONIFIED_P (f)) f->async_iconified = 1; } +#ifdef USE_X_TOOLKIT + goto OTHER; +#endif /* USE_X_TOOLKIT */ break; case MapNotify: +#ifdef USE_X_TOOLKIT + f = x_any_window_to_frame (event.xmap.window); +#else /* not USE_X_TOOLKIT */ f = x_window_to_frame (event.xmap.window); +#endif /* not USE_X_TOOLKIT */ if (f) { f->async_visible = 1; @@ -2917,7 +3104,10 @@ XTread_socket (sd, bufp, numchars, waitp, expected) the frame's display structures. */ SET_FRAME_GARBAGED (f); } - break; +#ifdef USE_X_TOOLKIT + goto OTHER; +#endif /* USE_X_TOOLKIT */ + break; /* Turn off processing if we become fully obscured. */ case VisibilityNotify: @@ -2940,7 +3130,9 @@ XTread_socket (sd, bufp, numchars, waitp, expected) if (f != 0) { KeySym keysym, orig_keysym; - unsigned char copy_buffer[80]; + /* al%imercury@uunet.uu.net says that making this 81 instead of + 80 fixed a bug whereby meta chars made his Emacs hang. */ + unsigned char copy_buffer[81]; int modifiers; event.xkey.state @@ -2975,6 +3167,45 @@ XTread_socket (sd, bufp, numchars, waitp, expected) incorrectly. */ || ((unsigned) (keysym) >= XK_Select && (unsigned)(keysym) < XK_KP_Space) +#endif +#ifdef XK_dead_circumflex + || orig_keysym == XK_dead_circumflex +#endif +#ifdef XK_dead_grave + || orig_keysym == XK_dead_grave +#endif +#ifdef XK_dead_tilde + || orig_keysym == XK_dead_tilde +#endif +#ifdef XK_dead_diaeresis + || orig_keysym == XK_dead_diaeresis +#endif +#ifdef XK_dead_macron + || orig_keysym == XK_dead_macron +#endif +#ifdef XK_dead_degree + || orig_keysym == XK_dead_degree +#endif +#ifdef XK_dead_acute + || orig_keysym == XK_dead_acute +#endif +#ifdef XK_dead_cedilla + || orig_keysym == XK_dead_cedilla +#endif +#ifdef XK_dead_breve + || orig_keysym == XK_dead_breve +#endif +#ifdef XK_dead_ogonek + || orig_keysym == XK_dead_ogonek +#endif +#ifdef XK_dead_caron + || orig_keysym == XK_dead_caron +#endif +#ifdef XK_dead_doubleacute + || orig_keysym == XK_dead_doubleacute +#endif +#ifdef XK_dead_abovedot + || orig_keysym == XK_dead_abovedot #endif || IsKeypadKey (keysym) /* 0xff80 <= x < 0xffbe */ || IsFunctionKey (keysym) /* 0xffbe <= x < 0xffe1 */ @@ -2994,7 +3225,7 @@ XTread_socket (sd, bufp, numchars, waitp, expected) temp_index = 0; temp_buffer[temp_index++] = keysym; bufp->kind = non_ascii_keystroke; - XSET (bufp->code, Lisp_Int, (unsigned) keysym - 0xff00); + bufp->code = keysym; XSET (bufp->frame_or_window, Lisp_Frame, f); bufp->modifiers = x_x_to_emacs_modifiers (modifiers); bufp->timestamp = event.xkey.time; @@ -3012,7 +3243,7 @@ XTread_socket (sd, bufp, numchars, waitp, expected) temp_index = 0; temp_buffer[temp_index++] = copy_buffer[i]; bufp->kind = ascii_keystroke; - XSET (bufp->code, Lisp_Int, copy_buffer[i]); + bufp->code = copy_buffer[i]; XSET (bufp->frame_or_window, Lisp_Frame, f); bufp->modifiers = x_x_to_emacs_modifiers (modifiers); bufp->timestamp = event.xkey.time; @@ -3066,7 +3297,7 @@ XTread_socket (sd, bufp, numchars, waitp, expected) for (i = 0; i < nbytes; i++) { bufp->kind = ascii_keystroke; - XSET (bufp->code, Lisp_Int, where_mapping[i]); + bufp->code = where_mapping[i]; XSET (bufp->time, Lisp_Int, event.xkey.time); XSET (bufp->frame_or_window, Lisp_Frame, f); bufp++; @@ -3102,7 +3333,9 @@ XTread_socket (sd, bufp, numchars, waitp, expected) } else if (f == x_focus_frame) x_new_focus_frame (0); - +#ifdef USE_X_TOOLKIT + goto OTHER; +#endif /* USE_X_TOOLKIT */ break; case FocusIn: @@ -3111,6 +3344,9 @@ XTread_socket (sd, bufp, numchars, waitp, expected) x_focus_event_frame = f; if (f) x_new_focus_frame (f); +#ifdef USE_X_TOOLKIT + goto OTHER; +#endif /* USE_X_TOOLKIT */ break; @@ -3131,6 +3367,9 @@ XTread_socket (sd, bufp, numchars, waitp, expected) if (f == x_focus_frame) x_new_focus_frame (0); } +#ifdef USE_X_TOOLKIT + goto OTHER; +#endif /* USE_X_TOOLKIT */ break; case FocusOut: @@ -3140,6 +3379,9 @@ XTread_socket (sd, bufp, numchars, waitp, expected) x_focus_event_frame = 0; if (f && f == x_focus_frame) x_new_focus_frame (0); +#ifdef USE_X_TOOLKIT + goto OTHER; +#endif /* USE_X_TOOLKIT */ break; #else /* ! defined (HAVE_X11) */ @@ -3181,21 +3423,31 @@ XTread_socket (sd, bufp, numchars, waitp, expected) #ifdef HAVE_X11 case MotionNotify: { - f = x_window_to_frame (event.xmotion.window); + if (x_mouse_grabbed) + f = last_mouse_frame; + else + f = x_window_to_frame (event.xmotion.window); if (f) note_mouse_movement (f, &event.xmotion); else { - struct scroll_bar *bar = - x_window_to_scroll_bar (event.xmotion.window); + struct scroll_bar *bar + = x_window_to_scroll_bar (event.xmotion.window); if (bar) x_scroll_bar_note_movement (bar, &event); } } +#ifdef USE_X_TOOLKIT + goto OTHER; +#endif /* USE_X_TOOLKIT */ break; case ConfigureNotify: +#ifdef USE_X_TOOLKIT + /* process done in widget.c */ + goto OTHER; +#else /* not USE_X_TOOLKIT */ f = x_window_to_frame (event.xconfigure.window); if (f) { @@ -3246,6 +3498,7 @@ XTread_socket (sd, bufp, numchars, waitp, expected) f->display.x->left_pos = event.xconfigure.x; f->display.x->top_pos = event.xconfigure.y; } +#endif /* not USE_X_TOOLKIT */ break; case ButtonPress: @@ -3260,8 +3513,7 @@ XTread_socket (sd, bufp, numchars, waitp, expected) if (f) { if (!x_focus_frame || (f == x_focus_frame)) - construct_mouse_click (&emacs_event, - &event, f); + construct_mouse_click (&emacs_event, &event, f); } else { @@ -3270,6 +3522,15 @@ XTread_socket (sd, bufp, numchars, waitp, expected) if (bar) x_scroll_bar_handle_click (bar, &event, &emacs_event); +#ifdef USE_X_TOOLKIT + else + { + f = x_any_window_to_frame (event.xbutton.window); + if (f && event.type == ButtonPress) + construct_menu_click (&emacs_event, + &event, f); + } +#endif /* USE_X_TOOLKIT */ } if (numchars >= 1 && emacs_event.kind != no_event) @@ -3279,6 +3540,10 @@ XTread_socket (sd, bufp, numchars, waitp, expected) count++; numchars--; } + +#ifdef USE_X_TOOLKIT + goto OTHER; +#endif /* USE_X_TOOLKIT */ } break; @@ -3306,13 +3571,13 @@ XTread_socket (sd, bufp, numchars, waitp, expected) if (numchars >= 2) { bufp->kind = ascii_keystroke; - bufp->code = (char) 'X' & 037; /* C-x */ + bufp->code = 'X' & 037; /* C-x */ XSET (bufp->frame_or_window, Lisp_Frame, f); XSET (bufp->time, Lisp_Int, event.xkey.time); bufp++; bufp->kind = ascii_keystroke; - bufp->code = (char) 0; /* C-@ */ + bufp->code = 0; /* C-@ */ XSET (bufp->frame_or_window, Lisp_Frame, f); XSET (bufp->time, Lisp_Int, event.xkey.time); bufp++; @@ -3343,13 +3608,29 @@ XTread_socket (sd, bufp, numchars, waitp, expected) case MappingKeyboard: XRefreshKeyboardMapping (&event.xmapping); } +#ifdef USE_X_TOOLKIT + goto OTHER; +#endif /* USE_X_TOOLKIT */ break; default: +#ifdef USE_X_TOOLKIT + OTHER: + BLOCK_INPUT; + XtDispatchEvent (&event); + UNBLOCK_INPUT; +#endif /* USE_X_TOOLKIT */ break; } } +#ifdef X_IO_BUG + if (! event_found) + /* On some systems, an X bug causes Emacs to get no more events + when the window is destroyed. Detect that. */ + XNoOp (x_current_display); +#endif /* X_IO_BUG */ + #ifdef HAVE_SELECT if (expected && ! event_found) { @@ -3357,13 +3638,15 @@ XTread_socket (sd, bufp, numchars, waitp, expected) there is an EOF condition; in other words, that X has died. Act as if there had been a hangup. */ int fd = ConnectionNumber (x_current_display); - SELECT_TYPE mask; + SELECT_TYPE mask, junk1, junk2; EMACS_TIME timeout; FD_ZERO (&mask); FD_SET (fd, &mask); EMACS_SET_SECS_USECS (timeout, 0, 0); - if (0 != select (fd + 1, &mask, (long *) 0, (long *) 0, &timeout) + FD_ZERO (&junk1); + FD_ZERO (&junk2); + if (0 != select (fd + 1, &mask, &junk1, &junk2, &timeout) && !XStuffPending ()) kill (getpid (), SIGHUP); } @@ -3674,6 +3957,8 @@ x_display_cursor (f, on) struct frame *f; int on; { + BLOCK_INPUT; + if (FRAME_DESIRED_CURSOR (f) == filled_box_cursor) x_display_box_cursor (f, on); else if (FRAME_DESIRED_CURSOR (f) == bar_cursor) @@ -3681,6 +3966,8 @@ x_display_cursor (f, on) else /* Those are the only two we have implemented! */ abort (); + + UNBLOCK_INPUT; } /* Icons. */ @@ -3941,7 +4228,7 @@ x_error_catcher (display, error) Calling x_uncatch_errors resumes the normal error handling. */ -void x_catch_errors(), x_check_errors (), x_uncatch_errors (); +void x_catch_errors (), x_check_errors (), x_uncatch_errors (); void x_catch_errors () @@ -4127,7 +4414,7 @@ x_new_font (f, fontname) XSetFont (x_current_display, f->display.x->cursor_gc, f->display.x->font->fid); - x_set_window_size (f, f->width, f->height); + x_set_window_size (f, 0, f->width, f->height); } { @@ -4159,14 +4446,12 @@ x_new_font (f, newname) f->display.x->font = temp; if (FRAME_X_WINDOW (f) != 0) - x_set_window_size (f, f->width, f->height); + x_set_window_size (f, 0, f->width, f->height); return 0; } #endif /* ! defined (HAVE_X11) */ -/* X Window sizes and positions. */ - x_calc_absolute_position (f) struct frame *f; { @@ -4197,13 +4482,13 @@ x_calc_absolute_position (f) position that fits on the screen. */ if (f->display.x->left_pos < 0) f->display.x->left_pos = (x_screen_width - - f->display.x->border_width - win_x + - 2 * f->display.x->border_width - win_x - PIXEL_WIDTH (f) + f->display.x->left_pos); if (f->display.x->top_pos < 0) f->display.x->top_pos = (x_screen_height - - f->display.x->border_width - win_y + - 2 * f->display.x->border_width - win_y - PIXEL_HEIGHT (f) + f->display.x->top_pos); @@ -4231,23 +4516,39 @@ x_set_offset (f, xoff, yoff) x_calc_absolute_position (f); BLOCK_INPUT; +#ifdef USE_X_TOOLKIT + XMoveWindow (XDISPLAY XtWindow (f->display.x->widget), + f->display.x->left_pos, f->display.x->top_pos); +#else /* not USE_X_TOOLKIT */ XMoveWindow (XDISPLAY FRAME_X_WINDOW (f), f->display.x->left_pos, f->display.x->top_pos); +#endif /* not USE_X_TOOLKIT */ #ifdef HAVE_X11 - x_wm_set_size_hint (f, 0, xoff, yoff); + x_wm_set_size_hint (f, 0, 1, xoff, yoff); #endif /* ! defined (HAVE_X11) */ UNBLOCK_INPUT; } -/* Call this to change the size of frame F's x-window. */ +/* Call this to change the size of frame F's x-window. + If CHANGE_GRAVITY is 1, we change to top-left-corner window gravity + for this size change and subsequent size changes. + Otherwise we leave the window gravity unchanged. */ -x_set_window_size (f, cols, rows) +x_set_window_size (f, change_gravity, cols, rows) struct frame *f; + int change_gravity; int cols, rows; { int pixelwidth, pixelheight; int mask; +#ifdef USE_X_TOOLKIT + BLOCK_INPUT; + EmacsFrameSetCharSize (f->display.x->edit_widget, cols, rows); + UNBLOCK_INPUT; + +#else /* not USE_X_TOOLKIT */ + BLOCK_INPUT; check_frame_size (f, &rows, &cols); @@ -4259,7 +4560,7 @@ x_set_window_size (f, cols, rows) pixelheight = CHAR_TO_PIXEL_HEIGHT (f, rows); #ifdef HAVE_X11 - x_wm_set_size_hint (f, 0, 0, 0); + x_wm_set_size_hint (f, 0, change_gravity, 0, 0); #endif /* ! defined (HAVE_X11) */ XChangeWindowSize (FRAME_X_WINDOW (f), pixelwidth, pixelheight); @@ -4285,6 +4586,7 @@ x_set_window_size (f, cols, rows) XFlushQueue (); UNBLOCK_INPUT; +#endif /* not USE_X_TOOLKIT */ } #ifndef HAVE_X11 @@ -4307,7 +4609,9 @@ x_set_mouse_position (f, x, y) { int pix_x, pix_y; +#if 0 /* Let the user ask for this if he wants it. */ x_raise_frame (f); +#endif pix_x = CHAR_TO_PIXEL_COL (f, x) + FONT_WIDTH (f->display.x->font) / 2; pix_y = CHAR_TO_PIXEL_ROW (f, y) + FONT_HEIGHT (f->display.x->font) / 2; @@ -4328,7 +4632,9 @@ x_set_mouse_position (f, x, y) x_focus_on_frame (f) struct frame *f; { +#if 0 /* This proves to be unpleasant. */ x_raise_frame (f); +#endif #if 0 /* I don't think that the ICCCM allows programs to do things like this without the interaction of the window manager. Whatever you end up @@ -4359,7 +4665,11 @@ x_raise_frame (f) if (f->async_visible) { BLOCK_INPUT; +#ifdef USE_X_TOOLKIT + XRaiseWindow (XDISPLAY XtWindow (f->display.x->widget)); +#else /* not USE_X_TOOLKIT */ XRaiseWindow (XDISPLAY FRAME_X_WINDOW (f)); +#endif /* not USE_X_TOOLKIT */ XFlushQueue (); UNBLOCK_INPUT; } @@ -4373,7 +4683,11 @@ x_lower_frame (f) if (f->async_visible) { BLOCK_INPUT; +#ifdef USE_X_TOOLKIT + XLowerWindow (XDISPLAY XtWindow (f->display.x->widget)); +#else /* not USE_X_TOOLKIT */ XLowerWindow (XDISPLAY FRAME_X_WINDOW (f)); +#endif /* not USE_X_TOOLKIT */ XFlushQueue (); UNBLOCK_INPUT; } @@ -4405,8 +4719,11 @@ x_make_frame_visible (f) #ifdef HAVE_X11 if (! EQ (Vx_no_window_manager, Qt)) x_wm_set_window_state (f, NormalState); - +#ifdef USE_X_TOOLKIT + XtPopup (f->display.x->widget, XtGrabNone); +#else /* not USE_X_TOOLKIT */ XMapWindow (XDISPLAY FRAME_X_WINDOW (f)); +#endif /* not USE_X_TOOLKIT */ if (FRAME_HAS_VERTICAL_SCROLL_BARS (f)) XMapSubwindows (x_current_display, FRAME_X_WINDOW (f)); #else /* ! defined (HAVE_X11) */ @@ -4446,8 +4763,13 @@ x_make_frame_invisible (f) #ifdef HAVE_X11R4 +#ifdef USE_X_TOOLKIT + if (! XWithdrawWindow (x_current_display, XtWindow (f->display.x->widget), + DefaultScreen (x_current_display))) +#else /* not USE_X_TOOLKIT */ if (! XWithdrawWindow (x_current_display, FRAME_X_WINDOW (f), DefaultScreen (x_current_display))) +#endif /* not USE_X_TOOLKIT */ { UNBLOCK_INPUT_RESIGNAL; error ("can't notify window manager of window withdrawal"); @@ -4462,7 +4784,11 @@ x_make_frame_invisible (f) XEvent unmap; unmap.xunmap.type = UnmapNotify; +#ifdef USE_X_TOOLKIT + unmap.xunmap.window = XtWindow (f->display.x->widget); +#else /* not USE_X_TOOLKIT */ unmap.xunmap.window = FRAME_X_WINDOW (f); +#endif /* not USE_X_TOOLKIT */ unmap.xunmap.event = DefaultRootWindow (x_current_display); unmap.xunmap.from_configure = False; if (! XSendEvent (x_current_display, @@ -4477,8 +4803,11 @@ x_make_frame_invisible (f) } /* Unmap the window ourselves. Cheeky! */ +#ifdef USE_X_TOOLKIT + XUnmapWindow (x_current_display, XtWindow (f->display.x->widget)); +#else /* not USE_X_TOOLKIT */ XUnmapWindow (x_current_display, FRAME_X_WINDOW (f)); - +#endif /* not USE_X_TOOLKIT */ #else /* ! defined (HAVE_X11) */ XUnmapWindow (FRAME_X_WINDOW (f)); @@ -4499,6 +4828,7 @@ x_iconify_frame (f) struct frame *f; { int mask; + int result; /* Don't keep the highlight on an invisible frame. */ if (x_highlight_frame == f) @@ -4507,6 +4837,23 @@ x_iconify_frame (f) if (f->async_iconified) return; +#ifdef USE_X_TOOLKIT + BLOCK_INPUT; + result = XIconifyWindow (x_current_display, + XtWindow (f->display.x->widget), + DefaultScreen (x_current_display)); + UNBLOCK_INPUT; + + if (!result) + error ("Can't notify window manager of iconification."); + + f->async_iconified = 1; + + BLOCK_INPUT; + XFlushQueue (); + UNBLOCK_INPUT; +#else /* not USE_X_TOOLKIT */ + BLOCK_INPUT; #ifdef HAVE_X11 @@ -4561,6 +4908,7 @@ x_iconify_frame (f) XFlushQueue (); UNBLOCK_INPUT; +#endif /* not USE_X_TOOLKIT */ } /* Destroy the X window of frame F. */ @@ -4573,6 +4921,10 @@ x_destroy_window (f) if (f->display.x->icon_desc != 0) XDestroyWindow (XDISPLAY f->display.x->icon_desc); XDestroyWindow (XDISPLAY f->display.x->window_desc); +#ifdef USE_X_TOOLKIT + XtDestroyWidget (f->display.x->widget); +#endif /* USE_X_TOOLKIT */ + free_frame_faces (f); XFlushQueue (); @@ -4602,7 +4954,7 @@ x_destroy_window (f) of certain kinds into our private queues. All ExposeRegion events are put in x_expose_queue. - All ButtonPressed and ButtonReleased events are put in x_mouse_queue. */ + All ButtonPress and ButtonRelease events are put in x_mouse_queue. */ /* Write the event *P_XREP into the event queue *QUEUE. @@ -4664,16 +5016,27 @@ mouse_event_pending_p () #ifdef HAVE_X11 +/* Record the gravity used previously, in case CHANGE_GRAVITY is 0. */ +static int previous_gravity; + /* SPEC_X and SPEC_Y are the specified positions. - We look only at their sign, to decide the gravity. */ + We look only at their sign, to decide the gravity. + If CHANGE_GRAVITY is 0, we ignore SPEC_X and SPEC_Y + and leave the gravity unchanged. */ -x_wm_set_size_hint (f, prompting, spec_x, spec_y) +x_wm_set_size_hint (f, prompting, change_gravity, spec_x, spec_y) struct frame *f; long prompting; + int change_gravity; int spec_x, spec_y; { XSizeHints size_hints; + +#ifdef USE_X_TOOLKIT + Window window = XtWindow (f->display.x->widget); +#else /* not USE_X_TOOLKIT */ Window window = FRAME_X_WINDOW (f); +#endif /* not USE_X_TOOLKIT */ size_hints.flags = PResizeInc | PMinSize /* | PMaxSize */; @@ -4741,21 +5104,28 @@ x_wm_set_size_hint (f, prompting, spec_x, spec_y) size_hints.flags |= USSize; } #if defined (PWinGravity) - switch (((spec_x < 0) << 1) + (spec_y < 0)) + if (change_gravity) { - case 0: - size_hints.win_gravity = NorthWestGravity; - break; - case 1: - size_hints.win_gravity = SouthWestGravity; - break; - case 2: - size_hints.win_gravity = NorthEastGravity; - break; - case 3: - size_hints.win_gravity = SouthEastGravity; - break; + switch (((spec_x < 0) << 1) + (spec_y < 0)) + { + case 0: + size_hints.win_gravity = NorthWestGravity; + break; + case 1: + size_hints.win_gravity = NorthEastGravity; + break; + case 2: + size_hints.win_gravity = SouthWestGravity; + break; + case 3: + size_hints.win_gravity = SouthEastGravity; + break; + } + previous_gravity = size_hints.win_gravity; } + else + size_hints.win_gravity = previous_gravity; + size_hints.flags |= PWinGravity; #endif /* PWinGravity */ @@ -4771,7 +5141,11 @@ x_wm_set_window_state (f, state) struct frame *f; int state; { +#ifdef USE_X_TOOLKIT + Window window = XtWindow (f->display.x->widget); +#else /* not USE_X_TOOLKIT */ Window window = FRAME_X_WINDOW (f); +#endif /* not USE_X_TOOLKIT */ f->display.x->wm_hints.flags |= StateHint; f->display.x->wm_hints.initial_state = state; @@ -4812,12 +5186,33 @@ x_wm_set_icon_position (f, icon_x, icon_y) /* Initialization. */ +#ifdef USE_X_TOOLKIT +static XrmOptionDescRec emacs_options[] = { + {"-geometry", ".geometry", XrmoptionSepArg, NULL}, + {"-iconic", ".iconic", XrmoptionNoArg, (XtPointer) "yes"}, + + {"-internal-border-width", "*EmacsScreen.internalBorderWidth", + XrmoptionSepArg, NULL}, + {"-ib", "*EmacsScreen.internalBorderWidth", XrmoptionSepArg, NULL}, + + {"-T", "*EmacsShell.title", XrmoptionSepArg, (XtPointer) NULL}, + {"-wn", "*EmacsShell.title", XrmoptionSepArg, (XtPointer) NULL}, + {"-title", "*EmacsShell.title", XrmoptionSepArg, (XtPointer) NULL}, + {"-iconname", "*EmacsShell.iconName", XrmoptionSepArg, (XtPointer) NULL}, + {"-in", "*EmacsShell.iconName", XrmoptionSepArg, (XtPointer) NULL}, + {"-mc", "*pointerColor", XrmoptionSepArg, (XtPointer) NULL}, + {"-cr", "*cursorColor", XrmoptionSepArg, (XtPointer) NULL} +}; +#endif /* USE_X_TOOLKIT */ + void x_term_init (display_name) char *display_name; { Lisp_Object frame; char *defaultvalue; + int argc = 0; + char** argv = 0; #ifndef F_SETOWN_BUG #ifdef F_SETOWN extern int old_fcntl_owner; @@ -4826,7 +5221,22 @@ x_term_init (display_name) x_focus_frame = x_highlight_frame = 0; +#ifdef USE_X_TOOLKIT + argv = (char **) XtMalloc (3 * sizeof (char *)); + argv [0] = ""; + argv [1] = "-display"; + argv [2] = display_name; + argc = 3; + Xt_app_shell = XtAppInitialize (&Xt_app_con, "Emacs", + emacs_options, XtNumber (emacs_options), + &argc, argv, + NULL, NULL, 0); + XtFree (argv); + x_current_display = XtDisplay (Xt_app_shell); + +#else /* not USE_X_TOOLKIT */ x_current_display = XOpenDisplay (display_name); +#endif /* not USE_X_TOOLKIT */ if (x_current_display == 0) fatal ("X server %s not responding.\n\ Check the DISPLAY environment variable or use \"-d\"\n", @@ -4834,30 +5244,10 @@ Check the DISPLAY environment variable or use \"-d\"\n", #ifdef HAVE_X11 { - int hostname_size = 256; - - hostname = (char *) xmalloc (hostname_size); - #if 0 XSetAfterFunction (x_current_display, x_trace_wire); #endif /* ! 0 */ - - /* Try to get the host name; if the buffer is too short, try - again. Apparently, the only indication gethostname gives of - whether the buffer was large enough is the presence or absence - of a '\0' in the string. Eech. */ - for (;;) - { - gethostname (hostname, hostname_size - 1); - hostname[hostname_size - 1] = '\0'; - - /* Was the buffer large enough for gethostname to store the '\0'? */ - if (strlen (hostname) < hostname_size - 1) - break; - - hostname_size <<= 1; - hostname = (char *) xrealloc (hostname, hostname_size); - } + hostname = get_system_name (); x_id_name = (char *) xmalloc (XSTRING (Vinvocation_name)->size + strlen (hostname) + 2);