/*#include <X/Xproto.h> */
#endif /* ! defined (HAVE_X11) */
+#ifdef FD_SET
+/* We could get this from param.h, but better not to depend on finding that.
+ And better not to risk that it might define other symbols used in this
+ file. */
+#ifdef FD_SETSIZE
+#define MAXDESC FD_SETSIZE
+#else
+#define MAXDESC 64
+#endif
+#define SELECT_TYPE fd_set
+#else /* no FD_SET */
+#define MAXDESC 32
+#define SELECT_TYPE int
+
+/* Define the macros to access a single-int bitmap of descriptors. */
+#define FD_SET(n, p) (*(p) |= (1 << (n)))
+#define FD_CLR(n, p) (*(p) &= ~(1 << (n)))
+#define FD_ISSET(n, p) (*(p) & (1 << (n)))
+#define FD_ZERO(p) (*(p) = 0)
+#endif /* no FD_SET */
+
/* For sending Meta-characters. Do we need this? */
#define METABIT 0200
extern FONT_TYPE *XOpenFont ();
static void flashback ();
+static void redraw_previous_char ();
#ifndef HAVE_X11
static void dumpqueue ();
of the frame being updated, so that the XT... functions do not
need to take a frame as argument. Most of the XT... functions
should never be called except during an update, the only exceptions
- being XTcursor_to, XTwrite_char and XTreassert_line_highlight. */
+ being XTcursor_to, XTwrite_glyphs and XTreassert_line_highlight. */
extern int mouse_track_top, mouse_track_left, mouse_track_width;
Since the display generation code is responsible for calling
compute_char_face and compute_glyph_face on everything it puts in
the display structure, we can assume that the face code on each
- glyph is a valid index into FRAME_FACES (f), and the one to which
- we can actually apply intern_face. */
+ glyph is a valid index into FRAME_COMPUTED_FACES (f), and the one
+ to which we can actually apply intern_face. */
#if 1
/* This is the multi-face code. */
{
/* The face codes on the glyphs must be valid indices into the
frame's face table. */
- if (cf < 0 || cf >= FRAME_N_FACES (f))
+ if (cf < 0 || cf >= FRAME_N_COMPUTED_FACES (f)
+ || FRAME_COMPUTED_FACES (f) [cf] == 0)
abort ();
if (cf == 1)
face = FRAME_MODE_LINE_FACE (f);
else
- face = intern_face (f, FRAME_FACES (f) [cf]);
+ face = intern_face (f, FRAME_COMPUTED_FACES (f) [cf]);
font = FACE_FONT (face);
gc = FACE_GC (face);
defaulted = 0;
CHAR_TO_PIXEL_ROW (f, curs_y),
FONT_WIDTH (f->display.x->font) * (first_unused - curs_x),
FONT_HEIGHT (f->display.x->font), False);
-
+#if 0
+ redraw_previous_char (f, curs_x, curs_y);
+#endif
#else /* ! defined (HAVE_X11) */
XPixSet (FRAME_X_WINDOW (f),
CHAR_TO_PIXEL_COL (f, curs_x),
UNBLOCK_INPUT;
}
+/* Erase the character (if any) at the position just before X, Y in frame F,
+ then redraw it and the character before it.
+ This is necessary when we erase starting at X,
+ in case the character after X overlaps into the one before X. */
+
+static void
+redraw_previous_char (f, x, y)
+ FRAME_PTR f;
+ int x, y;
+{
+ /* Erase the character before the new ones, in case
+ what was here before overlaps it.
+ Reoutput that character, and the previous character
+ (in case the previous character overlaps it). */
+ if (x > 0)
+ {
+ int start_x = x - 2;
+ if (start_x < 0)
+ start_x = 0;
+ XClearArea (x_current_display, FRAME_X_WINDOW (f),
+ CHAR_TO_PIXEL_COL (f, x - 1),
+ CHAR_TO_PIXEL_ROW (f, y),
+ FONT_WIDTH (f->display.x->font),
+ FONT_HEIGHT (f->display.x->font), 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);
+ }
+}
+
static
XTclear_frame ()
{
frame_highlight (frame)
struct frame *frame;
{
- if (! EQ (Vx_no_window_manager, Qnil))
- XSetWindowBorder (x_current_display, FRAME_X_WINDOW (frame),
- frame->display.x->border_pixel);
+ /* We used to only do this if Vx_no_window_manager was non-nil, but
+ the ICCCM (section 4.1.6) says that the window's border pixmap
+ and border pixel are window attributes which are "private to the
+ client", so we can always change it to whatever we want. */
+ BLOCK_INPUT;
+ XSetWindowBorder (x_current_display, FRAME_X_WINDOW (frame),
+ frame->display.x->border_pixel);
+ UNBLOCK_INPUT;
x_display_cursor (frame, 1);
}
frame_unhighlight (frame)
struct frame *frame;
{
- if (! EQ (Vx_no_window_manager, Qnil))
- XSetWindowBorderPixmap (x_current_display, FRAME_X_WINDOW (frame),
- frame->display.x->border_tile);
+ /* We used to only do this if Vx_no_window_manager was non-nil, but
+ the ICCCM (section 4.1.6) says that the window's border pixmap
+ and border pixel are window attributes which are "private to the
+ client", so we can always change it to whatever we want. */
+ BLOCK_INPUT;
+ XSetWindowBorderPixmap (x_current_display, FRAME_X_WINDOW (frame),
+ frame->display.x->border_tile);
+ UNBLOCK_INPUT;
x_display_cursor (frame, 1);
}
#else /* ! defined (HAVE_X11) */
int items_pending; /* How many items are in the X queue. */
XEvent event;
struct frame *f;
- int event_found;
+ int event_found = 0;
int prefix;
Lisp_Object part;
/* The window manager never makes a window invisible
("withdrawn"); all it does is switch between visible
and iconified. Frames get into the invisible state
- only through x_make_frame_invisible.
+ only through x_make_frame_invisible. */
if (FRAME_VISIBLE_P (f) || FRAME_ICONIFIED_P (f))
f->async_iconified = 1;
}
if (f != 0)
{
KeySym keysym, orig_keysym;
- char copy_buffer[80];
+ unsigned char copy_buffer[80];
int modifiers;
event.xkey.state
if (numchars > 1)
{
- if ((keysym >= XK_BackSpace && keysym <= XK_Escape)
- || keysym == XK_Delete
- || IsCursorKey (keysym) /* 0xff50 <= x < 0xff60 */
- || IsMiscFunctionKey (keysym) /* 0xff60 <= x < VARIES */
+ if (((keysym >= XK_BackSpace && keysym <= XK_Escape)
+ || keysym == XK_Delete
+ || IsCursorKey (keysym) /* 0xff50 <= x < 0xff60 */
+ || IsMiscFunctionKey (keysym) /* 0xff60 <= x < VARIES */
#ifdef HPUX
- /* This recognizes the "extended function keys".
- It seems there's no cleaner way.
- Test IsModifierKey to avoid handling mode_switch
- incorrectly. */
- || (!IsModifierKey (orig_keysym)
- && (unsigned) (keysym) >= XK_Select
- && (unsigned)(keysym) < XK_KP_Space)
+ /* This recognizes the "extended function keys".
+ It seems there's no cleaner way.
+ Test IsModifierKey to avoid handling mode_switch
+ incorrectly. */
+ || ((unsigned) (keysym) >= XK_Select
+ && (unsigned)(keysym) < XK_KP_Space)
+#endif
+ || IsKeypadKey (keysym) /* 0xff80 <= x < 0xffbe */
+ || IsFunctionKey (keysym) /* 0xffbe <= x < 0xffe1 */
+ || x_is_vendor_fkey (orig_keysym))
+ && ! (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
- || IsKeypadKey (keysym) /* 0xff80 <= x < 0xffbe */
- || IsFunctionKey (keysym) /* 0xffbe <= x < 0xffe1 */
- || x_is_vendor_fkey (orig_keysym)) /* wherever */
+#endif /* not HAVE_X11R5 */
+ ))
{
if (temp_index == sizeof temp_buffer / sizeof (short))
temp_index = 0;
Window win, child;
int win_x, win_y;
- /* Coords are relative to the parent.
- Convert them to root-relative. */
+ /* Find the position of the outside upper-left corner of
+ the window, in the root coordinate system. Don't
+ refer to the parent window here; we may be processing
+ this event after the window manager has changed our
+ parent, but before we have reached the ReparentNotify. */
XTranslateCoordinates (x_current_display,
/* From-window, to-window. */
- f->display.x->parent_desc,
+ f->display.x->window_desc,
ROOT_WINDOW,
/* From-position, to-position. */
- event.xconfigure.x,
- event.xconfigure.y,
+ -event.xconfigure.border_width,
+ -event.xconfigure.border_width,
&win_x, &win_y,
/* Child of win. */
}
}
-#if 0
#ifdef HAVE_SELECT
if (expected && ! event_found)
{
/* AOJ 880406: if select returns true but XPending doesn't, it means that
there is an EOF condition; in other words, that X has died.
Act as if there had been a hangup. */
-
int fd = ConnectionNumber (x_current_display);
- int mask = 1 << fd;
+ SELECT_TYPE mask;
+ EMACS_TIME timeout;
- if (0 != select (fd + 1, &mask, (long *) 0, (long *) 0,
- (EMACS_TIME) 0)
+ FD_SET(fd, &mask);
+ EMACS_SET_SECS_USECS (timeout, 0, 0);
+ if (0 != select (fd + 1, &mask, (long *) 0, (long *) 0, &timeout)
&& !XStuffPending ())
kill (getpid (), SIGHUP);
}
#endif /* ! defined (HAVE_SELECT) */
-#endif /* ! 0 */
#ifndef HAVE_X11
if (updating_frame == 0)
if (_Xdebug)
abort ();
- shut_down_emacs (0, 1);
+ shut_down_emacs (0, 1, Qnil);
exit (70);
}
#ifdef HAVE_X11
+struct font_info
+{
+ XFontStruct *font;
+ char *name;
+};
+
/* A table of all the fonts we have already loaded. */
-static XFontStruct **x_font_table;
+static struct font_info *x_font_table;
/* The current capacity of x_font_table. */
static int x_font_table_size;
/* Get a list of all the fonts that match this name. Once we
have a list of matching fonts, we compare them against the fonts
we already have by comparing font ids. */
- font_names = (char **) XListFontsWithInfo (x_current_display, fontname,
- 1024, &n_matching_fonts,
- &font_info);
+ font_names = (char **) XListFonts (x_current_display, fontname,
+ 1024, &n_matching_fonts);
/* Apparently it doesn't set n_matching_fonts to zero when it can't
find any matches; font_names == 0 is the only clue. */
if (! font_names)
for (i = 0; i < n_fonts; i++)
for (j = 0; j < n_matching_fonts; j++)
- if (x_font_table[i]->fid == font_info[j].fid)
+ if (!strcmp (x_font_table[i].name, font_names[j]))
{
already_loaded = i;
fontname = font_names[j];
found_font:
/* If we have, just return it from the table. */
- if (already_loaded > 0)
- f->display.x->font = x_font_table[already_loaded];
+ if (already_loaded >= 0)
+ f->display.x->font = x_font_table[already_loaded].font;
/* Otherwise, load the font and add it to the table. */
else
font = (XFontStruct *) XLoadQueryFont (x_current_display, fontname);
if (! font)
{
- /* Free the information from XListFontsWithInfo. */
+ /* Free the information from XListFonts. */
if (n_matching_fonts)
- XFreeFontInfo (font_names, font_info, n_matching_fonts);
+ XFreeFontNames (font_names);
return Qnil;
}
{
x_font_table_size = 16;
x_font_table
- = (XFontStruct **) xmalloc (x_font_table_size
- * sizeof (x_font_table[0]));
+ = (struct font_info *) xmalloc (x_font_table_size
+ * sizeof (x_font_table[0]));
}
/* Do we need to grow the table? */
else if (n_fonts >= x_font_table_size)
{
x_font_table_size *= 2;
x_font_table
- = (XFontStruct **) xrealloc (x_font_table,
- (x_font_table_size
- * sizeof (x_font_table[0])));
+ = (struct font_info *) xrealloc (x_font_table,
+ (x_font_table_size
+ * sizeof (x_font_table[0])));
}
- f->display.x->font = x_font_table[n_fonts++] = font;
+ x_font_table[n_fonts].name = (char *) xmalloc (strlen (fontname));
+ bcopy (fontname, x_font_table[n_fonts].name, strlen (fontname) + 1);
+ f->display.x->font = x_font_table[n_fonts++].font = font;
}
-
+
/* Now make the frame display the given font. */
if (FRAME_X_WINDOW (f) != 0)
{
Lisp_Object lispy_name = build_string (fontname);
- /* Free the information from XListFontsWithInfo. The data
+ /* Free the information from XListFonts. The data
we actually retain comes from XLoadQueryFont. */
- XFreeFontInfo (font_names, font_info, n_matching_fonts);
+ XFreeFontNames (font_names);
return lispy_name;
}
struct frame *f;
{
#ifdef HAVE_X11
+ Window win, child;
+ int win_x = 0, win_y = 0;
+
+ /* Find the position of the outside upper-left corner of
+ the inner window, with respect to the outer window. */
+ if (f->display.x->parent_desc != ROOT_WINDOW)
+ {
+ BLOCK_INPUT;
+ XTranslateCoordinates (x_current_display,
+
+ /* From-window, to-window. */
+ f->display.x->window_desc,
+ f->display.x->parent_desc,
+
+ /* From-position, to-position. */
+ 0, 0, &win_x, &win_y,
+
+ /* Child of win. */
+ &child);
+ UNBLOCK_INPUT;
+ }
+
+ /* Treat negative positions as relative to the leftmost bottommost
+ position that fits on the screen. */
if (f->display.x->left_pos < 0)
- f->display.x->left_pos
- = x_screen_width - PIXEL_WIDTH (f) + f->display.x->left_pos;
+ f->display.x->left_pos = (x_screen_width
+ - f->display.x->border_width - win_x
+ - PIXEL_WIDTH (f)
+ + f->display.x->left_pos);
if (f->display.x->top_pos < 0)
- f->display.x->top_pos
- = x_screen_height - PIXEL_HEIGHT (f) + f->display.x->top_pos;
+ f->display.x->top_pos = (x_screen_height
+ - f->display.x->border_width - win_y
+ - PIXEL_HEIGHT (f)
+ + f->display.x->top_pos);
+
#else /* ! defined (HAVE_X11) */
WINDOWINFO_TYPE parentinfo;
XMoveWindow (XDISPLAY FRAME_X_WINDOW (f),
f->display.x->left_pos, f->display.x->top_pos);
#ifdef HAVE_X11
- x_wm_set_size_hint (f, 0);
+ x_wm_set_size_hint (f, 0, xoff, yoff);
#endif /* ! defined (HAVE_X11) */
UNBLOCK_INPUT;
}
BLOCK_INPUT;
check_frame_size (f, &rows, &cols);
- f->display.x->vertical_scroll_bar_extra =
- (FRAME_HAS_VERTICAL_SCROLL_BARS (f)
- ? VERTICAL_SCROLL_BAR_PIXEL_WIDTH (f)
- : 0);
+ f->display.x->vertical_scroll_bar_extra
+ = (FRAME_HAS_VERTICAL_SCROLL_BARS (f)
+ ? VERTICAL_SCROLL_BAR_PIXEL_WIDTH (f)
+ : 0);
pixelwidth = CHAR_TO_PIXEL_WIDTH (f, cols);
pixelheight = CHAR_TO_PIXEL_HEIGHT (f, rows);
#ifdef HAVE_X11
- x_wm_set_size_hint (f, 0);
+ x_wm_set_size_hint (f, 0, 0, 0);
#endif /* ! defined (HAVE_X11) */
XChangeWindowSize (FRAME_X_WINDOW (f), pixelwidth, pixelheight);
IconicState. */
x_wm_set_window_state (f, IconicState);
+ if (!FRAME_VISIBLE_P (f))
+ {
+ /* If the frame was withdrawn, before, we must map it. */
+ XMapWindow (XDISPLAY FRAME_X_WINDOW (f));
+ if (FRAME_HAS_VERTICAL_SCROLL_BARS (f))
+ XMapSubwindows (x_current_display, FRAME_X_WINDOW (f));
+ }
+
f->async_iconified = 1;
#else /* ! defined (HAVE_X11) */
XUnmapWindow (XDISPLAY FRAME_X_WINDOW (f));
#ifdef HAVE_X11
-x_wm_set_size_hint (f, prompting)
+/* SPEC_X and SPEC_Y are the specified positions.
+ We look only at their sign, to decide the gravity. */
+
+x_wm_set_size_hint (f, prompting, spec_x, spec_y)
struct frame *f;
long prompting;
+ int spec_x, spec_y;
{
XSizeHints size_hints;
Window window = FRAME_X_WINDOW (f);
size_hints.flags |= USSize;
}
+ switch (((spec_x < 0) << 1) + (spec_y < 0))
+ {
+ case 0:
+ size_hints.win_gravity = NorthWestGravity;
+ break;
+ case 1:
+ size_hints.win_gravity = SouthWestGravity;
+ break;
+ case 2:
+ size_hints.win_gravity = NorthEastGravity;
+ break;
+ case 3:
+ size_hints.win_gravity = SouthEastGravity;
+ break;
+ }
+ size_hints.flags |= PWinGravity;
+
#ifdef HAVE_X11R4
XSetWMNormalHints (x_current_display, window, &size_hints);
#else
{
Lisp_Object frame;
char *defaultvalue;
+#ifndef F_SETOWN_BUG
#ifdef F_SETOWN
extern int old_fcntl_owner;
#endif /* ! defined (F_SETOWN) */
+#endif /* F_SETOWN_BUG */
x_focus_frame = x_highlight_frame = 0;
x_current_display = XOpenDisplay (display_name);
if (x_current_display == 0)
- fatal ("X server %s not responding; check the DISPLAY environment variable or use \"-d\"\n",
+ fatal ("X server %s not responding.\n\
+Check the DISPLAY environment variable or use \"-d\"\n",
display_name);
#ifdef HAVE_X11
#endif /* ! defined (HAVE_X11) */
+#ifndef F_SETOWN_BUG
#ifdef F_SETOWN
old_fcntl_owner = fcntl (0, F_GETOWN, 0);
#ifdef F_SETOWN_SOCK_NEG
fcntl (0, F_SETOWN, getpid ());
#endif /* ! defined (F_SETOWN_SOCK_NEG) */
#endif /* ! defined (F_SETOWN) */
+#endif /* F_SETOWN_BUG */
#ifdef SIGIO
init_sigio ();
#endif /* ! defined (SIGIO) */
- /* Must use interrupt input because we cannot otherwise
- arrange for C-g to be noticed immediately.
- We cannot connect it to SIGINT. */
- Fset_input_mode (Qt, Qnil, Qt, Qnil);
-
expose_all_windows = 0;
clear_frame_hook = XTclear_frame;
off the bottom */
baud_rate = 19200;
+ /* Try to use interrupt input; if we can't, then start polling. */
+ Fset_input_mode (Qt, Qnil, Qt, Qnil);
+
/* Note that there is no real way portable across R3/R4 to get the
original error handler. */
XHandleError (x_error_quitter);