home *** CD-ROM | disk | FTP | other *** search
/ Source Code 1992 March / Source_Code_CD-ROM_Walnut_Creek_March_1992.iso / usenet / altsrcs / 3 / 3497 < prev    next >
Internet Message Format  |  1991-06-19  |  56KB

  1. From: pgf@cayman.COM (Paul Fox)
  2. Newsgroups: alt.sources
  3. Subject: Vile 11/17 - vi feel-alike (multi-window)
  4. Message-ID: <4530@cayman.COM>
  5. Date: 7 Jun 91 22:09:58 GMT
  6.  
  7. #!/bin/sh
  8. # this is vileshar.11 (part 11 of Vile)
  9. # do not concatenate these parts, unpack them in order with /bin/sh
  10. # file news.cps continued
  11. #
  12. if test ! -r _shar_seq_.tmp; then
  13.     echo 'Please unpack part 1 first!'
  14.     exit 1
  15. fi
  16. (read Scheck
  17.  if test "$Scheck" != 11; then
  18.     echo Please unpack part "$Scheck" next!
  19.     exit 1
  20.  else
  21.     exit 0
  22.  fi
  23. ) < _shar_seq_.tmp || exit 1
  24. echo 'x - continuing file news.cps'
  25. sed 's/^X//' << 'SHAR_EOF' >> 'news.cps' &&
  26. X
  27. X    /prefix_flag false def
  28. X    /prefixes 0 string def
  29. X    /normal_prefixes {
  30. X        /prefixes 2 string store
  31. X        prefixes 0 ESC put
  32. X        prefixes 1 CTRLX put
  33. X    } def
  34. X    /no_prefixes {
  35. X        /prefixes 0 string store
  36. X    } def
  37. X    normal_prefixes
  38. X    /prefix? {    % int => flag        (is char in the set?)
  39. X        chartostring prefixes exch search
  40. X        {pop pop pop true}
  41. X        {pop false}
  42. X        ifelse
  43. X    } def
  44. X
  45. X
  46. X    /times 128 array def        % delay times
  47. X    /default_short .4 def        % command time delay
  48. X    /default_long 2. def        % text time delay
  49. X    /normal_times {
  50. X        0 1 31 {times exch default_short put} for
  51. X        32 1 126 {times exch default_long put} for
  52. X        times 127 default_short put
  53. X    } def
  54. X    normal_times
  55. X
  56. X    /immediateon {
  57. X        {0 1 127 {times exch default_short put} for} win send
  58. X        no_prefixes
  59. X    } def
  60. X    /immediateoff {
  61. X        normal_times
  62. X        normal_prefixes
  63. X    } def
  64. X    /local? {    % int => flag    % local display if long
  65. X        times exch get default_long eq
  66. X    } def
  67. X
  68. X
  69. X    /outtimerrefresh {        % seconds => -    refresh timer
  70. X        /outtimer_seconds exch def
  71. X        currentdict /flushevent known {
  72. X            flushevent recallevent
  73. X        } if
  74. X        /flushevent createevent def
  75. X        flushevent dup begin
  76. X            /Name /Flush def
  77. X            /TimeStamp currenttime 
  78. X                outtimer_seconds 60 div add def
  79. X            /Canvas wincanvas def
  80. X        end sendevent
  81. X    } def
  82. X
  83. X
  84. X    % Event handlers.  Routines are invoked with XLocation, YLocation,
  85. X    % and Action on the stack.
  86. X
  87. X    /eventdict dictbegin
  88. X        /LeftMouseButton {    % cutting text
  89. X            /UpTransition eq
  90. X            {    % wipeout
  91. X                /xy_rc win send
  92. X                SPEC addtobuf
  93. X                [exch 3 -1 roll exch (W) ctrl] sendarray
  94. X            }
  95. X            {    % set mark
  96. X                /xy_rc win send
  97. X                SPEC addtobuf
  98. X                [exch 3 -1 roll exch ESC BLANK] sendarray
  99. X                10. outtimerrefresh    % "infinite" wait
  100. X            } ifelse
  101. X        } def
  102. X        /MiddleMouseButton {    % yanking text
  103. X            pop
  104. X            /xy_rc win send
  105. X            SPEC addtobuf
  106. X            [exch 3 -1 roll exch (Y) ctrl] sendarray
  107. X        } def
  108. X        /MouseDragged { pop        % reset "still" timer
  109. X            /yl exch def
  110. X            /xl exch def
  111. X            /mcursorwait win send
  112. X            currentdict /stillevent known {
  113. X                stillevent recallevent
  114. X            } if
  115. X            /stillevent createevent def
  116. X            stillevent dup begin
  117. X                /Name /MouseStill def
  118. X                /TimeStamp currenttime .5 60 div add def
  119. X                /Canvas wincanvas def
  120. X                /Xl xl def
  121. X                /Yl yl def
  122. X            end sendevent
  123. X        } def
  124. X        /InsertValue {
  125. X            dup length 3 sub 2 exch getinterval cvi
  126. X            [exch] sendarray
  127. X            pop pop
  128. X        } def
  129. X        0 1 127 { dup [exch /asciihandler cvx] cvx def } for
  130. X    dictend def
  131. X
  132. X
  133. X
  134. X    % A restricted set handler names, safe on the command line.
  135. X    /keyeventdict dictbegin
  136. X        /InsertValue dup def
  137. X        0 1 127 { dup [exch /asciihandler cvx] cvx def } for
  138. X    dictend def
  139. X
  140. X
  141. X
  142. X    % ordinary character handler (called with Xl, Yl, Action, and code).
  143. X    /asciihandler {
  144. X        /ascii_code exch def pop pop pop
  145. X        prefix_flag
  146. X        {    /prefix_flag false store
  147. X            ascii_code addtobuf
  148. X            default_short outtimerrefresh }
  149. X        {
  150. X            ascii_code prefix?
  151. X            {    /prefix_flag true store
  152. X                ascii_code addtobuf
  153. X                default_long outtimerrefresh }
  154. X            {    ascii_code dup local?
  155. X                    {dup /writechar win send} if
  156. X                addtobuf
  157. X                times ascii_code get outtimerrefresh
  158. X            } ifelse
  159. X            
  160. X        } ifelse
  161. X    } def
  162. X
  163. X
  164. X
  165. X    % Send an array of characters to the remote process.
  166. X    /sendarray {        % [(A) ascii (B) ascii] => -
  167. X        {addtobuf} forall
  168. X        default_short outtimerrefresh
  169. X    } def
  170. X
  171. X
  172. X    % Output buffer (accumulate stuff to send to the remote machine).
  173. X    /Outbufdict dictbegin
  174. X        /outbuf 1000 string def
  175. X        /bufindex 0 def
  176. X    dictend def
  177. X
  178. X    /addtobuf {        % int => -    % Add a character
  179. X        Outbufdict begin
  180. X            outbuf bufindex 3 -1 roll put
  181. X            /bufindex bufindex 1 add store
  182. X        end
  183. X    } def
  184. X    /clearbuf {
  185. X        Outbufdict begin
  186. X            /bufindex 0 store
  187. X        end
  188. X    } def
  189. X    /getbuf {
  190. X        Outbufdict begin
  191. X            outbuf 0 bufindex getinterval
  192. X        end
  193. X    } def
  194. X
  195. X
  196. X    % Get a string from the user
  197. X    /getstring {        % - => array
  198. X        createevent dup begin
  199. X            /Name /Flush def
  200. X            /Canvas wincanvas def
  201. X        end expressinterest
  202. X    
  203. X        {    awaitevent pop
  204. X            getbuf
  205. X            dup length 0 gt {
  206. X                clearbuf
  207. X                exit
  208. X            } if
  209. X            pop
  210. X        } loop
  211. X    } def
  212. X
  213. X
  214. X
  215. X    % Start her up.
  216. X    {    reshapefromuser
  217. X        trimwindow
  218. X        initwindow
  219. X        ColorDisplay? setcoloring
  220. X        0 1 LastRow {Image exch Cols string put} for
  221. X        starteventtraps
  222. X        cls map
  223. X    } win send
  224. SHAR_EOF
  225. echo 'File news.cps is complete' &&
  226. chmod 0444 news.cps ||
  227. echo 'restore of news.cps failed'
  228. Wc_c="`wc -c < 'news.cps'`"
  229. test 19928 -eq "$Wc_c" ||
  230.     echo 'news.cps: original size 19928, current size' "$Wc_c"
  231. # ============= npopen.c ==============
  232. echo 'x - extracting npopen.c (Text)'
  233. sed 's/^X//' << 'SHAR_EOF' > 'npopen.c' &&
  234. /*    npopen:  like popen, but grabs stderr, too    */
  235. /*        written by John Hutchinson, heavily modified by Paul Fox */
  236. X
  237. #include <stdio.h>
  238. #include "estruct.h"
  239. #include "edef.h"
  240. X
  241. #if UNIX
  242. X
  243. #include <sys/signal.h>
  244. #include <errno.h>
  245. #include <sys/param.h>
  246. X
  247. #if BSD
  248. #define strrchr rindex
  249. #endif
  250. X
  251. #define R 0
  252. #define W 1
  253. X
  254. extern char *getenv();
  255. extern char *strrchr();
  256. X
  257. static int pid;
  258. X
  259. FILE *
  260. npopen (cmd, type)
  261. char *cmd, *type;
  262. {
  263. X    FILE *fr, *fw;
  264. X
  265. X    if (*type != 'r' && *type != 'w')
  266. X        return NULL;
  267. X
  268. X    if (inout_popen(&fr, &fw, cmd) != TRUE)
  269. X        return NULL;
  270. X
  271. X    if (*type == 'r')
  272. X        return fr;
  273. X    else
  274. X        return fw;
  275. }
  276. X
  277. inout_popen(fr, fw, cmd)
  278. FILE **fr, **fw;
  279. char *cmd;
  280. {
  281. X    int tries = 5;
  282. X    unsigned slp = 1;
  283. X    int rp[2];
  284. X    int wp[2];
  285. X    char *sh, *shname;
  286. X    
  287. X
  288. X    if (pipe(rp))
  289. X        return FALSE;
  290. X    if (pipe(wp))
  291. X        return FALSE;
  292. X        
  293. X    /* Try & fork 5 times, backing off 1, 2, 4 .. seconds each try */
  294. X    while ((pid = fork ()) < 0) {
  295. X        if (--tries == 0)
  296. X            return FALSE;
  297. X        (void) sleep (slp);
  298. X        slp <<= 1;
  299. X    }
  300. X
  301. X    if (pid) { /* parent */
  302. X
  303. X        *fr = fdopen (rp[0], "r");
  304. X        setbuf(*fr,NULL);
  305. X        (void) close (rp[1]);
  306. X
  307. X        *fw = fdopen (wp[1], "w");
  308. X        setbuf(*fw,NULL);
  309. X        (void) close (wp[0]);
  310. X        return TRUE;
  311. X
  312. X    } else {            /* child */
  313. X        int i;
  314. X
  315. X        (void)close (1);
  316. X        if (dup (rp[1]) != 1)
  317. X            exit(-1);
  318. X        (void)close (2);
  319. X        if (dup (rp[1]) != 2)
  320. X            exit(-1);
  321. X        (void)close (0);
  322. X        if (dup (wp[0]) != 0)
  323. X            exit(-1);
  324. X            
  325. X        /* Make sure there are no inherited file descriptors */
  326. X        for (i = 3; i < NOFILE; i += 1)
  327. X            (void) close (i);
  328. X
  329. #if ! MY_EXEC
  330. X            if ((sh = getenv("SHELL")) == NULL || *sh == '\0') {
  331. X            sh = "/bin/sh";
  332. X            shname = "sh";
  333. X        } else {
  334. X            shname = strrchr(sh,'/');
  335. X            if (shname == NULL)
  336. X                shname = sh;
  337. X            else {
  338. X                shname++;
  339. X                if (*shname == '\0')
  340. X                    shname = sh;
  341. X            }
  342. X        }
  343. X        (void) execl (sh, shname, "-c", cmd, 0);
  344. #else
  345. X        my_exec(cmd);
  346. #endif
  347. X        exit (-1);
  348. X
  349. X    }
  350. X    return TRUE;
  351. }
  352. X
  353. npclose (fp)
  354. FILE *fp;
  355. {
  356. X    fflush(fp);
  357. X    fclose(fp);
  358. X    if (wait ((int *)0) < 0 && errno == EINTR) {
  359. X        (void) kill (SIGKILL, pid);
  360. X    }
  361. X    return 0;
  362. }
  363. X
  364. #if MY_EXEC
  365. X
  366. static
  367. my_exec (cmd)
  368. register char *cmd;
  369. {
  370. X    char *argv [256];
  371. X    register char **argv_p, *cp;
  372. X    
  373. X        if ((argv[0] = getenv("SHELL")) == NULL || argv[0][0] == '\0') {
  374. X        argv[0] = "/bin/sh";
  375. X        argv[1] = "sh";
  376. X    } else {
  377. X        argv[1] = strrchr(argv[0]);
  378. X        if (argv[1] == NULL) {
  379. X            argv[1] = argv[0];
  380. X        } else {
  381. X            argv[1]++;
  382. X            if (argv[1][0] == '\0')
  383. X                argv[1] = argv[0];
  384. X        }
  385. X    }
  386. X    argv[2] = "-c";
  387. X
  388. X    argv_p = &argv[3];
  389. X
  390. X    cp = cmd;
  391. X    /* Scan up cmd, splitting arguments into argv. This is the
  392. X     * child, so we can zap things in cmd safely */
  393. X    
  394. X    while (*cp) {
  395. X        /* Skip any white space */
  396. X        while (*cp && isspace(*cp))
  397. X            cp++;
  398. X        if (!*cp)
  399. X            break;
  400. X        *argv_p++ = cp;
  401. X        while (*cp && !isspace(*cp))
  402. X            cp++;
  403. X        if (!*cp)
  404. X            break;
  405. X        *cp++ = '\0';
  406. X    }
  407. X    *argv_p = NULL;
  408. X    execv (argv[0], &argv[1]);
  409. }
  410. #endif
  411. X
  412. #else
  413. npopenhello() {}
  414. #endif
  415. SHAR_EOF
  416. chmod 0444 npopen.c ||
  417. echo 'restore of npopen.c failed'
  418. Wc_c="`wc -c < 'npopen.c'`"
  419. test 2848 -eq "$Wc_c" ||
  420.     echo 'npopen.c: original size 2848, current size' "$Wc_c"
  421. # ============= oneliner.c ==============
  422. echo 'x - extracting oneliner.c (Text)'
  423. sed 's/^X//' << 'SHAR_EOF' > 'oneliner.c' &&
  424. #include    "estruct.h"
  425. #include        "edef.h"
  426. #include        <stdio.h>
  427. X
  428. /*
  429. X    a few functions that operate on single whole lines, mostly
  430. X    here to support the globals() function
  431. X    These could be turned into operators, but they're either not
  432. X    worth it, or a bit tricky
  433. X    written (except for delins()) for vile by Paul Fox, (c)1990
  434. */
  435. X
  436. #define PLIST    0x01
  437. X
  438. /*
  439. X * put lines in a popup window
  440. X */
  441. pregion(f, n, flag)
  442. {
  443. X    register WINDOW *wp;
  444. X    register BUFFER *bp;
  445. X        register int    s;
  446. X        REGION          region;
  447. X    static char bname[] = "[p-lines]";
  448. X    register LINE *linep;
  449. X    int cb;
  450. X
  451. X    fulllineregions = TRUE;
  452. X        
  453. X        if ((s=getregion(®ion,NULL)) != TRUE)
  454. X                return (s);
  455. X
  456. X        linep = region.r_linep;                 /* Current line.        */
  457. X        
  458. X    /* first check if we are already here */
  459. X    bp = bfind(bname, OK_CREAT, 0);
  460. X    if (bp == NULL)
  461. X        return FALSE;
  462. X
  463. X    /* bring p-lines up */
  464. X    if (popupbuff(bp) != TRUE)
  465. X        return FALSE;
  466. X        
  467. X    if (!calledbefore) {        /* fresh start */
  468. X        bclear(bp);
  469. X        if (flag & PLIST)
  470. X            bp->b_mode |= MDLIST;
  471. X        else
  472. X            bp->b_mode &= ~MDLIST;
  473. X        calledbefore = TRUE;
  474. X    }
  475. X    
  476. X    do {
  477. X        addline(bp,linep->l_text,llength(linep));
  478. X        linep = lforw(linep);
  479. X        } while (linep != region.r_endlinep);
  480. X
  481. X    bp->b_flag &= ~BFCHG;
  482. X    
  483. X    strcpy(bp->b_bname,bname);
  484. X    strcpy(bp->b_fname, "");
  485. X    bp->b_mode |= MDVIEW;
  486. X    bp->b_active = TRUE;
  487. X        for (wp=wheadp; wp!=NULL; wp=wp->w_wndp) {
  488. X                if (wp->w_bufp == bp) {
  489. X                        wp->w_flag |= WFMODE|WFFORCE;
  490. X                }
  491. X        }
  492. X    return TRUE;
  493. }
  494. X
  495. llineregion(f,n)
  496. {
  497. X    return pregion(f,n,PLIST);
  498. }
  499. X
  500. plineregion(f,n)
  501. {
  502. X    return pregion(f,n,0);
  503. }
  504. X
  505. substregion(f,n)
  506. {
  507. X    int c, s;
  508. X    int foundit;
  509. X    static int printit, globally;
  510. X    REGION region;
  511. X
  512. X    fulllineregions = TRUE;
  513. X        
  514. X        if ((s=getregion(®ion,NULL)) != TRUE)
  515. X                return (s);
  516. X
  517. X    c = '\n';
  518. X    if (isnamedcmd) {
  519. X        c = tpeekc();
  520. X        if (c < 0) {
  521. X            c = '\n';
  522. X        } else {
  523. X            if (ispunct(c)) {
  524. X                (void)kbd_key();
  525. X            }
  526. X        }
  527. X    }
  528. X    if (calledbefore == FALSE) {
  529. X        if ((s = readpattern("substitute pattern: ", &pat[0], TRUE, c,
  530. X                FALSE)) != TRUE) {
  531. X            if (s != ABORT)
  532. X                mlwrite("No pattern.");
  533. X            return FALSE;
  534. X        }
  535. X        if ((s = readpattern("replacement string: ", &rpat[0], FALSE, c,
  536. X                FALSE)) != TRUE) {
  537. X            if (s == ABORT)
  538. X                return FALSE;
  539. X            /* else the pattern is null, which is okay... */
  540. X        }
  541. X        if (lastkey == c) {/* the user may have something to add */
  542. X            char buf[3];
  543. X            char *bp = buf;
  544. X            buf[0] = 0;
  545. X            mlreply("(g)lobally on line and/or (p)rint result: ",
  546. X                buf, sizeof buf);
  547. X            printit = globally = FALSE;
  548. X            while (*bp) {
  549. X                if (*bp == 'p' && !printit)
  550. X                    printit = TRUE;
  551. X                else if (*bp == 'g' && !globally)
  552. X                    globally = TRUE;
  553. X                else if (!isspace(*bp)) {
  554. X                    mlwrite("Unknown action %s",buf);
  555. X                    return FALSE;
  556. X                }
  557. X                bp++;
  558. X            }
  559. X        }
  560. X        calledbefore = TRUE;
  561. X    }
  562. X
  563. X
  564. X        curwp->w_dotp = region.r_linep;                 /* Current line.        */
  565. X
  566. X    do {
  567. X        foundit = FALSE;
  568. X        setboundry(TRUE, curwp->w_dotp, llength(curwp->w_dotp), FORWARD);
  569. X        curwp->w_doto = 0;
  570. X        do {
  571. #if    MAGIC
  572. X            if (magical && (curwp->w_bufp->b_mode & MDMAGIC) != 0)
  573. X                s = thescanner(&mcpat[0], FORWARD, PTBEG, TRUE);
  574. X            else
  575. #endif
  576. X                s = thescanner(&pat[0], FORWARD, PTBEG, TRUE);
  577. X            if (s != TRUE)
  578. X                break;
  579. X                
  580. X            /* found the pattern */
  581. X            foundit = TRUE;
  582. X            s = delins(matchlen, &rpat[0]);
  583. X            if (s != TRUE)
  584. X                return s;
  585. X            if (boundry(curwp->w_dotp, curwp->w_doto))
  586. X                break;
  587. X        } while (globally);
  588. X        if (foundit && printit) {
  589. X            setmark();
  590. X            s = plineregion(FALSE,1);
  591. X            if (s != TRUE) return s;
  592. X        }
  593. X        curwp->w_dotp = lforw(curwp->w_dotp);
  594. X    } while (curwp->w_dotp != region.r_endlinep);
  595. X    return TRUE;
  596. }
  597. X
  598. /*
  599. X * delins -- Delete a specified length from the current
  600. X *    point, then insert the string.
  601. X *  borrowed from original replaces() code 
  602. X */
  603. delins(dlength, instr)
  604. int    dlength;
  605. char    *instr;
  606. {
  607. X    int    status;
  608. X    char    tmpc;
  609. X
  610. X    /* Zap what we gotta,
  611. X     * and insert its replacement.
  612. X     */
  613. X    if (!(status = ldelete((long) dlength, FALSE))) {
  614. X        mlwrite("Error while deleting");
  615. X        return FALSE;
  616. X    } else {
  617. X        while (tmpc = *instr) {
  618. X            status = (tmpc == '\n'? lnewline(): linsert(1, tmpc));
  619. X            if (!status) {
  620. X                mlwrite("Out of memory while inserting");
  621. X                break;
  622. X            }
  623. X            instr++;
  624. X        }
  625. X    }
  626. X    return status;
  627. }
  628. SHAR_EOF
  629. chmod 0444 oneliner.c ||
  630. echo 'restore of oneliner.c failed'
  631. Wc_c="`wc -c < 'oneliner.c'`"
  632. test 4253 -eq "$Wc_c" ||
  633.     echo 'oneliner.c: original size 4253, current size' "$Wc_c"
  634. # ============= opers.c ==============
  635. echo 'x - extracting opers.c (Text)'
  636. sed 's/^X//' << 'SHAR_EOF' > 'opers.c' &&
  637. /*
  638. X * This file contains the command processing functions for the commands
  639. X * that take motion operators.
  640. X * written for vile by Paul Fox, (c)1990
  641. X */
  642. X
  643. #include    "estruct.h"
  644. #include        "edef.h"
  645. #ifndef NULL
  646. #define NULL 0
  647. #endif
  648. X
  649. extern CMDFUNC f_godotplus;
  650. X
  651. /* For the "operator" commands -- the following command is a motion, or
  652. X *  the operator itself is repeated.  All operate on regions.
  653. X */
  654. operator(f,n,fn,str)
  655. int (*fn)();
  656. char *str;
  657. {
  658. X    int c;
  659. X    int this1key;
  660. X    int status;
  661. X    CMDFUNC *cfp;            /* function to execute */
  662. X    char tok[NSTRING];        /* command incoming */
  663. X    LINE *ourmarkp;
  664. X    int ourmarko;
  665. X
  666. X    doingopcmd = TRUE;
  667. X
  668. X        ourmarkp = curwp->w_dotp;
  669. X        ourmarko = curwp->w_doto;
  670. X
  671. X    if (havemotion != NULL) {
  672. X        cfp = havemotion;
  673. X        havemotion = NULL;
  674. X    } else {
  675. X        mlwrite("%s operation pending...",str);
  676. X        update(FALSE);
  677. X
  678. X        /* get the next command from the keyboard */
  679. X        /* or a command line, as approp. */
  680. X        if (clexec) {
  681. X            macarg(tok);    /* get the next token */
  682. X            if (!strcmp(tok,"lines"))
  683. X                cfp = &f_godotplus;
  684. X            else
  685. X                cfp = engl2fnc(tok);
  686. X        } else {
  687. X            this1key = last1key;
  688. X            c = kbd_seq();
  689. X
  690. X            /* allow second chance for entering counts */
  691. X            if (f == FALSE) {
  692. X                do_num_proc(&c,&f,&n);
  693. X                do_rept_arg_proc(&c,&f,&n);
  694. X            }
  695. X
  696. X            if (this1key == last1key)
  697. X                cfp = &f_godotplus;
  698. X            else
  699. X                cfp = kcod2fnc(c);
  700. X
  701. X        }
  702. X        mlerase();
  703. X    }
  704. X
  705. X    if ((cfp->c_flags & MOTION) == 0) {
  706. X        TTbeep();
  707. X        return(ABORT);
  708. X    }
  709. X
  710. X    /* motion is interpreted as affecting full lines */
  711. X    if (cfp->c_flags & FL)
  712. X        fulllineregions = TRUE;
  713. X
  714. X    /* and execute the motion */
  715. X    status = execute(cfp, f, n);
  716. X
  717. X    if (status != TRUE || 
  718. X       ( (ourmarkp == curwp->w_dotp && ourmarko == curwp->w_doto) &&
  719. X            fulllineregions == FALSE) ) {
  720. X        doingopcmd = FALSE;
  721. X        fulllineregions = FALSE;
  722. X        return status;
  723. X    }
  724. X
  725. X    opcmd = 0;
  726. X
  727. X    curwp->w_mkp = ourmarkp;
  728. X    curwp->w_mko = ourmarko;
  729. X
  730. X    /* we've successfully set up a region */
  731. X    if (!fn) { /* be defensive */
  732. X        mlwrite("BUG -- null func pointer in operator");
  733. X        status = FALSE;
  734. X    } else {
  735. X        status = (fn)(f,n,NULL,NULL);
  736. X    }
  737. X
  738. X    swapmark();
  739. X
  740. X    if (fulllineregions) {
  741. X        fulllineregions = FALSE;
  742. X        firstnonwhite(f,n);
  743. X    }
  744. X
  745. X    doingopcmd = FALSE;
  746. X    return status;
  747. }
  748. X
  749. operdel(f,n)
  750. {
  751. X    extern int killregion();
  752. X
  753. X    opcmd = OPDEL;
  754. X    return operator(f,n,killregion,"Delete");
  755. }
  756. X
  757. operlinedel(f,n)
  758. {
  759. X    extern int killregion();
  760. X
  761. X    fulllineregions = TRUE;
  762. X    opcmd = OPDEL;
  763. X    return operator(f,n,killregion,"Delete of full lines");
  764. }
  765. X
  766. chgreg(f,n)
  767. {
  768. X    killregion(f,n);
  769. X    if (fulllineregions) {
  770. X        backline(FALSE,1);
  771. X        opendown(TRUE,1);
  772. X    } else {
  773. X        insert(f,n);
  774. X    }
  775. }
  776. X
  777. operchg(f,n)
  778. {
  779. X    int s;
  780. X
  781. X    opcmd = OPOTHER;
  782. X    s = operator(f,n,chgreg,"Change");
  783. X    swapmark();
  784. X    return s;
  785. }
  786. X
  787. operlinechg(f,n)
  788. {
  789. X    int s;
  790. X
  791. X    fulllineregions = TRUE;
  792. X    opcmd = OPOTHER;
  793. X    s = operator(f,n,chgreg,"Change of full lines");
  794. X    swapmark();
  795. X    return s;
  796. }
  797. X
  798. operyank(f,n)
  799. {
  800. X    extern int yankregion();
  801. X    opcmd = OPOTHER;
  802. X    return operator(f,n,yankregion,"Yank");
  803. }
  804. X
  805. operlineyank(f,n)
  806. {
  807. X    extern int yankregion();
  808. X
  809. X    fulllineregions = TRUE;
  810. X    opcmd = OPOTHER;
  811. X    return operator(f,n,yankregion,"Yank of full lines");
  812. }
  813. X
  814. operflip(f,n)
  815. {
  816. X    extern int flipregion();
  817. X
  818. X    opcmd = OPOTHER;
  819. X    return operator(f,n,flipregion,"Flip case");
  820. }
  821. X
  822. operupper(f,n)
  823. {
  824. X    extern int upperregion();
  825. X
  826. X    opcmd = OPOTHER;
  827. X    return operator(f,n,upperregion,"Upper case");
  828. }
  829. X
  830. operlower(f,n)
  831. {
  832. X    extern int lowerregion();
  833. X
  834. X    opcmd = OPOTHER;
  835. X    return operator(f,n,lowerregion,"Lower case");
  836. }
  837. X
  838. X
  839. operlshift(f,n)
  840. {
  841. X    extern int shiftlregion();
  842. X
  843. X    fulllineregions = TRUE;
  844. X    opcmd = OPOTHER;
  845. X    return operator(f,n,shiftlregion,"Left shift");
  846. }
  847. X
  848. operrshift(f,n)
  849. {
  850. X    extern int shiftrregion();
  851. X
  852. X    fulllineregions = TRUE;
  853. X    opcmd = OPOTHER;
  854. X    return operator(f,n,shiftrregion,"Right shift");
  855. }
  856. X
  857. operwrite(f,n)
  858. {
  859. X        register int    s;
  860. X        static char fname[NFILEN];
  861. X    extern int writeregion();
  862. X
  863. X    if (ukb != 0) {
  864. X            if ((s=mlreply("Write to file: ", fname, NFILEN)) != TRUE)
  865. X                    return s;
  866. X        return kwrite(fname,TRUE);
  867. X    } else {
  868. X        opcmd = OPOTHER;
  869. X        return operator(f,n,writeregion,"File write");
  870. X    }
  871. }
  872. X
  873. operformat(f,n)
  874. {
  875. X    extern int formatregion();
  876. X
  877. X    fulllineregions = TRUE;
  878. X    opcmd = OPOTHER;
  879. X    return operator(f,n,formatregion,"Format");
  880. }
  881. X
  882. operfilter(f,n)
  883. {
  884. X    extern int filterregion();
  885. X
  886. X    fulllineregions = TRUE;
  887. X    opcmd = OPOTHER;
  888. X    return operator(f,n,filterregion,"Filter");
  889. }
  890. X
  891. X
  892. operprint(f,n)
  893. {
  894. X    extern int plineregion();
  895. X
  896. X    fulllineregions = TRUE;
  897. X    opcmd = OPOTHER;
  898. X    return operator(f,n,plineregion,"Line print");
  899. }
  900. X
  901. operlist(f,n)
  902. {
  903. X    extern int llineregion();
  904. X
  905. X    fulllineregions = TRUE;
  906. X    opcmd = OPOTHER;
  907. X    return operator(f,n,llineregion,"Line list");
  908. }
  909. X
  910. opersubst(f,n)
  911. {
  912. X    extern int substregion();
  913. X
  914. X    fulllineregions = TRUE;
  915. X    opcmd = OPOTHER;
  916. X    return operator(f,n,substregion,"Substitute");
  917. }
  918. SHAR_EOF
  919. chmod 0444 opers.c ||
  920. echo 'restore of opers.c failed'
  921. Wc_c="`wc -c < 'opers.c'`"
  922. test 4699 -eq "$Wc_c" ||
  923.     echo 'opers.c: original size 4699, current size' "$Wc_c"
  924. # ============= random.c ==============
  925. echo 'x - extracting random.c (Text)'
  926. sed 's/^X//' << 'SHAR_EOF' > 'random.c' &&
  927. /*
  928. X * This file contains the command processing functions for a number of random
  929. X * commands. There is no functional grouping here, for sure.
  930. X */
  931. X
  932. #include        <stdio.h>
  933. #include    "estruct.h"
  934. #include        "edef.h"
  935. X
  936. showgmodes(f,n)
  937. {
  938. X    return showm(TRUE);
  939. }
  940. X
  941. showmodes(f,n)
  942. {
  943. X    return showm(FALSE);
  944. }
  945. X
  946. showm(g)
  947. {
  948. X    char modes[100];
  949. X    int gotmode = FALSE;
  950. X    int i,b;
  951. X
  952. X    modes[0] = '\0';
  953. X    for (i = 0; i < NUMMODES; i++) { /* add in the mode flags */
  954. X        b = 1 << i;
  955. X        if ((!g && (curbp->b_mode & b)) || (g && (gmode & b))) {
  956. X            gotmode = TRUE;
  957. X        } else {
  958. X            strcat(modes, "no");
  959. X        }
  960. X        strcat(modes, modename[i]);
  961. X        strcat(modes, " ");
  962. X    }
  963. X    if (gotmode == FALSE)
  964. X        mlwrite("No modes set");
  965. X    else
  966. X        mlwrite(modes);
  967. X    return TRUE;
  968. }
  969. X
  970. /*
  971. X * Set fill column to n.
  972. X */
  973. setfillcol(f, n)
  974. {
  975. X    if (f)
  976. X            fillcol = n;
  977. X    mlwrite("[Fill column is %d]",n);
  978. X        return(TRUE);
  979. }
  980. X
  981. /*
  982. X * Display the current position of the cursor, lines and columns, in the file,
  983. X * the character that is under the cursor (in hex), and the fraction of the
  984. X * text that is before the cursor. The displayed column is not the current
  985. X * column, but the column that would be used on an infinite width display.
  986. X */
  987. showcpos(f, n)
  988. {
  989. X        register LINE   *lp;        /* current line */
  990. X        register long   numchars;    /* # of chars in file */
  991. X        register int    numlines;    /* # of lines in file */
  992. X        register long   predchars;    /* # chars preceding point */
  993. X        register int    predlines;    /* # lines preceding point */
  994. X        register int    curchar;    /* character under cursor */
  995. X        int ratio;
  996. X        int col;
  997. X    int savepos;            /* temp save for current offset */
  998. X    int ecol;            /* column pos/end of current line */
  999. X
  1000. X    /* starting at the beginning of the buffer */
  1001. X        lp = lforw(curbp->b_linep);
  1002. X
  1003. X    /* start counting chars and lines */
  1004. X        numchars = 0;
  1005. X        numlines = 0;
  1006. X        while (lp != curbp->b_linep) {
  1007. X        /* if we are on the current line, record it */
  1008. X        if (lp == curwp->w_dotp) {
  1009. X            predlines = numlines;
  1010. X            predchars = numchars + curwp->w_doto;
  1011. X            if ((curwp->w_doto) == llength(lp))
  1012. X                curchar = '\n';
  1013. X            else
  1014. X                curchar = lgetc(lp, curwp->w_doto);
  1015. X        }
  1016. X        /* on to the next line */
  1017. X        ++numlines;
  1018. X        numchars += llength(lp) + 1;
  1019. X        lp = lforw(lp);
  1020. X        }
  1021. X
  1022. X    /* if at end of file, record it */
  1023. X    if (curwp->w_dotp == curbp->b_linep) {
  1024. X        predlines = numlines;
  1025. X        predchars = numchars;
  1026. X    }
  1027. X
  1028. X    /* Get real column and end-of-line column. */
  1029. X    col = getccol(FALSE);
  1030. X    savepos = curwp->w_doto;
  1031. X    curwp->w_doto = llength(curwp->w_dotp);
  1032. X    ecol = getccol(FALSE);
  1033. X    curwp->w_doto = savepos;
  1034. X
  1035. X        ratio = 0;              /* Ratio before dot. */
  1036. X        if (numchars != 0)
  1037. X                ratio = (100L*predchars) / numchars;
  1038. X
  1039. X    /* summarize and report the info */
  1040. X    mlwrite(
  1041. "Line %d of %d, Col %d of %d, Char %D of %D (%d%%) char is 0x%x",
  1042. X        predlines+1, numlines, col+1, ecol,
  1043. X        predchars+1, numchars, ratio, curchar);
  1044. X        return TRUE;
  1045. }
  1046. X
  1047. showlength(f,n)
  1048. {
  1049. X        register LINE   *lp;        /* current line */
  1050. X        register int    numlines = 0;    /* # of lines in file */
  1051. X
  1052. X    /* starting at the beginning of the buffer */
  1053. X        lp = lforw(curbp->b_linep);
  1054. X        while (lp != curbp->b_linep) {
  1055. X        ++numlines;
  1056. X        lp = lforw(lp);
  1057. X        }
  1058. X    mlwrite("%d",numlines);
  1059. X    return TRUE;
  1060. }
  1061. X
  1062. #if ! SMALLER
  1063. getcline()    /* get the current line number */
  1064. {
  1065. X        register LINE   *lp;        /* current line */
  1066. X        register int    numlines;    /* # of lines before point */
  1067. X
  1068. X    /* starting at the beginning of the buffer */
  1069. X        lp = lforw(curbp->b_linep);
  1070. X
  1071. X    /* start counting lines */
  1072. X        numlines = 0;
  1073. X        while (lp != curbp->b_linep) {
  1074. X        /* if we are on the current line, record it */
  1075. X        if (lp == curwp->w_dotp)
  1076. X            break;
  1077. X        ++numlines;
  1078. X        lp = lforw(lp);
  1079. X        }
  1080. X
  1081. X    /* and return the resulting count */
  1082. X    return(numlines + 1);
  1083. }
  1084. #endif
  1085. X
  1086. /*
  1087. X * Return current screen column.  Stop at first non-blank given TRUE argument.
  1088. X */
  1089. getccol(bflg)
  1090. int bflg;
  1091. {
  1092. X        register int c, i, col;
  1093. X        col = 0;
  1094. X        for (i=0; i<curwp->w_doto; ++i) {
  1095. X                c = lgetc(curwp->w_dotp, i);
  1096. X                if (c!=' ' && c!='\t' && bflg)
  1097. X                        break;
  1098. X        if (((curwp->w_bufp->b_mode&MDLIST) == 0) && c == '\t')
  1099. X                        col |= TABMASK;
  1100. X                else if (!isprint(c))
  1101. X                        ++col;
  1102. X                ++col;
  1103. X        }
  1104. X        return(col);
  1105. }
  1106. X
  1107. X
  1108. /*
  1109. X * Set current column.
  1110. X */
  1111. gotocol(f,n)
  1112. {
  1113. X        register int c;        /* character being scanned */
  1114. X    register int i;        /* index into current line */
  1115. X    register int col;    /* current cursor column   */
  1116. X    register int llen;    /* length of line in bytes */
  1117. X
  1118. X    col = 0;
  1119. X    llen = llength(curwp->w_dotp);
  1120. X    if ( n <= 0) n = 1;
  1121. X
  1122. X    /* scan the line until we are at or past the target column */
  1123. X    for (i = 0; i < llen; ++i) {
  1124. X        /* upon reaching the target, drop out */
  1125. X        if (col >= n)
  1126. X            break;
  1127. X
  1128. X        /* advance one character */
  1129. X                c = lgetc(curwp->w_dotp, i);
  1130. X        if (((curwp->w_bufp->b_mode&MDLIST) == 0) && c == '\t')
  1131. X                        col |= TABMASK;
  1132. X                else if (!isprint(c))
  1133. X                        ++col;
  1134. X                ++col;
  1135. X        }
  1136. X
  1137. X    /* set us at the new position */
  1138. X    curwp->w_doto = i;
  1139. X
  1140. X    /* and tell whether we made it */
  1141. X    return(col >= n);
  1142. }
  1143. X
  1144. #if ! SMALLER
  1145. /*
  1146. X * Twiddle the two characters on either side of dot. If dot is at the end of
  1147. X * the line twiddle the two characters before it. Return with an error if dot
  1148. X * is at the beginning of line; it seems to be a bit pointless to make this
  1149. X * work. This fixes up a very common typo with a single stroke.
  1150. X * This always works within a line, so "WFEDIT" is good enough.
  1151. X */
  1152. twiddle(f, n)
  1153. {
  1154. X        register LINE   *dotp;
  1155. X        register int    doto;
  1156. X        register int    cl;
  1157. X        register int    cr;
  1158. X
  1159. X        dotp = curwp->w_dotp;
  1160. X        doto = curwp->w_doto;
  1161. X        if (doto==llength(dotp) && --doto<0)
  1162. X                return (FALSE);
  1163. X        cr = lgetc(dotp, doto);
  1164. X        if (--doto < 0)
  1165. X                return (FALSE);
  1166. X        cl = lgetc(dotp, doto);
  1167. X    copy_for_undo(dotp);
  1168. X        lputc(dotp, doto+0, cr);
  1169. X        lputc(dotp, doto+1, cl);
  1170. X        lchange(WFEDIT);
  1171. X        return (TRUE);
  1172. }
  1173. #endif
  1174. X
  1175. /*
  1176. X * Quote the next character, and insert it into the buffer. All the characters
  1177. X * are taken literally, with the exception of the newline, which always has
  1178. X * its line splitting meaning. The character is always read, even if it is
  1179. X * inserted 0 times, for regularity.
  1180. X */
  1181. quote(f, n)
  1182. {
  1183. X        register int    s;
  1184. X        register int    c;
  1185. X
  1186. X        c = tgetc();
  1187. X        if (n < 0)
  1188. X                return (FALSE);
  1189. X        if (n == 0)
  1190. X                return (TRUE);
  1191. X        if (c == '\n') {
  1192. X                do {
  1193. X                        s = lnewline();
  1194. X                } while (s==TRUE && --n);
  1195. X                return (s);
  1196. X        }
  1197. X        return (linsert(n, c));
  1198. }
  1199. X
  1200. replacechar(f, n)
  1201. {
  1202. X        register int    s;
  1203. X        register int    c;
  1204. X
  1205. X    insertmode = TRUE;  /* need to fool the SPEC prefix code */
  1206. X        c = kbd_key();
  1207. X    insertmode = FALSE;
  1208. X
  1209. X        if (n < 0)
  1210. X                return (FALSE);
  1211. X        if (n == 0)
  1212. X                return (TRUE);
  1213. X    if (c == abortc)
  1214. X        return (FALSE);
  1215. X
  1216. X    ldelete((long)n,FALSE);
  1217. X    if (c == quotec) {
  1218. X        return(quote(f,n));
  1219. X    }
  1220. X    c = kcod2key(c);
  1221. X        if (c == '\n' || c == '\r') {
  1222. X                do {
  1223. X                        s = lnewline();
  1224. X                } while (s==TRUE && --n);
  1225. X                return (s);
  1226. X        } else if (isbackspace(c))
  1227. X        s = TRUE;
  1228. X    else
  1229. X        s = linsert(n, c);
  1230. X    if (s == TRUE)
  1231. X        s = backchar(FALSE,1);
  1232. X        return (s);
  1233. }
  1234. X
  1235. /*
  1236. X * Set tab size
  1237. X * for programmer convenience, tabs can only be 2, 4, 8, or 16
  1238. X * a lot of code uses masks, so this was easiest change from the old
  1239. X * hardcoded 8 column tabs
  1240. X */
  1241. settab(f, n)
  1242. {
  1243. X    register WINDOW *wp;
  1244. X    if (f && (n == 2 || n == 4 || n == 8 || n == 16)) {
  1245. X        TABVAL = n;
  1246. X        TABMASK = n-1;
  1247. X        for (wp = wheadp; wp != NULL; wp = wp->w_wndp)
  1248. X            wp->w_flag |= WFHARD;
  1249. X        refresh(FALSE,1);
  1250. X    } else if (f) {
  1251. X        mlwrite("Sorry, tabs must be 2, 4, 8, or 16");
  1252. X        TTbeep();
  1253. X        return FALSE;
  1254. X    }
  1255. X    mlwrite("Tabs are %d columns apart",TABVAL);
  1256. X    return TRUE;
  1257. }
  1258. X
  1259. /* insert a tab into the file */
  1260. tab(f, n)
  1261. {
  1262. X        return(linsert(1, '\t'));
  1263. }
  1264. X
  1265. #if    AEDIT
  1266. detab(f, n)        /* change tabs to spaces */
  1267. int f,n;    /* default flag and numeric repeat count */
  1268. {
  1269. X    register int inc;    /* increment to next line [sgn(n)] */
  1270. X
  1271. X
  1272. X    if (f == FALSE)
  1273. X        n = 1;
  1274. X
  1275. X    /* loop thru detabbing n lines */
  1276. X    inc = ((n > 0) ? 1 : -1);
  1277. X    while (n) {
  1278. X        curwp->w_doto = 0;    /* start at the beginning */
  1279. X
  1280. X        /* detab the entire current line */
  1281. X        while (curwp->w_doto < llength(curwp->w_dotp)) {
  1282. X            /* if we have a tab */
  1283. X            if (lgetc(curwp->w_dotp, curwp->w_doto) == '\t') {
  1284. X                ldelete(1L, FALSE);
  1285. X                insspace(TRUE, TABVAL - (curwp->w_doto & TABMASK));
  1286. X            }
  1287. X            forwchar(FALSE, 1);
  1288. X        }
  1289. X
  1290. X        /* advance/or back to the next line */
  1291. X        forwline(TRUE, inc);
  1292. X        n -= inc;
  1293. X    }
  1294. X    curwp->w_doto = 0;    /* to the begining of the line */
  1295. X    curgoal = -1;
  1296. X    lchange(WFEDIT);    /* yes, we have made at least an edit */
  1297. X    return(TRUE);
  1298. }
  1299. X
  1300. entab(f, n)        /* change spaces to tabs where posible */
  1301. int f,n;    /* default flag and numeric repeat count */
  1302. {
  1303. X    register int inc;    /* increment to next line [sgn(n)] */
  1304. X    register int fspace;    /* pointer to first space if in a run */
  1305. X    register int ccol;    /* current cursor column */
  1306. X    register char cchar;    /* current character */
  1307. X
  1308. X
  1309. X    if (f == FALSE)
  1310. X        n = 1;
  1311. X
  1312. X    /* loop thru entabbing n lines */
  1313. X    inc = ((n > 0) ? 1 : -1);
  1314. X    while (n) {
  1315. X        curwp->w_doto = 0;    /* start at the beginning */
  1316. X
  1317. X        /* entab the entire current line */
  1318. X        fspace = -1;
  1319. X        ccol = 0;
  1320. X        while (curwp->w_doto < llength(curwp->w_dotp)) {
  1321. X            /* see if it is time to compress */
  1322. X            if ((fspace >= 0) && (nextab(fspace) <= ccol))
  1323. X                if (ccol - fspace < 2)
  1324. X                    fspace = -1;
  1325. X                else {
  1326. X        /* there is a bug here dealing with mixed space/tabed
  1327. X           lines.......it will get fixed        */
  1328. X                    backchar(TRUE, ccol - fspace);
  1329. X                    ldelete((long)(ccol - fspace), FALSE);
  1330. X                    linsert(1, '\t');    
  1331. X                    fspace = -1;
  1332. X                }
  1333. X
  1334. X            /* get the current character */
  1335. X            cchar = lgetc(curwp->w_dotp, curwp->w_doto);
  1336. X
  1337. X            switch (cchar) {
  1338. X                case '\t': /* a tab...count em up */
  1339. X                    ccol = nextab(ccol);
  1340. X                    break;
  1341. X
  1342. X                case ' ':  /* a space...compress? */
  1343. X                    if (fspace == -1)
  1344. X                        fspace = ccol;
  1345. X                    ccol++;
  1346. X                    break;
  1347. X
  1348. X                default:   /* any other char...just count */
  1349. X                    ccol++;
  1350. X                    fspace = -1;
  1351. X                    break;
  1352. X            }
  1353. X            forwchar(FALSE, 1);
  1354. X        }
  1355. X
  1356. X        /* advance/or back to the next line */
  1357. X        forwline(TRUE, inc);
  1358. X        n -= inc;
  1359. X    }
  1360. X    curwp->w_doto = 0;    /* to the begining of the line */
  1361. X    curgoal = -1;
  1362. X    lchange(WFEDIT);    /* yes, we have made at least an edit */
  1363. X    return(TRUE);
  1364. }
  1365. X
  1366. #endif
  1367. X
  1368. /* trim trailing whitespace from a line.  leave dot at end of line */
  1369. trimline(f,n)
  1370. {
  1371. X    register int off, orig;
  1372. X    register LINE *lp;
  1373. X    
  1374. X    lp = curwp->w_dotp;
  1375. X        
  1376. X    off = llength(lp)-1;
  1377. X    orig = off;
  1378. X    while (off >= 0) {
  1379. X        if (!isspace(lgetc(lp,off)))
  1380. X            break;
  1381. X        off--;
  1382. X    }
  1383. X    
  1384. X    if (off == orig)
  1385. X        return TRUE;
  1386. X
  1387. X    curwp->w_doto = off+1;
  1388. X        
  1389. X    return ldelete(orig - off,FALSE);
  1390. }
  1391. X
  1392. X
  1393. #if NOCOUNT
  1394. /* open lines up before this one */
  1395. openup(f,n)
  1396. {
  1397. X    int backline();
  1398. X    int s;
  1399. X    gotobol(TRUE,1);
  1400. X    s = lnewline();
  1401. X    if (s != TRUE)
  1402. X        return(s);
  1403. X    s = backline(TRUE,1);
  1404. X    if (s != TRUE)
  1405. X        return(s);
  1406. X    return(opendown(TRUE,1));
  1407. }
  1408. X
  1409. /*
  1410. X * Open up some blank space. The basic plan is to insert a bunch of newlines,
  1411. X * and then back up over them. Everything is done by the subcommand
  1412. X * processors. They even handle the looping.
  1413. X * The function passed in is used to choose position before opening up.
  1414. X */
  1415. X
  1416. /* open lines up after this one */
  1417. opendown(f,n)
  1418. {
  1419. X        register int    i;
  1420. X        register int    s;
  1421. X
  1422. X    gotoeol(TRUE,1);
  1423. X        s = newline(TRUE,1);
  1424. X
  1425. X    curgoal = -1;
  1426. X
  1427. X    if (s != TRUE)
  1428. X        return (s);
  1429. X
  1430. X    return(ins(f,n));
  1431. }
  1432. #else
  1433. /* open lines up before this one */
  1434. openup(f,n)
  1435. {
  1436. X    int backline();
  1437. X    int s;
  1438. X    gotobol(TRUE,1);
  1439. X    s = lnewline();
  1440. X    if (s != TRUE)
  1441. X        return(s);
  1442. X    s = backline(TRUE,1);
  1443. X    if (s != TRUE)
  1444. X        return(s);
  1445. X    /* there's a bug here with counts.  I don't particularly care
  1446. X        right now.  */
  1447. X    return(opendown(f,n-1));
  1448. }
  1449. X
  1450. /*
  1451. X * Open up some blank space. The basic plan is to insert a bunch of newlines,
  1452. X * and then back up over them. Everything is done by the subcommand
  1453. X * processors. They even handle the looping.
  1454. X * The function passed in is used to choose position before opening up.
  1455. X */
  1456. X
  1457. /* open lines up after this one */
  1458. opendown(f,n)
  1459. {
  1460. X        register int    i;
  1461. X        register int    s;
  1462. X
  1463. X        if (n < 0)
  1464. X                return (FALSE);
  1465. X        if (n == 0) {
  1466. X                return (ins(f,n));
  1467. X    }
  1468. X
  1469. X        i = n;                                  /* Insert newlines.     */
  1470. X        do {
  1471. X        gotoeol(TRUE,1);
  1472. X                s = newline(TRUE,1);
  1473. X        } while (s==TRUE && --i);
  1474. X        if (s == TRUE)                          /* Then back up overtop */
  1475. X                s = backline(TRUE, n-1);             /* of them all.         */
  1476. X
  1477. X    curgoal = -1;
  1478. X
  1479. X    if (s != TRUE)
  1480. X        return (s);
  1481. X
  1482. X    return(ins(f,n));
  1483. }
  1484. #endif
  1485. X
  1486. X
  1487. /*
  1488. X * Go into insert mode.  I guess this isn't emacs anymore...
  1489. X */
  1490. insert(f, n)
  1491. {
  1492. X    return (ins(f,n));
  1493. }
  1494. X
  1495. insertbol(f, n)
  1496. {
  1497. X    firstnonwhite(f,n);
  1498. X    return (ins(f,n));
  1499. }
  1500. X
  1501. append(f, n)
  1502. {
  1503. X    if (curwp->w_doto != llength(curwp->w_dotp)) /* END OF LINE HACK */
  1504. X        forwchar(TRUE,1);
  1505. X    return (ins(f,n));
  1506. }
  1507. X
  1508. appendeol(f, n)
  1509. {
  1510. X    gotoeol(FALSE,0);
  1511. X    return (ins(f,n));
  1512. }
  1513. X
  1514. overwrite(f, n)
  1515. {
  1516. X    insertmode = OVERWRITE;
  1517. X    return ins(f,n);
  1518. }
  1519. X
  1520. /* grunt routine for insert mode */
  1521. ins(f,n)
  1522. {
  1523. X    register int status;
  1524. X    int (*execfunc)();        /* ptr to function to execute */
  1525. X    int    c;        /* command character */
  1526. X    extern int quote(), backspace(), tab(), newline(), nullproc();
  1527. #if BSD
  1528. X    extern int bktoshell();
  1529. #endif
  1530. X
  1531. X    if (insertmode == FALSE)
  1532. X    insertmode = INSERT;
  1533. X
  1534. X    /* get the next command from the keyboard */
  1535. X    while(1) {
  1536. X
  1537. X    update(FALSE);
  1538. X
  1539. X    f = FALSE;
  1540. X    n = 1;
  1541. X
  1542. X    c = kbd_key();
  1543. X
  1544. X    if (c == abortc ) {
  1545. X         /* an unfortunate Vi-ism that ensures one 
  1546. X             can always type "ESC a" if you're not sure 
  1547. X             you're in insert mode. */
  1548. X        if (curwp->w_doto != 0)
  1549. X            backchar(TRUE,1);
  1550. X        if (autoindented >= 0) {
  1551. X            trimline(FALSE,1);
  1552. X            autoindented = -1;
  1553. X        }
  1554. X        insertmode = FALSE;
  1555. X        return (TRUE);
  1556. X    }
  1557. X
  1558. X    execfunc = NULL;
  1559. X    if (c == quotec) {
  1560. X        execfunc = quote;
  1561. X    } else {
  1562. X            /*
  1563. X             * If a space was typed, fill column is defined, the
  1564. X         * argument is non- negative, wrap mode is enabled, and
  1565. X         * we are now past fill column, perform word wrap. 
  1566. X             */
  1567. X            if (isspace(c) /* c == ' ' */ && (curwp->w_bufp->b_mode & MDWRAP) && fillcol > 0 &&
  1568. X            n >= 0 && getccol(FALSE) > fillcol )
  1569. X                wrapword();
  1570. X
  1571. X        if (isbackspace(c))
  1572. X            c = '\b';
  1573. X        switch(c) {
  1574. X            /* ^D and ^T are aliased to ^H and tab, for 
  1575. X                users accustomed to "shiftwidth" */
  1576. X            case tocntrl('D'):
  1577. X            case '\b':
  1578. X                execfunc = (curwp->w_doto == 0) ?
  1579. X                        nullproc:backspace;
  1580. X                autoindented--;
  1581. X                break;
  1582. X            case tocntrl('T'):
  1583. X            case tocntrl('I'):
  1584. X                execfunc = tab;
  1585. X                autoindented = -1;
  1586. X                break;
  1587. X            case tocntrl('J'):
  1588. X            case tocntrl('M'):        
  1589. X                execfunc = newline;
  1590. X                if (autoindented >= 0) {
  1591. X                    trimline(FALSE,1);
  1592. X                    autoindented = -1;
  1593. X                }
  1594. X                break;
  1595. #if UNIX && defined(SIGTSTP)    /* job control */
  1596. X            case tocntrl('Z'):        
  1597. X                execfunc = bktoshell;
  1598. X                break;
  1599. #endif
  1600. X            case tocntrl('S'):
  1601. X            case tocntrl('Q'):        
  1602. X                execfunc = nullproc;
  1603. X                break;
  1604. X        }
  1605. X    }
  1606. X
  1607. X    if (execfunc != NULL) {
  1608. X        status     = (*execfunc)(f, n);
  1609. X        if (status != TRUE) {
  1610. X            insertmode = FALSE;
  1611. X            return (status);
  1612. X        }
  1613. X        continue;
  1614. X    }
  1615. X
  1616. X    
  1617. X    /* make it a real character again */
  1618. X    c = kcod2key(c);
  1619. X
  1620. X    /* if we are in overwrite mode, not at eol,
  1621. X       and next char is not a tab or we are at a tab stop,
  1622. X       delete a char forword            */
  1623. X    if (insertmode == OVERWRITE &&
  1624. X            curwp->w_doto < curwp->w_dotp->l_used &&
  1625. X            (lgetc(curwp->w_dotp, curwp->w_doto) != '\t' ||
  1626. X            (curwp->w_doto) % TABVAL == TABMASK)) {
  1627. X        autoindented = -1;
  1628. X        ldelete(1L, FALSE);
  1629. X    }
  1630. X
  1631. X    /* do the appropriate insertion */
  1632. X    if ((c == RBRACE) && ((curbp->b_mode & MDCMOD) != 0)) {
  1633. X            status = insbrace(n, c);
  1634. X    } else if (c == '#' && (curbp->b_mode & MDCMOD) != 0) {
  1635. X            status = inspound();
  1636. X    } else {
  1637. X        autoindented = -1;
  1638. X                status = linsert(n, c);
  1639. X    }
  1640. X
  1641. #if    CFENCE & !UNIX
  1642. X    /* check for CMODE fence matching */
  1643. X    if ((c == RBRACE || c == ')' || c == ']') &&
  1644. X            (curbp->b_mode & MDCMOD) != 0)
  1645. X        fmatch(c);
  1646. #endif
  1647. X
  1648. X    /* check auto-save mode */
  1649. X    if (curbp->b_mode & MDASAVE)
  1650. X        if (--gacount == 0) {
  1651. X            /* and save the file if needed */
  1652. X            upscreen(FALSE, 0);
  1653. X            filesave(FALSE, 0);
  1654. X            gacount = gasave;
  1655. X        }
  1656. X
  1657. X        if (status != TRUE) {
  1658. X        insertmode = FALSE;
  1659. X        return (status);
  1660. X    }
  1661. X    }
  1662. }
  1663. X
  1664. backspace()
  1665. {
  1666. X        register int    s;
  1667. X
  1668. X        if ((s=backchar(TRUE, 1)) == TRUE)
  1669. X                s = ldelete(1L, FALSE);
  1670. X        return (s);
  1671. }
  1672. X
  1673. /*
  1674. X * Insert a newline. If we are in CMODE, do automatic
  1675. X * indentation as specified.
  1676. X */
  1677. newline(f, n)
  1678. {
  1679. X    register int    s;
  1680. X
  1681. X    if (n < 0)
  1682. X        return (FALSE);
  1683. X
  1684. #if LATER    /* already done for autoindented != 0 in ins() */
  1685. X    if (curbp->b_mode & MDTRIM))
  1686. X        trimline(f,n);
  1687. #endif
  1688. X    
  1689. X    /* if we are in C mode and this is a default <NL> */
  1690. X    if (n == 1 && (curbp->b_mode & (MDCMOD|MDAIND)) &&
  1691. X        curwp->w_dotp != curbp->b_linep)
  1692. X        return indented_newline(curbp->b_mode & MDCMOD);
  1693. X
  1694. X        /*
  1695. X         * If a newline was typed, fill column is defined, the argument is non-
  1696. X         * negative, wrap mode is enabled, and we are now past fill column,
  1697. X     * perform word wrap.
  1698. X         */
  1699. X        if ((curwp->w_bufp->b_mode & MDWRAP) && fillcol > 0 &&
  1700. X                        getccol(FALSE) > fillcol)
  1701. X            wrapword();
  1702. X
  1703. X    /* insert some lines */
  1704. X    while (n--) {
  1705. X        if ((s=lnewline()) != TRUE)
  1706. X            return (s);
  1707. X        curwp->w_flag |= WFINS;
  1708. X    }
  1709. X    return (TRUE);
  1710. }
  1711. X
  1712. /* insert a newline and indentation for C */
  1713. indented_newline(cmode)
  1714. {
  1715. X    register int indentwas;    /* indent to reproduce */
  1716. X    int bracef;    /* was there a brace at the end of line? */
  1717. X    
  1718. X    indentwas = previndent(&bracef);
  1719. X    if (lnewline() == FALSE)
  1720. X        return FALSE;
  1721. X    if (cmode & bracef)
  1722. X        indentwas = (indentwas + TABVAL) & ~TABMASK;
  1723. X    if (doindent(indentwas) != TRUE)
  1724. X        return FALSE;
  1725. X    return TRUE;
  1726. }
  1727. X
  1728. /* get the indent of the last previous non-blank line.  also, if arg
  1729. X    is non-null, check if line ended in a brace */
  1730. int
  1731. previndent(bracefp)
  1732. int *bracefp;
  1733. {
  1734. X    int ind;
  1735. X    
  1736. X    setmark();
  1737. X    
  1738. X    if (backword(FALSE,1) == FALSE) {
  1739. X        if (bracefp) *bracefp = FALSE;
  1740. X        gomark();
  1741. X        return 0;
  1742. X    }
  1743. X    ind = indentlen(curwp->w_dotp);
  1744. X    if (bracefp)
  1745. X        *bracefp = (llength(curwp->w_dotp) > 0 &&
  1746. X            lgetc(curwp->w_dotp,llength(curwp->w_dotp)-1) == '{');
  1747. X        
  1748. X    gomark();
  1749. X    
  1750. X    return ind;
  1751. }
  1752. X
  1753. doindent(ind)
  1754. {
  1755. X    int i;
  1756. X    /* if no indent was asked for, we're done */
  1757. X    if (ind <= 0)
  1758. X        return TRUE;
  1759. X    autoindented = 0;
  1760. X        if ((i=ind/TABVAL)!=0) {
  1761. X        autoindented += i;
  1762. X        if (linsert(i, '\t') == FALSE)
  1763. X            return FALSE;
  1764. X    }
  1765. X    if ((i=ind%TABVAL) != 0) {
  1766. X        autoindented += i;
  1767. X        if (linsert(i,  ' ') == FALSE)
  1768. X            return FALSE;
  1769. X    }
  1770. X    if (!autoindented)
  1771. X        autoindented = -1;
  1772. X    
  1773. X    return TRUE;
  1774. }
  1775. X
  1776. /* return the column indent of the specified line */
  1777. int
  1778. indentlen(lp)
  1779. LINE *lp;
  1780. {
  1781. X    register int ind, i, c;
  1782. X        ind = 0;
  1783. X        for (i=0; i<llength(lp); ++i) {
  1784. X                c = lgetc(lp, i);
  1785. X                if (!isspace(c))
  1786. X                        break;
  1787. X                if (c == '\t')
  1788. X                        ind |= TABMASK;
  1789. X                ++ind;
  1790. X        }
  1791. X        return ind;
  1792. }
  1793. X
  1794. insbrace(n, c)    /* insert a brace into the text here...we are in CMODE */
  1795. int n;    /* repeat count */
  1796. int c;    /* brace to insert (always { for now) */
  1797. {
  1798. X    register int ch;    /* last character before input */
  1799. X    register int i;
  1800. X    register int target;    /* column brace should go after */
  1801. X
  1802. #if ! CFENCE
  1803. X    /* wouldn't want to back up from here, but fences might take us 
  1804. X        forward */
  1805. X    /* if we are at the beginning of the line, no go */
  1806. X    if (curwp->w_doto == 0)
  1807. X        return(linsert(n,c));
  1808. #endif
  1809. X
  1810. X    if (autoindented >= 0) {
  1811. X        trimline(FALSE,1);
  1812. X    }
  1813. X    else {
  1814. X        return linsert(n,c);
  1815. X    }
  1816. #if ! CFENCE /* no fences?  then put brace one tab in from previous line */
  1817. X    doindent((previndent(NULL)-1) & ~TABMASK);
  1818. #else /* line up brace with the line containing its match */
  1819. X    doindent(fmatchindent());
  1820. #endif
  1821. X    autoindented = -1;
  1822. X
  1823. X    /* and insert the required brace(s) */
  1824. X    return(linsert(n, c));
  1825. }
  1826. X
  1827. inspound()    /* insert a # into the text here...we are in CMODE */
  1828. {
  1829. X    register int ch;    /* last character before input */
  1830. X    register int i;
  1831. X
  1832. X    /* if we are at the beginning of the line, no go */
  1833. X    if (curwp->w_doto == 0)
  1834. X        return(linsert(1,'#'));
  1835. X
  1836. X    if (autoindented > 0) {    /* must all be whitespace before us */
  1837. X        curwp->w_doto = 0;
  1838. X        ldelete(autoindented,FALSE);
  1839. X    }
  1840. X    autoindented = -1;
  1841. X
  1842. X    /* and insert the required pound */
  1843. X    return(linsert(1, '#'));
  1844. }
  1845. X
  1846. #if AEDIT
  1847. /*
  1848. X * Delete blank lines around dot. What this command does depends if dot is
  1849. X * sitting on a blank line. If dot is sitting on a blank line, this command
  1850. X * deletes all the blank lines above and below the current line. If it is
  1851. X * sitting on a non blank line then it deletes all of the blank lines after
  1852. X * the line. Any argument is ignored.
  1853. X */
  1854. deblank(f, n)
  1855. {
  1856. X        register LINE   *lp1;
  1857. X        register LINE   *lp2;
  1858. X        long nld;
  1859. X
  1860. X        lp1 = curwp->w_dotp;
  1861. X        while (llength(lp1)==0 && (lp2=lback(lp1))!=curbp->b_linep)
  1862. X                lp1 = lp2;
  1863. X        lp2 = lp1;
  1864. X        nld = 0;
  1865. X        while ((lp2=lforw(lp2))!=curbp->b_linep && llength(lp2)==0)
  1866. X                ++nld;
  1867. X        if (nld == 0)
  1868. X                return (TRUE);
  1869. X        curwp->w_dotp = lforw(lp1);
  1870. X        curwp->w_doto = 0;
  1871. X        return (ldelete(nld, FALSE));
  1872. }
  1873. X
  1874. #endif
  1875. X
  1876. /* '~' is synonymous with 'M-~<space>' */
  1877. flipchar(f, n)
  1878. {
  1879. X    int s;
  1880. X    extern CMDFUNC f_forwchar;
  1881. X
  1882. X    if (curwp->w_doto != llength(curwp->w_dotp)) {
  1883. X        havemotion = &f_forwchar;
  1884. X        s = operflip(FALSE,1);
  1885. X        if (s == TRUE)
  1886. X            return forwchar(FALSE,1);
  1887. X    }
  1888. X    return FALSE;
  1889. }
  1890. X
  1891. /* 'x' is synonymous with 'd<space>' */
  1892. forwdelchar(f, n)
  1893. {
  1894. X    extern CMDFUNC f_forwchar, f_backchar;
  1895. X
  1896. X    if (curwp->w_doto != llength(curwp->w_dotp)) /* END OF LINE HACK */
  1897. X        havemotion = &f_forwchar;
  1898. X    else
  1899. X        havemotion = &f_backchar;
  1900. X    return(operdel(f,n));
  1901. }
  1902. X
  1903. /* 'X' is synonymous with 'd<backspace>' */
  1904. backdelchar(f, n)
  1905. {
  1906. X    extern CMDFUNC f_backchar, f_forwchar;
  1907. X
  1908. X    if (curwp->w_doto != 0) /* BEGINNING OF LINE HACK */
  1909. X        havemotion = &f_backchar;
  1910. X    else
  1911. X        havemotion = &f_forwchar;
  1912. X    return(operdel(f,n));
  1913. }
  1914. X
  1915. /* 'D' is synonymous with 'd$' */
  1916. deltoeol(f, n)
  1917. {
  1918. X    extern CMDFUNC f_gotoeol;
  1919. X
  1920. X    havemotion = &f_gotoeol;
  1921. X    return(operdel(FALSE,1));
  1922. }
  1923. X
  1924. /* 'C' is synonymous with 'c$' */
  1925. chgtoeol(f, n)
  1926. {
  1927. X    extern CMDFUNC f_gotoeol;
  1928. X
  1929. X        if (llength(curwp->w_dotp) == 0) {
  1930. X            return ins(f,n);
  1931. X        } else {
  1932. X        havemotion = &f_gotoeol;
  1933. X        return operchg(FALSE,1);
  1934. X    }
  1935. }
  1936. X
  1937. /* 'Y' is synonymous with 'yy' */
  1938. yankline(f, n)
  1939. {
  1940. X    extern CMDFUNC f_godotplus;
  1941. X    havemotion = &f_godotplus;
  1942. X    return(operyank(f,n));
  1943. }
  1944. X
  1945. /* 'S' is synonymous with 'cc' */
  1946. chgline(f, n)
  1947. {
  1948. X    extern CMDFUNC f_godotplus;
  1949. X    havemotion = &f_godotplus;
  1950. X    return(operchg(f,n));
  1951. }
  1952. X
  1953. /* 's' is synonymous with 'c<space>' */
  1954. chgchar(f, n)
  1955. {
  1956. X    extern CMDFUNC f_forwchar;
  1957. X
  1958. X    havemotion = &f_forwchar;
  1959. X    return(operchg(f,n));
  1960. }
  1961. X
  1962. setmode(f, n)    /* prompt and set an editor mode */
  1963. int f, n;    /* default and argument */
  1964. {
  1965. X    return(adjustmode(TRUE, FALSE));
  1966. }
  1967. X
  1968. delmode(f, n)    /* prompt and delete an editor mode */
  1969. int f, n;    /* default and argument */
  1970. {
  1971. X    return(adjustmode(FALSE, FALSE));
  1972. }
  1973. X
  1974. setgmode(f, n)    /* prompt and set a global editor mode */
  1975. int f, n;    /* default and argument */
  1976. {
  1977. X    return(adjustmode(TRUE, TRUE));
  1978. }
  1979. X
  1980. delgmode(f, n)    /* prompt and delete a global editor mode */
  1981. int f, n;    /* default and argument */
  1982. {
  1983. X    return(adjustmode(FALSE, TRUE));
  1984. }
  1985. X
  1986. X
  1987. adjustmode(kind, global)    /* change the editor mode status */
  1988. int kind;    /* true = set,        false = delete */
  1989. int global;    /* true = global flag,    false = current buffer flag */
  1990. {
  1991. X    register char *scan;        /* scanning pointer to convert prompt */
  1992. X    register int i;            /* loop index */
  1993. X    register status;        /* error return on input */
  1994. #if    COLOR
  1995. X    register int uflag;        /* was modename uppercase?    */
  1996. #endif
  1997. X    int no = 0;
  1998. X    int okind;
  1999. X    char prompt[50];    /* string to prompt user with */
  2000. X    static char cbuf[NPAT];        /* buffer to recieve mode name into */
  2001. X
  2002. X    /* build the proper prompt string */
  2003. X    if (global)
  2004. X        strcpy(prompt,"Global mode to ");
  2005. X    else
  2006. X        strcpy(prompt,"Mode to ");
  2007. X
  2008. X    if (kind == TRUE)
  2009. X        strcat(prompt, "add: ");
  2010. X    else
  2011. X        strcat(prompt, "delete: ");
  2012. X
  2013. X    /* prompt the user and get an answer */
  2014. X
  2015. X    status = mlreply(prompt, cbuf, NPAT - 1);
  2016. X    if (status != TRUE)
  2017. X        return(status);
  2018. X
  2019. X    /* make it lowercase */
  2020. X
  2021. X    scan = cbuf;
  2022. #if    COLOR
  2023. X    uflag = isupper(*scan);
  2024. #endif
  2025. X    while (*scan != 0) {
  2026. X        if (isupper(*scan))
  2027. X            *scan = tolower(*scan);
  2028. X        scan++;
  2029. X    }
  2030. X
  2031. X    if (!strcmp(cbuf,"all")) {
  2032. X        return showm(global);
  2033. X    }
  2034. X
  2035. X    /* test it first against the colors we know */
  2036. X    for (i=0; i<NCOLORS; i++) {
  2037. X        if (strcmp(cbuf, cname[i]) == 0) {
  2038. X            /* finding the match, we set the color */
  2039. #if    COLOR
  2040. X            if (uflag)
  2041. X                if (global)
  2042. X                    gfcolor = i;
  2043. X                else if (curwp)
  2044. X                    curwp->w_fcolor = i;
  2045. X            else
  2046. X                if (global)
  2047. X                    gbcolor = i;
  2048. X                else if (curwp)
  2049. X                    curwp->w_bcolor = i;
  2050. X
  2051. X            if (curwp)
  2052. X                curwp->w_flag |= WFCOLR;
  2053. #endif
  2054. X            mlerase();
  2055. X            return(TRUE);
  2056. X        }
  2057. X    }
  2058. X
  2059. X    /* test it against the modes we know */
  2060. X
  2061. X    if (strncmp(cbuf, "no", 2) == 0) {
  2062. X        okind = kind;
  2063. X        kind = !kind;
  2064. X        no = 2;
  2065. X    }
  2066. X    for (i=0; i < NUMMODES; i++) {
  2067. X        if (strcmp(&cbuf[no], modename[i]) == 0) {
  2068. X            /* finding a match, we process it */
  2069. X            if (kind == TRUE) {
  2070. X                if (global) {
  2071. X                    gmode |= (1 << i);
  2072. X                } else if (curbp) {
  2073. X                    curbp->b_mode |= (1 << i);
  2074. X                }
  2075. X            } else {
  2076. X                if (global) {
  2077. X                    gmode &= ~(1 << i);
  2078. X                } else if (curbp) {
  2079. X                    curbp->b_mode &= ~(1 << i);
  2080. X                }
  2081. X            }
  2082. X            /* display new mode line */
  2083. X            if (global == 0 && curbp)
  2084. X                upmode();
  2085. X            mlerase();    /* erase the junk */
  2086. X            return(TRUE);
  2087. X        }
  2088. X    }
  2089. X
  2090. X    /* test it against other modes... */
  2091. X    /* these are global modes that don't inherit to windows */
  2092. X    for (i=0; i < NUMOTHERMODES; i++) {
  2093. X        if (strcmp(&cbuf[no], othermodes[i]) == 0) {
  2094. X            /* finding a match, we process it */
  2095. X            if (kind == TRUE)
  2096. X                othmode |= (1 << i);
  2097. X            else
  2098. X                othmode &= ~(1 << i);
  2099. X            mlerase();    /* erase the junk */
  2100. X            return(TRUE);
  2101. X        }
  2102. X    }
  2103. X    kind = okind;
  2104. X
  2105. X    /* test it against valued  modes... */
  2106. X    /* these are global modes that have values */
  2107. X    for (i=0; i < NUMVALUEMODES; i++) {
  2108. X        if (strcmp(cbuf, valuemodes[i]) == 0) {
  2109. X            int nval;
  2110. X            char *cp;
  2111. X            char valbuf[NPAT];
  2112. X
  2113. X            valbuf[0] = '\0';
  2114. X            status = mlreply("New value: ", valbuf, NPAT - 1);
  2115. X            if (status != TRUE)
  2116. X                return status;
  2117. X            /* finding a match, we process it */
  2118. X            nval = 0;
  2119. X            cp = valbuf;
  2120. X            while (isdigit(*cp))
  2121. X                nval = (nval * 10) + (*cp++ - '0');
  2122. X            switch(i) {
  2123. X            case VAL_TAB:
  2124. X                settab(TRUE,nval);
  2125. X                break;
  2126. X            case VAL_FILL:
  2127. X                setfillcol(TRUE,nval);
  2128. X                break;
  2129. X            }
  2130. X            mlerase();    /* erase the junk */
  2131. X            return(TRUE);
  2132. X        }
  2133. X    }
  2134. X
  2135. X    mlwrite("No such mode!");
  2136. X    return(FALSE);
  2137. }
  2138. X
  2139. X
  2140. /* Quiet adjust mode, no message line echo.
  2141. X * Expects a string to follow: SGover to set global overtype.
  2142. X * Prefixes are SG, RG, SL, RL.  Text will be taken until a newline.
  2143. X */
  2144. #if    NeWS
  2145. newsadjustmode()    /* change the editor mode status */
  2146. {
  2147. X    register char *scan;        /* scanning pointer to convert prompt */
  2148. X    register int i;            /* loop index */
  2149. #if    COLOR
  2150. X    register int uflag;        /* was modename uppercase?    */
  2151. #endif
  2152. X    char cbuf[NPAT];        /* buffer to recieve mode name into */
  2153. X    char ch ;
  2154. X    int kind, global ;
  2155. X
  2156. X    /* get the mode name and switches */
  2157. X    kind = ('S' == tgetc()) ;
  2158. X    global = ('G' == tgetc()) ;
  2159. X    for (i=0; i<NPAT; i++) {
  2160. X        if ( '\n' == (ch=tgetc()) ) {
  2161. X            cbuf[i] = NULL ;
  2162. X            break ;
  2163. X        }
  2164. X        cbuf[i] = ch ;
  2165. X    }
  2166. X
  2167. X    /* make it uppercase */
  2168. X    scan = cbuf;
  2169. #if    COLOR
  2170. X    uflag = isupper(*scan);
  2171. #endif
  2172. X    while (*scan != 0) {
  2173. X        if (islower(*scan))
  2174. X            *scan = toupper(*scan);
  2175. X        scan++;
  2176. X    }
  2177. X
  2178. X    /* test it first against the colors we know */
  2179. X    for (i=0; i<NCOLORS; i++) {
  2180. X        if (strcmp(cbuf, cname[i]) == 0) {
  2181. X            /* finding the match, we set the color */
  2182. #if    COLOR
  2183. X            if (uflag)
  2184. X                if (global)
  2185. X                    gfcolor = i;
  2186. X                else if (curwp)
  2187. X                    curwp->w_fcolor = i;
  2188. X            else
  2189. X                if (global)
  2190. X                    gbcolor = i;
  2191. X                else if (curwp)
  2192. X                    curwp->w_bcolor = i;
  2193. X
  2194. X            if (curwp)
  2195. X                curwp->w_flag |= WFCOLR;
  2196. #endif
  2197. X            return(TRUE);
  2198. X        }
  2199. X    }
  2200. X
  2201. X    /* test it against the modes we know */
  2202. X    for (i=0; i < NUMMODES; i++) {
  2203. X        if (strcmp(cbuf, modename[i]) == 0) {
  2204. X            /* finding a match, we process it */
  2205. X            if (kind == TRUE)
  2206. X                if (global)
  2207. X                    gmode |= (1 << i);
  2208. X                else if (curbp)
  2209. X                    curbp->b_mode |= (1 << i);
  2210. X            else
  2211. X                if (global)
  2212. X                    gmode &= ~(1 << i);
  2213. X                else if (curbp)
  2214. X                    curbp->b_mode &= ~(1 << i);
  2215. X            /* display new mode line */
  2216. X            if (global == 0 && curbp)
  2217. X                upmode();
  2218. X            return(TRUE);
  2219. X        }
  2220. X    }
  2221. X    return(FALSE);
  2222. }
  2223. #endif
  2224. X
  2225. X
  2226. /*    This function simply clears the message line,
  2227. X        mainly for macro usage            */
  2228. X
  2229. clrmes(f, n)
  2230. X
  2231. int f, n;    /* arguments ignored */
  2232. X
  2233. {
  2234. X    mlforce("");
  2235. X    return(TRUE);
  2236. }
  2237. X
  2238. #if ! SMALLER
  2239. X
  2240. /*    This function writes a string on the message line
  2241. X        mainly for macro usage            */
  2242. X
  2243. writemsg(f, n)
  2244. int f, n;    /* arguments ignored */
  2245. {
  2246. X    register char *sp;    /* pointer into buf to expand %s */
  2247. X    register char *np;    /* ptr into nbuf */
  2248. X    register int status;
  2249. X    char buf[NPAT];        /* buffer to recieve message into */
  2250. X    char nbuf[NPAT*2];    /* buffer to expand string into */
  2251. X
  2252. X    buf[0] = 0;
  2253. X    if ((status = mlreply("Message to write: ", buf, NPAT - 1)) != TRUE)
  2254. X        return(status);
  2255. X
  2256. X    /* expand all '%' to "%%" so mlwrite won't expect arguments */
  2257. X    sp = buf;
  2258. X    np = nbuf;
  2259. X    while (*sp) {
  2260. X        *np++ = *sp;
  2261. X        if (*sp++ == '%')
  2262. X            *np++ = '%';
  2263. X    }
  2264. X    *np = '\0';
  2265. X
  2266. X    /* write the message out */
  2267. X    mlforce(nbuf);
  2268. X    return(TRUE);
  2269. }
  2270. #endif
  2271. X
  2272. #if    CFENCE
  2273. /*    the cursor is moved to a matching fence    */
  2274. X
  2275. getfence(f, n, ch)
  2276. int f, n;    /* not used */
  2277. int ch;    /* fence type to match against */
  2278. {
  2279. X    register LINE *oldlp;    /* original line pointer */
  2280. X    register int oldoff;    /* and offset */
  2281. X    register int sdir;    /* direction of search (1/-1) */
  2282. X    register int count;    /* current fence level count */
  2283. X    register int ofence;    /* open fence */
  2284. X    register int c;    /* current character in scan */
  2285. X    int s;
  2286. X
  2287. X    /* save the original cursor position */
  2288. X    oldlp = curwp->w_dotp;
  2289. X    oldoff = curwp->w_doto;
  2290. X
  2291. X    if (!ch) {    /* ch may have been passed, if being used internally */
  2292. X        /* get the current character */
  2293. X        if (oldoff == llength(oldlp))
  2294. X            ch = '\n';
  2295. X        else
  2296. X            ch = lgetc(oldlp, oldoff);
  2297. X    }
  2298. X
  2299. X    /* setup proper matching fence */
  2300. X    switch (ch) {
  2301. X        case '(': ofence = ')'; sdir = FORWARD; break;
  2302. X        case LBRACE: ofence = RBRACE; sdir = FORWARD; break;
  2303. X        case '[': ofence = ']'; sdir = FORWARD; break;
  2304. X        case ')': ofence = '('; sdir = REVERSE; break;
  2305. X        case RBRACE: ofence = LBRACE; sdir = REVERSE; break;
  2306. X        case ']': ofence = '['; sdir = REVERSE; break;
  2307. X        default: TTbeep(); return(FALSE);
  2308. X    }
  2309. X
  2310. X    /* ops are inclusive of the endpoint */
  2311. X    if (doingopcmd && sdir == REVERSE) {
  2312. X        forwchar(TRUE,1);
  2313. X        setmark();
  2314. X        backchar(TRUE,1);
  2315. X    }
  2316. X
  2317. X    /* set up for scan */
  2318. X    if (sdir == REVERSE)
  2319. X        backchar(FALSE, 1);
  2320. X    else
  2321. X        forwchar(FALSE, 1);
  2322. X
  2323. X    count = 1;
  2324. X    while (count > 0) {
  2325. X        if (curwp->w_doto == llength(curwp->w_dotp))
  2326. X            c = '\n';
  2327. X        else
  2328. X            c = lgetc(curwp->w_dotp, curwp->w_doto);
  2329. X
  2330. X        if (c == ch)
  2331. X            ++count;
  2332. X        else if (c == ofence)
  2333. X            --count;
  2334. X
  2335. X        if (sdir == FORWARD)
  2336. X            s = forwchar(FALSE, 1);
  2337. X        else
  2338. X            s = backchar(FALSE, 1);
  2339. X
  2340. X        if (s == FALSE)
  2341. X            break;
  2342. X
  2343. X        if (interrupted) {
  2344. X            count = 1;
  2345. X            break;
  2346. X        }
  2347. X    }
  2348. X
  2349. X    /* if count is zero, we have a match, move the sucker */
  2350. X    if (count == 0) {
  2351. X        if (sdir == FORWARD) {
  2352. X            if (!doingopcmd)
  2353. X                backchar(FALSE, 1);
  2354. X        } else {
  2355. X            forwchar(FALSE, 1);
  2356. X        }
  2357. X        curwp->w_flag |= WFMOVE;
  2358. X        return(TRUE);
  2359. X    }
  2360. X
  2361. X    /* restore the current position */
  2362. X    curwp->w_dotp = oldlp;
  2363. X    curwp->w_doto = oldoff;
  2364. X    TTbeep();
  2365. X    return(FALSE);
  2366. }
  2367. X
  2368. /* get the indent of the line containing the matching brace. */
  2369. int
  2370. fmatchindent()
  2371. {
  2372. X    int ind;
  2373. X    
  2374. X    setmark();
  2375. X    
  2376. X    if (getfence(FALSE,1,RBRACE) == FALSE) {
  2377. X        gomark();
  2378. X        return previndent(NULL);
  2379. X    }
  2380. X
  2381. X    ind = indentlen(curwp->w_dotp);
  2382. X
  2383. X    gomark();
  2384. X    
  2385. X    return ind;
  2386. }
  2387. X
  2388. X
  2389. #if ! UNIX    /* the code as written is useless, since it busy-waits... */
  2390. X
  2391. /*    Close fences are matched against their partners, and if
  2392. X    on screen the cursor briefly lights there        */
  2393. fmatch(ch)
  2394. char ch;    /* fence type to match against */
  2395. {
  2396. X    register LINE *oldlp;    /* original line pointer */
  2397. X    register int oldoff;    /* and offset */
  2398. X    register LINE *toplp;    /* top line in current window */
  2399. X    register int count;    /* current fence level count */
  2400. X    register char opench;    /* open fence */
  2401. X    register char c;    /* current character in scan */
  2402. X    register int i;
  2403. X
  2404. X    /* first get the display update out there */
  2405. X    update(FALSE);
  2406. X
  2407. X    /* save the original cursor position */
  2408. X    oldlp = curwp->w_dotp;
  2409. X    oldoff = curwp->w_doto;
  2410. X
  2411. X    /* setup proper open fence for passed close fence */
  2412. X    if (ch == ')')
  2413. X        opench = '(';
  2414. X    else if (ch == RBRACE)
  2415. X        opench = LBRACE;
  2416. X    else
  2417. X        opench = '[';
  2418. X
  2419. X    /* find the top line and set up for scan */
  2420. X    toplp = curwp->w_linep->l_bp;
  2421. X    count = 1;
  2422. X    backchar(FALSE, 2);
  2423. X
  2424. X    /* scan back until we find it, or reach past the top of the window */
  2425. X    while (count > 0 && curwp->w_dotp != toplp) {
  2426. X        if (curwp->w_doto == llength(curwp->w_dotp))
  2427. X            c = '\n';
  2428. X        else
  2429. X            c = lgetc(curwp->w_dotp, curwp->w_doto);
  2430. X        if (c == ch)
  2431. X            ++count;
  2432. X        if (c == opench)
  2433. X            --count;
  2434. X        backchar(FALSE, 1);
  2435. X        if (curwp->w_dotp == curwp->w_bufp->b_linep->l_fp &&
  2436. X            curwp->w_doto == 0)
  2437. X            break;
  2438. X    }
  2439. X
  2440. X    /* if count is zero, we have a match, display the sucker */
  2441. X    /* there is a real machine dependant timing problem here we have
  2442. X       yet to solve......... */
  2443. X    if (count == 0) {
  2444. X        forwchar(FALSE, 1);
  2445. X        for (i = 0; i < term.t_pause; i++)
  2446. X            update(FALSE);
  2447. X    }
  2448. X
  2449. X    /* restore the current position */
  2450. X    curwp->w_dotp = oldlp;
  2451. X    curwp->w_doto = oldoff;
  2452. X    return(TRUE);
  2453. }
  2454. #endif /* ! UNIX */
  2455. X
  2456. #endif /* CFENCE */
  2457. X
  2458. #if ! SMALLER
  2459. istring(f, n)    /* ask for and insert a string into the current
  2460. X           buffer at the current point */
  2461. int f, n;    /* ignored arguments */
  2462. {
  2463. X    register char *tp;    /* pointer into string to add */
  2464. X    register int status;    /* status return code */
  2465. X    static char tstring[NPAT+1];    /* string to add */
  2466. X
  2467. X    /* ask for string to insert */
  2468. X    status = mlreply("String to insert: ", tstring, NPAT);
  2469. X    if (status != TRUE)
  2470. X        return(status);
  2471. X
  2472. X    if (f == FALSE)
  2473. X        n = 1;
  2474. X
  2475. X    if (n < 0)
  2476. X        n = - n;
  2477. X
  2478. X    /* insert it */
  2479. X    while (n--) {
  2480. X        tp = &tstring[0];
  2481. X        while (*tp) {
  2482. X            if (*tp == '\n')
  2483. X                status = lnewline();
  2484. X            else
  2485. X                status = linsert(1, *tp);
  2486. X            ++tp;
  2487. X            if (status != TRUE)
  2488. X                return(status);
  2489. X        }
  2490. X    }
  2491. X
  2492. X    return(TRUE);
  2493. }
  2494. #endif
  2495. SHAR_EOF
  2496. chmod 0444 random.c ||
  2497. echo 'restore of random.c failed'
  2498. Wc_c="`wc -c < 'random.c'`"
  2499. test 34147 -eq "$Wc_c" ||
  2500.     echo 'random.c: original size 34147, current size' "$Wc_c"
  2501. # ============= readme.news ==============
  2502. echo 'x - extracting readme.news (Text)'
  2503. sed 's/^X//' << 'SHAR_EOF' > 'readme.news' &&
  2504. Here follows the NeWS README that was with the version I got....  -pgf
  2505. X
  2506. NeWS Distributed EMACS
  2507. X
  2508. Roger Ove
  2509. X
  2510. Introduction
  2511. X
  2512. This distributed version of MicroEMACS is designed primarily for
  2513. operation on machines where excessive keyboard interrupts are to be
  2514. avoided, such as Cray supercomputers running UNICOS. It reduces the
  2515. interrupt load to the level of a line editor, while providing some
  2516. additional features over typical resident full-screen editors. It will
  2517. function equally well on other unix machines, and as it also optimizes
  2518. screen updates and reduces network packets it may be of use in some low
  2519. bandwidth situations.
  2520. X
  2521. MicroEMACS was originally written by Dave Conroy, and includes
  2522. contributions from many people.  Most notable among the contributors is
  2523. Daniel Lawrence, who also maintains the source.  This noncommercial
  2524. implementation is derived from Lawrence's v3.9, to which he holds the
  2525. copyright.
  2526. X
  2527. Operation
  2528. X
  2529. Some of the features of this distributed version include:
  2530. X
  2531. X    Efficient i/o handling while remaining completely seamless.
  2532. X
  2533. X    Mouse support (for cutting/pasting text and cursor movement).
  2534. X
  2535. X    Menu support for most of the features of emacs.
  2536. X
  2537. X    Usable on any workstation running the NeWS server without the
  2538. X    need for the user to obtain the front end module.  The front end
  2539. X    is automatically downloaded to the workstation when the editor is
  2540. X    invoked. 
  2541. X
  2542. X    All features of MicroEMACS 3.9 are supported, including multiple
  2543. SHAR_EOF
  2544. true || echo 'restore of readme.news failed'
  2545. echo 'End of Vile part 11'
  2546. echo 'File readme.news is continued in part 12'
  2547. echo 12 > _shar_seq_.tmp
  2548. exit 0
  2549. -- 
  2550.         paul fox, pgf@cayman.com, (617)494-1999
  2551.         Cayman Systems, 26 Landsdowne St., Cambridge, MA 02139
  2552.