DRAW_IMAGE_SUNKEN
};
+static const XColor *x_color_cells P_ ((struct frame *, int *));
static void x_update_window_end P_ ((struct window *, int, int));
static void frame_to_window_pixel_xy P_ ((struct window *, int *, int *));
void x_delete_display P_ ((struct x_display_info *));
static void x_produce_image_glyph P_ ((struct it *it));
-/* Return a pointer to per-char metric information in FONT of a
- character pointed by B which is a pointer to an XChar2b. */
-
-#define PER_CHAR_METRIC(font, b) \
- ((font)->per_char \
- ? ((font)->per_char + (b)->byte2 - (font)->min_char_or_byte2 \
- + (((font)->min_byte1 || (font)->max_byte1) \
- ? (((b)->byte1 - (font)->min_byte1) \
- * ((font)->max_char_or_byte2 - (font)->min_char_or_byte2 + 1)) \
- : 0)) \
- : &((font)->max_bounds))
-
-
/* Get metrics of character CHAR2B in FONT. Value is null if CHAR2B
is not contained in the font. */
F_HEIGHT = FRAME_LINE_HEIGHT (F)
*/
-#define VCENTER_BASELINE_OFFSET(FONT, F) \
- ((FONT)->descent \
- + (FRAME_LINE_HEIGHT ((F)) - FONT_HEIGHT ((FONT))) / 2 \
- - ((F)->output_data.x->font->descent - (F)->output_data.x->baseline_offset))
+#define VCENTER_BASELINE_OFFSET(FONT, F) \
+ ((FONT)->descent \
+ + (FRAME_LINE_HEIGHT ((F)) - FONT_HEIGHT ((FONT)) \
+ + (FRAME_LINE_HEIGHT ((F)) > FONT_HEIGHT ((FONT)))) / 2 \
+ - ((F)->output_data.x->font->descent - (F)->output_data.x->baseline_offset))
/* Produce glyphs/get display metrics for the display element IT is
loaded with. See the description of struct display_iterator in
int font_not_found_p;
struct font_info *font_info;
int boff; /* baseline offset */
+ /* We may change it->multibyte_p upon unibyte<->multibyte
+ conversion. So, save the current value now and restore it
+ later.
+
+ Note: It seems that we don't have to record multibyte_p in
+ struct glyph because the character code itself tells if or
+ not the character is multibyte. Thus, in the future, we must
+ consider eliminating the field `multibyte_p' in the struct
+ glyph.
+ */
+ int saved_multibyte_p = it->multibyte_p;
/* Maybe translate single-byte characters to multibyte, or the
other way. */
|| !NILP (Vnonascii_translation_table)))
{
it->char_to_display = unibyte_char_to_multibyte (it->c);
+ it->multibyte_p = 1;
it->face_id = FACE_FOR_CHAR (it->f, face, it->char_to_display);
face = FACE_FROM_ID (it->f, it->face_id);
}
&& !it->multibyte_p)
{
it->char_to_display = multibyte_char_to_unibyte (it->c, Qnil);
+ it->multibyte_p = 0;
it->face_id = FACE_FOR_CHAR (it->f, face, it->char_to_display);
face = FACE_FROM_ID (it->f, it->face_id);
}
if (it->glyph_row)
x_append_glyph (it);
}
+ it->multibyte_p = saved_multibyte_p;
}
else if (it->what == IT_COMPOSITION)
{
cmp->font = (void *) font;
/* Initialize the bounding box. */
- pcm = x_per_char_metric (font, &char2b);
- if (pcm)
+ if (font_info
+ && (pcm = x_per_char_metric (font, &char2b)))
{
width = pcm->width;
ascent = pcm->ascent;
boff = VCENTER_BASELINE_OFFSET (font, it->f) - boff;
}
- pcm = x_per_char_metric (font, &char2b);
- if (pcm)
+ if (font_info
+ && (pcm = x_per_char_metric (font, &char2b)))
{
width = pcm->width;
ascent = pcm->ascent;
else
{
width = FONT_WIDTH (font);
- ascent = font->ascent;
- descent = font->descent;
+ ascent = 1;
+ descent = 0;
}
if (cmp->method != COMPOSITION_WITH_RULE_ALTCHARS)
struct frame *f;
enum face_id face_id;
{
- int height = 1;
+ int height = FONT_HEIGHT (FRAME_FONT (f));
/* This function is called so early when Emacs starts that the face
cache and mode line face are not yet initialized. */
{
struct face *face = FACE_FROM_ID (f, face_id);
if (face)
- height = FONT_HEIGHT (face->font) + 2 * face->box_line_width;
+ {
+ if (face->font)
+ height = FONT_HEIGHT (face->font);
+ height += 2 * face->box_line_width;
+ }
}
return height;
#endif /* USE_X_TOOLKIT */
+/* Value is an array of XColor structures for the contents of the
+ color map of frame F. Set *NCELLS to the size of the array.
+ Note that this probably shouldn't be called for large color maps,
+ say a 24-bit TrueColor map. */
+
+static const XColor *
+x_color_cells (f, ncells)
+ struct frame *f;
+ int *ncells;
+{
+ struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
+
+ if (dpyinfo->color_cells == NULL)
+ {
+ Display *display = FRAME_X_DISPLAY (f);
+ Screen *screen = FRAME_X_SCREEN (f);
+ int i;
+
+ dpyinfo->ncolor_cells
+ = XDisplayCells (display, XScreenNumberOfScreen (screen));
+ dpyinfo->color_cells
+ = (XColor *) xmalloc (dpyinfo->ncolor_cells
+ * sizeof *dpyinfo->color_cells);
+
+ for (i = 0; i < dpyinfo->ncolor_cells; ++i)
+ dpyinfo->color_cells[i].pixel = i;
+
+ XQueryColors (display, FRAME_X_COLORMAP (f),
+ dpyinfo->color_cells, dpyinfo->ncolor_cells);
+ }
+
+ *ncells = dpyinfo->ncolor_cells;
+ return dpyinfo->color_cells;
+}
+
+
+/* On frame F, translate pixel colors to RGB values for the NCOLORS
+ colors in COLORS. Use cached information, if available. */
+
+void
+x_query_colors (f, colors, ncolors)
+ struct frame *f;
+ XColor *colors;
+ int ncolors;
+{
+ struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
+
+ if (dpyinfo->color_cells)
+ {
+ int i;
+ for (i = 0; i < ncolors; ++i)
+ {
+ unsigned long pixel = colors[i].pixel;
+ xassert (pixel < dpyinfo->ncolor_cells);
+ xassert (dpyinfo->color_cells[pixel].pixel == pixel);
+ colors[i] = dpyinfo->color_cells[pixel];
+ }
+ }
+ else
+ XQueryColors (FRAME_X_DISPLAY (f), FRAME_X_COLORMAP (f), colors, ncolors);
+}
+
+
+/* On frame F, translate pixel color to RGB values for the color in
+ COLOR. Use cached information, if available. */
+
+void
+x_query_color (f, color)
+ struct frame *f;
+ XColor *color;
+{
+ x_query_colors (f, color, 1);
+}
+
+
/* Allocate the color COLOR->pixel on SCREEN of DISPLAY, colormap
CMAP. If an exact match can't be allocated, try the nearest color
available. Value is non-zero if successful. Set *COLOR to the
color matching with StaticColor visuals. */
int nearest, i;
unsigned long nearest_delta = ~0;
- int ncells = XDisplayCells (display, XScreenNumberOfScreen (screen));
- XColor *cells = (XColor *) alloca (ncells * sizeof *cells);
-
- for (i = 0; i < ncells; ++i)
- cells[i].pixel = i;
- XQueryColors (display, cmap, cells, ncells);
+ int ncells;
+ const XColor *cells = x_color_cells (f, &ncells);
for (nearest = i = 0; i < ncells; ++i)
{
color->blue = cells[nearest].blue;
rc = XAllocColor (display, cmap, color);
}
+ else
+ {
+ /* If allocation succeeded, and the allocated pixel color is not
+ equal to a cached pixel color recorded earlier, there was a
+ change in the colormap, so clear the color cache. */
+ struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
+ XColor *cached_color;
+
+ if (dpyinfo->color_cells
+ && (cached_color = &dpyinfo->color_cells[color->pixel],
+ (cached_color->red != color->red
+ || cached_color->blue != color->blue
+ || cached_color->green != color->green)))
+ {
+ xfree (dpyinfo->color_cells);
+ dpyinfo->color_cells = NULL;
+ dpyinfo->ncolor_cells = 0;
+ }
+ }
#ifdef DEBUG_X_COLORS
if (rc)
color.pixel = pixel;
BLOCK_INPUT;
- XQueryColor (FRAME_X_DISPLAY (f), FRAME_X_COLORMAP (f), &color);
+ x_query_color (f, &color);
XAllocColor (FRAME_X_DISPLAY (f), FRAME_X_COLORMAP (f), &color);
UNBLOCK_INPUT;
#ifdef DEBUG_X_COLORS
}
+/* Brightness beyond which a color won't have its highlight brightness
+ boosted.
+
+ Nominally, highlight colors for `3d' faces are calculated by
+ brightening an object's color by a constant scale factor, but this
+ doesn't yield good results for dark colors, so for colors who's
+ brightness is less than this value (on a scale of 0-65535) have an
+ use an additional additive factor.
+
+ The value here is set so that the default menu-bar/mode-line color
+ (grey75) will not have its highlights changed at all. */
+#define HIGHLIGHT_COLOR_DARK_BOOST_LIMIT 48000
+
+
/* Allocate a color which is lighter or darker than *PIXEL by FACTOR
or DELTA. Try a color with RGB values multiplied by FACTOR first.
If this produces the same color as PIXEL, try a color where all RGB
int delta;
{
XColor color, new;
+ long bright;
int success_p;
/* Get RGB color values. */
color.pixel = *pixel;
- XQueryColor (display, cmap, &color);
+ x_query_color (f, &color);
/* Change RGB values by specified FACTOR. Avoid overflow! */
xassert (factor >= 0);
new.green = min (0xffff, factor * color.green);
new.blue = min (0xffff, factor * color.blue);
+ /* Calculate brightness of COLOR. */
+ bright = (2 * color.red + 3 * color.green + color.blue) / 6;
+
+ /* We only boost colors that are darker than
+ HIGHLIGHT_COLOR_DARK_BOOST_LIMIT. */
+ if (bright < HIGHLIGHT_COLOR_DARK_BOOST_LIMIT)
+ /* Make an additive adjustment to NEW, because it's dark enough so
+ that scaling by FACTOR alone isn't enough. */
+ {
+ /* How far below the limit this color is (0 - 1, 1 being darker). */
+ double dimness = 1 - (double)bright / HIGHLIGHT_COLOR_DARK_BOOST_LIMIT;
+ /* The additive adjustment. */
+ int min_delta = delta * dimness * factor / 2;
+
+ if (factor < 1)
+ {
+ new.red = max (0, new.red - min_delta);
+ new.green = max (0, new.green - min_delta);
+ new.blue = max (0, new.blue - min_delta);
+ }
+ else
+ {
+ new.red = min (0xffff, min_delta + new.red);
+ new.green = min (0xffff, min_delta + new.green);
+ new.blue = min (0xffff, min_delta + new.blue);
+ }
+ }
+
/* Try to allocate the color. */
success_p = x_alloc_nearest_color (f, cmap, &new);
if (success_p)
/* Top. */
XFillRectangle (s->display, s->window, s->gc,
- left_x, top_y, right_x - left_x, width);
+ left_x, top_y, right_x - left_x + 1, width);
/* Left. */
if (left_p)
XFillRectangle (s->display, s->window, s->gc,
- left_x, top_y, width, bottom_y - top_y);
+ left_x, top_y, width, bottom_y - top_y + 1);
/* Bottom. */
XFillRectangle (s->display, s->window, s->gc,
- left_x, bottom_y - width, right_x - left_x, width);
+ left_x, bottom_y - width + 1, right_x - left_x + 1, width);
/* Right. */
if (right_p)
XFillRectangle (s->display, s->window, s->gc,
- right_x - width, top_y, width, bottom_y - top_y);
+ right_x - width + 1, top_y, width, bottom_y - top_y + 1);
XSetForeground (s->display, s->gc, xgcv.foreground);
XSetClipMask (s->display, s->gc, None);
/* Draw underline. */
if (s->face->underline_p)
{
- unsigned long dy, h;
+ unsigned long tem, h;
+ int y;
+ /* Get the underline thickness. Default is 1 pixel. */
if (!XGetFontProperty (s->font, XA_UNDERLINE_THICKNESS, &h))
h = 1;
- if (!XGetFontProperty (s->font, XA_UNDERLINE_POSITION, &dy))
- dy = s->height - h;
+
+ /* Get the underline position. This is the recommended
+ vertical offset in pixels from the baseline to the top of
+ the underline. This is a signed value according to the
+ specs, and its default is
+
+ ROUND ((maximum descent) / 2), with
+ ROUND(x) = floor (x + 0.5) */
+
+ if (XGetFontProperty (s->font, XA_UNDERLINE_POSITION, &tem))
+ y = s->ybase + (long) tem;
+ else if (s->face->font)
+ y = s->ybase + (s->face->font->max_bounds.descent + 1) / 2;
+ else
+ y = s->height - h;
if (s->face->underline_defaulted_p)
- XFillRectangle (s->display, s->window, s->gc, s->x, s->y + dy,
- s->width, h);
+ XFillRectangle (s->display, s->window, s->gc,
+ s->x, y, s->width, h);
else
{
XGCValues xgcv;
XGetGCValues (s->display, s->gc, GCForeground, &xgcv);
XSetForeground (s->display, s->gc, s->face->underline_color);
- XFillRectangle (s->display, s->window, s->gc, s->x, s->y + dy,
- s->width, h);
+ XFillRectangle (s->display, s->window, s->gc,
+ s->x, y, s->width, h);
XSetForeground (s->display, s->gc, xgcv.foreground);
}
}
XRectangle *r;
enum glyph_row_area area;
{
- int x;
struct glyph *first = row->glyphs[area];
struct glyph *end = row->glyphs[area] + row->used[area];
struct glyph *last;
- int first_x;
-
- /* Set x to the window-relative start position for drawing glyphs of
- AREA. The first glyph of the text area can be partially visible.
- The first glyphs of other areas cannot. */
- if (area == LEFT_MARGIN_AREA)
- x = 0;
- else if (area == TEXT_AREA)
- x = row->x + window_box_width (w, LEFT_MARGIN_AREA);
- else
- x = (window_box_width (w, LEFT_MARGIN_AREA)
- + window_box_width (w, TEXT_AREA));
+ int first_x, start_x, x;
if (area == TEXT_AREA && row->fill_line_p)
/* If row extends face to end of line write the whole line. */
- x_draw_glyphs (w, x, row, area,
+ x_draw_glyphs (w, 0, row, area,
0, row->used[area],
row->inverse_p ? DRAW_INVERSE_VIDEO : DRAW_NORMAL_TEXT,
NULL, NULL, 0);
else
{
+ /* Set START_X to the window-relative start position for drawing glyphs of
+ AREA. The first glyph of the text area can be partially visible.
+ The first glyphs of other areas cannot. */
+ if (area == LEFT_MARGIN_AREA)
+ start_x = 0;
+ else if (area == TEXT_AREA)
+ start_x = row->x + window_box_width (w, LEFT_MARGIN_AREA);
+ else
+ start_x = (window_box_width (w, LEFT_MARGIN_AREA)
+ + window_box_width (w, TEXT_AREA));
+ x = start_x;
+
/* Find the first glyph that must be redrawn. */
while (first < end
&& x + first->pixel_width < r->x)
/* Repaint. */
if (last > first)
- x_draw_glyphs (w, first_x, row, area,
+ x_draw_glyphs (w, first_x - start_x, row, area,
first - row->glyphs[area],
last - row->glyphs[area],
row->inverse_p ? DRAW_INVERSE_VIDEO : DRAW_NORMAL_TEXT,
happen when toolkit scroll bars are used and a window is split.
Reconfiguring the scroll bar will generate an expose for a newly
created window. */
- if (w->current_matrix == NULL)
+ if (w->current_matrix == NULL || w == updated_window)
return;
TRACE ((stderr, "expose_window (%d, %d, %d, %d)\n",
}
-/* Take proper action when mouse has moved to the mode or top line of
+/* Take proper action when mouse has moved to the mode or header line of
window W, x-position X. MODE_LINE_P non-zero means mouse is on the
mode line. X is relative to the start of the text display area of
W, so the width of bitmap areas and scroll bars must be subtracted
row = MATRIX_MODE_LINE_ROW (w->current_matrix);
else
row = MATRIX_HEADER_LINE_ROW (w->current_matrix);
-
+
if (row->enabled_p)
{
struct glyph *glyph, *end;
end = glyph + row->used[TEXT_AREA];
x0 = - (FRAME_LEFT_SCROLL_BAR_WIDTH (f) * CANON_X_UNIT (f)
+ FRAME_X_LEFT_FLAGS_AREA_WIDTH (f));
+
while (glyph < end
&& x >= x0 + glyph->pixel_width)
{
/* Change the mouse pointer according to what is under X/Y. */
map = Fget_text_property (make_number (glyph->charpos),
Qlocal_map, glyph->object);
- if (!NILP (Fkeymapp (map)))
+ if (KEYMAPP (map))
cursor = f->output_data.x->nontext_cursor;
else
{
map = Fget_text_property (make_number (glyph->charpos),
Qkeymap, glyph->object);
- if (!NILP (Fkeymapp (map)))
+ if (KEYMAPP (map))
cursor = f->output_data.x->nontext_cursor;
}
}
note_mode_line_highlight (w, x, portion == 1);
return;
}
+ else if (portion == 2)
+ XDefineCursor (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
+ f->output_data.x->horizontal_drag_cursor);
else
XDefineCursor (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
f->output_data.x->text_cursor);
Return in *GLYPH a pointer to the glyph of the tool-bar item in
the current matrix of the tool-bar window of F, or NULL if not
on a tool-bar item. Return in *PROP_IDX the index of the tool-bar
- item in F->current_tool_bar_items. Value is
+ item in F->tool_bar_items. Value is
-1 if X/Y is not on a tool-bar item
0 if X/Y is on the same item that was highlighted before.
return -1;
/* Get the start of this tool-bar item's properties in
- f->current_tool_bar_items. */
+ f->tool_bar_items. */
if (!tool_bar_item_info (f, *glyph, prop_idx))
return -1;
return;
/* If item is disabled, do nothing. */
- enabled_p = (XVECTOR (f->current_tool_bar_items)
- ->contents[prop_idx + TOOL_BAR_ITEM_ENABLED_P]);
+ enabled_p = AREF (f->tool_bar_items, prop_idx + TOOL_BAR_ITEM_ENABLED_P);
if (NILP (enabled_p))
return;
show_mouse_face (dpyinfo, DRAW_IMAGE_RAISED);
dpyinfo->mouse_face_image_state = DRAW_IMAGE_RAISED;
- key = (XVECTOR (f->current_tool_bar_items)
- ->contents[prop_idx + TOOL_BAR_ITEM_KEY]);
+ key = AREF (f->tool_bar_items, prop_idx + TOOL_BAR_ITEM_KEY);
XSETFRAME (frame, f);
event.kind = TOOL_BAR_EVENT;
draw = mouse_down_p ? DRAW_IMAGE_SUNKEN : DRAW_IMAGE_RAISED;
/* If tool-bar item is not enabled, don't highlight it. */
- enabled_p = (XVECTOR (f->current_tool_bar_items)
- ->contents[prop_idx + TOOL_BAR_ITEM_ENABLED_P]);
+ enabled_p = AREF (f->tool_bar_items, prop_idx + TOOL_BAR_ITEM_ENABLED_P);
if (!NILP (enabled_p))
{
/* Compute the x-position of the glyph. In front and past the
XTread_socket does the rest. */
help_echo_object = help_echo_window = Qnil;
help_echo_pos = -1;
- help_echo = (XVECTOR (f->current_tool_bar_items)
- ->contents[prop_idx + TOOL_BAR_ITEM_HELP]);
+ help_echo = AREF (f->tool_bar_items, prop_idx + TOOL_BAR_ITEM_HELP);
if (NILP (help_echo))
- help_echo = (XVECTOR (f->current_tool_bar_items)
- ->contents[prop_idx + TOOL_BAR_ITEM_CAPTION]);
+ help_echo = AREF (f->tool_bar_items, prop_idx + TOOL_BAR_ITEM_CAPTION);
}
clear_mouse_face (dpyinfo)
struct x_display_info *dpyinfo;
{
- if (tip_frame)
+ if (!NILP (tip_frame))
return;
if (! NILP (dpyinfo->mouse_face_window))
/* Is win one of our frames? */
f1 = x_any_window_to_frame (FRAME_X_DISPLAY_INFO (*fp), win);
+
+#ifdef USE_X_TOOLKIT
+ /* If we end up with the menu bar window, say it's not
+ on the frame. */
+ if (f1 != NULL
+ && f1->output_data.x->menubar_widget
+ && win == XtWindow (f1->output_data.x->menubar_widget))
+ f1 = NULL;
+#endif /* USE_X_TOOLKIT */
}
if (x_had_errors_p (FRAME_X_DISPLAY (*fp)))
Toolkit scroll bars
************************************************************************/
-#if USE_TOOLKIT_SCROLL_BARS
+#ifdef USE_TOOLKIT_SCROLL_BARS
static void x_scroll_bar_to_input_event P_ ((XEvent *, struct input_event *));
static void x_send_scroll_bar_event P_ ((Lisp_Object, int, int, int));
}
}
+/* A vector of windows used for communication between
+ x_send_scroll_bar_event and x_scroll_bar_to_input_event. */
+
+static struct window **scroll_bar_windows;
+static int scroll_bar_windows_size;
+
/* Send a client message with message type Xatom_Scrollbar for a
scroll action to the frame of WINDOW. PART is a value identifying
{
XEvent event;
XClientMessageEvent *ev = (XClientMessageEvent *) &event;
- struct frame *f = XFRAME (XWINDOW (window)->frame);
+ struct window *w = XWINDOW (window);
+ struct frame *f = XFRAME (w->frame);
+ int i;
+ BLOCK_INPUT;
+
/* Construct a ClientMessage event to send to the frame. */
ev->type = ClientMessage;
ev->message_type = FRAME_X_DISPLAY_INFO (f)->Xatom_Scrollbar;
ev->display = FRAME_X_DISPLAY (f);
ev->window = FRAME_X_WINDOW (f);
ev->format = 32;
- ev->data.l[0] = (long) XFASTINT (window);
+
+ /* We can only transfer 32 bits in the XClientMessageEvent, which is
+ not enough to store a pointer or Lisp_Object on a 64 bit system.
+ So, store the window in scroll_bar_windows and pass the index
+ into that array in the event. */
+ for (i = 0; i < scroll_bar_windows_size; ++i)
+ if (scroll_bar_windows[i] == NULL)
+ break;
+
+ if (i == scroll_bar_windows_size)
+ {
+ int new_size = max (10, 2 * scroll_bar_windows_size);
+ size_t nbytes = new_size * sizeof *scroll_bar_windows;
+ size_t old_nbytes = scroll_bar_windows_size * sizeof *scroll_bar_windows;
+
+ scroll_bar_windows = (struct window **) xrealloc (scroll_bar_windows,
+ nbytes);
+ bzero (&scroll_bar_windows[i], nbytes - old_nbytes);
+ scroll_bar_windows_size = new_size;
+ }
+
+ scroll_bar_windows[i] = w;
+ ev->data.l[0] = (long) i;
ev->data.l[1] = (long) part;
ev->data.l[2] = (long) 0;
ev->data.l[3] = (long) portion;
/* Setting the event mask to zero means that the message will
be sent to the client that created the window, and if that
window no longer exists, no event will be sent. */
- BLOCK_INPUT;
XSendEvent (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), False, 0, &event);
UNBLOCK_INPUT;
}
XClientMessageEvent *ev = (XClientMessageEvent *) event;
Lisp_Object window;
struct frame *f;
+ struct window *w;
+
+ w = scroll_bar_windows[ev->data.l[0]];
+ scroll_bar_windows[ev->data.l[0]] = NULL;
- XSETFASTINT (window, ev->data.l[0]);
- f = XFRAME (XWINDOW (window)->frame);
+ XSETWINDOW (window, w);
+ f = XFRAME (w->frame);
ievent->kind = scroll_bar_click;
ievent->frame_or_window = window;
struct scroll_bar *bar;
int portion, position, whole;
{
+ struct frame *f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
+ Widget widget = SCROLL_BAR_X_WIDGET (FRAME_X_DISPLAY (f), bar);
float top, shown;
- Widget widget = SCROLL_BAR_X_WIDGET (bar);
if (whole == 0)
top = 0, shown = 1;
BLOCK_INPUT;
-#if USE_TOOLKIT_SCROLL_BARS
+#ifdef USE_TOOLKIT_SCROLL_BARS
x_create_toolkit_scroll_bar (f, bar);
#else /* not USE_TOOLKIT_SCROLL_BARS */
{
XSETVECTOR (XSCROLL_BAR (bar->next)->prev, bar);
/* Map the window/widget. */
-#if USE_TOOLKIT_SCROLL_BARS
- XtMapWidget (SCROLL_BAR_X_WIDGET (bar));
- XtConfigureWidget (SCROLL_BAR_X_WIDGET (bar),
+#ifdef USE_TOOLKIT_SCROLL_BARS
+ {
+ Widget scroll_bar = SCROLL_BAR_X_WIDGET (FRAME_X_DISPLAY (f), bar);
+ XtConfigureWidget (scroll_bar,
left + VERTICAL_SCROLL_BAR_WIDTH_TRIM,
top,
width - VERTICAL_SCROLL_BAR_WIDTH_TRIM * 2,
height, 0);
+ XtMapWidget (scroll_bar);
+ }
#else /* not USE_TOOLKIT_SCROLL_BARS */
XMapRaised (FRAME_X_DISPLAY (f), SCROLL_BAR_X_WINDOW (bar));
#endif /* not USE_TOOLKIT_SCROLL_BARS */
x_scroll_bar_remove (bar)
struct scroll_bar *bar;
{
+ struct frame *f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
BLOCK_INPUT;
-#if USE_TOOLKIT_SCROLL_BARS
- XtDestroyWidget (SCROLL_BAR_X_WIDGET (bar));
-#else /* not USE_TOOLKIT_SCROLL_BARS */
- {
- FRAME_PTR f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
- XDestroyWindow (FRAME_X_DISPLAY (f), SCROLL_BAR_X_WINDOW (bar));
- }
-#endif /* not USE_TOOLKIT_SCROLL_BARS */
+#ifdef USE_TOOLKIT_SCROLL_BARS
+ XtDestroyWidget (SCROLL_BAR_X_WIDGET (FRAME_X_DISPLAY (f), bar));
+#else
+ XDestroyWindow (FRAME_X_DISPLAY (f), SCROLL_BAR_X_WINDOW (bar));
+#endif
/* Disassociate this scroll bar from its window. */
XWINDOW (bar->window)->vertical_scroll_bar = Qnil;
/* Move/size the scroll bar widget. */
if (mask)
- XtConfigureWidget (SCROLL_BAR_X_WIDGET (bar),
+ XtConfigureWidget (SCROLL_BAR_X_WIDGET (FRAME_X_DISPLAY (f), bar),
sb_left + VERTICAL_SCROLL_BAR_WIDTH_TRIM,
top,
sb_width - VERTICAL_SCROLL_BAR_WIDTH_TRIM * 2,
UNBLOCK_INPUT;
}
-#if USE_TOOLKIT_SCROLL_BARS
+#ifdef USE_TOOLKIT_SCROLL_BARS
x_set_toolkit_scroll_bar_thumb (bar, portion, position, whole);
#else /* not USE_TOOLKIT_SCROLL_BARS */
/* Set the scroll bar's current state, unless we're currently being
}
}
+
/* Un-mark WINDOW's scroll bar for deletion in this judgment cycle.
Note that WINDOW isn't necessarily condemned at all. */
+
static void
XTredeem_scroll_bar (window)
struct window *window;
{
struct scroll_bar *bar;
+ struct frame *f;
/* We can't redeem this window's scroll bar if it doesn't have one. */
if (NILP (window->vertical_scroll_bar))
bar = XSCROLL_BAR (window->vertical_scroll_bar);
/* Unlink it from the condemned list. */
- {
- FRAME_PTR f = XFRAME (WINDOW_FRAME (window));
-
- if (NILP (bar->prev))
- {
- /* If the prev pointer is nil, it must be the first in one of
- the lists. */
- if (EQ (FRAME_SCROLL_BARS (f), window->vertical_scroll_bar))
- /* It's not condemned. Everything's fine. */
- return;
- else if (EQ (FRAME_CONDEMNED_SCROLL_BARS (f),
- window->vertical_scroll_bar))
- FRAME_CONDEMNED_SCROLL_BARS (f) = bar->next;
- else
- /* If its prev pointer is nil, it must be at the front of
- one or the other! */
- abort ();
- }
- else
- XSCROLL_BAR (bar->prev)->next = bar->next;
+ f = XFRAME (WINDOW_FRAME (window));
+ if (NILP (bar->prev))
+ {
+ /* If the prev pointer is nil, it must be the first in one of
+ the lists. */
+ if (EQ (FRAME_SCROLL_BARS (f), window->vertical_scroll_bar))
+ /* It's not condemned. Everything's fine. */
+ return;
+ else if (EQ (FRAME_CONDEMNED_SCROLL_BARS (f),
+ window->vertical_scroll_bar))
+ FRAME_CONDEMNED_SCROLL_BARS (f) = bar->next;
+ else
+ /* If its prev pointer is nil, it must be at the front of
+ one or the other! */
+ abort ();
+ }
+ else
+ XSCROLL_BAR (bar->prev)->next = bar->next;
- if (! NILP (bar->next))
- XSCROLL_BAR (bar->next)->prev = bar->prev;
+ if (! NILP (bar->next))
+ XSCROLL_BAR (bar->next)->prev = bar->prev;
- bar->next = FRAME_SCROLL_BARS (f);
- bar->prev = Qnil;
- XSETVECTOR (FRAME_SCROLL_BARS (f), bar);
- if (! NILP (bar->next))
- XSETVECTOR (XSCROLL_BAR (bar->next)->prev, bar);
- }
+ bar->next = FRAME_SCROLL_BARS (f);
+ bar->prev = Qnil;
+ XSETVECTOR (FRAME_SCROLL_BARS (f), bar);
+ if (! NILP (bar->next))
+ XSETVECTOR (XSCROLL_BAR (bar->next)->prev, bar);
}
/* Remove all scroll bars on FRAME that haven't been saved since the
case KeyPress:
f = x_any_window_to_frame (dpyinfo, event.xkey.window);
-#ifdef USE_MOTIF
+#if defined USE_MOTIF && defined USE_TOOLKIT_SCROLL_BARS
/* I couldn't find a way to prevent LessTif scroll bars
from consuming key events. */
if (f == 0)
f = x_any_window_to_frame (dpyinfo, XtWindow (widget));
}
}
-#endif /* USE_MOTIF */
+#endif /* USE_MOTIF and USE_TOOLKIT_SCROLL_BARS */
if (f != 0)
{
struct x_display_info *dpyinfo = x_display_info_for_display (display);
Lisp_Object frame, tail;
- /* Indicate that this display is dead. */
+ /* We have to close the display to inform Xt that it doesn't
+ exist anymore. If we don't, Xt will continue to wait for
+ events from the display. As a consequence, a sequence of
-#if 0 /* Closing the display caused a bus error on OpenWindows. */
+ M-x make-frame-on-display RET :1 RET
+ ...kill the new frame, so that we get an IO error...
+ M-x make-frame-on-display RET :1 RET
+
+ will indefinitely wait in Xt for events for display `:1', opened
+ in the first class to make-frame-on-display.
+
+ Closing the display is reported to lead to a bus error on
+ OpenWindows in certain situations. I suspect that is a bug
+ in OpenWindows. I don't know how to cicumvent it here. */
+
#ifdef USE_X_TOOLKIT
XtCloseDisplay (display);
-#endif
#endif
+ /* Indicate that this display is dead. */
if (dpyinfo)
dpyinfo->display = 0;
TOTALLY_UNBLOCK_INPUT;
clear_waiting_for_input ();
+ handling_signal = 0;
error ("%s", error_message);
}
{
#ifdef USE_XIM
#ifdef HAVE_X11R6_XIM
- XUnregisterIMInstantiateCallback (dpyinfo->display, dpyinfo->xrdb,
- NULL, EMACS_CLASS,
- xim_instantiate_callback, NULL);
+ if (dpyinfo->display)
+ XUnregisterIMInstantiateCallback (dpyinfo->display, dpyinfo->xrdb,
+ NULL, EMACS_CLASS,
+ xim_instantiate_callback, NULL);
#endif /* not HAVE_X11R6_XIM */
- XCloseIM (dpyinfo->xim);
+ if (dpyinfo->display)
+ XCloseIM (dpyinfo->xim);
dpyinfo->xim = NULL;
XFree (dpyinfo->xim_styles);
#endif /* USE_XIM */
- PIXEL_WIDTH (f)
+ f->output_data.x->left_pos);
- if (flags & YNegative)
- {
- int menubar_height = 0;
+ {
+ int height = PIXEL_HEIGHT (f);
-#ifdef USE_X_TOOLKIT
- if (f->output_data.x->menubar_widget)
- menubar_height
- = (f->output_data.x->menubar_widget->core.height
- + f->output_data.x->menubar_widget->core.border_width);
+#if defined USE_X_TOOLKIT && defined USE_MOTIF
+ /* Something is fishy here. When using Motif, starting Emacs with
+ `-g -0-0', the frame appears too low by a few pixels.
+
+ This seems to be so because initially, while Emacs is starting,
+ the column widget's height and the frame's pixel height are
+ different. The column widget's height is the right one. In
+ later invocations, when Emacs is up, the frame's pixel height
+ is right, though.
+
+ It's not obvious where the initial small difference comes from.
+ 2000-12-01, gerd. */
+
+ XtVaGetValues (f->output_data.x->column_widget, XtNheight, &height, NULL);
#endif
-
- f->output_data.x->top_pos = (FRAME_X_DISPLAY_INFO (f)->height
- - 2 * f->output_data.x->border_width
- - win_y
- - PIXEL_HEIGHT (f)
- - menubar_height
- + f->output_data.x->top_pos);
- }
+ if (flags & YNegative)
+ f->output_data.x->top_pos = (FRAME_X_DISPLAY_INFO (f)->height
+ - 2 * f->output_data.x->border_width
+ - win_y
+ - height
+ + f->output_data.x->top_pos);
+ }
+
/* The left_pos and top_pos
are now relative to the top and left screen edges,
so the flags should correspond. */
{
Lisp_Object type;
int original_top, original_left;
+ int retry_count = 2;
+
+ retry:
BLOCK_INPUT;
/* See if a MapNotify event has been processed. */
FRAME_SAMPLE_VISIBILITY (f);
}
+
+ /* 2000-09-28: In
+
+ (let ((f (selected-frame)))
+ (iconify-frame f)
+ (raise-frame f))
+
+ the frame is not raised with various window managers on
+ FreeBSD, Linux and Solaris. It turns out that, for some
+ unknown reason, the call to XtMapWidget is completely ignored.
+ Mapping the widget a second time works. */
+
+ if (!FRAME_VISIBLE_P (f) && --retry_count > 0)
+ goto retry;
}
}
UNBLOCK_INPUT;
#endif /* not USE_X_TOOLKIT */
}
+
\f
-/* Destroy the X window of frame F. */
+/* Free X resources of frame F. */
void
-x_destroy_window (f)
+x_free_frame_resources (f)
struct frame *f;
{
struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
/* If a display connection is dead, don't try sending more
commands to the X server. */
- if (dpyinfo->display != 0)
+ if (dpyinfo->display)
{
- if (f->output_data.x->icon_desc != 0)
+ if (f->output_data.x->icon_desc)
XDestroyWindow (FRAME_X_DISPLAY (f), f->output_data.x->icon_desc);
+
#ifdef HAVE_X_I18N
if (FRAME_XIC (f))
free_frame_xic (f);
#endif
- XDestroyWindow (FRAME_X_DISPLAY (f), f->output_data.x->window_desc);
+
+ if (FRAME_X_WINDOW (f))
+ XDestroyWindow (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f));
+
#ifdef USE_X_TOOLKIT
if (f->output_data.x->widget)
XtDestroyWidget (f->output_data.x->widget);
unload_color (f, f->output_data.x->cursor_foreground_pixel);
unload_color (f, f->output_data.x->border_pixel);
unload_color (f, f->output_data.x->mouse_pixel);
+
if (f->output_data.x->scroll_bar_background_pixel != -1)
unload_color (f, f->output_data.x->scroll_bar_background_pixel);
if (f->output_data.x->scroll_bar_foreground_pixel != -1)
unload_color (f, f->output_data.x->white_relief.pixel);
if (f->output_data.x->black_relief.allocated_p)
unload_color (f, f->output_data.x->black_relief.pixel);
+
+ if (FRAME_FACE_CACHE (f))
+ free_frame_faces (f);
- free_frame_faces (f);
+ x_free_gcs (f);
XFlush (FRAME_X_DISPLAY (f));
}
xfree (f->output_data.x->saved_menu_event);
xfree (f->output_data.x);
- f->output_data.x = 0;
+ f->output_data.x = NULL;
+
if (f == dpyinfo->x_focus_frame)
dpyinfo->x_focus_frame = 0;
if (f == dpyinfo->x_focus_event_frame)
if (f == dpyinfo->x_highlight_frame)
dpyinfo->x_highlight_frame = 0;
- dpyinfo->reference_count--;
-
if (f == dpyinfo->mouse_face_mouse_frame)
{
dpyinfo->mouse_face_beg_row
UNBLOCK_INPUT;
}
+
+
+/* Destroy the X window of frame F. */
+
+void
+x_destroy_window (f)
+ struct frame *f;
+{
+ struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
+
+ /* If a display connection is dead, don't try sending more
+ commands to the X server. */
+ if (dpyinfo->display != 0)
+ x_free_frame_resources (f);
+
+ dpyinfo->reference_count--;
+}
+
\f
/* Setting window manager hints. */
fontp->size = font->max_bounds.width;
fontp->height = FONT_HEIGHT (font);
- {
- /* For some font, ascent and descent in max_bounds field is
- larger than the above value. */
- int max_height = font->max_bounds.ascent + font->max_bounds.descent;
- if (max_height > fontp->height)
- fontp->height = max_height;
- }
if (NILP (font_names))
{
elt = XCAR (list);
if (CONSP (elt)
&& STRINGP (XCAR (elt))
- && (fast_c_string_match_ignore_case (XCAR (elt), fontp->name)
- >= 0))
+ && ((fast_c_string_match_ignore_case (XCAR (elt), fontp->name)
+ >= 0)
+ || (fast_c_string_match_ignore_case (XCAR (elt), fontp->full_name)
+ >= 0)))
break;
}
/* We have definitely succeeded. Record the new connection. */
dpyinfo = (struct x_display_info *) xmalloc (sizeof (struct x_display_info));
+ bzero (dpyinfo, sizeof *dpyinfo);
#ifdef MULTI_KBOARD
{
{
extern int gray_bitmap_width, gray_bitmap_height;
- extern unsigned char *gray_bitmap_bits;
+ extern char *gray_bitmap_bits;
dpyinfo->gray
= XCreatePixmapFromBitmapData (dpyinfo->display, dpyinfo->root_window,
gray_bitmap_bits,
xfree (dpyinfo->font_table);
xfree (dpyinfo->x_id_name);
+ xfree (dpyinfo->color_cells);
xfree (dpyinfo);
}
+
\f
/* Set up use of X before we make the first connection. */
}
#endif
-#if USE_TOOLKIT_SCROLL_BARS
+#ifdef USE_TOOLKIT_SCROLL_BARS
xaw3d_arrow_scroll = False;
xaw3d_pick_top = True;
#endif
DEFVAR_BOOL ("x-toolkit-scroll-bars-p", &x_toolkit_scroll_bars_p,
"If not nil, Emacs uses toolkit scroll bars.");
-#if USE_TOOLKIT_SCROLL_BARS
+#ifdef USE_TOOLKIT_SCROLL_BARS
x_toolkit_scroll_bars_p = 1;
#else
x_toolkit_scroll_bars_p = 0;
}
#endif /* not HAVE_X_WINDOWS */
-