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