1: #include <X/mit-copyright.h>
   2: 
   3: /* Copyright    Massachusetts Institute of Technology    1984, 1985	*/
   4: /*
   5: button.c	Handles button events in the terminal emulator.
   6: 		does cut/paste operations, change modes via menu,
   7: 		passes button events through to some applications.
   8: 				J. Gettys.
   9: */
  10: #ifndef lint
  11: static char *rcsid_window_c = "$Header: button.c,v 10.11 86/02/01 16:05:41 tony Rel $";
  12: #endif	lint
  13: #include <stdio.h>
  14: #include <X/Xlib.h>
  15: #include "ptyx.h"
  16: #ifdef MODEMENU
  17: #include <X/XMenu.h>
  18: #endif
  19: 
  20: #define NBUTS 3
  21: #define DIRS 2
  22: #define UP 1
  23: #define DOWN 0
  24: #define SHIFTS 8        /* three keys, so eight combinations */
  25: char *GetRestOfLine();
  26: char *SaveText();
  27: extern UnSaltText();
  28: extern SaltTextAway();
  29: extern StartCut();
  30: extern ReExecute();
  31: extern EditorDown();
  32: #ifdef MODEMENU
  33: extern ModeMenu();
  34: extern char *xterm_name;
  35: #else
  36: #define ModeMenu Bogus
  37: #endif MODEMENU
  38: extern Bogus(), Silence();
  39: /* due to LK201 limitations, not all of the below are actually possible */
  40: int (*bfunc[SHIFTS][DIRS][NBUTS])() = {
  41: /*	left		middle		right	*/
  42:     EditorDown, EditorDown, EditorDown, /* down	|	  */
  43:     Silence,    Silence,    Silence,    /* up	|no shift */
  44: 
  45:     Silence,    StartCut,   Silence,    /* down |	  */
  46:     ReExecute,  SaltTextAway,   UnSaltText, /* up	|shift	  */
  47: 
  48:     Bogus,      Bogus,      Bogus,      /* down	|	  */
  49:     Silence,    Silence,    Silence,    /* up	|meta	  */
  50: 
  51:     Bogus,      Bogus,      Bogus,      /* down	|	  */
  52:     Silence,    Silence,    Silence,    /* up	|meta shift */
  53: 
  54:     Bogus,      ModeMenu,   Bogus,      /* down	|	  */
  55:     Silence,    Silence,    Silence,    /* up	|control  */
  56: 
  57:     Bogus,      Bogus,      Bogus,      /* down	|	  */
  58:     Silence,    Silence,    Silence,    /* up	|ctl shift */
  59: 
  60:     Bogus,      Bogus,      Bogus,      /* down	|	  */
  61:     Silence,    Silence,    Silence,    /* up	|no shift */
  62: 
  63:     Bogus,      Bogus,      Bogus,      /* down	| control  */
  64:     Silence,    Silence,    Silence     /* up	|meta shift*/
  65: 
  66: };  /* button, shift keys, and direction */
  67: 
  68: static crow, ccol;  /* cut row and column */
  69: 
  70: HandleButtons(term, reply, pty)
  71: register Terminal *term;
  72: register XEvent *reply;
  73: int pty;            /* file descriptor of pty */
  74: {
  75:     int (*bp)();
  76:     int dir = DOWN;
  77:     /* so table above will be nice, we change left to right */
  78:     int button = 2 - ((XKeyOrButtonEvent *)reply)->detail & 0177;
  79:     int shift = KeyState(((XKeyOrButtonEvent *)reply)->detail);
  80:     switch (reply->type) {
  81:         case ButtonPressed:
  82:             dir = DOWN;
  83:             break;
  84:         case ButtonReleased:
  85:             dir = UP;
  86:             break;
  87:         default:
  88:             break;
  89:     }
  90:     bp = bfunc[shift][dir][button];
  91:     if (bp != NULL) return ((*bp)(term, reply, pty));
  92:     XFeep(0);
  93:     return(0);
  94: }
  95: 
  96: UnSaltText(term, reply, pty)
  97: register Terminal *term;
  98: register XKeyOrButtonEvent *reply;
  99: int pty;            /* file descriptor of pty */
 100: {
 101:     char *line;
 102:     int nbytes;
 103:     register char *lag, *cp, *end;
 104: 
 105:     line = XFetchBytes(&nbytes);
 106:     end = &line[nbytes];
 107:     lag = line;
 108:     for (cp = line; cp != end; cp++)
 109:     {
 110:         if (*cp != '\n') continue;
 111:         *cp = '\r';
 112:         write(pty, lag, cp - lag + 1);
 113:         lag = cp + 1;
 114:     }
 115:     if (lag != end)
 116:         write(pty, lag, end - lag);
 117:     free (line);    /* free text from fetch */
 118:     return(0);
 119: }
 120: 
 121: ReExecute(term, reply, pty)
 122: register Terminal *term;
 123: register XKeyOrButtonEvent *reply;
 124: int pty;            /* file descriptor of pty */
 125: {
 126:     char *line = GetRestOfLine(&term->screen, reply);
 127:     register int nbytes = strlen(line);
 128: 
 129:     write(pty, line, nbytes);
 130:     line[nbytes] = '\n';
 131:     XStoreBytes(line, nbytes);
 132:     free (line);    /* free text from fetch */
 133:     return(0);
 134: }
 135: 
 136: char *GetRestOfLine(screen, reply)
 137: register XKeyOrButtonEvent *reply;
 138: register Screen *screen;
 139: {
 140:     char *line;
 141:     int i;
 142:     register int row, col;
 143:     row = (reply->y - screen->border) / screen->f_height;
 144:     col = (reply->x - screen->border) / screen->f_width;
 145:     if ( row < 0 ) row = 0;
 146:     else if ( row > screen->max_row ) row = screen->max_row;
 147:     if ( col < 0 ) col = 0;
 148:     else if ( col > screen->max_col ) col = screen->max_col;
 149:     i = Length(screen, row, col, screen->max_col);
 150:     if((line = (char *)malloc(i + 2)) == NULL) Error();
 151:     SaveText(screen, row, col, screen->max_col, line);
 152:     line[i] = '\r';
 153:     line[i+1] = '\0';
 154:     return(line);
 155: }
 156: 
 157: StartCut(term, reply, pty)
 158: register XKeyOrButtonEvent *reply;
 159: Terminal *term;
 160: int pty;
 161: {
 162:     register Screen *screen = &term->screen;
 163:     crow = (reply->y - screen->border) / screen->f_height;
 164:     ccol = (reply->x - screen->border) / screen->f_width;
 165:     return(0);
 166: }
 167: 
 168: SaltTextAway(term, reply, pty)
 169: register XKeyOrButtonEvent *reply;
 170: Terminal *term;
 171: int pty;
 172: {
 173:     register Screen *screen = &term->screen;
 174:     register int i, j = 0;
 175:     register row, col;
 176:     register char *str;     /* string to be saved */
 177:     char *line, *lp;
 178:     row = (reply->y - screen->border) / screen->f_height;
 179:     col = (reply->x - screen->border) / screen->f_width;
 180: 
 181:     /* first order of business is to guarantee that crow,ccol is before */
 182:     /* row,col. */
 183:     if ( row == crow ) {        /* must exchange as pairs */
 184:         if ( ccol > col ) {     /* may have to exchange columns */
 185:             register int tmp;
 186:             tmp = ccol; ccol = col; col = tmp;
 187:         }
 188:     }
 189:     else {
 190:         if ( crow > row ) { /* may have to exchange row and col */
 191:             register int tmp;
 192:             tmp = ccol; ccol = col; col = tmp;
 193:             tmp = crow; crow = row; row = tmp;
 194:         }
 195:     }
 196: 
 197:     if (ccol < 0) ccol = 0;
 198:     else if (ccol > screen->max_col) { crow++; ccol = 0; }
 199:     if (crow < 0) crow = ccol = 0;
 200:     else if (crow > screen->max_row) { crow = screen->max_row; ccol = 0; }
 201: 
 202:     if (row > screen->max_row) { row = screen->max_row + 1 ; col = 0; }
 203:     else if (--col > screen->max_col) col = screen->max_col;
 204: 
 205:     /* first we need to know how long the string is before we can save it*/
 206: 
 207:     if ( row == crow ) j = Length(screen, crow, ccol, col);
 208:     else {  /* two cases, cut is on same line, cut spans multiple lines */
 209:         j += Length(screen, crow, ccol, screen->max_col) + 1;
 210:         for(i = crow + 1; i < row; i++)
 211:             j += Length(screen, i, 0, screen->max_col) + 1;
 212:         if (col >= 0)
 213:             j += Length(screen, row, 0, col);
 214:     }
 215: 
 216:     /* now get some memory to save it in */
 217: 
 218:     if((line = (char *)malloc(j + 1)) == NULL) Error();
 219:     line[j] = '\0';     /* make sure it is null terminated */
 220:     lp = line;      /* lp points to where to save the text */
 221:     if ( row == crow ) lp = SaveText(screen, row, ccol, col, lp);
 222:     else {
 223:         lp = SaveText(screen, crow, ccol, screen->max_col, lp);
 224:         *lp ++ = '\n';  /* put in newline at end of line */
 225:         for(i = crow +1; i < row; i++) {
 226:             lp = SaveText(screen, i, 0, screen->max_col, lp);
 227:             *lp ++ = '\n';
 228:             }
 229:         if (col >= 0)
 230:             lp = SaveText(screen, row, 0, col, lp);
 231:     }
 232:     *lp = '\0';     /* make sure we have end marked */
 233: 
 234:     XStoreBytes(line, j);
 235:     free(line);
 236:     return(0);
 237: }
 238: 
 239: /* returns number of chars in line from scol to ecol out */
 240: int Length(screen, row, scol, ecol)
 241: register int row, scol, ecol;
 242: register Screen *screen;
 243: {
 244:     register short *ch;
 245:     int end = 0;
 246:     ch = screen->buf[row];
 247:     while (ecol >= scol &&
 248:         ((ch[ecol] & CHAR) == 0 || (ch[ecol] & CHAR) == ' '))
 249:         ecol--;
 250:     return (ecol - scol + 1);
 251: }
 252: 
 253: /* copies text into line, preallocated */
 254: char *SaveText(screen, row, scol, ecol, lp)
 255: int row;
 256: int scol, ecol;
 257: Screen *screen;
 258: register char *lp;      /* pointer to where to put the text */
 259: {
 260:     register int i = 0;
 261:     register short *ch = screen->buf[row];
 262:     register int c;
 263:     if ((i = Length(screen, row, scol, ecol)) == 0) return(lp);
 264:     ecol = scol + i;
 265:     for (i = scol; i < ecol; i++)
 266:     {
 267:         c = ch[i] & CHAR;
 268:         if (c == 0) c = ' ';
 269:         *lp++ = c;
 270:     }
 271:     return(lp);
 272: }
 273: 
 274: EditorDown (term, reply, pty)
 275: Terminal *term;
 276: register XKeyOrButtonEvent *reply;
 277: int pty;            /* file descriptor of pty */
 278: {
 279:     register Screen *screen = &term->screen;
 280:     char line[6];
 281:     register unsigned row, col;
 282:     int button = 2 - reply->detail & 0177;
 283:     if (!screen->send_mouse_pos) {
 284:         XFeep(0);
 285:         return(0);
 286:     }
 287:     row = (reply->y - screen->border) / screen->f_height;
 288:     col = (reply->x - screen->border) / screen->f_width;
 289:     strcpy(line, "\033[M");
 290:     line[3] = ' ' + button;
 291:     line[4] = ' '+col+1;
 292:     line[5] = ' '+row+1;
 293:     write(pty, line, 6);
 294:     return(0);
 295: }
 296: 
 297: #ifdef MODEMENU
 298: 
 299: static int menutoggled;
 300: static Terminal *menuterm;
 301: 
 302: HandleMenuEvent (rep)
 303:     XEvent *rep;
 304: {
 305:     register Screen *screen = &menuterm->screen;
 306: 
 307:     switch (rep->type)
 308:     {
 309:         case ExposeWindow:
 310:             menutoggled = 1;
 311:             if (ScreenResize (screen,
 312:                 ((XExposeWindowEvent *)rep)->width,
 313:                 ((XExposeWindowEvent *)rep)->height,
 314:                 menuterm->flags) != -1)
 315:             {
 316:             TabReset (menuterm->tabs);
 317:             XClear (screen->window);
 318:             ScrnRefresh (screen, 0, 0,
 319:                      screen->max_row + 1,
 320:                      screen->max_col + 1);
 321: 
 322:             if (screen->TekEmu) TekRefresh (menuterm);
 323:             }
 324:             break;
 325: 
 326:         case ExposeRegion:
 327:             if (HandleExposure (screen, rep))
 328:                 menutoggled = 1;
 329:             break;
 330:         }
 331: }
 332: 
 333: #define MMENU_SCROLL 1
 334: #define MMENU_VIDEO 2
 335: #define MMENU_WRAP 3
 336: #define MMENU_NLM 4
 337: #define MMENU_CURSOR 5
 338: #define MMENU_PAD 6
 339: #define MMENU_RESET 7
 340: #define MMENU_FULLRESET 8
 341: 
 342: static XMenu *menu = NULL;
 343: static int menutermflags = 0;
 344: static int menukbdflags = 0;
 345: static int lastmenupane = 0;
 346: static int lastmenusel = 0;
 347: 
 348: ModeMenu(term, reply, pty)
 349: Terminal *term;
 350: register XKeyOrButtonEvent *reply;
 351: int pty;            /* file descriptor of pty */
 352: {
 353:     register Screen *screen = &term->screen;
 354:     register char **ptr;
 355:     int x, y;
 356:     int ulx, uly;
 357:     int menuw, menuh;
 358:     int pnum = lastmenupane, snum = lastmenusel;
 359:     int status, val;
 360: 
 361:     if (menu == NULL) {
 362:         if ((menu = (XMenu *)XMenuCreate(RootWindow, xterm_name)) == NULL)
 363:         return(0);
 364:         XMenuAddPane(menu, "Modes", 1);
 365: #ifdef JUMPSCROLL
 366:         XMenuAddSelection(menu, 0, MMENU_SCROLL,
 367:             (term->flags & SMOOTHSCROLL) ? "jump scroll" : "smooth scroll",
 368:             1);
 369: #endif
 370:         XMenuAddSelection(menu, 0, MMENU_VIDEO,
 371:             (term->flags & REVERSE_VIDEO) ? "normal video" : "reverse video",
 372:             1);
 373:         XMenuAddSelection(menu, 0, MMENU_WRAP,
 374:             (term->flags & WRAPAROUND) ? "no wrap" : "auto wrap",
 375:             1);
 376:         XMenuAddSelection(menu, 0, MMENU_NLM,
 377:             (term->flags & LINEFEED) ? "normal linefeed" : "auto linefeed",
 378:             1);
 379:         XMenuAddSelection(menu, 0, MMENU_CURSOR,
 380:             (term->keyboard.flags & CURSOR_APL) ? "normal cursors" : "application cursors",
 381:             1);
 382:         XMenuAddSelection(menu, 0, MMENU_PAD,
 383:             (term->keyboard.flags & KYPD_APL) ? "numeric pad" : "application pad",
 384:             1);
 385:         XMenuAddSelection(menu, 0, MMENU_RESET, "soft reset", 1);
 386:         XMenuAddSelection(menu, 0, MMENU_FULLRESET, "full reset", 1);
 387:         menuterm = term;
 388:         menutermflags = term->flags;
 389:         menukbdflags = term->keyboard.flags;
 390:     }
 391: #ifdef JUMPSCROLL
 392:     if ((menutermflags ^ term->flags) & SMOOTHSCROLL) {
 393:         XMenuChangeSelection(menu, 0, MMENU_SCROLL-1, MMENU_SCROLL, 1,
 394:             (term->flags & SMOOTHSCROLL) ? "jump scroll" : "smooth scroll",
 395:             1);
 396:     }
 397: #endif
 398:     if ((menutermflags ^ term->flags) & REVERSE_VIDEO) {
 399:         XMenuChangeSelection(menu, 0, MMENU_VIDEO-1, MMENU_VIDEO, 1,
 400:             (term->flags & REVERSE_VIDEO) ? "normal video" : "reverse video",
 401:             1);
 402:     }
 403:     if ((menutermflags ^ term->flags) & WRAPAROUND) {
 404:         XMenuChangeSelection(menu, 0, MMENU_WRAP-1, MMENU_WRAP, 1,
 405:             (term->flags & WRAPAROUND) ? "no wrap" : "auto wrap",
 406:             1);
 407:     }
 408:     if ((menutermflags ^ term->flags) & LINEFEED) {
 409:         XMenuChangeSelection(menu, 0, MMENU_NLM-1, MMENU_NLM, 1,
 410:             (term->flags & LINEFEED) ? "normal linefeed" : "auto linefeed",
 411:             1);
 412:     }
 413:     if ((menukbdflags ^ term->keyboard.flags) & CURSOR_APL) {
 414:         XMenuChangeSelection(menu, 0, MMENU_CURSOR-1, MMENU_CURSOR, 1,
 415:             (term->keyboard.flags & CURSOR_APL) ? "normal cursors" : "application cursors",
 416:             1);
 417:     }
 418:     if ((menukbdflags ^ term->keyboard.flags) & KYPD_APL) {
 419:         XMenuChangeSelection(menu, 0, MMENU_PAD-1, MMENU_PAD, 1,
 420:             (term->keyboard.flags & KYPD_APL) ? "numeric pad" : "application pad",
 421:             1);
 422:     }
 423:     XMenuRecompute(menu);
 424:     menutermflags = term->flags;
 425:     menukbdflags = term->keyboard.flags;
 426:     x = (reply->location >> 16) & 0xffff;
 427:     y = reply->location & 0xffff;
 428:     XMenuLocate(menu, pnum, snum, x, y, &ulx, &uly, &menuw, &menuh);
 429:     if ((ulx + menuw) > DisplayWidth())
 430:         x -= ((ulx + menuw) - DisplayWidth());
 431:     if (ulx < 0)
 432:         x -= ulx;
 433:     if ((uly + menuh) > DisplayHeight())
 434:         y -= ((uly + menuh) - DisplayHeight());
 435:     if (uly < 0)
 436:         y -= uly;
 437:     XMenuEventHandler(HandleMenuEvent);
 438:     menutoggled = 0;
 439:     status = XMenuActivate(
 440:         menu,
 441:         &pnum, &snum,
 442:         x, y,
 443:         MiddleMask|ButtonReleased,
 444:         (char **)&val
 445:     );
 446:     if (status == XM_FAILURE) return(menutoggled);
 447:     if (status == XM_NO_SELECT) return(menutoggled);
 448:     else {
 449:         lastmenupane = pnum;
 450:         lastmenusel = snum;
 451:     }
 452:     switch (val) {
 453: #ifdef JUMPSCROLL
 454:     case MMENU_SCROLL:
 455:         term->flags ^= SMOOTHSCROLL;
 456:         if (term->flags & SMOOTHSCROLL) {
 457:         screen->jumpscroll = 0;
 458:         if (screen->scroll_amt) FlushScroll(screen);
 459:         } else if (!screen->TekEmu) screen->jumpscroll = 1;
 460:         break;
 461: #endif
 462:     case MMENU_VIDEO:
 463:         term->flags ^= REVERSE_VIDEO;
 464:         ReverseVideo(term);
 465:         menutoggled = 1;
 466:         break;
 467:     case MMENU_WRAP:
 468:         term->flags ^= WRAPAROUND;
 469:     case MMENU_NLM:
 470:         term->flags ^= LINEFEED;
 471:     case MMENU_CURSOR:
 472:         term->keyboard.flags ^= CURSOR_APL;
 473:         break;
 474:     case MMENU_PAD:
 475:         term->keyboard.flags ^= KYPD_APL;
 476:         break;
 477:     case MMENU_FULLRESET:
 478:         TabReset (term->tabs);
 479:         term->keyboard.flags = NULL;
 480:         screen->mode = ANSInormal;
 481:         /* Reset Tektronix alpha mode */
 482:         screen->TekGMode = 0;
 483:         screen->TekAMode = 0;
 484:         screen->gsets[0] = 'B';
 485:         screen->gsets[1] = 'B';
 486:         screen->gsets[2] = '<';
 487:         screen->gsets[3] = '<';
 488:         screen->curgl = 0;
 489:         screen->curgr = 2;
 490:         screen->cur_x = screen->cur_y = 0;
 491:         screen->cur_X = screen->cur_Y = 0;
 492:         if (term->flags & REVERSE_VIDEO) ReverseVideo(term);
 493:         term->flags &= ~REVERSE_VIDEO;
 494:         menutoggled = 1;
 495:         CursorSet(screen, 0, 0, term->flags);
 496:         ClearScreen(screen);
 497:         term->flags = WRAPAROUND|SMOOTHSCROLL;
 498:     case MMENU_RESET:
 499:         /* reset scrolling region */
 500:         screen->top_marg = 0;
 501:         screen->bot_marg = screen->max_row;
 502:         term->flags &= ~ORIGIN;
 503:         break;
 504:     }
 505:     return(menutoggled);
 506: }
 507: #endif MODEMENU
 508: 
 509: Bogus(term, reply, pty)
 510: Terminal *term;
 511: XKeyOrButtonEvent *reply;
 512: int pty;            /* file descriptor of pty */
 513: {
 514:     XFeep(0);
 515:     return(0);
 516: }
 517: 
 518: Silence(term, reply, pty)
 519: Terminal *term;
 520: XKeyOrButtonEvent *reply;
 521: int pty;            /* file descriptor of pty */
 522: {
 523:     return(0);
 524: }

Defined functions

Bogus defined in line 509; used 19 times
EditorDown defined in line 274; used 4 times
GetRestOfLine defined in line 136; used 2 times
HandleButtons defined in line 70; used 1 times
HandleMenuEvent defined in line 302; used 1 times
Length defined in line 240; used 6 times
ModeMenu defined in line 348; never used
ReExecute defined in line 121; used 2 times
SaltTextAway defined in line 168; used 2 times
SaveText defined in line 254; used 6 times
Silence defined in line 518; used 24 times
StartCut defined in line 157; used 2 times
UnSaltText defined in line 96; used 2 times

Defined variables

lastmenupane defined in line 345; used 2 times
lastmenusel defined in line 346; used 2 times
menu defined in line 342; used 20 times
menukbdflags defined in line 344; used 4 times
menutermflags defined in line 343; used 6 times
menutoggled defined in line 299; used 8 times
rcsid_window_c defined in line 11; never used

Defined macros

DIRS defined in line 21; used 1 times
  • in line 40
DOWN defined in line 23; used 2 times
MMENU_CURSOR defined in line 337; used 3 times
MMENU_FULLRESET defined in line 340; used 1 times
MMENU_NLM defined in line 336; used 3 times
MMENU_PAD defined in line 338; used 3 times
MMENU_RESET defined in line 339; used 1 times
MMENU_SCROLL defined in line 333; used 3 times
MMENU_VIDEO defined in line 334; used 3 times
MMENU_WRAP defined in line 335; used 3 times
ModeMenu defined in line 36; used 2 times
NBUTS defined in line 20; used 1 times
  • in line 40
SHIFTS defined in line 24; used 1 times
  • in line 40
UP defined in line 22; used 1 times
  • in line 85
Last modified: 1986-02-01
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 1858
Valid CSS Valid XHTML 1.0 Strict