1 
2 /*
3  initialize_screen()
4  reset_screen()
5  restart_screen()
6  set_attribute(int attr)
7  input_character(int timeout)
8  input_line(int buflen, char *buffer, int timeout, int *read_size)
9  display_char(int ch)
10  clear_line()
11  clear_screen()
12  clear_status_window()
13  clear_text_window()
14  create_status_window(int lines)
15  delete_status_window()
16  get_cursor_position(int *row, int *col)
17  move_cursor(int row, int col)
18  scroll_line()
19  select_status_window()
20  select_text_window()
21  */
22 
23 #include <stdio.h>
24 #ifdef NEEDS_SELECT_H
25 #include <sys/select.h>
26 #endif
27 #include <ctype.h>
28 #include <sys/time.h>
29 #include <X11/Xlib.h>
30 #include <X11/Xutil.h>
31 #include <X11/keysym.h>
32 
33 #include "ztypes.h"
34 #include "xio.h"
35 #include "greypm.bm"
36 
37 #define EVENTMASK (ButtonPressMask | ButtonReleaseMask | ButtonMotionMask | KeyPressMask | StructureNotifyMask | ExposureMask)
38 #define STATEVENTMASK (ButtonPressMask | KeyPressMask | StructureNotifyMask | ExposureMask)
39 #define TICKLENGTH (100000)
40 
41 Display *xiodpy;
42 int xioscn;
43 Window xiowin, xioswin;
44 int xiodepth;
45 int xiobackstore;
46 GC gcblack, gcwhite, gcflip, gcgrey;
47 GC gcfont[NUMFONTS];
48 GC gcsblack, gcsflip;
49 GC gcsfont[NUMFONTS], gcsnegfont[NUMFONTS];
50 XFontStruct *fontstr[NUMFONTS];
51 int spacewidth[NUMFONTS];
52 int lineheight, lineheightoff;
53 preferences prefs;
54 
55 static int screen_inited = FALSE;
56 
57 static int xiowinwid, xiowinhgt;
58 static int statusmode;
59 static int machineattr;
60 
61 static int escapemode = FALSE;
62 static int modifymode = op_Cancel;
63 
64 #ifdef __STDC__
65 static char *ansicheck = "\nThis binary was compiled with ANSI C.\n";
66 #else
67 static char *ansicheck = "\nThis binary was compiled with non-ANSI C.\n";
68 #endif
69 
70 #ifdef __STDC__
71 static void loop(int stringmode, int *killflag, int timeout);
72 static void eventloop(int stringmode, int *killflag, int timeout);
73 static void redraw(int xpos, int ypos, int wid, int hgt);
74 static void rearrange_window();
75 #else
76 static void loop();
77 static void eventloop();
78 static void redraw();
79 static void rearrange_window();
80 #endif
81 
82 #ifdef TESTING
83 static char *wordlist[10] = { "One ", "two ", "three ", "seventeen ", "a ", "veryvery ", "short ", "maybenot ", "I ", "stop. "};
84 #ifdef __STDC__
main()85 main()
86 #else
87 main()
88 #endif
89 {
90     int numl;
91     initialize_screen();
92     SRANDOM_FUNC(getpid() + time(NULL));
93     for (numl=0; numl>=0; numl++) {
94 	int numwords = RANDOM_FUNC() % 20 + 10;
95 	int ix, jx;
96 	char *cx;
97 	char buf[256];
98 	int pos;
99 	pos = 0;
100 	input_line(256, buf, 0, &pos);
101 	if (pos >= 4 && !strncmp(buf, "quit", 4))
102 	    break;
103 	for (ix=0; ix<numwords; ix++) {
104 	    jx = RANDOM_FUNC() % 10;
105 	    for (cx=wordlist[jx]; *cx; cx++) {
106 		display_char(*cx);
107 	    }
108 	}
109 	display_char('\n');
110 	/*ix = input_character(0);
111 	if (ix=='q')
112 	    break;*/
113     }
114     /*while (1) {
115 	char buf[256];
116 	int pos;
117 	input_line(256, buf, 0, &pos);
118     }*/
119     reset_screen();
120     return 0;
121 }
122 #endif
123 
124 #ifdef __STDC__
display_char(int ch)125 void display_char(int ch)
126 #else
127 void display_char(ch)
128 int ch;
129 #endif
130 {
131     if (!statusmode) {
132 	xtext_add(ch, -1);
133     }
134     else {
135 	if (ch=='\n' || ch=='\r')
136 	    xstat_newline();
137 	else
138 	    xstat_insert(ch);
139     }
140 }
141 
142 /* timeout is in tenth-seconds; 0 means never timeout. returns char gotten, or -1 for timed-out. */
143 #ifdef __STDC__
input_character(int timeout)144 int input_character(int timeout)
145 #else
146 int input_character(timeout)
147 int timeout;
148 #endif
149 {
150     int killflag;
151 
152     if (statusmode) {
153 	xstat_set_dot_active(TRUE);
154     }
155 
156     killflag = (-1);
157     loop(FALSE, &killflag, timeout);
158 
159     if (statusmode) {
160 	xstat_set_dot_active(FALSE);
161     }
162 
163     return killflag;
164 }
165 
166 #ifdef __STDC__
xio_pause()167 void xio_pause()
168 #else
169 void xio_pause()
170 #endif
171 {
172     int killflag;
173 
174     killflag = (-1);
175     eventloop(FALSE, &killflag, 0);
176 }
177 
178 /* timeout is in tenth-seconds; 0 means never timeout. returns -1 for timed-out (and don't affect other vars). returns '\n' if enter is hit.
179  buffer and readpos are set on entry and should be set on exit.
180  cannot be called reentrantly. */
181 #ifdef __STDC__
input_line(int buflen,char * buffer,int timeout,int * readpos,int firsttime)182 int input_line(int buflen, char *buffer, int timeout, int *readpos,
183   int firsttime)
184 #else
185 int input_line(buflen, buffer, timeout, readpos, firsttime)
186 int buflen;
187 char *buffer;
188 int timeout;
189 int *readpos;
190 int firsttime;
191 #endif
192 {
193     int killflag;
194     int ix;
195 
196     xted_init(buflen, buffer, readpos, &killflag, firsttime);
197 
198     loop(TRUE, &killflag, timeout);
199 
200     if (killflag == (-1)) {
201 	xtext_line_timeout();
202     }
203 
204     return killflag;
205 }
206 
207 #ifdef __STDC__
initialize_screen()208 void initialize_screen()
209 #else
210 void initialize_screen()
211 #endif
212 {
213     int ix;
214     Pixmap greypm;
215 
216     XSetWindowAttributes attr;
217     XGCValues gcvalues;
218 
219     xinit_openconnection();
220 
221     /* --- status window --- */
222 
223     xioswin = XCreateSimpleWindow(xiodpy, DefaultRootWindow(xiodpy), prefs.statwinx, prefs.statwiny, prefs.statwid*spacewidth[FIXED_FONT], prefs.stathgt*lineheight, 1, prefs.forecolor, prefs.backcolor);
224 
225     {
226 	XSizeHints szhints;
227 	szhints.flags = PMinSize|PResizeInc|USPosition|USSize;
228 	szhints.x = prefs.statwinx;
229 	szhints.y = prefs.statwiny;
230 	szhints.width_inc = spacewidth[FIXED_FONT];
231 	szhints.height_inc = lineheight;
232 	szhints.width = prefs.statwid * szhints.width_inc;
233 	szhints.height = prefs.stathgt * szhints.height_inc;
234 	szhints.min_width = 1 * szhints.width_inc;
235 	szhints.min_height = 1 * szhints.height_inc;
236 	XSetNormalHints(xiodpy, xioswin, &szhints);
237     }
238     { /* make some window managers happy */
239 	XWMHints wmhints;
240 	wmhints.flags = InputHint;
241 	wmhints.input = True;
242 	XSetWMHints(xiodpy, xioswin, &wmhints);
243     }
244 
245     attr.event_mask = STATEVENTMASK;
246     /*attr.backing_store = WhenMapped;*/
247     XChangeWindowAttributes(xiodpy, xioswin, CWEventMask /*|CWBackingStore*/, &attr);
248 
249     XStoreName(xiodpy, xioswin, "XZip Status");
250     XMapWindow(xiodpy, xioswin);
251 
252     gcvalues.function = GXcopy;
253     gcvalues.foreground = prefs.forecolor;
254     gcvalues.background = prefs.backcolor;
255     gcsblack = XCreateGC(xiodpy, xioswin, GCForeground|GCBackground, &gcvalues);
256     XSetGraphicsExposures(xiodpy, gcsblack, FALSE);
257 
258     gcvalues.function = GXxor;
259     gcvalues.foreground = (prefs.textcolor[FIXED_FONT])^(prefs.backcolor);
260     gcvalues.background = (prefs.textcolor[FIXED_FONT])^(prefs.backcolor);
261     gcsflip = XCreateGC(xiodpy, xioswin, GCFunction|GCForeground|GCBackground, &gcvalues);
262 
263     gcvalues.function = GXcopy;
264     for (ix=0; ix<NUMFONTS; ix++) {
265 	gcvalues.font = fontstr[ix]->fid;
266 	gcvalues.foreground = prefs.backcolor;
267 	gcvalues.background = prefs.textcolor[ix];
268 	gcsnegfont[ix] = XCreateGC(xiodpy, xioswin, GCForeground|GCBackground|GCFont, &gcvalues);
269 	gcvalues.foreground = prefs.textcolor[ix];
270 	gcvalues.background = prefs.backcolor;
271 	gcsfont[ix] = XCreateGC(xiodpy, xioswin, GCForeground|GCBackground|GCFont, &gcvalues);
272     }
273 
274     /* --- text window --- */
275 
276     xiowinwid = prefs.winw;
277     xiowinhgt = prefs.winh;
278     xiowin = XCreateSimpleWindow(xiodpy, DefaultRootWindow(xiodpy), prefs.winx, prefs.winy, xiowinwid, xiowinhgt, 1, prefs.forecolor, prefs.backcolor);
279 
280     {
281 	XSizeHints szhints;
282 	szhints.flags = PMinSize|USPosition|USSize;
283 	szhints.min_width = 250;
284 	szhints.min_height = 200;
285 	szhints.x = prefs.winx;
286 	szhints.y = prefs.winy;
287 	szhints.width = xiowinwid;
288 	szhints.height = xiowinhgt;
289 	XSetNormalHints(xiodpy, xiowin, &szhints);
290     }
291     { /* make some window managers happy */
292 	XWMHints wmhints;
293 	wmhints.flags = InputHint;
294 	wmhints.input = True;
295 	XSetWMHints(xiodpy, xiowin, &wmhints);
296     }
297 
298     attr.event_mask = EVENTMASK;
299     attr.backing_store = WhenMapped;
300     XChangeWindowAttributes(xiodpy, xiowin, CWEventMask|CWBackingStore, &attr);
301 
302     XStoreName(xiodpy, xiowin, "XZip");
303     XMapWindow(xiodpy, xiowin);
304 
305     gcvalues.function = GXcopy;
306     gcvalues.foreground = prefs.forecolor;
307     gcvalues.background = prefs.backcolor;
308     gcblack = XCreateGC(xiodpy, xiowin, GCForeground|GCBackground, &gcvalues);
309     XSetGraphicsExposures(xiodpy, gcblack, FALSE);
310 
311     gcvalues.foreground = prefs.backcolor;
312     gcvalues.background = prefs.forecolor;
313     gcwhite = XCreateGC(xiodpy, xiowin, GCForeground|GCBackground, &gcvalues);
314 
315     if (xiodepth==1) {
316 	gcvalues.fill_style = FillOpaqueStippled;
317 	greypm = XCreateBitmapFromData(xiodpy, xiowin, greypm_bits, greypm_width, greypm_height);
318 	gcvalues.foreground = prefs.forecolor;
319 	gcvalues.background = prefs.backcolor;
320 	gcvalues.stipple = greypm;
321 	gcgrey = XCreateGC(xiodpy, xiowin, GCForeground|GCBackground|GCFillStyle|GCStipple, &gcvalues);
322     }
323     else {
324 	gcvalues.foreground = prefs.greycolor;
325 	gcvalues.background = prefs.backcolor;
326 	gcgrey = XCreateGC(xiodpy, xiowin, GCForeground|GCBackground, &gcvalues);
327     }
328 
329     gcvalues.function = GXxor;
330     gcvalues.foreground = (prefs.textcolor[0])^(prefs.backcolor);
331     gcvalues.background = (prefs.textcolor[0])^(prefs.backcolor);
332     gcflip = XCreateGC(xiodpy, xiowin, GCFunction|GCForeground|GCBackground, &gcvalues);
333 
334     gcvalues.function = GXcopy;
335     for (ix=0; ix<NUMFONTS; ix++) {
336 	gcvalues.font = fontstr[ix]->fid;
337 	if (ix & REVERSE) {
338 	    gcvalues.foreground = prefs.backcolor;
339 	    gcvalues.background = prefs.textcolor[ix];
340 	}
341 	else {
342 	    gcvalues.foreground = prefs.textcolor[ix];
343 	    gcvalues.background = prefs.backcolor;
344 	}
345 	gcfont[ix] = XCreateGC(xiodpy, xiowin, GCForeground|GCBackground|GCFont, &gcvalues);
346     }
347 
348     /* --- final initing */
349 
350     screen_inited = TRUE;
351 
352     statusmode = FALSE;
353     xtext_init();
354     xmess_init();
355     rearrange_window();
356     {
357 	char buf[64];
358 	sprintf(buf, "Welcome to XZip version %s.", XZIPVERSION);
359 	xmess_set_message(buf, FALSE);
360     }
361     xstat_init(prefs.statwid, prefs.stathgt, prefs.statwinx, prefs.statwiny);
362 
363     machineattr = NORMAL;
364 }
365 
366 #ifdef __STDC__
restart_screen()367 void restart_screen()
368 #else
369 void restart_screen()
370 #endif
371 {
372   zbyte_t val;
373 
374   /* H_CONFIG is "flags 1"; H_FLAGS[0,1] is "flags 2". */
375 
376   switch (h_type) {
377   case V1:
378   case V2:
379   case V3:
380     val = get_byte (H_CONFIG);
381     val |= (0x20 | 0x40); /* screen-splitting, variable-pitch font */
382     set_byte (H_CONFIG, val);
383     break;
384   case V4:
385     val = get_byte (H_CONFIG);
386     val |= (0x04 | 0x08 | 0x10 | 0x80); /* bold, italic, fixed-width, timed input */
387     set_byte (H_CONFIG, val);
388     break;
389   case V5:
390   case V8:
391     val = get_byte (H_CONFIG);
392     val |= (0x04 | 0x08 | 0x10 | 0x80); /* bold, italic, fixed-width, timed input */
393     set_byte (H_CONFIG, val);
394     val = get_byte (H_FLAGS+1);
395     val &= (~0x08); /* no graphics */
396     val &= (~0x20); /* no mouse */
397     val &= (~0x80); /* no sound */
398     set_byte (H_FLAGS+1, val);
399     break;
400   }
401 }
402 
403 #ifdef __STDC__
reset_screen()404 void reset_screen()
405 #else
406 void reset_screen()
407 #endif
408 {
409     static char *killmessage = "[Hit any key to exit.]";
410 
411     if (!screen_inited)
412 	return;
413 
414     xmess_set_message(killmessage, TRUE);
415     input_character(0);
416     XCloseDisplay(xiodpy);
417 }
418 
419 /* I have extended the definition of this function; a value of -1 does not affect the style, except to re-check the force-fixed bit that the game can set.
420  The original Zip program never called set_attribute with a negative value, so this should be ok. */
421 #ifdef __STDC__
set_attribute(int attr)422 void set_attribute(int attr)
423 #else
424 void set_attribute(attr)
425 int attr;
426 #endif
427 {
428     int finalattr;
429 
430     if (!attr)
431 	machineattr = NORMAL;
432     else if (attr > 0)
433 	machineattr |= attr;
434     else {
435     }
436 
437     if (get_word (H_FLAGS) & FIXED_FONT_FLAG)
438 	finalattr = machineattr | FIXED_FONT;
439     else
440 	finalattr = machineattr;
441 
442     if (!statusmode) {
443 	xtext_setstyle(-1, finalattr);
444     }
445     else {
446 	xstat_setattr(finalattr);
447     }
448 }
449 
450 #ifdef __STDC__
clear_line()451 void clear_line()
452 #else
453 void clear_line()
454 #endif
455 {
456     /* ### do something! */
457 }
458 
459 /* clear both text and status window */
460 #ifdef __STDC__
clear_screen()461 void clear_screen()
462 #else
463 void clear_screen()
464 #endif
465 {
466     xstat_clear_window();
467     xtext_clear_window();
468 }
469 
470 #ifdef __STDC__
clear_status_window()471 void clear_status_window()
472 #else
473 void clear_status_window()
474 #endif
475 {
476     xstat_clear_window();
477 }
478 
479 #ifdef __STDC__
clear_text_window()480 void clear_text_window()
481 #else
482 void clear_text_window()
483 #endif
484 {
485     xtext_clear_window();
486 }
487 
488 #ifdef __STDC__
create_status_window(int lines)489 void create_status_window(int lines)
490 #else
491 void create_status_window(lines)
492 int lines;
493 #endif
494 {
495     xstat_set_window_size(lines);
496 }
497 
498 #ifdef __STDC__
delete_status_window()499 void delete_status_window()
500 #else
501 void delete_status_window()
502 #endif
503 {
504     xstat_set_window_size(0);
505 }
506 
507 #ifdef __STDC__
get_cursor_position(int * row,int * col)508 void get_cursor_position(int *row, int *col)
509 #else
510 void get_cursor_position(row, col)
511 int *row;
512 int *col;
513 #endif
514 {
515     if (statusmode) {
516 	xstat_getpos(row, col);
517     }
518     else {
519 	*row = 1;
520 	*col = 1;
521     }
522 }
523 
524 #ifdef __STDC__
move_cursor(int row,int col)525 void move_cursor(int row, int col)
526 #else
527 void move_cursor(row, col)
528 int row;
529 int col;
530 #endif
531 {
532     if (statusmode) {
533 	xstat_setpos(row, col);
534     }
535 }
536 
537 #ifdef __STDC__
scroll_line()538 void scroll_line()
539 #else
540 void scroll_line()
541 #endif
542 {
543     if (statusmode) {
544 	/* ### do something? */
545     }
546     else
547 	display_char ('\n');
548 }
549 
550 #ifdef __STDC__
select_status_window()551 void select_status_window()
552 #else
553 void select_status_window()
554 #endif
555 {
556     statusmode = TRUE;
557 }
558 
559 #ifdef __STDC__
select_text_window()560 void select_text_window()
561 #else
562 void select_text_window()
563 #endif
564 {
565     statusmode = FALSE;
566 }
567 
568 
569 #ifdef __STDC__
xio_bell()570 void xio_bell()
571 #else
572 void xio_bell()
573 #endif
574 {
575     XBell(xiodpy, 0);
576 }
577 
578 
579 #ifdef __STDC__
redraw(int xpos,int ypos,int wid,int hgt)580 static void redraw(int xpos, int ypos, int wid, int hgt)
581 #else
582 static void redraw(xpos, ypos, wid, hgt)
583 int xpos;
584 int ypos;
585 int wid;
586 int hgt;
587 #endif
588 {
589     /* yes, we ignore the exposure region. */
590     XClearWindow(xiodpy, xiowin);
591     xtext_redraw();
592     xmess_redraw();
593 }
594 
595 #ifdef __STDC__
handlekey(XKeyEvent * event,int stringmode,int * killflag)596 static void handlekey(XKeyEvent *event, int stringmode, int *killflag)
597 #else
598 static void handlekey(event, stringmode, killflag)
599 XKeyEvent *event;
600 int stringmode;
601 int *killflag;
602 #endif
603 {
604     int ix;
605     char ch;
606     KeySym ksym;
607 
608     ix = XLookupString(event, &ch, 1, &ksym, NULL);
609     if (IsModifierKey(ksym) || ksym==XK_Multi_key) {
610 	return;
611     }
612     /* not yet set up to do keybindings */
613     if (!stringmode) {
614         if (!ix) {
615 	    /* ignore non-ascii characters, except arrow keys */
616 	    switch (ksym) {
617     	        case XK_Up:
618 	            *killflag = 129;
619 		    break;
620     	        case XK_Down:
621 	            *killflag = 130;
622 		    break;
623     	        case XK_Left:
624 	            *killflag = 131;
625 		    break;
626     	        case XK_Right:
627 	            *killflag = 132;
628 		    break;
629 	    }
630 	    return;
631 	}
632 	switch (ch) {
633 	    case '\014': /* ctrl-L */
634 		xtexted_redraw(op_AllWindows);
635 		break;
636 	    default:
637 		*killflag = (unsigned char)ch;
638 		break;
639 	}
640     }
641     else {
642 	cmdentry *command;
643 	int val, which, keynum, op;
644 	if (!ix) {
645 	    val = (ksym & 255);
646 	    which = keytype_sym;
647 	}
648 	else {
649 	    if (escapemode || (event->state & Mod1Mask)) {
650 		escapemode = FALSE;
651 		val = (ch & 255);
652 		which = keytype_meta;
653 	    }
654 	    else {
655 		val = (ch & 255);
656 		which = keytype_main;
657 	    }
658 	}
659 	keynum = (val | which);
660 	command = keycmds[keynum];
661 	if (modifymode != op_Cancel && !(command && command->ignoremods)) {
662 	    op = modifymode;
663 	    modifymode = op_Cancel;
664 	    xtexted_modify(keynum, op);
665 	}
666 	else if (!command) {
667 	    char buf[128];
668 	    char *cx;
669 	    cx = xkey_get_key_name(keynum);
670 	    sprintf(buf, "Key <%s> not bound", cx);
671 	    xmess_set_message(buf, FALSE);
672 	}
673 	else {
674 	    if (command->operand == (-1))
675 		op = keynum;
676 	    else
677 		op = command->operand;
678 	    (*(command->func))(op);
679 	}
680     }
681 }
682 
683 /* based on new xiowinwid, xiowinhgt */
684 #ifdef __STDC__
rearrange_window()685 static void rearrange_window()
686 #else
687 static void rearrange_window()
688 #endif
689 {
690     int botwidth = lineheight+3;
691     xtext_resize(0, 0, xiowinwid, xiowinhgt-botwidth);
692     xmess_resize(0, xiowinhgt-botwidth, xiowinwid, botwidth);
693 }
694 
695 /* do one round of iteration -- getchar, getline, whatever is relevant. return -1 after timeout tenth-seconds (if timeout > 0).
696  If stringmode==FALSE, return the first keystroke (immediately).
697  Otherwise, do a line of input using loop_*, returning \n. */
698 #ifdef __STDC__
loop(int stringmode,int * killflag,int timeout)699 static void loop(int stringmode, int *killflag, int timeout)
700 #else
701 static void loop(stringmode, killflag, timeout)
702 int stringmode;
703 int *killflag;
704 int timeout;
705 #endif
706 {
707     xstat_layout();
708     xtext_layout(); /* the biggie; everything has to be right after this */
709     xtext_end_visible();
710 
711     eventloop(stringmode, killflag, timeout);
712     xtext_set_lastseen();
713 }
714 
715 /* guts of the event loop */
716 #ifdef __STDC__
eventloop(int stringmode,int * killflag,int timeout)717 static void eventloop(int stringmode, int *killflag, int timeout)
718 #else
719 static void eventloop(stringmode, killflag, timeout)
720 int stringmode;
721 int *killflag;
722 int timeout;
723 #endif
724 {
725     int ix, jx;
726     int eventp;
727     XEvent event;
728     long evmasks;
729     struct timeval tv, curtime, outtime;
730     struct timezone tz;
731     fd_set readbits;
732     static unsigned int buttonhit;
733     static unsigned int buttonmods;
734     static int clicknum;
735     static int lastclickx=(-999), lastclicky=(-999);
736 
737     if (timeout) {
738 	gettimeofday (&outtime, &tz);
739 	outtime.tv_sec += (timeout/10);
740 	outtime.tv_usec += ((timeout%10)*100000);
741 	if (outtime.tv_usec >= 1000000) {
742 	  outtime.tv_sec++;
743 	  outtime.tv_usec -= 1000000;
744 	}
745     }
746 
747     while (1) {
748 	evmasks = ~(NoEventMask);
749 	eventp = XCheckMaskEvent(xiodpy, evmasks, &event);
750 	if (!eventp) {
751 	    tv.tv_sec = 0;
752 	    tv.tv_usec = TICKLENGTH;
753 	    FD_ZERO(&readbits);
754 	    FD_SET(ConnectionNumber(xiodpy), &readbits);
755 	    XFlush(xiodpy);
756 	    select(1+ConnectionNumber(xiodpy), &readbits, 0, 0, &tv);
757 	}
758 	else if (event.xany.window==xioswin) {
759 	    switch (event.type) {
760 		case ButtonPress:
761 		    break;
762 		case KeyPress:
763 		    xmess_check_timeout();
764 		    handlekey(&event.xkey, stringmode, killflag);
765 		    break;
766 		case ConfigureNotify:
767 		    xstat_newgeometry(event.xconfigure.x, event.xconfigure.y, event.xconfigure.width, event.xconfigure.height);
768 		    break;
769 		case Expose:
770 		    do {
771 			ix = XCheckWindowEvent(xiodpy, xioswin, ExposureMask, &event);
772 		    } while (ix);
773 		    xstat_redraw();
774 		    break;
775 	    }
776 	}
777 	else {
778 	    switch (event.type) {
779 		case ButtonPress:
780 		    xmess_check_timeout();
781 		    buttonhit = event.xbutton.button;
782 		    buttonmods = event.xbutton.state;
783 		    ix = lastclickx-event.xbutton.x;
784 		    jx = lastclicky-event.xbutton.y;
785 		    if (ix<=1 && ix>=(-1) && jx<=1 && jx>=(-1)) {
786 			clicknum++;
787 		    }
788 		    else {
789 			clicknum = 1;
790 			lastclickx = event.xbutton.x;
791 			lastclicky = event.xbutton.y;
792 		    }
793 		    xtext_hitdown(event.xbutton.x, event.xbutton.y, buttonhit, buttonmods, clicknum);
794 		    break;
795 		case MotionNotify:
796 		    xtext_hitmove(event.xbutton.x, event.xbutton.y, buttonhit, buttonmods, clicknum);
797 		    break;
798 		case ButtonRelease:
799 		    xtext_hitup(event.xbutton.x, event.xbutton.y, buttonhit, buttonmods, clicknum);
800 		    break;
801 		case KeyPress:
802 		    xmess_check_timeout();
803 		    handlekey(&event.xkey, stringmode, killflag);
804 		    break;
805 		case ConfigureNotify:
806 		    xmess_check_timeout();
807 		    if (event.xconfigure.width != xiowinwid || event.xconfigure.height != xiowinhgt) {
808 			xiowinwid = event.xconfigure.width;
809 			xiowinhgt = event.xconfigure.height;
810 			rearrange_window();
811 		    }
812 		    break;
813 		case Expose:
814 		    do {
815 			ix = XCheckWindowEvent(xiodpy, xiowin, ExposureMask, &event);
816 		    } while (ix);
817 		    redraw(event.xexpose.x, event.xexpose.y, event.xexpose.width, event.xexpose.height);
818 		    break;
819 		default:
820 		    break;
821 	    }
822 	}
823 
824 	if (*killflag != (-1)) {
825 	    return;
826 	}
827 	if (timeout) {
828 	    gettimeofday (&curtime, &tz);
829 	    if (curtime.tv_sec > outtime.tv_sec || (curtime.tv_sec == outtime.tv_sec && curtime.tv_usec > outtime.tv_usec)) {
830 		/* timed out */
831 		*killflag = (-1);
832 		return;
833 	    }
834 	}
835     }
836 }
837 
838 #ifdef __STDC__
xtexted_redraw(int op)839 void xtexted_redraw(int op)
840 #else
841 void xtexted_redraw(op)
842 int op;
843 #endif
844 {
845     switch (op) {
846 	case op_Screen:
847 	    redraw(0, 0, xiowinwid, xiowinhgt);
848 	    break;
849 	case op_Status:
850 	    xstat_redraw();
851 	    break;
852 	case op_AllWindows:
853 	    redraw(0, 0, xiowinwid, xiowinhgt);
854 	    xstat_redraw();
855 	    break;
856     }
857 }
858 
859 #ifdef __STDC__
xtexted_meta(int op)860 void xtexted_meta(int op)
861 #else
862 void xtexted_meta(op)
863 int op;
864 #endif
865 {
866     switch (op) {
867 	case op_Cancel:
868 	    escapemode = FALSE;
869 	    modifymode = op_Cancel;
870 	    xmess_set_message("Cancelled.", FALSE);
871 	    break;
872 	case op_DefineMacro:
873 	    xmess_set_message("Type a macro key to redefine.", FALSE);
874 	    modifymode = op_DefineMacro;
875 	    break;
876 	case op_ExplainKey:
877 	    xmess_set_message("Type a key to explain.", FALSE);
878 	    modifymode = op_ExplainKey;
879 	    break;
880 	case op_Escape:
881 	    escapemode = !escapemode;
882 	    break;
883     }
884 }
885 
886 #ifdef __STDC__
xtexted_modify(int keynum,int op)887 void xtexted_modify(int keynum, int op)
888 #else
889 void xtexted_modify(keynum, op)
890 int keynum;
891 int op;
892 #endif
893 {
894     char buf[128];
895     char *cx;
896     cmdentry *command;
897 
898     switch (op) {
899 	case op_DefineMacro:
900 	    xted_define_macro(keynum);
901 	    break;
902 	case op_ExplainKey:
903 	    cx = xkey_get_key_name(keynum);
904 	    command = keycmds[keynum];
905 	    if (!command)
906 		sprintf(buf, "Key <%s> is not bound", cx);
907 	    else if (!keycmdargs[keynum])
908 		sprintf(buf, "Key <%s>: %s", cx, command->name);
909 	    else {
910 		if (strlen(keycmdargs[keynum]) < sizeof(buf) - 64)
911 		    sprintf(buf, "Key <%s>: %s \"%s\"", cx, command->name, keycmdargs[keynum]);
912 		else {
913 		    sprintf(buf, "Key <%s>: %s \"", cx, command->name);
914 		    strncat(buf, keycmdargs[keynum], sizeof(buf) - 64);
915 		    strcat(buf, "...\"");
916 		}
917 	    }
918 	    xmess_set_message(buf, FALSE);
919 	    break;
920 	default:
921 	    sprintf(buf, "Unknown key modifier (%d).", op);
922 	    xmess_set_message(buf, FALSE);
923 	    break;
924     }
925 }
926 
927