static int XTcursor_to ();
static int XTclear_end_of_line ();
static int x_io_error_quitter ();
-void x_catch_errors ();
+int x_catch_errors ();
void x_uncatch_errors ();
\f
#if 0
Window window = FRAME_X_WINDOW (f);
int orig_left = left;
int gidx = 0;
- int pixel_width;
+ int i;
while (n > 0)
{
|| (cmpcharp == NULL && FAST_GLYPH_FACE (g) != cf))
break;
- if (c2)
+ if (c2 > 0)
cp->byte1 = c1, cp->byte2 = c2;
else
cp->byte1 = 0, cp->byte2 = c1;
/* LEN gets the length of the run. */
len = cp - buf;
- /* PIXEL_WIDTH get the pixcel width of the run. */
- pixel_width
- = (FONT_WIDTH (f->output_data.x->font)
- * (cmpcharp ? cmpcharp->width : len * CHARSET_WIDTH (charset)));
-
/* Now output this run of chars, with the font and pixel values
determined by the face code CF. */
{
XFontStruct *font = NULL;
GC gc;
int stippled = 0;
+ int line_height = f->output_data.x->line_height;
+ /* Pixel width of each glyph in this run. */
+ int glyph_width
+ = (FONT_WIDTH (f->output_data.x->font)
+ * (cmpcharp ? cmpcharp->width : CHARSET_WIDTH (charset)));
+ /* Overall pixel width of this run. */
+ int run_width
+ = (FONT_WIDTH (f->output_data.x->font)
+ * (cmpcharp ? cmpcharp->width : len * CHARSET_WIDTH (charset)));
/* A flag to tell if we have already filled background. We
fill background in advance in the following cases:
1) A face has stipple.
- 2) A height of font is different from that of the current line.
+ 2) A height of font is shorter than LINE_HEIGHT.
3) Drawing a composite character.
4) Font has non-zero _MULE_BASELINE_OFFSET property.
After filling background, we draw glyphs by XDrawString16. */
/* The property value of `_MULE_RELATIVE_COMPOSE' and
`_MULE_DEFAULT_ASCENT'. */
int relative_compose = 0, default_ascent = 0;
+ /* 1 if we find no font or a font of inappropriate size. */
+ int require_clipping;
/* HL = 3 means use a mouse face previously chosen. */
if (hl == 3)
stippled = 1;
}
+#define FACE_DEFAULT (~0)
+
/* Setting appropriate font and gc for this charset. */
if (charset != CHARSET_ASCII)
{
struct font_info *fontp;
if ((fontset < 0 && (fontset = FRAME_FONTSET (f)) < 0)
- || !(fontp = fs_load_font (f, FRAME_X_FONT_TABLE (f),
+ || !(fontp = FS_LOAD_FONT (f, FRAME_X_FONT_TABLE (f),
charset, NULL, fontset)))
goto font_not_found;
font = (XFontStruct *) (fontp->font);
gc = FACE_NON_ASCII_GC (face);
XSetFont (FRAME_X_DISPLAY (f), gc, font->fid);
- if (font->max_byte1 != 0)
- baseline = (f->output_data.x->line_height
- + font->ascent - font->descent) / 2;
- else
- baseline = (f->output_data.x->font_baseline
- - fontp->baseline_offset);
+ baseline
+ = (font->max_byte1 != 0
+ ? (line_height + font->ascent - font->descent) / 2
+ : f->output_data.x->font_baseline - fontp->baseline_offset);
+ if (FONT_HEIGHT (font) <= line_height
+ && (font->ascent > baseline
+ || font->descent > line_height - baseline))
+ /* Adjust baseline for this font to show the whole
+ glyphs in a line. */
+ baseline = line_height - font->descent;
+
if (cmpcharp && cmpcharp->cmp_rule == NULL)
{
relative_compose = fontp->relative_compose;
}
else
{
- font = FACE_FONT (face);
- baseline = FONT_BASE (font);
font_not_found:
- gc = FACE_GC (face);
+ if (charset == CHARSET_ASCII || charset == charset_latin_iso8859_1)
+ {
+ font = FACE_FONT (face);
+ if (font == (XFontStruct *) FACE_DEFAULT)
+ font = f->output_data.x->font;
+ baseline = FONT_BASE (font);
+ if (charset == charset_latin_iso8859_1)
+ {
+ if (font->max_char_or_byte2 < 0x80)
+ /* This font can't display Latin1 characters. */
+ font = NULL;
+ else
+ {
+ for (cp = buf; cp < buf + len; cp++)
+ cp->byte2 |= 0x80;
+ }
+ }
+ }
+ gc = FACE_GC (face);
}
-#define FACE_DEFAULT (~0)
-
/* Now override that if the cursor's on this character. */
if (hl == 2)
{
/* The cursor overrides stippling. */
stippled = 0;
- if (!cmpcharp
- && (!font
- || font == (XFontStruct *) FACE_DEFAULT
- || font == f->output_data.x->font)
+ if (font == f->output_data.x->font
&& face->background == f->output_data.x->background_pixel
- && face->foreground == f->output_data.x->foreground_pixel)
+ && face->foreground == f->output_data.x->foreground_pixel
+ && !cmpcharp)
{
gc = f->output_data.x->cursor_gc;
}
}
}
- if (font == (XFontStruct *) FACE_DEFAULT)
- font = f->output_data.x->font;
+ if (font)
+ require_clipping = (!NILP (Vclip_large_size_font)
+ && (font->ascent > baseline
+ || font->descent > line_height - baseline
+ || (!cmpcharp
+ && FONT_WIDTH (font) > glyph_width)));
if (font && (just_foreground || (cmpcharp && gidx > 0)))
background_filled = 1;
- else if (!font
- || stippled
- || f->output_data.x->line_height != FONT_HEIGHT (font)
- || cmpcharp
- || baseline != f->output_data.x->font_baseline)
+ else if (stippled)
{
- if (!stippled)
- /* This is to fill a rectangle with background color. */
- XSetStipple (FRAME_X_DISPLAY (f), gc,
- FRAME_X_DISPLAY_INFO (f)->null_pixel);
/* Turn stipple on. */
XSetFillStyle (FRAME_X_DISPLAY (f), gc, FillOpaqueStippled);
/* Draw stipple or background color on background. */
XFillRectangle (FRAME_X_DISPLAY (f), window, gc,
- left, top, pixel_width,
- f->output_data.x->line_height);
+ left, top, run_width, line_height);
/* Turn stipple off. */
XSetFillStyle (FRAME_X_DISPLAY (f), gc, FillSolid);
+ background_filled = 1;
+ }
+ else if (!font
+ || FONT_HEIGHT (font) < line_height
+ || FONT_WIDTH (font) < glyph_width
+ || cmpcharp)
+ {
+ /* Fill a area for the current run in background pixle of GC. */
+ XGCValues xgcv;
+ unsigned long mask = GCForeground | GCBackground;
+ unsigned long fore, back;
+
+ /* The current code at first set foreground to background,
+ fill the area, then recover the original foreground.
+ Aren't there any smarter ways? */
+
+ XGetGCValues (FRAME_X_DISPLAY (f), gc, mask, &xgcv);
+ XSetForeground (FRAME_X_DISPLAY (f), gc, xgcv.background);
+ XFillRectangle (FRAME_X_DISPLAY (f), window, gc,
+ left, top, run_width, line_height);
+ XSetForeground (FRAME_X_DISPLAY (f), gc, xgcv.foreground);
+
background_filled = 1;
if (cmpcharp)
/* To assure not to fill background while drawing
if (font)
{
- if (cmpcharp)
+ if (require_clipping)
+ {
+ Region region; /* Region used for setting clip mask to GC. */
+ XPoint x[4]; /* Data used for creating REGION. */
+
+ x[0].x = x[3].x = left, x[1].x = x[2].x = left + glyph_width;
+ x[0].y = x[1].y = top, x[2].y = x[3].y = top + line_height;
+ region = XPolygonRegion (x, 4, EvenOddRule);
+ XSetRegion (FRAME_X_DISPLAY (f), gc, region);
+ XDestroyRegion (region);
+ }
+
+ if (!cmpcharp)
+ {
+ if (require_clipping || FONT_WIDTH (font) != glyph_width)
+ for (i = 0; i < len; i++)
+ {
+ if (require_clipping && i > 0)
+ XSetClipOrigin (FRAME_X_DISPLAY (f), gc,
+ glyph_width * i, 0);
+ if (background_filled)
+ XDrawString16 (FRAME_X_DISPLAY (f), window, gc,
+ left + glyph_width * i,
+ top + baseline, buf + i, 1);
+ else
+ XDrawImageString16 (FRAME_X_DISPLAY (f), window, gc,
+ left + glyph_width * i,
+ top + baseline, buf + i, 1);
+ }
+ else
+ {
+ if (background_filled)
+ XDrawString16 (FRAME_X_DISPLAY (f), window, gc,
+ left, top + baseline, buf, len);
+ else
+ XDrawImageString16 (FRAME_X_DISPLAY (f), window, gc,
+ left, top + baseline, buf, len);
+ }
+ }
+ else
{
XCharStruct *pcm; /* Pointer to per char metric info. */
- int i;
if ((cmpcharp->cmp_rule || relative_compose)
&& gidx == 0)
buf + i, 1);
}
}
- else if (background_filled)
- XDrawString16 (FRAME_X_DISPLAY (f), window, gc,
- left, top + baseline, buf, len);
- else
- XDrawImageString16 (FRAME_X_DISPLAY (f), window, gc,
- left, top + baseline, buf, len);
-
- /* Clear the rest of the line's height. */
- if (f->output_data.x->line_height > FONT_HEIGHT (font))
- XClearArea (FRAME_X_DISPLAY (f), window, left,
- top + FONT_HEIGHT (font),
- FONT_WIDTH (font) * len,
- /* This is how many pixels of height
- we have to clear. */
- f->output_data.x->line_height - FONT_HEIGHT (font),
- False);
+ if (require_clipping)
+ XSetClipMask (FRAME_X_DISPLAY (f), gc, None);
#if 0 /* Doesn't work, because it uses FRAME_CURRENT_GLYPHS,
which often is not up to date yet. */
}
#endif
}
- else
+ if (!font)
{
- /* There's no appropriate font for this glyph. Just show
- rectangles. */
+ /* Show rectangles to indicate that we found no font. */
+ int limit = cmpcharp ? 1 : len;
- if (cmpcharp)
- XDrawRectangle
- (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), gc,
- left, top + 1,
- pixel_width - 2, f->output_data.x->line_height - 3);
- else
+ for (i = 0; i < limit; i++)
+ XDrawRectangle (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), gc,
+ left + glyph_width * i, top,
+ glyph_width - 1, line_height - 1);
+ }
+ else if (require_clipping && !NILP (Vhighlight_wrong_size_font))
+ {
+ /* Show ??? to indicate that we found a font of
+ inappropriate size. */
+ int limit = cmpcharp ? 1 : len;
+
+ for (i = 0; i < limit; i++)
{
- int left_offset;
- int left_skip_step = (FONT_WIDTH (f->output_data.x->font)
- * CHARSET_WIDTH (charset));
-
- for (left_offset = 0; left_offset < pixel_width;
- left_offset += left_skip_step)
- XDrawRectangle
- (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), gc,
- left + left_offset, top + 1,
- left_skip_step - 2, f->output_data.x->line_height - 3);
+ XDrawLine (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), gc,
+ left + glyph_width * i, top + line_height - 1,
+ left + glyph_width * i + 1, top + line_height - 1);
+ XDrawLine (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), gc,
+ left + glyph_width * i, top + line_height - 3,
+ left + glyph_width * i, top + line_height - 1);
}
}
-
+
/* We should probably check for XA_UNDERLINE_POSITION and
XA_UNDERLINE_THICKNESS properties on the font, but let's
just get the thing working, and come back to that. */
on the default font of this frame. */
int underline_position = f->output_data.x->font_baseline + 1;
- if (underline_position >= f->output_data.x->line_height)
- underline_position = f->output_data.x->line_height - 1;
+ if (underline_position >= line_height)
+ underline_position = line_height - 1;
if (face->underline)
XFillRectangle (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
FACE_GC (face),
- left, top + underline_position, pixel_width, 1);
+ left, top + underline_position, run_width, 1);
}
if (!cmpcharp)
- left += pixel_width;
+ left += run_width;
}
}
/* Make the event type no_event; we'll change that when we decide
otherwise. */
result->kind = mouse_click;
- XSETINT (result->code, event->button - Button1);
+ result->code = event->button - Button1;
result->timestamp = event->time;
result->modifiers = (x_x_to_emacs_modifiers (FRAME_X_DISPLAY_INFO (f),
event->state)
if (WINDOWP (window) && portion == 0 && row >= 0 && column >= 0
&& row < FRAME_HEIGHT (f) && column < FRAME_WIDTH (f)
&& EQ (w->window_end_valid, w->buffer)
- && w->last_modified == BUF_MODIFF (XBUFFER (w->buffer))
- && w->last_overlay_modified == BUF_OVERLAY_MODIFF (XBUFFER (w->buffer)))
+ && XFASTINT (w->last_modified) == BUF_MODIFF (XBUFFER (w->buffer))
+ && (XFASTINT (w->last_overlay_modified)
+ == BUF_OVERLAY_MODIFF (XBUFFER (w->buffer))))
{
int *ptr = FRAME_CURRENT_GLYPHS (f)->charstarts[row];
int i, pos;
/* Put all the overlays we want in a vector in overlay_vec.
Store the length in len. */
- noverlays = overlays_at (XINT (pos), 1, &overlay_vec, &len,
+ noverlays = overlays_at (pos, 1, &overlay_vec, &len,
NULL, NULL);
noverlays = sort_overlays (overlay_vec, noverlays, w);
int i;
int row = 0;
int left = WINDOW_LEFT_MARGIN (w);
- int top = w->top;
+ int top = XFASTINT (w->top);
int height = XFASTINT (w->height) - ! MINI_WINDOW_P (w);
int width = window_internal_width (w);
int *charstarts;
Window win, child;
int win_x, win_y;
int parent_x, parent_y;
+ int count;
win = root;
structure is changing at the same time this function
is running. So at least we must not crash from them. */
- x_catch_errors (FRAME_X_DISPLAY (*fp));
+ count = x_catch_errors (FRAME_X_DISPLAY (*fp));
if (FRAME_X_DISPLAY_INFO (*fp)->grabbed && last_mouse_frame
&& FRAME_LIVE_P (last_mouse_frame))
if (x_had_errors_p (FRAME_X_DISPLAY (*fp)))
f1 = 0;
- x_uncatch_errors (FRAME_X_DISPLAY (*fp));
+ x_uncatch_errors (FRAME_X_DISPLAY (*fp), count);
/* If not, is it one of our scroll bars? */
if (! f1)
{
f->async_visible = 1;
f->async_iconified = 0;
+ f->output_data.x->has_been_visible = 1;
SET_FRAME_GARBAGED (f);
}
else
{
f->async_visible = 1;
f->async_iconified = 0;
+ f->output_data.x->has_been_visible = 1;
SET_FRAME_GARBAGED (f);
}
else
/* We can't distinguish, from the event, whether the window
has become iconified or invisible. So assume, if it
was previously visible, than now it is iconified.
- We depend on x_make_frame_invisible to mark it invisible. */
+ But x_make_frame_invisible clears both
+ the visible flag and the iconified flag;
+ and that way, we know the window is not iconified now. */
if (FRAME_VISIBLE_P (f) || FRAME_ICONIFIED_P (f))
- f->async_iconified = 1;
+ {
+ f->async_iconified = 1;
- bufp->kind = iconify_event;
- XSETFRAME (bufp->frame_or_window, f);
- bufp++;
- count++;
- numchars--;
+ bufp->kind = iconify_event;
+ XSETFRAME (bufp->frame_or_window, f);
+ bufp++;
+ count++;
+ numchars--;
+ }
}
goto OTHER;
{
f->async_visible = 1;
f->async_iconified = 0;
+ f->output_data.x->has_been_visible = 1;
/* wait_reading_process_input will notice this and update
the frame's display structures. */
count++;
numchars--;
}
- else if (! NILP(Vframe_list)
+ else if (! NILP (Vframe_list)
&& ! NILP (XCONS (Vframe_list)->cdr))
/* Force a redisplay sooner or later
to update the frame titles
{
if (((keysym >= XK_BackSpace && keysym <= XK_Escape)
|| keysym == XK_Delete
+#ifdef XK_ISO_Left_Tab
+ || (keysym >= XK_ISO_Left_Tab && keysym <= XK_ISO_Enter)
+#endif
|| IsCursorKey (keysym) /* 0xff50 <= x < 0xff60 */
|| IsMiscFunctionKey (keysym) /* 0xff60 <= x < VARIES */
#ifdef HPUX
goto OTHER;
case ConfigureNotify:
- f = x_any_window_to_frame (dpyinfo, event.xconfigure.window);
- if (f
-#ifdef USE_X_TOOLKIT
- && (event.xconfigure.window == XtWindow (f->output_data.x->widget))
-#endif
- )
+ f = x_top_window_to_frame (dpyinfo, event.xconfigure.window);
+ if (f)
{
#ifndef USE_X_TOOLKIT
/* In the toolkit version, change_frame_size
}
#endif
- /* Formerly, in the USE_X_TOOLKIT version,
- we did not test send_event here. */
- if (1
-#ifndef USE_X_TOOLKIT
- && ! event.xconfigure.send_event
-#endif
- )
- {
- Window win, child;
- int win_x, win_y;
-
- /* Find the position of the outside upper-left corner of
- the window, in the root coordinate system. Don't
- refer to the parent window here; we may be processing
- this event after the window manager has changed our
- parent, but before we have reached the ReparentNotify. */
- XTranslateCoordinates (FRAME_X_DISPLAY (f),
-
- /* From-window, to-window. */
- event.xconfigure.window,
- FRAME_X_DISPLAY_INFO (f)->root_window,
-
- /* From-position, to-position. */
- -event.xconfigure.border_width,
- -event.xconfigure.border_width,
- &win_x, &win_y,
-
- /* Child of win. */
- &child);
- event.xconfigure.x = win_x;
- event.xconfigure.y = win_y;
- }
-
f->output_data.x->pixel_width = event.xconfigure.width;
f->output_data.x->pixel_height = event.xconfigure.height;
- f->output_data.x->left_pos = event.xconfigure.x;
- f->output_data.x->top_pos = event.xconfigure.y;
/* What we have now is the position of Emacs's own window.
Convert that to the position of the window manager window. */
- {
- int x, y;
- x_real_positions (f, &x, &y);
- f->output_data.x->left_pos = x;
- f->output_data.x->top_pos = y;
- /* Formerly we did not do this in the USE_X_TOOLKIT
- version. Let's try making them the same. */
-/* #ifndef USE_X_TOOLKIT */
- if (y != event.xconfigure.y)
- {
- /* Since the WM decorations come below top_pos now,
- we must put them below top_pos in the future. */
- f->output_data.x->win_gravity = NorthWestGravity;
- x_wm_set_size_hint (f, (long) 0, 0);
- }
-/* #endif */
- }
+ x_real_positions (f, &f->output_data.x->left_pos,
+ &f->output_data.x->top_pos);
+
+ if (f->output_data.x->parent_desc != FRAME_X_DISPLAY_INFO (f)->root_window)
+ {
+ /* Since the WM decorations come below top_pos now,
+ we must put them below top_pos in the future. */
+ f->output_data.x->win_gravity = NorthWestGravity;
+ x_wm_set_size_hint (f, (long) 0, 0);
+ }
}
goto OTHER;
return 0;
}
\f
+#define X_ERROR_MESSAGE_SIZE 200
+
+/* If non-nil, this should be a string.
+ It means catch X errors and store the error message in this string. */
+
+static Lisp_Object x_error_message_string;
+
+/* An X error handler which stores the error message in
+ x_error_message_string. This is called from x_error_handler if
+ x_catch_errors is in effect. */
+
+static int
+x_error_catcher (display, error)
+ Display *display;
+ XErrorEvent *error;
+{
+ XGetErrorText (display, error->error_code,
+ XSTRING (x_error_message_string)->data,
+ X_ERROR_MESSAGE_SIZE);
+}
+
+/* Begin trapping X errors for display DPY. Actually we trap X errors
+ for all displays, but DPY should be the display you are actually
+ operating on.
+
+ After calling this function, X protocol errors no longer cause
+ Emacs to exit; instead, they are recorded in the string
+ stored in x_error_message_string.
+
+ Calling x_check_errors signals an Emacs error if an X error has
+ occurred since the last call to x_catch_errors or x_check_errors.
+
+ Calling x_uncatch_errors resumes the normal error handling. */
+
+void x_check_errors ();
+static Lisp_Object x_catch_errors_unwind ();
+
+int
+x_catch_errors (dpy)
+ Display *dpy;
+{
+ int count = specpdl_ptr - specpdl;
+
+ /* Make sure any errors from previous requests have been dealt with. */
+ XSync (dpy, False);
+
+ record_unwind_protect (x_catch_errors_unwind, x_error_message_string);
+
+ x_error_message_string = make_uninit_string (X_ERROR_MESSAGE_SIZE);
+ XSTRING (x_error_message_string)->data[0] = 0;
+
+ return count;
+}
+
+/* Unbind the binding that we made to check for X errors. */
+
+static Lisp_Object
+x_catch_errors_unwind (old_val)
+ Lisp_Object old_val;
+{
+ x_error_message_string = old_val;
+ return Qnil;
+}
+
+/* If any X protocol errors have arrived since the last call to
+ x_catch_errors or x_check_errors, signal an Emacs error using
+ sprintf (a buffer, FORMAT, the x error message text) as the text. */
+
+void
+x_check_errors (dpy, format)
+ Display *dpy;
+ char *format;
+{
+ /* Make sure to catch any errors incurred so far. */
+ XSync (dpy, False);
+
+ if (XSTRING (x_error_message_string)->data[0])
+ error (format, XSTRING (x_error_message_string)->data);
+}
+
+/* Nonzero if we had any X protocol errors
+ since we did x_catch_errors on DPY. */
+
+int
+x_had_errors_p (dpy)
+ Display *dpy;
+{
+ /* Make sure to catch any errors incurred so far. */
+ XSync (dpy, False);
+
+ return XSTRING (x_error_message_string)->data[0] != 0;
+}
+
+/* Forget about any errors we have had, since we did x_catch_errors on DPY. */
+
+int
+x_clear_errors (dpy)
+ Display *dpy;
+{
+ XSTRING (x_error_message_string)->data[0] = 0;
+}
+
+/* Stop catching X protocol errors and let them make Emacs die.
+ DPY should be the display that was passed to x_catch_errors.
+ COUNT should be the value that was returned by
+ the corresponding call to x_catch_errors. */
+
+void
+x_uncatch_errors (dpy, count)
+ Display *dpy;
+ int count;
+{
+ unbind_to (count, Qnil);
+}
+
+#if 0
+static unsigned int x_wire_count;
+x_trace_wire ()
+{
+ fprintf (stderr, "Lib call: %d\n", ++x_wire_count);
+}
+#endif /* ! 0 */
+
+\f
+/* Handle SIGPIPE, which can happen when the connection to a server
+ simply goes away. SIGPIPE is handled by x_connection_signal.
+ Don't need to do anything, because the write which caused the
+ SIGPIPE will fail, causing Xlib to invoke the X IO error handler,
+ which will do the appropriate cleanup for us. */
+
+static SIGTYPE
+x_connection_signal (signalnum) /* If we don't have an argument, */
+ int signalnum; /* some compilers complain in signal calls. */
+{
+#ifdef USG
+ /* USG systems forget handlers when they are used;
+ must reestablish each time */
+ signal (signalnum, x_connection_signal);
+#endif /* USG */
+}
+\f
/* Handling X errors. */
/* Handle the loss of connection to display DISPLAY. */
/* Indicate that this display is dead. */
- #ifdef USE_X_TOOLKIT
+#ifdef USE_X_TOOLKIT
XtCloseDisplay (display);
- #endif
+#endif
dpyinfo->display = 0;
x_connection_closed (display, buf1);
}
-/* This is the handler for X IO errors, always.
- It kills all frames on the display that we lost touch with.
- If that was the only one, it prints an error message and kills Emacs. */
+/* This is the first-level handler for X protocol errors.
+ It calls x_error_quitter or x_error_catcher. */
static int
-x_io_error_quitter (display)
+x_error_handler (display, error)
Display *display;
+ XErrorEvent *error;
{
- char buf[256];
+ char buf[256], buf1[356];
- sprintf (buf, "Connection lost to X server `%s'", DisplayString (display));
- x_connection_closed (display, buf);
-}
-\f
-/* Handle SIGPIPE, which can happen when the connection to a server
- simply goes away. SIGPIPE is handled by x_connection_signal.
- Don't need to do anything, because the write which caused the
- SIGPIPE will fail, causing Xlib to invoke the X IO error handler,
- which will do the appropriate cleanup for us. */
-
-static SIGTYPE
-x_connection_signal (signalnum) /* If we don't have an argument, */
- int signalnum; /* some compilers complain in signal calls. */
-{
-#ifdef USG
- /* USG systems forget handlers when they are used;
- must reestablish each time */
- signal (signalnum, x_connection_signal);
-#endif /* USG */
+ if (! NILP (x_error_message_string))
+ x_error_catcher (display, error);
+ else
+ x_error_quitter (display, error);
}
-\f
-/* A buffer for storing X error messages. */
-static char *x_caught_error_message;
-#define X_CAUGHT_ERROR_MESSAGE_SIZE 200
-/* An X error handler which stores the error message in
- x_caught_error_message. This is what's installed when
- x_catch_errors is in effect. */
+/* This is the handler for X IO errors, always.
+ It kills all frames on the display that we lost touch with.
+ If that was the only one, it prints an error message and kills Emacs. */
static int
-x_error_catcher (display, error)
+x_io_error_quitter (display)
Display *display;
- XErrorEvent *error;
-{
- XGetErrorText (display, error->error_code,
- x_caught_error_message, X_CAUGHT_ERROR_MESSAGE_SIZE);
-}
-
-
-/* Begin trapping X errors for display DPY. Actually we trap X errors
- for all displays, but DPY should be the display you are actually
- operating on.
-
- After calling this function, X protocol errors no longer cause
- Emacs to exit; instead, they are recorded in x_cfc_error_message.
-
- Calling x_check_errors signals an Emacs error if an X error has
- occurred since the last call to x_catch_errors or x_check_errors.
-
- Calling x_uncatch_errors resumes the normal error handling. */
-
-void x_catch_errors (), x_check_errors (), x_uncatch_errors ();
-
-void
-x_catch_errors (dpy)
- Display *dpy;
-{
- /* Make sure any errors from previous requests have been dealt with. */
- XSync (dpy, False);
-
- /* Set up the error buffer. */
- x_caught_error_message
- = (char*) xmalloc (X_CAUGHT_ERROR_MESSAGE_SIZE);
- x_caught_error_message[0] = '\0';
-
- /* Install our little error handler. */
- XSetErrorHandler (x_error_catcher);
-}
-
-/* If any X protocol errors have arrived since the last call to
- x_catch_errors or x_check_errors, signal an Emacs error using
- sprintf (a buffer, FORMAT, the x error message text) as the text. */
-
-void
-x_check_errors (dpy, format)
- Display *dpy;
- char *format;
-{
- /* Make sure to catch any errors incurred so far. */
- XSync (dpy, False);
-
- if (x_caught_error_message[0])
- {
- char buf[X_CAUGHT_ERROR_MESSAGE_SIZE + 56];
-
- sprintf (buf, format, x_caught_error_message);
- x_uncatch_errors (dpy);
- error (buf);
- }
-}
-
-/* Nonzero if we had any X protocol errors since we did x_catch_errors. */
-
-int
-x_had_errors_p (dpy)
- Display *dpy;
{
- /* Make sure to catch any errors incurred so far. */
- XSync (dpy, False);
-
- return x_caught_error_message[0] != 0;
-}
-
-/* Stop catching X protocol errors and let them make Emacs die. */
-
-void
-x_uncatch_errors (dpy)
- Display *dpy;
-{
- xfree (x_caught_error_message);
- x_caught_error_message = 0;
- XSetErrorHandler (x_error_quitter);
-}
+ char buf[256];
-#if 0
-static unsigned int x_wire_count;
-x_trace_wire ()
-{
- fprintf (stderr, "Lib call: %d\n", ++x_wire_count);
+ sprintf (buf, "Connection lost to X server `%s'", DisplayString (display));
+ x_connection_closed (display, buf);
}
-#endif /* ! 0 */
-
\f
/* Changing the font of the frame. */
/* Give frame F the fontset named FONTSETNAME as its default font, and
return the full name of that fontset. FONTSETNAME may be a wildcard
- pattern; in that case, we choose some font that fits the pattern.
- The return value shows which font we chose. */
+ pattern; in that case, we choose some fontset that fits the pattern.
+ The return value shows which fontset we chose. */
Lisp_Object
x_new_fontset (f, fontsetname)
if (fontset < 0)
return Qnil;
+ if (f->output_data.x->fontset == fontset)
+ /* This fontset is already set in frame F. There's nothing more
+ to do. */
+ return build_string (fontsetname);
+
fontsetp = FRAME_FONTSET_DATA (f)->fontset_table[fontset];
if (!fontsetp->fontname[CHARSET_ASCII])
/* Since x_new_font doesn't update any fontset information, do it now. */
f->output_data.x->fontset = fontset;
- fs_load_font (f, FRAME_X_FONT_TABLE (f),
+ FS_LOAD_FONT (f, FRAME_X_FONT_TABLE (f),
CHARSET_ASCII, XSTRING (result)->data, fontset);
return build_string (fontsetname);
int flags = f->output_data.x->size_hint_flags;
int this_window;
+ /* We have nothing to do if the current position
+ is already for the top-left corner. */
+ if (! ((flags & XNegative) || (flags & YNegative)))
+ return;
+
#ifdef USE_X_TOOLKIT
this_window = XtWindow (f->output_data.x->widget);
#else
#endif
/* Find the position of the outside upper-left corner of
- the inner window, with respect to the outer window. */
+ the inner window, with respect to the outer window.
+ But do this only if we will need the results. */
if (f->output_data.x->parent_desc != FRAME_X_DISPLAY_INFO (f)->root_window)
{
+ int count;
+
BLOCK_INPUT;
- XTranslateCoordinates (FRAME_X_DISPLAY (f),
+ count = x_catch_errors (FRAME_X_DISPLAY (f));
+ while (1)
+ {
+ x_clear_errors (FRAME_X_DISPLAY (f));
+ XTranslateCoordinates (FRAME_X_DISPLAY (f),
+
+ /* From-window, to-window. */
+ this_window,
+ f->output_data.x->parent_desc,
+
+ /* From-position, to-position. */
+ 0, 0, &win_x, &win_y,
+
+ /* Child of win. */
+ &child);
+ if (x_had_errors_p (FRAME_X_DISPLAY (f)))
+ {
+ Window newroot, newparent = 0xdeadbeef;
+ Window *newchildren;
+ int nchildren;
+
+ if (! XQueryTree (FRAME_X_DISPLAY (f), this_window, &newroot,
+ &newparent, &newchildren, &nchildren))
+ break;
- /* From-window, to-window. */
- this_window,
- f->output_data.x->parent_desc,
+ XFree (newchildren);
- /* From-position, to-position. */
- 0, 0, &win_x, &win_y,
+ f->output_data.x->parent_desc = newparent;
+ }
+ else
+ break;
+ }
- /* Child of win. */
- &child);
+ x_uncatch_errors (FRAME_X_DISPLAY (f), count);
UNBLOCK_INPUT;
}
BLOCK_INPUT;
x_wm_set_size_hint (f, (long) 0, 0);
- /* It is a mystery why we need to add the border_width here
- when the frame is already visible, but experiment says we do. */
modified_left = f->output_data.x->left_pos;
modified_top = f->output_data.x->top_pos;
+#if 0 /* Running on psilocin (Debian), and displaying on the NCD X-terminal,
+ this seems to be unnecessary and incorrect. rms, 4/17/97. */
+ /* It is a mystery why we need to add the border_width here
+ when the frame is already visible, but experiment says we do. */
if (change_gravity != 0)
{
modified_left += f->output_data.x->border_width;
modified_top += f->output_data.x->border_width;
}
+#endif
#ifdef USE_X_TOOLKIT
XMoveWindow (FRAME_X_DISPLAY (f), XtWindow (f->output_data.x->widget),
{
int mask;
Lisp_Object type;
+ int starting_flags = f->output_data.x->size_hint_flags;
+ int original_top, original_left;
BLOCK_INPUT;
{
Lisp_Object frame;
int count = input_signal_count;
+ /* This must be before UNBLOCK_INPUT
+ since events that arrive in response to the actions above
+ will set it when they are handled. */
+ int previously_visible = f->output_data.x->has_been_visible;
+
+ original_left = f->output_data.x->left_pos;
+ original_top = f->output_data.x->top_pos;
/* This must come after we set COUNT. */
UNBLOCK_INPUT;
+ /* Arriving X events are processed here. */
+
+ /* Now move the window back to where it was "supposed to be".
+ But don't do it if the gravity is negative.
+ When the gravity is negative, this uses a position
+ that is 3 pixels too low. Perhaps that's really the border width.
+
+ Don't do this if the window has never been visible before,
+ because the window manager may choose the position
+ and we don't want to override it. */
+
+ if (! FRAME_VISIBLE_P (f)
+ && f->output_data.x->win_gravity == NorthWestGravity
+ && previously_visible)
+ {
+ BLOCK_INPUT;
+
+#ifdef USE_X_TOOLKIT
+ XMoveWindow (FRAME_X_DISPLAY (f), XtWindow (f->output_data.x->widget),
+ original_left, original_top);
+#else /* not USE_X_TOOLKIT */
+ XMoveWindow (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
+ original_left, original_top);
+#endif /* not USE_X_TOOLKIT */
+ UNBLOCK_INPUT;
+ }
+
XSETFRAME (frame, f);
while (1)
XFlush (FRAME_X_DISPLAY (f));
}
+ if (f->output_data.x->saved_menu_event)
+ free (f->output_data.x->saved_menu_event);
+
xfree (f->output_data.x);
f->output_data.x = 0;
if (f == dpyinfo->x_focus_frame)
int size;
int maxnames;
{
- Lisp_Object list, newlist, key;
+ Lisp_Object list, patterns, newlist = Qnil, key, tem, second_best;
Display *dpy = f != NULL ? FRAME_X_DISPLAY (f) : x_display_list->display;
- key = Fcons (pattern, make_number (maxnames));
-
- if (f == NULL)
- list = Qnil;
- else
- /* See if we cached the result for this particular query. */
- list = Fassoc (key,
- XCONS (FRAME_X_DISPLAY_INFO (f)->name_list_element)->cdr);
-
- /* Now LIST has the form (KEY . FONT-DATA-LIST), where KEY is a
- pattern which matches font names in FONT-DATA-LIST, FONT-DATA-LIST
- is a list of cons cells for the form (FONTNAME . FONTWIDTH). */
+ patterns = Fassoc (pattern, Valternative_fontname_alist);
+ if (NILP (patterns))
+ patterns = Fcons (pattern, Qnil);
- if (!NILP (list))
- list = XCONS (list)->cdr;
- else
+ for (; CONSP (patterns); patterns = XCONS (patterns)->cdr)
{
- /* At first, put PATTERN in the cache. */
int num_fonts;
char **names;
+ pattern = XCONS (patterns)->car;
+ /* See if we cached the result for this particular query. */
+ if (f && (tem = XCONS (FRAME_X_DISPLAY_INFO (f)->name_list_element)->cdr,
+ key = Fcons (pattern, make_number (maxnames)),
+ !NILP (list = Fassoc (key, tem))))
+ {
+ list = Fcdr_safe (list);
+ /* We have a cashed list. Don't have to get the list again. */
+ goto label_cached;
+ }
+
+ /* At first, put PATTERN in the cache. */
BLOCK_INPUT;
names = XListFonts (dpy, XSTRING (pattern)->data, maxnames, &num_fonts);
UNBLOCK_INPUT;
if (names)
{
int i;
- Lisp_Object tem;
/* Make a list of all the fonts we got back.
Store that in the font cache for the display. */
int average_width = -1, dashes = 0, width = 0;
/* Count the number of dashes in NAMES[I]. If there are
- 14 dashes, and the field value following 12th dash
- (AVERAGE_WIDTH) is 0, this is a auto-scaled font
- which is usually too ugly to be used for editing.
- Let's ignore it. */
+ 14 dashes, and the field value following 12th dash
+ (AVERAGE_WIDTH) is 0, this is a auto-scaled font which
+ is usually too ugly to be used for editing. Let's
+ ignore it. */
while (*p)
if (*p++ == '-')
{
if (NILP (Fassoc (tem, list)))
{
if (STRINGP (Vx_pixel_size_width_font_regexp)
- && (fast_string_match_ignore_case
- (Vx_pixel_size_width_font_regexp, names[i])
+ && ((fast_c_string_match_ignore_case
+ (Vx_pixel_size_width_font_regexp, names[i]))
>= 0))
/* We can set the value of PIXEL_SIZE to the
- width of this font. */
+ width of this font. */
list = Fcons (Fcons (tem, make_number (width)), list);
else
/* For the moment, width is not known. */
XFreeFontNames (names);
}
+ /* Now store the result in the cache. */
if (f != NULL)
XCONS (FRAME_X_DISPLAY_INFO (f)->name_list_element)->cdr
= Fcons (Fcons (key, list),
XCONS (FRAME_X_DISPLAY_INFO (f)->name_list_element)->cdr);
- }
- if (NILP (list))
- return Qnil;
+ label_cached:
+ if (NILP (list)) continue; /* Try the remaining alternatives. */
- newlist = Qnil;
+ newlist = second_best = Qnil;
+ /* Make a list of the fonts that have the right width. */
+ for (; CONSP (list); list = XCONS (list)->cdr)
+ {
+ tem = XCONS (list)->car;
- /* Make a list of the fonts that have the right width. */
- for (; CONSP (list); list = XCONS (list)->cdr)
- {
- Lisp_Object tem = XCONS (list)->car;
- int keeper;
+ if (!CONSP (tem) || NILP (XCONS (tem)->car))
+ continue;
+ if (!size)
+ {
+ newlist = Fcons (XCONS (tem)->car, newlist);
+ continue;
+ }
- if (!CONSP (tem) || NILP (XCONS (tem)->car))
- continue;
- if (!size)
- keeper = 1;
- else
- {
if (!INTEGERP (XCONS (tem)->cdr))
{
+ /* Since we have not yet known the size of this font, we
+ must try slow function call XLoadQueryFont. */
XFontStruct *thisinfo;
BLOCK_INPUT;
XFreeFont (dpy, thisinfo);
}
else
+ /* For unknown reason, the previous call of XListFont had
+ retruned a font which can't be opened. Record the size
+ as 0 not to try to open it again. */
XCONS (tem)->cdr = make_number (0);
}
- keeper = XINT (XCONS (tem)->cdr) == size;
+ if (XINT (XCONS (tem)->cdr) == size)
+ newlist = Fcons (XCONS (tem)->car, newlist);
+ else if (NILP (second_best))
+ second_best = tem;
+ else if (XINT (XCONS (tem)->cdr) < size)
+ {
+ if (XINT (XCONS (second_best)->cdr) > size
+ || XINT (XCONS (second_best)->cdr) < XINT (XCONS (tem)->cdr))
+ second_best = tem;
+ }
+ else
+ {
+ if (XINT (XCONS (second_best)->cdr) > size
+ && XINT (XCONS (second_best)->cdr) > XINT (XCONS (tem)->cdr))
+ second_best = tem;
+ }
+ }
+ if (!NILP (newlist))
+ break;
+ else if (!NILP (second_best))
+ {
+ newlist = Fcons (XCONS (second_best)->car, Qnil);
+ break;
}
- if (keeper)
- newlist = Fcons (XCONS (tem)->car, newlist);
}
return newlist;
struct font_info *fontp;
unsigned long value;
+ /* If we have found fonts by x_list_font, load one of them. If
+ not, we still try to load a font by the name given as FONTNAME
+ because XListFonts (called in x_list_font) of some X server has
+ a bug of not finding a font even if the font surely exists and
+ is loadable by XLoadQueryFont. */
if (!NILP (font_names))
- fontname = XSTRING (XCONS (font_names)->car)->data;
+ fontname = (char *) XSTRING (XCONS (font_names)->car)->data;
BLOCK_INPUT;
font = (XFontStruct *) XLoadQueryFont (FRAME_X_DISPLAY (f), fontname);
UNBLOCK_INPUT;
- if (!font || (size && font->max_bounds.width != size))
+ if (!font)
return NULL;
/* Do we need to create the table? */
fontp->size = font->max_bounds.width;
fontp->height = font->ascent + font->descent;
+ if (NILP (font_names))
+ {
+ /* We come here because of a bug of XListFonts mentioned at
+ the head of this block. Let's store this information in
+ the cache for x_list_fonts. */
+ Lisp_Object lispy_name = build_string (fontname);
+ Lisp_Object lispy_full_name = build_string (fontp->full_name);
+
+ XCONS (dpyinfo->name_list_element)->cdr
+ = Fcons (Fcons (Fcons (lispy_name, make_number (256)),
+ Fcons (Fcons (lispy_full_name,
+ make_number (fontp->size)),
+ Qnil)),
+ XCONS (dpyinfo->name_list_element)->cdr);
+ if (full_name)
+ XCONS (dpyinfo->name_list_element)->cdr
+ = Fcons (Fcons (Fcons (lispy_full_name, make_number (256)),
+ Fcons (Fcons (lispy_full_name,
+ make_number (fontp->size)),
+ Qnil)),
+ XCONS (dpyinfo->name_list_element)->cdr);
+ }
+
/* The slot `encoding' specifies how to map a character
code-points (0x20..0x7F or 0x2020..0x7F7F) of each charset to
- the font code-points (0x20..0x7F, 0xA0..0xFF, 0x2020..0x7F7F,
- 0xA0A0..0xFFFF, 0x20A0..0x7FFF, or 0xA020..0xFF7F). For the
- moment, we don't know which charset uses this font. So, we set
- informatoin in fontp->encoding[1] which is never used by any
- charset. If mapping can't be decided, set -1. */
+ the font code-points (0:0x20..0x7F, 1:0xA0..0xFF, 0:0x2020..0x7F7F,
+ the font code-points (0:0x20..0x7F, 1:0xA0..0xFF,
+ 0:0x2020..0x7F7F, 1:0xA0A0..0xFFFF, 3:0x20A0..0x7FFF, or
+ 2:0xA020..0xFF7F). For the moment, we don't know which charset
+ uses this font. So, we set informatoin in fontp->encoding[1]
+ which is never used by any charset. If mapping can't be
+ decided, set FONT_ENCODING_NOT_DECIDED. */
fontp->encoding[1]
= (font->max_byte1 == 0
/* 1-byte font */
? (font->min_char_or_byte2 < 0x80
? (font->max_char_or_byte2 < 0x80
? 0 /* 0x20..0x7F */
- : -1) /* 0x20..0xFF (can't decide) */
+ : FONT_ENCODING_NOT_DECIDED) /* 0x20..0xFF */
: 1) /* 0xA0..0xFF */
/* 2-byte font */
: (font->min_byte1 < 0x80
? (font->min_char_or_byte2 < 0x80
? (font->max_char_or_byte2 < 0x80
? 0 /* 0x2020..0x7F7F */
- : -1) /* 0x2020..0x7FFF (can't decide) */
+ : FONT_ENCODING_NOT_DECIDED) /* 0x2020..0x7FFF */
: 3) /* 0x20A0..0x7FFF */
- : -1) /* 0x20??..0xA0?? (can't decide) */
+ : FONT_ENCODING_NOT_DECIDED) /* 0x20??..0xA0?? */
: (font->min_char_or_byte2 < 0x80
? (font->max_char_or_byte2 < 0x80
? 2 /* 0xA020..0xFF7F */
- : -1) /* 0xA020..0xFFFF (can't decide) */
+ : FONT_ENCODING_NOT_DECIDED) /* 0xA020..0xFFFF */
: 1))); /* 0xA0A0..0xFFFF */
fontp->baseline_offset
Display *dpy = dpyinfo->display;
XrmValue d, fr, to;
Font font;
+ int count;
d.addr = (XPointer)&dpy;
d.size = sizeof (Display *);
fr.size = sizeof (XtDefaultFont);
to.size = sizeof (Font *);
to.addr = (XPointer)&font;
- x_catch_errors (dpy);
+ count = x_catch_errors (dpy);
if (!XtCallConverter (dpy, XtCvtStringToFont, &d, 1, &fr, &to, NULL))
abort ();
if (x_had_errors_p (dpy) || !XQueryFont (dpy, font))
XrmPutLineResource (&xrdb, "Emacs.dialog.*.font: 9x15");
- x_uncatch_errors (dpy);
+ x_uncatch_errors (dpy, count);
}
#endif
/* Note that there is no real way portable across R3/R4 to get the
original error handler. */
- XSetErrorHandler (x_error_quitter);
+ XSetErrorHandler (x_error_handler);
XSetIOErrorHandler (x_io_error_quitter);
/* Disable Window Change signals; they are handled by X events. */
void
syms_of_xterm ()
{
+ staticpro (&x_error_message_string);
+ x_error_message_string = Qnil;
+
staticpro (&x_display_name_list);
x_display_name_list = Qnil;