home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 January / usenetsourcesnewsgroupsinfomagicjanuary1994.iso / sources / unix / volume8 / jove / part01 / buf.c < prev    next >
Encoding:
C/C++ Source or Header  |  1987-02-02  |  10.8 KB  |  592 lines

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