diff options
Diffstat (limited to 'src/xterm.c')
-rw-r--r-- | src/xterm.c | 1933 |
1 files changed, 1933 insertions, 0 deletions
diff --git a/src/xterm.c b/src/xterm.c new file mode 100644 index 00000000000..7d946a76a76 --- /dev/null +++ b/src/xterm.c @@ -0,0 +1,1933 @@ +/* X Communication module for terminals which understand the X protocol. + Copyright (C) 1985, 1986, 1987, 1988 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) +any later version. + +GNU Emacs is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Emacs; see the file COPYING. If not, write to +the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ + +/* Written by Yakim Martillo, mods and things by Robert Krawitz */ + +/* + * $Source: /u2/third_party/gnuemacs.chow/src/RCS/xterm.c,v $ + * $Author: rlk $ + * $Locker: $ + * $Header: xterm.c,v 1.28 86/08/27 13:30:57 rlk Exp $ + */ + +#ifndef lint +static char *rcsid_TrmXTERM_c = "$Header: xterm.c,v 1.28 86/08/27 13:30:57 rlk Exp $"; +#endif lint + +/* On 4.3 this loses if it comes after xterm.h. */ +#include <signal.h> +#include "config.h" + +#ifdef HAVE_X_WINDOWS + +#include "lisp.h" +#undef NULL + +/* This may include sys/types.h, and that somehow loses + if this is not done before the other system files. */ +#include "xterm.h" + +/* Load sys/types.h if not already loaded. + In some systems loading it twice is suicidal. */ +#ifndef makedev +#include <sys/types.h> +#endif + +#if !defined(USG) || defined(IBMRTAIX) +#include <sys/time.h> +#else +#include <time.h> +#endif /* USG and not IBMRTAIX */ + +#include <sys/ioctl.h> +#include <fcntl.h> +#include <stdio.h> +#include <ctype.h> +#include <errno.h> +#ifdef BSD +#include <strings.h> +#endif +#include <sys/stat.h> + +#include "dispextern.h" +#include "termhooks.h" +#include "termopts.h" +#include "termchar.h" +#include "sink.h" +#include "sinkmask.h" +#include <X/Xkeyboard.h> +/*#include <X/Xproto.h> */ + +/* Allow m- file to inhibit use of FIONREAD. */ +#ifdef BROKEN_FIONREAD +#undef FIONREAD +#endif + +/* We are unable to use interrupts if FIONREAD is not available, + so flush SIGIO so we won't try. */ +#ifndef FIONREAD +#ifdef SIGIO +#undef SIGIO +#endif +#endif + +/* Allow config to specify default font. */ +#ifndef X_DEFAULT_FONT +#define X_DEFAULT_FONT "vtsingle" +#endif + +#define min(a,b) ((a)<(b) ? (a) : (b)) +#define max(a,b) ((a)>(b) ? (a) : (b)) +#define sigunblockx(sig) sigblock (0) +#define sigblockx(sig) sigblock (1 << ((sig) - 1)) +XREPBUFFER Xxrepbuffer; +int pixelwidth; +int pixelheight; +int PendingExposure; +int PendingIconExposure; +#define MAXICID 80 +char iconidentity[MAXICID]; +#define ICONTAG "emacs@" +#define METABIT 0x80 +Window XXIconWindow; +Bitmap XXIconMask; + +char *XXcurrentfont; +char *default_window; +int informflag; +extern int initialized; + +extern char *alternate_display; + +int XXdebug; +int XXpid; +extern int screen_garbaged; +int XXxoffset, XXyoffset; +int IconWindow; + +int WindowMapped; +int CurHL; + +static int flexlines; /* last line affect by dellines or */ + /* inslines functions */ +extern int errno; +int VisibleX, VisibleY; /* genuine location of cursor on screen */ + /* if it is there */ +static int SavedX, SavedY; /* Where the cursor was before update */ + /* started */ + +int bitblt; /* Used to track bit blt events */ +int CursorExists; /* during updates cursor is turned off */ +static int InUpdate; /* many of functions here may be invoked */ + /* even if no update in progress, when */ + /* no update is in progress the action */ + /* can be slightly different */ + +short MouseCursor[] = { + 0x0000, 0x0008, 0x0018, 0x0038, + 0x0078, 0x00f8, 0x01f8, 0x03f8, + 0x07f8, 0x00f8, 0x00d8, 0x0188, + 0x0180, 0x0300, 0x0300, 0x0000}; + +short MouseMask[] = { + 0x000c, 0x001c, 0x003c, 0x007c, + 0x00fc, 0x01fc, 0x03fc, 0x07fc, + 0x0ffc, 0x0ffc, 0x01fc, 0x03dc, + 0x03cc, 0x0780, 0x0780, 0x0300}; + +Display *XXdisplay; +FontInfo *fontinfo; +Window XXwindow; +Cursor EmacsCursor; + +char *fore_color; /* Variables to store colors */ +char *back_color; +char *brdr_color; +char *curs_color; +char *mous_color; + +int fore; +int back; +int brdr; +int curs; +int mous; + +static WindowInfo windowinfo; +WindowInfo rootwindowinfo; + + + +static XKeyPressedEvent XXEvent; /* as X messages are read in they are */ + /* stored here */ +static XREPBUFFER XXqueue;/* Used for storing up ExposeRegion */ + /* replies, so that the SIGIO inter- */ + /* rupt serving routines do almost */ + /* no writes to the X socket */ +/*int CurHL; /* Current Highlighting actually being */ + /* being used for bold font right now*/ + +int XXborder; +int XXInternalBorder; + +int (*handler)(); + +extern Display *XOpenDisplay (); +extern Window XCreateWindow (); +extern Cursor XDefineCursor (); +extern Cursor XCreateCursor (); +extern FontInfo *XOpenFont (); + +static int flashback (); + + +/* HLmode -- Changes the GX function for output strings. Could be used to + * change font. Check an XText library function call. + */ + +static +HLmode (new) + int new; +{ + CurHL = new; +} + + +/* External interface to control of standout mode. + Call this when about to modify line at position VPOS + and not change whether it is highlighted. */ + +XTreassert_line_highlight (highlight, vpos) + int highlight, vpos; +{ + HLmode (highlight); +} + +/* Call this when about to modify line at position VPOS + and change whether it is highlighted. */ + +static +XTchange_line_highlight (new_highlight, vpos, first_unused_hpos) + int new_highlight, vpos, first_unused_hpos; +{ + HLmode (new_highlight); + XTmove_cursor (vpos, 0); + x_clear_end_of_line (0); +} + + +/* Used for starting or restarting (after suspension) the X window. Puts the + * cursor in a known place, update does not begin with this routine but only + * with a call to redisplay. The mouse cursor is warped into the window and + * then the cursor is turned on. + */ + + + +static +XTset_terminal_modes () +{ + int stuffpending; +#ifdef XDEBUG + fprintf (stderr, "XTset_terminal_modes\n"); +#endif + InUpdate = 0; + stuffpending = 0; + if (!initialized) + { + CursorExists = 0; + VisibleX = 0; + VisibleY = 0; + } + XTclear_screen (); +#ifdef FIONREAD + ioctl (0, FIONREAD, &stuffpending); + if (stuffpending) + SIGNAL_INPUT (); +#endif +} + +/* XTmove_cursor moves the cursor to the correct location and checks whether an update + * is in progress in order to toggle it on. + */ + +static +XTmove_cursor (row, col) + register int row, col; +{ + BLOCK_INPUT_DECLARE () + + BLOCK_INPUT (); +#ifdef XDEBUG + fprintf (stderr, "XTmove_cursor\n"); +#endif + cursor_hpos = col; + cursor_vpos = row; + if (InUpdate) + { + if (CursorExists) + { + CursorToggle (); + } + UNBLOCK_INPUT (); + return; /* Generally, XTmove_cursor will be invoked */ + /* when InUpdate with !CursorExists */ + /* so that wasteful XFlush is not called */ + } + if ((row == VisibleY) && (col == VisibleX)) + { + if (!CursorExists) + { + CursorToggle (); + } + XFlush (); + UNBLOCK_INPUT (); + return; + } + if (CursorExists) CursorToggle (); + VisibleX = col; + VisibleY = row; + if (!CursorExists) CursorToggle (); + XFlush (); + UNBLOCK_INPUT (); +} + +/* Used to get the terminal back to a known state after resets. Usually + * used when restarting suspended or waiting emacs + */ + +static +cleanup () +{ + inverse_video = 0; + HLmode (0); +} + +/* Erase current line from column cursor_hpos to column END. + Leave cursor at END. */ + +static +XTclear_end_of_line (end) + register int end; +{ + register int numcols; + +#ifdef XDEBUG + fprintf (stderr, "XTclear_end_of_line\n"); + +#endif + if (cursor_vpos < 0 || cursor_vpos >= screen_height) + { + return; + } + + if (end >= screen_width) + end = screen_width; + if (end <= cursor_hpos) + return; + + numcols = end - cursor_hpos; + { + BLOCK_INPUT_DECLARE () + + BLOCK_INPUT (); + if (cursor_vpos == VisibleY && VisibleX >= cursor_hpos && VisibleX < end) + { + if (CursorExists) CursorToggle (); + } + XPixSet (XXwindow, + cursor_hpos * fontinfo->width + XXInternalBorder, + cursor_vpos * fontinfo->height+XXInternalBorder, + fontinfo->width * numcols, + fontinfo->height, + back); + XTmove_cursor (cursor_vpos, end); + UNBLOCK_INPUT (); + } +} + +/* Erase current line from column START to right margin. + Leave cursor at START. */ + +static +x_clear_end_of_line (start) + register int start; +{ + register int numcols; + +#ifdef XDEBUG + fprintf (stderr, "x_clear_end_of_line\n"); + +#endif + if (cursor_vpos < 0 || cursor_vpos >= screen_height) + { + return; + } + + if (start < 0) + start = 0; + if (start >= screen_width) + return; + + numcols = screen_width - start; + { + BLOCK_INPUT_DECLARE () + + BLOCK_INPUT (); + if (cursor_vpos == VisibleY && VisibleX >= start) + { + if (CursorExists) CursorToggle (); + } + XPixSet (XXwindow, + start * fontinfo->width + XXInternalBorder, + cursor_vpos * fontinfo->height+XXInternalBorder, + fontinfo->width * numcols, + fontinfo->height, + back); + XTmove_cursor (cursor_vpos, start); + UNBLOCK_INPUT (); + } +} + +static +XTreset_terminal_modes () +{ +#ifdef XDEBUG + fprintf (stderr, "XTreset_terminal_modes\n"); +#endif + XTclear_screen (); +} + +static +XTclear_screen () +{ +#ifdef XDEBUG + fprintf (stderr, "XTclear_screen\n"); +#endif + HLmode (0); + CursorExists = 0; + + cursor_hpos = 0; + cursor_vpos = 0; + SavedX = 0; + SavedY = 0; + VisibleX = 0; + VisibleY = 0; + { + BLOCK_INPUT_DECLARE () + + BLOCK_INPUT (); + XClear (XXwindow); + CursorToggle (); + if (!InUpdate) + XFlush (); + UNBLOCK_INPUT (); + } +} + +/* used by dumprectangle which is usually invoked upon ExposeRegion + * events which come from bit blt's or moving an obscuring opaque window + */ + +static +dumpchars (current_screen, numcols, tempX, tempY, tempHL) + register struct matrix *current_screen; + register int numcols; + register int tempX, tempY, tempHL; +{ + if (numcols <= 0) return; + if (((numcols - 1) + tempX) > screen_width) + { + numcols = (screen_width - tempX) + 1; + } + if ((tempX < 0) || (tempX >= screen_width) || + (tempY < 0) || (tempY >= screen_height)) + { + return; + } + XText (XXwindow, + (tempX * fontinfo->width+XXInternalBorder), + (tempY * fontinfo->height+XXInternalBorder), + ¤t_screen->contents[tempY][tempX], + numcols, + fontinfo->id, + (tempHL ? back : fore), + (tempHL ? fore : back)); +} + +/* When a line has been changed this function is called. X is so fast + * that the actual sequence is ignore. Rather, the new version of the + * line is simply output if this function is invoked while in UpDate. + * Sometimes writechars can be invoked when not in update if text is to + * be output at the end of the line. In this case the whole line is not + * output. Simply the new text at the current cursor position given + * by VisibleX,Y. The cursor is moved to the end of the new text. + */ +static +writechars (start, end) + register char *start, *end; +{ + register int temp_length; + BLOCK_INPUT_DECLARE () + + BLOCK_INPUT (); + + if ((cursor_vpos < 0) || (cursor_vpos >= screen_height)) + { + UNBLOCK_INPUT (); + return; + } + if (CursorExists) + { + CursorToggle (); + } + if (InUpdate) + { + if (end != start - 1) + { + XText (XXwindow, + (cursor_hpos * fontinfo->width+XXInternalBorder), + (cursor_vpos * fontinfo->height+XXInternalBorder), + start, + end + 1 - start, + fontinfo->id, + (CurHL ? back : fore), + (CurHL ? fore : back)); + XTmove_cursor (cursor_vpos, cursor_hpos + end - start + 1); + } + } + else + { + if ((VisibleX < 0) || (VisibleX >= screen_width)) + { + UNBLOCK_INPUT (); + return; + } + if ((VisibleY < 0) || (VisibleY >= screen_height)) + { + UNBLOCK_INPUT (); + return; + } + if (((end - start) + VisibleX) >= screen_width) + { + end = start + (screen_width - (VisibleX + 1)); + } + if (end >= start) + { + XText (XXwindow, + (VisibleX * fontinfo->width+XXInternalBorder), + (VisibleY * fontinfo->height+XXInternalBorder), + start, + ((end - start) + 1), + fontinfo->id, + (CurHL ? back : fore), + (CurHL ? fore : back)); + VisibleX = VisibleX + (end - start) + 1; + } + if (!CursorExists) CursorToggle (); + } + UNBLOCK_INPUT (); +} + + +static +XToutput_chars (start, len) + register char *start; + register int len; +{ +#ifdef XDEBUG + fprintf (stderr, "XToutput_chars\n"); +#endif + writechars (start, start + len - 1); +} + +/* The following routine is for the deaf or for the pervert who prefers + * that his terminal flash at him rather than beep at him. + */ + +static int flashedback; + +static +XTflash () +{ +#ifdef ITIMER_REAL + struct itimerval itimer; + +#ifdef XDEBUG + fprintf (stderr, "XTflash\n"); +#endif + + stop_polling (); + signal (SIGALRM, flashback); + getitimer (ITIMER_REAL, &itimer); + itimer.it_value.tv_usec += 250000; + itimer.it_interval.tv_sec = 0; + itimer.it_interval.tv_usec = 0; + flashedback = 0; + setitimer (ITIMER_REAL, &itimer, 0); + { + BLOCK_INPUT_DECLARE () + + BLOCK_INPUT (); + XPixFill (XXwindow, 0, 0, screen_width*fontinfo->width+2*XXInternalBorder, + screen_height * fontinfo->height+2*XXInternalBorder, WhitePixel, + ClipModeClipped, GXinvert, AllPlanes); + XFlush (); + UNBLOCK_INPUT (); + } + while (!flashedback) pause (); +#endif /* have ITIMER_REAL */ +} + +static +flashback () +{ +#ifdef ITIMER_REAL +#ifdef SIGIO + int mask = sigblock (sigmask (SIGIO) | sigmask (SIGALRM)); +#else + int mask = sigblock (sigmask (SIGALRM)); +#endif + XPixFill (XXwindow, 0, 0, screen_width * fontinfo->width+2*XXInternalBorder, + screen_height * fontinfo->height+2*XXInternalBorder, WhitePixel, + ClipModeClipped, GXinvert, AllPlanes); + XFlush (); + flashedback = 1; + sigsetmask (mask); + start_polling (); +#endif /* have ITIMER_REAL */ +} + +/* A kludge to get a bell */ + +static +XTfeep () +{ + BLOCK_INPUT_DECLARE () + + BLOCK_INPUT (); +#ifdef XDEBUG + fprintf (stderr, "XTfeep\n"); +#endif + XFeep (0); + UNBLOCK_INPUT (); +} + +/* Artificially creating a cursor is hard, the actual position on the + * screen (either where it is or last was) is tracked with VisibleX,Y. + * Gnu Emacs code tends to assume a cursor exists in hardward at cursor_hpos,Y + * and that output text will appear there. During updates, the cursor is + * supposed to be blinked out and will only reappear after the update + * finishes. + */ + +CursorToggle () +{ + if (!WindowMapped) + { + CursorExists = 0; + return 0; + } + if ((VisibleX < 0) || (VisibleX >= screen_width) || + (VisibleY < 0) || (VisibleY >= screen_height)) + { /* Current Cursor position trash */ + /* Not much can be done */ + XFlush (); + CursorExists = 0; + return 0; + /* Currently the return values are not */ + /* used, but I could anticipate using */ + /* them in the future. */ + } + + if (current_screen->enable[VisibleY] && + (VisibleX < current_screen->used[VisibleY])) + { + if (CursorExists) + { + XText (XXwindow, + VisibleX * fontinfo->width+XXInternalBorder, + VisibleY * fontinfo->height+XXInternalBorder, + ¤t_screen->contents[VisibleY][VisibleX], 1, + fontinfo->id, + fore, back); + } + else + { + XText (XXwindow, + VisibleX * fontinfo->width+XXInternalBorder, + VisibleY * fontinfo->height+XXInternalBorder, + ¤t_screen->contents[VisibleY][VisibleX], 1, + fontinfo->id, + back, curs); + } + } + else if (CursorExists) + { + XPixSet (XXwindow, + VisibleX * fontinfo->width+XXInternalBorder, + VisibleY * fontinfo->height+XXInternalBorder, + fontinfo->width, fontinfo->height, back); + } + else + { + XPixSet (XXwindow, + VisibleX * fontinfo->width+XXInternalBorder, + VisibleY * fontinfo->height+XXInternalBorder, + fontinfo->width, fontinfo->height, curs); + } + CursorExists = !CursorExists; + /* Cursor has either been blinked in */ + /* or out */ + if (!InUpdate) + { + XFlush (); + } + return 1; +} + +/* This routine is used by routines which are called to paint regions */ +/* designated by ExposeRegion events. If the cursor may be in the exposed */ +/* region, this routine makes sure it is gone so that dumprectangle can */ +/* toggle it back into existance if dumprectangle is invoked when not in */ +/* the midst of a screen update. */ +static +ClearCursor () +{ + BLOCK_INPUT_DECLARE () + + BLOCK_INPUT (); + if (!WindowMapped) + { + CursorExists = 0; + UNBLOCK_INPUT (); + return; + } + if ((VisibleX < 0) || (VisibleX >= screen_width) + || (VisibleY < 0) || (VisibleY >= screen_height)) + { /* Current Cursor position trash */ + /* Not much can be done */ + CursorExists = 0; + UNBLOCK_INPUT (); + return; + } + XPixSet (XXwindow, + VisibleX * fontinfo->width+XXInternalBorder, + VisibleY * fontinfo->height+XXInternalBorder, + fontinfo->width, fontinfo->height, + back); + CursorExists = 0; + UNBLOCK_INPUT (); +} + +static +XTupdate_begin () +{ + BLOCK_INPUT_DECLARE () + + BLOCK_INPUT (); +#ifdef XDEBUG + fprintf (stderr, "XTupdate_begin\n"); +#endif + + InUpdate = 1; + if (CursorExists) + { + CursorToggle (); + } + SavedX = cursor_hpos; /* The initial"hardware" cursor position is */ + /* saved because that is where gnu emacs */ + /* expects the cursor to be at the end of*/ + /* the update */ + SavedY = cursor_vpos; + dumpqueue (); + UNBLOCK_INPUT (); +} + + +static +XTupdate_end () +{ + BLOCK_INPUT_DECLARE () + + BLOCK_INPUT (); +#ifdef XDEBUG + fprintf (stderr, "XTupdate_end\n"); +#endif + if (CursorExists) + CursorToggle (); + InUpdate = 0; + dumpqueue (); + XTmove_cursor (SavedY, SavedX); /* XTmove_cursor invokes cursor toggle */ + UNBLOCK_INPUT (); +} + +/* Used for expose region and expose copy events. Have to get the text + * back into the newly blank areas. + */ + +dumprectangle (top, left, rows, cols) + register int top, left, rows, cols; +{ + register int index; + int localX, localY, localHL; + rows += top; + cols += left; + top /= fontinfo->height; + /* Get row and col containing up and */ + /* left borders of exposed region -- */ + /* round down here*/ + left /= fontinfo->width; + rows += (fontinfo->height - 1); + cols += (fontinfo->width - 1); + rows /= fontinfo->height; + /* Get row and col containing bottom and */ + /* right borders -- round up here */ + rows -= top; + cols /= fontinfo->width; + cols -= left; + if (rows < 0) return; + if (cols < 0) return; + if (top > (screen_height - 1)) return; + if (left > (screen_width - 1)) return; + if ((VisibleX >= left) && (VisibleX < (left + cols)) && + (VisibleY >= top) && (VisibleY < (top + rows))) + { + ClearCursor (); + } + + /* should perhaps be DesiredScreen */ + /* but PhysScreen is guaranteed to contain*/ + /* date which was good for every line on */ + /* screen. For desired screen only for */ + /* lines which are changing. Emacs does */ + /* not consider a line within a newly */ + /* exposed region necessarily to have */ + /* been changed. Emacs knows nothing */ + /* about ExposeRegion events.*/ + for (localY = top, index = 0; + (index < rows) && (localY < screen_height); + ++index, ++localY) + { + if ((localY < 0) || (localY >= screen_height)) continue; + if (!current_screen->enable[localY]) continue; + if ((left + 1) > current_screen->used[localY]) continue; + localX = left; + localHL = current_screen->highlight[localY]; + dumpchars (current_screen, + min (cols, + current_screen->used[localY] + - localX), + localX, localY, localHL); + } + if (!InUpdate && !CursorExists) CursorToggle (); + /* Routine usually called */ + /* when not in update */ +} + +/* What sections of the window will be modified from the UpdateDisplay + * routine is totally under software control. Any line with Y coordinate + * greater than flexlines will not change during an update. This is really + * used only during dellines and inslines routines (scraplines and stufflines) + */ +static +XTset_terminal_window (n) + register int n; +{ +#ifdef XDEBUG + fprintf (stderr, "XTset_terminal_window\n"); +#endif + if ((n <= 0) || (n > screen_height)) + flexlines = screen_height; + else + flexlines = n; +} + +XTins_del_lines (vpos, n) + int vpos, n; +{ +#ifdef XDEBUG + fprintf (stderr, "XTins_del_lines\n"); +#endif + XTmove_cursor (vpos, 0); + if (n >= 0) stufflines (n); + else scraplines (-n); +} + +static +XTinsert_chars (start, len) + register char *start; + register int len; +{ +#ifdef XDEBUG + fprintf (stderr, "XTinsert_chars\n"); +#endif + writechars (start, start + len - 1); +} + +static +XTdelete_chars (n) + register int n; +{ + char *msg = "***Delete Chars Called Outside of Update!!!***"; +#ifdef XDEBUG + fprintf (stderr, "XTdelete_chars\n"); +#endif + writechars (msg, msg + strlen (msg) - 1); +} + +static +stufflines (n) + register int n; +{ + register int topregion, bottomregion; + register int length, newtop; + BLOCK_INPUT_DECLARE () + + if (cursor_vpos >= flexlines) + return; + + if (!WindowMapped) + { + bitblt = 0; + return; + } + BLOCK_INPUT (); + if (CursorExists) CursorToggle (); + dumpqueue (); + UNBLOCK_INPUT (); + topregion = cursor_vpos; + bottomregion = flexlines - (n + 1); + newtop = cursor_vpos + n; + length = (bottomregion - topregion) + 1; + if ((length > 0) && (newtop <= flexlines)) + { + BLOCK_INPUT (); + /* Should already have cleared */ + /* queue of events associated */ + /* with old bitblts */ + XMoveArea (XXwindow, XXInternalBorder, + topregion * fontinfo->height+XXInternalBorder, + XXInternalBorder, newtop * fontinfo->height+XXInternalBorder, + screen_width * fontinfo->width, + length * fontinfo->height); + if (WindowMapped) + bitblt = 1; + XFlush (); + UNBLOCK_INPUT (); + SIGNAL_INPUT_WHILE (bitblt); + XFlush (); + } + newtop = min (newtop, (flexlines - 1)); + length = newtop - topregion; + if (length > 0) + { + XPixSet (XXwindow, + XXInternalBorder, + topregion * fontinfo->height+XXInternalBorder, + screen_width * fontinfo->width, + n * fontinfo->height, + back); + } + /* if (!InUpdate) CursorToggle (); */ +} + +static +scraplines (n) + register int n; +{ + BLOCK_INPUT_DECLARE () + if (!WindowMapped) + { + bitblt = 0; + return; + } + + if (cursor_vpos >= flexlines) + return; + BLOCK_INPUT (); + if (CursorExists) CursorToggle (); + dumpqueue (); + if ((cursor_vpos + n) >= flexlines) + { + if (flexlines >= (cursor_vpos + 1)) + { + XPixSet (XXwindow, + XXInternalBorder, cursor_vpos * fontinfo->height+XXInternalBorder, + screen_width * fontinfo->width, + (flexlines - cursor_vpos) * fontinfo->height, + back); + } + UNBLOCK_INPUT (); + } + else + { + XMoveArea (XXwindow, + XXInternalBorder, + (cursor_vpos + n) * fontinfo->height+XXInternalBorder, + XXInternalBorder, cursor_vpos * fontinfo->height+XXInternalBorder, + screen_width * fontinfo->width, + (flexlines - (cursor_vpos + n)) * fontinfo->height); + if (WindowMapped) + bitblt = 1; + XFlush (); + UNBLOCK_INPUT (); + SIGNAL_INPUT_WHILE (bitblt); + BLOCK_INPUT (); + XFlush (); + XPixSet (XXwindow, XXInternalBorder, + (flexlines - n) * fontinfo->height+XXInternalBorder, + screen_width * fontinfo->width, + n * fontinfo->height, back); + UNBLOCK_INPUT (); + } + /* if (!InUpdate) CursorToggle (); */ +} + +/* Substitutes for standard read routine. Under X not interested in individual + * bytes but rather individual packets. + */ + +XTread_socket (sd, bufp, numchars) + register int sd; + register char *bufp; + register int numchars; +{ + + int count; + char *where_mapping; + int nbytes; + int stuffpending; + int temp_width, temp_height; + BLOCK_INPUT_DECLARE () + /* XKeyPressedEvent event; */ + /* typedef struct reply {XEvent event; struct reply *next} Reply; + Reply *replies = NULL;*/ + + BLOCK_INPUT (); + count = 0; + if (numchars <= 0) + { /* To keep from overflowing read buffer */ + numchars = 1; + --bufp; + } +#ifdef SIGIO + while (bitblt || XPending () != 0) +#else +#ifndef HAVE_SELECT + if (! (fcntl (fileno (stdin), F_GETFL, 0) & O_NDELAY)) + { + extern int read_alarm_should_throw; + if (CursorExists) + xfixscreen (); + read_alarm_should_throw = 1; + XPeekEvent (&XXEvent); + read_alarm_should_throw = 0; + } +#endif + while (XPending () != 0) +#endif + { + /* while there are more events*/ + XNextEvent (&XXEvent); + switch (XXEvent.type) + { +/* case X_Reply: + { + extern char *malloc (); + Reply *reply = (Reply *) malloc (sizeof (Reply)); + reply->next = replies; + reply->event = XXEvent; + replies = reply; + break; + }*/ + default: + break; + case ExposeWindow: + if (((XExposeEvent *)&XXEvent)->window == XXIconWindow) + { + PendingIconExposure = 1; + } + else + PendingExposure = 1;/* No reason to repeat */ + /* this if several */ + /* ExposeWindow events */ + /* come in quick succes-*/ + /* ion */ + break; + case ExposeRegion: + if (PendingExposure) + { /* Don't bother with */ + /* region events when */ + /* full window event */ + /* is pending */ + break; + } + loadxrepbuffer (&XXEvent, &XXqueue); + if (XXqueue.rindex == XXqueue.windex) + { + PendingExposure = 1; + } + if ((XXqueue.rindex > XXqueue.mindex) || + (XXqueue.windex > XXqueue.mindex) || + (XXqueue.rindex < 0) || + (XXqueue.windex < 0)) + { + PendingExposure = 1; + } + break; + case ExposeCopy: /* For ExposeCopy sync */ + /* will block all outgoing */ + /* requests until this is */ + /* decremented */ + if (WindowMapped) bitblt = 0; + break; + case KeyPressed: + /* bcopy (XXEvent, event, sizeof (XKeyPressedEvent)); */ + where_mapping = XLookupMapping (&XXEvent, &nbytes); + /* Nasty fix for arrow keys */ + if (!nbytes && IsCursorKey (XXEvent.detail & 0xff)) + { + switch (XXEvent.detail & 0xff) + { + case KC_CURSOR_LEFT: + where_mapping = "\002"; + break; + case KC_CURSOR_RIGHT: + where_mapping = "\006"; + break; + case KC_CURSOR_UP: + where_mapping = "\020"; + break; + case KC_CURSOR_DOWN: + where_mapping = "\016"; + break; + } + nbytes = 1; + } + if (numchars - nbytes > 0) + { + bcopy (where_mapping, bufp, nbytes); + bufp += nbytes; + count += nbytes; + numchars -= nbytes; + } +/* else + { + bcopy (where_mapping, bufp, numchars); + bufp += numchars; + count += numchars; + numchars = 0; + *(bufp-1) = *(where_mapping + nbytes - 1); + }*/ + break; + case ButtonPressed: + case ButtonReleased: + switch (spacecheck (Xxrepbuffer.mindex, + Xxrepbuffer.rindex, + Xxrepbuffer.windex, 0)) + { + case 0: + loadxrepbuffer (&XXEvent, + &Xxrepbuffer); + if (informflag && (numchars > 1)) + { + *bufp++ = (char) 'X' & 037; /* C-x */ + ++count; + --numchars; + *bufp++ = (char) 0; /* C-@ */ + ++count; + --numchars; + } + break; + case -1: + break; + case -2: + default: + fixxrepbuffer (); + break; + } + break; + } + } +/* while (replies) { + Reply *reply = replies; + XPutBackEvent (&reply->event); + replies = reply->next; + free (reply); + }*/ + if (count < 0) + count = 0; +#ifdef HAVE_SELECT + if (CursorExists +#ifdef O_NDELAY +#ifdef F_GETFL + && (! (fcntl (fileno (stdin), F_GETFL, 0) & O_NDELAY)) +#endif +#endif + ) + xfixscreen (); +#endif + UNBLOCK_INPUT (); + return count; +} + +/* refresh bitmap kitchen sink icon */ +refreshicon () +{ + BLOCK_INPUT_DECLARE () + + BLOCK_INPUT (); + if (XXIconWindow) + XBitmapBitsPut (XXIconWindow, 0, 0, sink_width, sink_height, + sink_bits, BlackPixel, WhitePixel, + XXIconMask, GXcopy, AllPlanes); + XFlush (); + UNBLOCK_INPUT (); +} + +XBitmapIcon () +{ + BLOCK_INPUT_DECLARE () + + BLOCK_INPUT (); + if (!IconWindow) + { + XSetIconWindow (XXwindow,XXIconWindow); + XSelectInput (XXIconWindow, ExposeWindow); + IconWindow = !IconWindow; + } + UNBLOCK_INPUT (); +} + +XTextIcon () +{ + BLOCK_INPUT_DECLARE () + + BLOCK_INPUT (); + if (IconWindow) + { + XClearIconWindow (XXwindow); + XSelectInput (XXIconWindow, NoEvent); + IconWindow = !IconWindow; + } + UNBLOCK_INPUT (); +} + +/* Interpreting incoming keycodes. Should have table modifiable as needed + * from elisp. + */ + +/* Exit gracefully from gnuemacs, doing an autosave and giving a status. + */ + +XExitGracefully (disp, event) + Display *disp; + XErrorEvent *event; +{ + XCleanUp (); + exit (70); +} + +x_io_error (disp) + Display *disp; +{ + XCleanUp (); + exit (71); +} + +#if 0 +/* This kludge overcomes the failure to handle EAGAIN and EINTR + in a certain version of X for 386 running system V. */ + +x_io_error (disp, a, b, c, nwrite) + Display *disp; +{ + extern _XSend (); + unsigned int pc = ((unsigned int *)&disp)[-1]; + if (pc - (unsigned int)&_XSend - 100 < 100 + && (errno == EAGAIN || errno == EINTR)) + { + /* We were called by `writedata' erroneously. + Modify a local variable which `writedata' + will subtract from the number of bytes to be written. */ + nwrite = 0; + return; + } + abort (); +} +#endif + +xfixscreen () +{ + register int temp_width, temp_height; + BLOCK_INPUT_DECLARE () + /* register int temp_x, temp_y; */ + + BLOCK_INPUT (); + dumpqueue (); + /* Check that the connection is in fact open. This works by doing a nop */ + /* (well, almost) write operation. If there is an XIOerror or a */ + /* SIGPIPE, exit gracefully. This fixes the loop-on-logout bug.*/ + /* XIOErrorHandler (XExitGracefully); */ + XPixFill (XXwindow, 0, 0, 1, 1, back, ClipModeClipped, GXnoop, AllPlanes); + XFlush (); + /* XIOErrorHandler (0); */ + if (PendingIconExposure) + { + refreshicon (); + PendingIconExposure = 0; + } + if (PendingExposure) + { + PendingExposure = 0; + ClearCursor (); + XXqueue.rindex = 0; + XXqueue.windex = 0; + XQueryWindow (XXwindow, &windowinfo); /* Dangerous to do */ + /* writes here but */ + /* otherwise would */ + /* have to alter */ + /* gnu emacs display */ + /* routines to query */ + /* when screen garbaged */ + temp_width = (windowinfo.width - 2 * XXInternalBorder) / fontinfo->width; + temp_height = (windowinfo.height- 2*XXInternalBorder) / fontinfo->height; + if (temp_width != screen_width || temp_height != screen_height) + change_screen_size (max (5, temp_height), max (10, temp_width), + 0, 0, 0); + XXxoffset= windowinfo.x; + XXyoffset = windowinfo.y; + /*if (temp_x != XXxoffset || temp_y != XXyoffset) + XSetOffset (temp_x, temp_y);*/ + dumprectangle (0, 0, + screen_height * fontinfo->height + 2 * XXInternalBorder, + screen_width * fontinfo->width + 2 * XXInternalBorder); + } + if (!InUpdate) + if (!CursorExists) + CursorToggle (); + XFlush (); + UNBLOCK_INPUT (); + SIGNAL_INPUT (); +} + +x_term_init () +{ + char *vardisplay; + char *temp_font; + register char *option; + extern XTinterrupt_signal (); + int reversevideo; + Color cdef; + char *progname; + + Fset (intern ("window-system-version"), make_number (10)); + + vardisplay = (alternate_display ? alternate_display + : (char *) egetenv ("DISPLAY")); + if (!vardisplay || *vardisplay == '\0') + { + fprintf (stderr, "DISPLAY environment variable must be set\n"); + exit (-200); + } + + XXdisplay = XOpenDisplay (vardisplay); + if (XXdisplay == (Display *) 0) + { + fprintf (stderr, "X server not responding. Check your DISPLAY environment variable.\n"); + exit (-200); + } + x_init_1 (1); + Xxrepbuffer.mindex = XREPBUFSIZE - 1; + Xxrepbuffer.windex = 0; + Xxrepbuffer.rindex = 0; + XXqueue.mindex = XREPBUFSIZE - 1; + XXqueue.windex = 0; + XXqueue.rindex = 0; + WindowMapped = 0; + baud_rate = 9600; + min_padding_speed = 10000; + must_write_spaces = 1; + informflag = 1; + meta_key = 1; + visible_bell = 1; +#ifdef SIGIO + interrupt_input = 1; +#endif + inverse_video = 1; + bitblt = 0; + PendingExposure = 0; + + fix_screen_hook = xfixscreen; + clear_screen_hook = XTclear_screen; + clear_end_of_line_hook = XTclear_end_of_line; + ins_del_lines_hook = XTins_del_lines; + change_line_highlight_hook = XTchange_line_highlight; + insert_chars_hook = XTinsert_chars; + output_chars_hook = XToutput_chars; + delete_chars_hook = XTdelete_chars; + ring_bell_hook = XTfeep; + 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; + move_cursor_hook = XTmove_cursor; + /* raw_move_cursor_hook = XTraw_move_cursor; */ + reassert_line_highlight_hook = XTreassert_line_highlight; + scroll_region_ok = 1; /* we'll scroll partial screens */ + char_ins_del_ok = 0; /* just as fast to write the line */ + line_ins_del_ok = 1; /* we'll just blt 'em */ + fast_clear_end_of_line = 1; /* X does this well */ + memory_below_screen = 0; /* we don't remember what scrolls + off the bottom */ + dont_calculate_costs = 1; + + /* New options section */ + IconWindow = 0; + XXborder = 1; + XXInternalBorder = 1; + screen_width = 80; + screen_height = 66; + reversevideo = 0; + XXxoffset = 0; + XXyoffset = 0; + XXdebug = 0; + + XErrorHandler (XExitGracefully); + XIOErrorHandler (x_io_error); + + progname = "emacs"; + if (option = XGetDefault (progname,"ReverseVideo")) + if (strcmp (option,"on") == 0) reversevideo = 1; + if (option = XGetDefault (progname, "BitmapIcon")) + if (strcmp (option, "on") == 0) IconWindow = 1; + + if (option = XGetDefault (progname,"BorderWidth")) + XXborder = atoi (option); + if (option = XGetDefault (progname,"InternalBorder")) + XXInternalBorder = atoi (option); + + brdr_color = XGetDefault (progname,"Border"); + if (!brdr_color) brdr_color = XGetDefault (progname, "BorderColor"); + back_color = XGetDefault (progname,"Background"); + fore_color = XGetDefault (progname,"Foreground"); + mous_color = XGetDefault (progname,"Mouse"); + curs_color = XGetDefault (progname,"Cursor"); + + temp_font = XGetDefault (progname,"BodyFont"); + if (temp_font == 0) temp_font = X_DEFAULT_FONT; + XXcurrentfont = (char *) xmalloc (strlen (temp_font) + 1); + strcpy (XXcurrentfont, temp_font); + + /* If user has specified a special keymap for use with Emacs, use it. */ + { + char *temp = XGetDefault (progname, "KeyMap"); + if (temp) XUseKeymap (temp); + } + + if (DisplayCells () > 2) + { + + if (fore_color && XParseColor (fore_color, &cdef) && + XGetHardwareColor (&cdef)) + fore = cdef.pixel; + else + { + fore_color = "black"; + fore = BlackPixel; + } + + if (back_color && XParseColor (back_color, &cdef) && + XGetHardwareColor (&cdef)) + back = cdef.pixel; + else + { + back_color = "white"; + back = WhitePixel; + } + + if (curs_color && XParseColor (curs_color, &cdef) && + XGetHardwareColor (&cdef)) + curs = cdef.pixel; + else + { + curs_color = "black"; + curs = BlackPixel; + } + + if (mous_color && XParseColor (mous_color, &cdef) && + XGetHardwareColor (&cdef)) + mous = cdef.pixel; + else + { + mous_color = "black"; + mous = BlackPixel; + } + + if (brdr_color && XParseColor (brdr_color, &cdef) && + XGetHardwareColor (&cdef)) + brdr = cdef.pixel; + else + { + brdr_color = "black"; + brdr = BlackPixel; + } + } + else + { + fore_color = curs_color = mous_color = brdr_color = "black"; + fore = curs = mous = brdr = BlackPixel; + back_color = "white"; + back = WhitePixel; + } + + /* + if (fore_color && DisplayCells () > 2 && + XParseColor (fore_color, &cdef) && XGetHardwareColor (&cdef)) + fore = cdef.pixel; + else if (fore_color && strcmp (fore_color, "black") == 0) + fore = BlackPixel; + else if (fore_color && strcmp (fore_color, "white") == 0) + fore = WhitePixel; + else + { + fore_color = "black"; + fore = BlackPixel; + } + + if (back_color && DisplayCells () > 2 && + XParseColor (back_color, &cdef) && XGetHardwareColor (&cdef)) + back = cdef.pixel; + else if (back_color && strcmp (back_color, "white") == 0) + back = WhitePixel; + else if (back_color && strcmp (back_color, "black") == 0) + back = BlackPixel; + else + { + back_color = "white"; + back = WhitePixel; + } + + if (brdr_color && DisplayCells () > 2 && + XParseColor (brdr_color, &cdef) && XGetHardwareColor (&cdef)) + brdr = cdef.pixel; + else if (brdr_color && (!strcmp (brdr_color, "gray") || + !strcmp (brdr_color, "grey") || + !strcmp (brdr_color, "Gray") || + !strcmp (brdr_color, "Grey"))) + brdr = BlackPixel; + else if (brdr_color && strcmp (brdr_color, "white") == 0) + brdr = WhitePixel; + else + { + brdr_color = "black"; + brdr = BlackPixel; + } + + if (curs_color && DisplayCells () > 2 && + XParseColor (curs_color, &cdef) && XGetHardwareColor (&cdef)) + curs = cdef.pixel; + else if (curs_color && strcmp (curs_color, "black") == 0) + curs = BlackPixel; + else if (curs_color && strcmp (curs_color, "white") == 0) + curs = WhitePixel; + else + { + curs_color = "black"; + curs = BlackPixel; + } + + if (mous_color && DisplayCells () > 2 && + XParseColor (mous_color, &cdef) && XGetHardwareColor (&cdef)) + mous = cdef.pixel; + else if (mous_color && strcmp (mous_color, "black") == 0) + mous = BlackPixel; + else if (mous_color && strcmp (mous_color, "white") == 0) + mous = WhitePixel; + else + { + mous_color = "black"; + mous = BlackPixel; + } + */ + + XXpid = getpid (); + if (XXcurrentfont == (char *) 0) + { + fprintf (stderr, "Memory allocation failure.\n"); + exit (-150); + } + default_window = "=80x24+0+0"; +/* RMS: XTread_socket does not have an interface suitable + for being a signal handler. In any case, the SIGIO handler is + set up in init_keyboard and X uses the same one as usual. */ +/* signal (SIGIO, XTread_socket); */ + signal (SIGPIPE, XExitGracefully); + XQueryWindow (RootWindow, &rootwindowinfo); + strncpy (iconidentity, ICONTAG, MAXICID); + fontinfo = XOpenFont (XXcurrentfont); + if (fontinfo == (FontInfo *) 0) + { + fprintf (stderr, "No font\n"); + exit (-98); + } + pixelwidth = screen_width * fontinfo->width + 2 * XXInternalBorder; + pixelheight = screen_height * fontinfo->height + 2 * XXInternalBorder; + XXwindow = XCreateWindow (RootWindow, + XXxoffset /* Absolute horizontal offset */, + XXyoffset /* Absolute Vertical offset */, + pixelwidth, pixelheight, + XXborder, BlackPixmap, WhitePixmap); + if (!XXwindow) + { + fprintf (stderr, "Unable to create window.\n"); + exit (-97); + } + + XXIconWindow = XCreateWindow (RootWindow, 0, 0, sink_width, sink_height, + 2, WhitePixmap, (Pixmap) NULL); + + if (!XXIconWindow) + { + fprintf (stderr, "Unable to create icon window.\n"); + fflush (stderr); + exit (-97); + } + XSelectInput (XXIconWindow, NoEvent); + XXIconMask = XStoreBitmap (sink_mask_width, sink_mask_height, sink_mask_bits); + + XSelectInput (XXwindow, NoEvent); + XSetResizeHint (XXwindow, 2 * XXInternalBorder, 2 * XXInternalBorder, + /* fontinfo->width * 1, fontinfo->height * 1, */ + fontinfo->width, fontinfo->height); + +#if defined (BSD) || defined (HPUX) || defined (IBMRTAIX) + if (gethostname (&iconidentity[sizeof (ICONTAG) - 1], + (MAXICID - 1) - sizeof (ICONTAG))) +#endif + { + iconidentity[sizeof (ICONTAG) - 2] = '\0'; + } + XStoreName (XXwindow, &iconidentity[0]); + + EmacsCursor = XCreateCursor (16, 16, MouseCursor, MouseMask, + 0, 0, mous, back, GXcopy); + XDefineCursor (XXwindow, EmacsCursor); + flexlines = screen_height; +#if 0 +/* Do not call XPopUpWindow here! This is too early. + It is supposed ot be called via the term-setup-hook + and not until after lisp/term/x-win.el has had a chance + to process the user's switches. + I am not sure that there are any circumstances under which + this should be done here -- RMS. */ + XPopUpWindow (); /* This looks at Vxterm */ +#endif /* 0 */ + if (reversevideo) XFlipColor (); +} + +x_init_1 (unrequest) +{ +#ifdef F_SETOWN + extern int old_fcntl_owner; +#endif +#ifndef USG + extern void init_sigio (), request_sigio (), unrequest_sigio (); +#endif + + dup2 (dpyno (), 0); + close (dpyno ()); + dpyno () = 0; /* Looks a little strange? + check the def of the macro; + it is a genuine lvalue */ +#ifndef USG + init_sigio (); + request_sigio (); +#endif /* USG */ +#ifdef F_SETOWN + old_fcntl_owner = fcntl (0, F_GETOWN, 0); +#ifdef F_SETOWN_SOCK_NEG + fcntl (0, F_SETOWN, -getpid ()); /* stdin is a socket here */ +#else + fcntl (0, F_SETOWN, getpid ()); +#endif /* F_SETOWN_SOCK_NEG */ +#endif /* F_SETOWN */ +#ifndef USG + if (unrequest) unrequest_sigio (); +#endif +} + +/* Process all queued ExposeRegion events. */ +static +dumpqueue () +{ + register int i; + XExposeRegionEvent r; + if ((XXqueue.rindex > XXqueue.mindex) || + (XXqueue.windex > XXqueue.mindex) || + (XXqueue.rindex < 0) || + (XXqueue.windex < 0)) + { + PendingExposure = 1; + } + else + while (XXqueue.rindex != XXqueue.windex) + { + if (CursorExists) + CursorToggle (); + unloadxrepbuffer (&r, &XXqueue); + dumprectangle (r.y - XXInternalBorder, r.x - XXInternalBorder, + r.height, r.width); + } +} + +XSetFlash () +{ + ring_bell_hook = XTflash; +} + +XSetFeep () +{ + ring_bell_hook = XTfeep; +} + +XNewFont (newname) + register char *newname; +{ + FontInfo *temp; + BLOCK_INPUT_DECLARE () + + BLOCK_INPUT (); + XFlush (); + if (XXdebug) + fprintf (stderr, "Request id is %d\n", XXdisplay->request); + temp = XOpenFont (newname); + if (temp == (FontInfo *) 0) + { + UNBLOCK_INPUT_RESIGNAL (); + return -1; + } + XCloseFont (fontinfo); + fontinfo = temp; + XSetResizeHint (XXwindow, 2*XXInternalBorder, 2*XXInternalBorder, + /* fontinfo->width * 1, fontinfo->height * 1, */ + fontinfo->width, fontinfo->height); + XSetWindowSize (screen_height, screen_width); + UNBLOCK_INPUT_RESIGNAL (); + return 0; +} + +XFlipColor () +{ + Pixmap temp; + int tempcolor; + char *tempname; + Cursor temp_curs; + BLOCK_INPUT_DECLARE () + + BLOCK_INPUT (); + CursorToggle (); + temp = XMakeTile (fore); + XChangeBackground (XXwindow, temp); + XFreePixmap (temp); + temp = XMakeTile (back); + if (XXborder) + XChangeBorder (XXwindow, temp); + XFreePixmap (temp); + brdr = back; + brdr_color = back_color; + tempcolor = fore; + fore = back; + back = tempcolor; + tempname = fore_color ; + fore_color = back_color; + back_color = tempname; +/* XPixFill (XXwindow, 0, 0, screen_width * fontinfo->width, + screen_height * fontinfo->height, back, ClipModeClipped, + GXcopy, AllPlanes); + dumprectangle (0, 0, screen_height * fontinfo->height + 2 * XXInternalBorder, + screen_width * fontinfo -> width + 2 * XXInternalBorder);*/ + XRedrawDisplay (); + if (curs == WhitePixel) + { + curs = BlackPixel; + curs_color = "black"; + } + else if (curs == BlackPixel) + { + curs = WhitePixel; + curs_color = "white"; + } + if (mous == WhitePixel) + { + mous = BlackPixel; + mous_color = "black"; + } + else if (mous == BlackPixel) + { + mous = WhitePixel; + mous_color = "white"; + } + temp_curs = XCreateCursor (16, 16, MouseCursor, MouseMask, 0, 0, + mous, back, GXcopy); + XUndefineCursor (XXwindow); + XDefineCursor (XXwindow, temp_curs); + XFreeCursor (EmacsCursor); + bcopy (&temp_curs, &EmacsCursor, sizeof (Cursor)); + CursorToggle (); + XFlush (); + UNBLOCK_INPUT (); +} + +XSetOffset (xoff, yoff) + register int xoff, yoff; +{ + BLOCK_INPUT_DECLARE () + + BLOCK_INPUT (); + if (xoff < 0) + { + XXxoffset = rootwindowinfo.width + (++xoff) - pixelwidth - 4; + } + else + { + XXxoffset = xoff; + } + if (yoff < 0) + { + XXyoffset + = rootwindowinfo.height + (++yoff) - pixelheight - 4; + } + else + { + XXyoffset = yoff; + } + XMoveWindow (XXwindow, XXxoffset, XXyoffset); + UNBLOCK_INPUT (); + /* XWarpMouse (XXwindow, pixelwidth >> 1, pixelheight >> 1); */ +} + +XSetWindowSize (rows, cols) + register int rows, cols; +{ + /* if (rows < 3) rows = 24; + if (cols < 1) cols = 80; */ + pixelwidth = cols * fontinfo->width + 2 * XXInternalBorder; + pixelheight = rows * fontinfo->height + 2 * XXInternalBorder; + XChangeWindow (XXwindow, pixelwidth, pixelheight); + XFlush (); + change_screen_size (rows, cols, 0, 0, 0); + PendingExposure = 0; +} + +XPopUpWindow () +{ + BLOCK_INPUT_DECLARE () + if (WindowMapped) + return; + BLOCK_INPUT (); + if (!x_edges_specified) + Fx_rubber_band (); + bitblt = 0; + CursorExists = 0; + VisibleX = 0; + VisibleY = 0; + WindowMapped = 1; + XMapWindow (XXwindow); + dumprectangle (0, 0, + screen_height * fontinfo->height + 2 * XXInternalBorder, + screen_width * fontinfo->width + 2 * XXInternalBorder); + XSelectInput (XXwindow, KeyPressed | ExposeWindow | ButtonPressed + | ButtonReleased + | ExposeRegion | ExposeCopy); + /* XWarpMouse (XXwindow, pixelwidth >> 1, pixelheight >> 1);*/ + XTmove_cursor (0, 0); + if (IconWindow) + { + XSetIconWindow (XXwindow,XXIconWindow); + XSelectInput (XXIconWindow, ExposeWindow); + } + else + { + XClearIconWindow (XXwindow); + XSelectInput (XXIconWindow, NoEvent); + } + /* XRedrawDisplay ();*/ + XFlush (); + UNBLOCK_INPUT (); +} + +spacecheck (mindex, rindex, windex, minfreespace) + register int mindex, rindex, windex, minfreespace; +{ + if ((rindex > mindex) || (windex > mindex)) + { + /* fprintf (stderr, "Fatal Mouse Buffer Error.\n"); + fprintf (stderr, "%d = mindex, %d = rindex, %d = windex\n", + mindex, rindex, windex); */ + return -2; + } + if (windex >= rindex) + { + if ((mindex - (windex - rindex)) > minfreespace) + return 0; + } + else + { + if (((rindex - windex) - 1) > minfreespace) + return 0; + } + return -1; +} + +loadxrepbuffer (p_xrep, p_buffer) + register XEvent *p_xrep; + register XREPBUFFER *p_buffer; +{ + p_buffer->xrep[p_buffer->windex] = *p_xrep; + if (p_buffer->windex == p_buffer->mindex) + p_buffer->windex = 0; + else + p_buffer->windex++; +} + +unloadxrepbuffer (p_xrep, p_buffer) + register XEvent *p_xrep; + register XREPBUFFER *p_buffer; +{ + if (p_buffer->windex == p_buffer->rindex) + return -1; + *p_xrep = p_buffer->xrep[p_buffer->rindex]; + if (p_buffer->rindex == p_buffer->mindex) + p_buffer->rindex = 0; + else + p_buffer->rindex++; + return 0; +} + +fixxrepbuffer () +{ + Xxrepbuffer.mindex = XREPBUFSIZE - 1; + Xxrepbuffer.windex = 0; + Xxrepbuffer.rindex = 0; +} + +#endif /* HAVE_X_WINDOWS */ |