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