/* X Communication module for terminals which understand the X protocol.
- Copyright (C) 1989 Free Software Foundation, Inc.
+ Copyright (C) 1989, 1992 Free Software Foundation, Inc.
This file is part of GNU Emacs.
GNU Emacs is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 1, or (at your option)
+the Free Software Foundation; either version 2, or (at your option)
any later version.
GNU Emacs is distributed in the hope that it will be useful,
#ifdef HAVE_X_WINDOWS
#include "lisp.h"
-#undef NULL
/* On 4.3 this loses if it comes after xterm.h. */
#include <signal.h>
#endif
#endif
-#ifdef NEED_TIME_H
-#include <time.h>
-#else /* not NEED_TIME_H */
-#ifdef HAVE_TIMEVAL
-#include <sys/time.h>
-#endif /* HAVE_TIMEVAL */
-#endif /* not NEED_TIME_H */
+#include "systime.h"
#include <fcntl.h>
#include <stdio.h>
/* Stuff for dealing with the main icon title. */
extern Lisp_Object Vcommand_line_args;
-char *hostname, *id_name, *invocation_name;
+char *hostname, *x_id_name;
+Lisp_Object invocation_name;
/* This is the X connection that we are using. */
extern int errno;
-extern Lisp_Object Vglobal_minibuffer_screen;
-
extern Display *XOpenDisplay ();
extern Window XCreateWindow ();
#endif
void dumpborder ();
-static XTcursor_to ();
-static XTclear_end_of_line ();
+static int XTcursor_to ();
+static int XTclear_end_of_line ();
\f
/* These hooks are called by update_screen at the beginning and end
of a screen update. We record in `updating_screen' the identity
#ifndef HAVE_X11
dumpqueue ();
#endif
- x_display_cursor (s, 0);
UNBLOCK_INPUT;
}
where display update commands will take effect.
This does not affect the place where the cursor-box is displayed. */
+static int
XTcursor_to (row, col)
register int row, col;
{
int hl;
FONT_TYPE *font;
{
- char buf[s->width];
- register char *cp = buf;
register int len;
Window window = s->display.x->window_desc;
GC drawing_gc = (hl == 2 ? s->display.x->cursor_gc
curs_y = s->cursor_y;
}
- /* Clear the cursor if it appears on this line. */
- if (curs_y == s->cursor_y)
- x_display_cursor (s, 0);
-
dumpglyphs (s,
(curs_x * FONT_WIDTH (s->display.x->font)
+ s->display.x->internal_border_width),
(curs_y * FONT_HEIGHT (s->display.x->font)
+ s->display.x->internal_border_width),
start, len, highlight, s->display.x->font);
+
+ /* If we drew on top of the cursor, note that it is turned off. */
+ if (curs_y == s->phys_cursor_y
+ && curs_x <= s->phys_cursor_x
+ && curs_x + len > s->phys_cursor_x)
+ s->phys_cursor_x = -1;
if (updating_screen == 0)
{
to column FIRST_UNUSED (exclusive). The idea is that everything
from FIRST_UNUSED onward is already erased. */
-static
+static int
XTclear_end_of_line (first_unused)
register int first_unused;
{
BLOCK_INPUT;
- /* Clear the cursor if it appears on this line. */
- if (curs_y == s->cursor_y)
- x_display_cursor (s, 0);
+ /* Notice if the cursor will be cleared by this operation. */
+ if (curs_y == s->phys_cursor_y
+ && curs_x <= s->phys_cursor_x
+ && s->phys_cursor_x < first_unused)
+ s->phys_cursor_x = -1;
#ifdef HAVE_X11
XClearArea (x_current_display, s->display.x->window_desc,
if (updating_screen == 0)
abort ();
- /* Clear the cursor. */
+ /* Hide the cursor. */
x_display_cursor (updating_screen, 0);
XTcursor_to (vpos, 0);
if (XTYPE (screen) != Lisp_Screen)
continue;
s = XSCREEN (screen);
- if (s->output_method != output_x_window)
+ if (! SCREEN_IS_X (s))
continue;
if (!s->visible)
continue;
text_window,
};
-/* Symbol returned in input stream to indicate mouse movement. */
-Lisp_Object Qmouse_moved;
-
/* Position of the mouse in characters */
unsigned int x_mouse_x, x_mouse_y;
-/* Emacs window the mouse is in, if any. */
-extern Lisp_Object Vmouse_window;
-
/* Offset in buffer of character under the pointer, or 0. */
extern int mouse_buffer_offset;
-/* Part of the screen the mouse is in. */
-extern Lisp_Object Vmouse_screen_part;
-
-extern void pixel_to_glyph_translation ();
extern int buffer_posn_from_coords ();
/* Symbols from xfns.c to denote the different parts of a window. */
}
#endif
-/* Given a pixel position (pix_x, pix_y) on the screen s, return
- character co-ordinates in (*x, *y). */
-void
-pixel_to_glyph_translation (s, pix_x, pix_y, x, y)
+\f
+/* Mouse clicks and mouse movement. Rah. */
+#ifdef HAVE_X11
+
+/* Given a pixel position (PIX_X, PIX_Y) on the screen S, return
+ glyph co-ordinates in (*X, *Y). Set *BOUNDS to the rectangle
+ that the glyph at X, Y occupies, if BOUNDS != 0. */
+static void
+pixel_to_glyph_coords (s, pix_x, pix_y, x, y, bounds)
SCREEN_PTR s;
register unsigned int pix_x, pix_y;
register int *x, *y;
+ XRectangle *bounds;
{
- register struct screen_glyphs *s_glyphs = SCREEN_CURRENT_GLYPHS (s);
- register int line = SCREEN_HEIGHT (s) - 1;
int ibw = s->display.x->internal_border_width;
+ int width, height;
+ FONT_TYPE *font = s->display.x->font;
+
+ width = FONT_WIDTH (font);
+ height = FONT_HEIGHT (font);
/* What line is it on? */
- line = SCREEN_HEIGHT (s) - 1;
- while (s_glyphs->top_left_y[line] > pix_y)
- line--;
- *y = line;
+ if (pix_y < ibw)
+ *y = 0;
+ else if (pix_y > s->display.x->pixel_height - ibw)
+ *y = SCREEN_HEIGHT (s) - 1;
+ else
+ *y = (pix_y - ibw) / height;
- /* Horizontally, is it in the border? */
+ /* And what column? */
if (pix_x < ibw)
*x = 0;
-
- /* If it's off the right edge, clip it. */
else if (pix_x > s->display.x->pixel_width - ibw)
*x = SCREEN_WIDTH (s) - 1;
-
- /* It's in the midst of the screen; assume all the characters are
- the same width, and figure the column. */
else
- *x = (pix_x - ibw) / FONT_WIDTH (s->display.x->font);
+ *x = (pix_x - ibw) / width;
+
+ if (bounds)
+ {
+ bounds->width = width;
+ bounds->height = height;
+ bounds->x = ibw + (*x * width);
+ bounds->y = ibw + (*y * height);
+ }
}
-\f
-#ifdef HAVE_X11
/* Any buttons grabbed. */
unsigned int x_mouse_grabbed;
otherwise. */
result->kind = no_event;
XSET (result->code, Lisp_Int, event->button);
+ result->timestamp = event->time;
result->modifiers = (x_convert_modifiers (event->state)
| (event->type == ButtonRelease ? up_modifier : 0));
- XSET (result->timestamp, Lisp_Int, (event->time & 0x7fffff));
/* Notice if the mouse is still grabbed. */
if (event->type == ButtonPress)
{
if (! x_mouse_grabbed)
Vmouse_depressed = Qt;
- x_mouse_grabbed |= event->button;
+ x_mouse_grabbed |= (1 << event->button);
}
else if (event->type == ButtonRelease)
{
- x_mouse_grabbed &= ~(event->button);
+ x_mouse_grabbed &= ~(1 << event->button);
if (!x_mouse_grabbed)
Vmouse_depressed = Qnil;
}
{
int row, column;
- pixel_to_glyph_translation (s,
- event->x, event->y,
- &column, &row);
-
+ pixel_to_glyph_coords (s, event->x, event->y, &column, &row, NULL);
result->kind = mouse_click;
result->x = column;
result->y = row;
}
+/* Mouse movement. Rah.
+
+ In order to avoid asking for motion events and then throwing most
+ of them away or busy-polling the server for mouse positions, we ask
+ the server for pointer motion hints. This means that we get only
+ one event per group of mouse movements. "Groups" are delimited by
+ other kinds of events (focus changes and button clicks, for
+ example), or by XQueryPointer calls; when one of these happens, we
+ get another MotionNotify event the next time the mouse moves. This
+ is at least as efficient as getting motion events when mouse
+ tracking is on, and I suspect only negligibly worse when tracking
+ is off.
+
+ The silly O'Reilly & Associates Nutshell guides barely document
+ pointer motion hints at all (I think you have to infer how they
+ work from an example), and the description of XQueryPointer doesn't
+ mention that calling it causes you to get another motion hint from
+ the server, which is very important. */
+
+/* Where the mouse was last time we reported a mouse event. */
+static SCREEN_PTR last_mouse_screen;
+static XRectangle last_mouse_glyph;
+
+/* This is a hack. We would really prefer that XTmouse_position would
+ return the time associated with the position it returns, but there
+ doesn't seem to be any way to wrest the timestamp from the server
+ along with the position query. So, we just keep track of the time
+ of the last movement we received, and return that in hopes that
+ it's somewhat accurate. */
+static Time last_mouse_movement_time;
+
+/* Function to report a mouse movement to the mainstream Emacs code.
+ The input handler calls this.
+
+ We have received a mouse movement event, which is given in *event.
+ If the mouse is over a different glyph than it was last time, tell
+ the mainstream emacs code by setting mouse_moved. If not, ask for
+ another motion event, so we can check again the next time it moves. */
+static void
+note_mouse_position (screen, event)
+ SCREEN_PTR screen;
+ XMotionEvent *event;
+
+{
+ last_mouse_movement_time = event->time;
+
+ /* Has the mouse moved off the glyph it was on at the last sighting? */
+ 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)
+ mouse_moved = 1;
+ else
+ {
+ /* It's on the same glyph. Call XQueryPointer so we'll get an
+ event the next time the mouse moves and we can see if it's
+ *still* on the same glyph. */
+ int dummy;
+
+ XQueryPointer (event->display, event->window,
+ (Window *) &dummy, (Window *) &dummy,
+ &dummy, &dummy, &dummy, &dummy,
+ (unsigned int *) &dummy);
+ }
+}
+
+/* Return the current position of the mouse.
+
+ This clears the mouse_moved flag, so we can wait for the next mouse
+ position. This also calls XQueryPointer, which will cause the
+ server to give us another MotionNotify when the mouse moves again.
+ */
+
+static void
+XTmouse_position (s, x, y, time)
+ SCREEN_PTR *s;
+ Lisp_Object *x, *y;
+ unsigned long *time;
+{
+ int ix, iy, dummy;
+ Display *d = x_current_display;
+ Window guess, root, child;
+
+ BLOCK_INPUT;
+
+ /* I would like to have an X function that just told me the
+ innermost window containing the mouse.
+
+ /* There doesn't seem to be any way to just get the innermost window
+ containing the pointer, no matter what X screen it's on; you have
+ to guess a window, and then X will tell you which one of that
+ window's children it's in. If the pointer isn't in any of that
+ window's children, it gives you a root window that contains it.
+
+ So we start with the selected screen's window and chase down
+ branches under the guidance of XQueryPointer until we hit a leaf
+ (all of the Emacs windows we care about are leaf windows). If at
+ any time XQueryPointer returns false, that means that the current
+ window does not contain the pointer any more (perhaps it moved),
+ so we start with the root window XQueryPointer has given us and
+ start again. */
+
+ guess = selected_screen->display.x->window_desc;
+ for (;;)
+ if (XQueryPointer (d, guess, &root, &child,
+ &dummy, &dummy, &ix, &iy, (unsigned int *) &dummy))
+ {
+ if (child == None)
+ /* Guess is a leaf window, and it contains the pointer. */
+ break;
+ else
+ guess = child;
+ }
+ else
+ /* When XQueryPointer returns False, the pointer isn't in guess
+ anymore, but root is the root window of the screen we should
+ try instead. */
+ guess = root;
+
+ *s = last_mouse_screen = x_window_to_screen (guess);
+ if (! *s)
+ *x = *y = Qnil;
+ else
+ {
+ pixel_to_glyph_coords (*s, ix, iy, &ix, &iy, &last_mouse_glyph);
+ XSET (*x, Lisp_Int, ix);
+ XSET (*y, Lisp_Int, iy);
+ }
+
+ mouse_moved = 0;
+
+ /* I don't know how to find the time for the last movement; it seems
+ like XQueryPointer ought to return it, but it doesn't. So, we'll
+ return the time of the last MotionNotify event we received. Note
+ that the use of motion hints means that this isn't guaranteed to
+ be accurate at all. */
+ *time = last_mouse_movement_time;
+
+ UNBLOCK_INPUT;
+}
+
+\f
static char *events[] =
{
"0: ERROR!",
"1: REPLY",
"KeyPress",
- "KeyRelease",
- "ButtonPress",
- "ButtonRelease",
- "MotionNotify",
- "EnterNotify",
- "LeaveNotify",
- "FocusIn",
- "FocusOut",
- "KeymapNotify",
- "Expose",
- "GraphicsExpose",
- "NoExpose",
- "VisibilityNotify",
- "CreateNotify",
- "DestroyNotify",
- "UnmapNotify",
- "MapNotify",
- "MapRequest",
- "ReparentNotify",
- "ConfigureNotify",
- "ConfigureRequest",
- "GravityNotify",
- "ResizeRequest",
- "CirculateNotify",
- "CirculateRequest",
- "PropertyNotify",
- "SelectionClear",
- "SelectionRequest",
- "SelectionNotify",
- "ColormapNotify",
- "ClientMessage",
- "MappingNotify",
- "LASTEvent"
+ "KeyRelease",
+ "ButtonPress",
+ "ButtonRelease",
+ "MotionNotify",
+ "EnterNotify",
+ "LeaveNotify",
+ "FocusIn",
+ "FocusOut",
+ "KeymapNotify",
+ "Expose",
+ "GraphicsExpose",
+ "NoExpose",
+ "VisibilityNotify",
+ "CreateNotify",
+ "DestroyNotify",
+ "UnmapNotify",
+ "MapNotify",
+ "MapRequest",
+ "ReparentNotify",
+ "ConfigureNotify",
+ "ConfigureRequest",
+ "GravityNotify",
+ "ResizeRequest",
+ "CirculateNotify",
+ "CirculateRequest",
+ "PropertyNotify",
+ "SelectionClear",
+ "SelectionRequest",
+ "SelectionNotify",
+ "ColormapNotify",
+ "ClientMessage",
+ "MappingNotify",
+ "LASTEvent"
};
#else /* X10 */
#define XEvent XKeyPressedEvent
#endif /* HAVE_X11 */
-/* Symbols returned in the input stream to indicate various X events. */
-Lisp_Object Qmapped_screen;
-Lisp_Object Qunmapped_screen;
-Lisp_Object Qexited_scrollbar;
-Lisp_Object Qexited_window;
-Lisp_Object Qredraw_screen;
-Lisp_Object Qmouse_click;
-Lisp_Object Qscrollbar_click;
-
/* Timestamp of enter window event. This is only used by XTread_socket,
but we have to put it out here, since static variables within functions
sometimes don't work. */
static Time enter_timestamp;
+/* Communication with window managers. */
+Atom Xatom_wm_protocols;
+
+/* Kinds of protocol things we may receive. */
+Atom Xatom_wm_take_focus;
+Atom Xatom_wm_save_yourself;
+Atom Xatom_wm_delete_window;
+
+/* Other WM communication */
+Atom Xatom_wm_configure_denied; /* When our config request is denied */
+Atom Xatom_wm_window_moved; /* When the WM moves us. */
+
/* Read events coming from the X server.
This routine is called by the SIGIO handler.
We return as soon as there are no more events to be read.
switch (event.type)
{
#ifdef HAVE_X11
+ case ClientMessage:
+ {
+ if (event.xclient.message_type == Xatom_wm_protocols
+ && event.xclient.format == 32)
+ {
+ if (event.xclient.data.l[0] == Xatom_wm_take_focus)
+ {
+ s = x_window_to_screen (event.xclient.window);
+ if (s)
+ x_focus_on_screen (s);
+ /* Not certain about handling scrollbars here */
+ }
+ else if (event.xclient.data.l[0] == Xatom_wm_save_yourself)
+ {
+ /* Save state modify the WM_COMMAND property to
+ something which can reinstate us. This notifies
+ the session manager, who's looking for such a
+ PropertyNotify. Can restart processing when
+ a keyboard or mouse event arrives. */
+ if (numchars > 0)
+ {
+ }
+ }
+ else if (event.xclient.data.l[0] == Xatom_wm_delete_window)
+ {
+ struct screen *s = x_window_to_screen (event.xclient.window);
+
+ if (s)
+ if (numchars > 0)
+ {
+ }
+ }
+ }
+ else if (event.xclient.message_type == Xatom_wm_configure_denied)
+ {
+ }
+ else if (event.xclient.message_type == Xatom_wm_window_moved)
+ {
+ int new_x, new_y;
+
+ new_x = event.xclient.data.s[0];
+ new_y = event.xclient.data.s[1];
+ }
+ }
+ break;
case SelectionClear: /* Someone has grabbed ownership. */
x_disown_selection (event.xselectionclear.window,
disabled; you don't want to spend time updating a
display that won't ever be seen. */
s->visible = 0;
- Vmouse_window = Vmouse_screen_part = Qnil;
x_mouse_x = x_mouse_y = -1;
}
}
KeySym keysym;
XComposeStatus status;
char copy_buffer[80];
+ int modifiers = event.xkey.state;
+
+ /* Some keyboards generate different characters
+ depending on the state of the meta key, in an attempt
+ to support non-English typists. It would be nice to
+ keep this functionality somehow, but for now, we will
+ just clear the meta-key flag to get the 'pure' character. */
+ event.xkey.state &= ~Mod1Mask;
/* This will have to go some day... */
nbytes = XLookupString (&event.xkey,
&keysym,
&status);
+ /* Strip off the vendor-specific keysym bit, and take a shot
+ at recognizing the codes. HP servers have extra keysyms
+ that fit into the MiscFunctionKey category. */
+ keysym &= ~(1<<28);
+
if (numchars > 1)
{
- if (IsCursorKey (keysym) /* >= 0xff50 < 0xff60 */
- || IsMiscFunctionKey (keysym) /* >= 0xff60 < 0xff80 */
- || IsKeypadKey (keysym) /* >= 0xff80 <= 0xffbd */
- || IsFunctionKey (keysym)) /* >= 0xffbe <= 0xffe0 */
+ if (IsCursorKey (keysym) /* 0xff50 <= x < 0xff60 */
+ || IsMiscFunctionKey (keysym) /* 0xff60 <= x < 0xff80 */
+ || IsKeypadKey (keysym) /* 0xff80 <= x < 0xffbe */
+ || IsFunctionKey (keysym)) /* 0xffbe <= x < 0xffe1 */
{
bufp->kind = non_ascii_keystroke;
- bufp->code = (unsigned) keysym - 0xff50;
- bufp->screen = XSCREEN (SCREEN_FOCUS_SCREEN (s));
- bufp->modifiers = x_convert_modifiers (event.xkey.state);
+ XSET (bufp->code, Lisp_Int, (unsigned) keysym - 0xff50);
+ bufp->screen = s;
+ bufp->modifiers = x_convert_modifiers (modifiers);
+ bufp->timestamp = event.xkey.time;
bufp++;
count++;
numchars--;
if (nbytes == 1)
{
- if (event.xkey.state & Mod1Mask)
+ if (modifiers & Mod1Mask)
*copy_buffer |= METABIT;
bufp->kind = ascii_keystroke;
- bufp->screen = XSCREEN (SCREEN_FOCUS_SCREEN (s));
XSET (bufp->code, Lisp_Int, *copy_buffer);
+ bufp->screen = s;
+ bufp->timestamp = event.xkey.time;
bufp++;
}
else
{
bufp->kind = ascii_keystroke;
XSET (bufp->code, Lisp_Int, copy_buffer[i]);
- bufp->screen = XSCREEN (SCREEN_FOCUS_SCREEN (s));
+ bufp->screen = s;
+ bufp->timestamp = event.xkey.time;
bufp++;
}
{
bufp->kind = ascii_keystroke;
XSET (bufp->code, Lisp_Int, where_mapping[i]);
- bufp->screen = XSCREEN (SCREEN_FOCUS_SCREEN (s));
+ XSET (bufp->time, Lisp_Int, event.xkey.time);
+ bufp->screen = s;
bufp++;
}
count += nbytes;
break; /* Entering our own subwindow. */
{
- extern int waiting_for_input;
struct screen *old_s = x_input_screen;
s = x_window_to_screen (event.window);
x_mouse_screen = s;
- if (waiting_for_input && x_focus_screen == 0)
- x_new_focus_screen (s);
+ x_new_focus_screen (s);
}
break;
{
s = x_window_to_screen (event.xmotion.window);
if (s)
- {
- int row, column;
-
- pixel_to_glyph_translation (s,
- event.xmotion.x, event.xmotion.y,
- &column, &row);
-
- note_mouse_position (s, column, row, event.xmotion.time);
- }
+ note_mouse_position (s, &event.xmotion);
#if 0
else if ((s = x_window_to_scrollbar (event.xmotion.window,
&part, &prefix)))
- s->display.x->h_scrollbar_height)
/ FONT_HEIGHT (s->display.x->font));
- if (columns != s->width || rows != s->height)
+ /* Even if the number of character rows and columns has
+ not changed, the font size may have changed, so we need
+ to check the pixel dimensions as well. */
+ if (columns != s->width
+ || rows != s->height
+ || event.xconfigure.width != s->display.x->pixel_width
+ || event.xconfigure.height != s->display.x->pixel_height)
{
- XEvent ignored_event;
-
change_screen_size (s, rows, columns, 0);
x_resize_scrollbars (s);
SET_SCREEN_GARBAGED (s);
-#if 0
- dumprectangle (s, 0, 0, PIXEL_WIDTH (s), PIXEL_HEIGHT (s));
- /* Throw away the exposures generated by this reconfigure. */
- while (XCheckWindowEvent (x_current_display,
- event.xconfigure.window,
- ExposureMask, &ignored_event)
- == True);
-#endif
}
- s->display.x->left_pos = event.xconfigure.x;
- s->display.x->top_pos = event.xconfigure.y;
s->display.x->pixel_width = event.xconfigure.width;
s->display.x->pixel_height = event.xconfigure.height;
+ s->display.x->left_pos = event.xconfigure.x;
+ s->display.x->top_pos = event.xconfigure.y;
break;
}
{
bufp->kind = ascii_keystroke;
bufp->code = (char) 'X' & 037; /* C-x */
- bufp->screen = XSCREEN (SCREEN_FOCUS_SCREEN (s));
+ bufp->screen = s;
+ XSET (bufp->time, Lisp_Int, event.xkey.time);
bufp++;
bufp->kind = ascii_keystroke;
bufp->code = (char) 0; /* C-@ */
- bufp->screen = XSCREEN (SCREEN_FOCUS_SCREEN (s));
+ bufp->screen = s;
+ XSET (bufp->time, Lisp_Int, event.xkey.time);
bufp++;
count += 2;
int mask = 1 << fd;
if (0 != select (fd + 1, &mask, (long *) 0, (long *) 0,
- (struct timeval *) 0)
+ (EMACS_TIME) 0)
&& !XStuffPending ())
kill (getpid (), SIGHUP);
}
}
#endif /* HAVE_X11 */
-static int
-XTmouse_tracking_enable (enable)
- int enable;
-{
- Lisp_Object tail;
-
- /* Go through the list of screens and turn on/off mouse tracking for
- each of them. */
- for (tail = Vscreen_list; CONSP (tail); tail = XCONS (tail)->cdr)
- {
- if (XTYPE (XCONS (tail)->car) != Lisp_Screen)
- abort ();
- if (XSCREEN (XCONS (tail)->car)->output_method == output_x_window)
- XSelectInput (x_current_display,
- XSCREEN (XCONS (tail)->car)->display.x->window_desc,
- (enable
- ? (STANDARD_EVENT_SET
- | PointerMotionMask
- | ButtonReleaseMask)
- : STANDARD_EVENT_SET));
- }
-}
-
-
-static Lisp_Object
-XTmouse_position ()
-{
-
-}
-
-
\f
/* Draw a hollow box cursor. Don't change the inside of the box. */
s->phys_cursor_x = -1;
}
+static void
x_display_bar_cursor (s, on)
struct screen *s;
int on;
}
-/* Redraw the glyph at ROW, COLUMN on screen S, in the style HIGHLIGHT.
- If there is no character there, erase the area. HIGHLIGHT is as
- defined for dumpglyphs. */
+/* Redraw the glyph at ROW, COLUMN on screen S, in the style
+ HIGHLIGHT. HIGHLIGHT is as defined for dumpglyphs. Return the
+ glyph drawn. */
static void
-x_draw_single_glyph (s, row, column, highlight)
+x_draw_single_glyph (s, row, column, glyph, highlight)
struct screen *s;
int row, column;
+ GLYPH glyph;
int highlight;
{
- register struct screen_glyphs *current_screen = SCREEN_CURRENT_GLYPHS (s);
-
- /* If there is supposed to be a character there, redraw it
- in that line's normal video. */
- if (current_screen->enable[row]
- && column < current_screen->used[row])
- dumpglyphs (s,
- (column * FONT_WIDTH (s->display.x->font)
- + s->display.x->internal_border_width),
- (row * FONT_HEIGHT (s->display.x->font)
- + s->display.x->internal_border_width),
- ¤t_screen->glyphs[row][column],
- 1, highlight, s->display.x->font);
- else
- {
-#ifdef HAVE_X11
- static GLYPH a_space_glyph = SPACEGLYPH;
- dumpglyphs (s,
- (column * FONT_WIDTH (s->display.x->font)
- + s->display.x->internal_border_width),
- (row * FONT_HEIGHT (s->display.x->font)
- + s->display.x->internal_border_width),
- &a_space_glyph, 1, highlight, s->display.x->font);
-#else
- XPixSet (s->display.x->window_desc,
- (column * FONT_WIDTH (s->display.x->font)
- + s->display.x->internal_border_width),
- (row * FONT_HEIGHT (s->display.x->font)
- + s->display.x->internal_border_width),
- FONT_WIDTH (s->display.x->font),
- FONT_HEIGHT (s->display.x->font),
- (highlight == 0
- ? s->display.x->background_pixel
- : (highlight == 1
- ? s->display.x->foreground_pixel
- : s->display.x->cursor_pixel)));
-#endif /* HAVE_X11 */
- }
+ dumpglyphs (s,
+ (column * FONT_WIDTH (s->display.x->font)
+ + s->display.x->internal_border_width),
+ (row * FONT_HEIGHT (s->display.x->font)
+ + s->display.x->internal_border_width),
+ &glyph, 1, highlight, s->display.x->font);
}
/* Turn the displayed cursor of screen S on or off according to ON.
struct screen *s;
int on;
{
+ struct screen_glyphs *current_glyphs = SCREEN_CURRENT_GLYPHS (s);
+
+ /* If we're not updating, then we want to use the current screen's
+ cursor position, not our local idea of where the cursor ought to be. */
+ if (s != updating_screen)
+ {
+ curs_x = SCREEN_CURSOR_X (s);
+ curs_y = SCREEN_CURSOR_Y (s);
+ }
+
if (! s->visible)
return;
/* If cursor is off and we want it off, return quickly. */
-
if (!on && s->phys_cursor_x < 0)
return;
erase it. */
if (s->phys_cursor_x >= 0
&& (!on
- || s->phys_cursor_x != s->cursor_x
- || s->phys_cursor_y != s->cursor_y
+ || s->phys_cursor_x != curs_x
+ || s->phys_cursor_y != curs_y
|| (s->display.x->text_cursor_kind != hollow_box_cursor
&& (s != x_highlight_screen))))
{
/* Erase the cursor by redrawing the character underneath it. */
x_draw_single_glyph (s, s->phys_cursor_y, s->phys_cursor_x,
- (SCREEN_CURRENT_GLYPHS (s)
- ->highlight[s->phys_cursor_y]));
-
+ s->phys_cursor_glyph,
+ current_glyphs->highlight[s->phys_cursor_y]);
s->phys_cursor_x = -1;
}
|| (s->display.x->text_cursor_kind != filled_box_cursor
&& s == x_highlight_screen)))
{
+ s->phys_cursor_glyph
+ = ((current_glyphs->enable[curs_y]
+ && curs_x < current_glyphs->used[curs_y])
+ ? current_glyphs->glyphs[curs_y][curs_x]
+ : SPACEGLYPH);
if (s != x_highlight_screen)
{
x_draw_box (s);
}
else
{
- x_draw_single_glyph (s, s->cursor_y, s->cursor_x, 2);
+ x_draw_single_glyph (s, curs_y, curs_x,
+ s->phys_cursor_glyph, 2);
s->display.x->text_cursor_kind = filled_box_cursor;
}
- s->phys_cursor_x = s->cursor_x;
- s->phys_cursor_y = s->cursor_y;
+ s->phys_cursor_x = curs_x;
+ s->phys_cursor_y = curs_y;
}
if (updating_screen != s)
char *X_DefaultValue;
Bitmap b1;
-#if 0 /* This doesn't seem to be used, but I can't quite believe it. */
- static Pixmap grey_pixmap;
-#endif
-
#ifndef WhitePixel
#define WhitePixel 1
#endif
if (icon_font_info == 0)
icon_font_info
- = XGetFont (XGetDefault (XDISPLAY invocation_name, "BodyFont"));
+ = XGetFont (XGetDefault (XDISPLAY
+ (char *) XSTRING (invocation_name)->data,
+ "BodyFont"));
#ifdef HAVE_X11
if (icon_name)
return 0;
}
\f
+/* Handling X errors. */
+
+/* A handler for SIGPIPE, when it occurs on the X server's connection.
+ This basically does an orderly shutdown of Emacs. */
+static SIGTYPE
+x_death_handler ()
+{
+ if (_Xdebug)
+ abort ();
+ else
+ Fkill_emacs (make_number (70));
+}
+
static char *x_proto_requests[] =
{
"CreateWindow",
}
UNBLOCK_INPUT;
- if (_Xdebug)
- abort ();
- else
- Fkill_emacs (make_number (70));
+ x_death_handler ();
}
-/* Initialize communication with the X window server. */
-
#if 0
static unsigned int x_wire_count;
x_trace_wire ()
if (n_matching_fonts == 0)
return 1;
- /* See if we've already loaded this font. */
+ /* See if we've already loaded a matching font. */
{
int i, j;
/* If we have, just return it from the table. */
if (already_loaded)
- {
- s->display.x->font = x_font_table[already_loaded];
- }
-
+ s->display.x->font = x_font_table[already_loaded];
+
/* Otherwise, load the font and add it to the table. */
else
{
/* Do we need to grow the table? */
else if (n_fonts >= x_font_table_size)
{
- x_font_table_size <<= 1;
+ x_font_table_size *= 2;
x_font_table
= (XFontStruct **) xrealloc (x_font_table,
(x_font_table_size
{
int mask;
- if (s->visible)
- {
- BLOCK_INPUT;
- XRaiseWindow (XDISPLAY s->display.x->window_desc);
- XFlushQueue ();
- UNBLOCK_INPUT;
- return;
- }
-
BLOCK_INPUT;
-#ifdef HAVE_X11
- if (! EQ (Vx_no_window_manager, Qt))
- x_wm_set_window_state (s, NormalState);
-
- XMapWindow (XDISPLAY s->display.x->window_desc);
- if (s->display.x->v_scrollbar != 0 || s->display.x->h_scrollbar != 0)
- XMapSubwindows (x_current_display, s->display.x->window_desc);
+ if (! SCREEN_VISIBLE_P (s))
+ {
+#ifdef HAVE_X11
+ if (! EQ (Vx_no_window_manager, Qt))
+ x_wm_set_window_state (s, NormalState);
+ XMapWindow (XDISPLAY s->display.x->window_desc);
+ if (s->display.x->v_scrollbar != 0 || s->display.x->h_scrollbar != 0)
+ XMapSubwindows (x_current_display, s->display.x->window_desc);
#else
- XMapWindow (XDISPLAY s->display.x->window_desc);
- if (s->display.x->icon_desc != 0)
- XUnmapWindow (s->display.x->icon_desc);
+ XMapWindow (XDISPLAY s->display.x->window_desc);
+ if (s->display.x->icon_desc != 0)
+ XUnmapWindow (s->display.x->icon_desc);
- /* Handled by the MapNotify event for X11 */
- s->visible = 1;
- s->iconified = 0;
+ /* Handled by the MapNotify event for X11 */
+ s->visible = 1;
+ s->iconified = 0;
- /* NOTE: this may cause problems for the first screen. */
- XTcursor_to (0, 0);
-#endif /* not HAVE_X11 */
+ /* NOTE: this may cause problems for the first screen. */
+ XTcursor_to (0, 0);
+#endif /* not HAVE_X11 */
+ }
- XRaiseWindow (XDISPLAY s->display.x->window_desc);
XFlushQueue ();
+
UNBLOCK_INPUT;
}
Window window = s->display.x->window_desc;
size_hints.flags = PResizeInc | PMinSize | PMaxSize;
+#ifdef PBaseSize
+ size_hints.flags |= PBaseSize;
+#endif
flexlines = s->height;
}
\f
-static void
-init_input_symbols ()
-{
- Qmapped_screen = intern ("mapped-screen");
- Qunmapped_screen = intern ("unmapped-screen");
- Qexited_scrollbar = intern ("exited-scrollbar");
- Qexited_window = intern ("exited-window");
- Qredraw_screen = intern ("redraw-screen");
- Qmouse_moved = intern ("mouse-moved");
- Qmouse_click = intern ("mouse-click");
- Qscrollbar_click = intern ("scrollbar-click");
-}
-
void
x_term_init (display_name)
char *display_name;
XSetAfterFunction (x_current_display, x_trace_wire);
#endif
- invocation_name = (char *)
- XSTRING (Ffile_name_nondirectory (Fcar (Vcommand_line_args)))->data;
+ invocation_name = Ffile_name_nondirectory (Fcar (Vcommand_line_args));
/* Try to get the host name; if the buffer is too short, try
again. Apparently, the only indication gethostname gives of
hostname_size <<= 1;
hostname = (char *) xrealloc (hostname, hostname_size);
}
- id_name = (char *) xmalloc (strlen (invocation_name)
+ x_id_name = (char *) xmalloc (XSTRING (invocation_name)->size
+ strlen (hostname)
+ 2);
- sprintf (id_name, "%s@%s", invocation_name, hostname);
+ sprintf (x_id_name, "%s@%s", XSTRING (invocation_name)->data, hostname);
}
dup2 (ConnectionNumber (x_current_display), 0);
cursor_to_hook = XTcursor_to;
reassert_line_highlight_hook = XTreassert_line_highlight;
screen_rehighlight_hook = XTscreen_rehighlight;
- mouse_tracking_enable_hook = XTmouse_tracking_enable;
+ mouse_position_hook = XTmouse_position;
scroll_region_ok = 1; /* we'll scroll partial screens */
char_ins_del_ok = 0; /* just as fast to write the line */
off the bottom */
baud_rate = 19200;
- init_input_symbols ();
-
XHandleError (x_error_handler);
XHandleIOError (x_error_handler);
signal (SIGWINCH, SIG_DFL);
#endif /* SIGWINCH */
- signal (SIGPIPE, x_error_handler);
+ signal (SIGPIPE, x_death_handler);
+}
+
+void
+syms_of_xterm ()
+{
+ staticpro (&invocation_name);
+ invocation_name = Qnil;
}
#endif /* HAVE_X11 */
#endif /* HAVE_X_WINDOWS */