1 /* -*- mode: C; mode: fold; -*- */
2 /* Copyright (c) 1992, 1998, 2000, 2002, 2003, 2004, 2005, 2006 John E. Davis
3  * This file is part of JED editor library source.
4  *
5  * You may distribute this file under the terms the GNU General Public
6  * License.  See the file COPYING for more information.
7  */
8 
9 #include "config.h"
10 #include "jed-feat.h"
11 
12 #define USE_NEW_META_CODE	1
13 #define HAS_IBM_NUMLOCK_CODE	0
14 #define SKIP_LOCALE_CODE	0
15 #ifndef HAVE_SETLOCALE
16 # define X_LOCALE		1
17 #endif
18 
19 #define XJED_USE_COMPOUND_TEXT	0
20 
21 /*{{{ Include Files */
22 
23 #ifndef VMS
24 # include <X11/Xlib.h>
25 # include <X11/Xutil.h>
26 /* #include <X11/Xos.h> */
27 # include <X11/Xatom.h>
28 # include <X11/keysym.h>
29 # include <X11/cursorfont.h>
30 # include <X11/Intrinsic.h>
31 #ifndef XJED_HAS_XRENDERFONT
32 # define XJED_HAS_XRENDERFONT 0
33 #endif
34 # if XJED_HAS_XRENDERFONT
35 #  include <X11/Xft/Xft.h>
36 # endif
37 # if !SKIP_LOCALE_CODE
38 #  if XtSpecificationRelease >= 6
39 #   define XJED_USE_R6IM
40 #   include <X11/Xlocale.h>
41 #  endif
42 # endif
43 #else
44 # include <decw$include/Xlib.h>
45 # include <decw$include/Xutil.h>
46 /* #include <decw$include/Xos.h> */
47 # include <decw$include/Xatom.h>
48 # include <decw$include/keysym.h>
49 # include <decw$include/cursorfont.h>
50 #endif
51 
52 #include <stdio.h>
53 #include <string.h>
54 #include <ctype.h>
55 #include <signal.h>
56 
57 #include <slang.h>
58 
59 #include "jdmacros.h"
60 
61 /* #include "xterm.h"*/
62 #include "buffer.h"
63 #include "display.h"
64 #include "sysdep.h"
65 #include "screen.h"
66 #include "keymap.h"
67 #include "hooks.h"
68 #include "ins.h"
69 #include "ledit.h"
70 #include "misc.h"
71 #include "cmds.h"
72 #include "sig.h"
73 #include "file.h"
74 #include "vterm.h"
75 #include "colors.h"
76 
77 /* Fixes some X headers... */
78 #ifndef Button6Mask
79 # define Button6Mask (Button5Mask<<1)
80 #endif
81 
82 /*}}}*/
83 
84 /* X_HAVE_UTF8_STRING is defined in X11.h */
85 #if (SLANG_VERSION >= 20000) && defined(X_HAVE_UTF8_STRING)
86 # define USE_XUTF8_CODE		1
87 #else
88 # define USE_XUTF8_CODE		0
89 #endif
90 
91 /*{{{ Static Global Variables */
92 
93 static int JX_Screen_Cols;
94 static int JX_Screen_Rows;
95 static int JX_Term_Cannot_Scroll = 0;
96 static int JX_Term_Cannot_Insert = 0;
97 static int JX_Use_Ansi_Colors = 1;
98 static int JX_Ignore_Beep = 3;
99 static int JX_Blink_Mode = 1;
100 static int JX_MultiClick_Time = 500;   /* milliseconds */
101 
102 static int JX_MetaMask = Mod1Mask;
103 
104 #ifdef XJED_USE_R6IM
105 static char *R6IM_Input_Method = NULL;
106 static XIMStyle R6IM_Input_Style = 0;
107 static char *R6IM_Preedit_Type = "Root";
108 static XIC R6IM_Xic;
109 static void i18init(void);
110 static XPoint R6IM_Spot;
111 static XVaNestedList R6IM_Preedit_Attr;
112 static void move_input_position (void);
113 static void set_geometry (XEvent *, XIMStyle, char *);
114 #endif
115 
116 static char *The_Xserver_Vendor;
117 
118 /* static int Current_Color; */
119 static int X_Alt_Char = 27;
120 static KeySym X_Last_Keysym;
121 static int X_Warp_Pending = 0;
122 
123 typedef struct /*{{{*/
124 {
125    GC gc;
126    unsigned long fg, bg;
127    char *fg_name;
128    char *bg_name;
129    int dirty;
130 }
131 /*}}}*/
132 GC_Info_Type;
133 
134 typedef struct /*{{{*/
135 {
136    Window w;
137    Atom wm_del_win;		       /* delete window protocol */
138 
139    int height, width;
140    int border;			       /* inside border */
141    int o_border;		       /* outside border */
142    Colormap color_map;
143 
144    /* font information */
145    XFontStruct *font;
146    char *font_name;
147    int font_height, font_width, font_base;
148    int is_dual_font;		       /* if both single and double width */
149 #if XJED_HAS_XRENDERFONT
150    XftFont *xftfont;
151    XftDraw *xftdraw;
152    double face_size;
153 #endif
154 
155    /* GC info */
156    GC_Info_Type *text_gc;
157    GC_Info_Type *current_gc;
158 
159    int vis_curs_row, vis_curs_col;     /* position of VISIBLE cursor */
160 
161    /* flags */
162    int cursor_showing;		       /* true if widow has cursor showing */
163    int focus;			       /* true if window has focus */
164    int window_mapped;		       /* true if window is mapped */
165 
166    /* Window tty parameters */
167    int insert_mode;		       /* true if inserting */
168    int scroll_r1,  scroll_r2;	       /* scrolling region */
169    int cursor_row, cursor_col;	       /* row column of cursor (0, 0) origin */
170 
171    int visible;			       /* from visibilitynotify */
172    Cursor mouse;
173 }
174 /*}}}*/
175 JXWindow_Type;
176 
177 static JXWindow_Type XWin_Buf;
178 static JXWindow_Type *XWin;
179 
180 static Display *This_XDisplay;
181 static Window This_XWindow;
182 static int This_XScreen;
183 static int Performing_Update;
184 static int Check_Buffers_Pending;
185 static int No_XEvents;		       /* if true, do nothing */
186 
187 typedef struct /*{{{*/
188 {
189    char *name;
190    char *name1;
191    int type;
192    char *value;
193    char **dflt;
194 }
195 
196 /*}}}*/
197 XWindow_Arg_Type;
198 
199 #define XJED_CLASS	"XTerm"
200 static char *This_App_Name = "xjed";
201 static char *This_App_Title = "XJed";
202 /* #define Default_Geometry "80x24+0-0" */
203 #define Default_Geometry "80x24"
204 static char *This_Geometry = NULL;
205 static char *This_Font_Name = "fixed";
206 #if XJED_HAS_XRENDERFONT
207 static char *This_Face_Size = "                           ";
208 #endif
209 static char *This_Border_Width_Name = "0";
210 static char *This_Internal_Border_Name = "0";
211 static char *This_MFG = "green";
212 static char *This_MBG = "white";
213 static char *Iconic = NULL;
214 
215 static Atom Xjed_Prop;
216 static Atom Compound_Text_Atom;
217 static Atom UTF8_String_Atom;
218 static Atom Text_Atom;
219 static Atom Targets_Atom;
220 
221 static XEvent Current_Event;
222 static char *Selection_Send_Data = NULL;
223 static int receive_selection (XEvent *);
224 static int send_selection (XEvent *);
225 
226 static GC_Info_Type Default_GC_Info[JMAX_COLORS] = /*{{{*/
227 {
228      {NULL, 0, 0, "black", "white",0},     /* NORMAL */
229      {NULL, 0, 0, "green", "red",0},       /* CURSOR */
230      {NULL, 0, 0, "default", "skyblue",0},   /* STATUS */
231      {NULL, 0, 0, "default", "magenta",0},      /* REGION */
232      {NULL, 0, 0, "default", "skyblue",0},      /* MENU */
233      {NULL, 0, 0, "default", "default",0},     /* operator */
234      {NULL, 0, 0, "green", "default",0},     /* numbers */
235      {NULL, 0, 0, "blue", "default",0},      /* strings */
236      {NULL, 0, 0, "default", "gray",0},      /* comments */
237      {NULL, 0, 0, "default", "default",0},      /* delimeters */
238      {NULL, 0, 0, "magenta", "default",0},      /* preprocess */
239      {NULL, 0, 0, "blue", "default",0},      /* message */
240      {NULL, 0, 0, "red", "default",0},      /* error */
241      {NULL, 0, 0, "magenta", "default",0},      /* dollar */
242      {NULL, 0, 0, "red", "default",0},       /* keyword */
243      {NULL, 0, 0, "green", "default",0},       /* keyword1 */
244      {NULL, 0, 0, "red", "default",0},       /* keyword2 */
245      {NULL, 0, 0, "green", "default",0}       /* ... fold mark */
246 };
247 
248 /*}}}*/
249 
250 /* cheat a little, use VOID_TYPE for boolean arguments */
251 static XWindow_Arg_Type X_Arg_List[] = /*{{{*/
252 {
253    /* These MUST be in this order!!! */
254 #define XARG_DISPLAY	0
255      {"Display",		"d", 	STRING_TYPE,	NULL,	NULL},
256 #define XARG_NAME	1
257      {"Name",		NULL,	STRING_TYPE,	NULL,	&This_App_Name},
258 #define XARG_GEOMETRY	2
259      {"Geometry",		NULL, 	STRING_TYPE,	NULL,	&This_Geometry},
260 
261 #define XARG_START	2
262      /* Note: it's good to look for
263       * `font', `background', `foreground'
264       * instead of
265       * `Font', `background', `foreground'
266       * so that XTerm names can be used
267       * (resource vs. class names)
268       *
269       * also, change order of names a little?
270       */
271      {"font",		"fn",	STRING_TYPE,	NULL,	&This_Font_Name},
272      {"fgMouse",		"mfg", 	STRING_TYPE,	NULL,	&This_MFG},
273      {"bgMouse",		"mbg", 	STRING_TYPE,	NULL,	&This_MBG},
274      {"background",	"bg", 	STRING_TYPE,	NULL,	&Default_GC_Info[JNORMAL_COLOR].bg_name},
275      {"foreground",	"fg",	STRING_TYPE,	NULL,	&Default_GC_Info[JNORMAL_COLOR].fg_name},
276      {"fgStatus",	"sfg", 	STRING_TYPE,	NULL,	&Default_GC_Info[JSTATUS_COLOR].fg_name},
277      {"bgStatus",	"sbg", 	STRING_TYPE,	NULL,	&Default_GC_Info[JSTATUS_COLOR].bg_name},
278      {"fgRegion",	"rfg", 	STRING_TYPE,	NULL,	&Default_GC_Info[JREGION_COLOR].fg_name},
279      {"bgRegion",	"rbg", 	STRING_TYPE,	NULL,	&Default_GC_Info[JREGION_COLOR].bg_name},
280      {"fgCursor",	"cfg", 	STRING_TYPE,	NULL,	&Default_GC_Info[JCURSOR_COLOR].fg_name},
281      {"bgCursor",	"cbg", 	STRING_TYPE,	NULL,	&Default_GC_Info[JCURSOR_COLOR].bg_name},
282      {"fgCursorOvr",	"cofg", STRING_TYPE,	NULL,	&Default_GC_Info[JCURSOROVR_COLOR].fg_name},
283      {"bgCursorOvr",	"cobg", STRING_TYPE,	NULL,	&Default_GC_Info[JCURSOROVR_COLOR].bg_name},
284      {"fgMenu",		"fgm", 	STRING_TYPE,	NULL,	&Default_GC_Info[JMENU_COLOR].fg_name},
285      {"bgMenu",		"bgm", 	STRING_TYPE,	NULL,	&Default_GC_Info[JMENU_COLOR].bg_name},
286      {"fgOperator",	"fgop",	STRING_TYPE,	NULL,	&Default_GC_Info[JOP_COLOR].fg_name},
287      {"bgOperator",	"bgop",	STRING_TYPE,	NULL,	&Default_GC_Info[JOP_COLOR].bg_name},
288      {"fgNumber",		"fgnm",	STRING_TYPE,	NULL,	&Default_GC_Info[JNUM_COLOR].fg_name},
289      {"bgNumber",		"bgnm",	STRING_TYPE,	NULL,	&Default_GC_Info[JNUM_COLOR].bg_name},
290      {"fgString",		"fgst",	STRING_TYPE,	NULL,	&Default_GC_Info[JSTR_COLOR].fg_name},
291      {"bgString",		"bgst",	STRING_TYPE,	NULL,	&Default_GC_Info[JSTR_COLOR].bg_name},
292      {"fgComments",	"fgco",	STRING_TYPE,	NULL,	&Default_GC_Info[JCOM_COLOR].fg_name},
293      {"bgComments",	"bgco",	STRING_TYPE,	NULL,	&Default_GC_Info[JCOM_COLOR].bg_name},
294      {"fgKeyword",	"fgkw",	STRING_TYPE,	NULL,	&Default_GC_Info[JKEY_COLOR].fg_name},
295      {"bgKeyword",	"bgkw",	STRING_TYPE,	NULL,	&Default_GC_Info[JKEY_COLOR].bg_name},
296      {"fgKeyword1",	"fgkw1",STRING_TYPE,	NULL,	&Default_GC_Info[JKEY_COLOR + 1].fg_name},
297      {"bgKeyword1",	"bgkw1",STRING_TYPE,	NULL,	&Default_GC_Info[JKEY_COLOR + 1].bg_name},
298      {"fgKeyword2",	"fgkw2",STRING_TYPE,	NULL,	&Default_GC_Info[JKEY_COLOR + 2].fg_name},
299      {"bgKeyword2",	"bgkw2",STRING_TYPE,	NULL,	&Default_GC_Info[JKEY_COLOR + 2].bg_name},
300      {"fgDelimiter",	"fgde",	STRING_TYPE,	NULL,	&Default_GC_Info[JDELIM_COLOR].fg_name},
301      {"bgDelimiter",	"bgde",	STRING_TYPE,	NULL,	&Default_GC_Info[JDELIM_COLOR].bg_name},
302      {"fgPreprocess",	"fgpr",	STRING_TYPE,	NULL,	&Default_GC_Info[JPREPROC_COLOR].fg_name},
303      {"bgPreprocess",	"bgpr",	STRING_TYPE,	NULL,	&Default_GC_Info[JPREPROC_COLOR].bg_name},
304      {"bgMessage",	"bgms",	STRING_TYPE,	NULL,	&Default_GC_Info[JMESSAGE_COLOR].bg_name},
305      {"fgMessage",	"fgms",	STRING_TYPE,	NULL,	&Default_GC_Info[JMESSAGE_COLOR].fg_name},
306      {"bgError",		"bger",	STRING_TYPE,	NULL,	&Default_GC_Info[JERROR_COLOR].bg_name},
307      {"fgError",		"fger",	STRING_TYPE,	NULL,	&Default_GC_Info[JERROR_COLOR].fg_name},
308      {"fgDots",		"fgdt",	STRING_TYPE,	NULL,	&Default_GC_Info[JDOTS_COLOR].bg_name},
309      {"bgDots",		"bgdt",	STRING_TYPE,	NULL,	&Default_GC_Info[JDOTS_COLOR].bg_name},
310 
311      {"BorderWidth",	"bw", 	STRING_TYPE,	NULL,	&This_Border_Width_Name},
312      {"title",		NULL,	STRING_TYPE,	NULL,	&This_App_Title},
313      {"BorderColor",	"bd", 	STRING_TYPE,	NULL,	NULL},
314      {"Iconic",		"ic",	VOID_TYPE,	NULL,	&Iconic},
315      {"xrm",		NULL,	STRING_TYPE,	NULL,	NULL},
316      {"internalBorder", "ib",	STRING_TYPE,	NULL,	&This_Internal_Border_Name},
317 #ifdef XJED_USE_R6IM
318      {"inputMethod",      "im",   STRING_TYPE,    NULL,   &R6IM_Input_Method},
319      {"inputStyle",       "is",   STRING_TYPE,    NULL,   &R6IM_Preedit_Type},
320 #endif
321 #if XJED_HAS_XRENDERFONT
322      {"facesize",	"fs",	STRING_TYPE,	NULL,	&This_Face_Size},
323 #endif
324      {NULL,		NULL,	0,		NULL,	NULL}
325 };
326 
327 /*}}}*/
328 
329 /*}}}*/
330 
331 #if XJED_HAS_XRENDERFONT
Pixel2XftColor(Pixel pixel)332 static XftColor *Pixel2XftColor (Pixel pixel)
333 {
334 # define CACHE_SIZE  40
335    static struct
336      {
337 	XftColor        color;
338 	unsigned long use;
339      }
340    cache[CACHE_SIZE];
341    static unsigned long use;
342    unsigned int i;
343    unsigned long oldest, oldestuse;
344    XColor color;
345 
346    oldestuse = (unsigned long) -1L;
347    oldest = 0;
348    for (i = 0; i < CACHE_SIZE; i++)
349      {
350 	if (cache[i].use)
351 	  {
352 	     if (cache[i].color.pixel == pixel)
353 	       {
354 		  cache[i].use = ++use;
355 		  return &cache[i].color;
356 	       }
357 	  }
358 
359 	if (cache[i].use < oldestuse)
360 	  {
361 	     oldestuse = cache[i].use;
362 	     oldest = i;
363 	  }
364     }
365 
366    i = oldest;
367    color.pixel = pixel;
368    XQueryColor (This_XDisplay, XWin->color_map, &color);
369    cache[i].color.color.red = color.red;
370    cache[i].color.color.green = color.green;
371    cache[i].color.color.blue = color.blue;
372    cache[i].color.color.alpha = 0xffff;
373    cache[i].color.pixel = pixel;
374    cache[i].use = ++use;
375    return &cache[i].color;
376 }
377 #endif
378 
379 #if SLANG_VERSION >= 20000
380 /* conversion tools */
381 /* wchars to XChar2b for X drawing */
wchars_to_XChar2b(SLwchar_Type * w,unsigned int nchars)382 static XChar2b *wchars_to_XChar2b(SLwchar_Type *w, unsigned int nchars)
383 {
384    unsigned int i;
385    XChar2b *x = (XChar2b *)SLmalloc(nchars*sizeof(XChar2b));
386 
387    if (x == NULL)
388      return NULL;
389 
390    for (i = 0; i < nchars; i++)
391      {
392 	SLwchar_Type w_i = w[i];
393 	if (w_i > 0xFFFF)
394 	  w_i = '?';
395 	x[i].byte2 = (unsigned char)(w_i & 0xFF);
396 	x[i].byte1 = (unsigned char)((w_i >> 8 )& 0xFF);
397      }
398 
399    return x;
400 }
401 
bytes_to_wchars(unsigned char * s,unsigned int nchars)402 static SLwchar_Type *bytes_to_wchars (unsigned char *s, unsigned int nchars)
403 {
404    unsigned int i;
405 
406    SLwchar_Type *w = (SLwchar_Type *)SLmalloc(nchars*sizeof(SLwchar_Type));
407    if (w == NULL)
408      return NULL;
409 
410    for (i = 0; i < nchars; i++)
411      w[i] = s[i];
412 
413    return w;
414 }
415 
utf8nt_to_wchars(unsigned char * s,unsigned int len,unsigned int * ncharsp)416 static SLwchar_Type *utf8nt_to_wchars(unsigned char *s, unsigned int len, unsigned int *ncharsp)
417 {
418    SLwchar_Type *w;
419    unsigned int i, nchars;
420    unsigned char *smax;
421 
422    nchars = SLutf8_strlen(s, 0);
423    if (NULL == (w = (SLwchar_Type *)SLmalloc(nchars*sizeof(SLwchar_Type))))
424      {
425 	*ncharsp = 0;
426 	return NULL;
427      }
428 
429    smax = s + len;
430    for (i = 0; i < nchars; i++)
431      {
432 	unsigned int n;
433 	if (SLutf8_decode(s, smax, &w[i], &n) == NULL)
434 	  w[i] = '?';
435 	s += n;
436      }
437 
438    *ncharsp = nchars;
439    return w;
440 }
441 
442 # define SLSMGCHAR_EQUAL(o, n) \
443    (((o)->nchars == (n)->nchars) \
444        && ((o)->color == (n)->color) \
445        && (0 == memcmp((o)->wchars, (n)->wchars, (n)->nchars * sizeof(SLwchar_Type))))
446 
447 # define SLSMGCHAR_SET_CHAR(sc, _char) \
448    do { (sc).nchars = 1; (sc).wchars[0] = (_char); } while (0)
449 # define SLSMGCHAR_SET_COLOR(sc, _color) \
450    (sc).color = (_color)
451 # define SLSMG_COUNT_CHARS(sc) ((sc).nchars)
452 
453 #else
454 /* SLang1 versions */
455 # define SLSMGCHAR_EQUAL(o, n) ((o) == (n))
456 
457 # ifdef SLSMG_HLINE_CHAR_UNICODE
458 /* Grrr.... hack for the slang1-utf8 version hacked by RedHat and SuSE... */
459 #  define SLSMGCHAR_SET_CHAR(sc, _char) (sc) = ((sc) & 0xFF000000) + (_char)
460 #  define SLSMGCHAR_SET_COLOR(sc, _color) (sc) = ((sc) & 0xFF) + ((_color)<<24)
461 # else
462 #  define SLSMGCHAR_SET_CHAR(sc, _char) (sc) = ((sc) & 0xFF00) + (_char)
463 #  define SLSMGCHAR_SET_COLOR(sc, _color) (sc) = ((sc) & 0xFF) + ((_color)<<8)
464 # endif
465 # define SLSMG_COUNT_CHARS(sc) (1)
466 /* These exist in SLang 2 include, but not on SLang 1. Define here to allow
467  * using the same code
468  */
469 # define SLSMG_COLOR_MASK 0xFF
470 # define SLwchar_Type char
471 
472 #endif				       /* SLANG_VERSION >= 20000 */
473 
474 /* This function does the low-level drawing.
475  * It can draw the new text, but setting 'overimpose' to 1 it draws the string
476  * over the existing text (used for unicode combining characters).
477  * It can use Xft (if configured), or plain X functions.
478  */
479 
xdraw(GC_Info_Type * gc,int row,int col,SLwchar_Type * w,int nchars,int overimpose)480 static int xdraw (GC_Info_Type *gc, int row, int col, SLwchar_Type *w, int nchars, int overimpose)
481 {
482    int b = XWin->border;
483    int x = col * XWin->font_width;
484    int y = row * XWin->font_height;
485 
486 #if XJED_HAS_XRENDERFONT
487    if ((XWin->face_size > 0) && (XWin->xftdraw != NULL))
488      {
489 	/* if (!XWin->xftdraw) */
490 	/*   XWin->xftdraw = XftDrawCreate(This_XDisplay, This_XWindow, DefaultVisual(This_XDisplay, This_XScreen), XWin->color_map); */
491 
492 	if (overimpose == 0)
493 	  XftDrawRect (XWin->xftdraw, Pixel2XftColor(gc->bg), x + b, y,
494 		       nchars * XWin->font_width, XWin->font_height);
495 
496 # if SLANG_VERSION >= 20000
497 	XftDrawString32 (XWin->xftdraw, Pixel2XftColor(gc->fg), XWin->xftfont,
498 			x + b, y + b + XWin->font_base, w, nchars);
499 # else
500 	XftDrawString8 (XWin->xftdraw, Pixel2XftColor(gc->fg), XWin->xftfont,
501 			x + b, y + b + XWin->font_base, (unsigned char *)w, nchars);
502 # endif
503 	return 0;
504      }
505 #endif				       /* XJED_HAS_XRENDERFONT */
506 
507 #if SLANG_VERSION >= 20000
508      {
509 	XChar2b *d = wchars_to_XChar2b (w, nchars);
510 
511 	if (d == NULL)
512 	  return -1;
513 
514 	if (overimpose)
515 	  XDrawString16(This_XDisplay, This_XWindow, gc->gc,
516 			x + b, y + b + XWin->font_base, d, nchars);
517 	else
518 	  XDrawImageString16(This_XDisplay, This_XWindow, gc->gc,
519 			     x + b, y + b + XWin->font_base, d, nchars);
520 	SLfree((char *)d);
521 	return 0;
522      }
523 #else
524    /* Standard X, SLang 1 */
525      {
526 	if (overimpose)
527 	  XDrawString(This_XDisplay, This_XWindow, gc->gc,
528 		      x + b, y + b + XWin->font_base, w, nchars);
529 	else
530 	  XDrawImageString(This_XDisplay, This_XWindow, gc->gc,
531 			   x + b, y + b + XWin->font_base, w, nchars);
532 	return 0;
533      }
534 #endif
535 }
536 
537 /* Get 'n' characters from SLSMG screen, at position ('row', 'col'). */
smg_read_at(int row,int col,SLsmg_Char_Type * s,unsigned int n)538 static unsigned int smg_read_at(int row, int col, SLsmg_Char_Type *s, unsigned int n)
539 {
540    int saverow, savecol;
541    unsigned int rc;
542 
543    saverow = SLsmg_get_row ();
544    savecol = SLsmg_get_column ();
545    SLsmg_gotorc(row, col);
546    rc = SLsmg_read_raw (s, n);
547    SLsmg_gotorc (saverow, savecol);
548    return rc;
549 }
550 
551 /* Write to screen a single SLsmg_Char, handling combining characters
552  * (X doesn't seem to handle these...) to position (row, col).
553  * This function doesn't touch the cursor position.
554  */
JX_write_smgchar(int row,int col,SLsmg_Char_Type * s)555 static void JX_write_smgchar (int row, int col, SLsmg_Char_Type *s)
556 {
557    int color = SLSMG_EXTRACT_COLOR(*s) & SLSMG_COLOR_MASK;
558 
559    if ((color >= JMAX_COLORS) || (color < 0))
560      color = 0;
561 
562 #if SLANG_VERSION >= 20000
563    if (s->nchars > 0)
564      (void) xdraw (XWin->text_gc + color, row, col, s->wchars, 1, 0);
565 
566    if (Jed_UTF8_Mode)
567      {
568 	unsigned int i;
569 	for (i = 1; i < s->nchars; i++)
570 	  (void) xdraw(XWin->text_gc+color, row, col, &s->wchars[i], 1, 1);
571      }
572 #else
573      {
574 	SLwchar_Type ch = SLSMG_EXTRACT_CHAR(*s);
575 	(void) xdraw(XWin->text_gc+color, row, col, &ch, 1, 0);
576      }
577 #endif
578 }
579 
580 /* Write to screen a row of SLsmg_Chars, handling combining characters
581  * (X doesn't seem to handle these...) to position (row, col).
582  * This function doesn't touch the cursor position.
583  */
584 
JX_write_smgchars(int row,int col,SLsmg_Char_Type * s,SLsmg_Char_Type * smax)585 static void JX_write_smgchars(int row, int col, SLsmg_Char_Type *s, SLsmg_Char_Type *smax)
586 {
587    SLwchar_Type *b, *bend, buf[512];
588    int oldcolor, color;
589    SLsmg_Char_Type *s0;
590    int is_dual_font;
591 
592    b = buf;
593    bend = buf + 510;
594 
595    oldcolor = (SLSMG_EXTRACT_COLOR(*s) & SLSMG_COLOR_MASK);
596    if ((oldcolor < 0) || (oldcolor >= JMAX_COLORS))
597      oldcolor = 0;
598 
599    is_dual_font = XWin->is_dual_font;
600    s0 = s;
601    while (s < smax)
602      {
603         color = (SLSMG_EXTRACT_COLOR(*s) & SLSMG_COLOR_MASK);
604 	if ((color < 0) || (color >= JMAX_COLORS))
605 	  color = 0;
606 
607 	if (oldcolor != color		   /* Color changed. */
608 	    || (b >= bend)		   /* Space finished */
609 	    || SLSMG_COUNT_CHARS(*s) > 1)  /* a combining character */
610           {
611 	     (void) xdraw(XWin->text_gc+oldcolor, row, col, buf, b-buf, 0);
612 	     col += (int)(s-s0);
613 	     s0 = s;
614 	     b = buf;
615              oldcolor = color;
616           }
617 #if SLANG_VERSION >= 20000
618 	if (s->nchars > 1)
619 	  {
620 	     /* this cell has combining characters */
621 	     JX_write_smgchar(row, col, s);
622 	     col++;
623 	     s0 = s + 1;
624 	  }
625 	else if (s->nchars == 0)
626 	  {
627 	     /* SLsmg thinks this is a double width character, but the font has no such characters */
628 	     if (is_dual_font == 0)
629 	       *b++ = ' ';
630 	  }
631 	else
632 #endif
633 	  *b++ = SLSMG_EXTRACT_CHAR(*s);
634 	s++;
635      }
636    if (b != buf)
637      (void) xdraw(XWin->text_gc+color, row, col, buf, b-buf, 0);
638 }
639 
hide_cursor(void)640 static void hide_cursor (void) /*{{{*/
641 {
642    SLsmg_Char_Type sc;
643 
644    if (No_XEvents
645        || (XWin->cursor_showing == 0))
646      return;
647 
648    XWin->cursor_showing = 0;
649    if (0 == smg_read_at (XWin->vis_curs_row, XWin->vis_curs_col, &sc, 1))
650      {
651 	SLSMGCHAR_SET_CHAR(sc, ' ');
652 	SLSMGCHAR_SET_COLOR(sc, JNORMAL_COLOR);
653      }
654 
655    JX_write_smgchar(XWin->vis_curs_row, XWin->vis_curs_col, &sc);
656 }
657 /*}}}*/
658 
copy_rect(int x1,int y1,int x2,int y2,int x3,int y3)659 static void copy_rect(int x1, int y1, int x2, int y2, int x3, int y3) /*{{{*/
660 {
661    int w, h;
662 
663    if (No_XEvents || (XWin->window_mapped == 0))
664      return;
665 
666    w = (x2 - x1) * XWin->font_width;
667    h = (y2 - y1) * XWin->font_height;
668 
669    if ((w <= 0) || (h <= 0)) return;
670 
671    x3 = XWin->border + x3 * XWin->font_width;
672    x1 = XWin->border + x1 * XWin->font_width;
673    y3 = XWin->border + y3 * XWin->font_height;
674    y1 = XWin->border + y1 * XWin->font_height;
675    hide_cursor ();
676    XCopyArea (This_XDisplay, This_XWindow, This_XWindow, XWin->current_gc->gc,
677 	      x1, y1, w, h, x3, y3);
678 }
679 
680 /*}}}*/
681 
blank_rect(int x1,int y1,int x2,int y2)682 static void blank_rect (int x1,  int y1, int x2, int y2) /*{{{*/
683 {
684    int w, h;
685 
686    if (No_XEvents || (XWin->window_mapped == 0)) return;
687 
688    w = (x2 - x1) * XWin->font_width;
689    h = (y2 - y1) * XWin->font_height;
690 
691    if ((w <= 0) || (h <= 0)) return;
692 
693    x1 = XWin->border + x1 * XWin->font_width;
694    y1 = XWin->border + y1 * XWin->font_height;
695    hide_cursor ();
696    XClearArea (This_XDisplay, This_XWindow, x1, y1, w, h, 0);
697 }
698 
699 /*}}}*/
700 
JX_set_scroll_region(int r1,int r2)701 static void JX_set_scroll_region(int r1, int r2) /*{{{*/
702 {
703    XWin->scroll_r1 = r1;
704    XWin->scroll_r2 = r2;
705    /* vterm_set_scroll_region (r1, r2); */
706 }
707 
708 /*}}}*/
709 
JX_reset_scroll_region(void)710 static void JX_reset_scroll_region (void) /*{{{*/
711 {
712    JX_set_scroll_region (0, JX_Screen_Rows - 1);
713 }
714 
715 /*}}}*/
716 
show_cursor(void)717 static void show_cursor (void) /*{{{*/
718 {
719    SLsmg_Char_Type sc;
720    int row, col, b;
721    int color;
722    GC_Info_Type *gc_info;
723    GC gc;
724    XGCValues gcv;
725 
726    if (No_XEvents)
727      return;
728 
729    if (XWin->cursor_showing) hide_cursor ();
730 
731    XWin->cursor_showing = 1;
732    row = XWin->vis_curs_row = XWin->cursor_row;
733    col = XWin->vis_curs_col = XWin->cursor_col;
734    b = XWin->border;
735 
736    if ((CBuf != NULL) && (CBuf->flags & OVERWRITE_MODE))
737      color = JCURSOROVR_COLOR;
738    else
739      color = JCURSOR_COLOR;
740 
741    gc_info = &XWin->text_gc[color];
742    gc = gc_info->gc;
743 
744    if (XWin->focus)
745      {
746 	/* restore the modified GC */
747 	if (gc_info->dirty)
748 	  {
749 	     gc_info->dirty = 0;
750 	     gcv.foreground = gc_info->fg;
751 	     gcv.background = gc_info->bg;
752 	     XChangeGC(This_XDisplay, gc, GCForeground | GCBackground, &gcv);
753 	  }
754 	if (smg_read_at(row, col, &sc, 1) == 0)
755 	  SLSMGCHAR_SET_CHAR(sc, ' ');
756 	SLSMGCHAR_SET_COLOR(sc, color);
757 	JX_write_smgchar(row, col, &sc);
758      }
759    else
760      {
761 	gc_info->dirty = 1;
762 	gcv.foreground = gc_info->bg;
763 	gcv.background = gc_info->fg;
764 	XChangeGC(This_XDisplay, gc, GCForeground | GCBackground, &gcv);
765 
766 	XDrawRectangle(This_XDisplay, This_XWindow,
767 		       gc,
768 		       col * XWin->font_width + b,
769 		       row * XWin->font_height + b,
770 		       XWin->font_width - 1,
771 		       XWin->font_height - 1);
772      }
773 
774    XFlush(This_XDisplay);
775 }
776 
777 /*}}}*/
778 
toggle_cursor(int on)779 static void toggle_cursor (int on) /*{{{*/
780 {
781    if (on)
782      {
783 	if (XWin->focus) return;
784 	XWin->focus = 1;
785      }
786    else
787      {
788 	if (XWin->focus == 0) return;
789 	XWin->focus = 0;
790      }
791    show_cursor ();
792 }
793 
794 /*}}}*/
795 
796 
797 /* This routine assumes that cursor is in the correct location.  The
798  * cursor is placed at the end of the string.  Even if we are unable to
799  * write the string, make sure that the cursor is moved as if we did
800  * the write. The main reason for this is that our X cursor must track
801  * the vterm cursor so that the display gets updated properly.
802  * Otherwise, smart_puts will call forward_cursor and then write to the
803  * virtual display, and get that wrong because forward_cursor assumes
804  * that the XWin cursor is correct.
805  */
806 
JX_write_string(char * s)807 static void JX_write_string (char *s) /*{{{*/
808 {
809    unsigned int nchars;
810    SLwchar_Type *w;
811    unsigned int nbytes = strlen(s);
812 #if SLANG_VERSION >= 20000
813 
814    if (Jed_UTF8_Mode)
815      w = utf8nt_to_wchars((unsigned char *)s, nbytes, &nchars);
816    else
817      {
818 	w = bytes_to_wchars((unsigned char *)s, nbytes);
819 	nchars = nbytes;
820      }
821    if (w == NULL)
822      goto write_done;
823 
824 #else
825    nchars = nbytes;
826    w = s;
827 #endif
828 
829    if ((No_XEvents == 0) && XWin->window_mapped)
830      {
831 	hide_cursor ();
832 	(void) xdraw(XWin->current_gc, XWin->cursor_row, XWin->cursor_col, w, nchars, 0);
833      }
834 #if SLANG_VERSION >= 20000
835    SLfree((char *)w);
836    write_done:
837 #endif
838 
839    XWin->cursor_col += nchars;
840    if (XWin->cursor_col >= JX_Screen_Cols)
841      XWin->cursor_col = JX_Screen_Cols - 1;
842    if (!Performing_Update)
843      show_cursor ();
844 }
845 
JX_goto_rc(int r,int c)846 static void JX_goto_rc(int r, int c) /*{{{*/
847 {
848    if (XWin == NULL) return;
849    if (XWin->cursor_showing) hide_cursor ();
850    if (r >= JX_Screen_Rows) r = JX_Screen_Rows - 1;
851    if (c >= JX_Screen_Cols) c = JX_Screen_Cols - 1;
852    XWin->cursor_row = r + XWin->scroll_r1;
853    XWin->cursor_col = c;
854    /* vterm_goto_rc (r, c); */
855    if (Performing_Update) return;
856    show_cursor ();
857 }
858 
859 /*}}}*/
860 
861 /* Must respect scrolling region */
JX_delete_nlines(int n)862 static void JX_delete_nlines(int n) /*{{{*/
863 {
864    int r1, r2;
865 
866    /* vterm_delete_nlines (n); */
867 
868    if (No_XEvents || (XWin->window_mapped == 0))
869      return;
870 
871    r1 = XWin->cursor_row;
872    r2 = XWin->scroll_r2;
873 
874    if (r1 <= r2 - n) copy_rect(0, r1 + n, JX_Screen_Cols, r2 + 1,
875 			       0, r1);
876 
877    r2++;
878    blank_rect(0, r2 - n, JX_Screen_Cols, r2);
879 }
880 
881 /*}}}*/
882 
JX_reverse_index(int n)883 static void JX_reverse_index(int n) /*{{{*/
884 {
885    int r1, r2;
886 
887    /* vterm_reverse_index (n); */
888 
889    if (No_XEvents || (XWin->window_mapped == 0))
890      return;
891 
892    r1 = XWin->scroll_r1;
893    r2 = XWin->scroll_r2;
894 
895    if (r2 >= r1 + n) copy_rect(0, r1, JX_Screen_Cols, r2 - n + 1,
896 			       0, r1 + n);
897 
898    blank_rect(0, r1, JX_Screen_Cols, r1 + n);
899 }
900 
901 /*}}}*/
902 
JX_beep(void)903 static void JX_beep(void) /*{{{*/
904 {
905    GC gc;
906    XGCValues gcv;
907 
908    if (No_XEvents) return;
909    flush_input();
910    if (JX_Ignore_Beep & 0x1) XBell (This_XDisplay, 50);
911 
912    /* visible bell */
913 
914    if (JX_Ignore_Beep & 0x2)
915      {
916 	gc = XCreateGC(This_XDisplay, This_XWindow, 0, &gcv);
917 
918         XSetState(This_XDisplay, gc,
919 		  WhitePixel (This_XDisplay, This_XScreen),
920                   BlackPixel(This_XDisplay, This_XScreen),
921 		  GXinvert, AllPlanes);
922 
923         XFillRectangle (This_XDisplay, This_XWindow, gc,
924                         0, 0,
925 			XWin->font_width * JX_Screen_Cols,
926 			XWin->font_height * JX_Screen_Rows);
927 
928         XFlush (This_XDisplay);
929 
930 	/* I attempted to put a pause in here but it was too slow. */
931 
932         XFillRectangle (This_XDisplay, This_XWindow, gc,
933                         0, 0,
934 			XWin->font_width * JX_Screen_Cols,
935 			XWin->font_height * JX_Screen_Rows);
936 
937 	XFreeGC(This_XDisplay, gc);
938      }
939    XFlush (This_XDisplay);
940 }
941 
942 /*}}}*/
943 
JX_del_eol(void)944 static void JX_del_eol(void) /*{{{*/
945 {
946    /* vterm_del_eol (); */
947 
948    if (No_XEvents || (XWin->window_mapped == 0))
949      return;
950 
951    blank_rect(XWin->cursor_col, XWin->cursor_row, JX_Screen_Cols, XWin->cursor_row + 1);
952 }
953 
954 /*}}}*/
955 
JX_reverse_video(int color)956 static void JX_reverse_video(int color) /*{{{*/
957 {
958    if ((color < 0) || (color >= JMAX_COLORS))
959      return;
960 
961    if (XWin == NULL) return;
962    /* Current_Color = color; */
963    XWin->current_gc = XWin->text_gc + color;
964    /* vterm_reverse_video (color); */
965 }
966 
967 /*}}}*/
968 
JX_normal_video(void)969 static void JX_normal_video(void) /*{{{*/
970 {
971    JX_reverse_video (JNORMAL_COLOR);
972 }
973 
974 /*}}}*/
975 
JX_smart_puts(SLsmg_Char_Type * neww,SLsmg_Char_Type * oldd,int len,int row)976 static void JX_smart_puts(SLsmg_Char_Type *neww, SLsmg_Char_Type *oldd, int len, int row)
977 {
978    int col;
979 
980    /* Skip equal chars at the beginning */
981    col = 0;
982    while ((col < len) && SLSMGCHAR_EQUAL(&neww[col], &oldd[col]))
983      col++;
984 
985    if (col < len)
986      {
987 	hide_cursor();
988 	JX_write_smgchars(row, col, neww+col, neww+len);
989 	JX_goto_rc (row, len);
990      }
991 }
992 
993 /*}}}*/
994 
cover_exposed_area(int x,int y,int width,int height,int count)995 static void cover_exposed_area (int x, int y, int width, int height, int count) /*{{{*/
996 {
997    SLsmg_Char_Type *s;
998    int row, max_col, max_row, col;
999    int width_chars, len;
1000 
1001    Performing_Update++;
1002    /* VTerm_Suspend_Update++; */
1003    hide_cursor ();
1004    col = (x - XWin->border) / XWin->font_width;
1005    row = (y - XWin->border) / XWin->font_height;
1006 
1007    width_chars = 2 + width / XWin->font_width;
1008    max_col = col + width_chars;
1009    max_row = 2 + row + height / XWin->font_height;
1010    if (max_col > JX_Screen_Cols) max_col = JX_Screen_Cols;
1011    if (max_row > JX_Screen_Rows) max_row = JX_Screen_Rows;
1012 
1013    if (NULL != (s = (SLsmg_Char_Type *)SLmalloc(width_chars*sizeof(SLsmg_Char_Type))))
1014      {
1015 	while (row < max_row)
1016 	  {
1017 	     len = smg_read_at(row, col, s, width_chars);
1018 	     JX_write_smgchars(row, col, s, s + len);
1019 	     row++;
1020 	  }
1021 	SLfree ((char *)s);
1022      }
1023    Performing_Update--;
1024    if (count == 0) show_cursor ();
1025 }
1026 
1027 /*}}}*/
1028 
1029 #include "xkeys.c"
1030 
1031 /* Return 1 if event is listed in the switch or zero otherwise.  The switch
1032  * events are considered harmless--- that is, processing them does not really
1033  * interfere with internal JED state (redisplay, etc...).  More bluntly,
1034  * harmless means that the events can be processesed while checking for
1035  * pending input.
1036  */
1037 static int Debug_Xjed = 0;
x_handle_harmless_events(XEvent * report)1038 static int x_handle_harmless_events (XEvent *report) /*{{{*/
1039 {
1040    switch (report->type)
1041      {
1042       case EnterNotify:
1043 	toggle_cursor(report->xcrossing.focus);
1044 	break;
1045 
1046       case LeaveNotify:
1047 	/* toggle_cursor(0); */
1048 	break;
1049 
1050       case UnmapNotify:
1051 	XWin->window_mapped = 0;
1052 	break;
1053       case MapNotify:
1054 	XWin->window_mapped = 1;
1055 	break;
1056 
1057       case FocusIn:
1058 	toggle_cursor(1);
1059 #ifdef XJED_USE_R6IM
1060 	if (NULL != R6IM_Xic)
1061 	  XSetICFocus (R6IM_Xic);
1062 #endif
1063 	Check_Buffers_Pending = 1;
1064 	break;
1065 
1066       case FocusOut:
1067 	toggle_cursor(0);
1068 #ifdef XJED_USE_R6IM
1069 	if (NULL != R6IM_Xic)
1070 	  XUnsetICFocus (R6IM_Xic);
1071 #endif
1072 	break;
1073 
1074       case VisibilityNotify: XWin->visible = report->xvisibility.state;
1075 	break;
1076 
1077       case GraphicsExpose:
1078 	cover_exposed_area (report->xgraphicsexpose.x,
1079 			    report->xgraphicsexpose.y,
1080 			    report->xgraphicsexpose.width,
1081 			    report->xgraphicsexpose.height,
1082 			    report->xgraphicsexpose.count);
1083 	break;
1084 
1085       case ConfigureNotify:
1086 	if ((report->xconfigure.height == XWin->height)
1087 	    && (report->xconfigure.width == XWin->width))
1088 	  break;
1089 
1090 	XWin->width = report->xconfigure.width;
1091 	XWin->height = report->xconfigure.height;
1092 	jed_init_display ();
1093 	jed_redraw_screen (1);
1094 	break;
1095 
1096       case Expose:
1097 	cover_exposed_area (report->xexpose.x,
1098 			    report->xexpose.y,
1099 			    report->xexpose.width,
1100 			    report->xexpose.height,
1101 			    report->xexpose.count);
1102 	break;
1103 
1104       case ReparentNotify:
1105       case NoExpose:
1106 	break;
1107 
1108       case KeyPress:
1109 	/* Just look for Modifier key presses */
1110 #ifdef XJED_USE_R6IM
1111 	if (R6IM_Xic && (R6IM_Input_Style & XIMPreeditPosition))
1112 	  move_input_position ();
1113 #endif
1114 	return IsModifierKey (XLookupKeysym (&report->xkey, 0));
1115 
1116       case SelectionNotify:
1117 	(void) receive_selection (report);
1118 	if (Performing_Update == 0)
1119 	  update_cmd (&Number_One);
1120 	break;
1121 
1122       default:
1123 	if (Debug_Xjed)
1124 	  fprintf(stderr, "harmless: %d\n", report->type);
1125 	return 0;
1126      }
1127    return 1;
1128 }
1129 
1130 /*}}}*/
1131 
fill_jmouse(JMouse_Type * jmouse,unsigned char type,int x,int y,unsigned long t,unsigned int button,unsigned int state)1132 static void fill_jmouse (JMouse_Type *jmouse, /*{{{*/
1133 			 unsigned char type, int x, int y, unsigned long t,
1134 			 unsigned int button, unsigned int state)
1135 {
1136    unsigned char s;
1137 #if JED_HAS_MULTICLICK
1138    static unsigned long last_press_time;
1139    static unsigned int clicks;
1140    static unsigned int last_button;
1141 
1142    if (type == JMOUSE_DOWN)
1143      {
1144 	if ((last_button == button)
1145 	    && (last_press_time + JX_MultiClick_Time > t))
1146 	  {
1147 	     clicks++;
1148 	     if (clicks == 2)
1149 	       type = JMOUSE_DOUBLE_CLICK;
1150 	     else
1151 	       type = JMOUSE_TRIPLE_CLICK;
1152 	  }
1153 	else
1154 	  {
1155 	     clicks = 1;
1156 	     last_button = button;
1157 	  }
1158 	last_press_time = t;
1159      }
1160    else if ((clicks > 1) && (last_button == button))
1161      {
1162 	/* Last was a multi-click.  Ignore this event. */
1163 	type = JMOUSE_IGNORE_EVENT;
1164      }
1165 #endif
1166    jmouse->type = type;
1167    jmouse->x = 1 + (x - XWin->border) / XWin->font_width;
1168 
1169    if (y < XWin->border) jmouse->y = 0;
1170    else jmouse->y = 1 + (y - XWin->border) / XWin->font_height;
1171 
1172    if (button == Button1) jmouse->button = JMOUSE_BUTTON_1;
1173    else if (button == Button2) jmouse->button = JMOUSE_BUTTON_2;
1174    else if (button == Button3) jmouse->button = JMOUSE_BUTTON_3;
1175    else if (button == Button4) jmouse->button = JMOUSE_BUTTON_4;
1176    else if (button == Button5) jmouse->button = JMOUSE_BUTTON_5;
1177    else jmouse->button = JMOUSE_BUTTON_6;
1178 
1179    s = 0;
1180    if (state & Button1Mask) s |= JMOUSE_BUTTON_1;
1181    if (state & Button2Mask) s |= JMOUSE_BUTTON_2;
1182    if (state & Button3Mask) s |= JMOUSE_BUTTON_3;
1183    if (state & Button4Mask) s |= JMOUSE_BUTTON_4;
1184    if (state & Button5Mask) s |= JMOUSE_BUTTON_5;
1185    if (state & Button6Mask) s |= JMOUSE_BUTTON_5;
1186    if (state & ShiftMask) s |= JMOUSE_SHIFT;
1187    if (state & ControlMask) s |= JMOUSE_CTRL;
1188 
1189    jmouse->state = s;
1190 }
1191 
1192 /*}}}*/
1193 
1194 #define MOUSE_DRAG_THRESHOLD 3
1195 
1196 /* if force is true, wait for an event.  If force is false, only
1197  *  process events that exist.  This will return either when there
1198  *  are no more events or a key/mouse event is processed returning
1199  *  1 in the process */
X_process_events(int force,char * buf,unsigned int buflen,int * n_chars)1200 static int X_process_events (int force, char *buf, unsigned int buflen,
1201 			     int *n_chars) /*{{{*/
1202 {
1203    XEvent report;
1204    JMouse_Type jmouse;
1205    int ch1;
1206    int block_expose = 0;
1207    char *bufp;
1208    KeySym ks = 0;
1209    int esc = 27;
1210 
1211    Window root, child;
1212    int posx, posy, rootx, rooty;
1213    unsigned int keys_buttons;
1214    int last_x, last_y;
1215    static int last_event, last_motion_down_button;
1216    static unsigned int motion_state;
1217 #if MOUSE_DRAG_THRESHOLD
1218    static int button_press_x, button_press_y;
1219 #endif
1220    int width, height;
1221 
1222    while (force || XPending(This_XDisplay))
1223      {
1224 	XNextEvent(This_XDisplay, &report);
1225 	Current_Event = report;
1226 
1227 	switch (report.type)
1228 	  {
1229 	   case ClientMessage:
1230 	     if ((report.xclient.format == 32) &&
1231 		 ((Atom) report.xclient.data.l[0] == XWin->wm_del_win))
1232 	       jed_exit_jed (1);
1233 	     break;
1234 
1235 	   case MotionNotify:
1236 
1237 	     /* Make sure we get the last event of this type */
1238 	     while (XCheckMaskEvent (This_XDisplay, ButtonMotionMask, &report))
1239 	       ;
1240 
1241 	     if (!XQueryPointer(This_XDisplay, report.xmotion.window,
1242 				&root, &child, &rootx, &rooty, &posx, &posy,
1243 				&keys_buttons)) break;
1244 
1245 	     /* This will ensure that modifier keys are not pressed while
1246 	        we are in motion. */
1247 
1248 	     if ((last_event == MotionNotify)
1249 		 && (motion_state != keys_buttons))
1250 	       break;
1251 
1252 	     motion_state = keys_buttons;
1253 
1254 	     memset ((char *) &jmouse, 0, sizeof (jmouse));
1255 	     last_x = jmouse.x;
1256 	     last_y = jmouse.y;
1257 
1258 	     fill_jmouse (&jmouse, JMOUSE_DRAG,
1259 			  posx, posy, report.xmotion.time,
1260 			  last_motion_down_button, keys_buttons);
1261 
1262 #if MOUSE_DRAG_THRESHOLD
1263 	     if ((abs(button_press_x - posx) <= MOUSE_DRAG_THRESHOLD)
1264 		 && (abs(button_press_y - posy) <= MOUSE_DRAG_THRESHOLD))
1265 	       break;
1266 #endif
1267 	     if ((last_x == jmouse.x) && (last_y == jmouse.y)) break;
1268 	     if (-1 == (ch1 = jed_mouse_add_event (&jmouse)))
1269 	       break;		       /* queue full */
1270 
1271 	     /* return ESC ^@ */
1272 	     *buf++ = esc; *buf++ = 0; *buf++ = ch1;
1273 	     *n_chars = 3;
1274 
1275 	     last_event = MotionNotify;
1276 	     return 1;
1277 
1278 	   case Expose:
1279 	     if (block_expose == 0) cover_exposed_area (report.xexpose.x,
1280 							report.xexpose.y,
1281 							report.xexpose.width,
1282 							report.xexpose.height,
1283 							report.xexpose.count);
1284 	     else
1285 	       {
1286 		  if (report.xexpose.count == 0)
1287 		    {
1288 		       jed_redraw_screen (1);
1289 		       block_expose = 0;
1290 		    }
1291 	       }
1292 	     break;
1293 
1294 	   case ConfigureNotify:
1295 	     width = report.xconfigure.width;
1296 	     height = report.xconfigure.height;
1297 	     if ((width != XWin->width) ||
1298 		 (height != XWin->height))
1299 	       {
1300 		  XWin->width = width;
1301 		  XWin->height = height;
1302 		  jed_init_display ();
1303 		  jed_redraw_screen (0);
1304 		  block_expose = -1;
1305 	       }
1306 #ifdef XJED_USE_R6IM
1307 	     if (R6IM_Input_Style & XIMPreeditArea)
1308 	       {
1309 		  set_geometry (&report, XIMPreeditArea, XNPreeditAttributes);
1310 		  set_geometry (&report, XIMStatusArea, XNStatusAttributes);
1311 	       }
1312 #endif
1313 	     break;
1314 
1315 	   case ButtonPress:
1316 	     /* Prohibit dragging more than one button at a time. */
1317 	     if (last_event == MotionNotify) break;
1318 	     /* drop */
1319 
1320 	   case ButtonRelease:
1321 	     if ((last_event == MotionNotify) &&
1322 		 (report.xbutton.button != (unsigned int) last_motion_down_button))
1323 	       break;
1324 
1325 #if MOUSE_DRAG_THRESHOLD
1326 	     if (report.type == ButtonPress)
1327 	       {
1328 		  button_press_x = report.xbutton.x;
1329 		  button_press_y = report.xbutton.y;
1330 	       }
1331 	     else
1332 	       {
1333 		  button_press_x = 0;
1334 		  button_press_y = 0;
1335 	       }
1336 #endif
1337 	     last_event = 0;
1338 
1339 	     fill_jmouse (&jmouse,
1340 			  ((report.type == ButtonRelease) ? JMOUSE_UP : JMOUSE_DOWN),
1341 			  report.xbutton.x, report.xbutton.y, report.xbutton.time,
1342 			  report.xbutton.button, report.xbutton.state);
1343 
1344 	     if (-1 == (ch1 = jed_mouse_add_event (&jmouse)))
1345 	       break;		       /* queue full */
1346 
1347 	     if ((report.type == ButtonPress)
1348 		 && (0 == (report.xbutton.state
1349 			   & (Button1Mask|Button2Mask|Button3Mask
1350 			      |Button4Mask|Button5Mask|Button6Mask))))
1351 	       last_motion_down_button = report.xbutton.button;
1352 
1353 	     /* ESC ^@ is a  mouse prefix */
1354 	     *buf++ = esc; *buf++ = 0; *buf++ = ch1;
1355 	     *n_chars = 3;
1356 
1357 	     return 1;
1358 
1359 #if HAS_IBM_NUMLOCK_CODE
1360 	   case KeyRelease:
1361 	     if ((report.xkey.keycode != 98)
1362 # if 0
1363 		 || (0 != strcmp (The_Xserver_Vendor,
1364 				  "International Business Machines"))
1365 # endif
1366 		 )
1367 	       {
1368 		  (void) x_handle_harmless_events (&report);
1369 		  break;
1370 	       }
1371 	     /* Drop */
1372 #endif
1373 	   case KeyPress:
1374 	     bufp = buf;
1375 #ifndef XJED_USE_R6IM
1376 	     *n_chars = XLookupString(&report.xkey, buf, buflen, &ks, NULL);
1377 #else
1378 	     if (!XFilterEvent (&report, report.xkey.window))
1379 	       {
1380 		  Status status_return;
1381 		  if (R6IM_Xic != NULL)
1382 		    {
1383 #if USE_XUTF8_CODE
1384 		       if (Jed_UTF8_Mode)
1385 			 *n_chars = Xutf8LookupString (R6IM_Xic, &report.xkey, buf, buflen,
1386 						       &ks, &status_return);
1387 		       else
1388 #endif
1389 
1390 			 *n_chars = XmbLookupString (R6IM_Xic, &report.xkey, buf, buflen,
1391 						     &ks, &status_return);
1392 		    }
1393 		  else
1394 		    *n_chars = XLookupString(&report.xkey, buf, buflen, &ks, NULL);
1395 
1396 	       }
1397 	     else
1398 	       *n_chars = 0;
1399 #endif
1400 	     ks = ks & 0xFFFF;
1401 	     X_Last_Keysym = ks;
1402 #if USE_NEW_META_CODE
1403 	     if ((*n_chars == 0) && (ks > 0x00FF) && (ks < 0x0FFF))
1404 	       {
1405 		  *n_chars = 1;
1406 		  buf[0] = ks & 0x00FF ;
1407 	       }
1408 #endif
1409 
1410 	     bufp = (char *)map_keysym_to_keyseq (ks, report.xkey.state & (ShiftMask|ControlMask));
1411 	     if (bufp != NULL)
1412 	       {
1413 		  *n_chars = (unsigned char) *bufp++;
1414 #if USE_NEW_META_CODE
1415 		  if (report.xkey.state & JX_MetaMask)
1416 		    {
1417 		       buf[0] = X_Alt_Char;
1418 		       SLMEMCPY (buf + 1, bufp, *n_chars);
1419 		       *n_chars += 1;
1420 		    }
1421 		  else
1422 #endif
1423 		    SLMEMCPY(buf, bufp, *n_chars);
1424 	       }
1425 	     else if (*n_chars == 1)
1426 	       {
1427 		  if (bufp == NULL)
1428 		    bufp = buf;
1429 
1430 		  if (report.xkey.state & JX_MetaMask)
1431 		    {
1432 		       ch1 = *bufp;
1433 #if 0
1434 		       /* Only do this on alphabetic characters.  This
1435 			* is because, e.g., german keyboards use 'Alt-{'
1436 			* to generate the '{' character
1437 			*/
1438 		       if (isalnum (ch1) && (ch1 < 0x80))
1439 			 {
1440 #endif
1441 			    if (X_Alt_Char <= 0) *buf |= 0x80;
1442 			    else
1443 			      {
1444 				 *bufp++ = (unsigned char) X_Alt_Char;
1445 				 *bufp = (unsigned char) ch1;
1446 				 *n_chars = 2;
1447 			      }
1448 #if 0
1449 			 }
1450 #endif
1451 		    }
1452 		  else if (report.xkey.state & ControlMask)
1453 		    {
1454 		       if (*buf == ' ') *buf = 0;
1455 		       else if (*buf == '-') *buf = 0x1F;
1456 		    }
1457 	       }
1458 
1459 	     if (*n_chars == 0) break;
1460 	     return 1;
1461 
1462 	   case SelectionNotify:
1463 	     (void) receive_selection (&report);
1464 	     break;
1465 	   case SelectionClear:
1466 	     SLfree (Selection_Send_Data);   /* NULL ok */
1467 	     Selection_Send_Data = NULL;
1468 	     break;
1469 	   case SelectionRequest:
1470 	     (void) send_selection (&report);
1471 	     break;
1472 
1473 	   default:
1474 	     (void) x_handle_harmless_events (&report);
1475 	  }
1476      }
1477    return 0;
1478 }
1479 
1480 /*}}}*/
1481 
X_read_key(void)1482 static int X_read_key (void) /*{{{*/
1483 {
1484    int nread;
1485    char buf[64];
1486    (void) X_process_events (1, buf, sizeof (buf), &nread);
1487    if (nread > 1) ungetkey_string(buf + 1, nread - 1);
1488    return (int) *buf;
1489 }
1490 
1491 /*}}}*/
1492 
X_input_pending(void)1493 static int X_input_pending (void) /*{{{*/
1494 {
1495    XEvent ev;
1496 
1497    int n;
1498 
1499    if (No_XEvents) return 0;
1500 #if 1
1501    /* XCheckMaskEvent searches the queue and removes the specified event. */
1502    if (0 != XCheckMaskEvent(This_XDisplay, KeyPressMask, &ev))
1503      {
1504 	/* XPutBackEvent pushes the event to the head of the event queue-- no return value */
1505 	XPutBackEvent(This_XDisplay, &ev);
1506 	return 1;
1507      }
1508 #endif
1509    n = XPending (This_XDisplay);
1510    while (n > 0)
1511      {
1512 	XPeekEvent(This_XDisplay, &ev);
1513 	if (0 == x_handle_harmless_events (&ev)) return 1;
1514 	XNextEvent(This_XDisplay, &ev);
1515 	n--;
1516      }
1517    return 0;
1518 }
1519 
1520 /*}}}*/
1521 
JX_get_display_size(int * rows,int * cols)1522 static void JX_get_display_size (int *rows, int *cols) /*{{{*/
1523 {
1524    JX_Screen_Cols = (XWin->width - XWin->border) / XWin->font_width;
1525    JX_Screen_Rows = (XWin->height - XWin->border) / XWin->font_height;
1526    *cols = JX_Screen_Cols;
1527    *rows = JX_Screen_Rows;
1528 }
1529 
1530 /*}}}*/
1531 
JX_set_term_vtxxx(int * n)1532 static void JX_set_term_vtxxx (int *n) /*{{{*/
1533 {
1534    (void) n;
1535 }
1536 
1537 /*}}}*/
1538 
JX_narrow_width(void)1539 static void JX_narrow_width (void) /*{{{*/
1540 {
1541 }
1542 
1543 /*}}}*/
1544 
JX_wide_width(void)1545 static void  JX_wide_width (void) /*{{{*/
1546 {
1547 }
1548 
1549 /*}}}*/
1550 
JX_enable_cursor_keys(void)1551 static void JX_enable_cursor_keys(void) /*{{{*/
1552 {
1553 }
1554 
1555 /*}}}*/
1556 
JX_cls(void)1557 static void JX_cls(void) /*{{{*/
1558 {
1559    /* vterm_cls (); */
1560 
1561    if (No_XEvents) return;
1562    if (XWin->window_mapped == 0) return;
1563    XClearWindow(This_XDisplay, This_XWindow);
1564 }
1565 
1566 /*}}}*/
1567 
1568 /* This routine is called from S-Lang inner interpreter.  It serves
1569    as a poor mans version of an interrupt 9 handler */
xjed_check_kbd(void)1570 static void xjed_check_kbd(void) /*{{{*/
1571 {
1572    char buf[64];
1573    int n;
1574    register char *b, *bmax;
1575 
1576    if (Batch || No_XEvents) return;
1577    while (XPending(This_XDisplay))
1578      {
1579 	if (X_process_events (0, buf, sizeof (buf), &n) == 0) continue;
1580 
1581 	b = buf; bmax = b + n;
1582 	while (b < bmax)
1583 	  {
1584 	     if (*b == (char) Jed_Abort_Char)
1585 	       {
1586 		  if (Ignore_User_Abort == 0)
1587 		    SLang_set_error (USER_BREAK);
1588 		  if (b != buf) buffer_keystring (buf, (int) (b - buf));
1589 		  SLKeyBoard_Quit = 1;
1590 		  break;
1591 	       }
1592 	     b++;
1593 	  }
1594 	if (!SLKeyBoard_Quit) buffer_keystring (buf, n);
1595      }
1596 }
1597 
1598 /*}}}*/
1599 
xjed_suspend(void)1600 static void xjed_suspend (void) /*{{{*/
1601 {
1602    if (No_XEvents) return;
1603    if (XWin->focus)
1604      {
1605 	/* XIconifyWindow (This_XDisplay, XWin->w, This_XScreen); */
1606 	if (XWin->visible == VisibilityUnobscured) XLowerWindow (This_XDisplay, This_XWindow);
1607 	else XRaiseWindow (This_XDisplay, This_XWindow);
1608      }
1609    else
1610      {
1611 	/* The window doesn't have focus which means that this was most
1612 	 * likely called by pressing Ctrl-Z from another window.
1613 	 */
1614 	fprintf (stderr, "jed stopping\n");
1615 #ifdef SIGSTOP
1616 	kill (0, SIGSTOP);
1617 #endif
1618 	/* sys_suspend (); */
1619      }
1620 }
1621 
1622 /*}}}*/
1623 
x_toggle_visibility(void)1624 static void x_toggle_visibility (void) /*{{{*/
1625 {
1626    int hide_win = (XWin->visible == VisibilityUnobscured);
1627 
1628    if ((SLang_Num_Function_Args == 1)
1629        && (-1 == SLang_pop_integer (&hide_win)))
1630      return;
1631 
1632    if (hide_win)
1633      /* XIconifyWindow (This_XDisplay, XWin->w, This_XScreen); */
1634      XLowerWindow (This_XDisplay, This_XWindow);
1635    else
1636      XRaiseWindow (This_XDisplay, This_XWindow);
1637 }
1638 /*}}}*/
1639 
1640 
get_font_width(XFontStruct * f,int * wp,int * is_dualp)1641 static int get_font_width (XFontStruct *f, int *wp, int *is_dualp)
1642 {
1643    int w0, w1;
1644 
1645    *is_dualp = 0;
1646    if (f->min_bounds.width == f->max_bounds.width)
1647      {
1648 	*wp = f->max_bounds.width;
1649 	return 0;
1650      }
1651 
1652    /* Simple heristic */
1653    w0 = XTextWidth (f, "M", 1);
1654    w1 = XTextWidth (f, "l", 1);
1655    if (w0 != w1)
1656      (void) fprintf (stderr, "This font does not appear to be single-width.  Expect rendering problems.\n");
1657 
1658 #if SLANG_VERSION >= 20000
1659    if (Jed_UTF8_Mode
1660        && (f->min_bounds.width * 2 == f->max_bounds.width))
1661      {
1662 	*wp = f->min_bounds.width;
1663 	*is_dualp = 1;
1664 	return 0;
1665      }
1666 #endif
1667 
1668    *wp = f->max_bounds.width;
1669    return 0;
1670 }
1671 
load_font(char * font)1672 static int load_font (char *font) /*{{{*/
1673 {
1674    static XFontStruct *xfont;
1675 
1676 #if XJED_HAS_XRENDERFONT
1677    if (XWin->face_size > 0)
1678      {
1679 	/* the user wants xrender */
1680 	XWin->xftfont = XftFontOpen(This_XDisplay, This_XScreen,
1681 				    XFT_FAMILY, XftTypeString, font,
1682 				    XFT_SIZE, XftTypeDouble, XWin->face_size,
1683 				    XFT_SPACING, XftTypeInteger, XFT_MONO,
1684 				    NULL);
1685 	if (XWin->xftfont == NULL) return -1;
1686 	XWin->font_name = font;
1687 	XWin->font_height = XWin->xftfont->ascent + XWin->xftfont->descent;
1688 	XWin->font_width = XWin->xftfont->max_advance_width;
1689 	XWin->font_base = XWin->xftfont->ascent;
1690 	return 0;
1691      }
1692 #endif
1693    xfont = XLoadQueryFont(This_XDisplay, font);
1694    if (xfont == NULL) return -1;
1695    XWin->font = xfont;
1696    XWin->font_name = font;
1697    XWin->font_height = xfont->ascent + xfont->descent;
1698    XWin->font_base = xfont->ascent;
1699    (void) get_font_width (xfont, &XWin->font_width, &XWin->is_dual_font);
1700    if (XWin->font_width <= 0)
1701      {
1702 	fprintf (stderr, "Font width for %s is <= 0\n", font);
1703 	return -1;
1704      }
1705    return 0;
1706 }
1707 
1708 /*}}}*/
1709 
get_xdefaults(void)1710 static void get_xdefaults (void) /*{{{*/
1711 {
1712    XWindow_Arg_Type *xargs = X_Arg_List + XARG_START;  /* skip display, name, etc */
1713 
1714    while (xargs->name != NULL)
1715      {
1716 	if (xargs->dflt == NULL)
1717 	  {
1718 	     xargs++;
1719 	     continue;
1720 	  }
1721 
1722 	if ((xargs->type != VOID_TYPE)
1723 	    && (xargs->value == NULL))
1724 	  {
1725 	     static char *class_names[] =
1726 	       {
1727 		  "UXjed", "UXJed", "uxjed", NULL
1728 	       };
1729 	     char *p, *cn;
1730 	     char **cnp;
1731 
1732 	     /* Note that strings returned by XGetDefault are owned by
1733 	      * Xlib and should not be modified or freed by the client.
1734 	      * However, the solaris folks apparantly are not aware of this
1735 	      * and the following two function calls produce memory leaks.
1736 	      * Sigh.
1737 	      */
1738 	     p = NULL;
1739 #if SLANG_VERSION >= 20000
1740 	     if (Jed_UTF8_Mode)
1741 	       {
1742 		  cnp = class_names;
1743 		  while (NULL != (cn = *cnp++))
1744 		    {
1745 		       p = XGetDefault (This_XDisplay, cn, xargs->name);
1746 		       if (p != NULL)
1747 			 break;
1748 		    }
1749 	       }
1750 #endif
1751 	     if (p == NULL)
1752 	       {
1753 		  cnp = class_names;
1754 		  while (NULL != (cn = *cnp++))
1755 		    {
1756 		       cn++;	       /* Skip leading U */
1757 		       p = XGetDefault (This_XDisplay, cn, xargs->name);
1758 		       if (p != NULL)
1759 			 break;
1760 		    }
1761 	       }
1762 	     if (p == NULL)
1763 	       {
1764 #if SLANG_VERSION >= 20000
1765 		  if (Jed_UTF8_Mode)
1766 		    p = XGetDefault (This_XDisplay, "UXTerm", xargs->name);
1767 #endif
1768 		  if (p == NULL)
1769 		    p = XGetDefault (This_XDisplay, "XTerm", xargs->name);
1770 	       }
1771 
1772 	     if (p != NULL)
1773 	       xargs->value = p;
1774 	  }
1775 
1776 	if (xargs->value != NULL)
1777 	  *xargs->dflt = xargs->value;
1778 
1779 	xargs++;
1780      }
1781 }
1782 
1783 /*}}}*/
1784 
set_window_name(char * s)1785 static void set_window_name (char *s) /*{{{*/
1786 {
1787    if (Batch) return;
1788    XStoreName (This_XDisplay, XWin->w, s);
1789 }
1790 
1791 /*}}}*/
1792 
set_icon_name(char * s)1793 static void set_icon_name (char *s) /*{{{*/
1794 {
1795    if (Batch) return;
1796    XSetIconName(This_XDisplay, XWin->w, s);
1797 }
1798 
1799 /*}}}*/
1800 
1801 #if 0
1802 static void set_wm_hints (JXWindow_Type *w, int xpos,  int ypos, unsigned long orflags) /*{{{*/
1803 {
1804    XSizeHints h;
1805    XWMHints h1;
1806    XClassHint ch;
1807 
1808    ch.res_name = "xjed";
1809    ch.res_class = "XJed";
1810 
1811    h.width_inc = w->font_width;
1812    h.height_inc = w->font_height;
1813    h.min_width = 5 * w->font_width + w->border;
1814    h.min_height = 5 * w->font_height + w->border;
1815    h.base_height = 0;
1816    h.base_width = 0;
1817    h.x = xpos; h.y = ypos;
1818    h.height = w->height;
1819    h.width = w->width;
1820 
1821    h.flags = PMinSize | PResizeInc | PBaseSize;
1822    h.flags |= orflags;
1823 
1824    XSetWMNormalHints(This_XDisplay, w->w, &h);
1825 
1826    /* This bit allows me to track the focus.  It is not at all clear from
1827       the documentation. */
1828    h1.input = 1;
1829    h1.flags = InputHint;
1830    XSetWMHints(This_XDisplay, w->w, &h1);
1831 # if 0
1832    XSetClassHint(This_XDisplay, w->w, &ch);
1833 # endif
1834 }
1835 
1836 /*}}}*/
1837 #endif
1838 
alloc_color(char * color_name,XColor * color_info)1839 static int alloc_color(char* color_name, XColor* color_info)
1840 {
1841    XColor exact_info;
1842 
1843    if (XAllocNamedColor(This_XDisplay, XWin->color_map, color_name, color_info,
1844 			&exact_info))
1845      return color_info->pixel;
1846 
1847    if (0 == strncmp (color_name, "bright", 6))
1848      color_name += 6;
1849 
1850    if (XAllocNamedColor(This_XDisplay, XWin->color_map, color_name, color_info,
1851 			&exact_info))
1852      return color_info->pixel;
1853 
1854    fprintf(stderr, "Can't allocate color %s\n", color_name);
1855    return -1;
1856 }
1857 
1858 /* This parses the colors in the XWin structure and setting
1859    defaults to fg, bg upon failure of either one */
setup_ith_color(int i)1860 static void setup_ith_color (int i) /*{{{*/
1861 {
1862    XColor xcol;
1863    int fg, bg;
1864 
1865    if (!Term_Supports_Color)
1866      return;
1867 
1868    fg = alloc_color(XWin->text_gc[i].fg_name, &xcol);
1869    bg = alloc_color(XWin->text_gc[i].bg_name, &xcol);
1870 
1871    if ((fg < 0) || (bg < 0))
1872      return;
1873 
1874    XWin->text_gc[i].fg = fg;
1875    XWin->text_gc[i].bg = bg;
1876 }
1877 
1878 /*}}}*/
1879 
1880 /* This is used to set the colors in the Win structure and if f is non-zero,
1881  * the previous definitions are freed.  f is 0 when the colors correspond to the
1882  * default. */
1883 
x_set_color_free(int i,char * fgcolor,char * bgcolor,int do_free)1884 static void x_set_color_free (int i, char *fgcolor, char *bgcolor, int do_free) /*{{{*/
1885 {
1886    char *save_fg, *save_bg, *fg, *bg;
1887 
1888    if ((*fgcolor == 0) || !strcmp (fgcolor, "default"))
1889      fgcolor = XWin->text_gc[0].fg_name;
1890 
1891    if ((*bgcolor == 0) || !strcmp (bgcolor, "default"))
1892      bgcolor = XWin->text_gc[0].bg_name;
1893 
1894    if (NULL == (fg = SLmalloc(strlen(fgcolor) + 1)))
1895      return;
1896 
1897    strcpy (fg, fgcolor);
1898    if (NULL == (bg = SLmalloc (strlen(bgcolor) + 1)))
1899      {
1900 	SLfree (fg);
1901 	return;
1902      }
1903    strcpy (bg, bgcolor);
1904 
1905    save_fg = XWin->text_gc[i].fg_name;
1906    XWin->text_gc[i].fg_name = fg;
1907    save_bg = XWin->text_gc[i].bg_name;
1908    XWin->text_gc[i].bg_name = bg;
1909 
1910    setup_ith_color (i);
1911    if (do_free)
1912      {
1913 	if (save_fg != NULL) SLfree (save_fg);
1914 	if (save_bg != NULL) SLfree (save_bg);
1915      }
1916 }
1917 
1918 /*}}}*/
1919 
setup_and_parse_colors(void)1920 static int setup_and_parse_colors (void) /*{{{*/
1921 {
1922    unsigned long fg, bg, tmp;
1923    char *fg_name, *bg_name;
1924 
1925    int i;
1926    GC_Info_Type *d;
1927 
1928    /* Check to see if this is a color display */
1929 
1930    bg = WhitePixel (This_XDisplay, This_XScreen);
1931    fg = BlackPixel (This_XDisplay, This_XScreen);
1932 
1933    fg_name = Default_GC_Info[0].fg_name;
1934    bg_name = Default_GC_Info[0].bg_name;
1935 
1936    XWin->color_map = DefaultColormap (This_XDisplay, This_XScreen);
1937 #if 0
1938    if (XWin->color_map == NULL)
1939      {
1940 	fprintf (stderr, "Unable to get a colormap\n");
1941 	exit (1);
1942      }
1943 #endif
1944    if (DisplayCells (This_XDisplay, This_XScreen) > 2)
1945      {
1946 	Term_Supports_Color = 1;
1947      }
1948    else Term_Supports_Color = 0;
1949 
1950    for (i = 0; i < JMAX_COLORS; i++)
1951      {
1952 	d = Default_GC_Info + i;
1953 	/* The assumption here is that ALL colors beyond JNORMAL_COLOR (0)
1954 	 * take reversed fg, bgs.  I really ought to have flags if this is
1955 	 * not the case. */
1956 	d->fg = fg;
1957 	d->bg = bg;
1958 	if (d->fg_name == NULL) d->fg_name = fg_name;
1959 	if (d->bg_name == NULL) d->bg_name = bg_name;
1960 
1961 	if (i == JNORMAL_COLOR)
1962 	  {
1963 	     char *tmp_name;
1964 	     tmp = fg; fg = bg; bg = tmp;
1965 	     tmp_name = fg_name; fg_name = bg_name; bg_name = tmp_name;
1966 	  }
1967 
1968 	x_set_color_free (i, d->fg_name, d->bg_name, 0);
1969      }
1970 
1971    return 0;
1972 }
1973 
1974 /*}}}*/
1975 
set_mouse_color(char * fgc,char * bgc)1976 static void set_mouse_color (char *fgc, char *bgc) /*{{{*/
1977 {
1978    XColor xfg, xbg;
1979 
1980    if (0 == Term_Supports_Color)
1981      return;
1982 
1983    if (alloc_color(fgc, &xfg) < 0)
1984      return;
1985    if (alloc_color(bgc, &xbg) < 0)
1986      return;
1987 
1988    XRecolorCursor (This_XDisplay, XWin->mouse, &xfg, &xbg);
1989 }
1990 
1991 /*}}}*/
1992 
create_needed_gcs(void)1993 static void create_needed_gcs (void) /*{{{*/
1994 {
1995    int i;
1996    XGCValues xgcv;
1997 
1998 #if XJED_HAS_XRENDERFONT
1999    if (XWin->face_size == 0)
2000 #endif
2001      xgcv.font = XWin->font->fid;
2002 
2003    for (i = 0; i < JMAX_COLORS; i++)
2004      {
2005 	xgcv.foreground = XWin->text_gc[i].fg;
2006 	xgcv.background = XWin->text_gc[i].bg;
2007 
2008 #if XJED_HAS_XRENDERFONT
2009 	if (XWin->face_size > 0)
2010 	  {
2011 	     XWin->text_gc[i].gc = XCreateGC(This_XDisplay, This_XWindow,
2012 					     GCForeground | GCBackground /*| GCFont*/, /* XFT */
2013 					     &xgcv);
2014 	  }
2015 	else
2016 #endif
2017 	  XWin->text_gc[i].gc = XCreateGC(This_XDisplay, This_XWindow,
2018 					  GCForeground | GCBackground | GCFont,
2019 					  &xgcv);
2020      }
2021 }
2022 
2023 /*}}}*/
2024 
create_XWindow(JXWindow_Type * win)2025 static Window create_XWindow (JXWindow_Type *win) /*{{{*/
2026 {
2027    int bdr, x, y, flags;
2028    unsigned int width, height;
2029    XSizeHints sizehint;
2030    XClassHint xcls;
2031    XWMHints wmhint;
2032    long key_event_type;
2033 
2034    bdr = atoi(This_Border_Width_Name);
2035 
2036    if (This_Geometry == NULL)
2037      This_Geometry = Default_Geometry;
2038 
2039    sizehint.flags = 0;
2040    flags = XParseGeometry (This_Geometry, &x, &y, &width, &height);
2041    if (flags & WidthValue)
2042      {
2043 	sizehint.width = width;
2044 	sizehint.flags |= USSize;
2045      }
2046    else
2047      {
2048 	width = JX_Screen_Cols;
2049      }
2050    if (flags & HeightValue)
2051      {
2052 	sizehint.height = height;
2053 	sizehint.flags |= USSize;
2054      }
2055    else
2056      {
2057 	height = JX_Screen_Rows;
2058      }
2059 
2060    win->height  	= height * win->font_height + 2 * win->border;
2061    win->width		= width  * win->font_width  + 2 * win->border;
2062 
2063    sizehint.height	= win->height;
2064    sizehint.width	= win->width;
2065    sizehint.width_inc	= win->font_width;
2066    sizehint.height_inc	= win->font_height;
2067    sizehint.min_width	= 5 * win->font_width  + win->border;
2068    sizehint.min_height	= 5 * win->font_height + win->border;
2069    sizehint.base_height	= 0;
2070    sizehint.base_width	= 0;
2071 
2072    if (flags & XValue)
2073      {
2074 	if (flags & XNegative)
2075 	  {
2076 	     x += (DisplayWidth (This_XDisplay, This_XScreen)
2077 		   - sizehint.width - 2 * win->border);
2078 	     sizehint.win_gravity = NorthEastGravity;
2079 	  }
2080 	sizehint.x = x;
2081 	sizehint.flags |= USPosition;
2082      }
2083    else	x = 0;
2084 
2085    if (flags & YValue)
2086      {
2087 	if (flags & YNegative)
2088 	  {
2089 	     y += (DisplayHeight (This_XDisplay, This_XScreen)
2090 		   - sizehint.height - 2 * win->border);
2091 	     if ((flags&XValue) && (flags&XNegative))
2092 	       sizehint.win_gravity = SouthEastGravity;
2093 	     else
2094 	       sizehint.win_gravity = SouthWestGravity;
2095 	  }
2096 	sizehint.y = y;
2097 	sizehint.flags |= USPosition;
2098      }
2099    else	y = 0;
2100 
2101    sizehint.flags |= (PMinSize | PResizeInc | PBaseSize);
2102 
2103    /* create and display window */
2104    win->w = XCreateSimpleWindow(This_XDisplay,
2105 				RootWindow(This_XDisplay, This_XScreen),
2106 				x, y,     /* xpos, ypos */
2107 				win->width,     /* width, height */
2108 				win->height,     /* width, height */
2109 				bdr,	       /* border width */
2110 				win->text_gc[JNORMAL_COLOR].fg,
2111 				win->text_gc[JNORMAL_COLOR].bg
2112 				);
2113 
2114    xcls.res_name = This_App_Name;
2115    xcls.res_class = XJED_CLASS;
2116 
2117    wmhint.input = True;		/* track the focus */
2118    if (Iconic != NULL)
2119      wmhint.initial_state = IconicState;
2120    else
2121      wmhint.initial_state = NormalState;
2122 
2123    wmhint.flags = InputHint | StateHint;
2124 
2125    wmhint.window_group = win->w;
2126    wmhint.flags |= WindowGroupHint;
2127 
2128    XSetWMProperties (This_XDisplay, win->w, NULL, NULL, NULL, 0,
2129                      &sizehint, &wmhint, &xcls);
2130 
2131    /* Enable the delete window protocol */
2132    win->wm_del_win = XInternAtom (This_XDisplay, "WM_DELETE_WINDOW", False);
2133    XSetWMProtocols (This_XDisplay, win->w, &win->wm_del_win, 1);
2134 
2135 #if XJED_SET_WM_COMMAND
2136    XSetCommand(This_XDisplay, win->w, _Jed_Startup_Argv, _Jed_Startup_Argc);
2137 #endif
2138 
2139    if (NULL == (The_Xserver_Vendor = XServerVendor (This_XDisplay)))
2140      The_Xserver_Vendor = "";
2141 
2142    key_event_type = KeyPressMask;
2143 
2144 #if HAS_IBM_NUMLOCK_CODE
2145    if ((0 == strcmp (The_Xserver_Vendor, "International Business Machines"))
2146        || 0 == strcmp (The_Xserver_Vendor, "Hewlett-Packard Company"))
2147      key_event_type |= KeyReleaseMask;
2148 #endif
2149 
2150    /* select event types */
2151    XSelectInput(This_XDisplay, win->w,
2152 		(ExposureMask | key_event_type
2153 		 | ButtonPressMask | ButtonReleaseMask
2154 		 | StructureNotifyMask
2155 		 | PointerMotionHintMask | ButtonMotionMask
2156 		 | EnterWindowMask
2157 		 /* | LeaveWindowMask */
2158 		 | FocusChangeMask
2159 		 | VisibilityChangeMask)
2160 		);
2161 
2162    if (XWin->mouse) XDefineCursor(This_XDisplay, win->w, XWin->mouse);
2163    return win->w;
2164 }
2165 
2166 /*}}}*/
2167 
x_err_handler(Display * d,XErrorEvent * ev)2168 static int x_err_handler (Display *d, XErrorEvent *ev) /*{{{*/
2169 {
2170    char errmsg[256];
2171    No_XEvents = 1;
2172    XGetErrorText (d, ev->error_code, errmsg, 255);
2173    exit_error (errmsg, 0);
2174    return 1;
2175 }
2176 
2177 /*}}}*/
2178 
x_ioerr_handler(Display * d)2179 static int x_ioerr_handler (Display *d) /*{{{*/
2180 {
2181    No_XEvents = 1;
2182    exit_error("XWindows IO error", 0);
2183    return d == NULL;  /* just use d to avoid a warning */
2184 }
2185 
2186 /*}}}*/
2187 
open_Xdisplay(void)2188 static int open_Xdisplay (void) /*{{{*/
2189 {
2190    char dname [256];
2191    char *n;
2192 
2193    n = X_Arg_List[XARG_DISPLAY].value;
2194    if (n != NULL)
2195      {
2196 	strncpy (dname, X_Arg_List[XARG_DISPLAY].value, sizeof (dname)-10);
2197 	dname[sizeof(dname)-10] = 0;
2198 	n = dname;
2199 	while (*n && (*n != ':')) n++;
2200 	if (*n == 0) strcpy(n, ":0.0");
2201 	n = dname;
2202      }
2203 
2204    XSetIOErrorHandler (x_ioerr_handler);
2205 
2206    if ( (This_XDisplay = XOpenDisplay(n)) == NULL )
2207      return 0;
2208 
2209    XSetErrorHandler (x_err_handler);
2210    return 1;
2211 }
2212 
2213 
2214 /* returns socket descriptor */
init_Xdisplay(void)2215 static int init_Xdisplay (void) /*{{{*/
2216 {
2217 #ifdef XJED_USE_R6IM
2218    setlocale(LC_ALL, "");
2219 #endif
2220 
2221    if (X_Arg_List[XARG_NAME].value != NULL)
2222      {
2223 	This_App_Name = X_Arg_List[XARG_NAME].value;
2224      }
2225 
2226    XWin = &XWin_Buf;
2227    memset ((char *)XWin, 0, sizeof (JXWindow_Type));
2228 
2229    get_xdefaults ();
2230    XWin->border = atoi(This_Internal_Border_Name);
2231    if (XWin->border < 0)
2232      XWin->border = 0;
2233 
2234    XWin->font_name = This_Font_Name;
2235 #if XJED_HAS_XRENDERFONT
2236    /* if a parameter to -fs was supplied, we assume the user wants XFT */
2237    if (strlen(This_Face_Size))
2238      {
2239 	if ((XWin->face_size = atof(This_Face_Size))<=0)
2240 	  /* we couldn't convert the value, or a negative value was specified */
2241 	  XWin->face_size = 0;
2242      }
2243    else
2244      /* there was no -fs, so we don't do anything */
2245      XWin->face_size = 0;
2246 
2247     /* make sure that XWin->xftdraw is null in any case */
2248    XWin->xftdraw = NULL;
2249 #endif
2250 
2251    This_XScreen = DefaultScreen(This_XDisplay);
2252 
2253    if (-1 == load_font(XWin->font_name))
2254      {
2255 	(void) fprintf( stderr, "xjed: cannot load font %s, using fixed.\n", XWin->font_name);
2256 	if (-1 == load_font("fixed"))
2257 	  {
2258 	     (void) fprintf( stderr, "xjed: cannot load fixed font.\n");
2259 	     exit (1);
2260 	  }
2261      }
2262 
2263    XWin->text_gc = Default_GC_Info;
2264    if (-1 == setup_and_parse_colors ())		       /* This allocs and parses colors */
2265      exit (1);
2266 
2267    XWin->mouse = XCreateFontCursor (This_XDisplay, XC_xterm);
2268    set_mouse_color (This_MFG, This_MBG);
2269 
2270    This_XWindow = create_XWindow(XWin);
2271 
2272    set_window_name (This_App_Title);
2273    set_icon_name (This_App_Name);
2274 
2275    /* GCs and their colors */
2276    create_needed_gcs ();		       /* This uses info from previous call */
2277 
2278    XWin->current_gc = XWin->text_gc + JNORMAL_COLOR;
2279 
2280 #if XJED_HAS_XRENDERFONT
2281    /* we only XSetFont() if we're NOT using renderfont */
2282    if (XWin->face_size != 0)
2283      {
2284 	XWin->xftdraw = XftDrawCreate(This_XDisplay, This_XWindow, DefaultVisual(This_XDisplay, This_XScreen), XWin->color_map);
2285 	if (NULL == XWin->xftdraw)
2286 	  {
2287 	     fprintf (stderr, "xjed: XftDrawCreate failed\n");
2288 	     exit (1);
2289 	  }
2290      }
2291    else
2292 #endif
2293      XSetFont (This_XDisplay, XWin->current_gc->gc, XWin->font->fid);
2294 
2295    /* display window */
2296 
2297    XMapWindow(This_XDisplay, This_XWindow);
2298 
2299 #ifdef XJED_USE_R6IM
2300    i18init ();
2301 #endif
2302    Compound_Text_Atom = XInternAtom(This_XDisplay, "COMPOUND_TEXT", False);
2303    Text_Atom = XInternAtom(This_XDisplay, "TEXT", False);
2304    UTF8_String_Atom = XInternAtom (This_XDisplay, "UTF8_STRING", False);
2305    Targets_Atom = XInternAtom (This_XDisplay, "TARGETS", False);
2306    Xjed_Prop = XInternAtom(This_XDisplay, "XJED_PROPERTY_TEXT", False);
2307    return ConnectionNumber (This_XDisplay);
2308 }
2309 
2310 /*}}}*/
2311 
reset_Xdisplay(void)2312 static void reset_Xdisplay (void) /*{{{*/
2313 {
2314    if (This_XDisplay != NULL) XCloseDisplay(This_XDisplay);
2315 }
2316 
2317 /*}}}*/
2318 
2319 #define UPCSE(x)  (((x) <= 'z') && ((x) >= 'a') ? (x) - 32 : (x))
myXstrcmp(char * a,char * b)2320 static int myXstrcmp(char *a, char *b) /*{{{*/
2321 {
2322    register char cha, chb;
2323    /* do simple comparison */
2324 
2325    cha = *a++;  chb = *b++;
2326    if ((cha != chb) && (UPCSE(cha) != UPCSE(chb))) return 0;
2327    while ((cha = *a++), (chb = *b++), (cha && chb) != 0)
2328      {
2329 	if (cha != chb) return 0;
2330      }
2331 
2332    return (cha == chb);
2333 }
2334 
2335 /*}}}*/
2336 
2337 #define STREQS(a, b) myXstrcmp(a, b)
X_eval_command_line(int argc,char ** argv)2338 static int X_eval_command_line (int argc, char **argv) /*{{{*/
2339 {
2340    char *arg;
2341    int i;
2342    XWindow_Arg_Type *opt;
2343 
2344    for (i = 1; i < argc; i++)
2345      {
2346 	arg = argv[i];
2347 	if (*arg != '-') break;
2348 	if (0 == strcmp ("--debug-xjed", arg))
2349 	  {
2350 	     Debug_Xjed = 1;
2351 	     continue;
2352 	  }
2353 
2354 	arg++;
2355 	opt = X_Arg_List;
2356 	while (opt->name != NULL)
2357 	  {
2358 	     if (STREQS(opt->name, arg)
2359 		 || ((opt->name1 != NULL) && STREQS(opt->name1, arg))) break;
2360 	     opt++;
2361 	  }
2362 
2363 	if (opt->name == NULL) break;
2364 
2365 	if (opt->type == VOID_TYPE) opt->value = "on";
2366 	else if (i + 1 < argc)
2367 	  {
2368 	     i++;
2369 	     opt->value = argv[i];
2370 	  }
2371 	else break;
2372      }
2373 
2374    /* Out of this loop, argv[i] is the last unprocessed argument */
2375    return i;
2376 }
2377 
2378 /*}}}*/
2379 
2380 #ifdef XJED_USE_R6IM
move_input_position(void)2381 static void move_input_position (void)
2382 {
2383    XPoint spot;
2384    /* XVaNestedList list; */
2385 
2386    spot.x = XWin->border + XWin->cursor_col * XWin->font_width;
2387    spot.y = XWin->cursor_row * XWin->font_height + XWin->border + XWin->font_base;
2388 
2389    if (R6IM_Preedit_Attr != NULL)
2390      XFree (R6IM_Preedit_Attr);
2391    if (NULL != (R6IM_Preedit_Attr = XVaCreateNestedList (0, XNSpotLocation, &spot, NULL)))
2392      {
2393 	if (R6IM_Xic != NULL)
2394 	  XSetICValues (R6IM_Xic, XNPreeditAttributes, R6IM_Preedit_Attr, NULL);
2395      }
2396 }
2397 
set_geometry(XEvent * report,XIMStyle style,char * attr)2398 static void set_geometry (XEvent *report, XIMStyle style, char *attr)
2399 {
2400    XVaNestedList list;
2401    static XRectangle ra, *rb;
2402 
2403    if (style == XIMPreeditArea)
2404      ra.width = report->xconfigure.width - (XWin->font_width * 8);
2405    else if (style == XIMStatusArea)
2406      ra.width = XWin->font_width * 8;
2407    /*   ra.width = report->xconfigure.width; */
2408    ra.height = XWin->font_height;
2409    list = XVaCreateNestedList (0, XNAreaNeeded, &ra, NULL);
2410    XSetICValues (R6IM_Xic, attr, list, NULL);
2411    XFree (list);
2412 
2413    rb = &ra;
2414    list = XVaCreateNestedList (0, XNAreaNeeded, rb, NULL);
2415    XGetICValues (R6IM_Xic, attr, list, NULL);
2416    XFree (list);
2417 
2418    rb->x = 0;
2419    if (style == XIMPreeditArea)
2420      {
2421 	rb->x = XWin->font_width * 8;
2422 	rb->y = report->xconfigure.height - rb->height;
2423      }
2424    else if (style == XIMStatusArea)
2425      {
2426 	rb->x = 0;
2427 	rb->y = report->xconfigure.height - rb->height;
2428 
2429      }
2430 
2431    list = XVaCreateNestedList (0, XNArea, rb, NULL);
2432    XSetICValues (R6IM_Xic, attr, list, NULL);
2433    XFree (list);
2434    /*   XFree (rb); */
2435 }
2436 
2437 /*
2438  * This is more or less stolen startight from XFree86 xterm. This should
2439  * support all European type languages.
2440  */
i18init(void)2441 static void i18init (void) /*{{{*/
2442 {
2443    int i;
2444    char *p, *s, *ns, *end, tmp[1024], buf[32];
2445    XIM xim = NULL;
2446    XIMStyles *xim_styles = NULL;
2447    int found;
2448 
2449    setlocale(LC_ALL, "");
2450 
2451    if (R6IM_Input_Method != NULL)
2452      {
2453 	strcpy(tmp, R6IM_Input_Method);
2454 	s=tmp;
2455 	while (*s)
2456 	  {
2457 	     while (*s && (isspace(*s) || (*s == ','))) s++;
2458 	     if (*s == 0) break;
2459 	     end = s;
2460 	     while (*end && (*end != ',')) end++;
2461 	     ns = end;
2462 	     if (*end) ns++;
2463 	     *end-- = 0;
2464 	     while ((end >= s) && isspace(*end)) *end-- = 0;
2465 
2466 	     if (*s)
2467 	       {
2468 		  strcpy(buf, "@im=");
2469 		  strcat(buf, s);
2470 		  if (((p = XSetLocaleModifiers(buf)) != NULL)
2471 		      && *p
2472 		      && (NULL != (xim = XOpenIM(This_XDisplay, NULL, NULL, NULL))))
2473 		    break;
2474 	       }
2475 	     s = ns;
2476 	  }
2477      }
2478 
2479    if ((xim == NULL) && ((p = XSetLocaleModifiers("")) != NULL) && *p)
2480      xim = XOpenIM(This_XDisplay, NULL, NULL, NULL);
2481 
2482    if ((xim == NULL) && ((p = XSetLocaleModifiers("@im=none")) != NULL) && *p)
2483      xim = XOpenIM(This_XDisplay, NULL, NULL, NULL);
2484 
2485    if (xim == NULL)
2486      {
2487 	fprintf(stderr, "Failed to open input method");
2488 	return;
2489      }
2490 
2491    /* Believe it or not, XGetIMValues return NULL upon success */
2492    if ((NULL != XGetIMValues(xim, XNQueryInputStyle, &xim_styles, NULL))
2493        || (xim_styles == NULL))
2494      {
2495         fprintf(stderr, "Input method doesn't support any style\n");
2496         XCloseIM(xim);
2497         return;
2498      }
2499 
2500    found = 0;
2501    strcpy(tmp, R6IM_Preedit_Type);
2502 
2503    s = tmp;
2504    while (*s && !found)
2505      {
2506 	while (*s && (isspace(*s) || (*s == ','))) s++;
2507 	if (*s == 0) break;
2508 	end = s;
2509 	while (*end && (*end != ',')) end++;
2510 	ns = end;
2511 	if (*ns) ns++;
2512 	*end-- = 0;
2513 	while ((end >= s) && isspace(*end)) *end-- = 0;
2514 
2515         if (!strcmp(s, "OverTheSpot"))
2516 	  R6IM_Input_Style = (XIMPreeditPosition | XIMStatusArea);
2517 	else if (!strcmp(s, "OffTheSpot"))
2518 	  R6IM_Input_Style = (XIMPreeditArea | XIMStatusArea);
2519 	else if (!strcmp(s, "Root"))
2520 	  R6IM_Input_Style = (XIMPreeditNothing | XIMStatusNothing);
2521 
2522 	/* FIXME!!!  (I think)
2523 	 * Examples on the web show testing of bits via & instead of
2524 	 * the == operator.
2525 	 */
2526         for (i = 0; (unsigned short)i < xim_styles->count_styles; i++)
2527 	  {
2528 	     if (R6IM_Input_Style == xim_styles->supported_styles[i])
2529 	       {
2530 		  found = 1;
2531 		  break;
2532 	       }
2533 	  }
2534         s = ns;
2535      }
2536    XFree(xim_styles);
2537 
2538    if (found == 0)
2539      {
2540         /* fprintf(stderr, "input method doesn't support my preedit type\n"); */
2541         XCloseIM(xim);
2542         return;
2543      }
2544 
2545     /*
2546      * This program only understands the Root preedit_style yet
2547      * Then misc.preedit_type should default to:
2548      *          "OverTheSpot,OffTheSpot,Root"
2549      *  /MaF
2550      */
2551 #if 0
2552    if (R6IM_Input_Style != (XIMPreeditNothing | XIMStatusNothing))
2553      {
2554         fprintf(stderr,"This program only supports the 'Root' preedit type\n");
2555         XCloseIM(xim);
2556         return;
2557      }
2558 #else
2559    if (R6IM_Input_Style == (XIMPreeditNothing | XIMStatusNothing))/* "Root" */
2560      R6IM_Xic = XCreateIC(xim, XNInputStyle, R6IM_Input_Style,
2561 			  XNClientWindow, This_XWindow,
2562 			  XNFocusWindow, This_XWindow,
2563 			  NULL);
2564    else if (R6IM_Input_Style == (XIMPreeditPosition | XIMStatusArea))/* "OverTheSpot" */
2565      {
2566 	XFontSet fs;
2567 	char **miss, *def;
2568 	int n_miss;
2569 	char *fontlist;
2570 
2571 	R6IM_Spot.x = 0;
2572 	R6IM_Spot.y = 0;
2573 	/*	R6IM_Spot.x = XWin->border + XWin->cursor_col * XWin->font_width;
2574 	 R6IM_Spot.y = XWin->cursor_row * XWin->font_height + XWin->border + XWin->font_base; */
2575 
2576 	if (NULL != (fontlist = SLmake_string (This_Font_Name)))
2577 	  {
2578 	     fs = XCreateFontSet (This_XDisplay, fontlist, &miss, &n_miss, &def);
2579 	     SLfree(fontlist);
2580 
2581 	     R6IM_Preedit_Attr = XVaCreateNestedList (0, XNFontSet, fs,
2582 						      XNSpotLocation, &R6IM_Spot,
2583 						      NULL);
2584 	     R6IM_Xic = XCreateIC(xim, XNInputStyle, R6IM_Input_Style,
2585 				  XNClientWindow, This_XWindow,
2586 				  XNPreeditAttributes, R6IM_Preedit_Attr,
2587 				  XNStatusAttributes, R6IM_Preedit_Attr,
2588 				  NULL);
2589 	  }
2590      }
2591    else if (R6IM_Input_Style == (XIMPreeditArea | XIMStatusArea))/* "OffTheSpot" */
2592      {
2593 	XFontSet fs;
2594 	char **miss, *def;
2595 	int n_miss;
2596 	char *fontlist;
2597 
2598 	if (NULL != (fontlist = SLmake_string (This_Font_Name)))
2599 	  {
2600 	     fs = XCreateFontSet (This_XDisplay, fontlist, &miss, &n_miss, &def);
2601 	     SLfree(fontlist);
2602 	     R6IM_Preedit_Attr = XVaCreateNestedList (0, XNFontSet, fs,
2603 						      XNSpotLocation, &R6IM_Spot,
2604 						      NULL);
2605 	     R6IM_Xic = XCreateIC(xim, XNInputStyle, R6IM_Input_Style,
2606 				  XNClientWindow, This_XWindow,
2607 				  XNPreeditAttributes, R6IM_Preedit_Attr,
2608 				  XNStatusAttributes, R6IM_Preedit_Attr,
2609 				  NULL);
2610 	  }
2611      }
2612 #endif
2613 
2614    if (NULL == R6IM_Xic)
2615      {
2616 	fprintf(stderr,"Failed to create input context\n");
2617 	XCloseIM(xim);
2618      }
2619 }
2620 
2621 /*}}}*/
2622 #endif
2623 
set_border_color(char * fgc,char * bgc)2624 static void set_border_color (char *fgc, char *bgc) /*{{{*/
2625 {
2626    XColor xfg;
2627    unsigned int bdr = atoi(bgc);
2628 
2629    if (!Term_Supports_Color)
2630      return;
2631 
2632    if (alloc_color(fgc, &xfg) < 0)
2633      return;
2634 
2635    XSetWindowBorder (This_XDisplay, XWin->w, xfg.pixel);
2636    if (bdr < 1000)
2637      XSetWindowBorderWidth (This_XDisplay, XWin->w, bdr);
2638 }
2639 
2640 /*}}}*/
JX_set_mono(int obj_unused,char * unused,SLtt_Char_Type c_unused)2641 static JX_SETXXX_RETURN_TYPE JX_set_mono (int obj_unused, char *unused, SLtt_Char_Type c_unused)
2642 {
2643    (void) obj_unused;
2644    (void) unused;
2645    (void) c_unused;
2646    return JX_SETXXX_RETURN_VAL;
2647 }
2648 
JX_set_color(int i,char * what,char * fg,char * bg)2649 static JX_SETXXX_RETURN_TYPE JX_set_color (int i, char *what, char *fg, char *bg)
2650 {
2651    if (XWin == NULL)
2652      return JX_SETXXX_RETURN_VAL;
2653 
2654    if (!Term_Supports_Color)
2655      return JX_SETXXX_RETURN_VAL;
2656 
2657 #if SLANG_VERSION >= 10306
2658    SLsmg_touch_screen ();
2659 #endif
2660 
2661    if (i == -1)
2662      {
2663 	if (!strcmp("mouse", what))
2664 	  {
2665 	     set_mouse_color (fg, bg);
2666 	  }
2667 	else if (!strcmp("border", what))
2668 	  {
2669 	     set_border_color (fg, bg);
2670 	  }
2671 
2672 	return JX_SETXXX_RETURN_VAL;
2673      }
2674 
2675    x_set_color_free (i, fg, bg, 1);
2676    XSetForeground(This_XDisplay, XWin->text_gc[i].gc, XWin->text_gc[i].fg);
2677    XSetBackground(This_XDisplay, XWin->text_gc[i].gc, XWin->text_gc[i].bg);
2678    if (i == JNORMAL_COLOR)
2679      XSetWindowBackground (This_XDisplay, This_XWindow, XWin->text_gc[i].bg);
2680    return JX_SETXXX_RETURN_VAL;
2681 }
2682 
2683 /*}}}*/
2684 
x_warp_pointer(void)2685 static void x_warp_pointer (void) /*{{{*/
2686 {
2687    X_Warp_Pending = 1;
2688 }
2689 
2690 /*}}}*/
2691 
x_region_2_cutbuffer(void)2692 static void x_region_2_cutbuffer (void) /*{{{*/
2693 {
2694    int nbytes;
2695    char *dat;
2696 
2697    dat = make_buffer_substring(&nbytes);
2698    if (dat == NULL) return;
2699 
2700    XStoreBytes (This_XDisplay, dat, nbytes);
2701 
2702 #if 0
2703    XChangeProperty (This_XDisplay, DefaultRootWindow (This_XDisplay),
2704 		    XA_CUT_BUFFER0, XA_STRING, 8, PropModeReplace,
2705 		    dat, nbytes);
2706 #endif
2707 
2708    SLfree (dat);
2709 }
2710 
2711 /*}}}*/
2712 
x_insert_cutbuffer(void)2713 static int x_insert_cutbuffer (void) /*{{{*/
2714 {
2715    int nbytes;
2716    char *dat;
2717 
2718    CHECK_READ_ONLY
2719      dat = XFetchBytes (This_XDisplay, &nbytes);
2720    if (nbytes && (dat != NULL)) jed_insert_nbytes ((unsigned char *) dat, nbytes);
2721    if (dat != NULL) XFree (dat);
2722    return nbytes;
2723 }
2724 
2725 /*}}}*/
2726 
x_insert_selection(void)2727 static int x_insert_selection (void)
2728 {
2729 #if XJED_USE_COMPOUND_TEXT
2730    XConvertSelection (This_XDisplay, XA_PRIMARY, Compound_Text_Atom, Xjed_Prop, This_XWindow,
2731 		      Current_Event.xbutton.time);
2732 #else
2733 # if SLANG_VERSION >= 20000
2734    if (Jed_UTF8_Mode)
2735      XConvertSelection (This_XDisplay, XA_PRIMARY, UTF8_String_Atom, Xjed_Prop, This_XWindow,
2736 			Current_Event.xbutton.time);
2737    else
2738 # endif
2739      XConvertSelection (This_XDisplay, XA_PRIMARY, XA_STRING, Xjed_Prop, This_XWindow,
2740 			Current_Event.xbutton.time);
2741 #endif
2742    return 0;
2743 }
2744 
2745 typedef struct Selection_Data_Type
2746 {
2747    unsigned int len;
2748    struct Selection_Data_Type *next;
2749    unsigned char bytes[1];
2750 }
2751 Selection_Data_Type;
2752 
free_selection_list(Selection_Data_Type * list)2753 static void free_selection_list (Selection_Data_Type *list)
2754 {
2755    while (list != NULL)
2756      {
2757 	Selection_Data_Type *next = list->next;
2758 	SLfree ((char *) list);
2759 	list = next;
2760      }
2761 }
2762 
append_to_selection_list(unsigned char * buf,unsigned int len,Selection_Data_Type ** rootp,Selection_Data_Type ** tailp)2763 static int append_to_selection_list (unsigned char *buf, unsigned int len,
2764 				 Selection_Data_Type **rootp, Selection_Data_Type **tailp)
2765 {
2766    Selection_Data_Type *next;
2767 
2768    if (NULL == (next = (Selection_Data_Type *)SLmalloc (sizeof(Selection_Data_Type)+len)))
2769      return -1;
2770    memcpy ((char *)next->bytes, buf, len);
2771    next->len = len;
2772    next->next = NULL;
2773    if (*rootp == NULL)
2774      *rootp = next;
2775    else
2776      *tailp = next;
2777    return 0;
2778 }
2779 
read_selection(Display * d,Window w,Atom property)2780 static Selection_Data_Type *read_selection (Display *d, Window w, Atom property)
2781 {
2782    Atom actual_type;
2783    int actual_format;
2784    unsigned long nitem, bytes_after;
2785    unsigned char *data;
2786    unsigned long total_bytes;
2787    Selection_Data_Type *list = NULL, *tail = NULL;
2788 
2789    data = NULL;
2790    /* XGetWindowProperty is a very messed up function.  I do not
2791     * recall one so poorly designed, including the win32 functions that
2792     * I have seen.
2793     */
2794    if (Success != XGetWindowProperty (d, w, property,
2795 				      0, 0, False, AnyPropertyType,
2796 				      &actual_type, &actual_format,
2797 				      &nitem, &bytes_after, &data))
2798      return NULL;
2799 
2800    if (data != NULL)
2801      XFree (data);
2802 
2803    if ((actual_type == None) || (actual_format != 8))
2804      return NULL;
2805 
2806    total_bytes = 0;
2807    while (bytes_after != 0)
2808      {
2809 	unsigned long bytes_read;
2810 	XTextProperty tp;
2811 	char **mb_data;
2812 	int mb_n;
2813 	int status;
2814 
2815 	if (Success != XGetWindowProperty (d, w, property,
2816 					   total_bytes/4, 1 + bytes_after/4,
2817 					   False, AnyPropertyType,
2818 					   &actual_type, &actual_format,
2819 					   &nitem, &bytes_after, &data))
2820 	  break;		       /* What the ?? */
2821 
2822 	bytes_read = nitem * (actual_format/8);
2823 
2824         tp.value = data;
2825 	tp.encoding = actual_type;
2826 	tp.format = actual_format;
2827 	tp.nitems = nitem;
2828 
2829 #if USE_XUTF8_CODE
2830 	if (Jed_UTF8_Mode)
2831 	  status = Xutf8TextPropertyToTextList (This_XDisplay, &tp, &mb_data, &mb_n);
2832 	else
2833 #endif
2834 	status = XmbTextPropertyToTextList(This_XDisplay, &tp, &mb_data, &mb_n);
2835 
2836 	if (status == Success)
2837 	  {
2838 	     int i;
2839 
2840 	     for (i=0; i < mb_n; i++)
2841 	       {
2842 		  if (-1 == append_to_selection_list ((unsigned char *)mb_data[i], strlen(mb_data[i]), &list, &tail))
2843 		    {
2844 		       free_selection_list (list);
2845 		       XFreeStringList (mb_data);
2846 		       XFree (data);
2847 		       return NULL;
2848 		    }
2849 	       }
2850 	     XFreeStringList (mb_data);
2851 	  }
2852 	else if (-1 == append_to_selection_list (data, bytes_read, &list, &tail))
2853 	  {
2854 	     free_selection_list (list);
2855 	     XFree (data);
2856 	     return NULL;
2857 	  }
2858 	total_bytes += bytes_read;
2859 	XFree (data);
2860      }
2861 
2862    return list;
2863 }
2864 
receive_selection(XEvent * ev)2865 static int receive_selection (XEvent *ev)
2866 {
2867    Atom property;
2868    Selection_Data_Type *list;
2869 
2870    if (None == (property = ev->xselection.property))
2871      {
2872 	/* Try this */
2873 	(void) x_insert_cutbuffer ();
2874 	return -1;
2875      }
2876 
2877    list = read_selection (This_XDisplay, This_XWindow, property);
2878    XDeleteProperty (This_XDisplay, This_XWindow, property);
2879    if (list == NULL)
2880      return -1;
2881    while (list != NULL)
2882      {
2883 	Selection_Data_Type *next = list->next;
2884 	if (-1 == jed_insert_nbytes (list->bytes, list->len))
2885 	  {
2886 	     free_selection_list (list);
2887 	     return -1;
2888 	  }
2889 	SLfree ((char *) list);
2890 	list = next;
2891      }
2892    return 0;
2893 }
2894 
2895 
x_region_2_selection(void)2896 static void x_region_2_selection (void)
2897 {
2898    int nbytes;
2899 
2900    if (Selection_Send_Data != NULL)
2901      SLfree (Selection_Send_Data);
2902    Selection_Send_Data = make_buffer_substring (&nbytes);
2903    if (Selection_Send_Data == NULL) return;
2904 
2905    XSetSelectionOwner (This_XDisplay, XA_PRIMARY, This_XWindow, Current_Event.xbutton.time);
2906    if (This_XWindow != XGetSelectionOwner (This_XDisplay, XA_PRIMARY)) return;
2907 }
2908 
send_selection(XEvent * ev)2909 static int send_selection (XEvent *ev)
2910 {
2911    int len;
2912    XTextProperty tp;
2913    XSelectionEvent sev;
2914    XSelectionRequestEvent *xsr;
2915    int status;
2916    Atom target;
2917    int free_tp_value;
2918 
2919    if (NULL == Selection_Send_Data)
2920      return 0;
2921 
2922    memset ((char *)&tp, 0, sizeof (tp));
2923 
2924    xsr = &ev->xselectionrequest;
2925    target = xsr->target;
2926 
2927    if (target == Targets_Atom)
2928      {
2929 	/* The requester wants to know what targets we support.  How polite. */
2930 #define MAX_SELECTION_TARGETS 5
2931 	Atom target_atoms[MAX_SELECTION_TARGETS];
2932 	unsigned int ntargets = 0;
2933 
2934 	target_atoms[ntargets++] = XA_STRING;
2935 	target_atoms[ntargets++] = Text_Atom;
2936 	target_atoms[ntargets++] = Compound_Text_Atom;
2937 #if USE_XUTF8_CODE
2938 	target_atoms[ntargets++] = UTF8_String_Atom;
2939 #endif
2940 	tp.value = (unsigned char *)target_atoms;
2941 	tp.format = 8;
2942 	tp.nitems = sizeof(Atom)*ntargets;
2943 	free_tp_value = 0;
2944 	len = 0;
2945      }
2946    else
2947      {
2948 	int (*text_to_property)(Display *, char **, int, XICCEncodingStyle, XTextProperty *);
2949 	XICCEncodingStyle style;
2950 
2951 #if USE_XUTF8_CODE
2952 	if (Jed_UTF8_Mode)
2953 	  text_to_property = Xutf8TextListToTextProperty;
2954 	else
2955 #endif
2956 	  text_to_property = XmbTextListToTextProperty;
2957 
2958 	if (target == Compound_Text_Atom)
2959 	  style = XCompoundTextStyle;
2960 	else if (target == UTF8_String_Atom)
2961 	  {
2962 #if USE_XUTF8_CODE
2963 	     style = XUTF8StringStyle;
2964 #else
2965 	     style = XTextStyle;
2966 #endif
2967 	  }
2968 	else if ((target == Text_Atom) || (target == XA_STRING))
2969 	  style = XTextStyle;
2970 	else
2971 	  {
2972 	     char *name = XGetAtomName(This_XDisplay, target);
2973 	     if (name != NULL)
2974 	       {
2975 		  (void) fprintf (stderr, "Unsupported selection target: %s\n", name);
2976 		  XFree (name);
2977 	       }
2978 	     return -1;
2979 	  }
2980 	status = (*text_to_property) (This_XDisplay, &Selection_Send_Data, 1, style, &tp);
2981 
2982 	if ((status != Success) || (tp.value == NULL))
2983 	  return -1;
2984 
2985 	free_tp_value = 1;
2986 	len = strlen (Selection_Send_Data);
2987      }
2988 
2989    status = XChangeProperty (This_XDisplay, xsr->requestor,
2990 			     xsr->property, xsr->target, tp.format,
2991 			     PropModeReplace, tp.value, tp.nitems);
2992 
2993    sev.type = SelectionNotify;
2994    sev.requestor = xsr->requestor;
2995    sev.selection = xsr->selection;
2996    sev.target = target;
2997    sev.time = xsr->time;
2998    sev.property = xsr->property;
2999    /* Apparantly XChangeProperty can return BadRequest, even if it succeeds.
3000     * So ignore its return value except for BadAlloc
3001     */
3002    if (status != BadAlloc)
3003      (void) XSendEvent (This_XDisplay, xsr->requestor, False, (long)NULL, (XEvent*)&sev);
3004 
3005    if (free_tp_value)
3006      XFree (tp.value);
3007 
3008    return len;
3009 }
3010 
x_server_vendor(void)3011 static char *x_server_vendor (void)
3012 {
3013    return The_Xserver_Vendor;
3014 }
3015 
3016 #if SLANG_VERSION < 10404
get_termcap_string(char * cap)3017 static char *get_termcap_string (char *cap)
3018 {
3019    return "";
3020 }
3021 #endif
3022 
3023 
x_set_meta_keys(int * maskp)3024 static void x_set_meta_keys (int *maskp)
3025 {
3026    int mask = *maskp;
3027 
3028    JX_MetaMask = 0;
3029    if (mask & (1<<0)) JX_MetaMask |= Mod1Mask;
3030    if (mask & (1<<1)) JX_MetaMask |= Mod2Mask;
3031    if (mask & (1<<2)) JX_MetaMask |= Mod3Mask;
3032    if (mask & (1<<3)) JX_MetaMask |= Mod4Mask;
3033    if (mask & (1<<4)) JX_MetaMask |= Mod5Mask;
3034 }
3035 
3036 static SLang_Intrin_Fun_Type sl_x_table[] = /*{{{*/
3037 {
3038    MAKE_INTRINSIC_S("x_set_window_name", set_window_name, VOID_TYPE),
3039    MAKE_INTRINSIC_S("x_set_icon_name", set_icon_name, VOID_TYPE),
3040    MAKE_INTRINSIC("x_warp_pointer", x_warp_pointer, VOID_TYPE, 0),
3041    MAKE_INTRINSIC("x_insert_cutbuffer", x_insert_cutbuffer, INT_TYPE, 0),
3042    /* Prototype: Integer x_insert_cutbuffer ();
3043     * Inserts cutbuffer into the current buffer and returns the number
3044     * of characters inserted.
3045     */
3046    MAKE_INTRINSIC("x_copy_region_to_cutbuffer", x_region_2_cutbuffer, VOID_TYPE, 0),
3047    /*Prototype: Void x_copy_region_to_cutbuffer();
3048     */
3049    MAKE_INTRINSIC("x_insert_selection", x_insert_selection, SLANG_INT_TYPE, 0),
3050    /* Prototype: Integer x_insert_selection ();
3051     * This function only requests selection data from the selection owner.
3052     * If Xjed received EVENT, Xjed inserts selection data into the current buffer.
3053     * And returns the number of characters inserted.
3054     */
3055    MAKE_INTRINSIC("x_copy_region_to_selection", x_region_2_selection, VOID_TYPE, 0),
3056    /*Prototype: Void x_copy_region_to_selection();
3057     */
3058    MAKE_INTRINSIC_IIS("x_set_keysym", x_set_keysym, VOID_TYPE),
3059   /*Prototype: Void x_set_keysym (Integer keysym, Integer shift, String str);
3060    *
3061    * This function may be used to assocate a string 'str' with a key
3062    * 'keysym' modified by mask @shift@. Pressing the key associated with
3063    * @keysym@ will then generate the keysequence given by @str@. The
3064    * function keys are mapped to integers in the range @0xFF00@ to @0xFFFF@.
3065    * On most systems, the keys that these mappings refer to are located in
3066    * the file @/usr/include/X11/keysymdef.h@. For example, on my system, the
3067    * keysyms for the function keys @XK_F1@ to @XK_F35@ fall in the range
3068    * @0xFFBE@ to @0xFFE0@. So to make the @F1@ key correspond to the string
3069    * given by the two characters @Ctrl-X@ @Ctrl-C@, simply use:
3070    * @ x_set_keysym (0xFFBE, 0, "^X^C");
3071    * The @shift@ argument is an integer with the following meanings:
3072    * @ 0   : unmodified key
3073    * @ '$'  : shifted
3074    * @ '^'  : control
3075    * Any other value for shift will default to 0 (unshifted).
3076    */
3077    MAKE_INTRINSIC("x_server_vendor", x_server_vendor, STRING_TYPE, 0),
3078    /* Prototype: String x_server_vendor ();
3079     * This function returns the vendor name of the X server.
3080     */
3081    MAKE_INTRINSIC_I("x_set_meta_keys", x_set_meta_keys, SLANG_VOID_TYPE),
3082 #if SLANG_VERSION < 10404
3083    MAKE_INTRINSIC_S("get_termcap_string", get_termcap_string, STRING_TYPE),
3084 #endif
3085    MAKE_INTRINSIC_0("x_toggle_visibility", x_toggle_visibility, SLANG_VOID_TYPE),
3086    MAKE_INTRINSIC(NULL,NULL,0,0)
3087 };
3088 
3089 /*}}}*/
3090 
3091 static SLang_Intrin_Var_Type X_Variable_Table [] =
3092 {
3093    MAKE_VARIABLE("ALT_CHAR", &X_Alt_Char, INT_TYPE, 0),
3094    MAKE_VARIABLE("X_LAST_KEYSYM", &X_Last_Keysym, INT_TYPE, 0),
3095    MAKE_VARIABLE(NULL,NULL,0,0)
3096 };
3097 
X_init_slang(void)3098 static int X_init_slang (void) /*{{{*/
3099 {
3100    if ((-1 == SLadd_intrin_fun_table (sl_x_table, "XWINDOWS"))
3101        || (-1 == SLadd_intrin_var_table (X_Variable_Table, NULL)))
3102      return -1;
3103    return 0;
3104 }
3105 
3106 /*}}}*/
3107 
X_update_open(void)3108 static void X_update_open (void) /*{{{*/
3109 {
3110    hide_cursor ();
3111    if (Check_Buffers_Pending)
3112      {
3113 	check_buffers();
3114 	Check_Buffers_Pending = 0;
3115      }
3116    Performing_Update = 1;
3117 }
3118 
3119 /*}}}*/
3120 
X_update_close(void)3121 static void X_update_close (void) /*{{{*/
3122 {
3123    Performing_Update = 0;
3124    if (XWin->window_mapped == 0) JWindow->trashed = 1;
3125    if (JWindow->trashed) return;
3126    show_cursor ();
3127    if (X_Warp_Pending)
3128      {
3129 	XWarpPointer (This_XDisplay, None, XWin->w, 0, 0, 0, 0,
3130 		      (XWin->vis_curs_col * XWin->font_width
3131 		       + XWin->border + XWin->font_width / 2),
3132 		      (XWin->vis_curs_row * XWin->font_height
3133 		       + XWin->border + XWin->font_height / 2));
3134 	X_Warp_Pending = 0;
3135      }
3136 
3137 }
3138 
3139 /*}}}*/
3140 
x_define_xkeys(SLKeyMap_List_Type * map)3141 static void x_define_xkeys (SLKeyMap_List_Type *map) /*{{{*/
3142 {
3143    SLkm_define_key ("\033[^D", (FVOID_STAR) jed_scroll_right_cmd, map);
3144    SLkm_define_key ("\033[d", (FVOID_STAR) jed_scroll_right_cmd, map);
3145    SLkm_define_key ("\033[^C", (FVOID_STAR) jed_scroll_left_cmd, map);
3146    SLkm_define_key ("\033[c", (FVOID_STAR) jed_scroll_left_cmd, map);
3147    SLkm_define_key ("\033[a", (FVOID_STAR) bob, map);
3148    SLkm_define_key ("\033[^A", (FVOID_STAR) bob, map);
3149    SLkm_define_key ("\033[b", (FVOID_STAR) eob, map);
3150    SLkm_define_key ("\033[^B", (FVOID_STAR) eob, map);
3151    SLkm_define_key ("\033[1~", (FVOID_STAR) bol, map);   /* home */
3152    SLkm_define_key ("\033[4~", (FVOID_STAR) eol, map);   /* end */
3153 }
3154 
3155 /*}}}*/
3156 
JX_reset_video(void)3157 static int JX_reset_video (void) /*{{{*/
3158 {
3159    JX_reset_scroll_region ();
3160    JX_goto_rc (0, 0);
3161    JX_normal_video ();
3162    /* return vterm_reset_display (); */
3163    return 0;
3164 }
3165 
3166 /*}}}*/
3167 
JX_init_video(void)3168 static int JX_init_video (void) /*{{{*/
3169 {
3170    JX_reset_video ();
3171    if ((JX_Screen_Rows == 0) || (JX_Screen_Cols == 0))
3172      {
3173 	JX_Screen_Cols = 80;
3174 	JX_Screen_Rows = 24;
3175      }
3176 
3177    /* return vterm_init_display (JX_Screen_Rows, JX_Screen_Cols); */
3178    return 0;
3179 }
3180 
3181 /*}}}*/
3182 
flush_output(void)3183 void flush_output (void) /*{{{*/
3184 {
3185    if (This_XDisplay == NULL)
3186      fflush (stdout);
3187    else
3188      SLtt_flush_output ();
3189 }
3190 
3191 /*}}}*/
3192 
3193 /* a hook to parse some command line args. */
3194 int (*X_Argc_Argv_Hook)(int, char **) = X_eval_command_line;
3195 
JX_flush_output(void)3196 static int JX_flush_output (void)
3197 {
3198    return 0;
3199 }
3200 
3201 static int JX_Zero = 0;
3202 
get_screen_size(int * r,int * c)3203 static void get_screen_size (int *r, int *c)
3204 {
3205    SLtt_get_screen_size ();
3206    *r = SLtt_Screen_Rows;
3207    *c = SLtt_Screen_Cols;
3208 }
3209 
3210 
3211 /* the links to functions and variables here */
3212 void (*tt_beep)(void);
3213 void (*tt_write_string)(char *);
3214 
3215 JX_SETXXX_RETURN_TYPE (*tt_set_color)(int, char *, char *, char *);
3216 JX_SETXXX_RETURN_TYPE (*tt_set_color_esc)(int, char *);
3217 JX_SETXXX_RETURN_TYPE (*tt_set_mono) (int, char *, SLtt_Char_Type);
3218 
3219 void (*tt_wide_width)(void);
3220 void (*tt_narrow_width)(void);
3221 void (*tt_enable_cursor_keys)(void);
3222 void (*tt_set_term_vtxxx)(int *);
3223 void (*tt_get_screen_size)(int *, int *);
3224 
3225 int *tt_Ignore_Beep;
3226 int *tt_Use_Ansi_Colors;
3227 int *tt_Term_Cannot_Scroll;
3228 int *tt_Term_Cannot_Insert;
3229 int *tt_Blink_Mode;
3230 
3231 /* int *tt_Baud_Rate; */
3232 
set_xtt_hooks(void)3233 static void set_xtt_hooks (void)
3234 {
3235    tt_beep = JX_beep;
3236    tt_write_string = JX_write_string;
3237    tt_get_screen_size = JX_get_display_size;
3238    tt_set_color = JX_set_color;
3239    tt_set_mono = JX_set_mono;
3240 
3241    tt_wide_width = JX_wide_width;
3242    tt_narrow_width = JX_narrow_width;
3243    tt_enable_cursor_keys = JX_enable_cursor_keys;
3244    tt_set_term_vtxxx = JX_set_term_vtxxx;
3245 
3246    tt_Ignore_Beep  		= &JX_Ignore_Beep;
3247    tt_Use_Ansi_Colors  	= &JX_Use_Ansi_Colors;
3248    tt_Term_Cannot_Scroll  	= &JX_Term_Cannot_Scroll;
3249    tt_Term_Cannot_Insert  	= &JX_Term_Cannot_Insert;
3250    tt_Blink_Mode		= &JX_Blink_Mode;
3251 }
3252 
JX_get_terminfo(void)3253 static void JX_get_terminfo (void) /*{{{*/
3254 {
3255    SLsmg_Term_Type tt;
3256 
3257 #ifdef REAL_UNIX_SYSTEM
3258    SLtt_Force_Keypad_Init = 1;
3259 #endif
3260    if ((Batch) || !open_Xdisplay())
3261     {
3262        /* This function should match the corresponding function in display.c.
3263 	* I should "include" it to guarantee the correspondence.
3264 	*/
3265        tt_beep                 = SLtt_beep;
3266        tt_write_string         = SLtt_write_string;
3267        tt_get_screen_size      = get_screen_size;
3268        tt_set_color            = SLtt_set_color;
3269        tt_set_mono             = SLtt_set_mono;
3270 #if SLANG_VERSION < 20000
3271        tt_set_color_esc        = SLtt_set_color_esc;
3272 #endif
3273        tt_wide_width           = SLtt_wide_width;
3274        tt_narrow_width         = SLtt_narrow_width;
3275        tt_enable_cursor_keys   = SLtt_enable_cursor_keys;
3276        tt_set_term_vtxxx       = SLtt_set_term_vtxxx;
3277        tt_Ignore_Beep          = &SLtt_Ignore_Beep;
3278        tt_Use_Ansi_Colors      = &SLtt_Use_Ansi_Colors;
3279        tt_Term_Cannot_Scroll   = &SLtt_Term_Cannot_Scroll;
3280        tt_Term_Cannot_Insert   = &SLtt_Term_Cannot_Insert;
3281        tt_Blink_Mode           = &SLtt_Blink_Mode;
3282        /*     tt_Baud_Rate            = &SLtt_Baud_Rate; */
3283 
3284        if (Batch == 0) SLtt_get_terminfo ();
3285        return;
3286     }
3287 
3288    set_xtt_hooks ();
3289 
3290    if (-1 == init_xkeys ())
3291      {
3292      }
3293 
3294    JX_Screen_Cols = 80;
3295    JX_Screen_Rows = 24;
3296 
3297    (void) jed_add_init_slang_hook (X_init_slang);
3298 
3299    /* init hooks */
3300    X_Read_Hook = X_read_key;
3301    X_Input_Pending_Hook = X_input_pending;
3302    X_Update_Open_Hook = X_update_open;
3303    X_Update_Close_Hook = X_update_close;
3304    X_Suspend_Hook = xjed_suspend;
3305    X_Init_Term_Hook = init_Xdisplay;
3306    X_Reset_Term_Hook = reset_Xdisplay;
3307    X_Define_Keys_Hook = x_define_xkeys;
3308    SLang_Interrupt = xjed_check_kbd;
3309 
3310    /* Set this so that main will not try to read from stdin.  It is quite
3311     * likely that this is started from a menu or something.
3312     */
3313    Stdin_Is_TTY = -1;
3314    /* We do not need this since we do not have to worry about incoming
3315     * eight bit escape sequences.
3316     */
3317    DEC_8Bit_Hack = 0;
3318 
3319    memset ((char *) &tt, 0, sizeof (SLsmg_Term_Type));
3320 
3321    tt.tt_normal_video = JX_normal_video;
3322    tt.tt_set_scroll_region = JX_set_scroll_region;
3323    tt.tt_goto_rc = JX_goto_rc;
3324    tt.tt_reverse_index = JX_reverse_index;
3325    tt.tt_reset_scroll_region = JX_reset_scroll_region;
3326    tt.tt_delete_nlines = JX_delete_nlines;
3327    tt.tt_cls = JX_cls;
3328    tt.tt_del_eol = JX_del_eol;
3329    tt.tt_smart_puts = JX_smart_puts;
3330    tt.tt_flush_output = JX_flush_output;
3331    tt.tt_reset_video = JX_reset_video;
3332    tt.tt_init_video = JX_init_video;
3333 
3334    tt.tt_screen_rows = &JX_Screen_Rows;
3335    tt.tt_screen_cols = &JX_Screen_Cols;
3336    tt.tt_term_cannot_scroll = &JX_Term_Cannot_Scroll;
3337    tt.tt_has_alt_charset = &JX_Zero;
3338 
3339 #if SLANG_VERSION >= 20000
3340    tt.unicode_ok = &Jed_UTF8_Mode;
3341 #endif
3342 
3343    SLsmg_set_terminal_info (&tt);
3344    Jed_Handle_SIGTSTP = 0;
3345 }
3346 
3347 /*}}}*/
3348 
3349 void (*tt_get_terminfo)(void) = JX_get_terminfo;
3350 
3351 /* Unused but required. */
3352 #ifdef USE_GPM_MOUSE
3353 int (*X_Open_Mouse_Hook)(void);
3354 void (*X_Close_Mouse_Hook)(void);
3355 #endif
3356