#include <signal.h>
#include <config.h>
#include <stdio.h>
#ifdef HAVE_X_WINDOWS
#include "lisp.h"
#include "blockinput.h"
#include "syssignal.h"
#include "xterm.h"
#include <X11/cursorfont.h>
#ifndef USG
#ifndef makedev
#include <sys/types.h>
#endif
#endif
#ifdef BSD_SYSTEM
#include <sys/ioctl.h>
#endif
#include "systty.h"
#include "systime.h"
#ifndef INCLUDED_FCNTL
#include <fcntl.h>
#endif
#include <ctype.h>
#include <errno.h>
#include <setjmp.h>
#include <sys/stat.h>
#include "charset.h"
#include "ccl.h"
#include "frame.h"
#include "fontset.h"
#include "dispextern.h"
#include "termhooks.h"
#include "termopts.h"
#include "termchar.h"
#if 0
#include "sink.h"
#include "sinkmask.h"
#endif
#include "gnu.h"
#include "disptab.h"
#include "buffer.h"
#include "window.h"
#include "keyboard.h"
#include "intervals.h"
#include "process.h"
#ifdef USE_X_TOOLKIT
#include <X11/Shell.h>
#endif
#ifdef USE_X_TOOLKIT
extern void free_frame_menubar ();
extern FRAME_PTR x_menubar_window_to_frame ();
#if (XtSpecificationRelease >= 5) && !defined(NO_EDITRES)
#define HACK_EDITRES
extern void _XEditResCheckMessages ();
#endif
#endif
#ifndef USE_X_TOOLKIT
#define x_any_window_to_frame x_window_to_frame
#define x_top_window_to_frame x_window_to_frame
#endif
#ifdef USE_X_TOOLKIT
#include "widget.h"
#ifndef XtNinitialState
#define XtNinitialState "initialState"
#endif
#endif
#ifdef HAVE_SETLOCALE
#include <locale.h>
#endif
#ifdef SOLARIS2
#include <string.h>
#endif
#ifndef min
#define min(a,b) ((a)<(b) ? (a) : (b))
#endif
#ifndef max
#define max(a,b) ((a)>(b) ? (a) : (b))
#endif
struct x_display_info *x_display_list;
Lisp_Object x_display_name_list;
extern struct frame *updating_frame;
extern int waiting_for_input;
struct frame *pending_autoraise_frame;
#ifdef USE_X_TOOLKIT
XtAppContext Xt_app_con;
static String Xt_default_resources[] =
{
0
};
#endif
static int flexlines;
static int highlight;
static int curs_x;
static int curs_y;
static FRAME_PTR last_mouse_frame;
static XRectangle last_mouse_glyph;
static Lisp_Object last_mouse_press_frame;
static Lisp_Object last_mouse_scroll_bar;
static Time last_mouse_movement_time;
#ifdef __STDC__
static int volatile input_signal_count;
#else
static int input_signal_count;
#endif
static int x_noop_count;
extern char **initial_argv;
extern int initial_argc;
extern Lisp_Object Vcommand_line_args, Vsystem_name;
extern Lisp_Object Vx_no_window_manager;
extern Lisp_Object Qface, Qmouse_face;
extern int errno;
extern int extra_keyboard_modifiers;
static Lisp_Object Qvendor_specific_keysyms;
extern XrmDatabase x_load_resources ();
extern Lisp_Object x_icon_type ();
void x_delete_display ();
static void redraw_previous_char ();
static void redraw_following_char ();
static unsigned int x_x_to_emacs_modifiers ();
static int fast_find_position ();
static void note_mouse_highlight ();
static void clear_mouse_face ();
static void show_mouse_face ();
static void do_line_dance ();
static void XTcursor_to ();
static void XTclear_end_of_line ();
static int x_io_error_quitter ();
int x_catch_errors ();
void x_uncatch_errors ();
#if 0
struct record
{
char *locus;
int type;
};
struct record event_record[100];
int event_record_index;
record_event (locus, type)
char *locus;
int type;
{
if (event_record_index == sizeof (event_record) / sizeof (struct record))
event_record_index = 0;
event_record[event_record_index].locus = locus;
event_record[event_record_index].type = type;
event_record_index++;
}
#endif
struct x_display_info *
x_display_info_for_display (dpy)
Display *dpy;
{
struct x_display_info *dpyinfo;
for (dpyinfo = x_display_list; dpyinfo; dpyinfo = dpyinfo->next)
if (dpyinfo->display == dpy)
return dpyinfo;
return 0;
}
static void
XTupdate_begin (f)
struct frame *f;
{
int mask;
if (f == 0)
abort ();
flexlines = f->height;
highlight = 0;
BLOCK_INPUT;
curs_x = FRAME_CURSOR_X (f);
curs_y = FRAME_CURSOR_Y (f);
if (f == FRAME_X_DISPLAY_INFO (f)->mouse_face_mouse_frame)
{
FRAME_X_DISPLAY_INFO (f)->mouse_face_defer = 1;
if (FRAME_GARBAGED_P (f))
FRAME_X_DISPLAY_INFO (f)->mouse_face_window = Qnil;
if (!NILP (FRAME_X_DISPLAY_INFO (f)->mouse_face_window))
{
int firstline, lastline, i;
struct window *w = XWINDOW (FRAME_X_DISPLAY_INFO (f)->mouse_face_window);
for (firstline = 0; firstline < f->height; firstline++)
if (FRAME_DESIRED_GLYPHS (f)->enable[firstline])
break;
lastline = f->height;
for (i = f->height - 1; i >= 0; i--)
{
if (FRAME_DESIRED_GLYPHS (f)->enable[i])
break;
else
lastline = i;
}
if (! (firstline > (XFASTINT (w->top) + window_internal_height (w))
|| lastline < XFASTINT (w->top)))
clear_mouse_face (FRAME_X_DISPLAY_INFO (f));
}
}
UNBLOCK_INPUT;
}
static void
XTupdate_end (f)
struct frame *f;
{
int mask;
BLOCK_INPUT;
do_line_dance ();
x_display_cursor (f, 1, curs_x, curs_y);
FRAME_X_DISPLAY_INFO (f)->mouse_face_defer = 0;
#if 0
if (f == FRAME_X_DISPLAY_INFO (f)->mouse_face_mouse_frame)
note_mouse_highlight (f, FRAME_X_DISPLAY_INFO (f)->mouse_face_mouse_x,
FRAME_X_DISPLAY_INFO (f)->mouse_face_mouse_y);
#endif
XFlush (FRAME_X_DISPLAY (f));
UNBLOCK_INPUT;
}
static void
XTframe_up_to_date (f)
FRAME_PTR f;
{
BLOCK_INPUT;
if (FRAME_X_DISPLAY_INFO (f)->mouse_face_deferred_gc
|| f == FRAME_X_DISPLAY_INFO (f)->mouse_face_mouse_frame)
{
if (FRAME_X_DISPLAY_INFO (f)->mouse_face_mouse_frame)
note_mouse_highlight (FRAME_X_DISPLAY_INFO (f)->mouse_face_mouse_frame,
FRAME_X_DISPLAY_INFO (f)->mouse_face_mouse_x,
FRAME_X_DISPLAY_INFO (f)->mouse_face_mouse_y);
FRAME_X_DISPLAY_INFO (f)->mouse_face_deferred_gc = 0;
}
UNBLOCK_INPUT;
}
void
XTreassert_line_highlight (new, vpos)
int new, vpos;
{
highlight = new;
}
static void
XTchange_line_highlight (new_highlight, vpos, first_unused_hpos)
int new_highlight, vpos, first_unused_hpos;
{
highlight = new_highlight;
XTcursor_to (vpos, 0);
XTclear_end_of_line (FRAME_WINDOW_WIDTH (updating_frame));
}
static void
XTset_terminal_modes ()
{
}
static void
XTreset_terminal_modes ()
{
}
static void
XTcursor_to (row, col)
register int row, col;
{
int mask;
int orow = row;
struct frame *f;
f = updating_frame;
if (f == 0)
f = selected_frame;
curs_x = col;
if (curs_x >= FRAME_CURSOR_X_LIMIT (f))
curs_x = FRAME_CURSOR_X_LIMIT (f) - 1;
curs_y = row;
if (updating_frame == 0)
{
BLOCK_INPUT;
x_display_cursor (selected_frame, 1, curs_x, curs_y);
XFlush (FRAME_X_DISPLAY (selected_frame));
UNBLOCK_INPUT;
}
}
#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))
#if 1
static int
dumpglyphs (f, left, top, gp, n, hl, just_foreground, cmpcharp)
struct frame *f;
int left, top;
register GLYPH *gp;
register int n;
int hl;
int just_foreground;
struct cmpchar_info *cmpcharp;
{
XChar2b *x_2byte_buffer
= (XChar2b *) alloca (FRAME_WINDOW_WIDTH (f) * sizeof (*x_2byte_buffer));
register XChar2b *cp;
char *x_1byte_buffer
= (char *) alloca (FRAME_WINDOW_WIDTH (f) * sizeof (*x_1byte_buffer));
register int tlen = GLYPH_TABLE_LENGTH;
register Lisp_Object *tbase = GLYPH_TABLE_BASE;
Window window = FRAME_X_WINDOW (f);
int orig_left = left;
int gidx = 0;
int i;
while (n > 0)
{
int cf, len;
GLYPH g = *gp;
int ch, charset;
Lisp_Object first_ch;
int highest, lowest;
GLYPH_FOLLOW_ALIASES (tbase, tlen, g);
cf = (cmpcharp ? cmpcharp->face_work : FAST_GLYPH_FACE (g));
ch = FAST_GLYPH_CHAR (g);
if (unibyte_display_via_language_environment
&& SINGLE_BYTE_CHAR_P (ch)
&& (ch >= 0240
|| (ch >= 0200 && !NILP (Vnonascii_translation_table))))
ch = unibyte_char_to_multibyte (ch);
if (gidx == 0) XSETFASTINT (first_ch, ch);
charset = CHAR_CHARSET (ch);
if (charset == CHARSET_COMPOSITION)
{
cmpcharp = cmpchar_table[COMPOSITE_CHAR_ID (ch)];
cmpcharp->face_work = cf;
dumpglyphs (f, left, top, cmpcharp->glyph, cmpcharp->glyph_len,
hl, just_foreground, cmpcharp);
left += FONT_WIDTH (f->output_data.x->font) * cmpcharp->width;
++gp, --n;
while (gp && (*gp & GLYPH_MASK_PADDING)) ++gp, --n;
cmpcharp = NULL;
continue;
}
cp = x_2byte_buffer;
while (n > 0)
{
int this_charset, c1, c2;
g = *gp;
GLYPH_FOLLOW_ALIASES (tbase, tlen, g);
ch = FAST_GLYPH_CHAR (g);
if (unibyte_display_via_language_environment
&& SINGLE_BYTE_CHAR_P (ch)
&& (ch >= 0240
|| (ch >= 0200 && !NILP (Vnonascii_translation_table))))
ch = unibyte_char_to_multibyte (ch);
SPLIT_CHAR (ch, this_charset, c1, c2);
if (this_charset != charset
|| (cmpcharp == NULL && FAST_GLYPH_FACE (g) != cf))
break;
if (c2 > 0)
cp->byte1 = c1, cp->byte2 = c2;
else
cp->byte1 = 0, cp->byte2 = c1;
++cp;
++gp, --n;
while (gp && (*gp & GLYPH_MASK_PADDING))
++gp, --n;
}
len = cp - x_2byte_buffer;
{
struct face *face = FRAME_DEFAULT_FACE (f);
XFontStruct *font = NULL;
GC gc;
int stippled = 0;
int line_height = f->output_data.x->line_height;
int glyph_width
= (FONT_WIDTH (f->output_data.x->font)
* (cmpcharp ? cmpcharp->width : CHARSET_WIDTH (charset)));
int run_width
= (FONT_WIDTH (f->output_data.x->font)
* (cmpcharp ? cmpcharp->width : len * CHARSET_WIDTH (charset)));
int background_filled;
int baseline;
int relative_compose = 0, default_ascent = 0;
int require_clipping;
if (hl == 3)
cf = FRAME_X_DISPLAY_INFO (f)->mouse_face_face_id;
if (cf != 0)
{
if (cf < 0 || cf >= FRAME_N_COMPUTED_FACES (f)
|| FRAME_COMPUTED_FACES (f) [cf] == 0)
cf = 0;
if (cf == 1)
face = FRAME_MODE_LINE_FACE (f);
else
face = intern_face (f, FRAME_COMPUTED_FACES (f) [cf]);
if (FACE_STIPPLE (face))
stippled = 1;
}
else if (hl == 0)
;
else if (hl == 1)
{
face = FRAME_MODE_LINE_FACE (f);
if (FACE_STIPPLE (face))
stippled = 1;
}
#define FACE_DEFAULT (~0)
if (charset != CHARSET_ASCII)
{
int font_id;
int fontset = FACE_FONTSET (face);
struct font_info *fontp;
if ((fontset < 0 && (fontset = FRAME_FONTSET (f)) < 0)
|| !(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);
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))
baseline = line_height - font->descent;
if (cmpcharp && cmpcharp->cmp_rule == NULL)
{
relative_compose = fontp->relative_compose;
default_ascent = fontp->default_ascent;
}
if (fontp->font_encoder)
{
struct ccl_program *ccl = fontp->font_encoder;
if (CHARSET_DIMENSION (charset) == 1)
for (cp = x_2byte_buffer; cp < x_2byte_buffer + len; cp++)
{
ccl->reg[0] = charset;
ccl->reg[1] = cp->byte2;
ccl_driver (ccl, NULL, NULL, 0, 0, NULL);
if (font->max_byte1 == 0)
cp->byte1 = 0, cp->byte2 = ccl->reg[1];
else
cp->byte1 = ccl->reg[1], cp->byte2 = ccl->reg[2];
}
else
for (cp = x_2byte_buffer; cp < x_2byte_buffer + len; cp++)
{
ccl->reg[0] = charset;
ccl->reg[1] = cp->byte1, ccl->reg[2] = cp->byte2;
ccl_driver (ccl, NULL, NULL, 0, 0, NULL);
if (font->max_byte1 == 0)
cp->byte1 = 0, cp->byte2 = ccl->reg[1];
else
cp->byte1 = ccl->reg[1], cp->byte2 = ccl->reg[2];
}
}
else if (fontp->encoding[charset])
{
int enc = fontp->encoding[charset];
if ((enc == 1 || enc == 2) && CHARSET_DIMENSION (charset) == 2)
for (cp = x_2byte_buffer; cp < x_2byte_buffer + len; cp++)
cp->byte1 |= 0x80;
if (enc == 1 || enc == 3)
for (cp = x_2byte_buffer; cp < x_2byte_buffer + len; cp++)
cp->byte2 |= 0x80;
}
}
else
{
font_not_found:
if (charset == CHARSET_ASCII || charset == charset_latin_iso8859_1)
{
font = FACE_FONT (face);
if (!font || font == (XFontStruct *) FACE_DEFAULT)
font = f->output_data.x->font;
baseline = FONT_BASE (f->output_data.x->font);
if (charset == charset_latin_iso8859_1)
{
if (font->max_char_or_byte2 < 0x80)
font = NULL;
else
{
for (cp = x_2byte_buffer; cp < x_2byte_buffer + len; cp++)
cp->byte2 |= 0x80;
}
}
}
gc = FACE_GC (face);
}
if (hl == 2)
{
stippled = 0;
if (font == f->output_data.x->font
&& face->background == f->output_data.x->background_pixel
&& face->foreground == f->output_data.x->foreground_pixel
&& !cmpcharp)
{
gc = f->output_data.x->cursor_gc;
}
else
{
XGCValues xgcv;
unsigned long mask;
xgcv.background = f->output_data.x->cursor_pixel;
xgcv.foreground = face->background;
if (xgcv.foreground == xgcv.background)
xgcv.foreground = face->foreground;
if (xgcv.foreground == xgcv.background)
xgcv.foreground = f->output_data.x->cursor_foreground_pixel;
if (xgcv.foreground == xgcv.background)
xgcv.foreground = face->foreground;
if (xgcv.background == face->background
&& xgcv.foreground == face->foreground)
{
xgcv.background = face->foreground;
xgcv.foreground = face->background;
}
xgcv.graphics_exposures = 0;
mask = GCForeground | GCBackground | GCGraphicsExposures;
if (font)
{
xgcv.font = font->fid;
mask |= GCFont;
}
if (FRAME_X_DISPLAY_INFO (f)->scratch_cursor_gc)
XChangeGC (FRAME_X_DISPLAY (f),
FRAME_X_DISPLAY_INFO (f)->scratch_cursor_gc,
mask, &xgcv);
else
FRAME_X_DISPLAY_INFO (f)->scratch_cursor_gc
= XCreateGC (FRAME_X_DISPLAY (f), window, mask, &xgcv);
gc = FRAME_X_DISPLAY_INFO (f)->scratch_cursor_gc;
#if 0
if (face->stipple && face->stipple != FACE_DEFAULT)
XSetStipple (FRAME_X_DISPLAY (f), gc, face->stipple);
#endif
}
}
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 (stippled)
{
XSetFillStyle (FRAME_X_DISPLAY (f), gc, FillOpaqueStippled);
XFillRectangle (FRAME_X_DISPLAY (f), window, gc,
left, top, run_width, line_height);
XSetFillStyle (FRAME_X_DISPLAY (f), gc, FillSolid);
background_filled = 1;
}
else if (!font
|| FONT_BASE (font) < baseline
|| (FONT_HEIGHT (font) - FONT_BASE (font)
< line_height - baseline)
|| FONT_WIDTH (font) < glyph_width
|| cmpcharp)
{
XGCValues xgcv;
unsigned long mask = GCForeground | GCBackground | GCFillStyle;
XGetGCValues (FRAME_X_DISPLAY (f), gc, mask, &xgcv);
XSetForeground (FRAME_X_DISPLAY (f), gc, xgcv.background);
XSetFillStyle (FRAME_X_DISPLAY (f), gc, FillSolid);
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)
just_foreground = 1;
}
else
background_filled = 0;
if (font)
{
if (require_clipping)
{
Region region;
XPoint x[4];
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, x_2byte_buffer + i, 1);
else
XDrawImageString16 (FRAME_X_DISPLAY (f), window, gc,
left + glyph_width * i,
top + baseline, x_2byte_buffer + i, 1);
}
else
{
for (i = 0; i < len; i++)
{
if (x_2byte_buffer[i].byte1 != 0)
break;
x_1byte_buffer[i] = x_2byte_buffer[i].byte2;
}
if (i == len)
{
if (background_filled)
XDrawString (FRAME_X_DISPLAY (f), window, gc,
left, top + baseline, x_1byte_buffer, len);
else
XDrawImageString (FRAME_X_DISPLAY (f), window, gc,
left, top + baseline, x_1byte_buffer, len);
}
else
{
if (background_filled)
XDrawString16 (FRAME_X_DISPLAY (f), window, gc,
left, top + baseline, x_2byte_buffer, len);
else
XDrawImageString16 (FRAME_X_DISPLAY (f), window, gc,
left, top + baseline, x_2byte_buffer, len);
}
}
}
else
{
XCharStruct *pcm;
if ((cmpcharp->cmp_rule || relative_compose)
&& gidx == 0)
{
int x_offset = 0;
if (default_ascent
&& CHAR_TABLE_P (Vuse_default_ascent)
&& !NILP (Faref (Vuse_default_ascent, first_ch)))
{
highest = default_ascent;
lowest = 0;
}
else
{
pcm = PER_CHAR_METRIC (font, x_2byte_buffer);
highest = pcm->ascent + 1;
lowest = - pcm->descent;
}
if (cmpcharp->cmp_rule)
x_offset = (cmpcharp->col_offset[0]
* FONT_WIDTH (f->output_data.x->font));
XDrawString16 (FRAME_X_DISPLAY (f), window, gc,
left + x_offset, top + baseline, x_2byte_buffer, 1);
i = 1;
gidx++;
}
else
i = 0;
for (; i < len; i++, gidx++)
{
int x_offset = 0, y_offset = 0;
if (relative_compose)
{
pcm = PER_CHAR_METRIC (font, x_2byte_buffer + i);
if (NILP (Vignore_relative_composition)
|| NILP (Faref (Vignore_relative_composition,
make_number (cmpcharp->glyph[gidx]))))
{
if (- pcm->descent >= relative_compose)
{
y_offset = highest + pcm->descent;
highest += pcm->ascent + pcm->descent;
}
else if (pcm->ascent <= 0)
{
y_offset = lowest - pcm->ascent;
lowest -= pcm->ascent + pcm->descent;
}
}
else
{
if (pcm->ascent > highest)
highest = pcm->ascent;
else if (- pcm->descent < lowest)
lowest = - pcm->descent;
}
}
else if (cmpcharp->cmp_rule)
{
int gref = (cmpcharp->cmp_rule[gidx] - 0xA0) / 9;
int nref = (cmpcharp->cmp_rule[gidx] - 0xA0) % 9;
int bottom, top;
gref = gref / 3 + (gref == 4) * 2;
nref = nref / 3 + (nref == 4) * 2;
pcm = PER_CHAR_METRIC (font, x_2byte_buffer + i);
bottom = ((gref == 0 ? highest : gref == 1 ? 0
: gref == 2 ? lowest
: (highest + lowest) / 2)
- (nref == 0 ? pcm->ascent + pcm->descent
: nref == 1 ? pcm->descent : nref == 2 ? 0
: (pcm->ascent + pcm->descent) / 2));
top = bottom + (pcm->ascent + pcm->descent);
if (top > highest)
highest = top;
if (bottom < lowest)
lowest = bottom;
y_offset = bottom + pcm->descent;
x_offset = (cmpcharp->col_offset[gidx]
* FONT_WIDTH (f->output_data.x->font));
}
XDrawString16 (FRAME_X_DISPLAY (f), window, gc,
left + x_offset, top + baseline - y_offset,
x_2byte_buffer + i, 1);
}
}
if (require_clipping)
XSetClipMask (FRAME_X_DISPLAY (f), gc, None);
#if 0
if (!just_foreground)
{
if (left == orig_left)
redraw_previous_char (f, PIXEL_TO_CHAR_COL (f, left),
PIXEL_TO_CHAR_ROW (f, top), hl == 1);
if (n == 0)
redraw_following_char (f, PIXEL_TO_CHAR_COL (f, left + len * FONT_WIDTH (font)),
PIXEL_TO_CHAR_ROW (f, top), hl == 1);
}
#endif
}
if (!font)
{
int limit = cmpcharp ? 1 : len;
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))
{
int limit = cmpcharp ? 1 : len;
for (i = 0; i < limit; i++)
{
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);
}
}
{
int underline_position = f->output_data.x->font_baseline + 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, run_width, 1);
}
if (!cmpcharp)
left += run_width;
}
}
return (left - orig_left);
}
#endif
#if 0
static void
dumpglyphs (f, left, top, gp, n, hl, font)
struct frame *f;
int left, top;
register GLYPH *gp;
register int n;
int hl;
XFontStruct *font;
{
register int len;
Window window = FRAME_X_WINDOW (f);
GC drawing_gc = (hl == 2 ? f->output_data.x->cursor_gc
: (hl ? f->output_data.x->reverse_gc
: f->output_data.x->normal_gc));
if (sizeof (GLYPH) == sizeof (XChar2b))
XDrawImageString16 (FRAME_X_DISPLAY (f), window, drawing_gc,
left, top + FONT_BASE (font), (XChar2b *) gp, n);
else if (sizeof (GLYPH) == sizeof (unsigned char))
XDrawImageString (FRAME_X_DISPLAY (f), window, drawing_gc,
left, top + FONT_BASE (font), (char *) gp, n);
else
abort ();
}
#endif
static void
XTwrite_glyphs (start, len)
register GLYPH *start;
int len;
{
register int temp_length;
int mask;
struct frame *f;
BLOCK_INPUT;
do_line_dance ();
f = updating_frame;
if (f == 0)
{
f = selected_frame;
curs_x = FRAME_CURSOR_X (f);
curs_y = FRAME_CURSOR_Y (f);
}
dumpglyphs (f,
CHAR_TO_PIXEL_COL (f, curs_x),
CHAR_TO_PIXEL_ROW (f, curs_y),
start, len, highlight, 0, NULL);
if (curs_y == f->phys_cursor_y
&& curs_x <= f->phys_cursor_x
&& curs_x + len > f->phys_cursor_x)
f->phys_cursor_on = 0;
curs_x += len;
if (curs_x >= FRAME_CURSOR_X_LIMIT (f))
curs_x = FRAME_CURSOR_X_LIMIT (f) - 1;
if (updating_frame == 0)
x_display_cursor (f, 1, curs_x, FRAME_CURSOR_Y (f));
UNBLOCK_INPUT;
}
static void
XTclear_end_of_line (first_unused)
register int first_unused;
{
struct frame *f = updating_frame;
int mask;
if (f == 0)
abort ();
if (curs_y < 0 || curs_y >= f->height)
return;
if (first_unused <= 0)
return;
if (first_unused >= FRAME_WINDOW_WIDTH (f))
first_unused = FRAME_WINDOW_WIDTH (f);
first_unused += FRAME_LEFT_SCROLL_BAR_WIDTH (f);
BLOCK_INPUT;
do_line_dance ();
if (curs_y == f->phys_cursor_y
&& curs_x <= f->phys_cursor_x
&& f->phys_cursor_x < first_unused)
f->phys_cursor_on = 0;
XClearArea (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
CHAR_TO_PIXEL_COL (f, curs_x),
CHAR_TO_PIXEL_ROW (f, curs_y),
FONT_WIDTH (f->output_data.x->font) * (first_unused - curs_x),
f->output_data.x->line_height, False);
#if 0
redraw_previous_char (f, curs_x, curs_y, highlight);
#endif
UNBLOCK_INPUT;
}
static void
XTclear_frame ()
{
int mask;
struct frame *f = updating_frame;
if (f == 0)
f = selected_frame;
f->phys_cursor_on = 0;
curs_x = 0;
curs_y = 0;
BLOCK_INPUT;
XClearWindow (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f));
x_scroll_bar_clear (f);
XFlush (FRAME_X_DISPLAY (f));
UNBLOCK_INPUT;
}
#if 0
static void
redraw_previous_char (f, x, y, highlight_flag)
FRAME_PTR f;
int x, y;
int highlight_flag;
{
if (x > 0)
{
int start_x = x - 2;
if (start_x < 0)
start_x = 0;
XClearArea (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
CHAR_TO_PIXEL_COL (f, x - 1),
CHAR_TO_PIXEL_ROW (f, y),
FONT_WIDTH (f->output_data.x->font),
f->output_data.x->line_height, False);
dumpglyphs (f, CHAR_TO_PIXEL_COL (f, start_x),
CHAR_TO_PIXEL_ROW (f, y),
&FRAME_CURRENT_GLYPHS (f)->glyphs[y][start_x],
x - start_x, highlight_flag, 1, NULL);
}
}
static void
redraw_following_char (f, x, y, highlight_flag)
FRAME_PTR f;
int x, y;
int highlight_flag;
{
int limit = FRAME_CURRENT_GLYPHS (f)->used[y];
if (x < limit
&& FRAME_CURRENT_GLYPHS (f)->glyphs[y][x] != SPACEGLYPH)
{
int end_x = x + 2;
if (end_x > limit)
end_x = limit;
XClearArea (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
CHAR_TO_PIXEL_COL (f, x),
CHAR_TO_PIXEL_ROW (f, y),
FONT_WIDTH (f->output_data.x->font),
f->output_data.x->line_height, False);
dumpglyphs (f, CHAR_TO_PIXEL_COL (f, x),
CHAR_TO_PIXEL_ROW (f, y),
&FRAME_CURRENT_GLYPHS (f)->glyphs[y][x],
end_x - x, highlight_flag, 1, NULL);
}
}
#endif
#if 0
static int
font_char_overlap_left (font, c)
XFontStruct *font;
int c;
{
XCharStruct *s;
if (font->per_char == 0)
s = &font->max_bounds;
else
{
int rowlen = font->max_char_or_byte2 - font->min_char_or_byte2 + 1;
int row, within;
row = c >> 8;
within = c & 0177;
if (!(within >= font->min_char_or_byte2
&& within <= font->max_char_or_byte2
&& row >= font->min_byte1
&& row <= font->max_byte1))
{
c = font->default_char;
row = c >> (BITS_PER_INT - 8);
within = c & 0177;
}
if (!(within >= font->min_char_or_byte2
&& within <= font->max_char_or_byte2
&& row >= font->min_byte1
&& row <= font->max_byte1))
return 0;
else
s = (font->per_char + (within - font->min_char_or_byte2)
+ row * rowlen);
}
return (s && s->lbearing < 0);
}
static int
font_char_overlap_right (font, c)
XFontStruct *font;
int c;
{
XCharStruct *s;
if (font->per_char == 0)
s = &font->max_bounds;
else
{
int rowlen = font->max_char_or_byte2 - font->min_char_or_byte2 + 1;
int row, within;
row = c >> 8;
within = c & 0177;
if (!(within >= font->min_char_or_byte2
&& within <= font->max_char_or_byte2
&& row >= font->min_byte1
&& row <= font->max_byte1))
{
c = font->default_char;
row = c >> (BITS_PER_INT - 8);
within = c & 0177;
}
if (!(within >= font->min_char_or_byte2
&& within <= font->max_char_or_byte2
&& row >= font->min_byte1
&& row <= font->max_byte1))
return 0;
else
s = (font->per_char + (within - font->min_char_or_byte2)
+ row * rowlen);
}
return (s && s->rbearing >= s->width);
}
#endif
#if defined (HAVE_TIMEVAL) && defined (HAVE_SELECT)
static int
timeval_subtract (result, x, y)
struct timeval *result, x, y;
{
if (x.tv_usec < y.tv_usec)
{
int nsec = (y.tv_usec - x.tv_usec) / 1000000 + 1;
y.tv_usec -= 1000000 * nsec;
y.tv_sec += nsec;
}
if (x.tv_usec - y.tv_usec > 1000000)
{
int nsec = (y.tv_usec - x.tv_usec) / 1000000;
y.tv_usec += 1000000 * nsec;
y.tv_sec -= nsec;
}
result->tv_sec = x.tv_sec - y.tv_sec;
result->tv_usec = x.tv_usec - y.tv_usec;
return x.tv_sec < y.tv_sec;
}
void
XTflash (f)
struct frame *f;
{
BLOCK_INPUT;
{
GC gc;
{
XGCValues values;
values.function = GXxor;
values.foreground = (f->output_data.x->foreground_pixel
^ f->output_data.x->background_pixel);
gc = XCreateGC (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
GCFunction | GCForeground, &values);
}
{
int height = CHAR_TO_PIXEL_HEIGHT (f, FRAME_HEIGHT (f));
int flash_height = FRAME_LINE_HEIGHT (f);
int flash_left = FRAME_INTERNAL_BORDER_WIDTH (f);
int flash_right = PIXEL_WIDTH (f) - FRAME_INTERNAL_BORDER_WIDTH (f);
int width;
switch (FRAME_VERTICAL_SCROLL_BAR_TYPE (f))
{
case vertical_scroll_bar_left:
flash_left += VERTICAL_SCROLL_BAR_WIDTH_TRIM;
break;
case vertical_scroll_bar_right:
flash_right -= VERTICAL_SCROLL_BAR_WIDTH_TRIM;
break;
}
width = flash_right - flash_left;
if (height > 3 * FRAME_LINE_HEIGHT (f))
{
XFillRectangle (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), gc,
flash_left, FRAME_INTERNAL_BORDER_WIDTH (f),
width, flash_height);
XFillRectangle (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), gc,
flash_left,
(height - flash_height
- FRAME_INTERNAL_BORDER_WIDTH (f)),
width, flash_height);
}
else
XFillRectangle (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), gc,
flash_left, FRAME_INTERNAL_BORDER_WIDTH (f),
width, height - 2 * FRAME_INTERNAL_BORDER_WIDTH (f));
XFlush (FRAME_X_DISPLAY (f));
{
struct timeval wakeup, now;
EMACS_GET_TIME (wakeup);
wakeup.tv_usec += 150000;
wakeup.tv_sec += (wakeup.tv_usec / 1000000);
wakeup.tv_usec %= 1000000;
while (1)
{
struct timeval timeout;
EMACS_GET_TIME (timeout);
if (timeval_subtract (&timeout, wakeup, timeout))
break;
select (0, NULL, NULL, NULL, &timeout);
}
}
if (height > 3 * FRAME_LINE_HEIGHT (f))
{
XFillRectangle (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), gc,
flash_left, FRAME_INTERNAL_BORDER_WIDTH (f),
width, flash_height);
XFillRectangle (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), gc,
flash_left,
(height - flash_height
- FRAME_INTERNAL_BORDER_WIDTH (f)),
width, flash_height);
}
else
XFillRectangle (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), gc,
flash_left, FRAME_INTERNAL_BORDER_WIDTH (f),
width, height - 2 * FRAME_INTERNAL_BORDER_WIDTH (f));
XFreeGC (FRAME_X_DISPLAY (f), gc);
XFlush (FRAME_X_DISPLAY (f));
}
}
UNBLOCK_INPUT;
}
#endif
#define XRINGBELL XBell (FRAME_X_DISPLAY (selected_frame), 0)
void
XTring_bell ()
{
if (FRAME_X_DISPLAY (selected_frame) == 0)
return;
#if defined (HAVE_TIMEVAL) && defined (HAVE_SELECT)
if (visible_bell)
XTflash (selected_frame);
else
#endif
{
BLOCK_INPUT;
XRINGBELL;
XFlush (FRAME_X_DISPLAY (selected_frame));
UNBLOCK_INPUT;
}
}
static void
XTinsert_glyphs (start, len)
register char *start;
register int len;
{
abort ();
}
static void
XTdelete_glyphs (n)
register int n;
{
abort ();
}
static void
XTset_terminal_window (n)
register int n;
{
if (updating_frame == 0)
abort ();
if ((n <= 0) || (n > updating_frame->height))
flexlines = updating_frame->height;
else
flexlines = n;
}
static int *line_dance;
static int line_dance_len;
static int line_dance_in_progress;
void
XTins_del_lines (vpos, n)
int vpos, n;
{
register int fence, i;
if (vpos >= flexlines)
return;
if (!line_dance_in_progress)
{
int ht = updating_frame->height;
if (ht > line_dance_len)
{
line_dance = (int *)xrealloc (line_dance, ht * sizeof (int));
line_dance_len = ht;
}
for (i = 0; i < ht; ++i) line_dance[i] = i;
line_dance_in_progress = 1;
}
if (n >= 0)
{
if (n > flexlines - vpos)
n = flexlines - vpos;
fence = vpos + n;
for (i = flexlines; --i >= fence;)
line_dance[i] = line_dance[i-n];
for (i = fence; --i >= vpos;)
line_dance[i] = -1;
}
else
{
n = -n;
if (n > flexlines - vpos)
n = flexlines - vpos;
fence = flexlines - n;
for (i = vpos; i < fence; ++i)
line_dance[i] = line_dance[i + n];
for (i = fence; i < flexlines; ++i)
line_dance[i] = -1;
}
}
static void
do_line_dance ()
{
register int i, j, distance;
register struct frame *f;
int ht;
int intborder;
if (!line_dance_in_progress)
return;
f = updating_frame;
if (f == 0)
abort ();
ht = f->height;
intborder = CHAR_TO_PIXEL_COL (f, FRAME_LEFT_SCROLL_BAR_WIDTH (f));
x_update_cursor (updating_frame, 0);
for (i = 0; i < ht; ++i)
if (line_dance[i] != -1 && (distance = line_dance[i]-i) > 0)
{
for (j = i; (j < ht && line_dance[j] != -1
&& line_dance[j]-j == distance); ++j);
XCopyArea (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
FRAME_X_WINDOW (f), f->output_data.x->normal_gc,
intborder, CHAR_TO_PIXEL_ROW (f, i+distance),
FRAME_WINDOW_WIDTH (f) * FONT_WIDTH (f->output_data.x->font),
(j-i) * f->output_data.x->line_height,
intborder, CHAR_TO_PIXEL_ROW (f, i));
i = j-1;
}
for (i = ht; --i >=0; )
if (line_dance[i] != -1 && (distance = line_dance[i]-i) < 0)
{
for (j = i; (--j >= 0 && line_dance[j] != -1
&& line_dance[j]-j == distance););
XCopyArea (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
FRAME_X_WINDOW (f), f->output_data.x->normal_gc,
intborder, CHAR_TO_PIXEL_ROW (f, j+1+distance),
FRAME_WINDOW_WIDTH (f) * FONT_WIDTH (f->output_data.x->font),
(i-j) * f->output_data.x->line_height,
intborder, CHAR_TO_PIXEL_ROW (f, j+1));
i = j+1;
}
for (i = 0; i < ht; ++i)
if (line_dance[i] == -1)
{
for (j = i; j < ht && line_dance[j] == -1; ++j);
XClearArea (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
intborder, CHAR_TO_PIXEL_ROW (f, i),
FRAME_WINDOW_WIDTH (f) * FONT_WIDTH (f->output_data.x->font),
(j-i) * f->output_data.x->line_height, False);
i = j-1;
}
line_dance_in_progress = 0;
}
static void clear_cursor ();
static void
dumprectangle (f, left, top, cols, rows)
struct frame *f;
register int left, top, cols, rows;
{
register struct frame_glyphs *active_frame = FRAME_CURRENT_GLYPHS (f);
int cursor_cleared = 0;
int bottom, right;
register int y;
if (FRAME_GARBAGED_P (f))
return;
bottom = top + rows;
right = left + cols;
top = PIXEL_TO_CHAR_ROW (f, top);
left = PIXEL_TO_CHAR_COL (f, left);
bottom += (f->output_data.x->line_height - 1);
right += (FONT_WIDTH (f->output_data.x->font) - 1);
bottom = PIXEL_TO_CHAR_ROW (f, bottom);
right = PIXEL_TO_CHAR_COL (f, right);
if (left < 0)
left = 0;
if (top < 0)
top = 0;
if (right > FRAME_WINDOW_WIDTH (f))
right = FRAME_WINDOW_WIDTH (f);
if (bottom > f->height)
bottom = f->height;
cols = right - left;
rows = bottom - top;
if (rows <= 0) return;
if (cols <= 0) return;
if ((f->phys_cursor_x >= left) && (f->phys_cursor_x < right)
&& (f->phys_cursor_y >= top) && (f->phys_cursor_y < bottom))
{
clear_cursor (f);
cursor_cleared = 1;
}
for (y = top; y < bottom; y++)
{
GLYPH *line = &active_frame->glyphs[y][left];
if (! active_frame->enable[y] || left > active_frame->used[y])
continue;
while (*line & GLYPH_MASK_PADDING)
{
left--;
line--;
cols++;
}
dumpglyphs (f,
CHAR_TO_PIXEL_COL (f, left),
CHAR_TO_PIXEL_ROW (f, y),
line, min (cols, active_frame->used[y] - left),
active_frame->highlight[y], 0, NULL);
}
if (cursor_cleared)
x_update_cursor (f, 1);
}
static void
frame_highlight (f)
struct frame *f;
{
BLOCK_INPUT;
XSetWindowBorder (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
f->output_data.x->border_pixel);
UNBLOCK_INPUT;
x_update_cursor (f, 1);
}
static void
frame_unhighlight (f)
struct frame *f;
{
BLOCK_INPUT;
XSetWindowBorderPixmap (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
f->output_data.x->border_tile);
UNBLOCK_INPUT;
x_update_cursor (f, 1);
}
static void XTframe_rehighlight ();
static void x_frame_rehighlight ();
static void
x_new_focus_frame (dpyinfo, frame)
struct x_display_info *dpyinfo;
struct frame *frame;
{
struct frame *old_focus = dpyinfo->x_focus_frame;
int events_enqueued = 0;
if (frame != dpyinfo->x_focus_frame)
{
dpyinfo->x_focus_frame = frame;
if (old_focus && old_focus->auto_lower)
x_lower_frame (old_focus);
#if 0
selected_frame = frame;
XSETFRAME (XWINDOW (selected_frame->selected_window)->frame,
selected_frame);
Fselect_window (selected_frame->selected_window);
choose_minibuf_frame ();
#endif
if (dpyinfo->x_focus_frame && dpyinfo->x_focus_frame->auto_raise)
pending_autoraise_frame = dpyinfo->x_focus_frame;
else
pending_autoraise_frame = 0;
}
x_frame_rehighlight (dpyinfo);
}
void
x_mouse_leave (dpyinfo)
struct x_display_info *dpyinfo;
{
x_new_focus_frame (dpyinfo, dpyinfo->x_focus_event_frame);
}
static void
XTframe_rehighlight (frame)
struct frame *frame;
{
x_frame_rehighlight (FRAME_X_DISPLAY_INFO (frame));
}
static void
x_frame_rehighlight (dpyinfo)
struct x_display_info *dpyinfo;
{
struct frame *old_highlight = dpyinfo->x_highlight_frame;
if (dpyinfo->x_focus_frame)
{
dpyinfo->x_highlight_frame
= ((GC_FRAMEP (FRAME_FOCUS_FRAME (dpyinfo->x_focus_frame)))
? XFRAME (FRAME_FOCUS_FRAME (dpyinfo->x_focus_frame))
: dpyinfo->x_focus_frame);
if (! FRAME_LIVE_P (dpyinfo->x_highlight_frame))
{
FRAME_FOCUS_FRAME (dpyinfo->x_focus_frame) = Qnil;
dpyinfo->x_highlight_frame = dpyinfo->x_focus_frame;
}
}
else
dpyinfo->x_highlight_frame = 0;
if (dpyinfo->x_highlight_frame != old_highlight)
{
if (old_highlight)
frame_unhighlight (old_highlight);
if (dpyinfo->x_highlight_frame)
frame_highlight (dpyinfo->x_highlight_frame);
}
}
static void
x_find_modifier_meanings (dpyinfo)
struct x_display_info *dpyinfo;
{
int min_code, max_code;
KeySym *syms;
int syms_per_code;
XModifierKeymap *mods;
dpyinfo->meta_mod_mask = 0;
dpyinfo->shift_lock_mask = 0;
dpyinfo->alt_mod_mask = 0;
dpyinfo->super_mod_mask = 0;
dpyinfo->hyper_mod_mask = 0;
#ifdef HAVE_X11R4
XDisplayKeycodes (dpyinfo->display, &min_code, &max_code);
#else
min_code = dpyinfo->display->min_keycode;
max_code = dpyinfo->display->max_keycode;
#endif
syms = XGetKeyboardMapping (dpyinfo->display,
min_code, max_code - min_code + 1,
&syms_per_code);
mods = XGetModifierMapping (dpyinfo->display);
{
int row, col;
for (row = 3; row < 8; row++)
for (col = 0; col < mods->max_keypermod; col++)
{
KeyCode code
= mods->modifiermap[(row * mods->max_keypermod) + col];
if (code == 0)
continue;
{
int code_col;
for (code_col = 0; code_col < syms_per_code; code_col++)
{
int sym = syms[((code - min_code) * syms_per_code) + code_col];
switch (sym)
{
case XK_Meta_L:
case XK_Meta_R:
dpyinfo->meta_mod_mask |= (1 << row);
break;
case XK_Alt_L:
case XK_Alt_R:
dpyinfo->alt_mod_mask |= (1 << row);
break;
case XK_Hyper_L:
case XK_Hyper_R:
dpyinfo->hyper_mod_mask |= (1 << row);
break;
case XK_Super_L:
case XK_Super_R:
dpyinfo->super_mod_mask |= (1 << row);
break;
case XK_Shift_Lock:
if ((1 << row) == LockMask)
dpyinfo->shift_lock_mask = LockMask;
break;
}
}
}
}
}
if (! dpyinfo->meta_mod_mask)
{
dpyinfo->meta_mod_mask = dpyinfo->alt_mod_mask;
dpyinfo->alt_mod_mask = 0;
}
if (dpyinfo->alt_mod_mask & dpyinfo->meta_mod_mask)
{
dpyinfo->alt_mod_mask &= ~dpyinfo->meta_mod_mask;
}
XFree ((char *) syms);
XFreeModifiermap (mods);
}
static unsigned int
x_x_to_emacs_modifiers (dpyinfo, state)
struct x_display_info *dpyinfo;
unsigned int state;
{
return ( ((state & (ShiftMask | dpyinfo->shift_lock_mask)) ? shift_modifier : 0)
| ((state & ControlMask) ? ctrl_modifier : 0)
| ((state & dpyinfo->meta_mod_mask) ? meta_modifier : 0)
| ((state & dpyinfo->alt_mod_mask) ? alt_modifier : 0)
| ((state & dpyinfo->super_mod_mask) ? super_modifier : 0)
| ((state & dpyinfo->hyper_mod_mask) ? hyper_modifier : 0));
}
static unsigned int
x_emacs_to_x_modifiers (dpyinfo, state)
struct x_display_info *dpyinfo;
unsigned int state;
{
return ( ((state & alt_modifier) ? dpyinfo->alt_mod_mask : 0)
| ((state & super_modifier) ? dpyinfo->super_mod_mask : 0)
| ((state & hyper_modifier) ? dpyinfo->hyper_mod_mask : 0)
| ((state & shift_modifier) ? ShiftMask : 0)
| ((state & ctrl_modifier) ? ControlMask : 0)
| ((state & meta_modifier) ? dpyinfo->meta_mod_mask : 0));
}
char *
x_get_keysym_name (keysym)
KeySym keysym;
{
char *value;
BLOCK_INPUT;
value = XKeysymToString (keysym);
UNBLOCK_INPUT;
return value;
}
void
pixel_to_glyph_coords (f, pix_x, pix_y, x, y, bounds, noclip)
FRAME_PTR f;
register int pix_x, pix_y;
register int *x, *y;
XRectangle *bounds;
int noclip;
{
if (pix_x < 0)
pix_x -= FONT_WIDTH ((f)->output_data.x->font) - 1;
if (pix_y < 0)
pix_y -= (f)->output_data.x->line_height - 1;
pix_x = PIXEL_TO_CHAR_COL (f, pix_x);
pix_y = PIXEL_TO_CHAR_ROW (f, pix_y);
if (bounds)
{
bounds->width = FONT_WIDTH (f->output_data.x->font);
bounds->height = f->output_data.x->line_height;
bounds->x = CHAR_TO_PIXEL_COL (f, pix_x);
bounds->y = CHAR_TO_PIXEL_ROW (f, pix_y);
}
if (!noclip)
{
if (pix_x < 0)
pix_x = 0;
else if (pix_x > FRAME_WINDOW_WIDTH (f))
pix_x = FRAME_WINDOW_WIDTH (f);
if (pix_y < 0)
pix_y = 0;
else if (pix_y > f->height)
pix_y = f->height;
}
*x = pix_x;
*y = pix_y;
}
void
glyph_to_pixel_coords (f, x, y, pix_x, pix_y)
FRAME_PTR f;
register int x, y;
register int *pix_x, *pix_y;
{
*pix_x = CHAR_TO_PIXEL_COL (f, x);
*pix_y = CHAR_TO_PIXEL_ROW (f, y);
}
static Lisp_Object
construct_mouse_click (result, event, f)
struct input_event *result;
XButtonEvent *event;
struct frame *f;
{
result->kind = mouse_click;
result->code = event->button - Button1;
result->timestamp = event->time;
result->modifiers = (x_x_to_emacs_modifiers (FRAME_X_DISPLAY_INFO (f),
event->state)
| (event->type == ButtonRelease
? up_modifier
: down_modifier));
{
int row, column;
#if 0
pixel_to_glyph_coords (f, event->x, event->y, &column, &row, NULL, 0);
XSETFASTINT (result->x, column);
XSETFASTINT (result->y, row);
#endif
XSETINT (result->x, event->x);
XSETINT (result->y, event->y);
XSETFRAME (result->frame_or_window, f);
}
}
static Lisp_Object
construct_menu_click (result, event, f)
struct input_event *result;
XButtonEvent *event;
struct frame *f;
{
result->kind = mouse_click;
result->code = event->button - Button1;
result->timestamp = event->time;
result->modifiers = (x_x_to_emacs_modifiers (FRAME_X_DISPLAY_INFO (f),
event->state)
| (event->type == ButtonRelease
? up_modifier
: down_modifier));
XSETINT (result->x, event->x);
XSETINT (result->y, -1);
XSETFRAME (result->frame_or_window, f);
}
static void
note_mouse_movement (frame, event)
FRAME_PTR frame;
XMotionEvent *event;
{
last_mouse_movement_time = event->time;
if (event->window != FRAME_X_WINDOW (frame))
{
frame->mouse_moved = 1;
last_mouse_scroll_bar = Qnil;
note_mouse_highlight (frame, -1, -1);
}
else if (event->x < last_mouse_glyph.x
|| event->x >= last_mouse_glyph.x + last_mouse_glyph.width
|| event->y < last_mouse_glyph.y
|| event->y >= last_mouse_glyph.y + last_mouse_glyph.height)
{
frame->mouse_moved = 1;
last_mouse_scroll_bar = Qnil;
note_mouse_highlight (frame, event->x, event->y);
}
}
static int disable_mouse_highlight;
static void
note_mouse_highlight (f, x, y)
FRAME_PTR f;
int x, y;
{
int row, column, portion;
XRectangle new_glyph;
Lisp_Object window;
struct window *w;
if (disable_mouse_highlight)
return;
FRAME_X_DISPLAY_INFO (f)->mouse_face_mouse_x = x;
FRAME_X_DISPLAY_INFO (f)->mouse_face_mouse_y = y;
FRAME_X_DISPLAY_INFO (f)->mouse_face_mouse_frame = f;
if (FRAME_X_DISPLAY_INFO (f)->mouse_face_defer)
return;
if (gc_in_progress)
{
FRAME_X_DISPLAY_INFO (f)->mouse_face_deferred_gc = 1;
return;
}
pixel_to_glyph_coords (f, x, y, &column, &row,
&new_glyph, FRAME_X_DISPLAY_INFO (f)->grabbed);
window = window_from_coordinates (f, column, row, &portion);
w = XWINDOW (window);
if (! EQ (window, FRAME_X_DISPLAY_INFO (f)->mouse_face_window))
clear_mouse_face (FRAME_X_DISPLAY_INFO (f));
if (WINDOWP (window) && portion == 0 && row >= 0 && column >= 0
&& row < FRAME_HEIGHT (f) && column < FRAME_WIDTH (f)
&& EQ (w->window_end_valid, 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;
for (i = column; i >= 0; i--)
if (ptr[i] > 0)
break;
pos = ptr[i];
if (pos <= 0)
clear_mouse_face (FRAME_X_DISPLAY_INFO (f));
else if (! (EQ (window, FRAME_X_DISPLAY_INFO (f)->mouse_face_window)
&& row >= FRAME_X_DISPLAY_INFO (f)->mouse_face_beg_row
&& row <= FRAME_X_DISPLAY_INFO (f)->mouse_face_end_row
&& (row > FRAME_X_DISPLAY_INFO (f)->mouse_face_beg_row
|| column >= FRAME_X_DISPLAY_INFO (f)->mouse_face_beg_col)
&& (row < FRAME_X_DISPLAY_INFO (f)->mouse_face_end_row
|| column < FRAME_X_DISPLAY_INFO (f)->mouse_face_end_col
|| FRAME_X_DISPLAY_INFO (f)->mouse_face_past_end)))
{
Lisp_Object mouse_face, overlay, position;
Lisp_Object *overlay_vec;
int len, noverlays, ignor1;
struct buffer *obuf;
int obegv, ozv;
if (pos > BUF_Z (XBUFFER (w->buffer)))
return;
obuf = current_buffer;
current_buffer = XBUFFER (w->buffer);
obegv = BEGV;
ozv = ZV;
BEGV = BEG;
ZV = Z;
clear_mouse_face (FRAME_X_DISPLAY_INFO (f));
XSETINT (position, pos);
len = 10;
overlay_vec = (Lisp_Object *) xmalloc (len * sizeof (Lisp_Object));
noverlays = overlays_at (pos, 1, &overlay_vec, &len,
NULL, NULL);
noverlays = sort_overlays (overlay_vec, noverlays, w);
overlay = Qnil;
for (i = 0; i < noverlays; i++)
{
mouse_face = Foverlay_get (overlay_vec[i], Qmouse_face);
if (!NILP (mouse_face))
{
overlay = overlay_vec[i];
break;
}
}
free (overlay_vec);
if (NILP (overlay))
mouse_face = Fget_text_property (position, Qmouse_face, w->buffer);
if (! NILP (overlay))
{
Lisp_Object before, after;
int ignore;
before = Foverlay_start (overlay);
after = Foverlay_end (overlay);
fast_find_position (window, XFASTINT (before),
&FRAME_X_DISPLAY_INFO (f)->mouse_face_beg_col,
&FRAME_X_DISPLAY_INFO (f)->mouse_face_beg_row);
FRAME_X_DISPLAY_INFO (f)->mouse_face_past_end
= !fast_find_position (window, XFASTINT (after),
&FRAME_X_DISPLAY_INFO (f)->mouse_face_end_col,
&FRAME_X_DISPLAY_INFO (f)->mouse_face_end_row);
FRAME_X_DISPLAY_INFO (f)->mouse_face_window = window;
FRAME_X_DISPLAY_INFO (f)->mouse_face_face_id
= compute_char_face (f, w, pos, 0, 0,
&ignore, pos + 1, 1);
show_mouse_face (FRAME_X_DISPLAY_INFO (f), 1);
}
else if (! NILP (mouse_face))
{
Lisp_Object before, after, beginning, end;
int ignore;
beginning = Fmarker_position (w->start);
XSETINT (end, (BUF_Z (XBUFFER (w->buffer))
- XFASTINT (w->window_end_pos)));
before
= Fprevious_single_property_change (make_number (pos + 1),
Qmouse_face,
w->buffer, beginning);
after
= Fnext_single_property_change (position, Qmouse_face,
w->buffer, end);
fast_find_position (window, XFASTINT (before),
&FRAME_X_DISPLAY_INFO (f)->mouse_face_beg_col,
&FRAME_X_DISPLAY_INFO (f)->mouse_face_beg_row);
FRAME_X_DISPLAY_INFO (f)->mouse_face_past_end
= !fast_find_position (window, XFASTINT (after),
&FRAME_X_DISPLAY_INFO (f)->mouse_face_end_col,
&FRAME_X_DISPLAY_INFO (f)->mouse_face_end_row);
FRAME_X_DISPLAY_INFO (f)->mouse_face_window = window;
FRAME_X_DISPLAY_INFO (f)->mouse_face_face_id
= compute_char_face (f, w, pos, 0, 0,
&ignore, pos + 1, 1);
show_mouse_face (FRAME_X_DISPLAY_INFO (f), 1);
}
BEGV = obegv;
ZV = ozv;
current_buffer = obuf;
}
}
}
static int
fast_find_position (window, pos, columnp, rowp)
Lisp_Object window;
int pos;
int *columnp, *rowp;
{
struct window *w = XWINDOW (window);
FRAME_PTR f = XFRAME (WINDOW_FRAME (w));
int i;
int row = 0;
int left = WINDOW_LEFT_MARGIN (w);
int top = XFASTINT (w->top);
int height = XFASTINT (w->height) - ! MINI_WINDOW_P (w);
int width = window_internal_width (w);
int *charstarts;
int lastcol;
int maybe_next_line = 0;
for (i = 0;
i < height;
i++)
{
int linestart = FRAME_CURRENT_GLYPHS (f)->charstarts[top + i][left];
if (linestart > pos)
break;
if (linestart == pos && pos == BUF_ZV (XBUFFER (w->buffer)))
{
maybe_next_line = 1;
break;
}
if (linestart > 0)
row = i;
}
charstarts = FRAME_CURRENT_GLYPHS (f)->charstarts[top + row];
lastcol = left;
for (i = 0; i < width; i++)
{
if (charstarts[left + i] == pos)
{
*rowp = row + top;
*columnp = i + left;
return 1;
}
else if (charstarts[left + i] > pos)
break;
else if (charstarts[left + i] > 0)
lastcol = left + i + 1;
}
if (maybe_next_line)
{
row++;
lastcol = left;
}
*rowp = row + top;
*columnp = lastcol;
return 0;
}
static void
show_mouse_face (dpyinfo, hl)
struct x_display_info *dpyinfo;
int hl;
{
struct window *w = XWINDOW (dpyinfo->mouse_face_window);
int width = window_internal_width (w);
FRAME_PTR f = XFRAME (WINDOW_FRAME (w));
int i;
int cursor_off = 0;
int old_curs_x = curs_x;
int old_curs_y = curs_y;
curs_x = f->phys_cursor_x;
curs_y = f->phys_cursor_y;
for (i = FRAME_X_DISPLAY_INFO (f)->mouse_face_beg_row;
i <= FRAME_X_DISPLAY_INFO (f)->mouse_face_end_row; i++)
{
int column = (i == FRAME_X_DISPLAY_INFO (f)->mouse_face_beg_row
? FRAME_X_DISPLAY_INFO (f)->mouse_face_beg_col
: WINDOW_LEFT_MARGIN (w));
int endcolumn = (i == FRAME_X_DISPLAY_INFO (f)->mouse_face_end_row
? FRAME_X_DISPLAY_INFO (f)->mouse_face_end_col
: WINDOW_LEFT_MARGIN (w) + width);
endcolumn = min (endcolumn, FRAME_CURRENT_GLYPHS (f)->used[i]);
if (i == curs_y
&& curs_x >= column - 1
&& curs_x <= endcolumn)
{
x_update_cursor (f, 0);
cursor_off = 1;
}
dumpglyphs (f,
CHAR_TO_PIXEL_COL (f, column),
CHAR_TO_PIXEL_ROW (f, i),
FRAME_CURRENT_GLYPHS (f)->glyphs[i] + column,
endcolumn - column,
hl > 0 ? 3 : 0, 0, NULL);
}
if (cursor_off)
x_display_cursor (f, 1, curs_x, curs_y);
curs_x = old_curs_x;
curs_y = old_curs_y;
if (hl > 0)
XDefineCursor (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
f->output_data.x->cross_cursor);
else
XDefineCursor (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
f->output_data.x->text_cursor);
}
static void
clear_mouse_face (dpyinfo)
struct x_display_info *dpyinfo;
{
if (! NILP (dpyinfo->mouse_face_window))
show_mouse_face (dpyinfo, 0);
dpyinfo->mouse_face_beg_row = dpyinfo->mouse_face_beg_col = -1;
dpyinfo->mouse_face_end_row = dpyinfo->mouse_face_end_col = -1;
dpyinfo->mouse_face_window = Qnil;
}
void
cancel_mouse_face (f)
FRAME_PTR f;
{
Lisp_Object window;
struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
window = dpyinfo->mouse_face_window;
if (! NILP (window) && XFRAME (XWINDOW (window)->frame) == f)
{
dpyinfo->mouse_face_beg_row = dpyinfo->mouse_face_beg_col = -1;
dpyinfo->mouse_face_end_row = dpyinfo->mouse_face_end_col = -1;
dpyinfo->mouse_face_window = Qnil;
}
}
static struct scroll_bar *x_window_to_scroll_bar ();
static void x_scroll_bar_report_motion ();
static void
XTmouse_position (fp, insist, bar_window, part, x, y, time)
FRAME_PTR *fp;
int insist;
Lisp_Object *bar_window;
enum scroll_bar_part *part;
Lisp_Object *x, *y;
unsigned long *time;
{
FRAME_PTR f1;
BLOCK_INPUT;
if (! NILP (last_mouse_scroll_bar) && insist == 0)
x_scroll_bar_report_motion (fp, bar_window, part, x, y, time);
else
{
Window root;
int root_x, root_y;
Window dummy_window;
int dummy;
Lisp_Object frame, tail;
FOR_EACH_FRAME (tail, frame)
if (FRAME_X_DISPLAY (XFRAME (frame)) == FRAME_X_DISPLAY (*fp))
XFRAME (frame)->mouse_moved = 0;
last_mouse_scroll_bar = Qnil;
XQueryPointer (FRAME_X_DISPLAY (*fp),
DefaultRootWindow (FRAME_X_DISPLAY (*fp)),
&root,
&dummy_window,
&root_x, &root_y,
&dummy, &dummy,
(unsigned int *) &dummy);
{
Window win, child;
int win_x, win_y;
int parent_x, parent_y;
int count;
win = root;
count = x_catch_errors (FRAME_X_DISPLAY (*fp));
if (FRAME_X_DISPLAY_INFO (*fp)->grabbed && last_mouse_frame
&& FRAME_LIVE_P (last_mouse_frame))
{
XTranslateCoordinates (FRAME_X_DISPLAY (*fp),
root, FRAME_X_WINDOW (last_mouse_frame),
root_x, root_y, &win_x, &win_y,
&child);
f1 = last_mouse_frame;
}
else
{
while (1)
{
XTranslateCoordinates (FRAME_X_DISPLAY (*fp),
root, win,
root_x, root_y, &win_x, &win_y,
&child);
if (child == None || child == win)
break;
win = child;
parent_x = win_x;
parent_y = win_y;
}
f1 = x_any_window_to_frame (FRAME_X_DISPLAY_INFO (*fp), win);
}
if (x_had_errors_p (FRAME_X_DISPLAY (*fp)))
f1 = 0;
x_uncatch_errors (FRAME_X_DISPLAY (*fp), count);
if (! f1)
{
struct scroll_bar *bar = x_window_to_scroll_bar (win);
if (bar)
{
f1 = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
win_x = parent_x;
win_y = parent_y;
}
}
if (f1 == 0 && insist > 0)
f1 = selected_frame;
if (f1)
{
int ignore1, ignore2;
pixel_to_glyph_coords (f1, win_x, win_y, &ignore1, &ignore2,
&last_mouse_glyph,
FRAME_X_DISPLAY_INFO (f1)->grabbed
|| insist);
*bar_window = Qnil;
*part = 0;
*fp = f1;
XSETINT (*x, win_x);
XSETINT (*y, win_y);
*time = last_mouse_movement_time;
}
}
}
UNBLOCK_INPUT;
}
static struct scroll_bar *
x_window_to_scroll_bar (window_id)
Window window_id;
{
Lisp_Object tail, frame;
for (tail = Vframe_list;
XGCTYPE (tail) == Lisp_Cons;
tail = XCONS (tail)->cdr)
{
Lisp_Object frame, bar, condemned;
frame = XCONS (tail)->car;
if (! GC_FRAMEP (frame))
abort ();
condemned = FRAME_CONDEMNED_SCROLL_BARS (XFRAME (frame));
for (bar = FRAME_SCROLL_BARS (XFRAME (frame));
! GC_NILP (bar) || (bar = condemned,
condemned = Qnil,
! GC_NILP (bar));
bar = XSCROLL_BAR (bar)->next)
if (SCROLL_BAR_X_WINDOW (XSCROLL_BAR (bar)) == window_id)
return XSCROLL_BAR (bar);
}
return 0;
}
static struct scroll_bar *
x_scroll_bar_create (window, top, left, width, height)
struct window *window;
int top, left, width, height;
{
FRAME_PTR f = XFRAME (WINDOW_FRAME (window));
struct scroll_bar *bar
= XSCROLL_BAR (Fmake_vector (make_number (SCROLL_BAR_VEC_SIZE), Qnil));
BLOCK_INPUT;
{
XSetWindowAttributes a;
unsigned long mask;
a.background_pixel = f->output_data.x->background_pixel;
a.event_mask = (ButtonPressMask | ButtonReleaseMask
| ButtonMotionMask | PointerMotionHintMask
| ExposureMask);
a.cursor = FRAME_X_DISPLAY_INFO (f)->vertical_scroll_bar_cursor;
mask = (CWBackPixel | CWEventMask | CWCursor);
#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,
f->output_data.x->edit_widget, al, ac);
SET_SCROLL_BAR_X_WINDOW
(bar, sb_widget->core.window);
#endif
SET_SCROLL_BAR_X_WINDOW
(bar,
XCreateWindow (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
left + VERTICAL_SCROLL_BAR_WIDTH_TRIM, top,
width - VERTICAL_SCROLL_BAR_WIDTH_TRIM * 2, height,
0, CopyFromParent, CopyFromParent, CopyFromParent,
mask, &a));
}
XSETWINDOW (bar->window, window);
XSETINT (bar->top, top);
XSETINT (bar->left, left);
XSETINT (bar->width, width);
XSETINT (bar->height, height);
XSETINT (bar->start, 0);
XSETINT (bar->end, 0);
bar->dragging = Qnil;
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);
XMapRaised (FRAME_X_DISPLAY (f), SCROLL_BAR_X_WINDOW (bar));
UNBLOCK_INPUT;
return bar;
}
static void
x_scroll_bar_set_handle (bar, start, end, rebuild)
struct scroll_bar *bar;
int start, end;
int rebuild;
{
int dragging = ! NILP (bar->dragging);
Window w = SCROLL_BAR_X_WINDOW (bar);
FRAME_PTR f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
GC gc = f->output_data.x->normal_gc;
if (! rebuild
&& start == XINT (bar->start)
&& end == XINT (bar->end))
return;
BLOCK_INPUT;
{
int inside_width = VERTICAL_SCROLL_BAR_INSIDE_WIDTH (f, XINT (bar->width));
int inside_height = VERTICAL_SCROLL_BAR_INSIDE_HEIGHT (f, XINT (bar->height));
int top_range = VERTICAL_SCROLL_BAR_TOP_RANGE (f, XINT (bar->height));
{
int length = end - start;
if (start < 0)
start = 0;
else if (start > top_range)
start = top_range;
end = start + length;
if (end < start)
end = start;
else if (end > top_range && ! dragging)
end = top_range;
}
XSETINT (bar->start, start);
XSETINT (bar->end, end);
if (end > top_range)
end = top_range;
end += VERTICAL_SCROLL_BAR_MIN_HANDLE;
if (0 < start)
XClearArea (FRAME_X_DISPLAY (f), w,
VERTICAL_SCROLL_BAR_LEFT_BORDER,
VERTICAL_SCROLL_BAR_TOP_BORDER,
inside_width, start,
False);
XFillRectangle (FRAME_X_DISPLAY (f), w, gc,
VERTICAL_SCROLL_BAR_LEFT_BORDER,
VERTICAL_SCROLL_BAR_TOP_BORDER + start,
inside_width, end - start);
if (end < inside_height)
XClearArea (FRAME_X_DISPLAY (f), w,
VERTICAL_SCROLL_BAR_LEFT_BORDER,
VERTICAL_SCROLL_BAR_TOP_BORDER + end,
inside_width, inside_height - end,
False);
}
UNBLOCK_INPUT;
}
static void
x_scroll_bar_move (bar, top, left, width, height)
struct scroll_bar *bar;
int top, left, width, height;
{
Window w = SCROLL_BAR_X_WINDOW (bar);
FRAME_PTR f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
BLOCK_INPUT;
{
XWindowChanges wc;
unsigned int mask = 0;
wc.x = left + VERTICAL_SCROLL_BAR_WIDTH_TRIM;
wc.y = top;
wc.width = width - VERTICAL_SCROLL_BAR_WIDTH_TRIM * 2;
wc.height = height;
if (left != XINT (bar->left)) mask |= CWX;
if (top != XINT (bar->top)) mask |= CWY;
if (width != XINT (bar->width)) mask |= CWWidth;
if (height != XINT (bar->height)) mask |= CWHeight;
if (mask)
XConfigureWindow (FRAME_X_DISPLAY (f), SCROLL_BAR_X_WINDOW (bar),
mask, &wc);
}
XSETINT (bar->left, left);
XSETINT (bar->top, top);
XSETINT (bar->width, width);
XSETINT (bar->height, height);
UNBLOCK_INPUT;
}
static void
x_scroll_bar_remove (bar)
struct scroll_bar *bar;
{
FRAME_PTR f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
BLOCK_INPUT;
XDestroyWindow (FRAME_X_DISPLAY (f), SCROLL_BAR_X_WINDOW (bar));
XWINDOW (bar->window)->vertical_scroll_bar = Qnil;
UNBLOCK_INPUT;
}
static void
XTset_vertical_scroll_bar (window, portion, whole, position)
struct window *window;
int portion, whole, position;
{
FRAME_PTR f = XFRAME (WINDOW_FRAME (window));
int top = XINT (window->top);
int left = WINDOW_VERTICAL_SCROLL_BAR_COLUMN (window);
int height = WINDOW_VERTICAL_SCROLL_BAR_HEIGHT (window);
int pixel_top = CHAR_TO_PIXEL_ROW (f, top);
int pixel_left = CHAR_TO_PIXEL_COL (f, left);
int pixel_width
= (FRAME_SCROLL_BAR_PIXEL_WIDTH (f) > 0
? FRAME_SCROLL_BAR_PIXEL_WIDTH (f)
: (FRAME_SCROLL_BAR_COLS (f) * FONT_WIDTH (f->output_data.x->font)));
int pixel_height = VERTICAL_SCROLL_BAR_PIXEL_HEIGHT (f, height);
struct scroll_bar *bar;
if (NILP (window->vertical_scroll_bar))
bar = x_scroll_bar_create (window,
pixel_top, pixel_left,
pixel_width, pixel_height);
else
{
bar = XSCROLL_BAR (window->vertical_scroll_bar);
x_scroll_bar_move (bar, pixel_top, pixel_left, pixel_width, pixel_height);
}
if (NILP (bar->dragging))
{
int top_range = VERTICAL_SCROLL_BAR_TOP_RANGE (f, pixel_height);
if (whole == 0)
x_scroll_bar_set_handle (bar, 0, top_range, 0);
else
{
int start = ((double) position * top_range) / whole;
int end = ((double) (position + portion) * top_range) / whole;
x_scroll_bar_set_handle (bar, start, end, 0);
}
}
XSETVECTOR (window->vertical_scroll_bar, bar);
}
static void
XTcondemn_scroll_bars (frame)
FRAME_PTR frame;
{
while (! NILP (FRAME_SCROLL_BARS (frame)))
{
Lisp_Object bar;
bar = FRAME_SCROLL_BARS (frame);
FRAME_SCROLL_BARS (frame) = XSCROLL_BAR (bar)->next;
XSCROLL_BAR (bar)->next = FRAME_CONDEMNED_SCROLL_BARS (frame);
XSCROLL_BAR (bar)->prev = Qnil;
if (! NILP (FRAME_CONDEMNED_SCROLL_BARS (frame)))
XSCROLL_BAR (FRAME_CONDEMNED_SCROLL_BARS (frame))->prev = bar;
FRAME_CONDEMNED_SCROLL_BARS (frame) = bar;
}
}
static void
XTredeem_scroll_bar (window)
struct window *window;
{
struct scroll_bar *bar;
if (NILP (window->vertical_scroll_bar))
abort ();
bar = XSCROLL_BAR (window->vertical_scroll_bar);
{
FRAME_PTR f = XFRAME (WINDOW_FRAME (window));
if (NILP (bar->prev))
{
if (EQ (FRAME_SCROLL_BARS (f), window->vertical_scroll_bar))
return;
else if (EQ (FRAME_CONDEMNED_SCROLL_BARS (f),
window->vertical_scroll_bar))
FRAME_CONDEMNED_SCROLL_BARS (f) = bar->next;
else
abort ();
}
else
XSCROLL_BAR (bar->prev)->next = bar->next;
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);
}
}
static void
XTjudge_scroll_bars (f)
FRAME_PTR f;
{
Lisp_Object bar, next;
bar = FRAME_CONDEMNED_SCROLL_BARS (f);
FRAME_CONDEMNED_SCROLL_BARS (f) = Qnil;
for (; ! NILP (bar); bar = next)
{
struct scroll_bar *b = XSCROLL_BAR (bar);
x_scroll_bar_remove (b);
next = b->next;
b->next = b->prev = Qnil;
}
}
static void
x_scroll_bar_expose (bar, event)
struct scroll_bar *bar;
XEvent *event;
{
Window w = SCROLL_BAR_X_WINDOW (bar);
FRAME_PTR f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
GC gc = f->output_data.x->normal_gc;
int width_trim = VERTICAL_SCROLL_BAR_WIDTH_TRIM;
BLOCK_INPUT;
x_scroll_bar_set_handle (bar, XINT (bar->start), XINT (bar->end), 1);
XDrawRectangle (FRAME_X_DISPLAY (f), w, gc,
0, 0,
XINT (bar->width) - 1 - width_trim - width_trim,
XINT (bar->height) - 1);
UNBLOCK_INPUT;
}
static void
x_scroll_bar_handle_click (bar, event, emacs_event)
struct scroll_bar *bar;
XEvent *event;
struct input_event *emacs_event;
{
if (! GC_WINDOWP (bar->window))
abort ();
emacs_event->kind = scroll_bar_click;
emacs_event->code = event->xbutton.button - Button1;
emacs_event->modifiers
= (x_x_to_emacs_modifiers (FRAME_X_DISPLAY_INFO
(XFRAME (WINDOW_FRAME (XWINDOW (bar->window)))),
event->xbutton.state)
| (event->type == ButtonRelease
? up_modifier
: down_modifier));
emacs_event->frame_or_window = bar->window;
emacs_event->timestamp = event->xbutton.time;
{
FRAME_PTR f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
int internal_height
= VERTICAL_SCROLL_BAR_INSIDE_HEIGHT (f, XINT (bar->height));
int top_range
= VERTICAL_SCROLL_BAR_TOP_RANGE (f, XINT (bar->height));
int y = event->xbutton.y - VERTICAL_SCROLL_BAR_TOP_BORDER;
if (y < 0) y = 0;
if (y > top_range) y = top_range;
if (y < XINT (bar->start))
emacs_event->part = scroll_bar_above_handle;
else if (y < XINT (bar->end) + VERTICAL_SCROLL_BAR_MIN_HANDLE)
emacs_event->part = scroll_bar_handle;
else
emacs_event->part = scroll_bar_below_handle;
#if 0
if (event->type == ButtonPress
&& emacs_event->part == scroll_bar_handle)
XSETINT (bar->dragging, y - XINT (bar->start));
#endif
if (event->type == ButtonRelease
&& ! NILP (bar->dragging))
{
int new_start = y - XINT (bar->dragging);
int new_end = new_start + (XINT (bar->end) - XINT (bar->start));
x_scroll_bar_set_handle (bar, new_start, new_end, 0);
bar->dragging = Qnil;
}
#if 0
if (emacs_event->part == scroll_bar_handle)
emacs_event->x = bar->start;
else
XSETINT (emacs_event->x, y);
#else
XSETINT (emacs_event->x, y);
#endif
XSETINT (emacs_event->y, top_range);
}
}
static void
x_scroll_bar_note_movement (bar, event)
struct scroll_bar *bar;
XEvent *event;
{
FRAME_PTR f = XFRAME (XWINDOW (bar->window)->frame);
last_mouse_movement_time = event->xmotion.time;
f->mouse_moved = 1;
XSETVECTOR (last_mouse_scroll_bar, bar);
if (! GC_NILP (bar->dragging))
{
int new_start = event->xmotion.y - XINT (bar->dragging);
if (new_start != XINT (bar->start))
{
int new_end = new_start + (XINT (bar->end) - XINT (bar->start));
x_scroll_bar_set_handle (bar, new_start, new_end, 0);
}
}
}
static void
x_scroll_bar_report_motion (fp, bar_window, part, x, y, time)
FRAME_PTR *fp;
Lisp_Object *bar_window;
enum scroll_bar_part *part;
Lisp_Object *x, *y;
unsigned long *time;
{
struct scroll_bar *bar = XSCROLL_BAR (last_mouse_scroll_bar);
Window w = SCROLL_BAR_X_WINDOW (bar);
FRAME_PTR f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
int win_x, win_y;
Window dummy_window;
int dummy_coord;
unsigned int dummy_mask;
BLOCK_INPUT;
if (! XQueryPointer (FRAME_X_DISPLAY (f), w,
&dummy_window, &dummy_window,
&dummy_coord, &dummy_coord,
&win_x, &win_y,
&dummy_mask))
;
else
{
int inside_height
= VERTICAL_SCROLL_BAR_INSIDE_HEIGHT (f, XINT (bar->height));
int top_range
= VERTICAL_SCROLL_BAR_TOP_RANGE (f, XINT (bar->height));
win_y -= VERTICAL_SCROLL_BAR_TOP_BORDER;
if (! NILP (bar->dragging))
win_y -= XINT (bar->dragging);
if (win_y < 0)
win_y = 0;
if (win_y > top_range)
win_y = top_range;
*fp = f;
*bar_window = bar->window;
if (! NILP (bar->dragging))
*part = scroll_bar_handle;
else if (win_y < XINT (bar->start))
*part = scroll_bar_above_handle;
else if (win_y < XINT (bar->end) + VERTICAL_SCROLL_BAR_MIN_HANDLE)
*part = scroll_bar_handle;
else
*part = scroll_bar_below_handle;
XSETINT (*x, win_y);
XSETINT (*y, top_range);
f->mouse_moved = 0;
last_mouse_scroll_bar = Qnil;
}
*time = last_mouse_movement_time;
UNBLOCK_INPUT;
}
void
x_scroll_bar_clear (f)
FRAME_PTR f;
{
Lisp_Object bar;
if (FRAME_HAS_VERTICAL_SCROLL_BARS (f))
for (bar = FRAME_SCROLL_BARS (f); VECTORP (bar);
bar = XSCROLL_BAR (bar)->next)
XClearArea (FRAME_X_DISPLAY (f), SCROLL_BAR_X_WINDOW (XSCROLL_BAR (bar)),
0, 0, 0, 0, True);
}
void
process_expose_from_menu (event)
XEvent event;
{
FRAME_PTR f;
struct x_display_info *dpyinfo;
BLOCK_INPUT;
dpyinfo = x_display_info_for_display (event.xexpose.display);
f = x_window_to_frame (dpyinfo, event.xexpose.window);
if (f)
{
if (f->async_visible == 0)
{
f->async_visible = 1;
f->async_iconified = 0;
f->output_data.x->has_been_visible = 1;
SET_FRAME_GARBAGED (f);
}
else
{
dumprectangle (x_window_to_frame (dpyinfo, 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;
}
struct selection_event_queue
{
XEvent event;
struct selection_event_queue *next;
};
static struct selection_event_queue *queue;
static int x_queue_selection_requests;
static void
x_queue_event (f, event)
FRAME_PTR f;
XEvent *event;
{
struct selection_event_queue *queue_tmp
= (struct selection_event_queue *) malloc (sizeof (struct selection_event_queue));
if (queue_tmp != NULL)
{
queue_tmp->event = *event;
queue_tmp->next = queue;
queue = queue_tmp;
}
}
static void
x_unqueue_events (display)
Display *display;
{
while (queue != NULL)
{
struct selection_event_queue *queue_tmp = queue;
XPutBackEvent (display, &queue_tmp->event);
queue = queue_tmp->next;
free ((char *)queue_tmp);
}
}
void
x_start_queuing_selection_requests (display)
Display *display;
{
x_queue_selection_requests++;
}
void
x_stop_queuing_selection_requests (display)
Display *display;
{
x_queue_selection_requests--;
x_unqueue_events (display);
}
static Time enter_timestamp;
static XComposeStatus compose_status;
static int temp_index;
static short temp_buffer[100];
struct x_display_info *XTread_socket_fake_io_error;
static struct x_display_info *next_noop_dpyinfo;
#define SET_SAVED_MENU_EVENT(size) { \
if (f->output_data.x->saved_menu_event == 0) \
f->output_data.x->saved_menu_event = (XEvent*)xmalloc (sizeof (XEvent)); \
bcopy (&event, f->output_data.x->saved_menu_event, size); \
if (numchars >= 1) \
{ \
bufp->kind = menu_bar_activate_event; \
XSETFRAME (bufp->frame_or_window, f); \
bufp++; \
count++; \
numchars--; \
} \
}
#define SET_SAVED_BUTTON_EVENT SET_SAVED_MENU_EVENT (sizeof (XButtonEvent))
#define SET_SAVED_KEY_EVENT SET_SAVED_MENU_EVENT (sizeof (XKeyEvent))
int
XTread_socket (sd, bufp, numchars, expected)
register int sd;
struct input_event *bufp;
int numchars;
int expected;
{
int count = 0;
int nbytes = 0;
int mask;
int items_pending;
XEvent event;
struct frame *f;
int event_found = 0;
int prefix;
Lisp_Object part;
struct x_display_info *dpyinfo;
#ifdef HAVE_X_I18N
Status status_return;
#endif
if (interrupt_input_blocked)
{
interrupt_input_pending = 1;
return -1;
}
interrupt_input_pending = 0;
BLOCK_INPUT;
input_signal_count++;
if (numchars <= 0)
abort ();
for (dpyinfo = x_display_list; dpyinfo; dpyinfo = dpyinfo->next)
{
#if 0
#ifdef FIOSNBIO
fcntl (dpyinfo->connection, F_SETFL, 0);
#endif
#endif
#if 0
#ifndef SIGIO
#ifndef HAVE_SELECT
if (! (fcntl (dpyinfo->connection, F_GETFL, 0) & O_NDELAY))
{
extern int read_alarm_should_throw;
read_alarm_should_throw = 1;
XPeekEvent (dpyinfo->display, &event);
read_alarm_should_throw = 0;
}
#endif
#endif
#endif
if (dpyinfo == XTread_socket_fake_io_error)
{
XTread_socket_fake_io_error = 0;
x_io_error_quitter (dpyinfo->display);
}
while (XPending (dpyinfo->display) != 0)
{
#ifdef USE_X_TOOLKIT
XtAppNextEvent (Xt_app_con, &event);
#else
XNextEvent (dpyinfo->display, &event);
#endif
#ifdef HAVE_X_I18N
{
struct frame *f1 = x_any_window_to_frame (dpyinfo,
event.xclient.window);
if (f1 != 0 && FRAME_XIC (f1) && XFilterEvent (&event, None))
break;
}
#endif
event_found = 1;
switch (event.type)
{
case ClientMessage:
{
if (event.xclient.message_type
== dpyinfo->Xatom_wm_protocols
&& event.xclient.format == 32)
{
if (event.xclient.data.l[0]
== dpyinfo->Xatom_wm_take_focus)
{
f = x_any_window_to_frame (dpyinfo, event.xclient.window);
#ifdef HAVE_X_I18N
if (f && FRAME_XIC (f))
XSetICFocus (FRAME_XIC (f));
#endif
if (f)
{
Display *d = event.xclient.display;
int count = x_catch_errors (d);
XSetInputFocus (d, event.xclient.window,
RevertToPointerRoot,
event.xclient.data.l[1]);
XSync (d, False);
x_uncatch_errors (d, count);
}
}
else if (event.xclient.data.l[0]
== dpyinfo->Xatom_wm_save_yourself)
{
if (numchars > 0)
{
f = x_top_window_to_frame (dpyinfo,
event.xclient.window);
if (f == selected_frame)
XSetCommand (FRAME_X_DISPLAY (f),
event.xclient.window,
initial_argv, initial_argc);
else if (f)
XSetCommand (FRAME_X_DISPLAY (f),
event.xclient.window,
0, 0);
}
}
else if (event.xclient.data.l[0]
== dpyinfo->Xatom_wm_delete_window)
{
struct frame *f
= x_any_window_to_frame (dpyinfo,
event.xclient.window);
if (f)
{
if (numchars == 0)
abort ();
bufp->kind = delete_window_event;
XSETFRAME (bufp->frame_or_window, f);
bufp++;
count += 1;
numchars -= 1;
}
}
}
else if (event.xclient.message_type
== dpyinfo->Xatom_wm_configure_denied)
{
}
else if (event.xclient.message_type
== dpyinfo->Xatom_wm_window_moved)
{
int new_x, new_y;
struct frame *f
= x_window_to_frame (dpyinfo, event.xclient.window);
new_x = event.xclient.data.s[0];
new_y = event.xclient.data.s[1];
if (f)
{
f->output_data.x->left_pos = new_x;
f->output_data.x->top_pos = new_y;
}
}
#ifdef HACK_EDITRES
else if (event.xclient.message_type
== dpyinfo->Xatom_editres)
{
struct frame *f
= x_any_window_to_frame (dpyinfo, event.xclient.window);
_XEditResCheckMessages (f->output_data.x->widget, NULL,
&event, NULL);
}
#endif
}
break;
case SelectionNotify:
#ifdef USE_X_TOOLKIT
if (! x_window_to_frame (dpyinfo, event.xselection.requestor))
goto OTHER;
#endif
x_handle_selection_notify (&event.xselection);
break;
case SelectionClear:
#ifdef USE_X_TOOLKIT
if (! x_window_to_frame (dpyinfo, event.xselectionclear.window))
goto OTHER;
#endif
{
XSelectionClearEvent *eventp = (XSelectionClearEvent *) &event;
if (numchars == 0)
abort ();
bufp->kind = selection_clear_event;
SELECTION_EVENT_DISPLAY (bufp) = eventp->display;
SELECTION_EVENT_SELECTION (bufp) = eventp->selection;
SELECTION_EVENT_TIME (bufp) = eventp->time;
bufp->frame_or_window = Qnil;
bufp++;
count += 1;
numchars -= 1;
}
break;
case SelectionRequest:
#ifdef USE_X_TOOLKIT
if (!x_window_to_frame (dpyinfo, event.xselectionrequest.owner))
goto OTHER;
#endif
if (x_queue_selection_requests)
x_queue_event (x_window_to_frame (dpyinfo, event.xselectionrequest.owner),
&event);
else
{
XSelectionRequestEvent *eventp = (XSelectionRequestEvent *) &event;
if (numchars == 0)
abort ();
bufp->kind = selection_request_event;
SELECTION_EVENT_DISPLAY (bufp) = eventp->display;
SELECTION_EVENT_REQUESTOR (bufp) = eventp->requestor;
SELECTION_EVENT_SELECTION (bufp) = eventp->selection;
SELECTION_EVENT_TARGET (bufp) = eventp->target;
SELECTION_EVENT_PROPERTY (bufp) = eventp->property;
SELECTION_EVENT_TIME (bufp) = eventp->time;
bufp->frame_or_window = Qnil;
bufp++;
count += 1;
numchars -= 1;
}
break;
case PropertyNotify:
#ifdef USE_X_TOOLKIT
if (!x_any_window_to_frame (dpyinfo, event.xproperty.window))
goto OTHER;
#endif
x_handle_property_notify (&event.xproperty);
break;
case ReparentNotify:
f = x_top_window_to_frame (dpyinfo, event.xreparent.window);
if (f)
{
int x, y;
f->output_data.x->parent_desc = event.xreparent.parent;
x_real_positions (f, &x, &y);
f->output_data.x->left_pos = x;
f->output_data.x->top_pos = y;
}
break;
case Expose:
f = x_window_to_frame (dpyinfo, event.xexpose.window);
if (f)
{
if (f->async_visible == 0)
{
f->async_visible = 1;
f->async_iconified = 0;
f->output_data.x->has_been_visible = 1;
SET_FRAME_GARBAGED (f);
}
else
dumprectangle (x_window_to_frame (dpyinfo,
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);
#ifdef USE_X_TOOLKIT
else
goto OTHER;
#endif
}
break;
case GraphicsExpose:
f = x_window_to_frame (dpyinfo, event.xgraphicsexpose.drawable);
if (f)
{
dumprectangle (f,
event.xgraphicsexpose.x, event.xgraphicsexpose.y,
event.xgraphicsexpose.width,
event.xgraphicsexpose.height);
}
#ifdef USE_X_TOOLKIT
else
goto OTHER;
#endif
break;
case NoExpose:
break;
case UnmapNotify:
f = x_top_window_to_frame (dpyinfo, event.xunmap.window);
if (f)
{
f->async_visible = 0;
if (FRAME_VISIBLE_P (f) || FRAME_ICONIFIED_P (f))
{
f->async_iconified = 1;
bufp->kind = iconify_event;
XSETFRAME (bufp->frame_or_window, f);
bufp++;
count++;
numchars--;
}
}
goto OTHER;
case MapNotify:
f = x_top_window_to_frame (dpyinfo, event.xmap.window);
if (f)
{
f->async_visible = 1;
f->async_iconified = 0;
f->output_data.x->has_been_visible = 1;
SET_FRAME_GARBAGED (f);
if (f->iconified)
{
bufp->kind = deiconify_event;
XSETFRAME (bufp->frame_or_window, f);
bufp++;
count++;
numchars--;
}
else if (! NILP (Vframe_list)
&& ! NILP (XCONS (Vframe_list)->cdr))
record_asynch_buffer_change ();
}
goto OTHER;
case VisibilityNotify:
break;
case KeyPress:
f = x_any_window_to_frame (dpyinfo, event.xkey.window);
if (f != 0)
{
KeySym keysym, orig_keysym;
unsigned char copy_buffer[81];
int modifiers;
#if 0
#ifdef USE_MOTIF
if (lw_window_is_in_menubar (event.xkey.window,
f->output_data.x->menubar_widget
))
{
SET_SAVED_KEY_EVENT;
break;
}
#endif
#endif
event.xkey.state
|= x_emacs_to_x_modifiers (FRAME_X_DISPLAY_INFO (f),
extra_keyboard_modifiers);
modifiers = event.xkey.state;
event.xkey.state &= ~ControlMask;
event.xkey.state &= ~(dpyinfo->meta_mod_mask
| dpyinfo->super_mod_mask
| dpyinfo->hyper_mod_mask
| dpyinfo->alt_mod_mask);
if (modifiers & dpyinfo->meta_mod_mask)
bzero (&compose_status, sizeof (compose_status));
#ifdef HAVE_X_I18N
if (FRAME_XIC (f))
{
if (XFilterEvent (&event, None))
break;
nbytes = XmbLookupString (FRAME_XIC (f),
&event.xkey, copy_buffer,
80, &keysym,
&status_return);
if (status_return == XLookupNone)
break;
else if (status_return == XLookupChars)
keysym = NoSymbol;
else if (status_return != XLookupKeySym
&& status_return != XLookupBoth)
abort ();
}
else
nbytes = XLookupString (&event.xkey, copy_buffer,
80, &keysym, &compose_status);
#else
nbytes = XLookupString (&event.xkey, copy_buffer,
80, &keysym, &compose_status);
#endif
orig_keysym = keysym;
if (numchars > 1)
{
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
|| (keysym >= XK_Kanji && keysym <= XK_Eisu_toggle)
|| IsCursorKey (keysym)
|| IsMiscFunctionKey (keysym)
#ifdef HPUX
|| ((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)
|| IsFunctionKey (keysym)
|| (orig_keysym & (1 << 28)))
&& ! (IsModifierKey (orig_keysym)
#ifndef HAVE_X11R5
#ifdef XK_Mode_switch
|| ((unsigned)(orig_keysym) == XK_Mode_switch)
#endif
#ifdef XK_Num_Lock
|| ((unsigned)(orig_keysym) == XK_Num_Lock)
#endif
#endif
))
{
if (temp_index == sizeof temp_buffer / sizeof (short))
temp_index = 0;
temp_buffer[temp_index++] = keysym;
bufp->kind = non_ascii_keystroke;
bufp->code = keysym;
XSETFRAME (bufp->frame_or_window, f);
bufp->modifiers
= x_x_to_emacs_modifiers (FRAME_X_DISPLAY_INFO (f),
modifiers);
bufp->timestamp = event.xkey.time;
bufp++;
count++;
numchars--;
}
else if (numchars > nbytes)
{
register int i;
for (i = 0; i < nbytes; i++)
{
if (temp_index == sizeof temp_buffer / sizeof (short))
temp_index = 0;
temp_buffer[temp_index++] = copy_buffer[i];
bufp->kind = ascii_keystroke;
bufp->code = copy_buffer[i];
XSETFRAME (bufp->frame_or_window, f);
bufp->modifiers
= x_x_to_emacs_modifiers (FRAME_X_DISPLAY_INFO (f),
modifiers);
bufp->timestamp = event.xkey.time;
bufp++;
}
count += nbytes;
numchars -= nbytes;
if (keysym == NoSymbol)
break;
}
else
abort ();
}
else
abort ();
}
goto OTHER;
case EnterNotify:
f = x_any_window_to_frame (dpyinfo, event.xcrossing.window);
if (event.xcrossing.focus)
{
if (f && (!(f->auto_raise)
|| !(f->auto_lower)
|| (event.xcrossing.time - enter_timestamp) > 500))
{
x_new_focus_frame (dpyinfo, f);
enter_timestamp = event.xcrossing.time;
}
}
else if (f == dpyinfo->x_focus_frame)
x_new_focus_frame (dpyinfo, 0);
if (f)
note_mouse_movement (f, &event.xmotion);
goto OTHER;
case FocusIn:
f = x_any_window_to_frame (dpyinfo, event.xfocus.window);
if (event.xfocus.detail != NotifyPointer)
dpyinfo->x_focus_event_frame = f;
if (f)
x_new_focus_frame (dpyinfo, f);
#ifdef HAVE_X_I18N
if (f && FRAME_XIC (f))
XSetICFocus (FRAME_XIC (f));
#endif
goto OTHER;
case LeaveNotify:
f = x_top_window_to_frame (dpyinfo, event.xcrossing.window);
if (f)
{
if (f == dpyinfo->mouse_face_mouse_frame)
clear_mouse_face (dpyinfo);
if (event.xcrossing.focus)
x_mouse_leave (dpyinfo);
else
{
if (f == dpyinfo->x_focus_event_frame)
dpyinfo->x_focus_event_frame = 0;
if (f == dpyinfo->x_focus_frame)
x_new_focus_frame (dpyinfo, 0);
}
}
goto OTHER;
case FocusOut:
f = x_any_window_to_frame (dpyinfo, event.xfocus.window);
if (event.xfocus.detail != NotifyPointer
&& f == dpyinfo->x_focus_event_frame)
dpyinfo->x_focus_event_frame = 0;
if (f && f == dpyinfo->x_focus_frame)
x_new_focus_frame (dpyinfo, 0);
#ifdef HAVE_X_I18N
if (f && FRAME_XIC (f))
XUnsetICFocus (FRAME_XIC (f));
#endif
goto OTHER;
case MotionNotify:
{
if (dpyinfo->grabbed && last_mouse_frame
&& FRAME_LIVE_P (last_mouse_frame))
f = last_mouse_frame;
else
f = x_window_to_frame (dpyinfo, event.xmotion.window);
if (f)
note_mouse_movement (f, &event.xmotion);
else
{
struct scroll_bar *bar
= x_window_to_scroll_bar (event.xmotion.window);
if (bar)
x_scroll_bar_note_movement (bar, &event);
clear_mouse_face (dpyinfo);
}
}
goto OTHER;
case ConfigureNotify:
f = x_top_window_to_frame (dpyinfo, event.xconfigure.window);
if (f)
{
int rows = PIXEL_TO_CHAR_HEIGHT (f, event.xconfigure.height);
int columns = PIXEL_TO_CHAR_WIDTH (f, event.xconfigure.width);
#ifndef USE_X_TOOLKIT
if (columns != f->width
|| rows != f->height
|| event.xconfigure.width != f->output_data.x->pixel_width
|| event.xconfigure.height != f->output_data.x->pixel_height)
{
change_frame_size (f, rows, columns, 0, 1);
SET_FRAME_GARBAGED (f);
cancel_mouse_face (f);
}
#endif
f->output_data.x->pixel_width = event.xconfigure.width;
f->output_data.x->pixel_height = event.xconfigure.height;
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)
{
f->output_data.x->win_gravity = NorthWestGravity;
x_wm_set_size_hint (f, (long) 0, 0);
}
#ifdef USE_MOTIF
if (event.xconfigure.x == 0 && event.xconfigure.y == 0)
{
event.xconfigure.x = f->output_data.x->widget->core.x;
event.xconfigure.y = f->output_data.x->widget->core.y;
}
#endif
if (f->phys_cursor_y >= rows
|| f->phys_cursor_x >= columns)
{
f->phys_cursor_x = 0;
f->phys_cursor_y = 0;
f->phys_cursor_on = 0;
}
}
goto OTHER;
case ButtonPress:
case ButtonRelease:
{
struct input_event emacs_event;
emacs_event.kind = no_event;
bzero (&compose_status, sizeof (compose_status));
if (dpyinfo->grabbed && last_mouse_frame
&& FRAME_LIVE_P (last_mouse_frame))
f = last_mouse_frame;
else
f = x_window_to_frame (dpyinfo, event.xbutton.window);
if (f)
{
if (!dpyinfo->x_focus_frame || f == dpyinfo->x_focus_frame)
construct_mouse_click (&emacs_event, &event, f);
}
else
{
struct scroll_bar *bar
= x_window_to_scroll_bar (event.xbutton.window);
if (bar)
x_scroll_bar_handle_click (bar, &event, &emacs_event);
}
if (event.type == ButtonPress)
{
dpyinfo->grabbed |= (1 << event.xbutton.button);
last_mouse_frame = f;
if (f != 0)
f->mouse_moved = 0;
}
else
{
dpyinfo->grabbed &= ~(1 << event.xbutton.button);
}
if (numchars >= 1 && emacs_event.kind != no_event)
{
bcopy (&emacs_event, bufp, sizeof (struct input_event));
bufp++;
count++;
numchars--;
}
#ifdef USE_X_TOOLKIT
f = x_menubar_window_to_frame (dpyinfo, event.xbutton.window);
if (f && event.type == ButtonPress
&& event.xbutton.x >= 0
&& event.xbutton.x < f->output_data.x->pixel_width
&& event.xbutton.y >= 0
&& event.xbutton.y < f->output_data.x->menubar_height
&& event.xbutton.same_screen)
{
SET_SAVED_BUTTON_EVENT;
XSETFRAME (last_mouse_press_frame, f);
}
else if (event.type == ButtonPress)
{
last_mouse_press_frame = Qnil;
goto OTHER;
}
#ifdef USE_MOTIF
else if (event.type == ButtonRelease)
{
if (!NILP (last_mouse_press_frame))
{
f = XFRAME (last_mouse_press_frame);
if (f->output_data.x)
{
SET_SAVED_BUTTON_EVENT;
}
}
else
goto OTHER;
}
#endif
else
goto OTHER;
#endif
}
break;
case CirculateNotify:
break;
case CirculateRequest:
break;
case MappingNotify:
switch (event.xmapping.request)
{
case MappingModifier:
x_find_modifier_meanings (dpyinfo);
case MappingKeyboard:
XRefreshKeyboardMapping (&event.xmapping);
}
goto OTHER;
default:
OTHER:
#ifdef USE_X_TOOLKIT
BLOCK_INPUT;
XtDispatchEvent (&event);
UNBLOCK_INPUT;
#endif
break;
}
}
}
if (! event_found)
{
x_noop_count++;
if (x_noop_count >= 100)
{
x_noop_count=0;
if (next_noop_dpyinfo == 0)
next_noop_dpyinfo = x_display_list;
XNoOp (next_noop_dpyinfo->display);
next_noop_dpyinfo = next_noop_dpyinfo->next;
}
}
if (pending_autoraise_frame)
{
x_raise_frame (pending_autoraise_frame);
pending_autoraise_frame = 0;
}
UNBLOCK_INPUT;
return count;
}
static void
x_draw_box (f, x, y)
struct frame *f;
int x, y;
{
int left = CHAR_TO_PIXEL_COL (f, x);
int top = CHAR_TO_PIXEL_ROW (f, y);
int width = FONT_WIDTH (f->output_data.x->font);
int height = f->output_data.x->line_height;
int c = FAST_GLYPH_CHAR (f->phys_cursor_glyph);
int charset = CHAR_CHARSET (c);
XGCValues xgcv;
unsigned long mask = GCForeground;
xgcv.foreground = f->output_data.x->cursor_pixel;
if (FRAME_X_DISPLAY_INFO (f)->scratch_cursor_gc)
XChangeGC (FRAME_X_DISPLAY (f),
FRAME_X_DISPLAY_INFO (f)->scratch_cursor_gc,
mask, &xgcv);
else
FRAME_X_DISPLAY_INFO (f)->scratch_cursor_gc
= XCreateGC (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), mask, &xgcv);
width *= (charset == CHARSET_COMPOSITION
? cmpchar_table[COMPOSITE_CHAR_ID (c)]->width
: CHARSET_WIDTH (charset));
XDrawRectangle (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
FRAME_X_DISPLAY_INFO (f)->scratch_cursor_gc,
left, top, width - 1, height - 1);
}
static void
clear_cursor (f)
struct frame *f;
{
int mask;
if (! FRAME_VISIBLE_P (f)
|| ! f->phys_cursor_on)
return;
x_update_cursor (f, 0);
f->phys_cursor_on = 0;
}
static void
x_draw_single_glyph (f, row, column, glyph, highlight)
struct frame *f;
int row, column;
GLYPH glyph;
int highlight;
{
dumpglyphs (f,
CHAR_TO_PIXEL_COL (f, column),
CHAR_TO_PIXEL_ROW (f, row),
&glyph, 1, highlight, 0, NULL);
}
static void
x_display_bar_cursor (f, on, x, y)
struct frame *f;
int on;
int x, y;
{
struct frame_glyphs *current_glyphs = FRAME_CURRENT_GLYPHS (f);
if (! FRAME_VISIBLE_P (f) || FRAME_GARBAGED_P (f))
return;
if (! on && ! f->phys_cursor_on)
return;
if (f->phys_cursor_on
&& (!on
|| f->phys_cursor_x != x
|| f->phys_cursor_y != y
|| f->output_data.x->current_cursor != bar_cursor))
{
x_draw_single_glyph (f, f->phys_cursor_y, f->phys_cursor_x,
f->phys_cursor_glyph,
current_glyphs->highlight[f->phys_cursor_y]);
f->phys_cursor_on = 0;
}
if (on
&& (! f->phys_cursor_on
|| (f->output_data.x->current_cursor != bar_cursor)))
{
f->phys_cursor_glyph
= ((current_glyphs->enable[y]
&& x < current_glyphs->used[y])
? current_glyphs->glyphs[y][x]
: SPACEGLYPH);
{
XGCValues xgcv;
unsigned long mask;
xgcv.background = f->output_data.x->cursor_pixel;
xgcv.foreground = f->output_data.x->cursor_pixel;
xgcv.graphics_exposures = 0;
mask = GCForeground | GCBackground | GCGraphicsExposures;
if (FRAME_X_DISPLAY_INFO (f)->scratch_cursor_gc)
XChangeGC (FRAME_X_DISPLAY (f),
FRAME_X_DISPLAY_INFO (f)->scratch_cursor_gc,
mask, &xgcv);
else
FRAME_X_DISPLAY_INFO (f)->scratch_cursor_gc
= XCreateGC (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), mask, &xgcv);
}
XFillRectangle (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
FRAME_X_DISPLAY_INFO (f)->scratch_cursor_gc,
CHAR_TO_PIXEL_COL (f, x),
CHAR_TO_PIXEL_ROW (f, y),
max (f->output_data.x->cursor_width, 1),
f->output_data.x->line_height);
f->phys_cursor_x = x;
f->phys_cursor_y = y;
f->phys_cursor_on = 1;
f->output_data.x->current_cursor = bar_cursor;
}
if (updating_frame != f)
XFlush (FRAME_X_DISPLAY (f));
}
static void
x_display_box_cursor (f, on, x, y)
struct frame *f;
int on;
int x, y;
{
struct frame_glyphs *current_glyphs = FRAME_CURRENT_GLYPHS (f);
if (! FRAME_VISIBLE_P (f) || FRAME_GARBAGED_P (f))
return;
if (!on && ! f->phys_cursor_on)
return;
if (f->phys_cursor_on
&& (!on
|| f->phys_cursor_x != x
|| f->phys_cursor_y != y
|| (f->output_data.x->current_cursor != hollow_box_cursor
&& (f != FRAME_X_DISPLAY_INFO (f)->x_highlight_frame))))
{
int mouse_face_here = 0;
struct frame_glyphs *active_glyphs = FRAME_CURRENT_GLYPHS (f);
if (f == FRAME_X_DISPLAY_INFO (f)->mouse_face_mouse_frame
&&
(f->phys_cursor_y > FRAME_X_DISPLAY_INFO (f)->mouse_face_beg_row
|| (f->phys_cursor_y == FRAME_X_DISPLAY_INFO (f)->mouse_face_beg_row
&& f->phys_cursor_x >= FRAME_X_DISPLAY_INFO (f)->mouse_face_beg_col))
&&
(f->phys_cursor_y < FRAME_X_DISPLAY_INFO (f)->mouse_face_end_row
|| (f->phys_cursor_y == FRAME_X_DISPLAY_INFO (f)->mouse_face_end_row
&& f->phys_cursor_x < FRAME_X_DISPLAY_INFO (f)->mouse_face_end_col))
&& active_glyphs->used[f->phys_cursor_y] > f->phys_cursor_x)
mouse_face_here = 1;
if (FONT_HEIGHT (f->output_data.x->font) != f->output_data.x->line_height)
XClearArea (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
CHAR_TO_PIXEL_COL (f, f->phys_cursor_x),
CHAR_TO_PIXEL_ROW (f, f->phys_cursor_y),
FONT_WIDTH (f->output_data.x->font),
f->output_data.x->line_height, False);
x_draw_single_glyph (f, f->phys_cursor_y, f->phys_cursor_x,
f->phys_cursor_glyph,
(mouse_face_here
? 3
: current_glyphs->highlight[f->phys_cursor_y]));
f->phys_cursor_on = 0;
}
if (on
&& (! f->phys_cursor_on
|| (f->output_data.x->current_cursor != filled_box_cursor
&& f == FRAME_X_DISPLAY_INFO (f)->x_highlight_frame)))
{
f->phys_cursor_glyph
= ((current_glyphs->enable[y]
&& x < current_glyphs->used[y])
? current_glyphs->glyphs[y][x]
: SPACEGLYPH);
if (f != FRAME_X_DISPLAY_INFO (f)->x_highlight_frame)
{
x_draw_box (f, x, y);
f->output_data.x->current_cursor = hollow_box_cursor;
}
else
{
x_draw_single_glyph (f, y, x,
f->phys_cursor_glyph, 2);
f->output_data.x->current_cursor = filled_box_cursor;
}
f->phys_cursor_x = x;
f->phys_cursor_y = y;
f->phys_cursor_on = 1;
}
if (updating_frame != f)
XFlush (FRAME_X_DISPLAY (f));
}
void
x_display_cursor (f, on, x, y)
struct frame *f;
int on;
int x, y;
{
BLOCK_INPUT;
if ((unsigned) x >= FRAME_CURSOR_X_LIMIT (f)
|| (unsigned) y >= FRAME_HEIGHT (f))
abort ();
if (FRAME_DESIRED_CURSOR (f) == filled_box_cursor)
x_display_box_cursor (f, on, x, y);
else if (FRAME_DESIRED_CURSOR (f) == bar_cursor)
x_display_bar_cursor (f, on, x, y);
else
abort ();
UNBLOCK_INPUT;
}
void
x_update_cursor (f, on)
struct frame *f;
int on;
{
BLOCK_INPUT;
if (FRAME_DESIRED_CURSOR (f) == filled_box_cursor)
x_display_box_cursor (f, on, f->phys_cursor_x, f->phys_cursor_y);
else if (FRAME_DESIRED_CURSOR (f) == bar_cursor)
x_display_bar_cursor (f, on, f->phys_cursor_x, f->phys_cursor_y);
else
abort ();
UNBLOCK_INPUT;
}
void
refreshicon (f)
struct frame *f;
{
}
int
x_bitmap_icon (f, file)
struct frame *f;
Lisp_Object file;
{
int mask, bitmap_id;
Window icon_window;
if (FRAME_X_WINDOW (f) == 0)
return 1;
if (f->output_data.x->icon_bitmap > 0)
x_destroy_bitmap (f, f->output_data.x->icon_bitmap);
f->output_data.x->icon_bitmap = 0;
if (STRINGP (file))
bitmap_id = x_create_bitmap_from_file (f, file);
else
{
if (FRAME_X_DISPLAY_INFO (f)->icon_bitmap_id < 0)
FRAME_X_DISPLAY_INFO (f)->icon_bitmap_id
= x_create_bitmap_from_data (f, gnu_bits,
gnu_width, gnu_height);
x_reference_bitmap (f, FRAME_X_DISPLAY_INFO (f)->icon_bitmap_id);
bitmap_id = FRAME_X_DISPLAY_INFO (f)->icon_bitmap_id;
}
x_wm_set_icon_pixmap (f, bitmap_id);
f->output_data.x->icon_bitmap = bitmap_id;
return 0;
}
int
x_text_icon (f, icon_name)
struct frame *f;
char *icon_name;
{
if (FRAME_X_WINDOW (f) == 0)
return 1;
#ifdef HAVE_X11R4
{
XTextProperty text;
text.value = (unsigned char *) icon_name;
text.encoding = XA_STRING;
text.format = 8;
text.nitems = strlen (icon_name);
#ifdef USE_X_TOOLKIT
XSetWMIconName (FRAME_X_DISPLAY (f), XtWindow (f->output_data.x->widget),
&text);
#else
XSetWMIconName (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), &text);
#endif
}
#else
XSetIconName (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), icon_name);
#endif
if (f->output_data.x->icon_bitmap > 0)
x_destroy_bitmap (f, f->output_data.x->icon_bitmap);
f->output_data.x->icon_bitmap = 0;
x_wm_set_icon_pixmap (f, 0);
return 0;
}
#define X_ERROR_MESSAGE_SIZE 200
static Lisp_Object x_error_message_string;
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);
}
void x_check_errors ();
static Lisp_Object x_catch_errors_unwind ();
int
x_catch_errors (dpy)
Display *dpy;
{
int count = specpdl_ptr - specpdl;
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;
}
static Lisp_Object
x_catch_errors_unwind (old_val)
Lisp_Object old_val;
{
x_error_message_string = old_val;
return Qnil;
}
void
x_check_errors (dpy, format)
Display *dpy;
char *format;
{
XSync (dpy, False);
if (XSTRING (x_error_message_string)->data[0])
error (format, XSTRING (x_error_message_string)->data);
}
int
x_had_errors_p (dpy)
Display *dpy;
{
XSync (dpy, False);
return XSTRING (x_error_message_string)->data[0] != 0;
}
int
x_clear_errors (dpy)
Display *dpy;
{
XSTRING (x_error_message_string)->data[0] = 0;
}
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
static SIGTYPE
x_connection_signal (signalnum)
int signalnum;
{
#ifdef USG
signal (signalnum, x_connection_signal);
#endif
}
static SIGTYPE
x_connection_closed (display, error_message)
Display *display;
char *error_message;
{
struct x_display_info *dpyinfo = x_display_info_for_display (display);
Lisp_Object frame, tail;
#ifdef USE_X_TOOLKIT
XtCloseDisplay (display);
#endif
dpyinfo->display = 0;
FOR_EACH_FRAME (tail, frame)
{
Lisp_Object minibuf_frame;
minibuf_frame
= WINDOW_FRAME (XWINDOW (FRAME_MINIBUF_WINDOW (XFRAME (frame))));
if (FRAME_X_P (XFRAME (frame))
&& FRAME_X_P (XFRAME (minibuf_frame))
&& ! EQ (frame, minibuf_frame)
&& FRAME_X_DISPLAY_INFO (XFRAME (minibuf_frame)) == dpyinfo)
Fdelete_frame (frame, Qt);
}
FOR_EACH_FRAME (tail, frame)
if (FRAME_X_P (XFRAME (frame))
&& FRAME_X_DISPLAY_INFO (XFRAME (frame)) == dpyinfo)
{
FRAME_KBOARD (XFRAME (frame))->Vdefault_minibuffer_frame = Qt;
Fdelete_frame (frame, Qt);
}
if (dpyinfo)
x_delete_display (dpyinfo);
if (x_display_list == 0)
{
fprintf (stderr, "%s\n", error_message);
shut_down_emacs (0, 0, Qnil);
exit (70);
}
#ifdef SIGIO
sigunblock (sigmask (SIGIO));
#endif
sigunblock (sigmask (SIGALRM));
TOTALLY_UNBLOCK_INPUT;
clear_waiting_for_input ();
error ("%s", error_message);
}
static int
x_error_quitter (display, error)
Display *display;
XErrorEvent *error;
{
char buf[256], buf1[356];
XGetErrorText (display, error->error_code, buf, sizeof (buf));
sprintf (buf1, "X protocol error: %s on protocol request %d",
buf, error->request_code);
x_connection_closed (display, buf1);
}
static int
x_error_handler (display, error)
Display *display;
XErrorEvent *error;
{
char buf[256], buf1[356];
if (! NILP (x_error_message_string))
x_error_catcher (display, error);
else
x_error_quitter (display, error);
}
static int
x_io_error_quitter (display)
Display *display;
{
char buf[256];
sprintf (buf, "Connection lost to X server `%s'", DisplayString (display));
x_connection_closed (display, buf);
}
Lisp_Object
x_new_font (f, fontname)
struct frame *f;
register char *fontname;
{
struct font_info *fontp
= fs_load_font (f, FRAME_X_FONT_TABLE (f), CHARSET_ASCII, fontname, -1);
if (!fontp)
return Qnil;
f->output_data.x->font = (XFontStruct *) (fontp->font);
f->output_data.x->font_baseline
= (f->output_data.x->font->ascent + fontp->baseline_offset);
f->output_data.x->fontset = -1;
if (f->scroll_bar_pixel_width > 0)
{
int wid = FONT_WIDTH (f->output_data.x->font);
f->scroll_bar_cols = (f->scroll_bar_pixel_width + wid-1) / wid;
}
else
{
int wid = FONT_WIDTH (f->output_data.x->font);
f->scroll_bar_cols = (14 + wid - 1) / wid;
}
if (FRAME_X_WINDOW (f) != 0)
{
XSetFont (FRAME_X_DISPLAY (f), f->output_data.x->normal_gc,
f->output_data.x->font->fid);
XSetFont (FRAME_X_DISPLAY (f), f->output_data.x->reverse_gc,
f->output_data.x->font->fid);
XSetFont (FRAME_X_DISPLAY (f), f->output_data.x->cursor_gc,
f->output_data.x->font->fid);
frame_update_line_height (f);
x_set_window_size (f, 0, f->width, f->height);
}
else
f->output_data.x->line_height = FONT_HEIGHT (f->output_data.x->font);
return build_string (fontp->full_name);
}
Lisp_Object
x_new_fontset (f, fontsetname)
struct frame *f;
char *fontsetname;
{
int fontset = fs_query_fontset (f, fontsetname);
struct fontset_info *fontsetp;
Lisp_Object result;
if (fontset < 0)
return Qnil;
if (f->output_data.x->fontset == fontset)
return build_string (fontsetname);
fontsetp = FRAME_FONTSET_DATA (f)->fontset_table[fontset];
if (!fontsetp->fontname[CHARSET_ASCII])
return Qnil;
result = x_new_font (f, fontsetp->fontname[CHARSET_ASCII]);
if (!STRINGP (result))
return Qnil;
f->output_data.x->fontset = fontset;
FS_LOAD_FONT (f, FRAME_X_FONT_TABLE (f),
CHARSET_ASCII, fontsetp->fontname[CHARSET_ASCII], fontset);
return build_string (fontsetname);
}
void
x_calc_absolute_position (f)
struct frame *f;
{
Window win, child;
int win_x = 0, win_y = 0;
int flags = f->output_data.x->size_hint_flags;
int this_window;
if (! ((flags & XNegative) || (flags & YNegative)))
return;
#ifdef USE_X_TOOLKIT
this_window = XtWindow (f->output_data.x->widget);
#else
this_window = FRAME_X_WINDOW (f);
#endif
if (f->output_data.x->parent_desc != FRAME_X_DISPLAY_INFO (f)->root_window)
{
int count;
BLOCK_INPUT;
count = x_catch_errors (FRAME_X_DISPLAY (f));
while (1)
{
x_clear_errors (FRAME_X_DISPLAY (f));
XTranslateCoordinates (FRAME_X_DISPLAY (f),
this_window,
f->output_data.x->parent_desc,
0, 0, &win_x, &win_y,
&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;
XFree ((char *) newchildren);
f->output_data.x->parent_desc = newparent;
}
else
break;
}
x_uncatch_errors (FRAME_X_DISPLAY (f), count);
UNBLOCK_INPUT;
}
if (flags & XNegative)
f->output_data.x->left_pos = (FRAME_X_DISPLAY_INFO (f)->width
- 2 * f->output_data.x->border_width - win_x
- PIXEL_WIDTH (f)
+ f->output_data.x->left_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
- PIXEL_HEIGHT (f)
+ f->output_data.x->top_pos);
f->output_data.x->size_hint_flags &= ~ (XNegative | YNegative);
}
void
x_set_offset (f, xoff, yoff, change_gravity)
struct frame *f;
register int xoff, yoff;
int change_gravity;
{
int modified_top, modified_left;
if (change_gravity > 0)
{
f->output_data.x->top_pos = yoff;
f->output_data.x->left_pos = xoff;
f->output_data.x->size_hint_flags &= ~ (XNegative | YNegative);
if (xoff < 0)
f->output_data.x->size_hint_flags |= XNegative;
if (yoff < 0)
f->output_data.x->size_hint_flags |= YNegative;
f->output_data.x->win_gravity = NorthWestGravity;
}
x_calc_absolute_position (f);
BLOCK_INPUT;
x_wm_set_size_hint (f, (long) 0, 0);
modified_left = f->output_data.x->left_pos;
modified_top = f->output_data.x->top_pos;
#if 0
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),
modified_left, modified_top);
#else
XMoveWindow (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
modified_left, modified_top);
#endif
UNBLOCK_INPUT;
}
void
x_set_window_size (f, change_gravity, cols, rows)
struct frame *f;
int change_gravity;
int cols, rows;
{
int pixelwidth, pixelheight;
int mask;
struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
BLOCK_INPUT;
#ifdef USE_X_TOOLKIT
{
int xpos = f->output_data.x->widget->core.x;
int ypos = f->output_data.x->widget->core.y;
EmacsFrameSetCharSize (f->output_data.x->edit_widget, cols, rows);
f->output_data.x->widget->core.x = xpos;
f->output_data.x->widget->core.y = ypos;
}
#else
check_frame_size (f, &rows, &cols);
f->output_data.x->vertical_scroll_bar_extra
= (!FRAME_HAS_VERTICAL_SCROLL_BARS (f)
? 0
: FRAME_SCROLL_BAR_PIXEL_WIDTH (f) > 0
? FRAME_SCROLL_BAR_PIXEL_WIDTH (f)
: (FRAME_SCROLL_BAR_COLS (f) * FONT_WIDTH (f->output_data.x->font)));
pixelwidth = CHAR_TO_PIXEL_WIDTH (f, cols);
pixelheight = CHAR_TO_PIXEL_HEIGHT (f, rows);
f->output_data.x->win_gravity = NorthWestGravity;
x_wm_set_size_hint (f, (long) 0, 0);
XSync (FRAME_X_DISPLAY (f), False);
XResizeWindow (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
pixelwidth, pixelheight);
change_frame_size (f, rows, cols, 0, 0);
PIXEL_WIDTH (f) = pixelwidth;
PIXEL_HEIGHT (f) = pixelheight;
SET_FRAME_GARBAGED (f);
XFlush (FRAME_X_DISPLAY (f));
#endif
if (f->phys_cursor_y >= rows
|| f->phys_cursor_x >= cols)
{
f->phys_cursor_x = 0;
f->phys_cursor_y = 0;
f->phys_cursor_on = 0;
}
cancel_mouse_face (f);
UNBLOCK_INPUT;
}
void
x_set_mouse_position (f, x, y)
struct frame *f;
int x, y;
{
int pix_x, pix_y;
pix_x = CHAR_TO_PIXEL_COL (f, x) + FONT_WIDTH (f->output_data.x->font) / 2;
pix_y = CHAR_TO_PIXEL_ROW (f, y) + f->output_data.x->line_height / 2;
if (pix_x < 0) pix_x = 0;
if (pix_x > PIXEL_WIDTH (f)) pix_x = PIXEL_WIDTH (f);
if (pix_y < 0) pix_y = 0;
if (pix_y > PIXEL_HEIGHT (f)) pix_y = PIXEL_HEIGHT (f);
BLOCK_INPUT;
XWarpPointer (FRAME_X_DISPLAY (f), None, FRAME_X_WINDOW (f),
0, 0, 0, 0, pix_x, pix_y);
UNBLOCK_INPUT;
}
void
x_set_mouse_pixel_position (f, pix_x, pix_y)
struct frame *f;
int pix_x, pix_y;
{
BLOCK_INPUT;
XWarpPointer (FRAME_X_DISPLAY (f), None, FRAME_X_WINDOW (f),
0, 0, 0, 0, pix_x, pix_y);
UNBLOCK_INPUT;
}
void
x_focus_on_frame (f)
struct frame *f;
{
#if 0
x_raise_frame (f);
#endif
#if 0
XSetInputFocus (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
RevertToPointerRoot, CurrentTime);
#endif
}
void
x_unfocus_frame (f)
struct frame *f;
{
#if 0
if (FRAME_X_DISPLAY_INFO (f)->x_focus_frame == f)
XSetInputFocus (FRAME_X_DISPLAY (f), PointerRoot,
RevertToPointerRoot, CurrentTime);
#endif
}
void
x_raise_frame (f)
struct frame *f;
{
if (f->async_visible)
{
BLOCK_INPUT;
#ifdef USE_X_TOOLKIT
XRaiseWindow (FRAME_X_DISPLAY (f), XtWindow (f->output_data.x->widget));
#else
XRaiseWindow (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f));
#endif
XFlush (FRAME_X_DISPLAY (f));
UNBLOCK_INPUT;
}
}
void
x_lower_frame (f)
struct frame *f;
{
if (f->async_visible)
{
BLOCK_INPUT;
#ifdef USE_X_TOOLKIT
XLowerWindow (FRAME_X_DISPLAY (f), XtWindow (f->output_data.x->widget));
#else
XLowerWindow (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f));
#endif
XFlush (FRAME_X_DISPLAY (f));
UNBLOCK_INPUT;
}
}
static void
XTframe_raise_lower (f, raise_flag)
FRAME_PTR f;
int raise_flag;
{
if (raise_flag)
x_raise_frame (f);
else
x_lower_frame (f);
}
void
x_make_frame_visible (f)
struct frame *f;
{
int mask;
Lisp_Object type;
int starting_flags = f->output_data.x->size_hint_flags;
int original_top, original_left;
BLOCK_INPUT;
type = x_icon_type (f);
if (!NILP (type))
x_bitmap_icon (f, type);
if (! FRAME_VISIBLE_P (f))
{
if (! FRAME_ICONIFIED_P (f)
&& ! f->output_data.x->asked_for_visible)
x_set_offset (f, f->output_data.x->left_pos, f->output_data.x->top_pos, 0);
f->output_data.x->asked_for_visible = 1;
if (! EQ (Vx_no_window_manager, Qt))
x_wm_set_window_state (f, NormalState);
#ifdef USE_X_TOOLKIT
XtMapWidget (f->output_data.x->widget);
#else
XMapRaised (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f));
#endif
#if 0
if (FRAME_HAS_VERTICAL_SCROLL_BARS (f))
XMapSubwindows (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f));
#endif
}
XFlush (FRAME_X_DISPLAY (f));
{
Lisp_Object frame;
int count = input_signal_count;
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;
UNBLOCK_INPUT;
if (! FRAME_VISIBLE_P (f) && ! FRAME_ICONIFIED_P (f)
&& f->output_data.x->win_gravity == NorthWestGravity
&& previously_visible)
{
Drawable rootw;
int x, y;
unsigned int width, height, border, depth;
BLOCK_INPUT;
XGetGeometry (FRAME_X_DISPLAY (f), FRAME_OUTER_WINDOW (f),
&rootw, &x, &y, &width, &height, &border, &depth);
if (original_left != x || original_top != y)
XMoveWindow (FRAME_X_DISPLAY (f), FRAME_OUTER_WINDOW (f),
original_left, original_top);
UNBLOCK_INPUT;
}
XSETFRAME (frame, f);
while (1)
{
x_sync (f);
if (input_signal_count != count)
break;
if (input_polling_used ())
{
alarm (0);
input_poll_signal (0);
}
if (input_signal_count != count)
break;
}
FRAME_SAMPLE_VISIBILITY (f);
}
}
void
x_make_frame_invisible (f)
struct frame *f;
{
int mask;
Window window;
#ifdef USE_X_TOOLKIT
window = XtWindow (f->output_data.x->widget);
#else
window = FRAME_X_WINDOW (f);
#endif
if (FRAME_X_DISPLAY_INFO (f)->x_highlight_frame == f)
FRAME_X_DISPLAY_INFO (f)->x_highlight_frame = 0;
#if 0
if (! f->async_visible && ! f->async_iconified)
return;
#endif
BLOCK_INPUT;
x_wm_set_size_hint (f, (long) 0, 1);
#ifdef HAVE_X11R4
if (! XWithdrawWindow (FRAME_X_DISPLAY (f), window,
DefaultScreen (FRAME_X_DISPLAY (f))))
{
UNBLOCK_INPUT_RESIGNAL;
error ("Can't notify window manager of window withdrawal");
}
#else
if (! EQ (Vx_no_window_manager, Qt))
{
XEvent unmap;
unmap.xunmap.type = UnmapNotify;
unmap.xunmap.window = window;
unmap.xunmap.event = DefaultRootWindow (FRAME_X_DISPLAY (f));
unmap.xunmap.from_configure = False;
if (! XSendEvent (FRAME_X_DISPLAY (f),
DefaultRootWindow (FRAME_X_DISPLAY (f)),
False,
SubstructureRedirectMask|SubstructureNotifyMask,
&unmap))
{
UNBLOCK_INPUT_RESIGNAL;
error ("Can't notify window manager of withdrawal");
}
}
XUnmapWindow (FRAME_X_DISPLAY (f), window);
#endif
f->visible = 0;
FRAME_ICONIFIED_P (f) = 0;
f->async_visible = 0;
f->async_iconified = 0;
x_sync (f);
UNBLOCK_INPUT;
}
void
x_iconify_frame (f)
struct frame *f;
{
int mask;
int result;
Lisp_Object type;
if (FRAME_X_DISPLAY_INFO (f)->x_highlight_frame == f)
FRAME_X_DISPLAY_INFO (f)->x_highlight_frame = 0;
if (f->async_iconified)
return;
BLOCK_INPUT;
FRAME_SAMPLE_VISIBILITY (f);
type = x_icon_type (f);
if (!NILP (type))
x_bitmap_icon (f, type);
#ifdef USE_X_TOOLKIT
if (! FRAME_VISIBLE_P (f))
{
if (! EQ (Vx_no_window_manager, Qt))
x_wm_set_window_state (f, IconicState);
XtMapWidget (f->output_data.x->widget);
f->iconified = 1;
f->visible = 1;
f->async_iconified = 1;
f->async_visible = 0;
UNBLOCK_INPUT;
return;
}
result = XIconifyWindow (FRAME_X_DISPLAY (f),
XtWindow (f->output_data.x->widget),
DefaultScreen (FRAME_X_DISPLAY (f)));
UNBLOCK_INPUT;
if (!result)
error ("Can't notify window manager of iconification");
f->async_iconified = 1;
f->async_visible = 0;
BLOCK_INPUT;
XFlush (FRAME_X_DISPLAY (f));
UNBLOCK_INPUT;
#else
if (! FRAME_VISIBLE_P (f) && !FRAME_ICONIFIED_P (f))
x_set_offset (f, f->output_data.x->left_pos, f->output_data.x->top_pos, 0);
{
XEvent message;
message.xclient.window = FRAME_X_WINDOW (f);
message.xclient.type = ClientMessage;
message.xclient.message_type = FRAME_X_DISPLAY_INFO (f)->Xatom_wm_change_state;
message.xclient.format = 32;
message.xclient.data.l[0] = IconicState;
if (! XSendEvent (FRAME_X_DISPLAY (f),
DefaultRootWindow (FRAME_X_DISPLAY (f)),
False,
SubstructureRedirectMask | SubstructureNotifyMask,
&message))
{
UNBLOCK_INPUT_RESIGNAL;
error ("Can't notify window manager of iconification");
}
}
x_wm_set_window_state (f, IconicState);
if (!FRAME_VISIBLE_P (f))
{
XMapRaised (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f));
}
f->async_iconified = 1;
f->async_visible = 0;
XFlush (FRAME_X_DISPLAY (f));
UNBLOCK_INPUT;
#endif
}
void
x_destroy_window (f)
struct frame *f;
{
struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
BLOCK_INPUT;
if (dpyinfo->display != 0)
{
if (f->output_data.x->icon_desc != 0)
XDestroyWindow (FRAME_X_DISPLAY (f), f->output_data.x->icon_desc);
#ifdef HAVE_X_I18N
if (FRAME_XIM (f))
{
XDestroyIC (FRAME_XIC (f));
#if ! defined (SOLARIS2) || defined (HAVE_X11R6)
XCloseIM (FRAME_XIM (f));
#endif
}
#endif
XDestroyWindow (FRAME_X_DISPLAY (f), f->output_data.x->window_desc);
#ifdef USE_X_TOOLKIT
XtDestroyWidget (f->output_data.x->widget);
free_frame_menubar (f);
#endif
free_frame_faces (f);
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)
dpyinfo->x_focus_frame = 0;
if (f == dpyinfo->x_focus_event_frame)
dpyinfo->x_focus_event_frame = 0;
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
= dpyinfo->mouse_face_beg_col = -1;
dpyinfo->mouse_face_end_row
= dpyinfo->mouse_face_end_col = -1;
dpyinfo->mouse_face_window = Qnil;
dpyinfo->mouse_face_deferred_gc = 0;
dpyinfo->mouse_face_mouse_frame = 0;
}
UNBLOCK_INPUT;
}
void
x_wm_set_size_hint (f, flags, user_position)
struct frame *f;
long flags;
int user_position;
{
XSizeHints size_hints;
#ifdef USE_X_TOOLKIT
Arg al[2];
int ac = 0;
Dimension widget_width, widget_height;
Window window = XtWindow (f->output_data.x->widget);
#else
Window window = FRAME_X_WINDOW (f);
#endif
size_hints.flags = PResizeInc | PMinSize ;
flexlines = f->height;
size_hints.x = f->output_data.x->left_pos;
size_hints.y = f->output_data.x->top_pos;
#ifdef USE_X_TOOLKIT
XtSetArg (al[ac], XtNwidth, &widget_width); ac++;
XtSetArg (al[ac], XtNheight, &widget_height); ac++;
XtGetValues (f->output_data.x->widget, al, ac);
size_hints.height = widget_height;
size_hints.width = widget_width;
#else
size_hints.height = PIXEL_HEIGHT (f);
size_hints.width = PIXEL_WIDTH (f);
#endif
size_hints.width_inc = FONT_WIDTH (f->output_data.x->font);
size_hints.height_inc = f->output_data.x->line_height;
size_hints.max_width
= FRAME_X_DISPLAY_INFO (f)->width - CHAR_TO_PIXEL_WIDTH (f, 0);
size_hints.max_height
= FRAME_X_DISPLAY_INFO (f)->height - CHAR_TO_PIXEL_HEIGHT (f, 0);
#ifndef USE_X_TOOLKIT
{
int base_width, base_height;
int min_rows = 0, min_cols = 0;
base_width = CHAR_TO_PIXEL_WIDTH (f, 0);
base_height = CHAR_TO_PIXEL_HEIGHT (f, 0);
check_frame_size (f, &min_rows, &min_cols);
#ifdef HAVE_X11R4
size_hints.flags |= PBaseSize;
size_hints.base_width = base_width;
size_hints.base_height = base_height;
size_hints.min_width = base_width + min_cols * size_hints.width_inc;
size_hints.min_height = base_height + min_rows * size_hints.height_inc;
#else
size_hints.min_width = base_width;
size_hints.min_height = base_height;
#endif
}
if (flags)
{
size_hints.flags |= flags;
goto no_read;
}
#endif
{
XSizeHints hints;
long supplied_return;
int value;
#ifdef HAVE_X11R4
value = XGetWMNormalHints (FRAME_X_DISPLAY (f), window, &hints,
&supplied_return);
#else
value = XGetNormalHints (FRAME_X_DISPLAY (f), window, &hints);
#endif
#ifdef USE_X_TOOLKIT
size_hints.base_height = hints.base_height;
size_hints.base_width = hints.base_width;
size_hints.min_height = hints.min_height;
size_hints.min_width = hints.min_width;
#endif
if (flags)
size_hints.flags |= flags;
else
{
if (value == 0)
hints.flags = 0;
if (hints.flags & PSize)
size_hints.flags |= PSize;
if (hints.flags & PPosition)
size_hints.flags |= PPosition;
if (hints.flags & USPosition)
size_hints.flags |= USPosition;
if (hints.flags & USSize)
size_hints.flags |= USSize;
}
}
no_read:
#ifdef PWinGravity
size_hints.win_gravity = f->output_data.x->win_gravity;
size_hints.flags |= PWinGravity;
if (user_position)
{
size_hints.flags &= ~ PPosition;
size_hints.flags |= USPosition;
}
#endif
#ifdef HAVE_X11R4
XSetWMNormalHints (FRAME_X_DISPLAY (f), window, &size_hints);
#else
XSetNormalHints (FRAME_X_DISPLAY (f), window, &size_hints);
#endif
}
void
x_wm_set_window_state (f, state)
struct frame *f;
int state;
{
#ifdef USE_X_TOOLKIT
Arg al[1];
XtSetArg (al[0], XtNinitialState, state);
XtSetValues (f->output_data.x->widget, al, 1);
#else
Window window = FRAME_X_WINDOW (f);
f->output_data.x->wm_hints.flags |= StateHint;
f->output_data.x->wm_hints.initial_state = state;
XSetWMHints (FRAME_X_DISPLAY (f), window, &f->output_data.x->wm_hints);
#endif
}
void
x_wm_set_icon_pixmap (f, pixmap_id)
struct frame *f;
int pixmap_id;
{
Pixmap icon_pixmap;
#ifdef USE_X_TOOLKIT
Window window = XtWindow (f->output_data.x->widget);
#else
Window window = FRAME_X_WINDOW (f);
#endif
if (pixmap_id > 0)
{
icon_pixmap = x_bitmap_pixmap (f, pixmap_id);
f->output_data.x->wm_hints.icon_pixmap = icon_pixmap;
}
else
{
#if 0
f->output_data.x->wm_hints.icon_pixmap = None;
#else
return;
#endif
}
#ifdef USE_X_TOOLKIT
{
Arg al[1];
XtSetArg (al[0], XtNiconPixmap, icon_pixmap);
XtSetValues (f->output_data.x->widget, al, 1);
}
#else
f->output_data.x->wm_hints.flags |= IconPixmapHint;
XSetWMHints (FRAME_X_DISPLAY (f), window, &f->output_data.x->wm_hints);
#endif
}
void
x_wm_set_icon_position (f, icon_x, icon_y)
struct frame *f;
int icon_x, icon_y;
{
#ifdef USE_X_TOOLKIT
Window window = XtWindow (f->output_data.x->widget);
#else
Window window = FRAME_X_WINDOW (f);
#endif
f->output_data.x->wm_hints.flags |= IconPositionHint;
f->output_data.x->wm_hints.icon_x = icon_x;
f->output_data.x->wm_hints.icon_y = icon_y;
XSetWMHints (FRAME_X_DISPLAY (f), window, &f->output_data.x->wm_hints);
}
struct font_info *
x_get_font_info (f, font_idx)
FRAME_PTR f;
int font_idx;
{
return (FRAME_X_FONT_TABLE (f) + font_idx);
}
Lisp_Object
x_list_fonts (f, pattern, size, maxnames)
FRAME_PTR f;
Lisp_Object pattern;
int size;
int maxnames;
{
Lisp_Object list = Qnil, patterns, newlist = Qnil, key, tem, second_best;
Display *dpy = f != NULL ? FRAME_X_DISPLAY (f) : x_display_list->display;
int try_XLoadQueryFont = 0;
int count;
patterns = Fassoc (pattern, Valternate_fontname_alist);
if (NILP (patterns))
patterns = Fcons (pattern, Qnil);
if (maxnames == 1 && !size)
try_XLoadQueryFont = 1;
for (; CONSP (patterns); patterns = XCONS (patterns)->cdr)
{
int num_fonts;
char **names;
pattern = XCONS (patterns)->car;
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);
goto label_cached;
}
BLOCK_INPUT;
count = x_catch_errors (dpy);
if (try_XLoadQueryFont)
{
XFontStruct *font;
unsigned long value;
font = XLoadQueryFont (dpy, XSTRING (pattern)->data);
if (x_had_errors_p (dpy))
{
font = NULL;
x_clear_errors (dpy);
}
if (font
&& XGetFontProperty (font, XA_FONT, &value))
{
char *name = (char *) XGetAtomName (dpy, (Atom) value);
int len = strlen (name);
char *tmp;
if (len == 0)
try_XLoadQueryFont = 0;
else
{
num_fonts = 1;
names = (char **) alloca (sizeof (char *));
tmp = (char *) alloca (len + 1); names[0] = tmp;
bcopy (name, names[0], len + 1);
XFree (name);
}
}
else
try_XLoadQueryFont = 0;
if (font)
XFreeFont (dpy, font);
}
if (!try_XLoadQueryFont)
{
names = XListFonts (dpy, XSTRING (pattern)->data, max (maxnames, 10),
&num_fonts);
if (x_had_errors_p (dpy))
{
names = NULL;
x_clear_errors (dpy);
}
}
x_uncatch_errors (dpy, count);
UNBLOCK_INPUT;
if (names)
{
int i;
for (i = 0; i < num_fonts; i++)
{
char *p = names[i];
int average_width = -1, dashes = 0, width = 0;
while (*p)
if (*p++ == '-')
{
dashes++;
if (dashes == 7)
width = atoi (p);
else if (dashes == 12)
average_width = atoi (p);
}
if (dashes < 14 || average_width != 0)
{
tem = build_string (names[i]);
if (NILP (Fassoc (tem, list)))
{
if (STRINGP (Vx_pixel_size_width_font_regexp)
&& ((fast_c_string_match_ignore_case
(Vx_pixel_size_width_font_regexp, names[i]))
>= 0))
list = Fcons (Fcons (tem, make_number (width)), list);
else
list = Fcons (Fcons (tem, Qnil), list);
}
}
}
if (!try_XLoadQueryFont)
XFreeFontNames (names);
}
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);
label_cached:
if (NILP (list)) continue;
newlist = second_best = Qnil;
for (; CONSP (list); list = XCONS (list)->cdr)
{
int found_size;
tem = XCONS (list)->car;
if (!CONSP (tem) || NILP (XCONS (tem)->car))
continue;
if (!size)
{
newlist = Fcons (XCONS (tem)->car, newlist);
continue;
}
if (!INTEGERP (XCONS (tem)->cdr))
{
XFontStruct *thisinfo;
BLOCK_INPUT;
count = x_catch_errors (dpy);
thisinfo = XLoadQueryFont (dpy,
XSTRING (XCONS (tem)->car)->data);
if (x_had_errors_p (dpy))
{
thisinfo = NULL;
x_clear_errors (dpy);
}
x_uncatch_errors (dpy, count);
UNBLOCK_INPUT;
if (thisinfo)
{
XCONS (tem)->cdr
= (thisinfo->min_bounds.width == 0
? make_number (0)
: make_number (thisinfo->max_bounds.width));
XFreeFont (dpy, thisinfo);
}
else
XCONS (tem)->cdr = make_number (0);
}
found_size = XINT (XCONS (tem)->cdr);
if (found_size == size)
newlist = Fcons (XCONS (tem)->car, newlist);
else if (found_size > 0)
{
if (NILP (second_best))
second_best = tem;
else if (found_size < size)
{
if (XINT (XCONS (second_best)->cdr) > size
|| XINT (XCONS (second_best)->cdr) < found_size)
second_best = tem;
}
else
{
if (XINT (XCONS (second_best)->cdr) > size
&& XINT (XCONS (second_best)->cdr) > found_size)
second_best = tem;
}
}
}
if (!NILP (newlist))
break;
else if (!NILP (second_best))
{
newlist = Fcons (XCONS (second_best)->car, Qnil);
break;
}
}
return newlist;
}
struct font_info *
x_load_font (f, fontname, size)
struct frame *f;
register char *fontname;
int size;
{
struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
Lisp_Object font_names;
int count;
font_names = x_list_fonts (f, build_string (fontname), size, 1);
if (!NILP (font_names))
{
Lisp_Object tail;
int i;
for (i = 0; i < dpyinfo->n_fonts; i++)
for (tail = font_names; CONSP (tail); tail = XCONS (tail)->cdr)
if (!strcmp (dpyinfo->font_table[i].name,
XSTRING (XCONS (tail)->car)->data)
|| !strcmp (dpyinfo->font_table[i].full_name,
XSTRING (XCONS (tail)->car)->data))
return (dpyinfo->font_table + i);
}
{
char *full_name;
XFontStruct *font;
struct font_info *fontp;
unsigned long value;
if (size > 0 && !NILP (font_names))
fontname = (char *) XSTRING (XCONS (font_names)->car)->data;
BLOCK_INPUT;
count = x_catch_errors (FRAME_X_DISPLAY (f));
font = (XFontStruct *) XLoadQueryFont (FRAME_X_DISPLAY (f), fontname);
if (x_had_errors_p (FRAME_X_DISPLAY (f)))
{
font = NULL;
x_clear_errors (FRAME_X_DISPLAY (f));
}
x_uncatch_errors (FRAME_X_DISPLAY (f), count);
UNBLOCK_INPUT;
if (!font)
return NULL;
if (dpyinfo->font_table_size == 0)
{
dpyinfo->font_table_size = 16;
dpyinfo->font_table
= (struct font_info *) xmalloc (dpyinfo->font_table_size
* sizeof (struct font_info));
}
else if (dpyinfo->n_fonts
>= dpyinfo->font_table_size)
{
dpyinfo->font_table_size *= 2;
dpyinfo->font_table
= (struct font_info *) xrealloc (dpyinfo->font_table,
(dpyinfo->font_table_size
* sizeof (struct font_info)));
}
fontp = dpyinfo->font_table + dpyinfo->n_fonts;
BLOCK_INPUT;
fontp->font = font;
fontp->font_idx = dpyinfo->n_fonts;
fontp->name = (char *) xmalloc (strlen (fontname) + 1);
bcopy (fontname, fontp->name, strlen (fontname) + 1);
full_name = 0;
if (XGetFontProperty (font, XA_FONT, &value))
{
char *name = (char *) XGetAtomName (FRAME_X_DISPLAY (f), (Atom) value);
char *p = name;
int dashes = 0;
while (*p)
{
if (*p == '-')
dashes++;
p++;
}
if (dashes >= 13)
{
full_name = (char *) xmalloc (p - name + 1);
bcopy (name, full_name, p - name + 1);
}
XFree (name);
}
if (full_name != 0)
fontp->full_name = full_name;
else
fontp->full_name = fontp->name;
fontp->size = font->max_bounds.width;
fontp->height = FONT_HEIGHT (font);
{
int max_height = font->max_bounds.ascent + font->max_bounds.descent;
if (max_height > fontp->height)
fontp->height = max_height;
}
if (NILP (font_names))
{
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);
}
fontp->encoding[1]
= (font->max_byte1 == 0
? (font->min_char_or_byte2 < 0x80
? (font->max_char_or_byte2 < 0x80
? 0
: FONT_ENCODING_NOT_DECIDED)
: 1)
: (font->min_byte1 < 0x80
? (font->max_byte1 < 0x80
? (font->min_char_or_byte2 < 0x80
? (font->max_char_or_byte2 < 0x80
? 0
: FONT_ENCODING_NOT_DECIDED)
: 3)
: FONT_ENCODING_NOT_DECIDED)
: (font->min_char_or_byte2 < 0x80
? (font->max_char_or_byte2 < 0x80
? 2
: FONT_ENCODING_NOT_DECIDED)
: 1)));
fontp->baseline_offset
= (XGetFontProperty (font, dpyinfo->Xatom_MULE_BASELINE_OFFSET, &value)
? (long) value : 0);
fontp->relative_compose
= (XGetFontProperty (font, dpyinfo->Xatom_MULE_RELATIVE_COMPOSE, &value)
? (long) value : 0);
fontp->default_ascent
= (XGetFontProperty (font, dpyinfo->Xatom_MULE_DEFAULT_ASCENT, &value)
? (long) value : 0);
UNBLOCK_INPUT;
dpyinfo->n_fonts++;
return fontp;
}
}
struct font_info *
x_query_font (f, fontname)
struct frame *f;
register char *fontname;
{
struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
int i;
for (i = 0; i < dpyinfo->n_fonts; i++)
if (!strcmp (dpyinfo->font_table[i].name, fontname)
|| !strcmp (dpyinfo->font_table[i].full_name, fontname))
return (dpyinfo->font_table + i);
return NULL;
}
void
x_find_ccl_program (fontp)
struct font_info *fontp;
{
extern Lisp_Object Vfont_ccl_encoder_alist, Vccl_program_table;
extern Lisp_Object Qccl_program_idx;
extern Lisp_Object resolve_symbol_ccl_program ();
Lisp_Object list, elt, ccl_prog, ccl_id;
for (list = Vfont_ccl_encoder_alist; CONSP (list); list = XCONS (list)->cdr)
{
elt = XCONS (list)->car;
if (CONSP (elt)
&& STRINGP (XCONS (elt)->car)
&& (fast_c_string_match_ignore_case (XCONS (elt)->car, fontp->name)
>= 0))
{
if (SYMBOLP (XCONS (elt)->cdr) &&
(!NILP (ccl_id = Fget (XCONS (elt)->cdr, Qccl_program_idx))))
{
ccl_prog = XVECTOR (Vccl_program_table)->contents[XUINT (ccl_id)];
if (!CONSP (ccl_prog)) continue;
ccl_prog = XCONS (ccl_prog)->cdr;
}
else
{
ccl_prog = XCONS (elt)->cdr;
if (!VECTORP (ccl_prog)) continue;
}
fontp->font_encoder
= (struct ccl_program *) xmalloc (sizeof (struct ccl_program));
setup_ccl_program (fontp->font_encoder,
resolve_symbol_ccl_program (ccl_prog));
break;
}
}
}
#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
static int x_initialized;
#ifdef MULTI_KBOARD
static int
same_x_server (name1, name2)
char *name1, *name2;
{
int seen_colon = 0;
unsigned char *system_name = XSTRING (Vsystem_name)->data;
int system_name_length = strlen (system_name);
int length_until_period = 0;
while (system_name[length_until_period] != 0
&& system_name[length_until_period] != '.')
length_until_period++;
if (! strncmp (name1, "unix:", 5))
name1 += 4;
if (! strncmp (name2, "unix:", 5))
name2 += 4;
if (! strncmp (name1, system_name, system_name_length)
&& name1[system_name_length] == ':')
name1 += system_name_length;
if (! strncmp (name2, system_name, system_name_length)
&& name2[system_name_length] == ':')
name2 += system_name_length;
if (! strncmp (name1, system_name, length_until_period)
&& name1[length_until_period] == ':')
name1 += length_until_period;
if (! strncmp (name2, system_name, length_until_period)
&& name2[length_until_period] == ':')
name2 += length_until_period;
for (; *name1 != '\0' && *name1 == *name2; name1++, name2++)
{
if (*name1 == ':')
seen_colon++;
if (seen_colon && *name1 == '.')
return 1;
}
return (seen_colon
&& (*name1 == '.' || *name1 == '\0')
&& (*name2 == '.' || *name2 == '\0'));
}
#endif
#if defined (HAVE_X_I18N) || (defined (USE_X_TOOLKIT) && defined (HAVE_X11XTR6))
static void
fixup_locale ()
{
#ifdef LC_MESSAGES
setlocale (LC_MESSAGES, "C");
#endif
setlocale (LC_NUMERIC, "C");
setlocale (LC_TIME, "C");
}
#endif
struct x_display_info *
x_term_init (display_name, xrm_option, resource_name)
Lisp_Object display_name;
char *xrm_option;
char *resource_name;
{
Lisp_Object frame;
char *defaultvalue;
int connection;
Display *dpy;
struct x_display_info *dpyinfo;
XrmDatabase xrdb;
BLOCK_INPUT;
if (!x_initialized)
{
x_initialize ();
x_initialized = 1;
}
#ifdef HAVE_X_I18N
setlocale (LC_ALL, "");
fixup_locale ();
#endif
#ifdef USE_X_TOOLKIT
#ifdef HAVE_X11XTR6
XtSetLanguageProc (NULL, NULL, NULL);
#endif
{
int argc = 0;
char *argv[3];
argv[0] = "";
argc = 1;
if (xrm_option)
{
argv[argc++] = "-xrm";
argv[argc++] = xrm_option;
}
dpy = XtOpenDisplay (Xt_app_con, XSTRING (display_name)->data,
resource_name, EMACS_CLASS,
emacs_options, XtNumber (emacs_options),
&argc, argv);
#ifdef HAVE_X11XTR6
fixup_locale ();
#endif
}
#else
#ifdef HAVE_X11R5
XSetLocaleModifiers ("");
#endif
dpy = XOpenDisplay (XSTRING (display_name)->data);
#endif
if (dpy == 0)
{
UNBLOCK_INPUT;
return 0;
}
dpyinfo = (struct x_display_info *) xmalloc (sizeof (struct x_display_info));
#ifdef MULTI_KBOARD
{
struct x_display_info *share;
Lisp_Object tail;
for (share = x_display_list, tail = x_display_name_list; share;
share = share->next, tail = XCONS (tail)->cdr)
if (same_x_server (XSTRING (XCONS (XCONS (tail)->car)->car)->data,
XSTRING (display_name)->data))
break;
if (share)
dpyinfo->kboard = share->kboard;
else
{
dpyinfo->kboard = (KBOARD *) xmalloc (sizeof (KBOARD));
init_kboard (dpyinfo->kboard);
if (!EQ (XSYMBOL (Qvendor_specific_keysyms)->function, Qunbound))
{
char *vendor = ServerVendor (dpy);
dpyinfo->kboard->Vsystem_key_alist
= call1 (Qvendor_specific_keysyms,
build_string (vendor ? vendor : ""));
}
dpyinfo->kboard->next_kboard = all_kboards;
all_kboards = dpyinfo->kboard;
if (current_kboard == initial_kboard)
current_kboard = dpyinfo->kboard;
}
dpyinfo->kboard->reference_count++;
}
#endif
dpyinfo->next = x_display_list;
x_display_list = dpyinfo;
x_display_name_list = Fcons (Fcons (display_name, Qnil),
x_display_name_list);
dpyinfo->name_list_element = XCONS (x_display_name_list)->car;
dpyinfo->display = dpy;
#if 0
XSetAfterFunction (x_current_display, x_trace_wire);
#endif
dpyinfo->x_id_name
= (char *) xmalloc (STRING_BYTES (XSTRING (Vinvocation_name))
+ STRING_BYTES (XSTRING (Vsystem_name))
+ 2);
sprintf (dpyinfo->x_id_name, "%s@%s",
XSTRING (Vinvocation_name)->data, XSTRING (Vsystem_name)->data);
x_find_modifier_meanings (dpyinfo);
dpyinfo->vertical_scroll_bar_cursor
= XCreateFontCursor (dpyinfo->display, XC_sb_v_double_arrow);
xrdb = x_load_resources (dpyinfo->display, xrm_option,
resource_name, EMACS_CLASS);
#ifdef HAVE_XRMSETDATABASE
XrmSetDatabase (dpyinfo->display, xrdb);
#else
dpyinfo->display->db = xrdb;
#endif
dpyinfo->xrdb = xrdb;
dpyinfo->screen = ScreenOfDisplay (dpyinfo->display,
DefaultScreen (dpyinfo->display));
dpyinfo->visual = select_visual (dpyinfo->display, dpyinfo->screen,
&dpyinfo->n_planes);
dpyinfo->height = HeightOfScreen (dpyinfo->screen);
dpyinfo->width = WidthOfScreen (dpyinfo->screen);
dpyinfo->root_window = RootWindowOfScreen (dpyinfo->screen);
dpyinfo->grabbed = 0;
dpyinfo->reference_count = 0;
dpyinfo->icon_bitmap_id = -1;
dpyinfo->n_fonts = 0;
dpyinfo->font_table_size = 0;
dpyinfo->bitmaps = 0;
dpyinfo->bitmaps_size = 0;
dpyinfo->bitmaps_last = 0;
dpyinfo->scratch_cursor_gc = 0;
dpyinfo->mouse_face_mouse_frame = 0;
dpyinfo->mouse_face_deferred_gc = 0;
dpyinfo->mouse_face_beg_row = dpyinfo->mouse_face_beg_col = -1;
dpyinfo->mouse_face_end_row = dpyinfo->mouse_face_end_col = -1;
dpyinfo->mouse_face_face_id = 0;
dpyinfo->mouse_face_window = Qnil;
dpyinfo->mouse_face_mouse_x = dpyinfo->mouse_face_mouse_y = 0;
dpyinfo->mouse_face_defer = 0;
dpyinfo->x_focus_frame = 0;
dpyinfo->x_focus_event_frame = 0;
dpyinfo->x_highlight_frame = 0;
dpyinfo->Xatom_wm_protocols
= XInternAtom (dpyinfo->display, "WM_PROTOCOLS", False);
dpyinfo->Xatom_wm_take_focus
= XInternAtom (dpyinfo->display, "WM_TAKE_FOCUS", False);
dpyinfo->Xatom_wm_save_yourself
= XInternAtom (dpyinfo->display, "WM_SAVE_YOURSELF", False);
dpyinfo->Xatom_wm_delete_window
= XInternAtom (dpyinfo->display, "WM_DELETE_WINDOW", False);
dpyinfo->Xatom_wm_change_state
= XInternAtom (dpyinfo->display, "WM_CHANGE_STATE", False);
dpyinfo->Xatom_wm_configure_denied
= XInternAtom (dpyinfo->display, "WM_CONFIGURE_DENIED", False);
dpyinfo->Xatom_wm_window_moved
= XInternAtom (dpyinfo->display, "WM_MOVED", False);
dpyinfo->Xatom_editres
= XInternAtom (dpyinfo->display, "Editres", False);
dpyinfo->Xatom_CLIPBOARD
= XInternAtom (dpyinfo->display, "CLIPBOARD", False);
dpyinfo->Xatom_TIMESTAMP
= XInternAtom (dpyinfo->display, "TIMESTAMP", False);
dpyinfo->Xatom_TEXT
= XInternAtom (dpyinfo->display, "TEXT", False);
dpyinfo->Xatom_COMPOUND_TEXT
= XInternAtom (dpyinfo->display, "COMPOUND_TEXT", False);
dpyinfo->Xatom_DELETE
= XInternAtom (dpyinfo->display, "DELETE", False);
dpyinfo->Xatom_MULTIPLE
= XInternAtom (dpyinfo->display, "MULTIPLE", False);
dpyinfo->Xatom_INCR
= XInternAtom (dpyinfo->display, "INCR", False);
dpyinfo->Xatom_EMACS_TMP
= XInternAtom (dpyinfo->display, "_EMACS_TMP_", False);
dpyinfo->Xatom_TARGETS
= XInternAtom (dpyinfo->display, "TARGETS", False);
dpyinfo->Xatom_NULL
= XInternAtom (dpyinfo->display, "NULL", False);
dpyinfo->Xatom_ATOM_PAIR
= XInternAtom (dpyinfo->display, "ATOM_PAIR", False);
dpyinfo->Xatom_PIXEL_SIZE
= XInternAtom (dpyinfo->display, "PIXEL_SIZE", False);
dpyinfo->Xatom_MULE_BASELINE_OFFSET
= XInternAtom (dpyinfo->display, "_MULE_BASELINE_OFFSET", False);
dpyinfo->Xatom_MULE_RELATIVE_COMPOSE
= XInternAtom (dpyinfo->display, "_MULE_RELATIVE_COMPOSE", False);
dpyinfo->Xatom_MULE_DEFAULT_ASCENT
= XInternAtom (dpyinfo->display, "_MULE_DEFAULT_ASCENT", False);
dpyinfo->cut_buffers_initialized = 0;
connection = ConnectionNumber (dpyinfo->display);
dpyinfo->connection = connection;
{
char null_bits[1];
null_bits[0] = 0x00;
dpyinfo->null_pixel
= XCreatePixmapFromBitmapData (dpyinfo->display, dpyinfo->root_window,
null_bits, 1, 1, (long) 0, (long) 0,
1);
}
#ifdef subprocesses
if (connection != 0)
add_keyboard_wait_descriptor (connection);
#endif
#ifndef F_SETOWN_BUG
#ifdef F_SETOWN
#ifdef F_SETOWN_SOCK_NEG
fcntl (connection, F_SETOWN, -getpid ());
#else
fcntl (connection, F_SETOWN, getpid ());
#endif
#endif
#endif
#ifdef SIGIO
if (interrupt_input)
init_sigio (connection);
#endif
#ifdef USE_LUCID
#ifdef HAVE_X11R5
{
Display *dpy = dpyinfo->display;
XrmValue d, fr, to;
Font font;
int count;
d.addr = (XPointer)&dpy;
d.size = sizeof (Display *);
fr.addr = XtDefaultFont;
fr.size = sizeof (XtDefaultFont);
to.size = sizeof (Font *);
to.addr = (XPointer)&font;
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, count);
}
#endif
#endif
UNBLOCK_INPUT;
return dpyinfo;
}
void
x_delete_display (dpyinfo)
struct x_display_info *dpyinfo;
{
delete_keyboard_wait_descriptor (dpyinfo->connection);
if (! NILP (x_display_name_list)
&& EQ (XCONS (x_display_name_list)->car, dpyinfo->name_list_element))
x_display_name_list = XCONS (x_display_name_list)->cdr;
else
{
Lisp_Object tail;
tail = x_display_name_list;
while (CONSP (tail) && CONSP (XCONS (tail)->cdr))
{
if (EQ (XCONS (XCONS (tail)->cdr)->car,
dpyinfo->name_list_element))
{
XCONS (tail)->cdr = XCONS (XCONS (tail)->cdr)->cdr;
break;
}
tail = XCONS (tail)->cdr;
}
}
if (x_display_list == dpyinfo)
x_display_list = dpyinfo->next;
else
{
struct x_display_info *tail;
for (tail = x_display_list; tail; tail = tail->next)
if (tail->next == dpyinfo)
tail->next = tail->next->next;
}
#ifndef USE_X_TOOLKIT
#ifndef AIX
XrmDestroyDatabase (dpyinfo->xrdb);
#endif
#endif
#ifdef MULTI_KBOARD
if (--dpyinfo->kboard->reference_count == 0)
delete_kboard (dpyinfo->kboard);
#endif
xfree (dpyinfo->font_table);
xfree (dpyinfo->x_id_name);
xfree (dpyinfo);
}
void
x_initialize ()
{
clear_frame_hook = XTclear_frame;
clear_end_of_line_hook = XTclear_end_of_line;
ins_del_lines_hook = XTins_del_lines;
change_line_highlight_hook = XTchange_line_highlight;
insert_glyphs_hook = XTinsert_glyphs;
write_glyphs_hook = XTwrite_glyphs;
delete_glyphs_hook = XTdelete_glyphs;
ring_bell_hook = XTring_bell;
reset_terminal_modes_hook = XTreset_terminal_modes;
set_terminal_modes_hook = XTset_terminal_modes;
update_begin_hook = XTupdate_begin;
update_end_hook = XTupdate_end;
set_terminal_window_hook = XTset_terminal_window;
read_socket_hook = XTread_socket;
frame_up_to_date_hook = XTframe_up_to_date;
cursor_to_hook = XTcursor_to;
reassert_line_highlight_hook = XTreassert_line_highlight;
mouse_position_hook = XTmouse_position;
frame_rehighlight_hook = XTframe_rehighlight;
frame_raise_lower_hook = XTframe_raise_lower;
set_vertical_scroll_bar_hook = XTset_vertical_scroll_bar;
condemn_scroll_bars_hook = XTcondemn_scroll_bars;
redeem_scroll_bar_hook = XTredeem_scroll_bar;
judge_scroll_bars_hook = XTjudge_scroll_bars;
scroll_region_ok = 1;
char_ins_del_ok = 0;
line_ins_del_ok = 1;
fast_clear_end_of_line = 1;
memory_below_frame = 0;
baud_rate = 19200;
x_noop_count = 0;
Fset_input_mode (Qt, Qnil, Qt, Qnil);
#ifdef USE_X_TOOLKIT
XtToolkitInitialize ();
Xt_app_con = XtCreateApplicationContext ();
XtAppSetFallbackResources (Xt_app_con, Xt_default_resources);
#endif
XSetErrorHandler (x_error_handler);
XSetIOErrorHandler (x_io_error_quitter);
#ifdef SIGWINCH
signal (SIGWINCH, SIG_DFL);
#endif
signal (SIGPIPE, x_connection_signal);
}
void
syms_of_xterm ()
{
staticpro (&x_error_message_string);
x_error_message_string = Qnil;
staticpro (&x_display_name_list);
x_display_name_list = Qnil;
staticpro (&last_mouse_scroll_bar);
last_mouse_scroll_bar = Qnil;
staticpro (&Qvendor_specific_keysyms);
Qvendor_specific_keysyms = intern ("vendor-specific-keysyms");
staticpro (&last_mouse_press_frame);
last_mouse_press_frame = Qnil;
}
#endif