|
|
1.1 root 1: /*
2: * $Source: /u1/X/xterm/RCS/button.c,v $
3: * $Header: button.c,v 10.103 86/12/02 09:49:20 swick Exp $
4: */
5:
6: #include <X/mit-copyright.h>
7:
8: /* Copyright Massachusetts Institute of Technology 1984, 1985 */
9: /*
10: button.c Handles button events in the terminal emulator.
11: does cut/paste operations, change modes via menu,
12: passes button events through to some applications.
13: J. Gettys.
14: */
15: #ifndef lint
16: static char csrg_id[] = "@(#)button.c 1.6\t(Berkeley/CSRG)\t9/18/87";
17: static char sccs_id[] = "@(#)button.c\tX10/6.6B\t12/26/86";
18: #endif lint
19: #include <stdio.h>
20: #include <signal.h>
21: #include <setjmp.h>
22: #include <ctype.h>
23: #include <X/Xlib.h>
24: #include "scrollbar.h"
25: #include "ptyx.h"
26: #include "data.h"
27: #include "error.h"
28: #ifdef MODEMENU
29: #include "menu.h"
30: #endif MODEMENU
31:
32: #define NBUTS 3
33: #define DIRS 2
34: #define UP 1
35: #define DOWN 0
36: #define SHIFTS 8 /* three keys, so eight combinations */
37: #define Coordinate(r,c) ((r) * ncols + (c))
38:
39: char *GetRestOfLine();
40: char *SaveText();
41: extern UnSaltText();
42: extern StartCut();
43: extern ReExecute();
44: extern EditorDown();
45:
46: extern ButtonUp();
47: extern DownButtonDown();
48: extern MiddleButtonDown();
49: extern UpButtonDown();
50: extern ModeMenu();
51: extern char *xterm_name;
52: extern Bogus(), Silence();
53: extern GINbutton();
54: /* due to LK201 limitations, not all of the below are actually possible */
55: static int (*bfunc[SHIFTS][DIRS][NBUTS])() = {
56: /* left middle right */
57: EditorDown, EditorDown, EditorDown, /* down | */
58: Silence, Silence, Silence, /* up |no shift */
59:
60: ReExecute, StartCut, Silence, /* down | */
61: Silence, Silence, UnSaltText, /* up |shift */
62:
63: EditorDown, EditorDown, EditorDown, /* down | */
64: Silence, Silence, Silence, /* up |meta */
65:
66: EditorDown, EditorDown, EditorDown, /* down | */
67: Silence, Silence, Silence, /* up |meta shift */
68:
69: ModeMenu, ModeMenu, ModeMenu, /* down | */
70: Silence, Silence, Silence, /* up |control */
71:
72: EditorDown, EditorDown, EditorDown, /* down | */
73: Silence, Silence, Silence, /* up |ctl shift */
74:
75: EditorDown, EditorDown, EditorDown, /* down | */
76: Silence, Silence, Silence, /* up |no shift */
77:
78: EditorDown, EditorDown, EditorDown, /* down | control */
79: Silence, Silence, Silence /* up |meta shift*/
80:
81: }; /* button, shift keys, and direction */
82: static int (*tfunc[SHIFTS][DIRS][NBUTS])() = {
83: /* left middle right */
84: ModeMenu, ModeMenu, ModeMenu, /* down | */
85: Silence, Silence, Silence, /* up |no shift */
86:
87: ModeMenu, ModeMenu, ModeMenu, /* down | */
88: Silence, Silence, Silence, /* up |shift */
89:
90: Bogus, Bogus, Bogus, /* down | */
91: Silence, Silence, Silence, /* up |meta */
92:
93: Bogus, Bogus, Bogus, /* down | */
94: Silence, Silence, Silence, /* up |meta shift */
95:
96: ModeMenu, ModeMenu, ModeMenu, /* down | */
97: Silence, Silence, Silence, /* up |control */
98:
99: ModeMenu, ModeMenu, ModeMenu, /* down | */
100: Silence, Silence, Silence, /* up |ctl shift */
101:
102: Bogus, Bogus, Bogus, /* down | */
103: Silence, Silence, Silence, /* up |no shift */
104:
105: Bogus, Bogus, Bogus, /* down | control */
106: Silence, Silence, Silence /* up |meta shift*/
107:
108: }; /* button, shift keys, and direction */
109: static int (*scrollfunc[SHIFTS][DIRS][NBUTS])() = {
110: /* left middle right */
111: DownButtonDown, ModeMenu, UpButtonDown, /* down | */
112: ButtonUp, Silence, ButtonUp, /* up |no shift */
113:
114: DownButtonDown, ModeMenu, UpButtonDown, /* down | */
115: ButtonUp, Silence, ButtonUp, /* up |shift */
116:
117: Bogus, Bogus, Bogus, /* down | */
118: Silence, Silence, Silence, /* up |meta */
119:
120: Bogus, Bogus, Bogus, /* down | */
121: Silence, Silence, Silence, /* up |meta shift */
122:
123: DownButtonDown, ModeMenu, UpButtonDown, /* down | */
124: ButtonUp, Silence, ButtonUp, /* up |control */
125:
126: Bogus, Bogus, Bogus, /* down | */
127: Silence, Silence, Silence, /* up |ctl shift */
128:
129: Bogus, Bogus, Bogus, /* down | */
130: Silence, Silence, Silence, /* up |no shift */
131:
132: Bogus, Bogus, Bogus, /* down | control */
133: Silence, Silence, Silence /* up |meta shift*/
134:
135: }; /* button, shift keys, and direction */
136: static int (*Tbfunc[SHIFTS][DIRS][NBUTS])() = {
137: /* left middle right */
138: GINbutton, GINbutton, GINbutton, /* down | */
139: Silence, Silence, Silence, /* up |no shift */
140:
141: GINbutton, GINbutton, GINbutton, /* down | */
142: Silence, Silence, Silence, /* up |shift */
143:
144: Bogus, Bogus, Bogus, /* down | */
145: Silence, Silence, Silence, /* up |meta */
146:
147: Bogus, Bogus, Bogus, /* down | */
148: Silence, Silence, Silence, /* up |meta shift */
149:
150: ModeMenu, ModeMenu, ModeMenu, /* down | */
151: Silence, Silence, Silence, /* up |control */
152:
153: Bogus, Bogus, Bogus, /* down | */
154: Silence, Silence, Silence, /* up |ctl shift */
155:
156: Bogus, Bogus, Bogus, /* down | */
157: Silence, Silence, Silence, /* up |no shift */
158:
159: Bogus, Bogus, Bogus, /* down | control */
160: Silence, Silence, Silence /* up |meta shift*/
161:
162: }; /* button, shift keys, and direction */
163:
164: extern Terminal term;
165:
166: static int crow, ccol; /* cut row and column */
167: static int ccoord;
168: static int ncols;
169:
170: HandleButtons(term, reply, pty)
171: register Terminal *term;
172: register XEvent *reply;
173: int pty; /* file descriptor of pty */
174: {
175: register Screen *screen = &term->screen;
176: int (*bp)();
177: int dir = DOWN;
178: /* so table above will be nice, we change left to right */
179: int button = 2 - ((XKeyOrButtonEvent *)reply)->detail & 0177;
180: int shift = KeyState(((XKeyOrButtonEvent *)reply)->detail);
181:
182: switch (reply->type) {
183: case ButtonPressed:
184: dir = DOWN;
185: break;
186: case ButtonReleased:
187: dir = UP;
188: break;
189: default:
190: break;
191: }
192: if(L_flag && !checklogin()) { /* if login window, check for login */
193: if(dir == DOWN)
194: Bell();
195: return;
196: }
197: bp = (screen->sb && (reply->window == screen->sb->bar ||
198: GetButtonState(screen->sb) != BUTTON_NORMAL)) ?
199: scrollfunc[shift][dir][button] :
200: ((Titlebar(screen) && (reply->window == screen->title.tbar ||
201: reply->window == screen->Ttitle.tbar)) ? tfunc[shift][dir][button] :
202: ((reply->window == TWindow(screen)) ? Tbfunc[shift][dir][button] :
203: bfunc[shift][dir][button]));
204: if (bp != NULL)
205: (*bp)(term, reply, pty);
206: else
207: Bell();
208: }
209:
210: UnSaltText(term, reply, pty)
211: register Terminal *term;
212: register XKeyOrButtonEvent *reply;
213: int pty; /* file descriptor of pty */
214: {
215: char *line;
216: int nbytes;
217: register char *lag, *cp, *end;
218:
219: line = XFetchBytes(&nbytes);
220: end = &line[nbytes];
221: lag = line;
222: for (cp = line; cp != end; cp++)
223: {
224: if (*cp != '\n') continue;
225: *cp = '\r';
226: write(pty, lag, cp - lag + 1);
227: lag = cp + 1;
228: }
229: if (lag != end)
230: write(pty, lag, end - lag);
231: free (line); /* free text from fetch */
232: }
233:
234: ReExecute(term, reply, pty)
235: register XKeyOrButtonEvent *reply;
236: Terminal *term;
237: int pty;
238: {
239: XKeyOrButtonEvent xevent;
240: register XKeyOrButtonEvent *ev = &xevent;
241: register Screen *screen = &term->screen;
242: register int xrow, xcol, mask, cursor, ignore;
243: register char *line;
244: int row, col;
245:
246: cursor = screen->curs;
247: if(!XGrabMouse(VWindow(screen), cursor,
248: mask = ButtonReleased | EnterWindow | LeaveWindow | MouseMoved)) {
249: Bell();
250: return;
251: }
252: ncols = screen->max_col + 1; /* needed by Coordinate() define */
253: if(NearestRowCol(reply->y, reply->x, &crow, &ccol) ||
254: crow > screen->max_row) {
255: Bell();
256: XUngrabMouse();
257: return;
258: }
259: xrow = crow;
260: xcol = ccol;
261: crow++;
262: ccol = 0;
263: ccoord = Coordinate(crow, ccol);
264: if (screen->cursor_state)
265: HideCursor ();
266: HiliteText(xrow, xcol, crow, 0, TRUE);
267: ignore = FALSE;
268: for( ; ; ) {
269: XMaskEvent(mask, ev);
270: switch(ev->type) {
271: case ButtonReleased:
272: if(xrow == crow - 1) {
273: line = GetRestOfLine(screen, xrow, xcol);
274: row = strlen(line);
275: write(pty, line, row);
276: line[row] = '\n';
277: XStoreBytes(line, row);
278: free (line); /* free text from fetch */
279: HiliteText(xrow, xcol, crow, 0, FALSE);
280: }
281: XUngrabMouse();
282: if (screen->cursor_set && !screen->cursor_state)
283: ShowCursor ();
284: return;
285: case LeaveWindow:
286: if(ev->window != VWindow(screen))
287: break;
288: if(xrow == crow - 1)
289: HiliteText(xrow, xcol, crow, 0, FALSE);
290: xrow = crow;
291: xcol = 0;
292: XGrabMouse(VWindow(screen), cursor, mask & ~MouseMoved);
293: ignore = TRUE;
294: break;
295: case EnterWindow:
296: if(ev->window != VWindow(screen))
297: break;
298: XGrabMouse(VWindow(screen), cursor, mask);
299: ignore = FALSE;
300: /* drop through */
301: case MouseMoved:
302: if(ignore)
303: break;
304: NearestRowCol(ev->y, ev->x, &row, &col);
305: if(row != crow - 1) {
306: if(xrow == crow - 1)
307: HiliteText(xrow, xcol, crow, 0, FALSE);
308: } else if(xrow == row)
309: TrackText(xrow, xcol, row, col);
310: else
311: HiliteText(row, col, crow, 0, TRUE);
312: xrow = row;
313: xcol = col;
314: break;
315: }
316: }
317: }
318:
319: char *GetRestOfLine(screen, row, col)
320: register Screen *screen;
321: register int row, col;
322: {
323: char *line;
324: int i;
325:
326: i = Length(screen, row, col, screen->max_col);
327: if((line = (char *)malloc(i + 2)) == NULL)
328: SysError(ERROR_BMALLOC);
329: SaveText(screen, row, col, screen->max_col, line);
330: line[i] = '\r';
331: line[i+1] = '\0';
332: return(line);
333: }
334:
335: StartCut(term, reply, pty)
336: register XKeyOrButtonEvent *reply;
337: Terminal *term;
338: int pty;
339: {
340: XKeyOrButtonEvent xevent;
341: register XKeyOrButtonEvent *ev = &xevent;
342: register Screen *screen = &term->screen;
343: register int xrow, xcol, mask, cursor, ignore;
344: int row, col;
345:
346: cursor = screen->curs;
347: if(!XGrabMouse(VWindow(screen), cursor,
348: mask = ButtonReleased | EnterWindow | LeaveWindow | MouseMoved)) {
349: Bell();
350: return;
351: }
352: ncols = screen->max_col + 1; /* needed by Coordinate() define */
353: NearestRowCol(reply->y, reply->x, &crow, &ccol);
354: ccoord = Coordinate(crow, ccol);
355: xrow = crow;
356: xcol = ccol;
357: ignore = FALSE;
358: if (screen->cursor_state)
359: HideCursor ();
360: for( ; ; ) {
361: XMaskEvent(mask, ev);
362: switch(ev->type) {
363: case ButtonReleased:
364: if(!ignore) {
365: row = crow;
366: col = ccol; /* SaltTextAway may alter these */
367: SaltTextAway(term, xrow, xcol, pty);
368: }
369: HiliteText(row, col, xrow, xcol, FALSE);
370: XUngrabMouse();
371: if (screen->cursor_set && !screen->cursor_state)
372: ShowCursor ();
373: return;
374: case LeaveWindow:
375: if(ev->window != VWindow(screen))
376: break;
377: HiliteText(crow, ccol, xrow, xcol, FALSE);
378: xrow = crow;
379: xcol = ccol;
380: XGrabMouse(VWindow(screen), cursor, mask & ~MouseMoved);
381: ignore = TRUE;
382: break;
383: case EnterWindow:
384: if(ev->window != VWindow(screen))
385: break;
386: XGrabMouse(VWindow(screen), cursor, mask);
387: ignore = FALSE;
388: /* drop through */
389: case MouseMoved:
390: if(ignore)
391: break;
392: NearestRowCol(ev->y, ev->x, &row, &col);
393: if(row != xrow || col != xcol) {
394: TrackText(xrow, xcol, row, col);
395: xrow = row;
396: xcol = col;
397: }
398: break;
399: }
400: }
401: }
402:
403: int NearestRowCol(y, x, r, c)
404: register int y, x;
405: int *r, *c;
406: {
407: register Screen *screen = &term.screen;
408: register row, col, i;
409: register char *ch;
410: register int passed_eol = FALSE;
411:
412: if((row = (y - screen->border - Titlebar(screen)) / FontHeight(screen))
413: < 0)
414: row = 0;
415: else if(row > screen->max_row)
416: row = screen->max_row;
417: i = FontWidth(screen);
418: if((col = (x - screen->border + (i / 3)) / i) < 0)
419: col = 0;
420: else if(col > screen->max_col) {
421: col = 0;
422: row++; /* this can be screen->max_row + 1 */
423: passed_eol = TRUE;
424: }
425: if(col > 0) {
426: for(i = screen->max_col,
427: ch = screen->buf[2 * (row + screen->topline)] + i ;
428: i > 0 && *ch == 0 ; ch--, i--);
429: if(col > i + 1) {
430: col = 0;
431: row++;
432: passed_eol = TRUE;
433: }
434: }
435: *r = row;
436: *c = col;
437: return(passed_eol);
438: }
439:
440: TrackText(frow, fcol, trow, tcol)
441: register int frow, fcol, trow, tcol;
442: {
443: register int f, t;
444:
445: f = Coordinate(frow, fcol);
446: t = Coordinate(trow, tcol);
447: if(f == t)
448: return;
449: if(f > ccoord) {
450: if(t < ccoord) {
451: HiliteText(crow, ccol, frow, fcol, FALSE);
452: HiliteText(trow, tcol, crow, ccol, TRUE);
453: } else if(t > f)
454: HiliteText(frow, fcol, trow, tcol, TRUE);
455: else
456: HiliteText(trow, tcol, frow, fcol, FALSE);
457: } else {
458: if(t > ccoord) {
459: HiliteText(frow, fcol, crow, ccol, FALSE);
460: HiliteText(crow, ccol, trow, tcol, TRUE);
461: } else if(t < f)
462: HiliteText(trow, tcol, frow, fcol, TRUE);
463: else
464: HiliteText(frow, fcol, trow, tcol, FALSE);
465: }
466: }
467:
468: HiliteText(frow, fcol, trow, tcol, hilite)
469: register int frow, fcol, trow, tcol;
470: int hilite;
471: {
472: register Screen *screen = &term.screen;
473: register int i, j;
474:
475: if((i = Coordinate(frow, fcol)) == (j = Coordinate(trow, tcol)))
476: return;
477: else if(i > j) {
478: i = frow;
479: j = fcol;
480: frow = trow;
481: fcol = tcol;
482: trow = i;
483: tcol = j;
484: }
485: if(hilite) {
486: i = screen->foreground;
487: screen->foreground = screen->background;
488: screen->background = i;
489: }
490: if(frow != trow) { /* do multiple rows */
491: if((i = screen->max_col - fcol + 1) > 0) { /* first row */
492: XPixSet(VWindow(screen), fcol * FontWidth(screen) +
493: screen->border, frow * FontHeight(screen) +
494: screen->border + Titlebar(screen), i * FontWidth(screen),
495: FontHeight(screen), screen->background);
496: ScrnRefresh(screen, frow, fcol, 1, i);
497: }
498: if((i = trow - frow - 1) > 0) { /* middle rows*/
499: j = screen->max_col + 1;
500: XPixSet(VWindow(screen), screen->border, (frow + 1) *
501: FontHeight(screen) + screen->border + Titlebar(screen),
502: j * FontWidth(screen), i * FontHeight(screen),
503: screen->background);
504: ScrnRefresh(screen, frow + 1, 0, i, j);
505: }
506: if(tcol > 0 && trow <= screen->max_row) { /* last row */
507: XPixSet(VWindow(screen), screen->border, trow *
508: FontHeight(screen) + screen->border + Titlebar(screen),
509: tcol * FontWidth(screen), FontHeight(screen),
510: screen->background);
511: ScrnRefresh(screen, trow, 0, 1, tcol);
512: }
513: } else { /* do single row */
514: i = tcol - fcol;
515: XPixSet(VWindow(screen), fcol* FontWidth(screen) + screen->border,
516: frow * FontHeight(screen) + screen->border + Titlebar(screen),
517: i * FontWidth(screen), FontHeight(screen), screen->background);
518: ScrnRefresh(screen, frow, fcol, 1, tcol - fcol);
519: }
520: if(hilite) {
521: i = screen->foreground;
522: screen->foreground = screen->background;
523: screen->background = i;
524: }
525: }
526:
527: SaltTextAway(term, row, col, pty)
528: Terminal *term;
529: register row, col;
530: int pty;
531: {
532: register Screen *screen = &term->screen;
533: register int i, j = 0;
534: register char *str; /* string to be saved */
535: char *line, *lp;
536:
537: /* first order of business is to guarantee that crow,ccol is before */
538: /* row,col. */
539: if ( row == crow ) { /* must exchange as pairs */
540: if ( ccol > col ) { /* may have to exchange columns */
541: register int tmp;
542: tmp = ccol; ccol = col; col = tmp;
543: }
544: }
545: else {
546: if ( crow > row ) { /* may have to exchange row and col */
547: register int tmp;
548: tmp = ccol; ccol = col; col = tmp;
549: tmp = crow; crow = row; row = tmp;
550: }
551: }
552:
553: if (ccol < 0) ccol = 0;
554: else if (ccol > screen->max_col) { crow++; ccol = 0; }
555: if (crow < 0) crow = ccol = 0;
556: else if (crow > screen->max_row) { crow = screen->max_row; ccol = 0; }
557:
558: if (row > screen->max_row) { row = screen->max_row + 1 ; col = 0; }
559: else if (--col > screen->max_col) col = screen->max_col;
560:
561: /* first we need to know how long the string is before we can save it*/
562:
563: if ( row == crow ) j = Length(screen, crow, ccol, col);
564: else { /* two cases, cut is on same line, cut spans multiple lines */
565: j += Length(screen, crow, ccol, screen->max_col) + 1;
566: for(i = crow + 1; i < row; i++)
567: j += Length(screen, i, 0, screen->max_col) + 1;
568: if (col >= 0)
569: j += Length(screen, row, 0, col);
570: }
571:
572: /* now get some memory to save it in */
573:
574: if((line = (char *)malloc(j + 1)) == NULL)
575: SysError(ERROR_BMALLOC2);
576: line[j] = '\0'; /* make sure it is null terminated */
577: lp = line; /* lp points to where to save the text */
578: if ( row == crow ) lp = SaveText(screen, row, ccol, col, lp);
579: else {
580: lp = SaveText(screen, crow, ccol, screen->max_col, lp);
581: *lp ++ = '\n'; /* put in newline at end of line */
582: for(i = crow +1; i < row; i++) {
583: lp = SaveText(screen, i, 0, screen->max_col, lp);
584: *lp ++ = '\n';
585: }
586: if (col >= 0)
587: lp = SaveText(screen, row, 0, col, lp);
588: }
589: *lp = '\0'; /* make sure we have end marked */
590:
591: XStoreBytes(line, j);
592: free(line);
593: }
594:
595: /* returns number of chars in line from scol to ecol out */
596: int Length(screen, row, scol, ecol)
597: register int row, scol, ecol;
598: register Screen *screen;
599: {
600: register char *ch;
601: int end = 0;
602:
603: ch = screen->buf[2 * (row + screen->topline)];
604: while (ecol >= scol && ch[ecol] == 0)
605: ecol--;
606: return (ecol - scol + 1);
607: }
608:
609: /* copies text into line, preallocated */
610: char *SaveText(screen, row, scol, ecol, lp)
611: int row;
612: int scol, ecol;
613: Screen *screen;
614: register char *lp; /* pointer to where to put the text */
615: {
616: register int i = 0;
617: register char *ch = screen->buf[2 * (row + screen->topline)];
618: register int c;
619:
620: if ((i = Length(screen, row, scol, ecol)) == 0) return(lp);
621: ecol = scol + i;
622: for (i = scol; i < ecol; i++) {
623: if ((c = ch[i]) == 0)
624: c = ' ';
625: else if(c < ' ') {
626: if(c == '\036')
627: c = '#';
628: else
629: c += 0x5f;
630: } else if(c == 0x7f)
631: c = 0x5f;
632: *lp++ = c;
633: }
634: return(lp);
635: }
636:
637: EditorDown (term, reply, pty)
638: Terminal *term;
639: register XKeyOrButtonEvent *reply;
640: int pty; /* file descriptor of pty */
641: {
642: register Screen *screen = &term->screen;
643: char line[6];
644: register unsigned row, col;
645: int button;
646:
647: if (!screen->send_mouse_pos) {
648: Bell();
649: return;
650: }
651: button = 2 - reply->detail & 0177;
652: row = (reply->y - screen->border - Titlebar(screen)) / FontHeight(screen);
653: col = (reply->x - screen->border) / FontWidth(screen);
654: strcpy(line, "\033[M");
655: line[3] = ' ' + button;
656: line[4] = ' ' + col + 1;
657: line[5] = ' ' + row + 1;
658: write(pty, line, 6);
659: }
660:
661: #ifdef ALLOWUNSHIFTEDSELECTION
662: UnshiftedSelectionInit()
663: {
664: register int i, j;
665:
666: /* copy table for shifted actions to table for unshifted
667: * actions. We assume the shifted actions are in bfunc[1]
668: * and the unshifted ones go in bfunc[0].
669: */
670: for (i = 0; i < DIRS; i++)
671: for (j = 0; j < NBUTS; j++)
672: bfunc[0][i][j] = bfunc[1][i][j];
673: }
674: #endif
675:
676: #ifdef MODEMENU
677: #define MAXWINDOWMENU 64
678: #define XTERMMENU 0
679: #define VTMENU 1
680: #define TEKMENU 2
681: #define SCROLLBARMENU 3
682: #ifndef NOWINDOWMENU
683: #define WINDOWMENU 4
684: #define NMENUS 5
685: #else NOWINDOWMENU
686: #define NMENUS 4
687: #endif NOWINDOWMENU
688:
689: static Menu *menus[NMENUS];
690: #ifndef NOWINDOWMENU
691: static char *namebuf[MAXWINDOWMENU + 1];
692: static char *wname;
693: static Window windows[MAXWINDOWMENU];
694: #endif NOWINDOWMENU
695:
696: ModeMenu(term, reply, pty)
697: Terminal *term;
698: register XKeyOrButtonEvent *reply;
699: int pty; /* file descriptor of pty */
700: {
701: register Screen *screen = &term->screen;
702: register Menu *menu;
703: register int type, item;
704: static int inited;
705: extern TekLink *TekRefresh;
706: extern int xeventpass();
707: extern Menu *setupmenu(), *Tsetupmenu(), *xsetupmenu();
708: #ifndef NOWINDOWMENU
709: extern Menu *wsetupmenu();
710: #endif NOWINDOWMENU
711: extern Menu *ssetupmenu();
712:
713: if((reply->window == screen->title.tbar || reply->window ==
714: screen->Ttitle.tbar) && InTitle(screen, reply->window,
715: reply->x))
716: return;
717: if(!inited) {
718: extern Pixmap Gray_Tile;
719: extern Cursor Menu_DefaultCursor;
720: extern char *Menu_DefaultFont;
721: extern FontInfo *Menu_DefaultFontInfo;
722:
723: inited++;
724: Gray_Tile = screen->graybordertile;
725: InitMenu(xterm_name);
726: Menu_DefaultCursor = screen->arrow;
727: if(strcmp(Menu_DefaultFont, f_t) == 0)
728: Menu_DefaultFontInfo = screen->titlefont;
729: }
730: if((reply->detail & 0177) == LeftButton)
731: type = XTERMMENU;
732: else if((reply->detail & 0177) == RightButton)
733: #ifndef NOWINDOWMENU
734: type = WINDOWMENU;
735: #else NOWINDOWMENU
736: {
737: Bell();
738: return;
739: }
740: #endif NOWINDOWMENU
741: else if(reply->window == VWindow(screen) || reply->window ==
742: screen->title.tbar)
743: type = VTMENU;
744: else if(reply->window == TWindow(screen) || reply->window ==
745: screen->Ttitle.tbar)
746: type = TEKMENU;
747: else
748: type = SCROLLBARMENU;
749: switch(type) {
750: case XTERMMENU:
751: if((menu = xsetupmenu(&menus[XTERMMENU])) == NULL)
752: return;
753: break;
754: case VTMENU:
755: if((menu = setupmenu(&menus[VTMENU])) == NULL)
756: return;
757: break;
758: #ifndef NOWINDOWMENU
759: case WINDOWMENU:
760: wname = (reply->window == screen->title.tbar || reply->window
761: == VWindow(screen)) ? screen->winname : screen->Twinname;
762: if((menu = wsetupmenu(&menus[WINDOWMENU])) == NULL)
763: return;
764: break;
765: #endif NOWINDOWMENU
766: case TEKMENU:
767: if((menu = Tsetupmenu(&menus[TEKMENU])) == NULL)
768: return;
769: screen->waitrefresh = TRUE;
770: break;
771: case SCROLLBARMENU:
772: if((menu = ssetupmenu(&menus[SCROLLBARMENU])) == NULL)
773: return;
774: break;
775: }
776: /*
777: * Make the window entry and leaving routines holdoff on setting
778: * the timer and on selecting or unselecting any windows. Then
779: * set the select mode manually.
780: */
781: screen->holdoff = TRUE;
782: SetMenuEventHandler(menu, xeventpass);
783: item = TrackMenu(menu, reply);
784: menusync();
785: screen->waitrefresh = FALSE;
786: screen->timer = 0;
787: screen->holdoff = FALSE;
788: reselectwindow(screen);
789:
790: if (item < 0) {
791: if(type == TEKMENU && TekRefresh)
792: dorefresh();
793: #ifndef NOWINDOWMENU
794: else if(type == WINDOWMENU)
795: wfree(menu);
796: #endif NOWINDOWMENU
797: return;
798: }
799: switch(type) {
800: case XTERMMENU:
801: xdomenufunc(item);
802: break;
803: case VTMENU:
804: domenufunc(item);
805: break;
806: #ifndef NOWINDOWMENU
807: case WINDOWMENU:
808: wdomenufunc(item);
809: wfree(menu);
810: break;
811: #endif NOWINDOWMENU
812: case TEKMENU:
813: Tdomenufunc(item);
814: break;
815: case SCROLLBARMENU:
816: sdomenufunc(item);
817: break;
818: }
819: }
820:
821: menusync()
822: {
823: XEvent ev;
824:
825: XSync(0);
826: while(QLength() > 0) {
827: XNextEvent(&ev);
828: xeventpass(&ev);
829: }
830: }
831:
832: #define XMENU_TITLE 0
833: #define XMENU_ACTIVEICON (XMENU_TITLE+1)
834: #define XMENU_ALLOWICONINPUT (XMENU_ACTIVEICON+1)
835: #define XMENU_AUTORAISE (XMENU_ALLOWICONINPUT+1)
836: #define XMENU_AUDIBLEBELL (XMENU_AUTORAISE+1)
837: #define XMENU_VISUALBELL (XMENU_AUDIBLEBELL+1)
838: #define XMENU_DEICONWARP (XMENU_VISUALBELL+1)
839: #define XMENU_SENDMOUSE (XMENU_DEICONWARP+1)
840: #define XMENU_LOG (XMENU_SENDMOUSE+1)
841: #define XMENU_LINE (XMENU_LOG+1)
842: #define XMENU_REDRAW (XMENU_LINE+1)
843: #define XMENU_RESUME (XMENU_REDRAW+1)
844: #define XMENU_SUSPEND (XMENU_RESUME+1)
845: #define XMENU_INTR (XMENU_SUSPEND+1)
846: #define XMENU_HANGUP (XMENU_INTR+1)
847: #define XMENU_TERM (XMENU_HANGUP+1)
848: #define XMENU_KILL (XMENU_TERM+1)
849:
850: static char *xtext[] = {
851: "Title Bar(s)",
852: "Active Icon",
853: "Allow Icon Input",
854: "Auto Raise",
855: "Audible Bell",
856: "Visual Bell",
857: "Deiconify Warp",
858: "Send Mouse Pos",
859: "Logging",
860: "-",
861: "Redraw",
862: "Continue",
863: "Suspend",
864: "Interrupt",
865: "Hangup",
866: "Terminate",
867: "Kill",
868: 0,
869: };
870:
871: static int xauto;
872: static int xabell;
873: static int xvbell;
874: static int xdeiconwarp;
875: static int xsendmouse;
876: static int xlog;
877: static int xtbar;
878: static int xactive_icon;
879: static int xallow_iconinput;
880:
881: Menu *xsetupmenu(menu)
882: register Menu **menu;
883: {
884: register Screen *screen = &term.screen;
885: register char **cp;
886: register int i;
887:
888: if (*menu == NULL) {
889: if ((*menu = NewMenu("xterm X10/6.6B", re_verse)) == NULL)
890: return(NULL);
891: for(cp = xtext ; *cp ; cp++)
892: AddMenuItem(*menu, *cp);
893: if(xtbar = (Titlebar(screen) > 0))
894: CheckItem(*menu, XMENU_TITLE);
895: if(xactive_icon = screen->active_icon)
896: CheckItem(*menu, XMENU_ACTIVEICON);
897: if(xallow_iconinput = (term.flags & ICONINPUT))
898: CheckItem(*menu, XMENU_ALLOWICONINPUT);
899: SetItemDisable(*menu, XMENU_ALLOWICONINPUT, !xactive_icon);
900: if(xauto = screen->autoraise)
901: CheckItem(*menu, XMENU_AUTORAISE);
902: if(xabell = screen->audiblebell)
903: CheckItem(*menu, XMENU_AUDIBLEBELL);
904: if(xvbell = screen->visualbell)
905: CheckItem(*menu, XMENU_VISUALBELL);
906: if(xdeiconwarp = screen->deiconwarp)
907: CheckItem(*menu, XMENU_DEICONWARP);
908: if(xlog = screen->logging)
909: CheckItem(*menu, XMENU_LOG);
910: if(xsendmouse = screen->send_mouse_pos)
911: CheckItem(*menu, XMENU_SENDMOUSE);
912: DisableItem(*menu, XMENU_LINE);
913: if(screen->inhibit & I_LOG)
914: DisableItem(*menu, XMENU_LOG);
915: if(screen->inhibit & I_SIGNAL)
916: for(i = XMENU_SUSPEND ; i <= XMENU_KILL ; i++)
917: DisableItem(*menu, i);
918: return(*menu);
919: }
920: if (xtbar != (Titlebar(screen) > 0))
921: SetItemCheck(*menu, XMENU_TITLE, (xtbar =
922: (Titlebar(screen) > 0)));
923: if (xactive_icon != screen->active_icon) {
924: SetItemCheck(*menu, XMENU_ACTIVEICON,
925: (xactive_icon = screen->active_icon));
926: SetItemDisable(*menu, XMENU_ALLOWICONINPUT, !xactive_icon);
927: }
928: if (xallow_iconinput != (term.flags & ICONINPUT))
929: SetItemCheck(*menu, XMENU_ALLOWICONINPUT,
930: (xallow_iconinput = (term.flags & ICONINPUT)));
931: if (xauto != screen->autoraise)
932: SetItemCheck(*menu, XMENU_AUTORAISE, (xauto =
933: screen->autoraise));
934: if (xabell != screen->audiblebell)
935: SetItemCheck(*menu, XMENU_AUDIBLEBELL, (xabell =
936: screen->audiblebell));
937: if (xvbell != screen->visualbell)
938: SetItemCheck(*menu, XMENU_VISUALBELL, (xvbell =
939: screen->visualbell));
940: if (xdeiconwarp != screen->deiconwarp)
941: SetItemCheck(*menu, XMENU_DEICONWARP, (xdeiconwarp =
942: screen->deiconwarp));
943: if (xsendmouse != screen->send_mouse_pos)
944: SetItemCheck(*menu, XMENU_SENDMOUSE,
945: (xsendmouse = screen->send_mouse_pos));
946: if (xlog != screen->logging)
947: SetItemCheck(*menu, XMENU_LOG, (xlog = screen->logging));
948: return(*menu);
949: }
950:
951: xdomenufunc(item)
952: int item;
953: {
954: register Screen *screen = &term.screen;
955:
956: switch (item) {
957: case XMENU_TITLE:
958: if(Titlebar(screen)) {
959: screen->fullVwin.titlebar =
960: screen->fullTwin.titlebar = 0;
961: if(VWindow(screen))
962: VTTitleHide();
963: if(TWindow(screen))
964: TekTitleHide();
965: } else {
966: screen->fullVwin.titlebar =
967: screen->fullTwin.titlebar = screen->titleheight;
968: if(VWindow(screen))
969: VTTitleShow(FALSE);
970: if(TWindow(screen))
971: TekTitleShow(FALSE);
972: }
973: break;
974:
975: case XMENU_ACTIVEICON:
976: screen->active_icon = !screen->active_icon;
977: if (screen->active_icon && !screen->fnt_icon) {
978: FontInfo *fInfo = XOpenFont( f_i );
979: screen->fnt_icon = fInfo->id;
980: screen->iconVwin.f_width = fInfo->width;
981: screen->iconVwin.f_height = fInfo->height;
982: }
983:
984: if (screen->iconVwin.window) {
985: SetIconSize( screen );
986: XSelectInput( screen->iconVwin.window,
987: screen->active_icon
988: && (term.flags & ICONINPUT)
989: ? ICONWINDOWEVENTS | ICONINPUTEVENTS
990: : ICONWINDOWEVENTS );
991: }
992:
993: if (screen->iconTwin.window) {
994: TSetIconSize( screen );
995: XSelectInput( screen->iconTwin.window,
996: screen->active_icon
997: && (term.flags & ICONINPUT)
998: ? TICONWINDOWEVENTS | ICONINPUTEVENTS
999: : TICONWINDOWEVENTS );
1000: }
1001:
1002: break;
1003:
1004: case XMENU_ALLOWICONINPUT:
1005: term.flags ^= ICONINPUT;
1006: if (screen->iconVwin.window)
1007: XSelectInput( screen->iconVwin.window,
1008: screen->active_icon
1009: && (term.flags & ICONINPUT)
1010: ? ICONWINDOWEVENTS | ICONINPUTEVENTS
1011: : ICONWINDOWEVENTS );
1012:
1013: if (screen->iconTwin.window)
1014: XSelectInput( screen->iconTwin.window,
1015: screen->active_icon
1016: && (term.flags & ICONINPUT)
1017: ? TICONWINDOWEVENTS | ICONINPUTEVENTS
1018: : TICONWINDOWEVENTS );
1019:
1020: break;
1021:
1022: case XMENU_AUTORAISE:
1023: screen->autoraise = !screen->autoraise;
1024: break;
1025:
1026: case XMENU_DEICONWARP:
1027: screen->deiconwarp = !screen->deiconwarp;
1028: break;
1029:
1030: case XMENU_AUDIBLEBELL:
1031: screen->audiblebell = !screen->audiblebell;
1032: break;
1033:
1034: case XMENU_VISUALBELL:
1035: screen->visualbell = !screen->visualbell;
1036: break;
1037:
1038: case XMENU_SENDMOUSE:
1039: screen->send_mouse_pos = !screen->send_mouse_pos;
1040: break;
1041:
1042: case XMENU_LOG:
1043: if(screen->logging)
1044: CloseLog(screen);
1045: else
1046: StartLog(screen);
1047: break;
1048:
1049: case XMENU_REDRAW:
1050: Redraw();
1051: break;
1052:
1053: case XMENU_RESUME:
1054: if(screen->pid > 1)
1055: killpg(getpgrp(screen->pid), SIGCONT);
1056: break;
1057:
1058: case XMENU_SUSPEND:
1059: if(screen->pid > 1)
1060: killpg(getpgrp(screen->pid), SIGTSTP);
1061: break;
1062:
1063: case XMENU_INTR:
1064: if(screen->pid > 1)
1065: killpg(getpgrp(screen->pid), SIGINT);
1066: break;
1067:
1068: case XMENU_HANGUP:
1069: if(screen->pid > 1)
1070: killpg(getpgrp(screen->pid), SIGHUP);
1071: break;
1072:
1073: case XMENU_TERM:
1074: if(screen->pid > 1)
1075: killpg(getpgrp(screen->pid), SIGTERM);
1076: break;
1077:
1078: case XMENU_KILL:
1079: if(screen->pid > 1)
1080: killpg(getpgrp(screen->pid), SIGKILL);
1081: break;
1082: }
1083: }
1084:
1085: #ifndef NOWINDOWMENU
1086: Menu *wsetupmenu(menu)
1087: register Menu **menu;
1088: {
1089: register Window *cp, *wp;
1090: register char **np;
1091: register int i, j;
1092: Window win, *children;
1093: int nchildren;
1094: char *name;
1095: WindowInfo winfo;
1096:
1097: if(!XQueryTree(RootWindow, &win, &nchildren, &children))
1098: return(NULL);
1099: if(nchildren > MAXWINDOWMENU)
1100: nchildren = MAXWINDOWMENU;
1101: if ((*menu = NewMenu("Windows", re_verse)) == NULL) {
1102: free((char *)children);
1103: return(NULL);
1104: }
1105: np = namebuf;
1106: wp = windows;
1107: for(i = nchildren, j = 0, cp = children ; i > 0 ; cp++, i--) {
1108: if(!XQueryWindow(*cp, &winfo))
1109: goto failed;
1110: if(winfo.mapped != IsMapped)
1111: continue;
1112: if(!XFetchName(*cp, &name)) {
1113: failed:
1114: free((char *)children);
1115: *np = NULL;
1116: wfree(*menu);
1117: return(NULL);
1118: }
1119: if(name == NULL)
1120: continue;
1121: AddMenuItem(*menu, *np++ = name);
1122: *wp++ = *cp;
1123: if(strcmp(wname, name) == 0)
1124: CheckItem(*menu, j);
1125: j++;
1126: }
1127: *np = NULL;
1128: free((char *)children);
1129: if(np > namebuf)
1130: return(*menu);
1131: DisposeMenu(*menu);
1132: return(NULL);
1133: }
1134:
1135: wdomenufunc(item)
1136: int item;
1137: {
1138: register Window w;
1139:
1140: if((w = windows[item]) != NULL)
1141: XRaiseWindow(w);
1142: }
1143:
1144: wfree(menu)
1145: Menu *menu;
1146: {
1147: register char **np;
1148:
1149: for(np = namebuf ; *np ; np++)
1150: free(*np);
1151: DisposeMenu(menu);
1152: }
1153: #endif NOWINDOWMENU
1154:
1155: MenuNewCursor(cur)
1156: register Cursor cur;
1157: {
1158: register Menu **menu;
1159: register int i;
1160: extern Cursor Menu_DefaultCursor;
1161:
1162: Menu_DefaultCursor = cur;
1163: for(i = XTERMMENU, menu = menus ; i <= TEKMENU ; menu++, i++) {
1164: if(!*menu)
1165: continue;
1166: (*menu)->menuCursor = cur;
1167: if((*menu)->menuWindow)
1168: XDefineCursor((*menu)->menuWindow, cur);
1169: }
1170: }
1171: #else MODEMENU
1172:
1173: ModeMenu(term, reply, pty)
1174: Terminal *term;
1175: register XKeyOrButtonEvent *reply;
1176: int pty; /* file descriptor of pty */
1177: {
1178: register Screen *screen = &term->screen;
1179:
1180: if((reply->window == screen->title.tbar || reply->window ==
1181: screen->Ttitle.tbar) && InTitle(screen, reply->window,
1182: reply->x))
1183: return;
1184: Bell();
1185: }
1186: #endif MODEMENU
1187:
1188: GINbutton(term, reply, pty)
1189: Terminal *term;
1190: XKeyOrButtonEvent *reply;
1191: int pty; /* file descriptor of pty */
1192: {
1193: register Screen *screen = &term->screen;
1194: register int i;
1195:
1196: if(screen->TekGIN) {
1197: i = "rml"[reply->detail & 0xff];
1198: if(reply->detail & ShiftMask)
1199: i = toupper(i);
1200: TekEnqMouse(i | 0x80); /* set high bit */
1201: TekGINoff();
1202: } else
1203: Bell();
1204: }
1205:
1206: Bogus(term, reply, pty)
1207: Terminal *term;
1208: XKeyOrButtonEvent *reply;
1209: int pty; /* file descriptor of pty */
1210: {
1211: Bell();
1212: }
1213:
1214: Silence(term, reply, pty)
1215: Terminal *term;
1216: XKeyOrButtonEvent *reply;
1217: int pty; /* file descriptor of pty */
1218: {
1219: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.