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