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