home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 January / usenetsourcesnewsgroupsinfomagicjanuary1994.iso / sources / unix / volume14 / jove4.9 / part06 / buf.c < prev    next >
Encoding:
C/C++ Source or Header  |  1988-04-25  |  13.1 KB  |  728 lines

  1. /***************************************************************************
  2.  * This program is Copyright (C) 1986, 1987, 1988 by Jonathan Payne.  JOVE *
  3.  * is provided to you without charge, and with no warranty.  You may give  *
  4.  * away copies of JOVE, including sources, provided that this notice is    *
  5.  * included in all the files.                                              *
  6.  ***************************************************************************/
  7.  
  8. /* Contains commands that deal with creating, selecting, killing and
  9.    listing buffers, and buffer modes, and find-file, etc. */
  10.  
  11. #include "jove.h"
  12.  
  13. #ifdef MAC
  14. #    include "mac.h"
  15. #else
  16. #    include <sys/stat.h>
  17. #endif
  18.  
  19. #ifdef MAC
  20. #    undef private
  21. #    define private
  22. #endif
  23.  
  24. #ifdef    LINT_ARGS
  25. private Buffer
  26.     * buf_alloc(void),
  27.     * mak_buf(void);
  28.  
  29. private char * line_cnt(Buffer *, char *);
  30.  
  31. private void    
  32.     BufNSelect(int),
  33.     defb_wind(Buffer *),
  34.     kill_buf(Buffer *),
  35.     mkbuflist(char **);
  36. #else
  37. private Buffer
  38.     * buf_alloc(),
  39.     * mak_buf();
  40.  
  41. private char * line_cnt();
  42.  
  43. private void
  44.     BufNSelect(),
  45.     defb_wind(),
  46.     kill_buf(),
  47.     mkbuflist();
  48. #endif    /* LINT_ARGS */
  49.  
  50. #ifdef MAC
  51. #    undef private
  52. #    define private static
  53. #endif
  54.  
  55. char    *Mainbuf = "Main",
  56.     *NoName = "Sans un nom!";
  57.  
  58. Buffer    *world = 0,        /* First in the list */
  59.     *curbuf = 0,
  60.     *lastbuf = 0;    /* Last buffer we were in so we have a default
  61.                buffer during a select buffer. */
  62.  
  63. /* Toggle BIT in the current buffer's minor mode flags.  If argument is
  64.    supplied, a positive one always turns on the mode and zero argument
  65.    always turns it off. */
  66.  
  67. void
  68. TogMinor(bit)
  69. {
  70.     if (is_an_arg()) {
  71.         if (arg_value() == 0)
  72.             curbuf->b_minor &= ~bit;
  73.         else
  74.             curbuf->b_minor |= bit;
  75.     } else
  76.         curbuf->b_minor ^= bit;
  77.     UpdModLine = YES;
  78. }
  79.  
  80. /* Creates a new buffer, links it at the end of the buffer chain, and
  81.    returns it. */
  82.  
  83. static Buffer *
  84. buf_alloc()
  85. {
  86.     register Buffer    *b,
  87.             *lastbp;
  88.  
  89.     lastbp = 0;
  90.     for (b = world; b != 0; lastbp = b, b = b->b_next)
  91.         ;
  92.  
  93.     b = (Buffer *) emalloc(sizeof (Buffer));
  94.     if (lastbp)
  95.         lastbp->b_next = b;
  96.     else
  97.         world = b;
  98.     b->b_first = 0;
  99.     b->b_next = 0;
  100. #ifdef MAC
  101.     b->Type = BUFFER;    /* kludge, but simplifies menu handlers */
  102.     b->Name = 0;
  103. #endif
  104.     return b;
  105. }
  106.  
  107. /* Makes a buffer and initializes it.  Obsolete.  Used to take two
  108.    arguments, a buffer name and a file name. */
  109.  
  110. static Buffer *
  111. mak_buf()
  112. {
  113.     register Buffer    *newb;
  114.     register int    i;
  115.  
  116.     newb = buf_alloc();
  117.     newb->b_fname = 0;
  118.     newb->b_name = NoName;
  119.     set_ino(newb);
  120.     newb->b_marks = 0;
  121.     newb->b_themark = 0;        /* Index into markring */
  122.     /* No marks yet */
  123.     for (i = 0; i < NMARKS; i++)
  124.         newb->b_markring[i] = 0;
  125.     newb->b_modified = 0;
  126.     newb->b_type = B_FILE;  /* File until proven SCRATCH */
  127.     newb->b_ntbf = 0;
  128.     newb->b_minor = 0;
  129.     newb->b_major = TEXT;
  130.     newb->b_first = 0;
  131.     newb->b_keybinds = 0;
  132. #ifdef IPROCS
  133.     newb->b_process = 0;
  134. #endif
  135.     initlist(newb);
  136. #ifdef MAC
  137.     Bufchange = 1;
  138. #endif
  139.     return newb;
  140. }
  141.  
  142. void
  143. ReNamBuf()
  144. {
  145.     register char    *new = 0,
  146.             *prompt = ProcFmt,
  147.             *second = "%s already exists; new name? ";
  148.  
  149.     for (;;) {
  150.         new = ask((char *) 0, prompt, new);
  151.         if (!buf_exists(new))
  152.             break;
  153.         prompt = second;
  154.     }
  155.     setbname(curbuf, new);
  156. }
  157.  
  158. void
  159. FindFile()
  160. {
  161.     register char    *name;
  162.     char    fnamebuf[FILESIZE];
  163.  
  164.     name = ask_file((char *) 0, curbuf->b_fname, fnamebuf);
  165.     SetABuf(curbuf);
  166.     SetBuf(do_find(curwind, name, 0));
  167. }
  168.  
  169. private void
  170. mkbuflist(bnamp)
  171. register char    **bnamp;
  172. {
  173.     register Buffer    *b;
  174.  
  175.     for (b = world; b != 0; b = b->b_next)
  176.         if (b->b_name != 0)
  177.             *bnamp++ = b->b_name;
  178.     *bnamp = 0;
  179. }
  180.  
  181. char *
  182. ask_buf(def)
  183. Buffer    *def;
  184. {
  185.     char    *bnames[100];
  186.     register char    *bname;
  187.     register int    offset;
  188.     char    prompt[100];
  189.  
  190.     if (def != 0 && def->b_name != 0)
  191.         sprintf(prompt, ": %f (default %s) ", def->b_name);
  192.     else
  193.         sprintf(prompt, ProcFmt);
  194.     mkbuflist(bnames);
  195.     offset = complete(bnames, prompt, RET_STATE);
  196.     if (offset == EOF)
  197.         complain((char *) 0);
  198.     if (offset == ORIGINAL || offset == AMBIGUOUS)
  199.         bname = Minibuf;
  200.     else if (offset == NULLSTRING) {
  201.         if (def)
  202.             bname = def->b_name;
  203.         else
  204.             complain((char *) 0);
  205.     } else if (offset < 0)
  206.         complain((char *) 0);
  207.     else
  208.         bname = bnames[offset];
  209.  
  210.     return bname;
  211. }
  212.  
  213. void
  214. BufSelect()
  215. {
  216.     register char    *bname;
  217.  
  218.     bname = ask_buf(lastbuf);
  219.     SetABuf(curbuf);
  220.     SetBuf(do_select(curwind, bname));
  221. }
  222.  
  223. #ifdef MSDOS
  224.  
  225. private void
  226. BufNSelect(n)
  227. {
  228.     char *bnames[100];
  229.     char *bname;
  230.     int i;
  231.  
  232.     mkbuflist(bnames);
  233.        for (i=0; i<n; i++)
  234.         if (bnames[i] == 0)
  235.            complain("[No such buffer]");
  236.     bname = bnames[n-1];
  237.     SetABuf(curbuf);
  238.     SetBuf(do_select(curwind, bname));
  239. }
  240.  
  241. void Buf1Select() { BufNSelect(1); }
  242. void Buf2Select() { BufNSelect(2); }
  243. void Buf3Select() { BufNSelect(3); }
  244. void Buf4Select() { BufNSelect(4); }
  245. void Buf5Select() { BufNSelect(5); }
  246. void Buf6Select() { BufNSelect(6); }
  247. void Buf7Select() { BufNSelect(7); }
  248. void Buf8Select() { BufNSelect(8); }
  249. void Buf9Select() { BufNSelect(9); }
  250. void Buf10Select() { BufNSelect(10); }
  251.  
  252. #endif /* MSDOS */
  253.  
  254. private void
  255. defb_wind(b)
  256. register Buffer *b;
  257. {
  258.     register Window    *w = fwind;
  259.     char    *alt;
  260.  
  261.     if (lastbuf == b || lastbuf == 0) {
  262.         lastbuf = 0;
  263.         alt = (b->b_next != 0) ? b->b_next->b_name : Mainbuf;
  264.     } else
  265.         alt = lastbuf->b_name;
  266.  
  267.     do {
  268.         if (w->w_bufp == b) {
  269.             if (one_windp() || alt != Mainbuf)
  270.                 (void) do_select(w, alt);
  271.             else {
  272.                 Window    *save = w->w_next;
  273.                 del_wind(w);
  274.                 w = save->w_prev;
  275.             }
  276.         }
  277.         w = w->w_next;
  278.     } while (w != fwind || w->w_bufp == b);
  279. }
  280.  
  281. Buffer *
  282. getNMbuf()
  283. {
  284.     register Buffer    *delbuf;
  285.     register char    *bname;
  286.  
  287.     bname = ask_buf(curbuf);
  288.     if ((delbuf = buf_exists(bname)) == 0)
  289.         complain("[No such buffer]");
  290.     if (delbuf->b_modified)
  291.         confirm("%s modified, are you sure? ", bname);
  292.     return delbuf;
  293. }
  294.  
  295. void
  296. BufErase()
  297. {
  298.     register Buffer    *delbuf;
  299.  
  300.     if (delbuf = getNMbuf()) {
  301.         initlist(delbuf);
  302.         delbuf->b_modified = 0;
  303.     }
  304. }
  305.  
  306. private void
  307. kill_buf(delbuf)
  308. register Buffer    *delbuf;
  309. {
  310.     register Buffer    *b,
  311.             *lastb = 0;
  312. #ifndef MAC
  313.     extern Buffer    *perr_buf;
  314. #endif
  315.  
  316. #ifdef IPROCS
  317.     pbuftiedp(delbuf);    /* check for lingering processes */
  318. #endif
  319.     for (b = world; b != 0; lastb = b, b = b->b_next)
  320.         if (b == delbuf)
  321.             break;
  322.     if (lastb)
  323.         lastb->b_next = delbuf->b_next;
  324.     else
  325.         world = delbuf->b_next;
  326.  
  327. #define okay_free(ptr)    if (ptr) free(ptr)
  328.  
  329.     lfreelist(delbuf->b_first);
  330.     okay_free(delbuf->b_name);
  331.     okay_free(delbuf->b_fname);
  332.     flush_marks(delbuf);
  333.     free((char *) delbuf);
  334.  
  335.     if (delbuf == lastbuf)
  336.         SetABuf(curbuf);
  337. #ifndef MAC
  338.     if (perr_buf == delbuf) {
  339.         ErrFree();
  340.         perr_buf = 0;
  341.     }
  342. #endif
  343.     defb_wind(delbuf);
  344.     if (curbuf == delbuf)
  345.         SetBuf(curwind->w_bufp);
  346. #ifdef MAC
  347.     Bufchange = 1;
  348. #endif
  349. }
  350.  
  351. /* offer to kill some buffers */
  352.  
  353. void
  354. KillSome()
  355. {
  356.     register Buffer    *b,
  357.             *next;
  358.     Buffer    *oldb;
  359.     register char    *y_or_n;
  360.  
  361.     for (b = world; b != 0; b = next) {
  362.         next = b->b_next;
  363.         if (yes_or_no_p("Kill %s? ", b->b_name) == NO)
  364.             continue;
  365.         if (IsModified(b)) {
  366.             y_or_n = ask("No", "%s modified; should I save it? ", b->b_name);
  367.             if (CharUpcase(*y_or_n) == 'Y') {
  368.                 oldb = curbuf;
  369.                 SetBuf(b);
  370.                 SaveFile();
  371.                 SetBuf(oldb);
  372.             }
  373.         }
  374.         kill_buf(b);
  375.     }
  376. }
  377.  
  378. void
  379. BufKill()
  380. {
  381.     Buffer    *b;
  382.  
  383.     if ((b = getNMbuf()) == 0)
  384.         return;
  385.     kill_buf(b);
  386. }
  387.  
  388. private char *
  389. line_cnt(b, buf)
  390. register Buffer    *b;
  391. char    *buf;
  392. {
  393.     register int    nlines = 0;
  394.     register Line    *lp;
  395.  
  396.     for (lp = b->b_first; lp != 0; lp = lp->l_next, nlines++)
  397.         ;
  398.     sprintf(buf, "%d", nlines);
  399.     return buf;
  400. }
  401.  
  402. private char    *TypeNames[] = {
  403.     0,
  404.     "Scratch",
  405.     "File",
  406.     "Process",
  407. };
  408.  
  409. void
  410. BufList()
  411. {
  412.     register char    *format = "%-2s %-5s %-11s %-1s %-*s  %-s";
  413.     register Buffer    *b;
  414.     int    bcount = 1,        /* To give each buffer a number */
  415.         buf_width = 11;
  416.     char    nbuf[10];
  417.  
  418.     for (b = world; b != 0; b = b->b_next)
  419.         buf_width = max(buf_width, strlen(b->b_name));
  420.  
  421.     TOstart("Buffer list", TRUE);    /* true means auto-newline */
  422.  
  423.     Typeout("(* means buffer needs saving)");
  424.     Typeout("(+ means file hasn't been read yet)");
  425.     Typeout(NullStr);
  426.     Typeout(format, "NO", "Lines", "Type", NullStr, buf_width, "Name", "File");
  427.     Typeout(format, "--", "-----", "----", NullStr, buf_width, "----", "----");
  428.     for (b = world; b != 0; b = b->b_next) {
  429.         Typeout(format, itoa(bcount++),
  430.                 line_cnt(b, nbuf),
  431.                 TypeNames[b->b_type],
  432.                 IsModified(b) ? "*" :
  433.                      b->b_ntbf ? "+" : NullStr,
  434.                 buf_width,
  435.                 /* For the * (variable length field) */
  436.                 b->b_name,
  437.                 filename(b));
  438.  
  439.         if (TOabort)
  440.             break;
  441.     }
  442.     TOstop();
  443. }
  444.  
  445. void
  446. bufname(b)
  447. register Buffer    *b;
  448. {
  449.     char    tmp[100],
  450.         *cp;
  451.     int    try = 1;
  452.  
  453.     if (b->b_fname == 0)
  454.         complain("[No file name]");
  455.     cp = basename(b->b_fname);
  456.     strcpy(tmp, cp);
  457.     while (buf_exists(tmp)) {
  458.         sprintf(tmp, "%s.%d", cp, try);
  459.         try += 1;
  460.     }
  461.     setbname(b, tmp);
  462. }
  463.  
  464. void
  465. initlist(b)
  466. register Buffer    *b;
  467. {
  468.     lfreelist(b->b_first);
  469.     b->b_first = b->b_dot = b->b_last = 0;
  470.     (void) listput(b, b->b_first);
  471.     
  472.     SavLine(b->b_dot, NullStr);
  473.     b->b_char = 0;
  474.     AllMarkSet(b, b->b_dot, 0);
  475.     if (b == curbuf)
  476.         getDOT();
  477. }
  478.  
  479. /* Returns pointer to buffer with name NAME, or if NAME is a string of digits
  480.    returns the buffer whose number equals those digits.  Otherwise, returns
  481.    0. */
  482.  
  483. Buffer *
  484. buf_exists(name)
  485. register char    *name;
  486. {
  487.     register Buffer    *bp;
  488.     int    n;
  489.  
  490.     if (name == 0)
  491.         return 0;
  492.  
  493.     for (bp = world; bp != 0; bp = bp->b_next)
  494.         if (strcmp(bp->b_name, name) == 0)
  495.             return bp;
  496.  
  497.     /* Doesn't match any names.  Try for a buffer number... */
  498.  
  499.     if (chr_to_int(name, 10, YES, &n) != INT_BAD) {
  500.         for (bp = world; n > 1; bp = bp->b_next) {
  501.             if (bp == 0)
  502.                 break;
  503.             n -= 1;
  504.         }
  505.         return bp;
  506.     }
  507.  
  508.     return 0;
  509. }
  510.  
  511. /* Returns buffer pointer with a file name NAME, if one exists.  Stat's the
  512.    file and compares inodes, in case NAME is a link, as well as the actual
  513.    characters that make up the file name. */
  514.  
  515. Buffer *
  516. file_exists(name)
  517. register char    *name;
  518. {
  519.     struct stat    stbuf;
  520.     register struct stat    *s = &stbuf;
  521.     register Buffer    *b = 0;
  522.     char    fnamebuf[FILESIZE];
  523.  
  524. #ifdef MSDOS
  525.     strlwr(name);
  526. #endif /* MSDOS */
  527.     if (name) {
  528.         PathParse(name, fnamebuf);
  529.         if (stat(fnamebuf, s) == -1)
  530.             s->st_ino = 0;
  531.         for (b = world; b != 0; b = b->b_next) {
  532. #ifndef MSDOS
  533.             if ((b->b_ino != 0 && b->b_ino == s->st_ino &&
  534.                  b->b_dev != 0 && b->b_dev == s->st_dev) ||
  535. #else /* MSDOS */
  536.             if ( /* (b->b_ino != 0 && b->b_ino == s->st_ino) || */
  537. #endif /* MSDOS */
  538.                 (strcmp(b->b_fname, fnamebuf) == 0))
  539.                 break;
  540.         }
  541.     }
  542.     return b;
  543. }
  544.  
  545. char *
  546. ralloc(obj, size)
  547. register char    *obj;
  548. {
  549.     register char    *new;
  550.  
  551.     if (obj)
  552.         new = realloc(obj, (unsigned) size);
  553.     if (new == 0 || !obj)
  554.         new = emalloc(size);
  555.     return new;
  556. }
  557.  
  558. void
  559. setbname(b, name)
  560. register Buffer    *b;
  561. register char    *name;
  562. {
  563.     UpdModLine = YES;    /* Kludge ... but speeds things up considerably */
  564.     if (name) {
  565.         if (b->b_name == NoName)
  566.             b->b_name = 0;
  567.         b->b_name = ralloc(b->b_name, strlen(name) + 1);
  568.         strcpy(b->b_name, name);
  569.     } else
  570.         b->b_name = 0;
  571. #ifdef MAC
  572.     Bufchange = 1;
  573. #endif
  574. }
  575.  
  576. void
  577. setfname(b, name)
  578. register Buffer    *b;
  579. register char    *name;
  580. {
  581.     char    wholename[FILESIZE],
  582.         oldname[FILESIZE],
  583.         *oldptr = oldname;
  584.     Buffer    *save = curbuf;
  585.  
  586.     SetBuf(b);
  587.     UpdModLine = YES;    /* Kludge ... but speeds things up considerably */
  588.     if (b->b_fname == 0)
  589.         oldptr = 0;
  590.     else
  591.         strcpy(oldname, b->b_fname);
  592.     if (name) {
  593. #ifdef MSDOS
  594.         strlwr(name);
  595. #endif /* MSDOS */
  596.         PathParse(name, wholename);
  597.         curbuf->b_fname = ralloc(curbuf->b_fname, strlen(wholename) + 1);
  598.         strcpy(curbuf->b_fname, wholename);
  599.     } else
  600.         b->b_fname = 0;
  601.     DoAutoExec(curbuf->b_fname, oldptr);
  602.     curbuf->b_mtime = curbuf->b_dev = curbuf->b_ino = 0;    /* until they're known. */
  603.     SetBuf(save);
  604. #ifdef MAC
  605.     Bufchange = 1;
  606. #endif
  607. }
  608.  
  609. void
  610. set_ino(b)
  611. register Buffer    *b;
  612. {
  613.     struct stat    stbuf;
  614.  
  615.     if (b->b_fname == 0 || stat(pr_name(b->b_fname, NO), &stbuf) == -1) {
  616.          b->b_dev = 0;
  617.         b->b_ino = 0;
  618.         b->b_mtime = 0;
  619.     } else {
  620.          b->b_dev = stbuf.st_dev;
  621.         b->b_ino = stbuf.st_ino;
  622.         b->b_mtime = stbuf.st_mtime;
  623.     }
  624. }
  625.  
  626. /* Find the file `fname' into buf and put in in window `w' */
  627.  
  628. Buffer *
  629. do_find(w, fname, force)
  630. register Window    *w;
  631. register char    *fname;
  632. {
  633.     register Buffer    *b;
  634.  
  635.     b = file_exists(fname);
  636.     if (b == 0) {
  637.         b = mak_buf();
  638.         setfname(b, fname);
  639.         bufname(b);
  640.         set_ino(b);
  641.         b->b_ntbf = 1;
  642.     }
  643.     if (force) {
  644.         Buffer    *oldb = curbuf;
  645.  
  646.         SetBuf(b);    /* this'll read the file */
  647.         SetBuf(oldb);
  648.     }
  649.     if (w)
  650.         tiewind(w, b);
  651.     return b;
  652. }
  653.  
  654. /* set alternate buffer */
  655.  
  656. void
  657. SetABuf(b)
  658. Buffer    *b;
  659. {
  660.     if (b != 0)
  661.         lastbuf = b;
  662. }
  663.  
  664.  
  665. /* check to see if BP is a valid buffer pointer */
  666. int
  667. valid_bp(bp)
  668. register Buffer    *bp;
  669. {
  670.     register Buffer    *b;
  671.  
  672.     for (b = world; b != 0; b = b->b_next)
  673.         if (b == bp)
  674.             break;
  675.     return b != 0;
  676. }
  677.  
  678. void
  679. SetBuf(newbuf)
  680. register Buffer    *newbuf;
  681. {
  682.     register Buffer    *oldb = curbuf,
  683.             *b;
  684.  
  685.     if (newbuf == curbuf || newbuf == 0)
  686.         return;
  687.  
  688.     if (!valid_bp(newbuf))
  689.         complain("Internal error: (0x%x) is not a valid buffer pointer!", newbuf);
  690.     lsave();
  691.     curbuf = newbuf;
  692.     curline = newbuf->b_dot;
  693.     curchar = newbuf->b_char;
  694.     getDOT();
  695.     /* do the read now ... */
  696.     if (curbuf->b_ntbf)
  697.         read_file(curbuf->b_fname, 0);
  698. #ifdef MAC
  699.     Modechange = 1;
  700. #endif
  701.  
  702. #ifdef IPROCS
  703.     if (oldb != 0 && ((oldb->b_process == 0) != (curbuf->b_process == 0))) {
  704.         if (curbuf->b_process)
  705.             PushPBs();        /* Push process bindings */
  706.         else if (oldb->b_process)
  707.             PopPBs();
  708.     }
  709. #endif
  710. }
  711.  
  712. Buffer *
  713. do_select(w, name)
  714. register Window    *w;
  715. register char    *name;
  716. {
  717.     register Buffer    *new;
  718.  
  719.     if ((new = buf_exists(name)) == 0) {
  720.         new = mak_buf();
  721.         setfname(new, (char *) 0);
  722.         setbname(new, name);
  723.     }
  724.     if (w)
  725.         tiewind(w, new);
  726.     return new;
  727. }
  728.