home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 January / usenetsourcesnewsgroupsinfomagicjanuary1994.iso / sources / unix / volume6 / uemacs3.7 / part05 < prev    next >
Encoding:
Internet Message Format  |  1986-11-30  |  44.9 KB

  1. Subject: v06i075:  MicroEmacs, Version 3.7 (uEmacs3.7), Part05/12
  2. Newsgroups: mod.sources
  3. Approved: rs@mirror.UUCP
  4.  
  5. Submitted by: ihnp4!pur-ee!pur-phy!duncan!lawrence
  6. Mod.sources: Volume 6, Issue 75
  7. Archive-name: uEmacs3.7/Part05
  8.  
  9. [  This is the latest revision of one of two programs named "MicroEmacs";
  10.    when discussing these on the net, or in contacting the authors, make
  11.    sure to mention the version number -- in this case 3.7 -- as that is
  12.    the easiest way to distinguish between them.  Daniel will be posting
  13.    uuencoded executables in net.micro.pc and net.micro.amiga; the file
  14.    'readme' contains information on how to also get these from him
  15.    directly.   --r$ ]
  16.  
  17. echo extracting - epath.h
  18. sed 's/^X//' > epath.h << 'FRIDAY_NIGHT'
  19. X/*    PATH:    This file contains certain info needed to locate the
  20. X        MicroEMACS files on a system dependant basis.
  21. X
  22. X                                    */
  23. X
  24. X/*    possible names and paths of help files under different OSs    */
  25. X
  26. Xchar *pathname[] =
  27. X
  28. X#if    AMIGA
  29. X{
  30. X    ".emacsrc",
  31. X    "emacs.hlp",
  32. X    "",
  33. X    ":c/",
  34. X    ":t/"
  35. X};
  36. X#endif
  37. X
  38. X#if    MSDOS
  39. X{
  40. X    "emacs.rc",
  41. X    "emacs.hlp",
  42. X    "\\sys\\public\\",
  43. X    "\\usr\\bin\\",
  44. X    "\\bin\\",
  45. X    "\\",
  46. X    ""
  47. X};
  48. X#endif
  49. X
  50. X#if    V7 | BSD | USG
  51. X{
  52. X    ".emacsrc",
  53. X    "emacs.hlp",
  54. X    "/usr/local/",
  55. X    "/usr/lib/",
  56. X    ""
  57. X};
  58. X#endif
  59. X
  60. X#if    VMS
  61. X{
  62. X    "emacs.rc",
  63. X    "emacs.hlp",
  64. X    "",
  65. X    "sys$sysdevice:[vmstools]"
  66. X};
  67. X#endif
  68. X
  69. X#define    NPNAMES    (sizeof(pathname)/sizeof(char *))
  70. FRIDAY_NIGHT
  71. echo extracting - estruct.h
  72. sed 's/^X//' > estruct.h << 'FRIDAY_NIGHT'
  73. X/*    ESTRUCT:    Structure and preprocesser defined for
  74. X            MicroEMACS 3.7
  75. X
  76. X            written by Dave G. Conroy
  77. X            modified by Steve Wilhite, George Jones
  78. X            greatly modified by Daniel Lawrence
  79. X*/
  80. X
  81. X#undef    LATTICE        /* don't use their definitions...use ours    */
  82. X#undef    MSDOS
  83. X#undef    CPM
  84. X#undef    AMIGA
  85. X
  86. X/*    Machine/OS definitions            */
  87. X
  88. X#define AMIGA   0                       /* AmigaDOS            */
  89. X#define ST520   0                       /* ST520, TOS                   */
  90. X#define MSDOS   0                       /* MS-DOS                       */
  91. X#define V7      1                       /* V7 UN*X or Coherent or BSD4.2*/
  92. X#define    BSD    0            /* UNIX BSD 4.2    and ULTRIX    */
  93. X#define    USG    0            /* UNIX system V        */
  94. X#define VMS     0                       /* VAX/VMS                      */
  95. X#define CPM     0                       /* CP/M-86                      */
  96. X
  97. X/*    Compiler definitions            */
  98. X#define MWC86   0    /* marc williams compiler */
  99. X#define    LATTICE    0    /* either lattice compiler */
  100. X#define    LAT2    0    /* Lattice 2.15 */
  101. X#define    LAT3    0    /* Lattice 3.0 */
  102. X#define    AZTEC    0    /* Aztec C 3.20e */
  103. X#define    MSC    0    /* MicroSoft C compile version 3 */
  104. X
  105. X/*    Profiling options    */
  106. X#define    APROF    0    /* turn Aztec C profiling on? */
  107. X#define    NBUCK    100    /* number of buckets to profile */
  108. X
  109. X/*   Special keyboard definitions            */
  110. X#define WANGPC    0            /* WangPC - mostly escape sequences     */
  111. X/*    Terminal Output definitions        */
  112. X
  113. X#define ANSI    0            /* ansi escape sequences    */
  114. X#define    HP150    0            /* HP150 screen driver        */
  115. X#define    VMSVT    0            /* various VMS terminal entries    */
  116. X#define VT52    0                       /* VT52 terminal (Zenith).      */
  117. X#define VT100   0                       /* Handle VT100 style keypad.   */
  118. X#define LK201   0                       /* Handle LK201 style keypad.   */
  119. X#define RAINBOW 0                       /* Use Rainbow fast video.      */
  120. X#define TERMCAP 1                       /* Use TERMCAP                  */
  121. X#define    IBMPC    0            /* IBM-PC specific driver    */
  122. X#define    DG10    0            /* Data General system/10    */
  123. X
  124. X/*    Configuration options    */
  125. X
  126. X#define CVMVAS  1    /* arguments to page forward/back in pages    */
  127. X#define    NFWORD    1    /* forward word jumps to begining of word    */
  128. X#define    CLRMSG    0    /* space clears the message line with no insert    */
  129. X#define    TYPEAH    1    /* type ahead causes update to be skipped    */
  130. X#define    FILOCK    0    /* file locking under unix BSD 4.2        */
  131. X#define    REVSTA    1    /* Status line appears in reverse video        */
  132. X#define    COLOR    0    /* color commands and windows            */
  133. X#define    ACMODE    1    /* auto CMODE on .C and .H files        */
  134. X#define    CFENCE    1    /* fench matching in CMODE            */
  135. X#define    ISRCH    1    /* Incremental searches like ITS EMACS        */
  136. X#define    WORDPRO    1    /* Advanced word processing features        */
  137. X
  138. X/*    System dependant library redefinitions, structures and includes    */
  139. X
  140. X#if    MSDOS & AZTEC
  141. X#undef    fputc
  142. X#undef    fgetc
  143. X#define    fputc    aputc
  144. X#define    fgetc    agetc
  145. X#define    int86    sysint
  146. X#define    inp    inportb
  147. X
  148. Xstruct XREG {
  149. X    int ax,bx,cx,dx,si,di;
  150. X};
  151. X
  152. Xstruct HREG {
  153. X    char al,ah,bl,bh,cl,ch,dl,dh;
  154. X};
  155. X
  156. Xunion REGS {
  157. X    struct XREG x;
  158. X    struct HREG h;
  159. X};
  160. X#endif
  161. X
  162. X#if    MSDOS & LATTICE
  163. X#undef    CPM
  164. X#undef    LATTICE
  165. X#include    <dos.h>
  166. X#undef    CPM
  167. X#endif
  168. X
  169. X/*    internal constants    */
  170. X
  171. X#define    NBINDS    200            /* max # of bound keys        */
  172. X#define NFILEN  80                      /* # of bytes, file name        */
  173. X#define NBUFN   16                      /* # of bytes, buffer name      */
  174. X#define NLINE   256                     /* # of bytes, line             */
  175. X#define    NSTRING    256            /* # of bytes, string buffers    */
  176. X#define NKBDM   256                     /* # of strokes, keyboard macro */
  177. X#define NPAT    80                      /* # of bytes, pattern          */
  178. X#define HUGE    1000                    /* Huge number                  */
  179. X#define    NLOCKS    100            /* max # of file locks active    */
  180. X#define    NCOLORS    8            /* number of supported colors    */
  181. X#define    KBLOCK    250            /* sizeof kill buffer chunks    */
  182. X#define    NBLOCK    16            /* line block chunk size    */
  183. X
  184. X#define AGRAVE  0x60                    /* M- prefix,   Grave (LK201)   */
  185. X#define METACH  0x1B                    /* M- prefix,   Control-[, ESC  */
  186. X#define CTMECH  0x1C                    /* C-M- prefix, Control-\       */
  187. X#define EXITCH  0x1D                    /* Exit level,  Control-]       */
  188. X#define CTRLCH  0x1E                    /* C- prefix,   Control-^       */
  189. X#define HELPCH  0x1F                    /* Help key,    Control-_       */
  190. X
  191. X#define CTRL    0x0100                  /* Control flag, or'ed in       */
  192. X#define META    0x0200                  /* Meta flag, or'ed in          */
  193. X#define CTLX    0x0400                  /* ^X flag, or'ed in            */
  194. X#define    SPEC    0x0800            /* special key (function keys)    */
  195. X
  196. X#define FALSE   0                       /* False, no, bad, etc.         */
  197. X#define TRUE    1                       /* True, yes, good, etc.        */
  198. X#define ABORT   2                       /* Death, ^G, abort, etc.       */
  199. X
  200. X#define FIOSUC  0                       /* File I/O, success.           */
  201. X#define FIOFNF  1                       /* File I/O, file not found.    */
  202. X#define FIOEOF  2                       /* File I/O, end of file.       */
  203. X#define FIOERR  3                       /* File I/O, error.             */
  204. X#define    FIOLNG    4            /*line longer than allowed len    */
  205. X
  206. X#define CFCPCN  0x0001                  /* Last command was C-P, C-N    */
  207. X#define CFKILL  0x0002                  /* Last command was a kill      */
  208. X
  209. X#define    BELL    0x07            /* a bell character        */
  210. X#define    TAB    0x09            /* a tab character        */
  211. X
  212. X/*
  213. X * There is a window structure allocated for every active display window. The
  214. X * windows are kept in a big list, in top to bottom screen order, with the
  215. X * listhead at "wheadp". Each window contains its own values of dot and mark.
  216. X * The flag field contains some bits that are set by commands to guide
  217. X * redisplay; although this is a bit of a compromise in terms of decoupling,
  218. X * the full blown redisplay is just too expensive to run for every input
  219. X * character.
  220. X */
  221. Xtypedef struct  WINDOW {
  222. X        struct  WINDOW *w_wndp;         /* Next window                  */
  223. X        struct  BUFFER *w_bufp;         /* Buffer displayed in window   */
  224. X        struct  LINE *w_linep;          /* Top line in the window       */
  225. X        struct  LINE *w_dotp;           /* Line containing "."          */
  226. X        short   w_doto;                 /* Byte offset for "."          */
  227. X        struct  LINE *w_markp;          /* Line containing "mark"       */
  228. X        short   w_marko;                /* Byte offset for "mark"       */
  229. X        char    w_toprow;               /* Origin 0 top row of window   */
  230. X        char    w_ntrows;               /* # of rows of text in window  */
  231. X        char    w_force;                /* If NZ, forcing row.          */
  232. X        char    w_flag;                 /* Flags.                       */
  233. X#if    COLOR
  234. X    char    w_fcolor;        /* current forground color    */
  235. X    char    w_bcolor;        /* current background color    */
  236. X#endif
  237. X}       WINDOW;
  238. X
  239. X#define WFFORCE 0x01                    /* Window needs forced reframe  */
  240. X#define WFMOVE  0x02                    /* Movement from line to line   */
  241. X#define WFEDIT  0x04                    /* Editing within a line        */
  242. X#define WFHARD  0x08                    /* Better to a full display     */
  243. X#define WFMODE  0x10                    /* Update mode line.            */
  244. X#define    WFCOLR    0x20            /* Needs a color change        */
  245. X
  246. X/*
  247. X * Text is kept in buffers. A buffer header, described below, exists for every
  248. X * buffer in the system. The buffers are kept in a big list, so that commands
  249. X * that search for a buffer by name can find the buffer header. There is a
  250. X * safe store for the dot and mark in the header, but this is only valid if
  251. X * the buffer is not being displayed (that is, if "b_nwnd" is 0). The text for
  252. X * the buffer is kept in a circularly linked list of lines, with a pointer to
  253. X * the header line in "b_linep".
  254. X *     Buffers may be "Inactive" which means the files accosiated with them
  255. X * have not been read in yet. These get read in at "use buffer" time.
  256. X */
  257. Xtypedef struct  BUFFER {
  258. X        struct  BUFFER *b_bufp;         /* Link to next BUFFER          */
  259. X        struct  LINE *b_dotp;           /* Link to "." LINE structure   */
  260. X        short   b_doto;                 /* Offset of "." in above LINE  */
  261. X        struct  LINE *b_markp;          /* The same as the above two,   */
  262. X        short   b_marko;                /* but for the "mark"           */
  263. X        struct  LINE *b_linep;          /* Link to the header LINE      */
  264. X    char    b_active;        /* window activated flag    */
  265. X        char    b_nwnd;                 /* Count of windows on buffer   */
  266. X        char    b_flag;                 /* Flags                        */
  267. X    char    b_mode;            /* editor mode of this buffer    */
  268. X        char    b_fname[NFILEN];        /* File name                    */
  269. X        char    b_bname[NBUFN];         /* Buffer name                  */
  270. X}       BUFFER;
  271. X
  272. X#define BFINVS  0x01                    /* Internal invisable buffer    */
  273. X#define BFCHG   0x02                    /* Changed since last write     */
  274. X
  275. X/*    mode flags    */
  276. X#define    NUMMODES    7        /* # of defined modes        */
  277. X
  278. X#define    MDWRAP    0x0001            /* word wrap            */
  279. X#define    MDCMOD    0x0002            /* C indentation and fence match*/
  280. X#define    MDSPELL    0x0004            /* spell error parcing        */
  281. X#define    MDEXACT    0x0008            /* Exact matching for searches    */
  282. X#define    MDVIEW    0x0010            /* read-only buffer        */
  283. X#define MDOVER    0x0020            /* overwrite mode        */
  284. X#define MDMAGIC    0x0040            /* regular expresions in search */
  285. X
  286. X/*
  287. X * The starting position of a region, and the size of the region in
  288. X * characters, is kept in a region structure.  Used by the region commands.
  289. X */
  290. Xtypedef struct  {
  291. X        struct  LINE *r_linep;          /* Origin LINE address.         */
  292. X        short   r_offset;               /* Origin LINE offset.          */
  293. X        long    r_size;                 /* Length in characters.        */
  294. X}       REGION;
  295. X
  296. X/*
  297. X * All text is kept in circularly linked lists of "LINE" structures. These
  298. X * begin at the header line (which is the blank line beyond the end of the
  299. X * buffer). This line is pointed to by the "BUFFER". Each line contains a the
  300. X * number of bytes in the line (the "used" size), the size of the text array,
  301. X * and the text. The end of line is not stored as a byte; it's implied. Future
  302. X * additions will include update hints, and a list of marks into the line.
  303. X */
  304. Xtypedef struct  LINE {
  305. X        struct  LINE *l_fp;             /* Link to the next line        */
  306. X        struct  LINE *l_bp;             /* Link to the previous line    */
  307. X        short   l_size;                 /* Allocated size               */
  308. X        short   l_used;                 /* Used size                    */
  309. X        char    l_text[1];              /* A bunch of characters.       */
  310. X}       LINE;
  311. X
  312. X#define lforw(lp)       ((lp)->l_fp)
  313. X#define lback(lp)       ((lp)->l_bp)
  314. X#define lgetc(lp, n)    ((lp)->l_text[(n)]&0xFF)
  315. X#define lputc(lp, n, c) ((lp)->l_text[(n)]=(c))
  316. X#define llength(lp)     ((lp)->l_used)
  317. X
  318. X/*
  319. X * The editor communicates with the display using a high level interface. A
  320. X * "TERM" structure holds useful variables, and indirect pointers to routines
  321. X * that do useful operations. The low level get and put routines are here too.
  322. X * This lets a terminal, in addition to having non standard commands, have
  323. X * funny get and put character code too. The calls might get changed to
  324. X * "termp->t_field" style in the future, to make it possible to run more than
  325. X * one terminal type.
  326. X */
  327. Xtypedef struct  {
  328. X        short   t_nrow;                 /* Number of rows.              */
  329. X        short   t_ncol;                 /* Number of columns.           */
  330. X    short    t_margin;        /* min margin for extended lines*/
  331. X    short    t_scrsiz;        /* size of scroll region "    */
  332. X    int    t_pause;        /* # times thru update to pause */
  333. X        int     (*t_open)();            /* Open terminal at the start.  */
  334. X        int     (*t_close)();           /* Close terminal at end.       */
  335. X        int     (*t_getchar)();         /* Get character from keyboard. */
  336. X        int     (*t_putchar)();         /* Put character to display.    */
  337. X        int     (*t_flush)();           /* Flush output buffers.        */
  338. X        int     (*t_move)();            /* Move the cursor, origin 0.   */
  339. X        int     (*t_eeol)();            /* Erase to end of line.        */
  340. X        int     (*t_eeop)();            /* Erase to end of page.        */
  341. X        int     (*t_beep)();            /* Beep.                        */
  342. X    int    (*t_rev)();        /* set reverse video state    */
  343. X#if    COLOR
  344. X    int    (*t_setfor)();        /* set forground color        */
  345. X    int    (*t_setback)();        /* set background color        */
  346. X#endif
  347. X}       TERM;
  348. X
  349. X/*    structure for the table of initial key bindings        */
  350. X
  351. Xtypedef struct  {
  352. X        short   k_code;                 /* Key code                     */
  353. X        int     (*k_fp)();              /* Routine to handle it         */
  354. X}       KEYTAB;
  355. X
  356. X/*    structure for the name binding table        */
  357. X
  358. Xtypedef struct {
  359. X    char *n_name;        /* name of function key */
  360. X    int (*n_func)();    /* function name is bound to */
  361. X}    NBIND;
  362. X
  363. X/*    The editor holds deleted text chunks in the KILL buffer. The
  364. X    kill buffer is logically a stream of ascii characters, however
  365. X    due to its unpredicatable size, it gets implemented as a linked
  366. X    list of chunks. (The d_ prefix is for "deleted" text, as k_
  367. X    was taken up by the keycode structure            */
  368. X
  369. Xtypedef    struct KILL {
  370. X    struct KILL *d_next;    /* link to next chunk, NULL if last */
  371. X    char d_chunk[KBLOCK];    /* deleted text */
  372. X} KILL;
  373. X
  374. FRIDAY_NIGHT
  375. echo extracting - exec.c
  376. sed 's/^X//' > exec.c << 'FRIDAY_NIGHT'
  377. X/*    This file is for functions dealing with execution of
  378. X    commands, command lines, buffers, files and startup files
  379. X
  380. X    written 1986 by Daniel Lawrence                */
  381. X
  382. X#include    <stdio.h>
  383. X#include    "estruct.h"
  384. X#include    "edef.h"
  385. X
  386. X/* namedcmd:    execute a named command even if it is not bound
  387. X*/
  388. X
  389. Xnamedcmd(f, n)
  390. X
  391. Xint f, n;    /* command arguments [passed through to command executed] */
  392. X
  393. X{
  394. X    register (*kfunc)();    /* ptr to the requexted function to bind to */
  395. X    int (*getname())();
  396. X
  397. X    /* prompt the user to type a named command */
  398. X    mlwrite(": ");
  399. X
  400. X    /* and now get the function name to execute */
  401. X    kfunc = getname();
  402. X    if (kfunc == NULL) {
  403. X        mlwrite("[No such function]");
  404. X        return(FALSE);
  405. X    }
  406. X
  407. X    /* and then execute the command */
  408. X    return((*kfunc)(f, n));
  409. X}
  410. X
  411. X/*    execcmd:    Execute a command line command to be typed in
  412. X            by the user                    */
  413. X
  414. Xexeccmd(f, n)
  415. X
  416. Xint f, n;    /* default Flag and Numeric argument */
  417. X
  418. X{
  419. X    register int status;        /* status return */
  420. X    char cmdstr[NSTRING];        /* string holding command to execute */
  421. X
  422. X    /* get the line wanted */
  423. X    if ((status = mlreply(": ", cmdstr, NSTRING)) != TRUE)
  424. X        return(status);
  425. X
  426. X    return(docmd(cmdstr));
  427. X}
  428. X
  429. X/*    docmd:    take a passed string as a command line and translate
  430. X        it to be executed as a command. This function will be
  431. X        used by execute-command-line and by all source and
  432. X        startup files.
  433. X
  434. X    format of the command line is:
  435. X
  436. X        {# arg} <command-name> {<argument string(s)>}
  437. X
  438. X    Macro storing is turned off by a line:
  439. X
  440. X        [end]
  441. X*/
  442. X
  443. Xdocmd(cline)
  444. X
  445. Xchar *cline;    /* command line to execute */
  446. X
  447. X{
  448. X    register char *tp;    /* pointer to current position in token */
  449. X    register int f;        /* default argument flag */
  450. X    register int n;        /* numeric repeat value */
  451. X    register int i;
  452. X    int sign;        /* sign of numeric argument */
  453. X    int (*fnc)();        /* function to execute */
  454. X    int status;        /* return status of function */
  455. X    int oldcle;        /* old contents of clexec flag */
  456. X    int llen;        /* length of cline */
  457. X    struct LINE *lp;    /* a line pointer */
  458. X    char token[NSTRING];    /* next token off of command line */
  459. X    int (*fncmatch())();
  460. X
  461. X    /* check to see if this line turns macro storage off */
  462. X    if (strcmp(cline, "[end]") == 0) {
  463. X        mstore = FALSE;
  464. X        bstore = NULL;
  465. X        return(TRUE);
  466. X    }
  467. X
  468. X    /* if macro store is on, just salt this away */
  469. X    if (mstore) {
  470. X        /* trim leading indentation */
  471. X        while (cline[0] == ' ' || cline[0] == '\t')
  472. X            strcpy(cline, &cline[1]);
  473. X
  474. X        /* allocate the space for the line */
  475. X        llen = strlen(cline);
  476. X        if ((lp=lalloc(llen)) == NULL) {
  477. X            mlwrite("Out of memory while storing macro");
  478. X            return (FALSE);
  479. X        }
  480. X
  481. X        /* copy the text into the new line */
  482. X        for (i=0; i<llen; ++i)
  483. X            lputc(lp, i, cline[i]);
  484. X
  485. X        /* attach the line to the end of the buffer */
  486. X               bstore->b_linep->l_bp->l_fp = lp;
  487. X        lp->l_bp = bstore->b_linep->l_bp;
  488. X        bstore->b_linep->l_bp = lp;
  489. X        lp->l_fp = bstore->b_linep;
  490. X        return (TRUE);
  491. X    }
  492. X    
  493. X    /* first set up the default command values */
  494. X    f = FALSE;
  495. X    n = 1;
  496. X
  497. X    strcpy(sarg, cline);    /* move string to string argument buffer */
  498. X    if ((status = nxtarg(token)) != TRUE)    /* and grab the first token */
  499. X        return(status);
  500. X
  501. X    /* check for and process numeric leadin argument */
  502. X    if ((token[0] >= '0' && token[0] <= '9') || token[0] == '-') {
  503. X        f = TRUE;
  504. X        n = 0;
  505. X        tp = &token[0];
  506. X
  507. X        /* check for a sign! */
  508. X        sign = 1;
  509. X        if (*tp == '-') {
  510. X            ++tp;
  511. X            sign = -1;
  512. X        }
  513. X
  514. X        /* calc up the digits in the token string */
  515. X        while(*tp) {
  516. X            if (*tp >= '0' && *tp <= '9')
  517. X                n = n * 10 + *tp - '0';
  518. X            ++tp;
  519. X        }
  520. X        n *= sign;    /* adjust for the sign */
  521. X
  522. X        /* and now get the command to execute */
  523. X        if ((status = nxtarg(token)) != TRUE)
  524. X            return(status);        
  525. X    }
  526. X
  527. X    /* and match the token to see if it exists */
  528. X    if ((fnc = fncmatch(token)) == NULL) {
  529. X        mlwrite("[No such Function]");
  530. X        return(FALSE);
  531. X    }
  532. X    
  533. X    /* save the arguments and go execute the command */
  534. X    oldcle = clexec;        /* save old clexec flag */
  535. X    clexec = TRUE;            /* in cline execution */
  536. X    status = (*fnc)(f, n);        /* call the function */
  537. X    clexec = oldcle;        /* restore clexec flag */
  538. X    return(status);
  539. X}
  540. X
  541. X/* gettok:    chop a token off a string
  542. X        return a pointer past the token
  543. X*/
  544. X
  545. Xchar *gettok(src, tok)
  546. X
  547. Xchar *src, *tok;    /* source string, destination token string */
  548. X
  549. X{
  550. X    register int quotef;    /* is the current string quoted? */
  551. X
  552. X    /* first scan past any whitespace in the source string */
  553. X    while (*src == ' ' || *src == '\t')
  554. X        ++src;
  555. X
  556. X    /* if quoted, record it */
  557. X    quotef = (*src == '"');
  558. X    if (quotef)
  559. X        ++src;
  560. X
  561. X    /* scan through the source string */
  562. X    while (*src) {
  563. X        /* process special characters */
  564. X        if (*src == '~') {
  565. X            ++src;
  566. X            if (*src == 0)
  567. X                break;
  568. X            switch (*src++) {
  569. X                case 'r':    *tok++ = 13; break;
  570. X                case 'n':    *tok++ = 10; break;
  571. X                case 't':    *tok++ = 9;  break;
  572. X                case 'b':    *tok++ = 8;  break;
  573. X                case 'f':    *tok++ = 12; break;
  574. X                case '@':    *tok++ = 192;break;
  575. X                default:    *tok++ = *(src-1);
  576. X            }
  577. X        } else {
  578. X            /* check for the end of the token */
  579. X            if (quotef) {
  580. X                if (*src == '"')
  581. X                    break;
  582. X            } else {
  583. X                if (*src == ' ' || *src == '\t')
  584. X                    break;
  585. X            }
  586. X
  587. X            /* record the character */
  588. X            *tok++ = *src++;
  589. X        }
  590. X    }
  591. X
  592. X    /* terminate the token and exit */
  593. X    if (*src)
  594. X        ++src;
  595. X    *tok = 0;
  596. X    return(src);
  597. X}
  598. X
  599. X/* nxtarg:    grab the next token out of sarg, return it, and
  600. X        chop it of sarg                    */
  601. X
  602. Xnxtarg(tok)
  603. X
  604. Xchar *tok;    /* buffer to put token into */
  605. X
  606. X{
  607. X    register char *newsarg;    /* pointer to new begining of sarg */
  608. X    register oldexec;    /* saved execution flag */
  609. X    register BUFFER *bp;    /* ptr to buffer to get arg from */
  610. X    register int status;
  611. X    char *gettok();
  612. X
  613. X    newsarg = gettok(sarg, tok);    /* grab the token */
  614. X    strcpy(sarg, newsarg);        /* and chop it of sarg */
  615. X
  616. X    /* check for an interactive argument */
  617. X    if (*tok == '@') {        /* get interactive argument */
  618. X        oldexec = clexec;    /* save execution flag */
  619. X        clexec = FALSE;
  620. X        status = mlreply(&tok[1], &tok[0], NSTRING);
  621. X        clexec = oldexec;
  622. X        if (status != TRUE)
  623. X            return(status);
  624. X    }
  625. X
  626. X    /* check for a quoted "@" in the first position */
  627. X    if (*tok == 192)
  628. X        *tok = '@';
  629. X
  630. X    /* check for an argument from a buffer */
  631. X    if (*tok == '#') {
  632. X
  633. X        /* get the referenced buffer */
  634. X        bp = bfind(&tok[1], FALSE, 0);
  635. X        if (bp == NULL)
  636. X            return(FALSE);
  637. X
  638. X        /* make sure we are not at the end */
  639. X        if (bp->b_linep == bp->b_dotp)
  640. X            return(FALSE);
  641. X
  642. X        /* grab the line as an argument */
  643. X        strncpy(tok, bp->b_dotp->l_text, bp->b_dotp->l_used);
  644. X        tok[bp->b_dotp->l_used] = 0;
  645. X
  646. X        /* and step the buffer's line ptr ahead a line */
  647. X        bp->b_dotp = bp->b_dotp->l_fp;
  648. X        bp->b_doto = 0;
  649. X    }
  650. X
  651. X    return(TRUE);
  652. X}
  653. X
  654. X/*    storemac:    Set up a macro buffer and flag to store all
  655. X            executed command lines there            */
  656. X
  657. Xstoremac(f, n)
  658. X
  659. Xint f;        /* default flag */
  660. Xint n;        /* macro number to use */
  661. X
  662. X{
  663. X    register struct BUFFER *bp;    /* pointer to macro buffer */
  664. X    char bname[NBUFN];        /* name of buffer to use */
  665. X
  666. X    /* must have a numeric argument to this function */
  667. X    if (f == FALSE) {
  668. X        mlwrite("No macro specified");
  669. X        return(FALSE);
  670. X    }
  671. X
  672. X    /* range check the macro number */
  673. X    if (n < 1 || n > 40) {
  674. X        mlwrite("Macro number out of range");
  675. X        return(FALSE);
  676. X    }
  677. X
  678. X    /* construct the macro buffer name */
  679. X    strcpy(bname, "[Macro xx]");
  680. X    bname[7] = '0' + (n / 10);
  681. X    bname[8] = '0' + (n % 10);
  682. X
  683. X    /* set up the new macro buffer */
  684. X    if ((bp = bfind(bname, TRUE, BFINVS)) == NULL) {
  685. X        mlwrite("Can not create macro");
  686. X        return(FALSE);
  687. X    }
  688. X
  689. X    /* and make sure it is empty */
  690. X    bclear(bp);
  691. X
  692. X    /* and set the macro store pointers to it */
  693. X    mstore = TRUE;
  694. X    bstore = bp;
  695. X    return(TRUE);
  696. X}
  697. X
  698. X/*    execbuf:    Execute the contents of a buffer of commands    */
  699. X
  700. Xexecbuf(f, n)
  701. X
  702. Xint f, n;    /* default flag and numeric arg */
  703. X
  704. X{
  705. X        register BUFFER *bp;        /* ptr to buffer to execute */
  706. X        register int status;        /* status return */
  707. X        char bufn[NBUFN];        /* name of buffer to execute */
  708. X
  709. X    /* find out what buffer the user wants to execute */
  710. X        if ((status = mlreply("Execute buffer: ", bufn, NBUFN)) != TRUE)
  711. X                return(status);
  712. X
  713. X    /* find the pointer to that buffer */
  714. X        if ((bp=bfind(bufn, FALSE, 0)) == NULL) {
  715. X        mlwrite("No such buffer");
  716. X                return(FALSE);
  717. X        }
  718. X
  719. X    /* and now execute it as asked */
  720. X    while (n-- > 0)
  721. X        if ((status = dobuf(bp)) != TRUE)
  722. X            return(status);
  723. X    return(TRUE);
  724. X}
  725. X
  726. X/*    dobuf:    execute the contents of the buffer pointed to
  727. X        by the passed BP                */
  728. X
  729. Xdobuf(bp)
  730. X
  731. XBUFFER *bp;    /* buffer to execute */
  732. X
  733. X{
  734. X        register int status;        /* status return */
  735. X    register LINE *lp;        /* pointer to line to execute */
  736. X    register LINE *hlp;        /* pointer to line header */
  737. X    register int linlen;        /* length of line to execute */
  738. X    register WINDOW *wp;        /* ptr to windows to scan */
  739. X    char eline[NSTRING];        /* text of line to execute */
  740. X
  741. X    /* starting at the beginning of the buffer */
  742. X    hlp = bp->b_linep;
  743. X    lp = hlp->l_fp;
  744. X    while (lp != hlp) {
  745. X        /* calculate the line length and make a local copy */
  746. X        linlen = lp->l_used;
  747. X        if (linlen > NSTRING - 1)
  748. X            linlen = NSTRING - 1;
  749. X        strncpy(eline, lp->l_text, linlen);
  750. X        eline[linlen] = 0;    /* make sure it ends */
  751. X
  752. X        /* if it is not a comment, execute it */
  753. X        if (eline[0] != ';' && eline[0] != 0) {
  754. X            status = docmd(eline);
  755. X            if (status != TRUE) {    /* a command error */
  756. X                /* look if buffer is showing */
  757. X                wp = wheadp;
  758. X                while (wp != NULL) {
  759. X                    if (wp->w_bufp == bp) {
  760. X                        /* and point it */
  761. X                        wp->w_dotp = lp;
  762. X                        wp->w_doto = 0;
  763. X                        wp->w_flag |= WFHARD;
  764. X                    }
  765. X                    wp = wp->w_wndp;
  766. X                }
  767. X                /* in any case set the buffer . */
  768. X                bp->b_dotp = lp;
  769. X                bp->b_doto = 0;
  770. X                return(status);
  771. X            }
  772. X        }
  773. X        lp = lp->l_fp;        /* on to the next line */
  774. X    }
  775. X        return(TRUE);
  776. X}
  777. X
  778. Xexecfile(f, n)    /* execute a series of commands in a file
  779. X*/
  780. X
  781. Xint f, n;    /* default flag and numeric arg to pass on to file */
  782. X
  783. X{
  784. X    register int status;    /* return status of name query */
  785. X    char *fname[NSTRING];    /* name of file to execute */
  786. X
  787. X    if ((status = mlreply("File to execute: ", fname, NSTRING -1)) != TRUE)
  788. X        return(status);
  789. X
  790. X    /* otherwise, execute it */
  791. X    while (n-- > 0)
  792. X        if ((status=dofile(fname)) != TRUE)
  793. X            return(status);
  794. X
  795. X    return(TRUE);
  796. X}
  797. X
  798. X/*    dofile:    yank a file into a buffer and execute it
  799. X        if there are no errors, delete the buffer on exit */
  800. X
  801. Xdofile(fname)
  802. X
  803. Xchar *fname;    /* file name to execute */
  804. X
  805. X{
  806. X    register BUFFER *bp;    /* buffer to place file to exeute */
  807. X    register BUFFER *cb;    /* temp to hold current buf while we read */
  808. X    register int status;    /* results of various calls */
  809. X    char bname[NBUFN];    /* name of buffer */
  810. X
  811. X    makename(bname, fname);        /* derive the name of the buffer */
  812. X    if ((bp = bfind(bname, TRUE, 0)) == NULL) /* get the needed buffer */
  813. X        return(FALSE);
  814. X
  815. X    bp->b_mode = MDVIEW;    /* mark the buffer as read only */
  816. X    cb = curbp;        /* save the old buffer */
  817. X    curbp = bp;        /* make this one current */
  818. X    /* and try to read in the file to execute */
  819. X    if ((status = readin(fname, FALSE)) != TRUE) {
  820. X        curbp = cb;    /* restore the current buffer */
  821. X        return(status);
  822. X    }
  823. X
  824. X    /* go execute it! */
  825. X    curbp = cb;        /* restore the current buffer */
  826. X    if ((status = dobuf(bp)) != TRUE)
  827. X        return(status);
  828. X
  829. X    /* if not displayed, remove the now unneeded buffer and exit */
  830. X    if (bp->b_nwnd == 0)
  831. X        zotbuf(bp);
  832. X    return(TRUE);
  833. X}
  834. X
  835. X/*    cbuf:    Execute the contents of a numbered buffer    */
  836. X
  837. Xcbuf(f, n, bufnum)
  838. X
  839. Xint f, n;    /* default flag and numeric arg */
  840. Xint bufnum;    /* number of buffer to execute */
  841. X
  842. X{
  843. X        register BUFFER *bp;        /* ptr to buffer to execute */
  844. X        register int status;        /* status return */
  845. X    static char bufname[] = "[Macro xx]";
  846. X
  847. X    /* make the buffer name */
  848. X    bufname[7] = '0' + (bufnum / 10);
  849. X    bufname[8] = '0' + (bufnum % 10);
  850. X
  851. X    /* find the pointer to that buffer */
  852. X        if ((bp=bfind(bufname, FALSE, 0)) == NULL) {
  853. X            mlwrite("Macro not defined");
  854. X                return(FALSE);
  855. X        }
  856. X
  857. X    /* and now execute it as asked */
  858. X    while (n-- > 0)
  859. X        if ((status = dobuf(bp)) != TRUE)
  860. X            return(status);
  861. X    return(TRUE);
  862. X}
  863. X
  864. Xcbuf1(f, n)
  865. X
  866. X{
  867. X    cbuf(f, n, 1);
  868. X}
  869. X
  870. Xcbuf2(f, n)
  871. X
  872. X{
  873. X    cbuf(f, n, 2);
  874. X}
  875. X
  876. Xcbuf3(f, n)
  877. X
  878. X{
  879. X    cbuf(f, n, 3);
  880. X}
  881. X
  882. Xcbuf4(f, n)
  883. X
  884. X{
  885. X    cbuf(f, n, 4);
  886. X}
  887. X
  888. Xcbuf5(f, n)
  889. X
  890. X{
  891. X    cbuf(f, n, 5);
  892. X}
  893. X
  894. Xcbuf6(f, n)
  895. X
  896. X{
  897. X    cbuf(f, n, 6);
  898. X}
  899. X
  900. Xcbuf7(f, n)
  901. X
  902. X{
  903. X    cbuf(f, n, 7);
  904. X}
  905. X
  906. Xcbuf8(f, n)
  907. X
  908. X{
  909. X    cbuf(f, n, 8);
  910. X}
  911. X
  912. Xcbuf9(f, n)
  913. X
  914. X{
  915. X    cbuf(f, n, 9);
  916. X}
  917. X
  918. Xcbuf10(f, n)
  919. X
  920. X{
  921. X    cbuf(f, n, 10);
  922. X}
  923. X
  924. Xcbuf11(f, n)
  925. X
  926. X{
  927. X    cbuf(f, n, 11);
  928. X}
  929. X
  930. Xcbuf12(f, n)
  931. X
  932. X{
  933. X    cbuf(f, n, 12);
  934. X}
  935. X
  936. Xcbuf13(f, n)
  937. X
  938. X{
  939. X    cbuf(f, n, 13);
  940. X}
  941. X
  942. Xcbuf14(f, n)
  943. X
  944. X{
  945. X    cbuf(f, n, 14);
  946. X}
  947. X
  948. Xcbuf15(f, n)
  949. X
  950. X{
  951. X    cbuf(f, n, 15);
  952. X}
  953. X
  954. Xcbuf16(f, n)
  955. X
  956. X{
  957. X    cbuf(f, n, 16);
  958. X}
  959. X
  960. Xcbuf17(f, n)
  961. X
  962. X{
  963. X    cbuf(f, n, 17);
  964. X}
  965. X
  966. Xcbuf18(f, n)
  967. X
  968. X{
  969. X    cbuf(f, n, 18);
  970. X}
  971. X
  972. Xcbuf19(f, n)
  973. X
  974. X{
  975. X    cbuf(f, n, 19);
  976. X}
  977. X
  978. Xcbuf20(f, n)
  979. X
  980. X{
  981. X    cbuf(f, n, 20);
  982. X}
  983. X
  984. Xcbuf21(f, n)
  985. X
  986. X{
  987. X    cbuf(f, n, 21);
  988. X}
  989. X
  990. Xcbuf22(f, n)
  991. X
  992. X{
  993. X    cbuf(f, n, 22);
  994. X}
  995. X
  996. Xcbuf23(f, n)
  997. X
  998. X{
  999. X    cbuf(f, n, 23);
  1000. X}
  1001. X
  1002. Xcbuf24(f, n)
  1003. X
  1004. X{
  1005. X    cbuf(f, n, 24);
  1006. X}
  1007. X
  1008. Xcbuf25(f, n)
  1009. X
  1010. X{
  1011. X    cbuf(f, n, 25);
  1012. X}
  1013. X
  1014. Xcbuf26(f, n)
  1015. X
  1016. X{
  1017. X    cbuf(f, n, 26);
  1018. X}
  1019. X
  1020. Xcbuf27(f, n)
  1021. X
  1022. X{
  1023. X    cbuf(f, n, 27);
  1024. X}
  1025. X
  1026. Xcbuf28(f, n)
  1027. X
  1028. X{
  1029. X    cbuf(f, n, 28);
  1030. X}
  1031. X
  1032. Xcbuf29(f, n)
  1033. X
  1034. X{
  1035. X    cbuf(f, n, 29);
  1036. X}
  1037. X
  1038. Xcbuf30(f, n)
  1039. X
  1040. X{
  1041. X    cbuf(f, n, 30);
  1042. X}
  1043. X
  1044. Xcbuf31(f, n)
  1045. X
  1046. X{
  1047. X    cbuf(f, n, 31);
  1048. X}
  1049. X
  1050. Xcbuf32(f, n)
  1051. X
  1052. X{
  1053. X    cbuf(f, n, 32);
  1054. X}
  1055. X
  1056. Xcbuf33(f, n)
  1057. X
  1058. X{
  1059. X    cbuf(f, n, 33);
  1060. X}
  1061. X
  1062. Xcbuf34(f, n)
  1063. X
  1064. X{
  1065. X    cbuf(f, n, 34);
  1066. X}
  1067. X
  1068. Xcbuf35(f, n)
  1069. X
  1070. X{
  1071. X    cbuf(f, n, 35);
  1072. X}
  1073. X
  1074. Xcbuf36(f, n)
  1075. X
  1076. X{
  1077. X    cbuf(f, n, 36);
  1078. X}
  1079. X
  1080. Xcbuf37(f, n)
  1081. X
  1082. X{
  1083. X    cbuf(f, n, 37);
  1084. X}
  1085. X
  1086. Xcbuf38(f, n)
  1087. X
  1088. X{
  1089. X    cbuf(f, n, 38);
  1090. X}
  1091. X
  1092. Xcbuf39(f, n)
  1093. X
  1094. X{
  1095. X    cbuf(f, n, 39);
  1096. X}
  1097. X
  1098. Xcbuf40(f, n)
  1099. X
  1100. X{
  1101. X    cbuf(f, n, 40);
  1102. X}
  1103. X
  1104. X
  1105. FRIDAY_NIGHT
  1106. echo extracting - file.c
  1107. sed 's/^X//' > file.c << 'FRIDAY_NIGHT'
  1108. X/*
  1109. X * The routines in this file
  1110. X * handle the reading and writing of
  1111. X * disk files. All of details about the
  1112. X * reading and writing of the disk are
  1113. X * in "fileio.c".
  1114. X */
  1115. X#include        <stdio.h>
  1116. X#include    "estruct.h"
  1117. X#include        "edef.h"
  1118. X
  1119. X/*
  1120. X * Read a file into the current
  1121. X * buffer. This is really easy; all you do it
  1122. X * find the name of the file, and call the standard
  1123. X * "read a file into the current buffer" code.
  1124. X * Bound to "C-X C-R".
  1125. X */
  1126. Xfileread(f, n)
  1127. X{
  1128. X        register int    s;
  1129. X        char fname[NFILEN];
  1130. X
  1131. X        if ((s=mlreply("Read file: ", fname, NFILEN)) != TRUE)
  1132. X                return(s);
  1133. X        return(readin(fname, TRUE));
  1134. X}
  1135. X
  1136. X/*
  1137. X * Insert a file into the current
  1138. X * buffer. This is really easy; all you do it
  1139. X * find the name of the file, and call the standard
  1140. X * "insert a file into the current buffer" code.
  1141. X * Bound to "C-X C-I".
  1142. X */
  1143. Xinsfile(f, n)
  1144. X{
  1145. X        register int    s;
  1146. X        char fname[NFILEN];
  1147. X
  1148. X    if (curbp->b_mode&MDVIEW)    /* don't allow this command if    */
  1149. X        return(rdonly());    /* we are in read only mode    */
  1150. X        if ((s=mlreply("Insert file: ", fname, NFILEN)) != TRUE)
  1151. X                return(s);
  1152. X        return(ifile(fname));
  1153. X}
  1154. X
  1155. X/*
  1156. X * Select a file for editing.
  1157. X * Look around to see if you can find the
  1158. X * fine in another buffer; if you can find it
  1159. X * just switch to the buffer. If you cannot find
  1160. X * the file, create a new buffer, read in the
  1161. X * text, and switch to the new buffer.
  1162. X * Bound to C-X C-F.
  1163. X */
  1164. Xfilefind(f, n)
  1165. X{
  1166. X        char fname[NFILEN];    /* file user wishes to find */
  1167. X        register int s;        /* status return */
  1168. X
  1169. X        if ((s=mlreply("Find file: ", fname, NFILEN)) != TRUE)
  1170. X                return(s);
  1171. X    return(getfile(fname, TRUE));
  1172. X}
  1173. X
  1174. Xviewfile(f, n)    /* visit a file in VIEW mode */
  1175. X{
  1176. X        char fname[NFILEN];    /* file user wishes to find */
  1177. X        register int s;        /* status return */
  1178. X    register WINDOW *wp;    /* scan for windows that need updating */
  1179. X
  1180. X        if ((s=mlreply("View file: ", fname, NFILEN)) != TRUE)
  1181. X                return (s);
  1182. X    s = getfile(fname, FALSE);
  1183. X    if (s) {    /* if we succeed, put it in view mode */
  1184. X        curwp->w_bufp->b_mode |= MDVIEW;
  1185. X
  1186. X        /* scan through and update mode lines of all windows */
  1187. X        wp = wheadp;
  1188. X        while (wp != NULL) {
  1189. X            wp->w_flag |= WFMODE;
  1190. X            wp = wp->w_wndp;
  1191. X        }
  1192. X    }
  1193. X    return(s);
  1194. X}
  1195. X
  1196. Xgetfile(fname, lockfl)
  1197. X
  1198. Xchar fname[];        /* file name to find */
  1199. Xint lockfl;        /* check the file for locks? */
  1200. X
  1201. X{
  1202. X        register BUFFER *bp;
  1203. X        register LINE   *lp;
  1204. X        register int    i;
  1205. X        register int    s;
  1206. X        char bname[NBUFN];    /* buffer name to put file */
  1207. X
  1208. X        for (bp=bheadp; bp!=NULL; bp=bp->b_bufp) {
  1209. X                if ((bp->b_flag&BFINVS)==0 && strcmp(bp->b_fname, fname)==0) {
  1210. X            swbuffer(bp);
  1211. X                        lp = curwp->w_dotp;
  1212. X                        i = curwp->w_ntrows/2;
  1213. X                        while (i-- && lback(lp)!=curbp->b_linep)
  1214. X                                lp = lback(lp);
  1215. X                        curwp->w_linep = lp;
  1216. X                        curwp->w_flag |= WFMODE|WFHARD;
  1217. X                        mlwrite("[Old buffer]");
  1218. X                        return (TRUE);
  1219. X                }
  1220. X        }
  1221. X        makename(bname, fname);                 /* New buffer name.     */
  1222. X        while ((bp=bfind(bname, FALSE, 0)) != NULL) {
  1223. X                s = mlreply("Buffer name: ", bname, NBUFN);
  1224. X                if (s == ABORT)                 /* ^G to just quit      */
  1225. X                        return (s);
  1226. X                if (s == FALSE) {               /* CR to clobber it     */
  1227. X                        makename(bname, fname);
  1228. X                        break;
  1229. X                }
  1230. X        }
  1231. X        if (bp==NULL && (bp=bfind(bname, TRUE, 0))==NULL) {
  1232. X                mlwrite("Cannot create buffer");
  1233. X                return (FALSE);
  1234. X        }
  1235. X        if (--curbp->b_nwnd == 0) {             /* Undisplay.           */
  1236. X                curbp->b_dotp = curwp->w_dotp;
  1237. X                curbp->b_doto = curwp->w_doto;
  1238. X                curbp->b_markp = curwp->w_markp;
  1239. X                curbp->b_marko = curwp->w_marko;
  1240. X        }
  1241. X        curbp = bp;                             /* Switch to it.        */
  1242. X        curwp->w_bufp = bp;
  1243. X        curbp->b_nwnd++;
  1244. X        return(readin(fname, lockfl));          /* Read it in.          */
  1245. X}
  1246. X
  1247. X/*
  1248. X * Read file "fname" into the current
  1249. X * buffer, blowing away any text found there. Called
  1250. X * by both the read and find commands. Return the final
  1251. X * status of the read. Also called by the mainline,
  1252. X * to read in a file specified on the command line as
  1253. X * an argument. If the filename ends in a ".c", CMODE is
  1254. X * set for the current buffer.
  1255. X */
  1256. Xreadin(fname, lockfl)
  1257. X
  1258. Xchar    fname[];    /* name of file to read */
  1259. Xint    lockfl;        /* check for file locks? */
  1260. X
  1261. X{
  1262. X        register LINE   *lp1;
  1263. X        register LINE   *lp2;
  1264. X        register int    i;
  1265. X        register WINDOW *wp;
  1266. X        register BUFFER *bp;
  1267. X        register int    s;
  1268. X        register int    nbytes;
  1269. X        register int    nline;
  1270. X    register char    *sptr;        /* pointer into filename string */
  1271. X    int        lflag;        /* any lines longer than allowed? */
  1272. X        char            line[NLINE];
  1273. X
  1274. X#if    FILOCK
  1275. X    if (lockfl && lockchk(fname) == ABORT)
  1276. X        return(ABORT);
  1277. X#endif
  1278. X        bp = curbp;                             /* Cheap.               */
  1279. X        if ((s=bclear(bp)) != TRUE)             /* Might be old.        */
  1280. X                return (s);
  1281. X        bp->b_flag &= ~(BFINVS|BFCHG);
  1282. X#if    ACMODE
  1283. X    if (strlen(fname) > 1) {        /* check if a 'C' file    */
  1284. X        sptr = fname + strlen(fname) - 2;
  1285. X        if (*sptr == '.' &&
  1286. X           *(sptr + 1) == 'c' || *(sptr + 1) == 'h')
  1287. X            bp->b_mode |= MDCMOD;
  1288. X    }
  1289. X#endif
  1290. X        strcpy(bp->b_fname, fname);
  1291. X        if ((s=ffropen(fname)) == FIOERR)       /* Hard file open.      */
  1292. X                goto out;
  1293. X        if (s == FIOFNF) {                      /* File not found.      */
  1294. X                mlwrite("[New file]");
  1295. X                goto out;
  1296. X        }
  1297. X        mlwrite("[Reading file]");
  1298. X        nline = 0;
  1299. X    lflag = FALSE;
  1300. X        while ((s=ffgetline(line, NLINE)) == FIOSUC || s == FIOLNG) {
  1301. X        if (s == FIOLNG)
  1302. X            lflag = TRUE;
  1303. X                nbytes = strlen(line);
  1304. X                if ((lp1=lalloc(nbytes)) == NULL) {
  1305. X                        s = FIOERR;             /* Keep message on the  */
  1306. X                        break;                  /* display.             */
  1307. X                }
  1308. X                lp2 = lback(curbp->b_linep);
  1309. X                lp2->l_fp = lp1;
  1310. X                lp1->l_fp = curbp->b_linep;
  1311. X                lp1->l_bp = lp2;
  1312. X                curbp->b_linep->l_bp = lp1;
  1313. X                for (i=0; i<nbytes; ++i)
  1314. X                        lputc(lp1, i, line[i]);
  1315. X                ++nline;
  1316. X        }
  1317. X        ffclose();                              /* Ignore errors.       */
  1318. X        if (s == FIOEOF) {                      /* Don't zap message!   */
  1319. X                if (nline == 1)
  1320. X                        mlwrite("[Read 1 line]");
  1321. X                else
  1322. X                        mlwrite("[Read %d lines]", nline);
  1323. X        }
  1324. X    if (lflag)
  1325. X        mlwrite("[Read %d line(s), Long lines wrapped]",nline);
  1326. Xout:
  1327. X        for (wp=wheadp; wp!=NULL; wp=wp->w_wndp) {
  1328. X                if (wp->w_bufp == curbp) {
  1329. X                        wp->w_linep = lforw(curbp->b_linep);
  1330. X                        wp->w_dotp  = lforw(curbp->b_linep);
  1331. X                        wp->w_doto  = 0;
  1332. X                        wp->w_markp = NULL;
  1333. X                        wp->w_marko = 0;
  1334. X                        wp->w_flag |= WFMODE|WFHARD;
  1335. X                }
  1336. X        }
  1337. X        if (s == FIOERR || s == FIOFNF)        /* False if error.      */
  1338. X                return(FALSE);
  1339. X        return (TRUE);
  1340. X}
  1341. X
  1342. X/*
  1343. X * Take a file name, and from it
  1344. X * fabricate a buffer name. This routine knows
  1345. X * about the syntax of file names on the target system.
  1346. X * I suppose that this information could be put in
  1347. X * a better place than a line of code.
  1348. X */
  1349. Xmakename(bname, fname)
  1350. Xchar    bname[];
  1351. Xchar    fname[];
  1352. X{
  1353. X        register char   *cp1;
  1354. X        register char   *cp2;
  1355. X
  1356. X        cp1 = &fname[0];
  1357. X        while (*cp1 != 0)
  1358. X                ++cp1;
  1359. X
  1360. X#if     AMIGA
  1361. X        while (cp1!=&fname[0] && cp1[-1]!=':' && cp1[-1]!='/')
  1362. X                --cp1;
  1363. X#endif
  1364. X#if     VMS
  1365. X        while (cp1!=&fname[0] && cp1[-1]!=':' && cp1[-1]!=']')
  1366. X                --cp1;
  1367. X#endif
  1368. X#if     CPM
  1369. X        while (cp1!=&fname[0] && cp1[-1]!=':')
  1370. X                --cp1;
  1371. X#endif
  1372. X#if     MSDOS
  1373. X        while (cp1!=&fname[0] && cp1[-1]!=':' && cp1[-1]!='\\'&&cp1[-1]!='/')
  1374. X                --cp1;
  1375. X#endif
  1376. X#if     V7 | USG | BSD
  1377. X        while (cp1!=&fname[0] && cp1[-1]!='/')
  1378. X                --cp1;
  1379. X#endif
  1380. X        cp2 = &bname[0];
  1381. X        while (cp2!=&bname[NBUFN-1] && *cp1!=0 && *cp1!=';')
  1382. X                *cp2++ = *cp1++;
  1383. X        *cp2 = 0;
  1384. X}
  1385. X
  1386. X/*
  1387. X * Ask for a file name, and write the
  1388. X * contents of the current buffer to that file.
  1389. X * Update the remembered file name and clear the
  1390. X * buffer changed flag. This handling of file names
  1391. X * is different from the earlier versions, and
  1392. X * is more compatable with Gosling EMACS than
  1393. X * with ITS EMACS. Bound to "C-X C-W".
  1394. X */
  1395. Xfilewrite(f, n)
  1396. X{
  1397. X        register WINDOW *wp;
  1398. X        register int    s;
  1399. X        char            fname[NFILEN];
  1400. X
  1401. X        if ((s=mlreply("Write file: ", fname, NFILEN)) != TRUE)
  1402. X                return (s);
  1403. X        if ((s=writeout(fname)) == TRUE) {
  1404. X                strcpy(curbp->b_fname, fname);
  1405. X                curbp->b_flag &= ~BFCHG;
  1406. X                wp = wheadp;                    /* Update mode lines.   */
  1407. X                while (wp != NULL) {
  1408. X                        if (wp->w_bufp == curbp)
  1409. X                                wp->w_flag |= WFMODE;
  1410. X                        wp = wp->w_wndp;
  1411. X                }
  1412. X        }
  1413. X        return (s);
  1414. X}
  1415. X
  1416. X/*
  1417. X * Save the contents of the current
  1418. X * buffer in its associatd file. No nothing
  1419. X * if nothing has changed (this may be a bug, not a
  1420. X * feature). Error if there is no remembered file
  1421. X * name for the buffer. Bound to "C-X C-S". May
  1422. X * get called by "C-Z".
  1423. X */
  1424. Xfilesave(f, n)
  1425. X{
  1426. X        register WINDOW *wp;
  1427. X        register int    s;
  1428. X
  1429. X    if (curbp->b_mode&MDVIEW)    /* don't allow this command if    */
  1430. X        return(rdonly());    /* we are in read only mode    */
  1431. X        if ((curbp->b_flag&BFCHG) == 0)         /* Return, no changes.  */
  1432. X                return (TRUE);
  1433. X        if (curbp->b_fname[0] == 0) {           /* Must have a name.    */
  1434. X                mlwrite("No file name");
  1435. X                return (FALSE);
  1436. X        }
  1437. X        if ((s=writeout(curbp->b_fname)) == TRUE) {
  1438. X                curbp->b_flag &= ~BFCHG;
  1439. X                wp = wheadp;                    /* Update mode lines.   */
  1440. X                while (wp != NULL) {
  1441. X                        if (wp->w_bufp == curbp)
  1442. X                                wp->w_flag |= WFMODE;
  1443. X                        wp = wp->w_wndp;
  1444. X                }
  1445. X        }
  1446. X        return (s);
  1447. X}
  1448. X
  1449. X/*
  1450. X * This function performs the details of file
  1451. X * writing. Uses the file management routines in the
  1452. X * "fileio.c" package. The number of lines written is
  1453. X * displayed. Sadly, it looks inside a LINE; provide
  1454. X * a macro for this. Most of the grief is error
  1455. X * checking of some sort.
  1456. X */
  1457. Xwriteout(fn)
  1458. Xchar    *fn;
  1459. X{
  1460. X        register int    s;
  1461. X        register LINE   *lp;
  1462. X        register int    nline;
  1463. X
  1464. X        if ((s=ffwopen(fn)) != FIOSUC)          /* Open writes message. */
  1465. X                return (FALSE);
  1466. X    mlwrite("[Writing..]");            /* tell us were writing */
  1467. X        lp = lforw(curbp->b_linep);             /* First line.          */
  1468. X        nline = 0;                              /* Number of lines.     */
  1469. X        while (lp != curbp->b_linep) {
  1470. X                if ((s=ffputline(&lp->l_text[0], llength(lp))) != FIOSUC)
  1471. X                        break;
  1472. X                ++nline;
  1473. X                lp = lforw(lp);
  1474. X        }
  1475. X        if (s == FIOSUC) {                      /* No write error.      */
  1476. X                s = ffclose();
  1477. X                if (s == FIOSUC) {              /* No close error.      */
  1478. X                        if (nline == 1)
  1479. X                                mlwrite("[Wrote 1 line]");
  1480. X                        else
  1481. X                                mlwrite("[Wrote %d lines]", nline);
  1482. X                }
  1483. X        } else                                  /* Ignore close error   */
  1484. X                ffclose();                      /* if a write error.    */
  1485. X        if (s != FIOSUC)                        /* Some sort of error.  */
  1486. X                return (FALSE);
  1487. X        return (TRUE);
  1488. X}
  1489. X
  1490. X/*
  1491. X * The command allows the user
  1492. X * to modify the file name associated with
  1493. X * the current buffer. It is like the "f" command
  1494. X * in UNIX "ed". The operation is simple; just zap
  1495. X * the name in the BUFFER structure, and mark the windows
  1496. X * as needing an update. You can type a blank line at the
  1497. X * prompt if you wish.
  1498. X */
  1499. Xfilename(f, n)
  1500. X{
  1501. X        register WINDOW *wp;
  1502. X        register int    s;
  1503. X        char            fname[NFILEN];
  1504. X
  1505. X        if ((s=mlreply("Name: ", fname, NFILEN)) == ABORT)
  1506. X                return (s);
  1507. X        if (s == FALSE)
  1508. X                strcpy(curbp->b_fname, "");
  1509. X        else
  1510. X                strcpy(curbp->b_fname, fname);
  1511. X        wp = wheadp;                            /* Update mode lines.   */
  1512. X        while (wp != NULL) {
  1513. X                if (wp->w_bufp == curbp)
  1514. X                        wp->w_flag |= WFMODE;
  1515. X                wp = wp->w_wndp;
  1516. X        }
  1517. X    curbp->b_mode &= ~MDVIEW;    /* no longer read only mode */
  1518. X        return (TRUE);
  1519. X}
  1520. X
  1521. X/*
  1522. X * Insert file "fname" into the current
  1523. X * buffer, Called by insert file command. Return the final
  1524. X * status of the read.
  1525. X */
  1526. Xifile(fname)
  1527. Xchar    fname[];
  1528. X{
  1529. X        register LINE   *lp0;
  1530. X        register LINE   *lp1;
  1531. X        register LINE   *lp2;
  1532. X        register int    i;
  1533. X        register BUFFER *bp;
  1534. X        register int    s;
  1535. X        register int    nbytes;
  1536. X        register int    nline;
  1537. X    int        lflag;        /* any lines longer than allowed? */
  1538. X        char            line[NLINE];
  1539. X
  1540. X        bp = curbp;                             /* Cheap.               */
  1541. X        bp->b_flag |= BFCHG;            /* we have changed    */
  1542. X    bp->b_flag &= ~BFINVS;            /* and are not temporary*/
  1543. X        if ((s=ffropen(fname)) == FIOERR)       /* Hard file open.      */
  1544. X                goto out;
  1545. X        if (s == FIOFNF) {                      /* File not found.      */
  1546. X                mlwrite("[No such file]");
  1547. X        return(FALSE);
  1548. X        }
  1549. X        mlwrite("[Inserting file]");
  1550. X
  1551. X    /* back up a line and save the mark here */
  1552. X    curwp->w_dotp = lback(curwp->w_dotp);
  1553. X    curwp->w_doto = 0;
  1554. X    curwp->w_markp = curwp->w_dotp;
  1555. X    curwp->w_marko = 0;
  1556. X
  1557. X        nline = 0;
  1558. X    lflag = FALSE;
  1559. X        while ((s=ffgetline(line, NLINE)) == FIOSUC || s == FIOLNG) {
  1560. X        if (s == FIOLNG)
  1561. X            lflag = TRUE;
  1562. X                nbytes = strlen(line);
  1563. X                if ((lp1=lalloc(nbytes)) == NULL) {
  1564. X                        s = FIOERR;             /* Keep message on the  */
  1565. X                        break;                  /* display.             */
  1566. X                }
  1567. X        lp0 = curwp->w_dotp;    /* line previous to insert */
  1568. X        lp2 = lp0->l_fp;    /* line after insert */
  1569. X
  1570. X        /* re-link new line between lp0 and lp2 */
  1571. X        lp2->l_bp = lp1;
  1572. X        lp0->l_fp = lp1;
  1573. X        lp1->l_bp = lp0;
  1574. X        lp1->l_fp = lp2;
  1575. X
  1576. X        /* and advance and write out the current line */
  1577. X        curwp->w_dotp = lp1;
  1578. X                for (i=0; i<nbytes; ++i)
  1579. X                        lputc(lp1, i, line[i]);
  1580. X                ++nline;
  1581. X        }
  1582. X        ffclose();                              /* Ignore errors.       */
  1583. X    curwp->w_markp = lforw(curwp->w_markp);
  1584. X        if (s == FIOEOF) {                      /* Don't zap message!   */
  1585. X                if (nline == 1)
  1586. X                        mlwrite("[Inserted 1 line]");
  1587. X                else
  1588. X                        mlwrite("[Inserted %d lines]", nline);
  1589. X        }
  1590. X    if (lflag)
  1591. X        mlwrite("[Inserted %d line(s), Long lines wrapped]",nline);
  1592. Xout:
  1593. X    /* advance to the next line and mark the window for changes */
  1594. X    curwp->w_dotp = lforw(curwp->w_dotp);
  1595. X    curwp->w_flag |= WFHARD | WFMODE;
  1596. X
  1597. X    /* copy window parameters back to the buffer structure */
  1598. X    curbp->b_dotp = curwp->w_dotp;
  1599. X    curbp->b_doto = curwp->w_doto;
  1600. X    curbp->b_markp = curwp->w_markp;
  1601. X    curbp->b_marko = curwp->w_marko;
  1602. X
  1603. X        if (s == FIOERR)                        /* False if error.      */
  1604. X                return (FALSE);
  1605. X        return (TRUE);
  1606. X}
  1607. FRIDAY_NIGHT
  1608. echo es.5 completed!
  1609. : That's all folks!
  1610.  
  1611.