Annotation of 43BSD/contrib/X/xterm/button.c, revision 1.1.1.1

1.1       root        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: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.