Annotation of researchv9/cmd/emacs/emacs_cmds.c, revision 1.1.1.1

1.1       root        1: /* EMACS_MODES: c, !fill */
                      2: #include "emacs_io.h"
                      3: #include "emacs_gb.h"
                      4: #include "emacs_cmds.h"
                      5: #include <signal.h>
                      6: #ifdef ux3
                      7: #include <fcntl.h>
                      8: #endif
                      9: 
                     10: /* lext -- extend line up to position if necessary */
                     11: 
                     12: lext(line,col)
                     13: /* Keywords: picture-mode movement insertion */
                     14: {
                     15:        mvc (line,col);
                     16:        if (column<col) insertc(col-column,' ');
                     17: }
                     18: 
                     19: dput(c)
                     20: /* Keywords: insertion modes:10 overwrite-mode */
                     21: {
                     22:        if (NODEL) insertc(1,c);
                     23:        else put(c);
                     24: }
                     25: 
                     26: /* move forward COUNT characters */
                     27: /* Keywords: movement commands forwards character-at-a-time picture-mode:20 */
                     28: forw(count)
                     29: 
                     30: register int count;
                     31: {
                     32:        register int retval;
                     33: 
                     34:        if (PICMODE) {
                     35:                if (count>0) {
                     36:                        lext(curln,count+column);
                     37:                        return(1);
                     38:                } else {
                     39:                        column += count;
                     40:                        if (column<0) {
                     41:                                beep();
                     42:                                column=0;
                     43:                                return(0);
                     44:                        } else return(1);
                     45:                }
                     46:        }
                     47:        if (count < 0) {
                     48:                retval = findb(-count);
                     49:        } else {
                     50:                retval = findf(count);
                     51:        }
                     52:        if (retval == 0) beep(); /* couldn't go all the way */
                     53:        move(kline,kcol);
                     54:        return(retval);
                     55: }
                     56: 
                     57: /* backward COUNT characters */
                     58: 
                     59: back(count)
                     60: /* Keywords: movement commands forwards character-at-a-time */
                     61: register int count;
                     62: 
                     63: {
                     64:        forw(-count);                   /* do it this way */
                     65: }
                     66: 
                     67: /* move to previous line, same collumn */
                     68: 
                     69: upl (count) 
                     70: 
                     71: /* Keywords: commands backwards:30 upward-movement movement text-lines */
                     72: register int count;
                     73: 
                     74: {
                     75: 
                     76:        if (curln-count < 1) {
                     77:                if (count == 1) {
                     78:                        beep();
                     79:                        return(0);
                     80:                } else curln = 1;
                     81:        } else curln -= count;
                     82:        if (PICMODE) lext(curln,column);
                     83:        else mvc(curln,column);
                     84:        return(1);
                     85: }
                     86: /* move down one line, same column */
                     87: 
                     88: downl (count)
                     89: /* Keywords: commands forwards:30 downward-movement movement text-lines */
                     90: register int count;
                     91: 
                     92: {
                     93: register int retval;
                     94: 
                     95:        if (((curln += count) > nlines)&& (PICMODE == 0)) {
                     96:                curln = nlines+NLRUN;
                     97:                beep();
                     98:                retval = 0;
                     99:        } else retval = 1;
                    100:        if (PICMODE) lext(curln,column);
                    101:        else mvc(curln,column);
                    102:        return(retval);
                    103: }
                    104: 
                    105: 
                    106: /* abort EMACS */
                    107: 
                    108: int aborts = 0;
                    109: eabort(sig)
                    110: int sig;
                    111: {
                    112: /* Keywords: internal-errors unix-interface commands */
                    113:        if (sig){
                    114:                signal(sig,SIG_DFL); /* Prevent looping */
                    115:        }
                    116:        signal (SIGIOT,SIG_DFL);
                    117:        cook();
                    118:        if (aborts>3) exit(-1);
                    119:        aborts++;
                    120: #ifdef MINFILES
                    121:        rmtemp();
                    122: #endif
                    123: #ifdef PC
                    124:        rmtemp();
                    125:        exit(-1);
                    126: #else
                    127: #ifdef bsd
                    128:        sigsetmask(0);                  /* ARGH, set mask to allow abort! */
                    129: #endif
                    130:        abort();
                    131:        exit(-1);
                    132: #endif PC
                    133: }
                    134: 
                    135: 
                    136: /* exit EMACS */
                    137: 
                    138: 
                    139: quit()
                    140: 
                    141: {
                    142: /* Keywords: commands exit-processing user-interface:20 unix-interface:30 */
                    143:        clear();
                    144:        cook();
                    145:        statout();
                    146: #ifdef MINFILES
                    147:        rmtemp();                       /* flush temp files */
                    148: #endif
                    149: #ifdef PC
                    150:        rmtemp();
                    151: #else
                    152:        flushproc();
                    153: #endif
                    154:        exit(0);
                    155: }
                    156: 
                    157: /* exit EMACS gracefully */
                    158: 
                    159: gquit()
                    160: /* Keywords: commands exit-processing user-interface:20 unix-interface:30 macro-hooks:10 */
                    161: {
                    162:        if (hooks[Exit_Emacs_Hook]) if (hook(Exit_Emacs_Hook) == 0) return;
                    163:        if(bclean()== 0)quit();
                    164: }
                    165: 
                    166: /* kill line */
                    167: 
                    168: /* if the count is one, and if there is text on the line beyond column,
                    169:  * only that text is killed 
                    170:  * if count is one, and column is at end of line, the end of line is killed */
                    171: /* if count is greater than one, the next count lines (and their end of
                    172:  * lines) are killed */
                    173: 
                    174: /* all killed text is put into the kill stack */
                    175: 
                    176: 
                    177: ekill (count)
                    178: 
                    179: register int count;
                    180: 
                    181: /* Keywords: commands deletion killstack:10 text-lines */
                    182: 
                    183: {
                    184:        register int l;
                    185:        int opic,onodel;
                    186:        
                    187:        if (numarg == 0) {
                    188:                if ((l=leng(curln)) > column) {
                    189:                        return(delc(l-column));
                    190:                }
                    191:        }
                    192:        opic = PICMODE;
                    193:        onodel =NODEL;
                    194:        PICMODE=NODEL=0;                /* Allow line kills! */
                    195:  
                    196:        kline = curln+count;
                    197:        kcol = 0;
                    198:        l= tkill();
                    199:        PICMODE=opic;
                    200:        NODEL=onodel;
                    201:        return(l);
                    202: }
                    203: 
                    204: /* goto beginning of current line */
                    205: 
                    206: begin()
                    207: /* Keywords: text-lines commands movement backwards */
                    208: {
                    209:        move(curln,0);
                    210: }
                    211: 
                    212: /* goto end of line */
                    213: 
                    214: endl()
                    215: /* Keywords: text-lines commands movement backwards */
                    216: {
                    217:        mvc (curln,10000);              /* mvc will adjust line length */
                    218: }
                    219: 
                    220: mquote(arg)
                    221: int arg;
                    222: /* Keywords: quoting commands insertion */
                    223: {
                    224:        quote(arg,0200);
                    225: }
                    226: rquote(arg)
                    227: int arg;
                    228: /* Keywords: quoting commands insertion */
                    229: {
                    230:        quote(arg,0);
                    231: }
                    232:        
                    233: /* insert the next character, whatever it is */
                    234: 
                    235: /* note that newlines inserted ths way act just like unquoted newlines */
                    236: 
                    237: quote(count,metf)
                    238: 
                    239: register int metf;
                    240: register int count;
                    241: 
                    242: {
                    243: /* Keywords: quoting commands insertion */
                    244:        register int c;
                    245: 
                    246:        while(count--) {
                    247:                if ((VERBOSE)&& (MOREIN == 0)) prompt1("%d ^Q: ",count+1);
                    248:                
                    249:                c = getchar();
                    250:                c = c | metf;
                    251:                insertc(1,c);
                    252:                if (VERBOSE && (MOREIN == 0)) {
                    253:                        unprompt();
                    254:                }
                    255:                disup();
                    256:        }
                    257: }
                    258: 
                    259: /* numchar -- convert argument to a character to insert */
                    260: 
                    261: numchar(count)
                    262: /* Keywords: quoting commands insertion argument-processing */
                    263: register int count;
                    264: {
                    265:        insertc(1,count);               /* insert the count */
                    266: }
                    267: 
                    268: 
                    269: /* deletes count characters going forward */
                    270: 
                    271: fdel(count)
                    272: /* Keywords: commands deletion forwards character-at-a-time */
                    273: {
                    274:        IGNORE(findf(count));
                    275:        return(tkill());
                    276: }
                    277: 
                    278: /* deletes count characters going backward */
                    279: 
                    280: bdel(count)
                    281: 
                    282: register int count;
                    283: /* Keywords: commands deletion backwards character-at-a-time */
                    284: {
                    285:        IGNORE(findb(count));
                    286:        return(tkill());
                    287: }
                    288: 
                    289: /* file write command */
                    290: 
                    291: 
                    292: int fright(arg)
                    293: 
                    294: int arg;
                    295: {
                    296:        register char *np;
                    297: /* Keywords: files commands buffers:20 filenames:10 writing */
                    298:        if ((np = expenv(getname("Write file? "))) != NULL) {
                    299:                return(wout(np,arg));
                    300:        }
                    301:        return(0);
                    302: }
                    303: 
                    304: /* fred -- read a file */
                    305: 
                    306: fred(arg)
                    307: 
                    308: int arg;
                    309: {
                    310: /* Keywords: files commands buffers:20 filenames:10 reading */
                    311:        
                    312:        register char *np;
                    313: 
                    314:        if ((np = expenv(getname("Read File? "))) != NULL) {
                    315:                return(readin(np,arg));
                    316:        } else return(0);
                    317: }
                    318: 
                    319: /* forward words -- leaves kline, kcol at spot that is count words
                    320:  *forward */
                    321: 
                    322: 
                    323: wordf(count)
                    324: 
                    325: register int count;
                    326: 
                    327: {
                    328:        kmark();
                    329: 
                    330: /* Keywords: commands:10 forwards movement:50 deletion:50 word-oriented-commands */
                    331:        
                    332:        while (count--) {
                    333:                if (skipf(WRDSEP) || skipf(WRDCHR)) {
                    334:                        return;
                    335:                }
                    336:        }
                    337: }
                    338: 
                    339: /* skips kline, kcol forward until a character without type bit on is
                    340:  * found */
                    341: 
                    342: 
                    343: skipf(bit)
                    344: 
                    345: register int bit;
                    346: /* Keywords: forwards sentence-commands word-oriented-commands movement:20 commands:10 */
                    347: {
                    348:        while (bits[*klptr] & bit) {
                    349:                if (mfk()) return(1);
                    350:        }
                    351:        return(0);
                    352: }
                    353: 
                    354: 
                    355: /* move forward count words */
                    356: 
                    357: mfwrd(count)
                    358: /* Keywords: commands forwards movement word-oriented-commands */
                    359: register int count;
                    360: 
                    361: {
                    362: 
                    363:        wordf(count);
                    364:        move(kline,kcol);
                    365: }
                    366: 
                    367: /* kill next count words */
                    368: 
                    369: 
                    370: 
                    371: kfwrd(count)
                    372: /* Keywords: commands forwards deletion word-oriented-commands */
                    373: register int count;
                    374: 
                    375: {
                    376:        wordf(count);
                    377:        return(tkill());
                    378: }
                    379: 
                    380: /* skip kline, kcol back until a character without type bit is found */
                    381: 
                    382: 
                    383: 
                    384: skipb(bit)
                    385: 
                    386: register int bit;
                    387: /* Keywords: sentence-commands word-oriented-commands movement:20 backwards commands:10 */
                    388: {
                    389:        do {
                    390:                if (mbk()) return(1);
                    391:        } while (bits[*klptr] &bit);
                    392:        return(0);
                    393: }
                    394: 
                    395: /* backward count words, leaves pointer in kline, kcol */
                    396: 
                    397: wordb(count)
                    398: 
                    399: register int count;
                    400: /* Keywords: commands:10 backwards movement:10 deletion:20 word-oriented-commands */
                    401: {
                    402:        kmark();
                    403:        while (count--) {
                    404:                if ((skipb(WRDSEP) || skipb(WRDCHR))) {
                    405:                        return;
                    406:                }
                    407:        }
                    408:        IGNORE(mfk());
                    409: }
                    410: 
                    411: /* move back count words */
                    412: 
                    413: mbwrd(count)
                    414: 
                    415: register int count;
                    416: /* Keywords: commands backwards movement word-oriented-commands */
                    417: {
                    418:        wordb(count);
                    419:        move(kline,kcol);
                    420: }
                    421: 
                    422: /* kill back count words */
                    423: 
                    424: kbwrd(count)
                    425: 
                    426: 
                    427: register int count;
                    428: /* Keywords: commands backwards deletion word-oriented-commands */
                    429: {
                    430:        wordb(count);
                    431:        return(tkill());
                    432: }
                    433: 
                    434: /* kmark -- set kline,kcol and klptr */
                    435: 
                    436: kmark()
                    437: 
                    438: /* Keywords: commands:5 movement:50 deletion:50 character-at-a-time:20 word-oriented-commands:20 sentence-commands:20 */
                    439: 
                    440: {
                    441:        kline = curln;
                    442:        kcol = column;
                    443:        klptr = mkline(kline)+kcol;
                    444: }
                    445: 
                    446: 
                    447: /* move kline,kcol forward one */
                    448: 
                    449: mfk()
                    450: /* Keywords: commands:5 movement:50 deletion:50 character-at-a-time:20 word-oriented-commands:20 sentence-commands:20 forwards */
                    451: {
                    452:        if ((*klptr++)!=EOL ) {
                    453:                ++kcol;
                    454:                return(0);
                    455:        }
                    456:        if (kline<nlines) {
                    457:                ++kline;
                    458:                klptr = mkline(kline);
                    459:                kcol=0;
                    460:                return(0);
                    461:        }
                    462:        return(1);
                    463: }
                    464: 
                    465: /* move kline, kcol back one character */
                    466: 
                    467: mbk()
                    468: /* Keywords: commands:5 movement:50 deletion:50 character-at-a-time:20 word-oriented-commands:20 sentence-commands:20 backwards */
                    469: {
                    470:        if ((kcol--)>0) {
                    471:                klptr--;
                    472:                
                    473:                return(0);
                    474:        }
                    475:        if (kline>1) {
                    476:                --kline;
                    477:                kcol = leng(kline);
                    478:                klptr = mkline(kline) + kcol;
                    479:                return(0);
                    480:        }
                    481:        kcol = 0;
                    482:        return(1);
                    483: }
                    484: 
                    485:        /* forward to end of sentence */
                    486: 
                    487:        /* leaves resulting pointer in kline, kcol */
                    488: 
                    489: fsent () 
                    490: 
                    491: /* Keywords: commands:10 forwards movement:40 sentence-commands */
                    492: 
                    493: {
                    494:        kmark();
                    495: 
                    496:        while (mfk() == 0) {
                    497:                if ((bits[*klptr] & SENTE) && (bits[klptr[1]]&WHITE)) {
                    498:                        return(1);
                    499:                }
                    500:        }
                    501:        return(0);
                    502: }
                    503: 
                    504: /* back one sentence, leaves pointer in kline, kcol */
                    505: 
                    506: bsent()
                    507: 
                    508: /* Keywords: commands:10 backwards movement:40 sentence-commands */
                    509: 
                    510: {
                    511:        
                    512:        kmark();
                    513: 
                    514:        IGNORE(skipb(WRDSEP));
                    515:        while (mbk() == 0) {
                    516:                if (kcol == 0) {
                    517:                        if (kline>1) {
                    518:                                if (bits[*mkline(kline-1)] & SENTE) return(1);
                    519:                        }
                    520:                }
                    521:                if ((bits[*klptr] & SENTE) && (bits[klptr[1]] & WHITE)) {
                    522:                        IGNORE(skipf(WRDCHR));
                    523:                        IGNORE(skipf(WRDSEP));
                    524:                        return(1);
                    525:                }
                    526:        }
                    527:        return(0);
                    528: }
                    529: 
                    530: /* move back count sentences */
                    531: 
                    532: ssent(count)
                    533: register int count;
                    534: 
                    535: /* Keywords: commands backwards movement sentence-commands */
                    536: 
                    537: {
                    538:        while (count--) {
                    539:                if(bsent()) move(kline,kcol);
                    540:        }
                    541: }
                    542: 
                    543: /* move forward count sentences */
                    544: 
                    545: 
                    546: esent(count)
                    547: register int count;
                    548: 
                    549: /* Keywords: commands forwards movement sentence-commands */
                    550: 
                    551: {
                    552:        while (count--) {
                    553:                if (fsent() == 0) break;
                    554:                move(kline,kcol+1);
                    555:        }
                    556: }
                    557: 
                    558: 
                    559: /* move to top of file */
                    560: 
                    561: top()
                    562: /* Keywords: files:20 buffers:20 movement upward-movement commands */
                    563: {
                    564:        move(1,0);
                    565: }
                    566: 
                    567: 
                    568: /* move to end of file */
                    569: 
                    570: bot()
                    571: 
                    572: /* Keywords: files:20 buffers:20 movement downward-movement commands */
                    573: 
                    574: {
                    575:        mvc(nlines,10000);
                    576: }
                    577: 
                    578: /* new line handler */
                    579: 
                    580: /* First, finishes off comment on the current line (if any) */
                    581: 
                    582: /* Next, if the current buffer has a sub-process, the line is sent to the sub-process */
                    583: 
                    584: /* Then, if the next line is non-empty, it creates an empty next line */
                    585: /* next, the next line is tab adjusted (if in C mode ) */
                    586: 
                    587: /* now, any text on the current line beyond the current position, it is
                    588:  * moved to the end of the next line */
                    589: 
                    590: /* finally, the pointer is moved to the (tab adjusted) start of the next
                    591:  * line */
                    592: 
                    593: /* if count > 1, then count-1 blank lines will be inserted in between
                    594:  * the current line and the 'next' line */
                    595: 
                    596: nl(count)
                    597: 
                    598: /* Keywords: commands C-mode:30 insertion text-lines comments:50 shell-escape:10 */
                    599: 
                    600: 
                    601: 
                    602: register int count;
                    603: 
                    604: {
                    605: 
                    606:        if (RARE == 0) {
                    607:                if (comln == curln) putin(" */");
                    608: #ifndef PC
                    609:                if (curbf == procbuf){
                    610:                        MARK *mp;
                    611:                
                    612:                        mp = markptr(curbf);
                    613:                        if ((mp->markl == curln) && (mp->markc <= column)) {
                    614: 
                    615: /* If this is the last line on which output was done from */
                    616: /* the sub-process, then send from mark and re-mark */
                    617:                        
                    618:                                sendproc (clptr+mp->markc, column+1-mp->markc);
                    619:                                mp->markl = curln+1;
                    620:                                mp->markc = 0;
                    621:                        } else {
                    622:                                sendproc(clptr,column+1);
                    623:                        }
                    624:                }
                    625: #endif
                    626:        }
                    627:        comln = 0;
                    628:        if ((count != 1) || (NLINS) || (isblank(curln+1)==0) || (clptr[column] != EOL)) {
                    629:                openl(count);
                    630:        }
                    631:        if (TABMD&& (RARE == 0)) tabjust(curln+count);
                    632:        else move(curln+count,0);
                    633: }
                    634: 
                    635: /* sets mark at current position */
                    636: 
                    637: mark(mnumb)
                    638: 
                    639: /* Keywords: marking regions commands */
                    640: 
                    641: {
                    642:        MARK *markp;
                    643:        markp = markptr(mnumb);
                    644:        markp->markl = curln;
                    645:        markp->markc = column;
                    646: }
                    647: 
                    648: /* returns mark pointer */
                    649: 
                    650: MARK *markptr(mnumb)
                    651: 
                    652: register int  mnumb;
                    653: 
                    654: /* Keywords: commands:10 marking:50 regions deletion:50 movement:50 */
                    655: {
                    656:        
                    657:        if (mnumb >= NMARKS) {
                    658:                error(WARN,44);
                    659:                mnumb = curbf;
                    660:        }
                    661:        if ((mnumb == 1) && (numarg == 0)) mnumb = curbf;
                    662:        return(&marks[mnumb]);
                    663: }
                    664: 
                    665: 
                    666: /* kills text between current position and mark position */
                    667: 
                    668: 
                    669: mkill(mnumb)
                    670: int mnumb;
                    671: /* Keywords: commands deletion regions */
                    672: {
                    673:        register MARK *markp;
                    674:        
                    675:        markp = markptr(mnumb);
                    676:        kline = markp->markl;
                    677:        if (kline < 1) kline = 1;
                    678:        if (kline > nlines) kline = nlines;
                    679:        kcol = leng(kline);
                    680:        if (markp->markc < kcol) kcol = markp->markc;
                    681:        if (PICMODE) {
                    682:                                        /* This pain is to get the
                    683:                                         * mark to work  in picture
                    684:                                         * mode so that everything
                    685:                                         * up to and including the
                    686:                                         * marked position is killed */
                    687:                if (kcol > column) {
                    688:                        kcol++;
                    689:                } else {
                    690:                        forw(1);
                    691:                }
                    692:        }
                    693:        return(tkill());
                    694: }
                    695: 
                    696: /* retrieves text from the kill stack and inserts it (count times ) */
                    697: 
                    698: 
                    699: int yline;
                    700: int ycol;
                    701: 
                    702: yank(count)
                    703: 
                    704: /* Keywords: regions commands insertion killstack retrieval popping:10 */
                    705: 
                    706: register int count;
                    707: {
                    708:        register int result;
                    709:        register int unp;
                    710:        
                    711:        unp = unstart();
                    712:        mark(curbf);
                    713:        while (count--) {
                    714:                result = retrv();
                    715:        }
                    716:        unend(unp);
                    717:        yline = curln;
                    718:        ycol = column;                  /* Save, so we know when not to re-yank */
                    719: 
                    720:        return(result);
                    721: }
                    722: 
                    723: /* kills the marked region, removes the top item from the kill stack,
                    724:  * and then inserts the next area from the kill stack */
                    725: 
                    726: 
                    727: reyank(count)          /* yank again */
                    728: register int count;
                    729: /* Keywords: regions commands insertion killstack retrieval deletion popping:10 */
                    730: {
                    731:        register int unp;
                    732: 
                    733:        if ((curln != yline) || (column != ycol)) {
                    734:                error (WARN,84);        /* Prevent some nastyness */
                    735:                return;
                    736:        } 
                    737:        kbapp = 0;
                    738:        unp = unstart();
                    739:        mkill(curbf);   /* flush last insertion */
                    740:        kpop();         /* first pop the mkill */
                    741:        kpop();         /* now pop that last insertion */
                    742:        yank(count);
                    743:        unend(unp);
                    744: }
                    745: 
                    746: /* search subroutine */
                    747: 
                    748: /* searches forward or backward for a string, starting at the 
                    749:  * given position.  If the string is found, 1 is returned, and the start
                    750:  * of the match is left in kline, kcol.  Return of 0 indicates no match */
                    751: 
                    752: /* Keywords: searching */
                    753: 
                    754: srch(sline,scol,sp,direct)
                    755: 
                    756: int sline;
                    757: int scol;
                    758: char *sp;
                    759: int direct;
                    760: 
                    761: {
                    762:        register char *lp;
                    763:        register char *cp;
                    764:        register int l;
                    765:        int c;
                    766:        
                    767:        lp = sp;
                    768:        while (c = *lp) *lp++ = casem[c&0177]; /* map string to allowed case */
                    769:        lp = mkline(sline)+scol;
                    770:        while (1) {
                    771:                cp = sp;
                    772:                l = sline;
                    773:                while (*cp) {
                    774:                        if ((c = casem[(*lp++)&0177]) != *cp++) goto again;
                    775:                        if (c == EOL) {
                    776:                                if (l == nlines) {
                    777:                                        if (direct>0) return(0);
                    778:                                        goto again;
                    779:                                }
                    780:                                ++l;
                    781:                                lp = mkline(l);
                    782:                        }
                    783:                }
                    784:                kline = sline;
                    785:                kcol = scol;
                    786:                return(1);
                    787: 
                    788: again:         if (brkflg) brkit();
                    789:                lp = mkline(sline)+scol;
                    790:                if (direct>0) {
                    791:                        do {                    
                    792:                                if (*lp++ !=EOL) scol++;
                    793:                                else {
                    794:                                        if (sline == nlines) return(0);
                    795:                                        sline++;
                    796:                                        scol = 0;
                    797:                                        lp = mkline(sline);
                    798:                                }
                    799:                        } while (casem[*lp&0177] != *sp);
                    800:                } else {
                    801: 
                    802:                        do {
                    803:                                if (--scol<0) {
                    804:                                        if (sline == 1) return(0);
                    805:                                        scol = leng(--sline);
                    806:                                        lp = mkline(sline)+scol;
                    807:                                } else lp--;
                    808:                        } while (casem[*lp&0177] != *sp);
                    809:                }
                    810:        }
                    811: }
                    812: 
                    813: fisrch(arg)
                    814: int arg;
                    815: /* Keywords: searching commands forwards key-bindings:10 */
                    816: {
                    817:        return(isrch(1,arg));
                    818: }
                    819: risrch(arg)
                    820: int arg;
                    821: /* Keywords: searching commands backwards key-bindings:10 */
                    822: 
                    823: {
                    824:        return(isrch(-1,arg));
                    825: }
                    826: /* incremental search command (either direction) */
                    827: 
                    828: 
                    829: isrch(d,arg)
                    830: int d;
                    831: int arg;
                    832: 
                    833: /* Keywords: commands:80 searching user-interface:60 key-bindings:50 */
                    834: 
                    835: 
                    836: {
                    837:        int oldln;
                    838:        int oldcol;
                    839:        register char *ilp;
                    840:        register int c;
                    841:        int lx;
                    842:        int ly;
                    843:        int nd;
                    844:        int missed;
                    845:        char sst[40];
                    846:        char *xp;
                    847: 
                    848:        ilp = sst;
                    849:        missed = 0;
                    850:        lx = oldln = curln;
                    851:        ly = oldcol = column;
                    852:        if (infrn < 0) {                        /* if in a macro */
                    853:                xp = getname(NULL);             /* search argument */
                    854:                ilp = mstrcpy(ilp,xp);
                    855:        }
                    856:        while (1) {
                    857:                *ilp = 0;
                    858:                if (missed == 0) {
                    859:                        psrch(d,sst);           /* prompt */
                    860:                        if (infrn == 0) mflush(stdout);
                    861:                        if (srch(curln,column,sst,d) == NULL) {
                    862:                                move(lx,ly);
                    863:                                if (infrn >= 0) {
                    864:                                        beep();
                    865:                                        prompt1("Failing Search: %s", sst);
                    866:                                }
                    867:                                missed = 1;
                    868:                        } else {
                    869:                                move(lx = kline,ly = kcol);
                    870:                                if (ilp!=sst)strcpy (presst,sst);
                    871:                                missed = 0;
                    872:                        }
                    873:                }
                    874:                if (infrn < 0) return(missed == 0); /* macro invocation */
                    875:                disup();
                    876:                if ((missed == 0) && (incnt == 0)) {
                    877:                        psrch(d,sst); /* restore prompt */
                    878:                        mgo(nln,ncol); /* goback to display position */
                    879:                }
                    880:                c = getchar();
                    881:                if ((c == CTRLH)||(c == RUBOUT)) {
                    882:                        if (ilp!=sst) ilp--;
                    883:                        missed=0;
                    884:                        move (oldln,oldcol);
                    885:                        continue;       /* next loop */
                    886:                } 
                    887:                if (c == CTRLG) {
                    888:                        move (oldln,oldcol);
                    889:                        unprompt();
                    890:                        beep();
                    891:                        return(0);
                    892:                }
                    893:                if (srch_nl?((c == '\n') || (c == '\r')) : (c == ESC)) {
                    894: goout:                 unprompt();
                    895:                        return(missed == 0);
                    896:                }
                    897:                if (nd=issrch(c)) {
                    898:                        if (nd == d) {
                    899:                                if (ilp == sst) {
                    900:                                        ilp = mstrcpy(sst,presst);
                    901:                                        continue;
                    902:                                } else {
                    903:                                        if (missed) {
                    904:                                                beep();
                    905:                                                continue;
                    906:                                        }
                    907:                                        forw(d);
                    908:                                }
                    909:                        } else {
                    910:                                missed=0;
                    911:                                d = nd;
                    912:                        }
                    913:                        continue;
                    914:                }
                    915:                if (isquote(c)) {
                    916:                        c = getchar(); /* skip all other processing */
                    917:                } else {
                    918:                        if (c == CTRLM) c = '\n';
                    919:                        if ((c < 040) && (c != '\n')) {
                    920:                                ungetch(c);
                    921:                                goto goout;
                    922:                        } 
                    923:                }
                    924:                if (missed) {
                    925:                        beep();
                    926:                        continue;
                    927:                }
                    928:                *ilp++ = c;
                    929:        }
                    930: }
                    931: 
                    932: /* psrch -- print search prompt */
                    933: 
                    934: psrch(dir,sstp)
                    935: register int dir;
                    936: char *sstp;
                    937: 
                    938: /* Keywords: mode-line prompting searching */
                    939: 
                    940: {
                    941:        if (dir>0) prompt1("Search: %s",sstp);
                    942:        else prompt1("Reverse Search: %s",sstp);
                    943: }
                    944: 
                    945: /* handle a separator character in auto fill mode */
                    946: 
                    947: /* if fill mode is on, and the current position is beyond FILLCOL, a
                    948:  * newline is inserted before the last word.  Otherwise, just insert the
                    949:  * character at the current position */
                    950: 
                    951: 
                    952: afsep(count,chr)
                    953: 
                    954: int count;
                    955: int chr;
                    956: 
                    957: /* Keywords: commands:40 modes:30 text-filling comments:20 C-mode:10 */
                    958: 
                    959: {
                    960:        register int cc;
                    961:        int newcol;
                    962:        int oldcol;
                    963:        char lbuf[MAXEL];               /* KLUDGE! */
                    964:        register char *p1;
                    965:        register char *p2;
                    966:        
                    967: /* whitespace characters in a macro expansion must be quoted to be
                    968:  * self-inserting.  The following checks for non-zero character
                    969:  * count, input from macro, and a whitespace character to be
                    970:  * inserted.  Under these conditions, no inserting is done. */
                    971:        
                    972:        if (count && (infrn < 0)&& (WHITE&bits[chr])) return(1);
                    973: 
                    974: 
                    975:        
                    976:        if (FILLMD && (RARE == 0)) {
                    977:                insertc(count,chr);
                    978:                oldcol = column;
                    979:                cc = leng(curln) - column;
                    980:                mline=0;
                    981:                findpos(clptr,column);
                    982:                if (mline || (mcol>FILLCOL)|| (column > FILLCOL)) {
                    983: 
                    984: again:                 newcol = column;
                    985:                        
                    986:                        do {
                    987:                                column--;
                    988:                        } while ((column) &&
                    989:                                (((bits[clptr[column]] & WHITE) == 0) ||
                    990:                                (clptr[column+1] == '.') ||
                    991:                                (clptr[column+1] == '\'')));
                    992:                        mline=0;
                    993:                        findpos(clptr,column);
                    994:                        if (mline || (mcol>FILLCOL)|| (column > FILLCOL)) goto again;
                    995: 
                    996: 
                    997: 
                    998: /* Now then, do the work.  We are sitting at the right column to break the line */
                    999: /* First, save the rest of the line.  Then, kill it, then, do a newline,  */
                   1000: /* now, bring it back */
                   1001:                        
                   1002:                        
                   1003:                        if (column == 0) column = newcol; /* 1 word line */
                   1004:                        if (column == oldcol) return(1); /* Do absolutely nothing */
                   1005:                        p1 = clptr+column+1; /* Eat the whitespace character */
                   1006:                        
                   1007:                        p2 = lbuf;
                   1008:                        while ((*p2++= *p1++)!=EOL); /* copy line */
                   1009:                        sputl(curln,column,curln); /* Flag line is bad! */
                   1010:                        clptr[column]=EOL; /* truncate line */
                   1011:                        if (comln == curln) {
                   1012:                                comln = -1;
                   1013:                                nl(1);
                   1014:                                cment(1);
                   1015:                                *(clptr+column-3)=' ';
                   1016:                        } else nl(1);
                   1017:                        p1 = lbuf;
                   1018:                        while (*p1 != EOL) put(*p1++); /* restore line */
                   1019:                        forw(-cc);   /* go back to right place. */
                   1020:                }
                   1021:                return(1);
                   1022:        }
                   1023:        insertc(count,chr);
                   1024:        return(1);
                   1025: }
                   1026: 
                   1027: /* unix escape */
                   1028: 
                   1029: char *shell = "sh";                    /* name of shell processor */
                   1030: 
                   1031: ux(arg)
                   1032: 
                   1033: int arg;
                   1034: {
                   1035: /* Keywords: commands buffers:20 unix-interface shell-escape */
                   1036: 
                   1037:        register char *sp;              
                   1038: 
                   1039:        if (SAVEMD) fsave(0);
                   1040:        do {
                   1041:                sp = (getname("command line? "));
                   1042:        } while (sp &&  (unx(sp,(arg != 1))== 0));
                   1043:        return(cstatus);
                   1044: }
                   1045: 
                   1046: #ifndef PC
                   1047: 
                   1048: char *
                   1049: nvmatch(s1, s2)
                   1050: register char *s1, *s2;
                   1051: 
                   1052: /* Keywords: unix-interface shell-escape environment-variables */
                   1053: {
                   1054:        while(*s1 == *s2++)
                   1055:                if(*s1++ == '=')
                   1056:                        return(s2);
                   1057:        if(*s1 == '\0' && *(s2-1) == '=')
                   1058:                return(s2);
                   1059:        return(NULL);
                   1060: }
                   1061: 
                   1062: /* Environment fixer-upper, adds definition of filename to the
                   1063:  * environment and returns a pointer to it. */
                   1064: 
                   1065: extern char **environ;
                   1066: 
                   1067: char **
                   1068: fixenv(defp)
                   1069: register char *defp;
                   1070: /* Keywords: unix-interface shell-escape environment-variables */
                   1071: 
                   1072: {
                   1073:        register char **xp;
                   1074:        register char **yp;
                   1075:        int envd = 0;
                   1076:        
                   1077:        xp =((char **)  &bbuf[0][0]);           /* Overlay screen */
                   1078:        yp = environ;
                   1079:        
                   1080:        while (*xp = *yp++) {
                   1081:                if (nvmatch(defp,*xp++)) {
                   1082:                        xp[-1] = defp;
                   1083:                        envd=1;
                   1084:                }
                   1085:        }
                   1086:        if (envd==0) {
                   1087:                *xp++ = defp;
                   1088:                *xp = NULL;
                   1089:        }
                   1090:        xp =((char **)  &bbuf[0][0]);           /* Overlay screen */
                   1091:        return(xp);
                   1092: }
                   1093: #endif
                   1094: 
                   1095: 
                   1096: /* general unix escape --  */
                   1097: 
                   1098: /* flag = 0 means just run it */
                   1099: /* flag = 1 means run and feed it the buffer */
                   1100: /* flag = 2 means run and replace .exec with the result */
                   1101: /* flag = 3 means run and append result to .exec */
                   1102: /* flag = 4 means run and bring results back in fnbuf */
                   1103: /* flag = 5 means run and hook up input and output pipes */
                   1104: /* flag = 6 means run it and hook up output to splfile, leave input in splfile */
                   1105: /* flag = 7 means run it and hook up input from splfile, leave output in splfile */
                   1106: 
                   1107: #define UNEEDSIN 1
                   1108: #define UNEEDSOUT 2
                   1109: #define UDOTEXEC 4
                   1110: #define UNOSCREEN 8
                   1111: #define URETBUF 16
                   1112: #define UPROCESS 32
                   1113: #define USENDBUF 64
                   1114: #define UREADBUF 128
                   1115: #define UINITBUF 256
                   1116: #define USPLIN 512
                   1117: #define USPLOUT 1024
                   1118: 
                   1119: int unxflags[8] = {
                   1120:        0,
                   1121:        UNEEDSIN+USENDBUF,
                   1122:        UNEEDSOUT+UDOTEXEC+UREADBUF+UINITBUF,
                   1123:        UNEEDSOUT+UDOTEXEC+UREADBUF,
                   1124:        UNEEDSOUT+UNOSCREEN+URETBUF,
                   1125:        UNEEDSIN+UNEEDSOUT+UNOSCREEN+UPROCESS,
                   1126:        UNEEDSIN+USPLOUT+UNOSCREEN,
                   1127:        UNEEDSOUT+USPLIN+UNOSCREEN
                   1128: };
                   1129: 
                   1130: 
                   1131: unx(cmd,flag)
                   1132: /* Keywords: commands:80 buffers:10 files:10 environment-variables:20 unix-interface shell-escape dired:10 sub-processes:40 encryption:20 */
                   1133: register char *cmd;
                   1134: register int flag;
                   1135: 
                   1136: {
                   1137: #ifdef PC
                   1138:        return(1);                      /* Don't do this, just exit */
                   1139: #else
                   1140:        struct pipes {
                   1141:                int rdpipe;
                   1142:                int wrpipe;
                   1143:        } piped1,piped2;
                   1144:        FILE tinbuf[1];
                   1145:        FILE *infile;
                   1146:        int (*istat)();
                   1147:        int (*qstat)();
                   1148:        register int i;
                   1149:        int c;
                   1150:        int obuf;
                   1151:        int pid;
                   1152:        char **evp;
                   1153:        char *obname;
                   1154:        char evbuf[256];
                   1155:        char *myshell;
                   1156:        
                   1157:        if (*cmd == 0) return(1);       /* Don't even bother with null commands */
                   1158:        obname=fname();
                   1159:        cstatus  = -1;                  /* start off bad */
                   1160:        flag = unxflags[flag];          /* Translate to bit-coded value */
                   1161:        
                   1162:        if ((flag & UPROCESS) && procpid) flushproc(); /* Zap old process */
                   1163: 
                   1164:        if (flag&UDOTEXEC) {            /* if .exec in the business */
                   1165:                obuf = curbf;           
                   1166:                if (chgbuf(".exec") == 0) return(0);
                   1167:        }
                   1168: 
                   1169:        if ((USILENT == 0) && ((flag&UNOSCREEN) == 0)) {
                   1170:                clear();
                   1171:                putout("%s",cmd);
                   1172:                istat = signal(SIGINT, SIG_IGN);
                   1173:                qstat = signal(SIGQUIT, SIG_IGN);
                   1174:                cook();
                   1175:        }
                   1176:        if (flag & UNEEDSIN) {
                   1177:                if (pipe(&piped1)) {
                   1178:                        error (WARN,errno,cmd);
                   1179:                        goto done;
                   1180:                }
                   1181:        }
                   1182:        
                   1183:        if (flag & UNEEDSOUT) {
                   1184:                if (pipe (&piped2)) {
                   1185:                        error (WARN,errno,cmd);
                   1186:                        if (flag & UNEEDSIN) {
                   1187:                                close(piped1.rdpipe);
                   1188:                                close(piped1.wrpipe);
                   1189:                        }
                   1190:                        goto done;
                   1191:                }
                   1192:        }
                   1193:        if ((pid = fork()) == 0) {      /* child process */
                   1194:                
                   1195:                if (flag &UNEEDSIN) {
                   1196:                        close(0);
                   1197:                        dup(piped1.rdpipe);
                   1198:                } else if (flag & USPLIN) {
                   1199:                        close(0);
                   1200:                        dup(splfile);
                   1201:                } else if ((USILENT)|| (flag & URETBUF)) {
                   1202:                        close(0);
                   1203:                        open("/dev/null",0);
                   1204:                }
                   1205:                if (flag &UNEEDSOUT) {  /* if writing to .exec */
                   1206:                        close(1);
                   1207:                        dup(piped2.wrpipe);
                   1208:                } else if (flag & USPLOUT) {
                   1209:                        close(1);
                   1210:                        dup(splfile);
                   1211: 
                   1212:                } else if (USILENT) { /* silent, throw away output */
                   1213:                        close(1);
                   1214:                        open("/dev/null",2);
                   1215:                }
                   1216:                signal(SIGINT, SIG_DFL);
                   1217:                signal(SIGQUIT,SIG_DFL);
                   1218:                xclose(2);      /* close all irrelavent files */
                   1219:                dup(1);         /* restore stderr */
                   1220: 
                   1221:                myshell = getenv("SHELL");
                   1222:                if ((myshell == NULL)|| (*myshell == '\0')) myshell = "/bin/sh";
                   1223:                umask(mymask);          /* Restore user's umask */
                   1224:                seprintf(evbuf,"filename=%s",obname);
                   1225:                evp = fixenv(evbuf);            /* Add filename definition */
                   1226:                
                   1227:                if (streq(cmd,shell)) execl(myshell,shell,"-i",0,evp);
                   1228:                execle(myshell, shell, "-c", cmd, 0,evp);
                   1229:                execle("/bin/sh",shell, "-c", cmd, 0,evp);
                   1230:                _exit(127);
                   1231:        }
                   1232: 
                   1233: /* parent process (the one that remains EMACS) */
                   1234:        
                   1235:        if (pid== -1)  {
                   1236:                error(WARN,73,cmd);
                   1237:                goto done;
                   1238:        }
                   1239:        if (flag &UPROCESS) {
                   1240:                close (piped1.rdpipe);
                   1241:                close (piped2.wrpipe);
                   1242:                inproc = piped2.rdpipe;
                   1243:                outproc = piped1.wrpipe;
                   1244: #ifdef ux3
                   1245:                fcntl(inproc,F_SETFL,O_NDELAY); /* Turn on non-blocking I/O */
                   1246:                ioset(1);               /* Set timeout on terminal short */
                   1247: #endif
                   1248:                procbuf = curbf;
                   1249:                procpid = pid;
                   1250:                return(1);
                   1251:        }
                   1252:        if (flag & USPLIN) {
                   1253:                close(splfile);
                   1254:                splfile = piped2.rdpipe;
                   1255:                close(piped2.wrpipe);
                   1256:                return(1);
                   1257:        }
                   1258:        if (flag & USPLOUT) {
                   1259:                close(splfile);
                   1260:                splfile = piped1.wrpipe;
                   1261:                close(piped1.rdpipe);
                   1262:                return(1);
                   1263:        }
                   1264:        if (flag&USENDBUF) {            /* if sending the buffer */
                   1265:                close(piped1.rdpipe);
                   1266:                infile = fdopen(tinbuf,piped1.wrpipe,"w");
                   1267:                for (i = 1; i <=nlines; i++) {
                   1268:                        cmd = mkline(i);
                   1269:                        while ((c = *cmd++) != EOL) {
                   1270:                                putc(c,infile);
                   1271:                        }
                   1272:                        if (i != nlines) putc(EOL,infile);
                   1273:                }
                   1274:                mclose(infile);
                   1275:        }
                   1276:        if (flag&(UREADBUF|URETBUF)) {          /* if writing */
                   1277:                close(piped2.wrpipe);
                   1278:                infile = fdopen(tinbuf,piped2.rdpipe,"r");
                   1279:                if (flag&UINITBUF) bufinit();
                   1280:                else if (flag&UREADBUF) {
                   1281:                        bot();  /* append */
                   1282:                        if (column != 0) nl(1);
                   1283:                        putin(cmd);
                   1284:                        nl(2);
                   1285:                }
                   1286:                if (flag&URETBUF) {
                   1287:                        cmd = fnbuf;
                   1288:                        i = 127;
                   1289:                        while (i--) {
                   1290:                                c = getc(infile);
                   1291:                                if ((c=='\0')||(c == '\n')||(c==' ')||(c=='\t')|| (c == EOF)) break;
                   1292:                                *cmd++ = c;
                   1293:                        }
                   1294:                        *cmd = 0;       /* EOS */
                   1295:                        mclose(infile);
                   1296:                } else {
                   1297:                        i = ((flag & UINITBUF) != 0);
                   1298:                        readsub(infile,i,cmd,1-(USILENT|NOECHO));
                   1299:                        chbuf(obuf);
                   1300:                }
                   1301:        }
                   1302:                /*  wait for child to finish */
                   1303: 
                   1304:        /* must wait for child else it becomes a <defunct> process */
                   1305: 
                   1306:        while ((i = wait(&cstatus)) != pid && i != -1);         
                   1307: 
                   1308:        if (flag&URETBUF) return(cstatus);
                   1309:        /* child is now done, go back to normal EMACS */
                   1310:        mailcnt = 0;
                   1311:        
                   1312: done:  if ((USILENT == 0) && ((flag&UNOSCREEN) == 0)) {
                   1313:                uncook();
                   1314:                signal(SIGINT, istat);
                   1315:                signal(SIGQUIT, qstat);
                   1316:                junked++;
                   1317:        }
                   1318:        return(contin());
                   1319: #endif 
                   1320: }
                   1321: 
                   1322: bux(arg)
                   1323: 
                   1324: int arg;
                   1325: 
                   1326: /* Keywords: commands buffers unix-interface shell-escape */
                   1327: 
                   1328: {
                   1329:        register char *sp;
                   1330:        register int flag;
                   1331:        if (SAVEMD) fsave(0);
                   1332:                if (arg == 0) flag = 5;
                   1333:        else if (arg == 1) flag = 2;
                   1334:        else flag = 3;
                   1335:        
                   1336:        do {
                   1337:                sp = (getname("command line? "));
                   1338:        } while (sp &&  (unx(sp,flag)== 0));
                   1339:        return(cstatus);
                   1340: }
                   1341: 
                   1342: /* query replace */
                   1343: /* prompts for strings and does conditional replacement */
                   1344: 
                   1345: qrep(gflag)
                   1346: int gflag;
                   1347: /* Keywords: commands query-replace */
                   1348: {
                   1349:        iqrep(0,gflag);                 /* no regular expressions */
                   1350: }
                   1351: 
                   1352: rqrep(gflag)
                   1353: int gflag;
                   1354: /* Keywords: commands query-replace regular-expressions */
                   1355: {
                   1356:        iqrep(1,gflag);                 /* regular expression version */
                   1357: }
                   1358: 
                   1359: 
                   1360: iqrep(regular,gflag)
                   1361: 
                   1362: int regular;
                   1363: int gflag;
                   1364: 
                   1365: /* Keywords: query-replace regular-expressions:20 user-interface key-bindings:20 commands:10 */
                   1366: 
                   1367: 
                   1368: {
                   1369: 
                   1370:        char sstring[128];
                   1371:        int dir = 1;
                   1372:        register char *sp;
                   1373:        int bsflag = 0;
                   1374:        int ask = 1;
                   1375:        int show = 1;
                   1376:        int l = 1;
                   1377:        int stop = 0;
                   1378:        int upt;
                   1379:        register int c;
                   1380:        int oldln;
                   1381:        int oldcol;
                   1382:        
                   1383:        if((sp = getname("From? "))== NULL) return;
                   1384:        if (*sp == NULL) sp = presst;
                   1385:        strcpy(sstring,sp);
                   1386:        if ((sp = getname("To? ")) == NULL) return;
                   1387:        if (!streq(sp,"%")) strcpy(rstring,sp); /* Copy over return string unless it is a single % */
                   1388:        oldln = curln;
                   1389:        oldcol = column;
                   1390:        upt = unstart();
                   1391:        while (1) {
                   1392:                if (regular) { 
                   1393:                        if (rgsrch(curln,column,sstring,0,dir)== 0) break;
                   1394:                } else {
                   1395:                        if (srch(curln,column,sstring,dir)== 0) break;
                   1396:                }
                   1397:                dir = 1;
                   1398:                if ((l == 0) && (curln == kline) && (column == kcol)) {
                   1399:                        error(WARN,72,sstring,rstring);
                   1400:                        goto rdone;
                   1401:                }
                   1402:                
                   1403:                prompt1("From %s To %s",sstring,rstring);
                   1404:                strcpy(presst,sstring); /* save successful search */
                   1405:                move(kline,kcol);
                   1406:                if (show) {
                   1407:                        disup();
                   1408:                }
                   1409:                if (ask){
                   1410:                        c = getchar();
                   1411:                        donttime=0;
                   1412:                } else c = 'y';
                   1413:                switch(c) {
                   1414: 
                   1415: case '.':      stop = 1;               /* stop after this one */
                   1416:                goto rep_it;            /* make this replacement. */
                   1417: case ESC:      sp = getname("Replace with: ");
                   1418:                if (sp) {
                   1419:                        strcpy(rstring,sp);
                   1420:                        goto rep_it;
                   1421:                }
                   1422: case CTRLG:    beep();
                   1423: done:          unprompt();             /* wipe out help message */
                   1424:                unend(upt);
                   1425:                return;
                   1426: 
                   1427: case '<':              
                   1428:                move (oldln,oldcol);    /* return to last replacement */
                   1429:                goto done;
                   1430: 
                   1431: 
                   1432: case 'R':      show = 0;
                   1433: case 'r':      ask = 0;                /* do rest */
                   1434:                NOBEL++;                /* Inhibit ding on zero length deletes */
                   1435:                /* fall through to do this one too */
                   1436: case ' ':
                   1437: case 'y':
                   1438: case 'Y':
                   1439: rep_it:                kbapp = 0;
                   1440:                oldln = curln;
                   1441:                oldcol = column;
                   1442:                if (regular) {
                   1443:                        l = (loc2-column);
                   1444:                } else {
                   1445:                        l = (lng(sstring));
                   1446:                }
                   1447:                fdel(l);
                   1448:                for (sp = rstring; *sp; sp++) {
                   1449:                        switch(*sp) {                   
                   1450:                        case '\\':
                   1451:                                if (!bsflag) {
                   1452:                                        bsflag = 1;
                   1453:                                        continue;
                   1454:                                }
                   1455:                        case '1':
                   1456:                        case '2':
                   1457:                        case '3':
                   1458:                        case '4':
                   1459:                        case '5':
                   1460:                        case '6':
                   1461:                        case '7':
                   1462:                        case '8':
                   1463:                                if (bsflag && regular && regrep(*sp-'1')) {
                   1464:                                        bsflag = 0;
                   1465:                                        continue; /* \number style replace */
                   1466:                                }
                   1467: /* fall through to default treatment of numbers        */
                   1468: 
                   1469:                        default:
                   1470:                                dput(*sp);
                   1471:                                bsflag = 0;
                   1472:                                break;
                   1473:                        case '&':
                   1474:                                if (bsflag) {
                   1475:                                        dput(*sp);
                   1476:                                        bsflag = 0;
                   1477:                                        continue;
                   1478:                                } else {
                   1479:                                        yank(1);
                   1480:                                        unpop(1);
                   1481:                                }
                   1482:                        }
                   1483:                }
                   1484:                unins(oldln,oldcol); /* Make an undo entry */
                   1485:                kpop();                 /* clean up our stack */
                   1486:                if (stop) goto done;
                   1487:                if (show) {
                   1488:                        disup();        /* before next search */
                   1489:                        mflush(stdout);
                   1490:                }
                   1491:                break;
                   1492: case CTRLH:
                   1493: case RUBOUT:
                   1494: case 'n':
                   1495: case 'N':
                   1496:                forw(1);
                   1497:                break;
                   1498: case 'p':
                   1499: case 'b':      
                   1500:                dir = -1;
                   1501:                forw(-1);
                   1502:                break;
                   1503:        default:
                   1504:                beep();
                   1505: case '?':
                   1506:                donttime=1;             /* Avoid time mode */
                   1507:                prompt3("Query replace -- 'y' to replace, 'n' to skip, ^G to quit,'R' or 'r' for rest");
                   1508: 
                   1509:        }
                   1510:        if (gflag>1) move(kline+1,0);   /* only do first one */
                   1511:        }
                   1512: rdone: prompt1("Replace Done");
                   1513:        if (ask==0) NOBEL--;            /* Re-enable warning on 0 length deletes */
                   1514:        unend(upt);
                   1515: }
                   1516: /* length of a string */
                   1517: 
                   1518: lng(sp)
                   1519: 
                   1520: char *sp;
                   1521: /* Keywords: string-handling length */
                   1522: {
                   1523:        register char *spo;
                   1524: 
                   1525:        spo = sp;
                   1526:        while(*spo++);
                   1527:        return(spo-sp-1);
                   1528: }
                   1529: 
                   1530: /* capitalize next count characters */
                   1531: 
                   1532: capnxt(count)
                   1533: 
                   1534: register int count;
                   1535: 
                   1536: /* Keywords: commands character-at-a-time forwards capitalization */
                   1537: {
                   1538:        register int c;
                   1539:        int oldover;
                   1540:        while (count--) {
                   1541:                c = (clptr[column]);
                   1542:                if ((c >= 'a') && (c <= 'z')) {
                   1543:                        oldover=OVERW;
                   1544:                        OVERW=1;
                   1545:                        insertc(1,c-040);
                   1546:                        OVERW=oldover;
                   1547:                } else if (forw(1)==0) break; /* check for EOF */
                   1548:        }
                   1549: }
                   1550: 
                   1551: 
                   1552: /* lowercase  next count characters */
                   1553: 
                   1554: lownxt(count)
                   1555: 
                   1556: register int count;
                   1557: 
                   1558: /* Keywords: commands character-at-a-time forwards capitalization */
                   1559: {
                   1560:        register int c;
                   1561:        int oldover;
                   1562:        while (count--) {
                   1563:                c = (clptr[column]);
                   1564:                if ((c >= 'A') && (c <= 'Z')) {
                   1565:                        oldover=OVERW;
                   1566:                        OVERW=1;
                   1567:                        insertc(1,c+040);
                   1568:                        OVERW=oldover;
                   1569:                } else if (forw(1)==0) break; /* check for EOF */
                   1570:        }
                   1571: }
                   1572: 
                   1573: /* capitalize first character of the next word */
                   1574: 
                   1575: capwrd(count)
                   1576: 
                   1577: register int count;
                   1578: 
                   1579: /* Keywords: commands word-oriented-commands forwards capitalization */
                   1580: {
                   1581:        while (count--) {
                   1582:                kmark();
                   1583:                IGNORE(skipf(WRDSEP));
                   1584:                move(kline,kcol);       /* to next word */
                   1585:                capnxt(1);
                   1586:                mfwrd(1);
                   1587:        }
                   1588: }
                   1589: 
                   1590: /* exchange current position and the marked position */
                   1591: 
                   1592: exch(mnumb)
                   1593: 
                   1594: /* Keywords: commands regions marking movement */
                   1595: {
                   1596:        register int x;
                   1597:        register int y;
                   1598:        register MARK *markp;
                   1599:        
                   1600:        markp = markptr(mnumb);
                   1601:        x = markp->markl;
                   1602:        if (x < 1) x = 1;
                   1603:        y = markp->markc;
                   1604:        if ((x == curln) && (y == column)) {
                   1605:                return(0);
                   1606:        }
                   1607:        if (x > nlines) x = nlines;
                   1608:        mark(mnumb);
                   1609:        mvc(x,y);
                   1610:        return(1);
                   1611: }
                   1612: 
                   1613: /* exchange next two chacters in the buffer and move forward one */
                   1614: 
                   1615: xpose(count)
                   1616: 
                   1617: register int count;
                   1618: 
                   1619: /* Keywords: commands forwards movement:10 transposition */
                   1620: {
                   1621:        int oldnodel,oldpic;
                   1622: 
                   1623:        register int undp;
                   1624:        
                   1625:        oldnodel=NODEL;
                   1626:        oldpic=PICMODE;
                   1627:        NODEL=0;
                   1628:        PICMODE=0;
                   1629:        kbapp = 0;
                   1630:        undp = unstart();
                   1631:        fdel(1);
                   1632:        forw(count);
                   1633:        yank(1);
                   1634:        unend(undp);
                   1635:        kpop();
                   1636:        forw(-1);
                   1637:        NODEL=oldnodel;
                   1638:        PICMODE=oldpic;
                   1639: }
                   1640: 
                   1641: /* changes a mode parameter.  Mode parameters are of three types,
                   1642:  * string, boolean, or integer.
                   1643: 
                   1644:  * Integer modes set from the count argument, boolean modes turn on if
                   1645:  * count is one, off otherwise, and string modes prompt for new value
                   1646: 
                   1647:  * chmode returns the previous value of the mode set */
                   1648: 
                   1649: 
                   1650: chmode(count)
                   1651: register int count;
                   1652: 
                   1653: /* Keywords: modes commands assignment */
                   1654: {
                   1655:        register char *mp;
                   1656:        
                   1657:        if ((mp=getname("Mode? ")) != NULL) {
                   1658:                if (*mp == '\0') {
                   1659:                        modisp(numarg);
                   1660:                        return(0);
                   1661:                }
                   1662:                return(setmode(mp,count,1));
                   1663:        }
                   1664:        return(0);
                   1665: }
                   1666: 
                   1667: char *MDHEAD = "EMACS_MODES:";
                   1668: 
                   1669: bfmodes()                              /* set modes from buffer */
                   1670: /* Keywords: modes buffers file-modes assignment:10 */
                   1671: {
                   1672:        register char *cp;
                   1673:        register char *cp1;
                   1674:        char mdbuf[20];
                   1675:        int onoff;
                   1676:        
                   1677:        kline = 11;
                   1678:        if (kline > nlines) kline = nlines;
                   1679:        while ((kline > 0) && srch(kline,leng(kline),MDHEAD,-1)) {
                   1680:                         /* if modes set */
                   1681: 
                   1682:                for (cp = mkline(kline)+kcol+12; *cp != EOL;) {
                   1683:                        cp1 = mdbuf;
                   1684:                        while ((*cp != EOL) && (*cp != '!') && ((bits[*cp] & WRDCHR) == 0)) cp++;
                   1685:                        if (*cp == '!') {
                   1686:                                onoff = 0; 
                   1687:                                cp++;
                   1688:                        } else onoff = 1;
                   1689:                        
                   1690:                        while (bits[*cp] & WRDCHR) {
                   1691:                                *cp1++ = *cp++;
                   1692:                        }
                   1693:                        if (*cp == '=') {
                   1694:                                cp++;
                   1695:                                cp = nscan(cp,&onoff);
                   1696:                        }
                   1697:                        
                   1698:                        *cp1 = 0;
                   1699:                        if (mdbuf[0]) setmode(mdbuf,onoff,0); /* Set up mode */
                   1700:                }
                   1701:                kline--;
                   1702:        }
                   1703: }
                   1704:                        
                   1705: 
                   1706: setmode(mp,count,fudge)
                   1707: register char *mp;
                   1708: int count;
                   1709: int fudge;
                   1710: /* Keywords: modes macro-programming:10 assignment time-handling:20 display-format:10 */
                   1711: {
                   1712:        register int i;
                   1713:        extern char cbuf[];
                   1714:        int retval;
                   1715:        int mfield;
                   1716:        
                   1717:        for (i = 0; i < NMODES; i++) {
                   1718:                if (streq(mdata[i].modename,mp)) {
                   1719:                        retval = *mdata[i].modeloc; /* old value */
                   1720:                        switch(mdata[i].modetype) {
                   1721:                        case ONOFF:
                   1722:                                if (fudge && (count != 1)) count = 0;
                   1723:                                *mdata[i].modeloc = count;
                   1724:                                break;
                   1725:                        case INT:
                   1726:                                *mdata[i].modeloc = count;
                   1727:                                break;
                   1728:                        }
                   1729:                        if ((mfield = mdata[i].moderset)&DSIZE) {
                   1730:                                SCRNLIN = SCRLINES+4;
                   1731:                                setsize();
                   1732:                        }
                   1733: /* customize the behavior of ^H in word commands */
                   1734:                
                   1735:                        if (mfield|CTYPE) {
                   1736:                                if (BACKP) {
                   1737:                                        bits[CTRLH] = bits['_'] = WRDCHR;
                   1738:                                        ctype[CTRLH] = BACKSP;
                   1739:                                } else {
                   1740:                                        bits[CTRLH] = bits['_'] = WRDSEP;
                   1741:                                        ctype[CTRLH] = CONTRL;
                   1742:                                }
                   1743:                                if (NOTABS) ctype[CTRLI] = CONTRL;
                   1744:                                else ctype[CTRLI] = TAB;
                   1745:                                if (bit8) metal = 0;
                   1746:                                else metal = 2;
                   1747:                        }
                   1748:                        if (mfield & CSE) {
                   1749:                                if (NOCASE) count = 'a'-'A';
                   1750:                                else count = 0;
                   1751:                                for (i = 'A'; i <= 'Z'; i++) {
                   1752:                                        casem[i] = i+count;
                   1753:                                }
                   1754:                        }
                   1755:                        if (timemd == 0) *cbuf = 0; /* Nullify current time */
                   1756:                        if (mfield&DISPLAY) {
                   1757:                                fclear(); /* force re-display */
                   1758:                                if (PICMODE==0) hcol=0;
                   1759:                        }
                   1760:                        return(retval);
                   1761:                }
                   1762:        }
                   1763:        IGNORE(error (WARN,45,mp));
                   1764:        return(0);
                   1765: }
                   1766: 
                   1767: 
                   1768: modval(mp)
                   1769: char *mp;
                   1770: /* Keywords: commands macro-programming modes */
                   1771: {
                   1772:        register int i;
                   1773: 
                   1774: 
                   1775:        for (i = 0; i < NMODES; i++) if (streq(mdata[i].modename,mp)) return(*mdata[i].modeloc);
                   1776:        return(0);
                   1777: }
                   1778: 
                   1779: 
                   1780: /* display all active modes.  Values displayed for integer and string
                   1781:  * modes, all on boolean modes are displayed */
                   1782: 
                   1783: modisp(arg)
                   1784: register int arg;
                   1785: /* Keywords: informational-displays modes commands user-interface */
                   1786: {
                   1787:        register int i;
                   1788:        char *mp;
                   1789: 
                   1790:        if ((arg < 0) && (mp = getname("Mode? "))) return(modval(mp));
                   1791: 
                   1792:        mtop();
                   1793:        for (i = 0; i < NMODES; i++) {
                   1794:                switch(mdata[i].modetype) {
                   1795: 
                   1796:                case ONOFF:
                   1797:                        if (*mdata[i].modeloc) putout("%s mode is on",mdata[i].modename);
                   1798:                        else if (arg) putout ("%s mode is off",mdata[i].modename);
                   1799:                        break;
                   1800:                case INT:
                   1801:                        putout("%s = %d",mdata[i].modename,*mdata[i].modeloc);
                   1802:                        break;
                   1803:                }
                   1804:        }
                   1805:        putout (endput);
                   1806:        return(contin());
                   1807: }
                   1808: 
                   1809: /* compare two strings */
                   1810: 
                   1811: streq(cp,cp1)
                   1812: 
                   1813: register char *cp;
                   1814: register char *cp1;
                   1815: 
                   1816: /* Keywords: string-handling comparison */
                   1817: {
                   1818:        while (*cp) if (*cp++ != *cp1++) return(0);
                   1819:        if (*cp1) return(0);
                   1820:        return(1);
                   1821: }
                   1822: 
                   1823: char *
                   1824: mstrcpy(cp,cp1)
                   1825: 
                   1826: /* Keywords: assignment string-handling */
                   1827: register char *cp;
                   1828: register char *cp1;
                   1829: {
                   1830:        while (*cp++ = *cp1++);
                   1831:        return(cp-1);
                   1832: }
                   1833: 
                   1834: /* push the marked region onto the kill stack without killing it */
                   1835: 
                   1836: 
                   1837: pickup(mnumb)
                   1838: 
                   1839: /* Keywords: regions commands killstack stacking */
                   1840: 
                   1841: 
                   1842: {
                   1843:        register MARK *markp;
                   1844:        
                   1845: 
                   1846:        markp = markptr(mnumb);
                   1847: 
                   1848:        if ((markp->markl < curln) || ((markp->markl == curln) && (markp->markc < column))) {
                   1849:                killstk(markp->markl,markp->markc,curln,column);
                   1850:        } else {
                   1851:                killstk(curln,column,markp->markl,markp->markc);
                   1852:        }
                   1853: }
                   1854: 
                   1855: /* go to beginning of count line */
                   1856: 
                   1857: absgoto(count)
                   1858: register int count;
                   1859: /* Keywords: commands movement text-lines */
                   1860: 
                   1861: {
                   1862:        move((count<nlines)?count:nlines, 0);
                   1863: }
                   1864: 
                   1865: /* begin a C coment.  comment begins in COMCOL, if current position is
                   1866:  * not column 0, otherwise begins in column 0.  the next newline will end
                   1867:  * the coment */
                   1868: 
                   1869: cment()
                   1870: 
                   1871: /* Keywords: C-mode commands comments */
                   1872: 
                   1873: {
                   1874:        
                   1875:        if (column) {
                   1876:                disup();
                   1877:                if (mcol<comcol) {
                   1878:                        while (mcol<comcol) {
                   1879:                                put('   ');
                   1880:                                disup();
                   1881:                        }
                   1882:                } else {
                   1883:                        put (' ');
                   1884:                }
                   1885:        }
                   1886:        putin ("\057* ");               /* it's a slash, for stupid compilers! */
                   1887:        comln = curln;
                   1888: }
                   1889: 
                   1890: /* adjust the indentation of the current line to be consistent with that
                   1891:  * in the last line.  */
                   1892: 
                   1893: tabjust(lno)
                   1894: register int lno;
                   1895: /* Keywords: insertion C-mode commands:10 */
                   1896: {
                   1897:        register int lln;
                   1898:        register int tabno;
                   1899:        char *llp;
                   1900:        int c;
                   1901: 
                   1902:        tabno = 0;
                   1903:        for (lln = lno-1; lln > 0; lln--) {
                   1904:                llp = mkline(lln);
                   1905:                while (llp[tabno] == '  ') ++tabno;
                   1906:                if ((llp[tabno]!= EOL) && (llp[tabno+1] != '*')) {
                   1907:                        while ((c = llp[tabno])!=EOL) {
                   1908:                                switch(c) {
                   1909:                                case '{':
                   1910:                                        ++tabno;
                   1911:                                        break;
                   1912:                                default:
                   1913:                                        ++llp;
                   1914:                                }
                   1915:                        }
                   1916:                        goto tabout;
                   1917:                }
                   1918:                tabno = 0;
                   1919:        }
                   1920: tabout:
                   1921:        move(lno,0);
                   1922:        while ((c = clptr[column]) == ' ') {
                   1923:                tabno--;
                   1924:                column++;
                   1925:        }
                   1926:        if ((c == '}') && tabno) tabno--;
                   1927:        if (tabno) {
                   1928:                if (tabno>0) tabc(tabno,'       ');
                   1929:                else {
                   1930:                        bdel(-tabno);
                   1931:                        kpop();
                   1932:                        unpop(1);
                   1933:                }
                   1934:        } else { 
                   1935:                sputl(curln,column,curln);
                   1936:                move(curln,column);
                   1937:        }
                   1938: }
                   1939: 
                   1940: /* } handler, re-sets the indentation back one level */
                   1941: 
                   1942: cbrak(count,brace)
                   1943: 
                   1944: register int count;
                   1945: register int brace;
                   1946: /* Keywords: C-mode insertion commands */
                   1947: {
                   1948:        if (TABMD &&(RARE == 0) && column && (*(clptr+column-1) == '    ')){
                   1949:                bdel(1);
                   1950:                kpop();
                   1951:                unpop(1);
                   1952:        };
                   1953:        insertc(count,brace);
                   1954: }
                   1955: 
                   1956: 
                   1957: /* returns 1 if next line contains no non blank (or tab) characters */
                   1958: 
                   1959: isblank(line)
                   1960: 
                   1961: register int line;
                   1962: /* Keywords: commands:10 line-representation:50 */
                   1963: {
                   1964:        register char *lp;
                   1965: 
                   1966:        if ((line <= nlines) && (ptrs[line] == 0)) return(1);
                   1967:        lp = mkline(line);
                   1968:        while (*lp!=EOL) {
                   1969:                if ((bits[*lp++] & WHITE) == 0) return(0);
                   1970:        }
                   1971:        return(1);
                   1972: }
                   1973: 
                   1974: /* change working dir */
                   1975: 
                   1976: cwd()
                   1977: 
                   1978: /* Keywords: commands directories unix-interface */
                   1979: {
                   1980: #ifndef PC
                   1981:        char *np;
                   1982:        np = expenv(getname("Directory? "));
                   1983:        if (np) {
                   1984:                if (SAVEMD) fsave(0);
                   1985:                if (*np == 0) np = getenv("HOME"); /* null means home */
                   1986:                if(chdir(np)) {
                   1987:                        IGNORE(error(WARN,errno,np));
                   1988:                        return(0);
                   1989:                }
                   1990:                return(1);
                   1991:        }
                   1992:        return(0);
                   1993: #endif PC
                   1994: }
                   1995: 
                   1996: stats()
                   1997: {
                   1998: /* Keywords: commands informational-displays statistics */
                   1999:        
                   2000: #ifdef COMPRESS
                   2001:        extern long coutc;
                   2002: #endif
                   2003:        mtop();
                   2004:        putout ("%d chars from terminal",ninch);
                   2005:        putout ("%D calls to mputc",nmput);
                   2006:        putout ("%D chars written by mputc",noutc);
                   2007: #ifdef COMPRESS
                   2008:        putout ("%D chars after compression",coutc);
                   2009: #endif
                   2010:        putout ("%d terminal writes", ntwrite);
                   2011:        putout ("%d calls to makeline",nmkline);
                   2012:        putout ("%d buffer reads",nbread);
                   2013:        putout ("%d file writes",nbwrite);
                   2014:        putout ("%d file seeks", nbseek);
                   2015:        putout ("%d characters of buffer left", (NBLOCK*BLEN)-macptr);
                   2016:        IGNORE(contin());
                   2017: }
                   2018: 
                   2019: uline(count)
                   2020: 
                   2021: /* Keywords: word-oriented-commands commands underlining */
                   2022: register int count;
                   2023: 
                   2024: {
                   2025:        while (count--) {
                   2026:                kmark();
                   2027:                IGNORE(skipf(WRDSEP));  /* skip to begginning of word */
                   2028:                move(kline,kcol);
                   2029:                while (bits[*klptr] & WRDCHR) {
                   2030:                        put('_');
                   2031:                        put(CTRLH);
                   2032:                        forw(1);
                   2033:                }
                   2034:        }
                   2035: }
                   2036: 
                   2037: infile(fn)
                   2038: 
                   2039: /* Keywords: commands:40 files keyboard-macros:10 command-line-processing:10 command-files */
                   2040: register char *fn;
                   2041: {
                   2042:        if (pushin(expenv(fn))) {
                   2043:                edit(1);
                   2044:                inpop();
                   2045:                return(1);
                   2046:        } else return(0);
                   2047: }
                   2048: 
                   2049: 
                   2050: inpsh(arg)
                   2051: int arg;
                   2052: {
                   2053:        register char *fp;
                   2054: /* Keywords: commands files keyboard-macros:10 command-files */
                   2055: 
                   2056:        if (fp=getname("Input file? ")) {
                   2057:                if (infile(fp)==0 )  {
                   2058:                        if (arg > 0) IGNORE(error(WARN,errno,fp));
                   2059:                        return(0);
                   2060:                }
                   2061:        }
                   2062:        return(1);
                   2063: }
                   2064: 
                   2065: /* send the contents of the buffer as mail */
                   2066: 
                   2067: /* mtch -- see if current line matches header */
                   2068: 
                   2069: mtch(cp)
                   2070: register char *cp;
                   2071: /* Keywords: mail-processing string-handling:20 comparison:40 */
                   2072: 
                   2073: {
                   2074:        register char *cl;
                   2075:        cl = clptr;
                   2076:        while (*cp) if (*cp++ != *cl++) return(0);
                   2077:        return(1);
                   2078: }
                   2079: 
                   2080: mailit()
                   2081: 
                   2082: /* Keywords: mail-processing unix-interface commands */
                   2083: 
                   2084: 
                   2085: {
                   2086:        char cmdbuf[256];
                   2087:        register char *mp;
                   2088:        register char *mp1;
                   2089:        int mailstat;
                   2090:        char *mailcom;
                   2091: #ifdef POSTHACK
                   2092:        char *s;
                   2093:        register int c;
                   2094:        extern char *strrchr();
                   2095: #endif 
                   2096:        mailstat = 0;
                   2097: #ifndef PC
                   2098: #ifdef bsd
                   2099: #define DEFMAIL "/usr/lib/sendmail -t"
                   2100: #else
                   2101: #define DEFMAIL "mail"
                   2102: #endif
                   2103:        if ((mailcom=getenv("MAILER"))==NULL) mailcom=DEFMAIL;
                   2104:        
                   2105:        mp = mstrcpy(cmdbuf,mailcom);
                   2106: 
                   2107: #ifdef POSTHACK
                   2108:        /* find the start of the mail command name */
                   2109:        if ((s = strrchr(mailcom, '/')) != NULL) {
                   2110:                ++s;
                   2111:        }
                   2112:        else {
                   2113:                s = mailcom;
                   2114:        }
                   2115:        /* if this is post or Berkeley mail */
                   2116:        if (streq(s, "post") || streq(s, "Mail")) {
                   2117:                top();
                   2118:                while (curln < 10 && *clptr != EOL) {
                   2119:                        
                   2120:                        /* if there is a subject line in the message */
                   2121:                        if (mtch("Subject: ")) {
                   2122:                                
                   2123:                                /* add -s 'subject' to the mail command */
                   2124:                                strcpy(mp, " -s '");
                   2125:                                mp += 5;
                   2126:                                mp1 = clptr + 9; /* skip "Subject: " */
                   2127:                                while ((c = *mp1) != EOL) {
                   2128:                                        if (c == '\'') { /* ' becomes '\'' */
                   2129:                                                *mp++ = '\'';
                   2130:                                                *mp++ = '\\';
                   2131:                                                *mp++ = '\'';
                   2132:                                                *mp++ = '\'';
                   2133:                                        }
                   2134:                                        else {
                   2135:                                                *mp++ = c;
                   2136:                                        }
                   2137:                                        ++mp1;
                   2138:                                }
                   2139:                                *mp++ = '\'';
                   2140:                                *mp = 0;
                   2141:                                break;
                   2142:                        }
                   2143:                        move(curln+1,0);
                   2144:                }
                   2145:        }
                   2146:        /* get the list of addressees */
                   2147: #endif
                   2148:        top();
                   2149:        while (curln < 10 && *clptr != EOL) {
                   2150:                if (mtch("TO: ") || mtch("To: ") || mtch("CC: ") || mtch("Cc: ")) {
                   2151:                        if (clptr[1] == 'O') clptr[1] = 'o';
                   2152:                        if (clptr[1] == 'C') clptr[1] = 'c';
                   2153:                        column = 3;
                   2154:                        if (((mp-cmdbuf)+leng(curln)-column) > 250) {
                   2155:                                mailstat += unx(cmdbuf,1); /* partial list */
                   2156:                                mp = mstrcpy(cmdbuf,mailcom);
                   2157:                                move(curln,column);
                   2158:                        }
                   2159:                        mp1 = clptr+column;
                   2160:                        while (*mp1 != EOL) *mp++ = *mp1++; /* copy mailing list */
                   2161:                        *mp = 0;
                   2162:                }
                   2163:                move(curln+1,0);
                   2164:        }
                   2165:        mp1 = cmdbuf+4;
                   2166:        while (*mp1) if (*mp1++ != ' ') { /* Check for non-null destination list */
                   2167:                
                   2168:                mailstat += unx(cmdbuf,1);              /* send to mail command */
                   2169:                return(mailstat == 0);
                   2170:        }
                   2171:        IGNORE(error (WARN,46));
                   2172: #endif
                   2173:        return(0);
                   2174: }
                   2175: 
                   2176: /* contin -- ask user to continue */
                   2177: 
                   2178: 
                   2179: contin()
                   2180: {
                   2181: /* Keywords: informational-displays:20 user-interface:10 prompting:40 */
                   2182:        register int c;
                   2183:        if (infrn < 0) return(1);       /* continue always in a macro */
                   2184:        prompt1("Continue?");
                   2185:        c = getchar();
                   2186:        prompt1("");
                   2187:        if ((c == 'y') || (c == ' ') || (c == '\n') || (c == '\015')) return(1);
                   2188:        if ('n' == c) return(0);
                   2189:        if (c == CTRLZ) {
                   2190:                gquit();
                   2191:                return(1);
                   2192:        }
                   2193:        ungetch(c);
                   2194:        return(0);
                   2195: }
                   2196: 
                   2197: /* buffer length and current position */
                   2198: 
                   2199: 
                   2200: /* If invoked from tty, prints buffer status info on the terminal.  If */
                   2201: /* invoked from a macro, returns a value dependent on its argument */
                   2202: 
                   2203: #define VLIN 0                         /* return line number */
                   2204: #define VCOL 1                         /* return column number */
                   2205: #define VDLIN 2                                /* display line */
                   2206: #define VDCOL 3                                /* display column */
                   2207: #define VMINLN 4                       /* First file line on screen */
                   2208: #define VMAXLN 5                       /* ditto last */
                   2209: #define VWTOP 6                                /* First screen line of window */
                   2210: #define VWBOT 7                                /* ditto last */
                   2211: 
                   2212: buflng(arg)
                   2213: 
                   2214: int arg;
                   2215: {
                   2216: /* Keywords: commands macro-programming:40 buffers statistics */
                   2217:        
                   2218:        long flng;
                   2219:        long fpos;      
                   2220:        char xbuf[128];
                   2221:        extern int minln;
                   2222:        extern int maxln;
                   2223:        register int i;
                   2224:        if (infrn < 0) {
                   2225:                                /* If from macro, return useful info */
                   2226:                switch(arg) {
                   2227:                        
                   2228:                case VCOL: return(column);
                   2229:                case VLIN: return(curln);
                   2230:                case VDCOL:
                   2231:                case VDLIN:
                   2232:                        if (findline(curln) == 0) return(-1);
                   2233:                        mline=nln;
                   2234:                        if (findpos(clptr,column) == 0) return(-1);
                   2235:                        if (arg == VDLIN) return(nln-wbase);
                   2236:                        else return(mcol);
                   2237:                case VMINLN: return(minln);
                   2238:                case VMAXLN: return(maxln);
                   2239:                case VWTOP: return(wbase);
                   2240:                case VWBOT: return(SCRLINES-1);
                   2241:                }
                   2242:        }
                   2243:        flng = 0L;
                   2244:        for (i = 1; i <= nlines; i++) {
                   2245:                if (i != 1) flng++;     /* linefeed from last line */
                   2246:                if (i == curln) fpos = flng + column;
                   2247:                flng += leng(i);
                   2248:        }
                   2249:        clptr=mkline(curln);
                   2250:        seprintf(xbuf,"next char: %o, line: %d/%d:  pos:  %D/%D column: %d",
                   2251:                clptr[column],curln,nlines-1,fpos,flng,column);
                   2252:        prompt1(xbuf);
                   2253:        return(0);
                   2254: }
                   2255: 
                   2256: filler(arg)
                   2257: /* Keywords: regions:50 text-filling commands */
                   2258: int arg;
                   2259: {
                   2260:        register int i;
                   2261:        register char *cp;
                   2262:        register int j;
                   2263:        int unp;
                   2264:        
                   2265:        unp = unstart();        
                   2266:        if (arg != 1) {
                   2267:                                        /* fill region only */
                   2268:                register MARK *markp;
                   2269:                markp = markptr(curbf);
                   2270:                if ((i = markp->markl) > curln) fillreg(curln,i,1);
                   2271:                else fillreg(i,curln,1);
                   2272:        } else {
                   2273:                undel();
                   2274:                killstk(1,0,nlines,0);
                   2275:                kpop();
                   2276:                for (i = 1; i < nlines;i++ ) {
                   2277:                        cp = mkline(i);
                   2278:                        if ((*cp != '.') && (*cp != '\'') && (*cp != EOL)) {
                   2279:                                j = i;
                   2280:                                while (i < nlines) {
                   2281:                                        cp = mkline(i);
                   2282:                                        if ((*cp == '.') || (*cp == '\'') || (*cp == EOL)) break;
                   2283:                                        i++;
                   2284:                                }
                   2285:                                fillreg(j,i,0);
                   2286:                                i = curln+1;
                   2287:                        }
                   2288:                }
                   2289:                unins(1,0);
                   2290:        }
                   2291:        unend(unp);
                   2292: }
                   2293: 
                   2294: fillreg(i,j,u)
                   2295: register int i;
                   2296: register int j;
                   2297: int u;
                   2298: {
                   2299: /* Keywords: commands:10 text-filling regions:20 undo:10 */
                   2300: 
                   2301:        int onlin,ofill;
                   2302:        onlin = NLINS;
                   2303:        ofill = FILLMD;
                   2304:        FILLMD = NLINS = 1;     /* Turn on "rigid_newline" mode */
                   2305:        move(i,0);
                   2306:        if (u) {
                   2307: 
                   2308:                /* Make an undo record for this region */
                   2309:                
                   2310:                undel();
                   2311:                killstk(i,0,j,0);
                   2312:                kpop();
                   2313:        }
                   2314:        while (curln < j) {
                   2315:                endl();
                   2316:                do {
                   2317:                        i = curln;
                   2318:                        afsep(0,0);/* Note that we don't really put anything in */
                   2319:                        if (i != curln) j++;
                   2320:                } while (i != curln);
                   2321:                if (curln < j-1) {
                   2322:                        fdel(1);
                   2323:                        kpop();
                   2324:                        unpop(1);
                   2325:                        while ((clptr[column] == ' ') || (clptr[column] == '    ')) {
                   2326:                                fdel(1);
                   2327:                                kpop();
                   2328:                                unpop(1);
                   2329:                        }
                   2330:                        put(' ');
                   2331:                        j--;
                   2332:                } else break;
                   2333:        }
                   2334:        if (u) {
                   2335:                move(j,0);
                   2336:                unins(i,0);             /* Make a second undo record */
                   2337:        }
                   2338:        NLINS = onlin;  
                   2339:        FILLMD = ofill;
                   2340: }
                   2341: 
                   2342: /* macro the region */
                   2343: 
                   2344: macro(arg)
                   2345: int arg;
                   2346: {
                   2347: /* Keywords: key-bindings memory-allocation:10 parsing symbol-handling commands macro-hooks:20 */
                   2348: 
                   2349:        register int mychar;    
                   2350:        register int balance;
                   2351:        register int machr;
                   2352:        int oldpic;
                   2353:        int compos;
                   2354:        int hookp;
                   2355:        int hash,ename;
                   2356: #ifdef u370
                   2357:        int beepbeep();
                   2358: #else  
                   2359:        extern int beep();
                   2360: #endif
                   2361:        
                   2362:        oldpic=PICMODE;
                   2363:        PICMODE=0;
                   2364:        bot();
                   2365:        back(2);
                   2366:        if (clptr[column] != CTRLZ) {
                   2367: 
                   2368: /* File does not end in ^Z, Try to catch a potential disaster */
                   2369:                
                   2370:                error(WARN,80,fname());
                   2371:                PICMODE=oldpic;
                   2372:                return(0);
                   2373:        }
                   2374:        if (arg != 1) {
                   2375:                for (mychar = 0; mychar < NCHARS; mychar++) {
                   2376:                        if (map_it[mychar] > ISIZE) {
                   2377:                                map_it[mychar] = 0;
                   2378:                        }
                   2379:                        if (mychar < NMAC) machash[mychar] = 0;
                   2380:                        if (mychar < NHOOKS) hooks[mychar] = 0;
                   2381: 
                   2382:                }
                   2383:                macptr = 0;
                   2384:                fbkno = 0;
                   2385:        }
                   2386:        top();
                   2387:                
                   2388:        while (curln<nlines) {
                   2389: 
                   2390:                balance = 0;
                   2391:                machr = clptr[column]&0377;
                   2392:                if (machr == ESC) machr = (clptr[++column]&0377)+0200;
                   2393:                if (machr == CTRLX) {
                   2394:                        machr = (clptr[++column]&0377)+0400;
                   2395:                }
                   2396:                if (machr == CTRLZ) {
                   2397:                        hookp =  (clptr[++column]&0377);
                   2398:                        if (hookp > NHOOKS) {
                   2399:                                hookp = 0; /* Just ignore the bad ones */
                   2400:                                --column; 
                   2401:                        }
                   2402:                }
                   2403:                forw(1);
                   2404:                if (macptr == 0) pshchr(0); /* Can't use the first location! */
                   2405:                compos = macptr;
                   2406:                pshchr(0);              /* Leave room for linkage chain */
                   2407:                pshchr(0);
                   2408:                hash = 0;
                   2409:                ename = 1;
                   2410:                if (clptr[column] == CTRLBACK) { /* if comment */
                   2411:                        pshchr(0);
                   2412:                        ++column;
                   2413:                        while (clptr[column] != EOL) {
                   2414:                                if ((clptr[column] == ' ')||(clptr[column] == ' ')) ename = 0;
                   2415:                                if (ename) hash += clptr[column];
                   2416:                                pshchr(clptr[column++]);
                   2417:                        }
                   2418:                        pshchr(0);
                   2419:                        forw(1);        /* skip newline */
                   2420:                }
                   2421:                hash %= NMAC;
                   2422:                bbuf[0][compos] = machash[hash];
                   2423:                bbuf[0][compos+1] = machash[hash]>>8;
                   2424:                machash[hash] = compos;
                   2425:                if (machr == CTRLZ) hooks[hookp] = macptr; /* Define hook */
                   2426:                else {
                   2427:                                        /* Define character command */
                   2428: 
                   2429:                        map_it[machr] = macptr+ISIZE;
                   2430:                }
                   2431:                while (curln < nlines) {
                   2432:                        mychar = clptr[column]&0377;
                   2433:                        if (column == 0) {
                   2434:                                while ((mychar==' ') || (mychar=='      ')) {
                   2435:                                        column++;
                   2436:                                        mychar = clptr[column]&0377;
                   2437:                                }
                   2438:                        }
                   2439:                        if (mychar != CTRLBACK) {
                   2440:                                if (mychar == MTA({)) balance++;
                   2441:                                else if (mychar == MTA(})) balance--;
                   2442:                                pshchr(mychar);
                   2443:                                forw(1);
                   2444:                                if ((mychar == CTRLZ) && (clptr[column] == EOL)) {
                   2445:                                        if (balance) {
                   2446:                                                error(WARN,47,curln);
                   2447:                                        }
                   2448:                                        goto macdone; /* end of macro definition */
                   2449:                                }
                   2450:                        } else {
                   2451:                                move(curln+1,0); /* skip comment */
                   2452:                        }
                   2453:                }
                   2454:                error (WARN,48);
                   2455:                pshchr(CTRLG);          /* escape from bad macro */
                   2456: 
                   2457: macdone:       forw(1);                /* on to next macro */
                   2458:        }
                   2459:        PICMODE=oldpic;
                   2460:        if (hooks[Load_Macro_Hook]) {
                   2461:                hook(Load_Macro_Hook);
                   2462:                hooks[Load_Macro_Hook] = 0;
                   2463:        }
                   2464:        return(1);
                   2465: }
                   2466: 
                   2467: ldmac(arg)
                   2468: int arg;
                   2469: /* Keywords: commands files reading macro-programming:20 */
                   2470: {
                   2471:        register int oldbuf;
                   2472:        register int tmpbuf;
                   2473:        char *obname;
                   2474:        int oldbin;     
                   2475:        int err;
                   2476:        
                   2477:        if (arg>0) err = 1;
                   2478:        else {
                   2479:                err = 0;
                   2480:                arg = 1;
                   2481:        }
                   2482:        obname = fname();               /* Old file name */
                   2483:        oldbuf = curbf;
                   2484:        chgbuf("...");                  /* temporary buffer */
                   2485:        strcpy(fname(),obname);         /* Restore file name */
                   2486: #ifdef PC
                   2487:        oldbin = BINMODE;
                   2488:        BINMODE = 1;
                   2489: #endif PC      
                   2490:        if (fred(err)) {                        /* read file */
                   2491:                macro(arg);
                   2492:                err = 1;
                   2493:        } else {
                   2494:                err = 0;
                   2495:        }
                   2496: #ifdef PC
                   2497:        BINMODE=oldbin;
                   2498: #endif PC
                   2499:        tmpbuf = curbf;
                   2500:        chbuf(oldbuf);
                   2501:        klbfr(tmpbuf);                  /* kill temp buffer */
                   2502:        return(err);
                   2503: }
                   2504: /* macro programming commands */
                   2505: 
                   2506: /* these commands perform various utility functions for macro commands */
                   2507: 
                   2508: bfchr()                                        /* get a character from the buffer */
                   2509: {
                   2510: /* Keywords: macro-programming quoting character-at-a-time buffers:40 */
                   2511:        return(clptr[column]&0377);     /* Trim sign bits! */
                   2512: }
                   2513: 
                   2514: litchr()                               /* literal character */
                   2515: 
                   2516: {
                   2517: /* Keywords: macro-programming quoting */
                   2518:        return(getchar());
                   2519: }
                   2520: 
                   2521: compar(ctype)                          /* general comparison */
                   2522: 
                   2523: /* comparison type definitions (pecular arangement for convenient */
                   2524: /* specification via ^U */
                   2525: 
                   2526: 
                   2527: #define CLE 0                          /* <= */
                   2528: #define CEQ 1                          /* = */
                   2529: #define CLS 2                          /* < */
                   2530: #define CGT 3                          /* > */
                   2531: #define CNE 4                          /* != */
                   2532: #define CGE 5                          /* >= */
                   2533: #define COR 6                          /* OR */
                   2534: #define CAND 7                         /* AND */
                   2535: #define CNOT 8                         /* NOT */
                   2536: #define CFALSE 9                       /* FALSE */
                   2537: #define CTRUE 10                       /* TRUE */
                   2538: #define CPLUS 11                       /* arg1 + arg2 */
                   2539: #define CMINUS 12                      /* arg1 - arg2 */
                   2540: #define CTIMES 13                      /* arg1 * arg2 */
                   2541: #define CDIV 14                                /* arg1 / arg2 */
                   2542: #define CREM 15                                /* arg1 % arg2 */
                   2543: #define CDTOS 16                       /* arg1 convert to string on kill stack */
                   2544: #define CSTOD 17                       /* convert ks to decimal and return */
                   2545: #define CBAND 18                       /* Bitwise and */
                   2546: #define CBOR 19                                /* Bitwise or */
                   2547: #define CXOR 20                                /* Bitwise xor */
                   2548: #define CUNGET 21                      /* Unget character */
                   2549: #define CPENDING 22                    /* number of characters pending */
                   2550: 
                   2551: /* Keywords: macro-programming arithmetic:50 comparison:50 */
                   2552: 
                   2553: register int ctype;
                   2554: {
                   2555:        register int r1;
                   2556:        register int r2;
                   2557:        char *sp;
                   2558:        char sbuf[20];
                   2559:        int res;
                   2560:        
                   2561:        if (ctype == CFALSE) return(0);
                   2562:        if (ctype == CTRUE) return(1);
                   2563:        if (ctype == CSTOD) {
                   2564:                sp = getname("Number?");
                   2565:                nscan(sp,&res);
                   2566:                return(res);
                   2567:        }
                   2568:        if (ctype == CPENDING) {
                   2569:                ttfill();               /* Read any pending tty input */
                   2570:                return(ttcnt);
                   2571:        }
                   2572:        r1 = edit(0);                   /* first arg */
                   2573: 
                   2574:        if (ctype == CNOT) return(r1 == 0);
                   2575:        if (ctype == CDTOS) {
                   2576:                seprintf(sbuf,"%d",r1);
                   2577:                stkstr(sbuf);
                   2578:                return(r1);
                   2579:        }
                   2580:        if (ctype == CUNGET) {
                   2581:                pushin(0);              /* Force to tty */
                   2582:                ungetch(r1);
                   2583:                inpop();
                   2584:                return(1);
                   2585:        }
                   2586:        r2 = edit(0);                   /* second arg */
                   2587:        
                   2588:        switch(ctype) {
                   2589:                
                   2590:        case CLE: return(r1<=r2);
                   2591:        case CEQ: return(r1==r2);
                   2592:        case CLS: return(r1<r2);
                   2593:        case CGT: return(r1>r2);
                   2594:        case CNE: return(r1!=r2);
                   2595:        case CGE: return(r1>=r2);
                   2596:        case CAND: return(r1 && r2);
                   2597:        case COR: return(r1 || r2);
                   2598:        case CPLUS: return(r1+r2);
                   2599:        case CMINUS: return(r1-r2);
                   2600:        case CTIMES: return (r1*r2);
                   2601:        case CDIV: if (r2) return(r1/r2);
                   2602:                else return(0);
                   2603:        case CREM: if (r2) return(r1%r2);
                   2604:                else return(0);
                   2605:        case CBAND: return(r1&r2);
                   2606:        case CBOR: return(r1|r2);
                   2607:        case CXOR: return (r1^r2);
                   2608: default:return(0);
                   2609:        }
                   2610: }
                   2611: 
                   2612: 
                   2613: pscan(lev)                             /* parenthesis scan */
                   2614: /* Keywords: macro-programming parsing control-flow:50 */
                   2615: register int lev;                              /* returns when lev+paren level = 0 */
                   2616: {
                   2617:        register int c;
                   2618:        register int ctlx;
                   2619:        ctlx = 0;
                   2620:        while (lev) {
                   2621:                c = Mgetchar();
                   2622:                if (c == CTRLX) {
                   2623:                        ctlx++;
                   2624:                        continue;
                   2625:                }
                   2626:                if (!ctlx && ((c == (CTRLQ)) || (c == MTA(q)) || (c == (CTRLQ+META)))) {
                   2627:                        c = Mgetchar();
                   2628:                        continue;
                   2629:                }
                   2630:                ctlx = 0;
                   2631:                if (c == MTA({)) lev++;
                   2632:                else if (c == MTA(})) lev--;
                   2633:        }
                   2634: }
                   2635: 
                   2636: 
                   2637: cond()                                 /* conditional execute */
                   2638: /* Keywords: control-flow parsing :5 conditionals macro-programming */
                   2639: {
                   2640:        register int c;
                   2641:        
                   2642:        MACEXIT;                        /* Only in a macro */
                   2643:        
                   2644:        if ((c = Mgetchar()) != MTA({)) {
                   2645:                                        /* must be M-{ */
                   2646:                return(error(NORM,49));
                   2647:        }
                   2648:        while ((c = Mgetchar()) != MTA(})) {
                   2649:                while ((c != MTA({)) && (c !=MTA(}))) c = Mgetchar();
                   2650:                if (c == MTA(})) return(0); /* failed */
                   2651:                if (edit(0)) {
                   2652:                        c = edit(1); /* scan command */
                   2653:                        pscan(1);       /* skip to end of cond */
                   2654:                        return(c);
                   2655:                } else pscan(1);        /* skip to end of block */
                   2656:        }
                   2657:        return(0);                      /* cond failed */
                   2658: }
                   2659: 
                   2660: /* macro case statement:  syntax is ^x!M-{<expr>
                   2661:  *                                     M-{<char><sequence>M-}
                   2662:  *                                     ...
                   2663:  *                                   M-}
                   2664:  */
                   2665: 
                   2666: 
                   2667: mcase()
                   2668: 
                   2669: 
                   2670: 
                   2671: /* Keywords: cases parsing:5 control-flow macro-programming */
                   2672: {
                   2673:        register int cchar;
                   2674:        register int c;
                   2675: 
                   2676:        MACEXIT;        
                   2677: 
                   2678:        while ((cchar =Mgetchar()) != MTA({));
                   2679:        cchar = edit(0);                /* match expression */
                   2680:        
                   2681:        while ((c = Mgetchar()) != MTA(})) {
                   2682:                while ((c != MTA({)) && (c !=MTA(}))) c = Mgetchar();
                   2683:                if (c == MTA(})) return(0); /* failed */
                   2684:                c = Mgetchar();
                   2685:                if ((c == cchar) || (c == 0377)) {
                   2686:                        c = edit(1); /* scan command */
                   2687:                        pscan(1);       /* skip to end of case */
                   2688:                        return(c);
                   2689:                } else pscan(1);        /* skip to end of block */
                   2690:        }
                   2691:        return(0);                      /* case failed */
                   2692: }
                   2693:        
                   2694: /* mbegin -- begin block in macro */
                   2695: 
                   2696: mbegin()
                   2697: 
                   2698: 
                   2699: /* Keywords: macro-programming parsing:20 control-flow */
                   2700: 
                   2701: {
                   2702:        return(edit(1));                /* push command */
                   2703: }
                   2704: 
                   2705: /* iteration handler */
                   2706: 
                   2707: iter()
                   2708: {
                   2709: /* Keywords: macro-programming control-flow parsing:10 loops */
                   2710: 
                   2711:        register int c;
                   2712:        register char *savptr;
                   2713:        
                   2714:        MACEXIT;
                   2715:        
                   2716:        while ((c =Mgetchar()) != MTA({)) {
                   2717:                if ((c != '     ') && (c != ' ') && (c != EOL)) {
                   2718:                        return(error (NORM,50));
                   2719:                }
                   2720:        }
                   2721:        savptr = inget();
                   2722:        while (edit(0)) {               /* test condition */
                   2723:                
                   2724:                c = edit(1);            /* execute body */
                   2725:                
                   2726:                inset(savptr);          /* backup */
                   2727:                
                   2728:        }
                   2729:        pscan(1);                       /* skip body */
                   2730:        return(c);
                   2731: }
                   2732: 
                   2733: /* gparam -- get a parameter and push into the kill stack */
                   2734: 
                   2735: /* with an argument of 1, it takes the parameter in line, with */
                   2736: /* other arguments, it takes the parameter from the tty, prompting with */
                   2737: /* the in line parameter4 */
                   2738: 
                   2739: 
                   2740: gparam(arg)                             /* get a parameter */
                   2741: 
                   2742: int arg;                               /* with 1 arg, from macro text, else from tty */
                   2743: 
                   2744: 
                   2745: /* Keywords: macro-programming string-handling:20 string-variables:50 filenames:10 prompting:40 reading:20 killstack:20 */
                   2746: {
                   2747:        char pbuf[128];
                   2748:        register char *pb;
                   2749:        register int pbch;
                   2750:        
                   2751:        MACEXIT;
                   2752:        for (pb = pbuf;;) {
                   2753:                *pb++ = pbch = Mgetchar();
                   2754:                if (pbch == CTRLQ){
                   2755:                        --pb;
                   2756:                        *pb++ = Mgetchar();
                   2757:                }
                   2758:                if ((pbch == EOL)|| (pbch==CTRLZ)) break;
                   2759:                if (pb>=(pbuf+128)) pb--; /* Truncate pb */
                   2760:        }
                   2761:        *(--pb) = 0;                    /* pickup prompt message */
                   2762:        return(gpm(arg,pbuf));          /* pickup up parameter */
                   2763: }
                   2764: 
                   2765: /* gkarm -- like gparm, except input is from the kill stack. */
                   2766: 
                   2767: 
                   2768: gkarm(arg)
                   2769: 
                   2770: /* Keywords: macro-programming string-handling:20 string-variables:50 filenames:10 prompting:40 reading:20 killstack:20 */
                   2771: int arg;
                   2772: {
                   2773:        char *pb;
                   2774:        
                   2775:        pb = getname("");               /* pick up parameter */
                   2776:        
                   2777:        return(gpm(arg,pb));
                   2778: }
                   2779: 
                   2780: 
                   2781: gpm(arg,pbuf)
                   2782: register int arg;
                   2783: register char *pbuf;
                   2784: 
                   2785: /* Keywords: macro-programming string-handling:20 string-variables:50 filenames:10 prompting:40 reading:20 killstack:20 */
                   2786: {
                   2787:        register char *pb;
                   2788:        char pmpt[128];
                   2789:        int pbch;
                   2790:        
                   2791:        if (arg == 3) {
                   2792:                eprintf("%s",pbuf);     /* Raw print, shouldn't mung screen */
                   2793:                
                   2794:                return(1);
                   2795:        }
                   2796:        if (arg != 1)   {
                   2797:                pushin(NULL);
                   2798:                if (arg <= 0) {
                   2799:                                        /* single character */
                   2800:                        prompt1("%s",pbuf);
                   2801:                        if (arg < 0) {
                   2802:                                mgo(nln,ncol);
                   2803:                                pbch = getchar();
                   2804:                                unprompt();
                   2805:                        }
                   2806:                        inpop();
                   2807:                        return(pbch);
                   2808:                }
                   2809:                strcpy(pmpt,pbuf);      /* In case prompt is in pbuf already */
                   2810:                pb = getname(pmpt);
                   2811:                if (pb == NULL) pb = "";
                   2812:                inpop();
                   2813:        } else pb = pbuf;
                   2814:        stkstr(pb);
                   2815:        return(lng(pb));
                   2816: }
                   2817: 
                   2818: 
                   2819: char *
                   2820: maclook(mp)
                   2821: char *mp;
                   2822: 
                   2823: /* Keywords: macro-programming:20 symbol-handling macro-invocation global-variables:50 */
                   2824: {
                   2825:        int hash,ohash;
                   2826:        register char *mp1,*mp2;
                   2827:        
                   2828: /* now look up macro name */
                   2829:        
                   2830:        mp1 = mp;
                   2831:        hash = 0;
                   2832:        while (*mp1) hash += *mp1++;
                   2833:        hash = hash %NMAC;
                   2834:        ohash = hash;
                   2835:        hash = machash[hash];
                   2836:        while (hash) {
                   2837:                for (mp1=mp,mp2= &bbuf[0][hash+3]; *mp1++ == *mp2++; ) {
                   2838:                        if ((*mp1 == 0) && ((*mp2 == 0)||(*mp2 == ' ')|| (*mp2 == '     '))) {
                   2839:                                while (*mp2++);
                   2840:                                return(mp2);
                   2841:                        }
                   2842:                }
                   2843:                hash = (bbuf[0][hash]&0377) + (bbuf[0][hash+1] <<8);
                   2844:        }
                   2845:        return(NULL);
                   2846: }
                   2847: 
                   2848: /* macro call by name */
                   2849: 
                   2850: 
                   2851: macex(arg,ivchar)
                   2852: 
                   2853: int arg;
                   2854: int ivchar;
                   2855: 
                   2856: /* Keywords: macro-invocation macro-programming modes:10 reading:40 */
                   2857: {
                   2858:        char mbuf[100];
                   2859:        register char *mp1;
                   2860:        register char *mp3;
                   2861:        register int c;
                   2862:        
                   2863:        mp1 = mbuf;
                   2864:        if (infrn < 0) {
                   2865:                while ((c = Mgetchar()) != EOL) *mp1++ = c;
                   2866:                *mp1 = 0;
                   2867:                mp3 = mbuf;
                   2868:        } else {
                   2869:                mp3 = getname ("Macro name? ");
                   2870:        }
                   2871:        if (mp3 == NULL) return(0);     /* aborted */
                   2872:        if (mp1 = maclook(mp3)) {
                   2873: run:           return(xmac(mp1-bbuf[0],arg,ivchar));
                   2874:        } else {
                   2875:                if (AUTOLOAD && (infrn < 0)) {
                   2876: 
                   2877: /* Autoload mode,  If an undefined macro is called from a macro, it */
                   2878: /* tries to load it from a standard library */
                   2879: 
                   2880:                        char buf[128];
                   2881: #ifdef PC
                   2882:                        seprintf (buf,"%s",mp3);
                   2883: #else
                   2884:                        seprintf(buf,"~EMACS/macros/%s",mp3);
                   2885: #endif
                   2886:                        stkstr(buf);
                   2887:                        if (ldmac(-1) &&(mp1 = maclook(mp3))) {
                   2888: loaded:                                prompt(ECHOL,"Autoloaded %s",buf);
                   2889:                                goto run;
                   2890:                        }
                   2891: #ifdef PC
                   2892:                        seprintf(buf,"c:%s",mp3);
                   2893: #else
                   2894:                        seprintf(buf,"$EMACS_LIB/%s",mp3);
                   2895: #endif
                   2896:                        stkstr(buf);
                   2897:                        if (ldmac(-1) && (mp1 = maclook(mp3))) goto loaded;
                   2898:                }
                   2899:                error (WARN,51,mp3);
                   2900:                return(NULL);
                   2901:        }
                   2902: }
                   2903: hook(hookp)
                   2904: int hookp;
                   2905: 
                   2906: /* Keywords: macro-programming macro-invoction:50 macro-hooks */
                   2907: {
                   2908:        register int oldhook;
                   2909:        int result;
                   2910:        char xfnbuf[FNLEN];
                   2911:        
                   2912:        strcpy(xfnbuf,fnbuf);           /* Preserve temp buffer, in case it's wiped by the macro */
                   2913:        
                   2914:        oldhook = hooks[hookp];
                   2915:        hooks[hookp] = 0;                       /* Prevent recursion */
                   2916:        result = xmac (oldhook,0,0);
                   2917:        hooks[hookp] = oldhook;
                   2918:        strcpy(fnbuf,xfnbuf);
                   2919:        return(result);
                   2920: }
                   2921: /* xmac -- execute a macro */
                   2922: 
                   2923: 
                   2924: xmac(macp,arg,ivchar)
                   2925: 
                   2926: register int macp;
                   2927: register int arg;
                   2928: int ivchar;
                   2929: {
                   2930: /* Keywords: macro-programming macro-invocation local-variables:60 argument-processing:20 */
                   2931:        
                   2932:        int mvars[NMVAR];               /* macro variables */
                   2933:        int *omarg;                     /* old pointer to mvars */
                   2934:        
                   2935:        omarg = marg;
                   2936:        marg = mvars;
                   2937:        mvars[1]=arg;                   /* record macro argument */
                   2938:        mvars[0] = ivchar;              /* invoking character */
                   2939:        pshmac(macp);
                   2940:        if (etrace) putout("Entering macro: %s",hmap(macp));
                   2941: 
                   2942:        arg = edit(1);
                   2943: 
                   2944:        if (etrace) putout ("Exiting macro: %s",hmap(macp));
                   2945:        marg = omarg;
                   2946:        inpop();
                   2947:        return(arg);
                   2948: }
                   2949: 
                   2950: /* setvar -- set a local variable */
                   2951: 
                   2952: setvar(arg)
                   2953: register int arg;
                   2954: {
                   2955: /* Keywords: assignment macro-programming local-variables */
                   2956:        register int oldvar;
                   2957: 
                   2958:        if ((arg <NMVAR) && (arg >=0)) {
                   2959:                oldvar = marg[arg];
                   2960:                marg[arg] = edit(0); /* set new value */
                   2961:                return(oldvar);
                   2962:        } else {
                   2963:                beep();
                   2964:                return(0);
                   2965:        }
                   2966: }
                   2967: 
                   2968: /* getsharg -- get argument from shell command line */
                   2969: 
                   2970: /* with argument of 1, gets one argument and pops. */
                   2971: /* with other argument, returns argument but does not pop */
                   2972: 
                   2973: /* Value returned is 1 unless there are no more command line options. */
                   2974: 
                   2975: 
                   2976: getsharg(arg)
                   2977: int arg;
                   2978: {
                   2979: /* Keywords: argument-processing:10 command-line-processing macro-programming */
                   2980:        extern char **sharg;
                   2981:        extern int nsharg;
                   2982:        
                   2983:        if (nsharg) {
                   2984:                
                   2985:                stkstr(*sharg);
                   2986:                if (arg==1) {
                   2987:                        nsharg--;
                   2988:                        sharg++;
                   2989:                }
                   2990:                return(1);
                   2991:        }
                   2992:        return(0);
                   2993: }
                   2994: 
                   2995: 
                   2996:        
                   2997: /* string operations */
                   2998: 
                   2999: /* compares same argument conventions as other comparisons */
                   3000: 
                   3001: #define CAPP 7                         /* Arg 2 appended to arg1 */
                   3002: #define CINDEX 8                       /* index of arg 2 in arg1 */
                   3003: #define SBINARY 8
                   3004: #define CSUBSTR 9                      /* string indexed by next 2 commands */
                   3005: #define CLENGTH 10                     /* String length */
                   3006: #define SUNARY 10
                   3007: #define CPTR 11
                   3008: #define CSTRING 12
                   3009: #define CPRINTF 13                     /* formatted I/O */
                   3010: 
                   3011: cmpst(arg)
                   3012: 
                   3013: register int arg;
                   3014: 
                   3015: /* Keywords: macro-programming comparison string-variables string-handling:30 conversions:20 */
                   3016: {
                   3017:        char buf[256];
                   3018:        
                   3019:        register char *bp1;
                   3020:        register char *bp2;
                   3021:        char *bp3;
                   3022:        int i,j;
                   3023:        
                   3024:        if (arg <= SUNARY)bp1 = getname("");            /* get first string */ 
                   3025:        
                   3026:        if (arg <= SBINARY) {
                   3027:                strcpy(buf,bp1); 
                   3028:                bp1 = buf;              
                   3029:                bp2 = getname("");
                   3030:        }
                   3031:        
                   3032:        if (arg <= CGE) {
                   3033:                while ((*bp1 == *bp2) && *bp1) {
                   3034:                        bp1++;
                   3035:                        bp2++;
                   3036:                }
                   3037:        }
                   3038:        switch (arg) {
                   3039:                
                   3040:        case CLE: return(*bp1<=*bp2);
                   3041:        case CEQ: return(*bp1==*bp2);
                   3042:        case CLS: return(*bp1<*bp2);
                   3043:        case CGT: return(*bp1>*bp2);
                   3044:        case CNE: return(*bp1!=*bp2);
                   3045:        case CGE: return(*bp1>=*bp2);
                   3046:        case CAPP:
                   3047:                strcpy(bp2+lng(bp2),bp1);
                   3048:                stkstr(bp2);
                   3049:                return(1);
                   3050:        case CINDEX:
                   3051:                i = 0;
                   3052:                bp3 = bp2;
                   3053:                while (*(bp2=bp3+i)) {
                   3054:                        bp1 = buf;
                   3055:                        while (*bp1++ == *bp2++) {
                   3056:                                if (*bp1 == 0) return(i);
                   3057:                        }
                   3058:                        i++;
                   3059:                }
                   3060:                return(-1);
                   3061:        case CSUBSTR: 
                   3062:                i = edit(0);
                   3063:                j = edit(0);
                   3064:                bp1[j]=0;
                   3065:                stkstr(bp1+i);
                   3066:                return(1);
                   3067:        case CLENGTH: return(lng(bp1));
                   3068:        case CPTR: return(kgptr());
                   3069:        case CSTRING:
                   3070:                i = edit(0);
                   3071:                kput(i);
                   3072:                return(1);
                   3073:        case CPRINTF:
                   3074:                                        /* Printf like formatting. */
                   3075:                {
                   3076:                        int pts[20],len;
                   3077:                        char buf2[256];
                   3078:                        bp1=bp2=getname(""); /* Format string */
                   3079: 
                   3080: /* First, collect all of the parameters */
                   3081:                        
                   3082:                        i = 0;
                   3083:                        while(*bp1) {
                   3084:                                if (bp1[0] == '%') {
                   3085:                                        if (bp1[1] == '%') bp1++;
                   3086:                                        else pts[i++] = kgptr(); /* Collect one */
                   3087:                                }
                   3088:                                bp1++;
                   3089:                        }
                   3090:                        strcpy(buf2,bp2);
                   3091:                        bp2 = buf2;
                   3092:                        bp1 = buf;
                   3093:                        while (*bp2) {
                   3094:                                if (*bp2 == '%') {
                   3095:                                        bp2 = nscan(bp2+1,&j);
                   3096:                                        if (*bp2 == '%') {
                   3097:                                                *bp1++ = *bp2++;
                   3098:                                                continue;
                   3099:                                        }
                   3100:                                        kput(pts[--i]);
                   3101:                                        bp3 = getname(""); /* get the param */
                   3102:                                        len = lng(bp3);
                   3103:                                        
                   3104:                                        switch(*bp2++) {
                   3105:                                                
                   3106:                                        case 'l': bp1 = mstrcpy(bp1,bp3);
                   3107:                                                j = j-len;
                   3108:                                                if (j>0) while (j--) *bp1++ = ' ';
                   3109:                                                break;
                   3110:                                        case 'r':
                   3111:                                                j = j-len;
                   3112:                                                if (j>0) while (j--) *bp1++ = ' ';
                   3113:                                                 bp1 = mstrcpy(bp1,bp3);
                   3114:                                                break;
                   3115:                                        case 'c':
                   3116:                                                len = (j-len);
                   3117:                                                if (len>= 0) {
                   3118:                                                        j = len/2;
                   3119:                                                        len = len-j;
                   3120:                                                        while (j--) *bp1++ = ' ';
                   3121:                                                }
                   3122:                                                bp1 = mstrcpy(bp1,bp3);
                   3123:                                                if (len> 0) while (len--) *bp1++ = ' ';
                   3124:                                                break;
                   3125:                                        }
                   3126:                                } else *bp1++ = *bp2++;
                   3127:                        }
                   3128:                        *bp1 = 0;
                   3129:                        stkstr(buf);
                   3130:                        return(1);
                   3131:                }
                   3132:        default:  return(0);
                   3133:        }
                   3134: }
                   3135: 
                   3136: 
                   3137: /* Global variable -- global variables are dynamically bound by
                   3138:  * names.  They are 2 or 4 bytes long and always stored in order of
                   3139:  * lsB first.   */
                   3140: 
                   3141: glob(arg)
                   3142: int arg;
                   3143: {
                   3144: /* Keywords: global-variables assignment:50 macro-programming */
                   3145:        int size;
                   3146:        char *name;
                   3147:        char *where;
                   3148:        int hash;
                   3149:        
                   3150:        
                   3151:        if (name= getname ("Global variable name? ")) {
                   3152:                if ((where = maclook(name)) == NULL) {
                   3153:                        if (arg == 0) return(0);
                   3154:                        where = name;
                   3155:                        hash = 0;
                   3156:                        while (*where) hash += *where++;
                   3157:                        hash = hash %NMAC;
                   3158:                        pshchr(machash[hash]);
                   3159:                        pshchr(machash[hash]>>8);
                   3160:                        machash[hash] = macptr-2;
                   3161:                        where = name;
                   3162:                        pshchr(0);
                   3163:                        while (*where) pshchr(*where++);
                   3164:                        pshchr(0);
                   3165:                        for (size=0; size<sizeof(size); size++) pshchr(0);
                   3166:                        where = maclook(name);
                   3167:                }
                   3168:                switch(arg) {
                   3169: 
                   3170:                case 0:
                   3171:                        return(1);
                   3172:                        break;
                   3173:                case 1:
                   3174:                        hash = 0;
                   3175:                        for (size=0; size<sizeof(size); size++) {
                   3176:                                hash+= ((*where++)&0377) << (size*8);
                   3177:                        }
                   3178:                        return(hash);
                   3179:                case 2:
                   3180:                        hash = edit(0);
                   3181:                        for (size=0; size<sizeof(size); size++) {
                   3182:                                *where++ = hash;
                   3183:                                hash = hash >>8;
                   3184:                        }
                   3185:                        break;
                   3186:                }
                   3187:        }
                   3188:        return(0);
                   3189: }
                   3190: /* envexp -- expand environment variables in a string */
                   3191: 
                   3192: /* expansion takes place in the caller's string buffer */
                   3193: /* pointer is returned for convenience only */
                   3194: 
                   3195: char *pwpath = "/etc/passwd";
                   3196: 
                   3197: char *
                   3198: expenv(str)
                   3199: register char *str;
                   3200: /* Keywords: environment-variables unix-interface user-interface:20 shell-escape:10 */
                   3201: {
                   3202:        char strtemp[128];
                   3203:        char vartemp [64];
                   3204:        register char *cp1;
                   3205:        char *cp2;
                   3206:        register int c;
                   3207:        int oc;
                   3208:        
                   3209:        if (str == NULL) return(NULL);
                   3210:                
                   3211:        cp1 = strtemp;
                   3212:        cp2 = str;
                   3213:        while (*cp1++ = *str) {
                   3214:                if ((*str== '`')||(*str=='*')||(*str=='{')||(*str=='[')||((*str++)=='?')) {
                   3215:                        seprintf(strtemp,"exec echo %s",cp2);
                   3216:                        unx(strtemp,4);                 /* expand through the shell */
                   3217:                        return(fnbuf);
                   3218:                }
                   3219:        }
                   3220:        cp1 = strtemp;
                   3221:        str = fnbuf;                    /* always copy back into file name */
                   3222:        while (c = *cp1++) {
                   3223:                if ((c == '$') || (c == '~')) {
                   3224: 
                   3225: /* Environment variable or `logdir` */
                   3226:                        
                   3227:                        oc = c;
                   3228:                        cp2 = vartemp;
                   3229:                        while (bits[c=((*cp1++)&0377)]&WRDCHR) {
                   3230:                                *cp2++ = c;
                   3231:                        }
                   3232:                        cp1--;          /* backspace pointer */
                   3233:                        *cp2 = 0;
                   3234:                        if (oc == '$') {
                   3235:                                cp2 = getenv(vartemp); /* environment variable */
                   3236:                        } else {
                   3237: #ifndef PC
                   3238: /* Home Directory */
                   3239:                        
                   3240:                                if (*vartemp == 0) {
                   3241:                                        cp2 = getenv("HOME"); /* Bare ~ means home */
                   3242:                                } else if (streq(vartemp,"EMACS")) {
                   3243:                                        cp2 = em_dir;
                   3244:                                } else if (streq(vartemp,"exptools") &&
                   3245:                                        (cp2 = getenv("TOOLS")) && *cp2) {
                   3246:                                        ;
                   3247:                                } else {
                   3248:                                        FILE pwfile[1];
                   3249:                                        FILE *pwptr;
                   3250:                                        char *vp;
                   3251:                                        
                   3252:                                        cp2 = NULL;
                   3253:                                        pwptr = xopen(pwfile,pwpath,"r");
                   3254:                                        if (pwptr) {
                   3255:                                                while ((c = getc(pwptr))!= EOF) {
                   3256:                                                        if (c == '\n') {
                   3257:                                                                vp = vartemp;
                   3258: /* Try to match the specified user ID */
                   3259:                                                                while (*vp++ == (c = getc(pwptr)));
                   3260:                                                                if ((vp[-1] == 0) && (c == ':')) {
                   3261: /* Found it, now skip 4 colons, and copy next field into vartemp; */
                   3262:                                                                        c = 0;
                   3263:                                                                        while (c < 4) if (getc(pwptr) == ':') c++;
                   3264:                                                                        cp2 = vartemp;
                   3265:                                                                        while ((c = getc(pwptr)) != ':') *cp2++=c;
                   3266:                                                                        *cp2++=0;
                   3267:                                                                        cp2=vartemp;
                   3268:                                                                        break; /* Break out of password scan */
                   3269:                                                                }
                   3270:                                                        }
                   3271:                                                }
                   3272:                                                mclose(pwptr);
                   3273:                                        } else error(WARN,errno,pwpath);
                   3274:                                }
                   3275: #endif PC
                   3276:                        }
                   3277:                        if (cp2 != NULL) {      
                   3278:                                str = mstrcpy(str,cp2);
                   3279:                        } else {
                   3280:                                *str++ = oc;
                   3281:                                str = mstrcpy(str,vartemp);
                   3282:                        }
                   3283:                } else {
                   3284:                        *str++ = c;
                   3285:                }
                   3286:        }
                   3287:        *str++ = 0;
                   3288:        return(fnbuf);
                   3289: }
                   3290: /*
                   3291:  * envget      takes a string and expands it into the string
                   3292:  *             stored in the shell variable by the same name.
                   3293:  *             If the shell variable did not exist, then envget
                   3294:  *             returns NULL.
                   3295:  */
                   3296: 
                   3297: envget()
                   3298: /* Keywords: commands environment-variables */
                   3299: 
                   3300: {
                   3301:        char * ptr;
                   3302:        
                   3303:        if (ptr = getenv(getname("Environment variable: ")))  {
                   3304:                stkstr(ptr);
                   3305:                return(1);
                   3306:        }
                   3307:        else {
                   3308:                stkstr("");
                   3309:                return(0);
                   3310:        }
                   3311: }
                   3312: 
                   3313: stopjob ()
                   3314: {
                   3315:        char x;
                   3316:        clear();
                   3317:        cook();
                   3318: #if (defined (bsd) || defined (v8))
                   3319:        kill(mypid,SIGSTOP);
                   3320: #else
                   3321:        eprintf ("Type ^Z to suspend emacs and <return> to continue");
                   3322:        read(0,&x,1);
                   3323: #endif
                   3324:        uncook();
                   3325:        clear();
                   3326: }
                   3327: 
                   3328: #ifdef u370
                   3329: beepbeep()
                   3330: {
                   3331:        extern int beep();
                   3332: }
                   3333: #endif
                   3334: 

unix.superglobalmegacorp.com

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