home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 January / usenetsourcesnewsgroupsinfomagicjanuary1994.iso / sources / misc / volume26 / beav / part04 < prev    next >
Encoding:
Text File  |  1991-11-21  |  54.4 KB  |  2,474 lines

  1. Newsgroups: comp.sources.misc
  2. From: pvr@wang.com (Peter Reilley)
  3. Subject:  v26i040:  beav - Binary file editor and viewer, v1.32, Part04/09
  4. Message-ID: <1991Nov21.230219.1655@sparky.imd.sterling.com>
  5. X-Md4-Signature: f20cc013ae00501fda6bbbc0bf7e25ad
  6. Date: Thu, 21 Nov 1991 23:02:19 GMT
  7. Approved: kent@sparky.imd.sterling.com
  8.  
  9. Submitted-by: pvr@wang.com (Peter Reilley)
  10. Posting-number: Volume 26, Issue 40
  11. Archive-name: beav/part04
  12. Environment: UNIX, AIX, MS-DOS, AMIGA
  13. Supersedes: beav: Volume 22, Issue 10-18
  14.  
  15. #! /bin/sh
  16. # into a shell via "sh file" or similar.  To overwrite existing files,
  17. # type "sh file -c".
  18. # The tool that generated this appeared in the comp.sources.unix newsgroup;
  19. # send mail to comp-sources-unix@uunet.uu.net if you want that tool.
  20. # Contents:  buffer.c random.c spawn.c
  21. # Wrapped by kent@sparky on Thu Nov 21 16:47:00 1991
  22. PATH=/bin:/usr/bin:/usr/ucb ; export PATH
  23. echo If this archive is complete, you will see the following message:
  24. echo '          "shar: End of archive 4 (of 9)."'
  25. if test -f 'buffer.c' -a "${1}" != "-c" ; then 
  26.   echo shar: Will not clobber existing file \"'buffer.c'\"
  27. else
  28.   echo shar: Extracting \"'buffer.c'\" \(20883 characters\)
  29.   sed "s/^X//" >'buffer.c' <<'END_OF_FILE'
  30. X/*
  31. X*       Buffer handling.
  32. X*/
  33. X
  34. X#include    "def.h"
  35. X
  36. Xbool    onebuf ();
  37. Xbool    killablebufs ();
  38. Xbool    _yankbuffer ();
  39. Xchar    next_buf ();
  40. Xbool    bclear ();
  41. Xbool    addline ();
  42. Xchar    makelist ();
  43. Xbool    popblist ();
  44. Xchar    listbuffers ();
  45. Xchar    _killbuffer ();
  46. Xbool    _usebuffer ();
  47. X
  48. Xextern  ROW_FMT text_fmt;
  49. Xextern    char    MSG_use_b[];
  50. Xextern    char    MSG_kill_b[];
  51. Xextern    char    MSG_not_fnd[];
  52. Xextern    char    MSG_no_del_m[];
  53. Xextern    char    MSG_buf_disp[];
  54. Xextern    char    MSG_main[];
  55. Xextern    char    MSG_l_buf_h[];
  56. Xextern    char    MSG_l_buf_h1[];
  57. Xextern    char    MSG_no_chg[];
  58. Xextern    char    MSG_yank_b[];
  59. Xextern    char    MSG_no_buf[];
  60. Xextern    char    MSG_no_s_yank[];
  61. Xextern    char    MSG_buf_nam[];
  62. Xextern    char    MSG_bad_l[];
  63. Xextern    char    MSG_pick[];
  64. Xextern    char    MSG_siz_chg[];
  65. Xextern    char    MSG_no_siz_chg[];
  66. Xextern    char    MSG_up_arrow[];
  67. Xextern    char    MSG_null[];
  68. Xextern    char    MSG_save_buf[];
  69. Xextern    char    MSG_cnt_al_b[];
  70. Xextern    char    MSG_ins_cnt[];
  71. X
  72. XBUFFER    sav_buf;
  73. XLINE    sav_line_h;
  74. X/*
  75. X* Attach a buffer to a window. The
  76. X* values of dot and mark come from the buffer
  77. X* if the use count is 0. Otherwise, they come
  78. X* from some other window.
  79. X*
  80. X* plus hacks for prev/next buffer and use-buffer-split  (jam)
  81. X* functions (like in file.c)
  82. X*/
  83. Xchar    usebuffer ()
  84. X{
  85. X
  86. X    char    bufn[NBUFN];
  87. X    register char   s;
  88. X
  89. X    if ((s = ereply (MSG_use_b, bufn, NBUFN, 0)) != TRUE)
  90. X        return (s);
  91. X    return (_usebuffer (bufn));
  92. X}
  93. X
  94. X/* use buffer, split window first
  95. X*/
  96. Xchar    use_buffer ()
  97. X{
  98. X    char    bufn[NBUFN];
  99. X    register char   s;
  100. X
  101. X    if ((s = ereply (MSG_use_b, bufn, NBUFN, 0)) != TRUE)
  102. X        return (s);
  103. X    splitwind ();
  104. X    return (_usebuffer (bufn));
  105. X}
  106. X
  107. X/* does all the work for changing to a new buffer for use-buffer,
  108. X* use-buffer-split and prev-buff & next-buff
  109. X*/
  110. Xbool _usebuffer (bufn)
  111. Xchar   *bufn;
  112. X{
  113. X    register    BUFFER * bp;
  114. X    register    WINDOW * wp;
  115. X
  116. X    if (strcmp (MSG_kill_b, bufn) == 0)/* hack! */
  117. X        bp = blistp;
  118. X    else
  119. X        if ((bp = bfind (bufn, TRUE)) == NULL)
  120. X            return (FALSE);
  121. X
  122. X    /* if current buffer is special and new buffer is normal */
  123. X    /* set to hex byte mode */
  124. X    if ((curbp == blistp) && (R_TYPE(curwp) == TEXT))
  125. X    {
  126. X        dispsize1 ();
  127. X        hexmode ();
  128. X    }
  129. X
  130. X    if (--curbp -> b_nwnd == 0)
  131. X    {
  132. X        /* Last use.         */
  133. X        curbp -> b_dotp = curwp -> w_dotp;
  134. X        curbp -> b_doto = curwp -> w_doto;
  135. X        curbp -> b_unit_offset = curwp -> w_unit_offset;/* pvr */
  136. X        curbp -> b_markp = curwp -> w_markp;
  137. X        curbp -> b_marko = curwp -> w_marko;
  138. X    }
  139. X    curbp = bp;                 /* Switch.       */
  140. X    curwp -> w_bufp = bp;
  141. X    curwp -> w_linep = bp -> b_linep;/* For macros, ignored.     */
  142. X    curwp -> w_loff = 0; /* pvr */
  143. X    curwp -> w_flag |= WFMODE | WFFORCE | WFHARD;
  144. X    /* Quite nasty.      */
  145. X    if (bp -> b_nwnd++ == 0)
  146. X    {
  147. X        /* First use.        */
  148. X        curwp -> w_dotp = bp -> b_dotp;
  149. X        curwp -> w_doto = bp -> b_doto;
  150. X        curwp -> w_unit_offset = 0;     /* pvr */
  151. X        curwp -> w_markp = bp -> b_markp;
  152. X        curwp -> w_marko = bp -> b_marko;
  153. X        wind_on_dot (curwp);
  154. X        /* if we are in the funny TEXT mode then goto standard HEX mode */
  155. X        if (R_TYPE(curwp) == TEXT)
  156. X            hexmode ();
  157. X        return (TRUE);
  158. X    }
  159. X    wp = wheadp;                /* Look for old.     */
  160. X    while (wp != NULL)
  161. X    {
  162. X        if (wp != curwp && wp -> w_bufp == bp)
  163. X        {
  164. X            curwp -> w_dotp = wp -> w_dotp;
  165. X            curwp -> w_doto = wp -> w_doto;
  166. X            curwp -> w_unit_offset = wp -> w_unit_offset;/* pvr */
  167. X            curwp -> w_markp = wp -> w_markp;
  168. X            curwp -> w_marko = wp -> w_marko;
  169. X            break;
  170. X        }
  171. X        wp = wp -> w_wndp;
  172. X    }
  173. X    wind_on_dot (curwp);
  174. X    /* if we are in the funny TEXT mode then goto standard HEX mode */
  175. X    if (R_TYPE(curwp) == TEXT)
  176. X        hexmode ();
  177. X    return (TRUE);
  178. X}
  179. X
  180. X
  181. X/*
  182. X* Dispose of a buffer, by name.
  183. X* Ask for the name. Look it up (don't get too
  184. X* upset if it isn't there at all!). Get quite upset
  185. X* if the buffer is being displayed. Clear the buffer (ask
  186. X* if the buffer has been changed). Then free the header
  187. X* line and the buffer header. Bound to "C-X K".
  188. X*/
  189. Xchar    killbuffer ()
  190. X{
  191. X    register char   s;
  192. X    char    bufn[NBUFN];
  193. X
  194. X    if ((s = ereply (MSG_kill_b, bufn, NBUFN, 0)) != TRUE)
  195. X        return (s);
  196. X    if (s = _killbuffer (bufn))
  197. X        writ_echo (okmsg);             /* verbose-ness (jam) */
  198. X    return (s);
  199. X}
  200. X
  201. X
  202. Xchar    _killbuffer (bufn)
  203. Xchar   *bufn;
  204. X{
  205. X    register    BUFFER * bp,
  206. X    *bp1,
  207. X    *bp2;
  208. X    register char   s,
  209. X    x = 0;
  210. X
  211. X    if (((bp = bfind (bufn, FALSE)) == NULL) ||
  212. X        !strcmp (bufn, MSG_save_buf))
  213. X    {
  214. X        writ_echo (MSG_not_fnd);
  215. X        return (FALSE);
  216. X    }
  217. X
  218. X
  219. X    if (killablebufs (bp))      /* can't kill '?' if no other buffers */
  220. X    {
  221. X        writ_echo (MSG_no_del_m);
  222. X        return (FALSE);
  223. X    }
  224. X
  225. X    /* see if the buffer to be killed is in a window */
  226. X    bp1 = bp;
  227. X    if (curbp == blistp && onebuf (bp))/* Hack ! */
  228. X    {
  229. X        next_buf ();
  230. X        onlywind ();
  231. X        update ();
  232. X    }
  233. X
  234. X    if (bp -> b_nwnd > 0)
  235. X    {
  236. X        if ((s = eyesno (MSG_buf_disp)) != TRUE)
  237. X            return (s);
  238. X
  239. X        /* make the current window the only window if it is to die */
  240. X        onlywind ();
  241. X        if (curbp == bp)
  242. X        {
  243. X            next_buf ();
  244. X            if (curbp == bp)
  245. X                x++;
  246. X        }
  247. X    }
  248. X    if ((s = bclear (bp)) != TRUE)/* Blow text away.      */
  249. X    {
  250. X        if (bp1 == blistp)      /* special buffer */
  251. X            curbp = bp1;
  252. X        else
  253. X            if (!x)
  254. X                _usebuffer (bp1 -> b_bname);
  255. X        /* back to original buffer (jam) */
  256. X        return (s);
  257. X    }
  258. X    if (x)
  259. X    {
  260. X        _usebuffer (MSG_main);
  261. X        x++;
  262. X    }
  263. X
  264. X    free ((char *) bp -> b_linep);/* Release header line.         */
  265. X    bp1 = NULL;                 /* Find the header.     */
  266. X    bp2 = bheadp;
  267. X    while (bp2 != bp)
  268. X    {
  269. X        bp1 = bp2;
  270. X        bp2 = bp2 -> b_bufp;
  271. X    }
  272. X    bp2 = bp2 -> b_bufp;        /* Next one in chain.   */
  273. X    if (bp1 == NULL)            /* Unlink it.           */
  274. X        bheadp = bp2;
  275. X    else
  276. X        bp1 -> b_bufp = bp2;
  277. X    free ((char *) bp);         /* Release buffer block         */
  278. X    if (x)
  279. X        update ();
  280. X    /* update buffer display */
  281. X    if ((blistp -> b_nwnd != 0) &&
  282. X        (blistp -> b_type == BTLIST))
  283. X        listbuffers ();
  284. X    return (TRUE);
  285. X}
  286. X
  287. X/*
  288. X* Display the buffer list. This is done
  289. X* in two parts. The "makelist" routine figures out
  290. X* the text, and puts it in the buffer whoses header is
  291. X* pointed to by the external "blistp". The "popblist"
  292. X* then pops the data onto the screen. Bound to
  293. X* "C-X C-B".
  294. X*/
  295. Xchar    listbuffers ()
  296. X{
  297. X    register char   s;
  298. X
  299. X    if ((s = makelist ()) != TRUE)
  300. X        return (s);
  301. X    return (popblist ());
  302. X}
  303. X/*
  304. X* Display the save buffer contents.
  305. X* Bound to "Meta C-W".
  306. X*/
  307. Xchar    showsavebuf ()
  308. X{
  309. X    WINDOW   *wp;
  310. X
  311. X    if (sav_buf.b_nwnd == 0)
  312. X    {
  313. X        splitwind ();
  314. X        _usebuffer (MSG_save_buf);
  315. X    }
  316. X    else
  317. X    {
  318. X        wp = wheadp;                /* Look for old.     */
  319. X        while (wp != NULL)
  320. X        {
  321. X            if (wp -> w_bufp == &sav_buf)
  322. X            {
  323. X                wp -> w_flag |= WFMODE | WFFORCE | WFHARD;
  324. X                break;
  325. X            }
  326. X            wp = wp -> w_wndp;
  327. X        }
  328. X    }
  329. X    return (TRUE);
  330. X}
  331. X
  332. X/*
  333. X* Pop the special buffer whose
  334. X* buffer header is pointed to by the external
  335. X* variable "blistp" onto the screen. This is used
  336. X* by the "listbuffers" routine (above) and by
  337. X* some other packages. Returns a status.
  338. X*/
  339. Xbool popblist ()
  340. X{
  341. X    register    WINDOW * wp;
  342. X    register    BUFFER * bp;
  343. X
  344. X    if (blistp -> b_nwnd == 0)  /* Not on screen yet.    */
  345. X    {
  346. X        if ((wp = wpopup ()) == NULL)
  347. X            return (FALSE);
  348. X        bp = wp -> w_bufp;
  349. X        if (--bp -> b_nwnd == 0)
  350. X        {
  351. X            bp -> b_dotp = wp -> w_dotp;
  352. X            bp -> b_doto = wp -> w_doto;
  353. X            bp -> b_unit_offset = wp -> w_unit_offset;/* pvr */
  354. X            bp -> b_markp = wp -> w_markp;
  355. X            bp -> b_marko = wp -> w_marko;
  356. X        }
  357. X        curwp = wp;
  358. X        curbp = blistp;
  359. X        wp -> w_bufp = blistp;
  360. X        ++blistp -> b_nwnd;
  361. X    }
  362. X    wp = wheadp;
  363. X    while (wp != NULL)
  364. X    {
  365. X        if (wp -> w_bufp == blistp)
  366. X        {
  367. X            wp -> w_linep = lforw (blistp -> b_linep);
  368. X            wp -> w_loff = 0;
  369. X            wp -> w_dotp = lforw (blistp -> b_linep);
  370. X            wp -> w_doto = 0;
  371. X            wp -> w_unit_offset = 0;
  372. X            wp -> w_markp = NULL;
  373. X            wp -> w_marko = 0;
  374. X            wp -> w_disp_shift = 0;
  375. X            wp -> w_intel_mode = FALSE;
  376. X            wp -> w_fmt_ptr = &text_fmt;
  377. X            wp -> w_flag |= WFMODE | WFHARD;
  378. X        }
  379. X        wp = wp -> w_wndp;
  380. X    }
  381. X    return (TRUE);
  382. X}
  383. X
  384. X/*
  385. X* This routine rebuilds the
  386. X* text in the special secret buffer
  387. X* that holds the buffer list. It is called
  388. X* by the list buffers command. Return TRUE
  389. X* if everything works. Return FALSE if there
  390. X* is an error (if there is no memory).
  391. X*/
  392. Xchar    makelist ()
  393. X{
  394. X    register    char  *cp1;
  395. X    register    char  *cp2;
  396. X    register    int    c;
  397. X    register    BUFFER * bp;
  398. X    register    A32    nbytes;
  399. X    register    char   s;
  400. X    char    b[8 + 1];
  401. X    char    line[128];
  402. X
  403. X    blistp -> b_flag &= ~BFCHG; /* Blow away old.    */
  404. X    if ((s = bclear (blistp)) != TRUE)
  405. X        return (s);
  406. X    blistp -> b_flag |= BFVIEW;
  407. X    blistp -> b_type = BTLIST;
  408. X    strcpy (blistp -> b_fname, MSG_up_arrow);
  409. X    if (addline (MSG_l_buf_h) == FALSE
  410. X        || addline (MSG_l_buf_h1) == FALSE)
  411. X        return (FALSE);
  412. X    bp = bheadp;                /* For all buffers   */
  413. X    while (bp != NULL)
  414. X    {
  415. X        cp1 = &line[0];         /* Start at left edge    */
  416. X        if ((bp -> b_flag & BFCHG) != 0)/* "*" if changed    */
  417. X            *cp1++ = '*';
  418. X        else
  419. X            if (bp -> b_flag & BFVIEW)/* jam */
  420. X                *cp1++ = 'R';   /* readonly */
  421. X            else
  422. X                *cp1++ = ' ';
  423. X        *cp1++ = ' ';           /* Gap. */
  424. X        if ((bp -> b_flag & BFBAD) != 0)/* "?" if maybe trashed  */
  425. X            *cp1++ = '?';
  426. X        else
  427. X            *cp1++ = ' ';
  428. X        *cp1++ = ' ';           /* Gap. */
  429. X        nbytes = bp -> b_linep -> l_bp -> l_file_offset +
  430. X            bp -> b_linep -> l_bp -> l_used;
  431. X        sprintf (b, "%8lx", nbytes); /* 8 digit buffer size.   */
  432. X        cp2 = &b[0];
  433. X        while ((c = *cp2++) != 0)
  434. X            *cp1++ = c;
  435. X        *cp1++ = ' ';           /* Gap.          */
  436. X        cp2 = &bp -> b_bname[0];/* Buffer name       */
  437. X        while ((c = *cp2++) != 0)
  438. X            *cp1++ = c;
  439. X        *cp1++ = ' ';           /* Gap.          */
  440. X        *cp1++ = ' ';           /* Gap.          */
  441. X        cp2 = &bp -> b_fname[0];/* File name         */
  442. X        if (*cp2 != 0)
  443. X        {
  444. X            while (cp1 < &line[1 + 1 + 1 + 1 + 6 + 1 + NBUFN + 1])
  445. X                *cp1++ = ' ';
  446. X            while ((c = *cp2++) != 0)
  447. X            {
  448. X                if (cp1 < &line[128 - 1])
  449. X                    *cp1++ = c;
  450. X            }
  451. X        }
  452. X        while (cp1 < &line[80])   /* Fill out line to col 80 */
  453. X            *cp1++ = ' ';
  454. X
  455. X        *cp1 = 0;               /* Add to the buffer.    */
  456. X        if (addline (line) == FALSE)
  457. X            return (FALSE);
  458. X        bp = bp -> b_bufp;
  459. X    }
  460. X    return (TRUE);              /* All done      */
  461. X}
  462. X
  463. X/*
  464. X* The argument "text" points to
  465. X* a string. Append this line to the
  466. X* buffer list buffer. 
  467. X* Return TRUE if it worked and
  468. X* FALSE if you ran out of room.
  469. X*/
  470. Xbool addline (text)
  471. Xchar   *text;
  472. X{
  473. X    register    LINE    * lp;
  474. X    register    int     i, allocsize;
  475. X    register    int     ntext;
  476. X
  477. X    ntext = strlen (text);
  478. X    allocsize = 128;
  479. X
  480. X    if ((lp = lalloc (allocsize)) == NULL)
  481. X        return (FALSE);
  482. X
  483. X    for (i = 0; i < ntext; ++i)
  484. X        lputc (lp, i, text[i]);
  485. X
  486. X    for (; i < allocsize; ++i)     /* fill out line with spaces */
  487. X        lputc (lp, i, ' ');
  488. X
  489. X    blistp -> b_linep -> l_bp -> l_fp = lp;/* Hook onto the end  */
  490. X    lp -> l_bp = blistp -> b_linep -> l_bp;
  491. X    blistp -> b_linep -> l_bp = lp;
  492. X    lp -> l_fp = blistp -> b_linep;
  493. X    lp -> l_size = allocsize;  /* line size is limited to 80 chars */
  494. X    lp -> l_used = allocsize;
  495. X    lp -> l_file_offset = lp -> l_bp -> l_file_offset + lp -> l_bp -> l_used;
  496. X    if (blistp -> b_dotp == blistp -> b_linep)/* If "." is at the end    */
  497. X        blistp -> b_dotp = lp;  /* move it to new line   */
  498. X    return (TRUE);
  499. X}
  500. X
  501. X
  502. X/*
  503. X* Look through the list of
  504. X* buffers. Return TRUE if there
  505. X* are any changed buffers. Special buffers
  506. X* like the buffer list buffer don't count, as
  507. X* they are not in the list. Return FALSE if
  508. X* there are no changed buffers.
  509. X*/
  510. Xbool anycb ()
  511. X{
  512. X    register    BUFFER * bp;
  513. X
  514. X    bp = bheadp;
  515. X    while (bp != NULL)
  516. X    {
  517. X
  518. X        if ((bp -> b_flag & BFCHG) != 0)
  519. X            return (TRUE);
  520. X        bp = bp -> b_bufp;
  521. X    }
  522. X    return (FALSE);
  523. X}
  524. X
  525. X
  526. X/*
  527. X* Search for a buffer, by name.
  528. X* If not found, and the "cflag" is TRUE,
  529. X* create a buffer and put it in the list of
  530. X* all buffers. Return pointer to the BUFFER
  531. X* block for the buffer.
  532. X*/
  533. XBUFFER * bfind (bname, cflag)
  534. Xregister char  *bname;
  535. X{
  536. X    register    BUFFER * bp;
  537. X
  538. X    bp = bheadp;
  539. X    while (bp != NULL)
  540. X    {
  541. X        if (strcmp (bname, bp -> b_bname) == 0)
  542. X            return (bp);
  543. X        bp = bp -> b_bufp;
  544. X    }
  545. X    if (cflag != FALSE && (bp = bcreate (bname)) != NULL)
  546. X    {
  547. X        bp -> b_bufp = bheadp;
  548. X        bheadp = bp;
  549. X    }
  550. X    return (bp);
  551. X}
  552. X
  553. X
  554. X/*
  555. X* Create a buffer, by name.
  556. X* Return a pointer to the BUFFER header
  557. X* block, or NULL if the buffer cannot
  558. X* be created. The BUFFER is not put in the
  559. X* list of all buffers; this is called by
  560. X* "edinit" to create the buffer list
  561. X* buffer.
  562. X*/
  563. XBUFFER * bcreate (bname)
  564. Xregister char  *bname;
  565. X{
  566. X
  567. X    register    BUFFER * bp;
  568. X    register    LINE * lp;
  569. X
  570. X    if ((bp = (BUFFER *) malloc (sizeof (BUFFER))) == NULL)
  571. X    {
  572. X        err_echo (MSG_cnt_al_b);
  573. X        return (NULL);
  574. X    }
  575. X    if ((lp = lalloc (0)) == NULL)
  576. X    {
  577. X        free ((char *) bp);
  578. X        return (NULL);
  579. X    }
  580. X    bp -> b_bufp = NULL;
  581. X    bp -> b_dotp = lp;
  582. X    bp -> b_doto = 0;
  583. X    bp -> b_unit_offset = 0;    /* unit offset   pvr */
  584. X    bp -> b_markp = NULL;
  585. X    bp -> b_marko = 0;
  586. X    bp -> b_flag = 0;
  587. X    bp -> b_nwnd = 0;
  588. X    bp -> b_linep = lp;
  589. X    strcpy (bp -> b_fname, MSG_null);
  590. X    strcpy (bp -> b_bname, bname);
  591. X    lp -> l_fp = lp;
  592. X    lp -> l_bp = lp;
  593. X    lp -> l_file_offset = 0;    /* pvr */
  594. X    lp -> l_used = 0;           /* pvr */
  595. X    lp -> l_size = 0;           /* size of zero indicates the header line  pvr 
  596. X                                                        */
  597. X    return (bp);
  598. X}
  599. X
  600. X
  601. X/*
  602. X* This routine blows away all of the text
  603. X* in a buffer. If the buffer is marked as changed
  604. X* then we ask if it is ok to blow it away; this is
  605. X* to save the user the grief of losing text. The
  606. X* window chain is nearly always wrong if this gets
  607. X* called; the caller must arrange for the updates
  608. X* that are required. Return TRUE if everything
  609. X* looks good.
  610. X*/
  611. Xbool bclear (bp)
  612. Xregister    BUFFER * bp;
  613. X{
  614. X    register    LINE * lp;
  615. X    register char   s;
  616. X
  617. X    if ((bp -> b_flag & BFCHG) != 0/* Changed.       */
  618. X    && (s = eyesno (MSG_no_chg)) != TRUE)
  619. X        return (s);
  620. X    bp -> b_flag &= ~BFCHG;     /* Not changed       */
  621. X    while ((lp = lforw (bp -> b_linep)) != bp -> b_linep)
  622. X        lfree (lp);
  623. X    bp -> b_dotp = bp -> b_linep;/* Fix "."      */
  624. X    bp -> b_doto = 0;
  625. X    bp -> b_unit_offset = 0;    /* pvr */
  626. X    bp -> b_markp = NULL;       /* Invalidate mark  */
  627. X    bp -> b_marko = 0;
  628. X    return (TRUE);
  629. X}
  630. X
  631. X
  632. X/* flip to next buffer in the list, wrap
  633. X* to beginning if required (wrap around)
  634. X* (skips buffers saved  by save-region)  
  635. X*/
  636. Xchar    next_buf ()
  637. X{
  638. X    register    BUFFER * bp;
  639. X
  640. X    bp = curbp;
  641. X    while (TRUE)
  642. X    {
  643. X        if (!(bp = bp -> b_bufp))
  644. X            bp = bheadp;
  645. X        if ((bp -> b_type == BTSAVE) ||
  646. X            (bp -> b_type == BTLIST) ||
  647. X            (bp -> b_type == BTHELP))
  648. X            continue;
  649. X        break;
  650. X    }
  651. X    _usebuffer (bp -> b_bname);
  652. X    return (TRUE);
  653. X}
  654. X
  655. X
  656. X/* flip to prev buffer in the list, wrap
  657. X* to end if required (wrap around)
  658. X* (does NOT skip buffers saved by save-region)  
  659. X*/
  660. Xchar    prev_buf ()
  661. X{
  662. X    register    BUFFER * sp;
  663. X
  664. X    if ((sp = curbp) == bheadp) /* front of list */
  665. X    {
  666. X        for (; sp -> b_bufp; sp = sp -> b_bufp)
  667. X            ;
  668. X    }
  669. X    else /* cycle around */
  670. X    {
  671. X        for (sp = bheadp; sp -> b_bufp; sp = sp -> b_bufp)
  672. X        {
  673. X            if (sp -> b_bufp == curbp)
  674. X                break;
  675. X        }
  676. X    }
  677. X    return (_usebuffer (sp -> b_bname));
  678. X}
  679. X
  680. X
  681. X/* yank a buffer into current buffer
  682. X*/
  683. Xchar    yank_buffer ()
  684. X{
  685. X    char    bufn[NBUFN];
  686. X
  687. X    if (ereply (MSG_yank_b, bufn, NBUFN, 0) != TRUE)
  688. X        return (FALSE);
  689. X    return (_yankbuffer (bufn));
  690. X}
  691. X
  692. X
  693. Xbool _yankbuffer (bufn)
  694. Xchar   *bufn;
  695. X{
  696. X    register    LINE * lp;
  697. X    register    BUFFER * bp = curbp;
  698. X    register int    s;
  699. X    A32      cnt;
  700. X    char        buf[NFILEN], buf1[NFILEN];
  701. X
  702. X    if ((bp = bfind (bufn, FALSE)) == NULL)
  703. X    {
  704. X        writ_echo (MSG_no_buf);
  705. X        return (FALSE);
  706. X    }
  707. X    if (strcmp (bp -> b_bname, curbp -> b_bname) == 0)
  708. X    {
  709. X        writ_echo (MSG_no_s_yank);
  710. X        return (FALSE);
  711. X    }
  712. X    cnt = 0;
  713. X    lp = lforw (bp -> b_linep);
  714. X    while (TRUE)
  715. X    {
  716. X        cnt += lp -> l_used;
  717. X        for (s = 0; s < lp -> l_used; s++)
  718. X            if (linsert (1, lp -> l_text[s]) == FALSE)
  719. X                return (FALSE);
  720. X
  721. X        if ((lp = lforw (lp)) == bp -> b_linep)
  722. X        {
  723. X            break;
  724. X        }
  725. X
  726. X        if ((cnt & 0x7ff) == 0)
  727. X        {
  728. X            sprintf (buf1, MSG_ins_cnt, R_POS_FMT(curwp));
  729. X            sprintf (buf, buf1, cnt);
  730. X            writ_echo (buf);
  731. X            /* check if we should quit */
  732. X            if (ttkeyready ())
  733. X            {
  734. X                l_fix_up (lp -> l_bp);
  735. X                wind_on_dot_all();
  736. X                if (ttgetc () == CTL_G)  /* was it an abort key? */
  737. X                    return (FALSE);
  738. X            }
  739. X        }
  740. X    }
  741. X    writ_echo (okmsg);
  742. X    return (TRUE);
  743. X}
  744. X
  745. X
  746. Xbool buffername ()
  747. X{
  748. X
  749. X    register    WINDOW * wp;
  750. X    register char  *p;
  751. X    register char   s;
  752. X    char    bname[NBUFN + 1];
  753. X
  754. X    if ((s = ereply (MSG_buf_nam, bname, NBUFN, 0)) == ABORT)
  755. X        return (s);
  756. X    for (p = bname; *p && *p != ' '; p++)
  757. X        ;
  758. X    *p = 0;                     /* no blanks */
  759. X    strcpy (curbp -> b_bname, bname);
  760. X    wp = wheadp;                /* Update mode lines.   */
  761. X    while (wp != NULL)
  762. X    {
  763. X        if (wp -> w_bufp == curbp)
  764. X            wp -> w_flag |= WFMODE;
  765. X        wp = wp -> w_wndp;
  766. X    }
  767. X    if ((blistp -> b_nwnd != 0) &&  /* update buffer display */
  768. X    (blistp -> b_type == BTLIST))
  769. X        listbuffers ();
  770. X    return (TRUE);
  771. X}
  772. X
  773. X
  774. X/* any killable buffers around ? (jam)
  775. X*/
  776. Xbool killablebufs (bp)
  777. Xregister    BUFFER * bp;
  778. X{
  779. X    if (strcmp (bp -> b_bname, MSG_main) == 0)/* doomed buffer is 'empty' */
  780. X        if (bheadp == bp)       /* and is only buffer in list */
  781. X            if (bheadp -> b_bufp == 0)/* then there are no killable buffers */
  782. X                return (TRUE);
  783. X    return (FALSE);
  784. X}
  785. X
  786. X
  787. X/* only 1 buffer around ?
  788. X*/
  789. Xbool onebuf (bp)
  790. Xregister    BUFFER * bp;
  791. X{
  792. X    if (strcmp (bp -> b_bname, bheadp -> b_bname) == 0)
  793. X        if (bheadp -> b_bufp == 0)
  794. X            return (TRUE);
  795. X    return (FALSE);
  796. X}
  797. X
  798. X
  799. X/* funky new name; real yukky!!!! (jam) 
  800. X*/
  801. Xvoid funky_name (bname, n)
  802. Xregister char  *bname;
  803. Xint     n;
  804. X{
  805. X    char    num[10];
  806. X    register int    i;
  807. X    register char  *p;
  808. X
  809. X    for (i = 0; i < 10; i++)
  810. X        num[i] = ' ';
  811. X    for (p = bname; *p; p++)
  812. X        *p = 0;
  813. X    *bname++ = '#';
  814. X    sprintf (num, "%lx", (long) n + 1);
  815. X    for (p = num; *p; p++)
  816. X        if (*p != ' ')
  817. X            *bname++ = *p;
  818. X    *bname = 0;
  819. X}
  820. X
  821. X
  822. X/* pick a buffer to goto/kill
  823. X*/
  824. X#define BUFFEROFFSET (13)       /* depends on makelist !! */
  825. X
  826. Xbool pickone ()
  827. X{
  828. X    register int    s,
  829. X    i,
  830. X    c;
  831. X    register    LINE * lp;
  832. X    char    name[NBUFN + 1];
  833. X    char    buf[3];
  834. X    WINDOW  *wp;
  835. X
  836. X    lp = curwp -> w_dotp;       /* get the buffer name from the line */
  837. X
  838. X    i = 0;
  839. X    if (!llength (lp))
  840. X    {
  841. X        writ_echo (MSG_bad_l);
  842. X        return (FALSE);
  843. X    }
  844. X    for (s = BUFFEROFFSET; (c = lgetc (lp, s)) != ' '; s++)
  845. X    {
  846. X        name[i++] = c;
  847. X        if (s >= llength (lp))
  848. X            break;
  849. X    }
  850. X    name[i] = 0;
  851. X    if (!bfind (name, FALSE))
  852. X    {
  853. X        writ_echo (MSG_bad_l);
  854. X        return (FALSE);
  855. X    }
  856. Xloop:
  857. X    if ((s = ereply (MSG_pick, buf, 2, name)) != TRUE)
  858. X        return (FALSE);
  859. X    if (ISLOWER (buf[0]) != FALSE)
  860. X        buf[0] = TOUPPER (buf[0]);
  861. X    if (buf[0] == 'K')
  862. X        _killbuffer (name);
  863. X    else
  864. X        if (buf[0] == 'G')
  865. X            _usebuffer (name);
  866. X        else
  867. X            if (buf[0] == 'S')
  868. X            {
  869. X                _usebuffer (name);
  870. X                /* goto this buffer, but don't show the user */
  871. X                filesave ();
  872. X                _usebuffer (MSG_kill_b);
  873. X                /* jump back to this window - HACK ! */
  874. X                listbuffers (); /* update the list */
  875. X            }
  876. X            else
  877. X                goto loop;
  878. X    writ_echo (MSG_null);
  879. X    return (TRUE);
  880. X}
  881. X/*
  882. X*   Toggle the buffer size lock bit.
  883. X*/
  884. Xchar bufsizlock ()
  885. X{
  886. X    if (curbp -> b_flag & BFSLOCK)
  887. X    {
  888. X        curbp -> b_flag &= ~BFSLOCK;
  889. X        writ_echo (MSG_siz_chg);
  890. X    }
  891. X    else
  892. X    {
  893. X        if (insert_mode)
  894. X            insert_toggle ();
  895. X        curbp -> b_flag |= BFSLOCK;
  896. X        writ_echo (MSG_no_siz_chg);
  897. X    }
  898. X    return (TRUE);
  899. X}
  900. X
  901. X/*
  902. X *   Append the given line to the end of the given buffer.
  903. X */
  904. Xvoid   b_append_l (buf_p, lp)
  905. XBUFFER *buf_p;
  906. XLINE   *lp;
  907. X{
  908. X    LINE   *h_lp;
  909. X
  910. X    h_lp = buf_p -> b_linep;
  911. X
  912. X    lp -> l_fp = h_lp;
  913. X    lp -> l_bp = h_lp -> l_bp;
  914. X    lp -> l_bp -> l_fp = lp;
  915. X    h_lp -> l_bp = lp;
  916. X    lp -> l_file_offset = lp -> l_bp -> l_file_offset + lp -> l_bp -> l_used;
  917. X}
  918. X/*
  919. X *   Append the given line to the end of the given buffer.
  920. X */
  921. Xbool   b_append_c (buf_p, ch)
  922. XBUFFER *buf_p;
  923. XD8     ch;
  924. X{
  925. X    LINE   *lp;
  926. X
  927. X    lp = buf_p -> b_linep -> l_bp;    /* get last line */
  928. X    /* do I need to get a new line? */
  929. X    if (lp -> l_size <= lp -> l_used)
  930. X    {
  931. X        if ((lp = lalloc (KBLOCK)) == NULL)
  932. X            return (FALSE);
  933. X
  934. X        lp -> l_fp = buf_p -> b_linep;
  935. X        lp -> l_bp = buf_p -> b_linep -> l_bp;
  936. X        lp -> l_bp -> l_fp = lp;
  937. X        buf_p -> b_linep -> l_bp = lp;
  938. X    }
  939. X    lp -> l_text[lp -> l_used++] = ch;
  940. X
  941. X    return (TRUE);
  942. X}
  943. X
  944. X/*
  945. X * Initialize the save buffer.
  946. X */
  947. Xvoid save_buf_init ()
  948. X{
  949. X    register    BUFFER * bp;
  950. X
  951. X    sav_line_h.l_fp = &sav_line_h;
  952. X    sav_line_h.l_bp = &sav_line_h;
  953. X    sav_line_h.l_file_offset = 0;
  954. X    sav_line_h.l_used = 0;
  955. X    sav_line_h.l_size = 0;
  956. X
  957. X    sav_buf.b_type = BTSAVE;
  958. X    sav_buf.b_bufp = NULL;
  959. X    sav_buf.b_dotp = &sav_line_h;
  960. X    sav_buf.b_doto = 0;
  961. X    sav_buf.b_unit_offset = 0;
  962. X    sav_buf.b_markp = NULL;
  963. X    sav_buf.b_marko = 0;
  964. X    sav_buf.b_linep = &sav_line_h;
  965. X    sav_buf.b_nwnd = 0;
  966. X    sav_buf.b_flag = BFVIEW;
  967. X    sav_buf.b_begin_addr = 0;
  968. X    sav_buf.b_file_size = 0;
  969. X    sav_buf.b_fname[0] = 0;
  970. X    strcpy (sav_buf.b_bname, MSG_save_buf);
  971. X
  972. X    /* put on end of chain */
  973. X    bp = bheadp;
  974. X    while ((bp -> b_bufp) != NULL)
  975. X        bp = bp -> b_bufp;
  976. X
  977. X    bp->b_bufp = &sav_buf;
  978. X
  979. X}
  980. X
  981. X/*
  982. X * Set the save buffer dot pointer to the begining.
  983. X */
  984. Xvoid save_buf_home ()
  985. X{
  986. X    sav_buf.b_dotp = sav_buf.b_linep -> l_fp;
  987. X    sav_buf.b_doto = 0;
  988. X    sav_buf.b_flag = BFVIEW;
  989. X}
  990. X
  991. XD16  get_save_char ()
  992. X{
  993. X    D8 ch;
  994. X
  995. X    /* are we past the end of the buffer */
  996. X    if (sav_buf.b_dotp == sav_buf.b_linep)
  997. X        return (-1);
  998. X    ch = sav_buf.b_dotp -> l_text[sav_buf.b_doto++];
  999. X    if (sav_buf.b_doto >= sav_buf.b_dotp -> l_used)
  1000. X    {
  1001. X        sav_buf.b_doto = 0;
  1002. X        sav_buf.b_dotp = sav_buf.b_dotp -> l_fp;
  1003. X    }
  1004. X    return ((D16)ch);
  1005. X}
  1006. X
  1007. END_OF_FILE
  1008.   if test 20883 -ne `wc -c <'buffer.c'`; then
  1009.     echo shar: \"'buffer.c'\" unpacked with wrong size!
  1010.   fi
  1011.   # end of 'buffer.c'
  1012. fi
  1013. if test -f 'random.c' -a "${1}" != "-c" ; then 
  1014.   echo shar: Will not clobber existing file \"'random.c'\"
  1015. else
  1016.   echo shar: Extracting \"'random.c'\" \(28521 characters\)
  1017.   sed "s/^X//" >'random.c' <<'END_OF_FILE'
  1018. X/*
  1019. X*              Assorted commands.
  1020. X* The file contains the command
  1021. X* processors for a large assortment of unrelated
  1022. X* commands. The only thing they have in common is
  1023. X* that they are all command processors.
  1024. X*/
  1025. X
  1026. X#include    "def.h"
  1027. X
  1028. Xchar    backdel ();
  1029. Xbool    fill_out ();
  1030. Xvoid    bad_key ();
  1031. X
  1032. X
  1033. X
  1034. Xextern    char    MSG_sh_pos[];
  1035. Xextern    char    MSG_sh_pos1[];
  1036. Xextern    char    MSG_f_str[];
  1037. Xextern    char    MSG_3u[];
  1038. Xextern    char    MSG_5u[];
  1039. Xextern    char    MSG_lu[];
  1040. Xextern    char    MSG_03u[];
  1041. Xextern    char    MSG_05u[];
  1042. Xextern    char    MSG_010lu[];
  1043. Xextern    char    MSG_lnk[];
  1044. Xextern    char    MSG_unlink[];
  1045. Xextern    char    MSG_link[];
  1046. Xextern    char    MSG_bad_key[];
  1047. Xextern    char    MSG_esc[];
  1048. Xextern    char    MSG_ctl_x[];
  1049. Xextern    char    MSG_ctl[];
  1050. Xextern    char    MSG_key_code[];
  1051. Xextern    char    char_str[];
  1052. Xextern    char    MSG_w_not_empty[];
  1053. Xextern    char    MSG_procing[];
  1054. Xextern    char    MSG_ok[];
  1055. X#if RUNCHK
  1056. Xextern    char    ERR_rnd_1[];
  1057. Xextern    char    ERR_rnd_2[];
  1058. Xextern    char    ERR_rnd_3[];
  1059. Xextern    char    ERR_rnd_4[];
  1060. Xextern    char    ERR_rnd_5[];
  1061. Xextern    char    ERR_rnd_6[];
  1062. Xextern    char    ERR_rnd_7[];
  1063. X#endif
  1064. X
  1065. Xextern  ROW_FMT ascii_fmt;
  1066. Xextern  ROW_FMT ebcdic_fmt;
  1067. Xextern  ROW_FMT binary_8_fmt;
  1068. Xextern  ROW_FMT binary_16_fmt;
  1069. Xextern  ROW_FMT binary_32_fmt;
  1070. Xextern  ROW_FMT octal_8_fmt;
  1071. Xextern  ROW_FMT octal_16_fmt;
  1072. Xextern  ROW_FMT octal_32_fmt;
  1073. Xextern  ROW_FMT decimal_8_fmt;
  1074. Xextern  ROW_FMT decimal_16_fmt;
  1075. Xextern  ROW_FMT decimal_32_fmt;
  1076. Xextern  ROW_FMT hex_8_fmt;
  1077. Xextern  ROW_FMT hex_16_fmt;
  1078. Xextern  ROW_FMT hex_32_fmt;
  1079. X
  1080. Xextern  bool    read_pat_mode;
  1081. Xextern  bool    dont_repeat;
  1082. Xextern    BUFFER  sav_buf;
  1083. X
  1084. Xchar    dec_chr_ok ();
  1085. Xulong   get_long ();
  1086. Xvoid wind_on_dot_all ();
  1087. X
  1088. X/*
  1089. X* Display a bunch of useful information about
  1090. X* the current location of dot and mark.
  1091. X* The position of the dot and mark and the difference between them.
  1092. X* The total buffer size is displayed.
  1093. X* This is normally bound to "C-X =".
  1094. X*/
  1095. Xbool showcpos (f, n, k)
  1096. X{
  1097. X
  1098. X    A32     dotoff,
  1099. X        markoff,
  1100. X        fsize,
  1101. X        bsize;
  1102. X    char    buf[NCOL * 2], buf1[NCOL * 2];
  1103. X
  1104. X    dotoff = curwp -> w_dotp -> l_file_offset;
  1105. X    dotoff += curwp -> w_doto;
  1106. X
  1107. X    if (curwp -> w_markp != NULL)
  1108. X    {
  1109. X        markoff = curwp -> w_markp -> l_file_offset;
  1110. X        markoff += curwp -> w_marko;
  1111. X    }
  1112. X
  1113. X    bsize = curwp -> w_bufp -> b_linep -> l_bp -> l_file_offset;
  1114. X    bsize += curwp -> w_bufp -> b_linep -> l_bp -> l_used;
  1115. X    fsize = curbp -> b_file_size;
  1116. X
  1117. X    if (curwp -> w_markp != NULL)
  1118. X    {
  1119. X        /* build format string */
  1120. X        sprintf (buf1, MSG_sh_pos, R_POS_FMT(curwp), R_POS_FMT(curwp), 
  1121. X            R_POS_FMT(curwp), R_POS_FMT(curwp));
  1122. X        sprintf (buf, buf1, dotoff, markoff, bsize, fsize);
  1123. X    }
  1124. X    else
  1125. X    {
  1126. X        /* build format string */
  1127. X        sprintf (buf1, MSG_sh_pos1, R_POS_FMT(curwp), R_POS_FMT(curwp), 
  1128. X            R_POS_FMT(curwp));
  1129. X        sprintf (buf, buf1, dotoff, bsize, fsize);
  1130. X    }
  1131. X
  1132. X    sprintf (&buf[strlen(buf)], MSG_f_str, curbp -> b_fname);
  1133. X    writ_echo (buf);
  1134. X
  1135. X    return (TRUE);
  1136. X}
  1137. X
  1138. X
  1139. X/*
  1140. X* Twiddle the two characters on either side of
  1141. X* dot. If dot is at the end of the line twiddle the
  1142. X* two characters before it. Return with an error if dot
  1143. X* is at the beginning of line; it seems to be a bit
  1144. X* pointless to make this work. This fixes up a very
  1145. X* common typo with a single stroke. Normally bound
  1146. X* to "C-T". This always works within a line, so
  1147. X* "WFEDIT" is good enough.
  1148. X*/
  1149. Xbool twiddle ()
  1150. X{
  1151. X
  1152. X    register    LINE * dotp;
  1153. X    register short  doto;
  1154. X    char    b_per_u,
  1155. X    f_buf[4],
  1156. X    s_buf[4],
  1157. X    i;
  1158. X
  1159. X    dotp = curwp -> w_dotp;
  1160. X    doto = curwp -> w_doto;
  1161. X    b_per_u = curwp -> w_fmt_ptr -> r_b_per_u;
  1162. X    /* try to move back one unit */
  1163. X    if (!move_ptr (curwp, (long) - b_per_u, TRUE, TRUE, TRUE))
  1164. X    {
  1165. X        curwp -> w_dotp = dotp; /* if fail then restore dot and quit */
  1166. X        curwp -> w_doto = doto;
  1167. X        ttbeep ();
  1168. X        return (FALSE);
  1169. X    }
  1170. X    /* pick up first unit byte by byte */
  1171. X    for (i = 0; i < b_per_u; i++)
  1172. X    {
  1173. X        f_buf[i] = DOT_CHAR(curwp);
  1174. X        move_ptr (curwp, 1L, TRUE, FALSE, TRUE);
  1175. X    }
  1176. X    /* move to the end of the second unit */
  1177. X    if (!move_ptr (curwp, (long) (b_per_u - 1), TRUE, FALSE, TRUE))
  1178. X    {
  1179. X        curwp -> w_dotp = dotp; /* if fail then restore dot and quit */
  1180. X        curwp -> w_doto = doto;
  1181. X        ttbeep ();
  1182. X        return (FALSE);
  1183. X    }
  1184. X    /* pick up second unit (reverse order) and deposit second unit */
  1185. X    for (i = 0; i < b_per_u; i++)
  1186. X    {
  1187. X        s_buf[i] = DOT_CHAR(curwp);
  1188. X        DOT_CHAR(curwp) = f_buf[b_per_u - 1 - i];
  1189. X        move_ptr (curwp, -1L, TRUE, FALSE, TRUE);
  1190. X    }
  1191. X    /* deposit first unit */
  1192. X    for (i = 0; i < b_per_u; i++)
  1193. X    {
  1194. X        DOT_CHAR(curwp) = s_buf[i];
  1195. X        move_ptr (curwp, -1L, TRUE, FALSE, TRUE);
  1196. X    }
  1197. X    curwp -> w_dotp = dotp;
  1198. X    curwp -> w_doto = doto;
  1199. X    lchange (WFHARD);
  1200. X    return (TRUE);
  1201. X}
  1202. X
  1203. X/*
  1204. X* Quote the next character, and
  1205. X* insert it into the buffer. All the characters
  1206. X* are taken literally.
  1207. X* The character
  1208. X* is always read, even if it is inserted 0 times, for
  1209. X* regularity.
  1210. X*/
  1211. Xbool quote (f, n, k)
  1212. X{
  1213. X    register int    c;
  1214. X
  1215. X    if (kbdmop != NULL)
  1216. X        c = *kbdmop++;
  1217. X    else
  1218. X    {
  1219. X        c = ttgetc ();
  1220. X        if (kbdmip != NULL)
  1221. X        {
  1222. X            if (kbdmip > &kbdm[NKBDM - 4])
  1223. X            {
  1224. X                ctrlg (FALSE, 0, KRANDOM);
  1225. X                return (ABORT);
  1226. X            }
  1227. X
  1228. X            *kbdmip++ = c;
  1229. X        }
  1230. X
  1231. X    }
  1232. X
  1233. X    if (n < 0)
  1234. X        return (FALSE);
  1235. X    if (n == 0)
  1236. X        return (TRUE);
  1237. X
  1238. X    return (linsert (n, c));
  1239. X}
  1240. X
  1241. X/*
  1242. X* Toggle the insert mode.  Insert mode is used only in ASCII or EBCDIC modes.
  1243. X*/
  1244. Xbool insert_toggle ()    /* toggle routine for selfinsert */
  1245. X{
  1246. X    register    WINDOW * wp;
  1247. X
  1248. X    if (curbp -> b_flag & BFSLOCK)
  1249. X        return (TRUE);
  1250. X
  1251. X    if (read_pat_mode)
  1252. X        dont_repeat = TRUE;
  1253. X
  1254. X    insert_mode = !insert_mode;
  1255. X    for (wp = wheadp; wp; wp = wp -> w_wndp)
  1256. X        wp -> w_flag |= WFMODE; /* force mode line update */
  1257. X    return (TRUE);
  1258. X}
  1259. X
  1260. X/*
  1261. X* Ordinary text characters are bound to this function,
  1262. X* which inserts them into the buffer. Characters marked as control
  1263. X* characters (using the CTRL flag) may be remapped to their ASCII
  1264. X* equivalent. This makes TAB (C-I) work right, and also makes the
  1265. X* world look reasonable if a control character is bound to this
  1266. X* this routine by hand. Any META or CTLX flags on the character
  1267. X* are discarded. 
  1268. X* 
  1269. X*   Edit the unit under the cursor.
  1270. X*   Check that the character is valid for the current display mode.
  1271. X*/
  1272. X
  1273. Xbool selfinsert (f, n, k)
  1274. X{
  1275. X
  1276. X    register int    c;
  1277. X    char    edt_buf[4],
  1278. X    i_chr,
  1279. X    b_per_u,
  1280. X    u_offs,
  1281. X    u_roffs,
  1282. X    bit_shf,
  1283. X    i;
  1284. X    LINE    * l_ptr;
  1285. X    short   d_offs;
  1286. X    int     bytes,
  1287. X    temp_int;
  1288. X    long    dot_shf,
  1289. X    l_mask,
  1290. X    l_val;
  1291. X    char    text_buf[12];
  1292. X    static char max_dec_8[] = "255";
  1293. X    static char max_dec_16[] = "65535";
  1294. X    static char max_dec_32[] = "4294967295";
  1295. X    int        cur_col;
  1296. X
  1297. X    bool intel;
  1298. X
  1299. X    if (n < 0)
  1300. X    {
  1301. X        ttbeep ();
  1302. X        return (FALSE);
  1303. X    }
  1304. X    if (n == 0)
  1305. X    {
  1306. X        ttbeep ();
  1307. X        return (TRUE);
  1308. X    }
  1309. X    c = k & KCHAR;
  1310. X    if ((k & KCTRL) != 0 && c >= '@' && c <= '_')/* ASCII-ify.           */
  1311. X        c -= '@';
  1312. X    b_per_u = curwp -> w_fmt_ptr -> r_b_per_u;
  1313. X    u_offs = curwp -> w_unit_offset;
  1314. X    u_roffs = curwp -> w_fmt_ptr -> r_chr_per_u - u_offs - 1;
  1315. X    intel = curwp -> w_intel_mode;
  1316. X
  1317. X    cur_col = ttcol;
  1318. X
  1319. X    switch (curwp -> w_fmt_ptr -> r_type)
  1320. X    {
  1321. X    case EBCDIC:
  1322. X        c = to_ebcdic (c);  /* convert ASCII to EBCDIC */
  1323. X    case ASCII:
  1324. X        if ((insert_mode) || (DOT_POS(curwp) == BUF_SIZE(curwp)))
  1325. X        {
  1326. X            linsert (n, c);
  1327. X            if (read_pat_mode)
  1328. X                forwchar (0, 1, KRANDOM);/* advance the cursor */
  1329. X        }
  1330. X        else
  1331. X            lreplace (n, c);
  1332. X        break;
  1333. X
  1334. X    case HEX:
  1335. X        if ((c >= '0') && (c <= '9'))
  1336. X        {
  1337. X            i_chr = c - '0';/* convert to binary */
  1338. X        }
  1339. X        else
  1340. X            if ((c >= 'A') && (c <= 'F'))
  1341. X            {
  1342. X                i_chr = c - 'A' + 10;/* convert to binary */
  1343. X            }
  1344. X            else
  1345. X                if ((c >= 'a') && (c <= 'f'))
  1346. X                {
  1347. X                    i_chr = c - 'a' + 10;/* convert to binary */
  1348. X                }
  1349. X                else
  1350. X                {
  1351. X                    bad_key (k);
  1352. X                    return (FALSE);
  1353. X                }
  1354. X        fill_out (); /* expand buffer if necessary */
  1355. X
  1356. X        /* position dot to byte to be altered */
  1357. X        if (intel)
  1358. X            dot_shf = u_roffs >> 1;
  1359. X        else
  1360. X            dot_shf = u_offs >> 1;
  1361. X
  1362. X        /* save dot position for later */
  1363. X        l_ptr = curwp -> w_dotp;
  1364. X        d_offs = curwp -> w_doto;
  1365. X        move_ptr (curwp, dot_shf, TRUE, FALSE, TRUE);
  1366. X
  1367. X        if (u_offs & 1)
  1368. X        {               /* lower nibble in byte */
  1369. X            i_chr &= 0x0f;
  1370. X            DOT_CHAR(curwp) &= 0xf0;
  1371. X            DOT_CHAR(curwp) |= i_chr;
  1372. X        }
  1373. X        else
  1374. X        {               /* upper nibble in byte */
  1375. X            i_chr <<= 4;
  1376. X            i_chr &= 0xf0;
  1377. X            DOT_CHAR(curwp) &= 0x0f;
  1378. X            DOT_CHAR(curwp) |= i_chr;
  1379. X        }
  1380. X
  1381. X        /* restore dot position */
  1382. X        curwp -> w_dotp = l_ptr;
  1383. X        curwp -> w_doto = d_offs;
  1384. X        forwchar (0, 1, KRANDOM);/* advance the cursor */
  1385. X        break;
  1386. X
  1387. X    case BINARY:
  1388. X        if ((c != '0') && (c != '1'))
  1389. X        {
  1390. X            bad_key (k);
  1391. X            return (FALSE);
  1392. X        }
  1393. X
  1394. X        /* position dot to byte to be altered */
  1395. X        if (intel)
  1396. X            dot_shf = u_roffs >> 3;
  1397. X        else
  1398. X            dot_shf = u_offs >> 3;
  1399. X
  1400. X        fill_out (); /* expand buffer if necessary */
  1401. X
  1402. X        /* save dot position for later */
  1403. X        l_ptr = curwp -> w_dotp;
  1404. X        d_offs = curwp -> w_doto;
  1405. X        move_ptr (curwp, dot_shf, TRUE, FALSE, TRUE);
  1406. X
  1407. X        bit_shf = u_roffs & 0x07;
  1408. X
  1409. X        if (c == '0')
  1410. X        {
  1411. X            DOT_CHAR(curwp) &= ~(1 << bit_shf);
  1412. X        }
  1413. X        else
  1414. X        {
  1415. X            DOT_CHAR(curwp) |= 1 << bit_shf;
  1416. X        }
  1417. X
  1418. X        /* restore dot position */
  1419. X        curwp -> w_dotp = l_ptr;
  1420. X        curwp -> w_doto = d_offs;
  1421. X        forwchar (0, 1, KRANDOM);/* advance the cursor */
  1422. X        break;
  1423. X
  1424. X    case OCTAL:
  1425. X        if (c < '0')
  1426. X        {
  1427. X            bad_key (k);
  1428. X            return (FALSE);
  1429. X        }
  1430. X        else
  1431. X            if ((c > '1') && (u_offs == 0) &&
  1432. X                ((curwp -> w_fmt_ptr -> r_size) == WORDS))
  1433. X            {
  1434. X                bad_key (k);
  1435. X                return (FALSE);
  1436. X            }
  1437. X            else
  1438. X                if ((c > '3') && (u_offs == 0))
  1439. X                {
  1440. X                    bad_key (k);
  1441. X                    return (FALSE);
  1442. X                }
  1443. X                else
  1444. X                    if (c > '7')
  1445. X                    {
  1446. X                        bad_key (k);
  1447. X                        return (FALSE);
  1448. X                    }
  1449. X
  1450. X        dot_shf = (c - '0') & 7;/* get binary value */
  1451. X        l_mask = 7;         /* create bit mask */
  1452. X
  1453. X        dot_shf <<= (u_roffs * 3);
  1454. X        l_mask <<= (u_roffs * 3);
  1455. X
  1456. X        fill_out (); /* expand buffer if necessary */
  1457. X
  1458. X        /* save dot position for later */
  1459. X        l_ptr = curwp -> w_dotp;
  1460. X        d_offs = curwp -> w_doto;
  1461. X
  1462. X        /* position dot to the byte to be altered */
  1463. X        if (intel)
  1464. X        {
  1465. X            for (i = 0; i < b_per_u; i++)
  1466. X            {
  1467. X                DOT_CHAR(curwp) &= ~((D8) l_mask & 0xff);
  1468. X                DOT_CHAR(curwp) |= (D8) dot_shf & 0xff;
  1469. X                l_mask >>= 8;
  1470. X                dot_shf >>= 8;
  1471. X                move_ptr (curwp, 1L, TRUE, FALSE, TRUE);
  1472. X            }
  1473. X        }
  1474. X        else
  1475. X        {
  1476. X            move_ptr (curwp, (long) (b_per_u - 1), TRUE, FALSE, TRUE);
  1477. X            /* move to last byte */
  1478. X            for (i = 0; i < b_per_u; i++)
  1479. X            {
  1480. X                DOT_CHAR(curwp) &= ~((D8) l_mask & 0xff);
  1481. X                DOT_CHAR(curwp) |= (D8) dot_shf & 0xff;
  1482. X                l_mask >>= 8;
  1483. X                dot_shf >>= 8;
  1484. X                move_ptr (curwp, -1L, TRUE, FALSE, TRUE);/* step back one byte */
  1485. X            }
  1486. X        }
  1487. X
  1488. X        /* restore dot position */
  1489. X        curwp -> w_dotp = l_ptr;
  1490. X        curwp -> w_doto = d_offs;
  1491. X        forwchar (0, 1, KRANDOM);/* advance the cursor */
  1492. X        break;
  1493. X
  1494. X    case DECIMAL:
  1495. X        fill_out (); /* expand buffer if necessary */
  1496. X
  1497. X        /* save dot position for later */
  1498. X        l_ptr = curwp -> w_dotp;
  1499. X        d_offs = curwp -> w_doto;
  1500. X
  1501. X        bytes = fill_buf (curwp, l_ptr, d_offs, edt_buf, b_per_u);
  1502. X        /* if last unit is not full and must be extended */
  1503. X        for (; bytes < b_per_u; bytes++)
  1504. X        {
  1505. X            edt_buf[3] = edt_buf[2];/* shuffle bytes down */
  1506. X            edt_buf[2] = edt_buf[1];
  1507. X            edt_buf[1] = edt_buf[0];
  1508. X            edt_buf[0] = 0;
  1509. X        }
  1510. X        switch (curwp -> w_fmt_ptr -> r_size)
  1511. X        {
  1512. X        case BYTES:
  1513. X            sprintf (text_buf, MSG_03u, (int) (edt_buf[0] & 0xff));
  1514. X            if (!dec_chr_ok (text_buf, max_dec_8, c, u_offs))
  1515. X            {
  1516. X                bad_key (k);
  1517. X                return (TRUE);  /* TRUE so that mask will be same len */
  1518. X            }
  1519. X            sscanf (text_buf, MSG_3u, &i);/* convert back to binary */
  1520. X            l_val = (long) i & 0xff;
  1521. X            break;
  1522. X
  1523. X        case WORDS:
  1524. X            l_val = get_int (edt_buf);/* do intel swap */
  1525. X            sprintf (text_buf, MSG_05u, (int) (l_val & 0xFFFF));
  1526. X            if (!dec_chr_ok (text_buf, max_dec_16, c, u_offs))
  1527. X            {
  1528. X                bad_key (k);
  1529. X                return (TRUE);  /* TRUE so that mask will be same len */
  1530. X            }
  1531. X            sscanf (text_buf, MSG_5u, &temp_int);
  1532. X            /* convert back to binary */
  1533. X            l_val = get_int ((char *) & temp_int);/* do intel swap */
  1534. X            break;
  1535. X
  1536. X        case DWORDS:
  1537. X            l_val = get_long (edt_buf);/* do intel swap */
  1538. X            sprintf (text_buf, MSG_010lu, l_val);
  1539. X            if (!dec_chr_ok (text_buf, max_dec_32, c, u_offs))
  1540. X            {
  1541. X                bad_key (k);
  1542. X                return (TRUE);  /* TRUE so that mask will be same len */
  1543. X            }
  1544. X            sscanf (text_buf, MSG_lu, &l_val);
  1545. X            /* convert back to binary */
  1546. X            l_val = get_long ((char *) & l_val);/* do intel swap */
  1547. X            break;
  1548. X#if RUNCHK
  1549. X        default:
  1550. X            writ_echo (ERR_rnd_2);
  1551. X            break;
  1552. X#endif
  1553. X        }
  1554. X        DOT_CHAR(curwp) = (char) l_val & 0xff;
  1555. X        for (i = 1; i < b_per_u; i++)
  1556. X        {
  1557. X            l_val >>= 8;
  1558. X            move_ptr (curwp, 1L, TRUE, FALSE, TRUE);/* step forward one byte */
  1559. X            DOT_CHAR(curwp) = (char) l_val & 0xff;
  1560. X        }
  1561. X
  1562. X        /* restore dot position */
  1563. X        curwp -> w_dotp = l_ptr;
  1564. X        curwp -> w_doto = d_offs;
  1565. X        forwchar (0, 1, KRANDOM);/* advance the cursor */
  1566. X        break;
  1567. X
  1568. X#if RUNCHK
  1569. X    default:
  1570. X        writ_echo (ERR_rnd_3);
  1571. X        break;
  1572. X#endif
  1573. X    }
  1574. X    /* if cursor has wrapped to the next line then previous line
  1575. X        will not be refreshed with WFEDIT so do a WFHARD */
  1576. X    if (cur_col > get_curcol(curwp))
  1577. X        lchange (WFHARD);
  1578. X    else
  1579. X        lchange (WFEDIT);
  1580. X
  1581. X    return (TRUE);
  1582. X}
  1583. X
  1584. X/*
  1585. X*   Insert one unit of zeros at the current dot position.
  1586. X*/
  1587. Xbool    insertunit (f, n, k)
  1588. X{
  1589. X    lchange (WFEDIT);
  1590. X    linsert ((R_B_PER_U(curwp) * n), 0);
  1591. X    return (TRUE);
  1592. X}
  1593. X
  1594. X/* 
  1595. X*   Increase the size of the buffer if necessary.
  1596. X*   If dot is at the byte after the last full unit
  1597. X*   then add enough bytes to the buffer to create 
  1598. X*   a full unit at the end.
  1599. X*/
  1600. X
  1601. Xbool    fill_out ()
  1602. X{
  1603. X    long    buf_size, dot_pos, last_unit;
  1604. X    int     b_per_u;
  1605. X    char    stat, shift;
  1606. X    int     insert_val;
  1607. X
  1608. X    buf_size = BUF_SIZE(curwp);
  1609. X    dot_pos = DOT_POS(curwp);
  1610. X    b_per_u = R_B_PER_U(curwp);
  1611. X    shift = curwp -> w_disp_shift;
  1612. X    stat = TRUE;
  1613. X    insert_val = 0;
  1614. X    last_unit = buf_size & ~((long)(b_per_u - 1));
  1615. X    /* there is an even number of units step back one */
  1616. X    if (last_unit == buf_size)
  1617. X        last_unit -= b_per_u;
  1618. X    last_unit += shift;
  1619. X
  1620. X    /* if dot is one byte past the end of the buffer */
  1621. X    if (dot_pos > last_unit)
  1622. X    {
  1623. X        insert_val = b_per_u;
  1624. X    }
  1625. X
  1626. X    /* if dot is pointed at the end of the buffer */
  1627. X    else if (dot_pos == last_unit)
  1628. X    {
  1629. X        insert_val = b_per_u - (buf_size - last_unit);
  1630. X    }
  1631. X
  1632. X    /* if insert is necessary then do it */
  1633. X    if (insert_val != 0)
  1634. X    {
  1635. X        lchange (WFHARD);
  1636. X        move_ptr (curwp, buf_size, TRUE, FALSE, FALSE); /* move dot to end */
  1637. X        stat = linsert (insert_val, 0);
  1638. X        move_ptr (curwp, dot_pos, TRUE, TRUE, FALSE); /* put dot back */
  1639. X    }
  1640. X    return (stat);
  1641. X}
  1642. X
  1643. X/*
  1644. X*   This checks that an entered character is ok
  1645. X*   for the position given.
  1646. X*/
  1647. X
  1648. Xchar    dec_chr_ok (char_buf, max_str, chr, pos)
  1649. X
  1650. Xchar    chr,
  1651. Xpos,
  1652. X*char_buf,
  1653. X*max_str;
  1654. X
  1655. X{
  1656. X    char    i;
  1657. X
  1658. X    if ((chr < '0') || (chr > '9'))
  1659. X        return (FALSE);
  1660. X
  1661. X    char_buf[pos] = chr;        /* insert typed char */
  1662. X
  1663. X    /* check if number is too big */
  1664. X    for (i = 0; max_str[i] != 0; i++)
  1665. X    {
  1666. X        if (char_buf[i] < max_str[i])
  1667. X            break;              /* if char is smaller then must be ok */
  1668. X
  1669. X        if (char_buf[i] > max_str[i])
  1670. X            return (FALSE);     /* val is too large; ERROR */
  1671. X    }
  1672. X    return (TRUE);
  1673. X}
  1674. X
  1675. X/*
  1676. X* Set the rest of the variables for the mode change.
  1677. X*/
  1678. Xvoid    set_mode_vars ()
  1679. X{
  1680. X    curwp -> w_disp_shift = 0;  /* shift to 0 when changing mode */
  1681. X    curwp -> w_unit_offset = 0; /* go to end of unit */
  1682. X    /* if we are in the middle of a search then use the proper format struc */
  1683. X    if (read_pat_mode)
  1684. X        curwp -> w_fmt_ptr = curwp -> w_fmt_ptr -> r_srch_fmt;
  1685. X
  1686. X    wind_on_dot (curwp);
  1687. X    curwp -> w_flag = WFHARD;
  1688. X    update ();
  1689. X}
  1690. X
  1691. X/*
  1692. X* Change the display mode to ASCII.
  1693. X* The default binding is META C-A.
  1694. X*/
  1695. Xbool    asciimode ()
  1696. X{
  1697. X    curwp -> w_fmt_ptr = &ascii_fmt;
  1698. X    set_mode_vars ();
  1699. X    return (TRUE);
  1700. X}
  1701. X
  1702. X/*
  1703. X* Change the display mode to EBCDIC.
  1704. X* The default binding is META C-E.
  1705. X*/
  1706. Xbool    ebcdicmode ()
  1707. X{
  1708. X    curwp -> w_fmt_ptr = &ebcdic_fmt;
  1709. X    set_mode_vars ();
  1710. X    return (TRUE);
  1711. X}
  1712. X
  1713. X/*
  1714. X* Change the display mode to DECIMAL.
  1715. X* The default binding is META C-D.
  1716. X*/
  1717. Xbool    decimalmode ()
  1718. X{
  1719. X    switch (curwp -> w_fmt_ptr -> r_size)
  1720. X    {
  1721. X    case BYTES:
  1722. X        curwp -> w_fmt_ptr = &decimal_8_fmt;
  1723. X        break;
  1724. X    case WORDS:
  1725. X        curwp -> w_fmt_ptr = &decimal_16_fmt;
  1726. X        break;
  1727. X
  1728. X    case DWORDS:
  1729. X        curwp -> w_fmt_ptr = &decimal_32_fmt;
  1730. X        break;
  1731. X#if RUNCHK
  1732. X    default:
  1733. X        writ_echo (ERR_rnd_4);
  1734. X        break;
  1735. X#endif
  1736. X    }
  1737. X    set_mode_vars ();
  1738. X    return (TRUE);
  1739. X}
  1740. X
  1741. X/*
  1742. X* Change the display mode to HEXADECIMAL.
  1743. X* The default binding is META C-H.
  1744. X*/
  1745. Xbool    hexmode ()
  1746. X{
  1747. X    switch (curwp -> w_fmt_ptr -> r_size)
  1748. X    {
  1749. X    case BYTES:
  1750. X        curwp -> w_fmt_ptr = &hex_8_fmt;
  1751. X        break;
  1752. X    case WORDS:
  1753. X        curwp -> w_fmt_ptr = &hex_16_fmt;
  1754. X        break;
  1755. X    case DWORDS:
  1756. X        curwp -> w_fmt_ptr = &hex_32_fmt;
  1757. X        break;
  1758. X#if RUNCHK
  1759. X    default:
  1760. X        writ_echo (ERR_rnd_5);
  1761. X        break;
  1762. X#endif
  1763. X    }
  1764. X    set_mode_vars ();
  1765. X    return (TRUE);
  1766. X}
  1767. X
  1768. X/*
  1769. X* Change the display mode to OCTAL.
  1770. X* The default binding is META C-O.
  1771. X*/
  1772. Xbool    octalmode ()
  1773. X{
  1774. X    switch (curwp -> w_fmt_ptr -> r_size)
  1775. X    {
  1776. X    case BYTES:
  1777. X        curwp -> w_fmt_ptr = &octal_8_fmt;
  1778. X        break;
  1779. X
  1780. X    case WORDS:
  1781. X        curwp -> w_fmt_ptr = &octal_16_fmt;
  1782. X        break;
  1783. X
  1784. X    case DWORDS:
  1785. X        curwp -> w_fmt_ptr = &octal_32_fmt;
  1786. X        break;
  1787. X#if RUNCHK
  1788. X    default:
  1789. X        writ_echo (ERR_rnd_6);
  1790. X        break;
  1791. X#endif
  1792. X    }
  1793. X    set_mode_vars ();
  1794. X    return (TRUE);
  1795. X}
  1796. X
  1797. X/*
  1798. X* Change the display mode to BINARY.
  1799. X* The default binding is META C-B.
  1800. X*/
  1801. Xbool    binarymode ()
  1802. X{
  1803. X    switch (curwp -> w_fmt_ptr -> r_size)
  1804. X    {
  1805. X    case BYTES:
  1806. X        curwp -> w_fmt_ptr = &binary_8_fmt;
  1807. X        break;
  1808. X    case WORDS:
  1809. X        curwp -> w_fmt_ptr = &binary_16_fmt;
  1810. X        break;
  1811. X    case DWORDS:
  1812. X        curwp -> w_fmt_ptr = &binary_32_fmt;
  1813. X        break;
  1814. X#if RUNCHK
  1815. X    default:
  1816. X        writ_echo (ERR_rnd_7);
  1817. X        break;
  1818. X#endif
  1819. X    }
  1820. X    set_mode_vars ();
  1821. X    return (TRUE);
  1822. X}
  1823. X
  1824. X/*
  1825. X* Change the display shift.
  1826. X* Circularly rotate through display shift of 0 through 3.
  1827. X* This value is used to shift the display by the designated number of bytes.
  1828. X* This is used to cause WORD and DWORD values to be calculated
  1829. X* from the correct offset.
  1830. X*/
  1831. Xbool dispshift (f, n, k)
  1832. X{
  1833. X    char    mode,
  1834. X    size;
  1835. X
  1836. X    if (read_pat_mode)
  1837. X        return (TRUE);  /* no shift is allowed in search mode */
  1838. X
  1839. X
  1840. X    mode = curwp -> w_fmt_ptr -> r_type;
  1841. X    size = curwp -> w_fmt_ptr -> r_size;
  1842. X
  1843. X    if (((mode == HEX) ||
  1844. X        (mode == DECIMAL) ||
  1845. X        (mode == BINARY) ||
  1846. X        (mode == OCTAL)) &&
  1847. X        (size != BYTES))
  1848. X    {
  1849. X        if ((size == WORDS) &&
  1850. X            (curwp -> w_disp_shift >= 1))
  1851. X        {                   /* roll over on words */
  1852. X            curwp -> w_disp_shift = 0;
  1853. X        }
  1854. X        else
  1855. X            if ((size == DWORDS) &&
  1856. X                (curwp -> w_disp_shift >= 3))
  1857. X            {               /* roll over on double words */
  1858. X                curwp -> w_disp_shift = 0;
  1859. X            }
  1860. X            else
  1861. X            {
  1862. X                curwp -> w_disp_shift++;/* increment shift */
  1863. X            }
  1864. X    }
  1865. X    else
  1866. X    {
  1867. X        curwp -> w_disp_shift = 0;/* set to no shift */
  1868. X    }
  1869. X    move_ptr (curwp, 0L, TRUE, TRUE, TRUE);
  1870. X    wind_on_dot (curwp);
  1871. X    curwp -> w_flag = WFHARD;   /* force full window refresh */
  1872. X    return (TRUE);
  1873. X}
  1874. X
  1875. X/*
  1876. X* Delete forward. This is real
  1877. X* easy, because the basic delete routine does
  1878. X* all of the work. Watches for negative arguments,
  1879. X* and does the right thing. If any argument is
  1880. X* present, it kills rather than deletes, to prevent
  1881. X* loss of text if typed with a big argument.
  1882. X* Normally bound to "C-D".
  1883. X*/
  1884. Xchar    forwdel (f, n, k)
  1885. X{
  1886. X    char    s;
  1887. X
  1888. X    if (n < 0)
  1889. X        return (backdel (f, -n, KRANDOM));
  1890. X
  1891. X    s = FALSE;
  1892. X    if (R_SIZE(curwp) == BYTES)
  1893. X    {
  1894. X        if (f != FALSE)
  1895. X        {
  1896. X            /* Really a kill.       */
  1897. X            if ((lastflag & CFKILL) == 0)
  1898. X                bclear (&sav_buf);
  1899. X            thisflag |= CFKILL;
  1900. X        }
  1901. X        s = ldelete ((A32)n, f);
  1902. X        curwp -> w_unit_offset = 0;
  1903. X    }
  1904. X    return (s);
  1905. X}
  1906. X
  1907. X
  1908. X/*
  1909. X* Delete backwards. This is quite easy too,
  1910. X* because it's all done with other functions. Just
  1911. X* move the cursor back, and delete forwards.
  1912. X* Like delete forward, this actually does a kill
  1913. X* if presented with an argument.
  1914. X*/
  1915. Xchar    backdel (f, n, k)
  1916. X{
  1917. X
  1918. X    int     u_off;
  1919. X    char    s;
  1920. X
  1921. X    if (n < 0)
  1922. X        return (forwdel (f, -n, KRANDOM));
  1923. X
  1924. X    s = FALSE;
  1925. X    if (R_SIZE(curwp) == BYTES)
  1926. X    {
  1927. X        u_off = curwp -> w_unit_offset;
  1928. X        curwp -> w_unit_offset = 0;
  1929. X        if ((s = backchar (f, n * R_CHR_PER_U(curwp), KRANDOM)) == TRUE)
  1930. X        {
  1931. X            s = ldelete ((A32)n, f);
  1932. X            if (f != FALSE)
  1933. X            {
  1934. X                /* Really a kill.       */
  1935. X                if ((lastflag & CFKILL) == 0)
  1936. X                    bclear (&sav_buf);
  1937. X                thisflag |= CFKILL;
  1938. X            }
  1939. X        }
  1940. X        curwp -> w_unit_offset = u_off;
  1941. X    }
  1942. X    return (s);
  1943. X}
  1944. X
  1945. X
  1946. X/*
  1947. X* Change the size of the display unit to BYTE.
  1948. X* Adjust byte shift to the allowable range.
  1949. X* Normally bound to "META-1".
  1950. X*/
  1951. Xbool dispsize1 ()
  1952. X{
  1953. X    curwp -> w_disp_shift = 0;  /* shift to 0 when changing size */
  1954. X    curwp -> w_unit_offset = 0; /* go to end of unit */
  1955. X
  1956. X    switch (R_TYPE(curwp))
  1957. X    {
  1958. X    case OCTAL:
  1959. X        curwp -> w_fmt_ptr = &octal_8_fmt;
  1960. X        break;
  1961. X
  1962. X    case DECIMAL:
  1963. X        curwp -> w_fmt_ptr = &decimal_8_fmt;
  1964. X        break;
  1965. X
  1966. X    case HEX:
  1967. X        curwp -> w_fmt_ptr = &hex_8_fmt;
  1968. X        break;
  1969. X
  1970. X    case BINARY:
  1971. X        curwp -> w_fmt_ptr = &binary_8_fmt;
  1972. X        break;
  1973. X
  1974. X    default:
  1975. X        return (TRUE);
  1976. X        break;
  1977. X    }
  1978. X
  1979. X    /* if we are in the middle of a search then use the proper format struc */
  1980. X    if (read_pat_mode)
  1981. X        curwp -> w_fmt_ptr = curwp -> w_fmt_ptr -> r_srch_fmt;
  1982. X
  1983. X    move_ptr (curwp, 0L, TRUE, TRUE, TRUE);
  1984. X    wind_on_dot (curwp);
  1985. X    curwp -> w_flag = WFHARD;
  1986. X    update ();
  1987. X    return (TRUE);
  1988. X}
  1989. X
  1990. X/*
  1991. X* Change the size of the display unit to WORD.
  1992. X* Adjust byte shift to the allowable range.
  1993. X* Normally bound to "META-2".
  1994. X*/
  1995. Xbool dispsize2 ()
  1996. X{
  1997. X    curwp -> w_disp_shift = 0;  /* shift to 0 when changing size */
  1998. X    curwp -> w_unit_offset = 0; /* go to end of unit */
  1999. X
  2000. X    switch (R_TYPE(curwp))
  2001. X    {
  2002. X    case OCTAL:
  2003. X        curwp -> w_fmt_ptr = &octal_16_fmt;
  2004. X        break;
  2005. X
  2006. X    case DECIMAL:
  2007. X        curwp -> w_fmt_ptr = &decimal_16_fmt;
  2008. X        break;
  2009. X
  2010. X    case HEX:
  2011. X        curwp -> w_fmt_ptr = &hex_16_fmt;
  2012. X        break;
  2013. X
  2014. X    case BINARY:
  2015. X        curwp -> w_fmt_ptr = &binary_16_fmt;
  2016. X        break;
  2017. X
  2018. X    default:
  2019. X        return (TRUE);
  2020. X        break;
  2021. X    }
  2022. X
  2023. X    /* if we are in the middle of a search then use the proper format struc */
  2024. X    if (read_pat_mode)
  2025. X        curwp -> w_fmt_ptr = curwp -> w_fmt_ptr -> r_srch_fmt;
  2026. X
  2027. X    move_ptr (curwp, 0L, TRUE, TRUE, TRUE);
  2028. X    wind_on_dot (curwp);
  2029. X    curwp -> w_flag = WFHARD;
  2030. X    update ();
  2031. X    return (TRUE);
  2032. X}
  2033. X
  2034. X/*
  2035. X* Change the size of the display unit to DOUBLE WORD.
  2036. X* Adjust byte shift to the allowable range.
  2037. X* Normally bound to "META-4".
  2038. X*/
  2039. Xbool dispsize4 ()
  2040. X{
  2041. X    curwp -> w_disp_shift = 0;  /* shift to 0 when changing size */
  2042. X    curwp -> w_unit_offset = 0; /* go to end of unit */
  2043. X
  2044. X    switch (R_TYPE(curwp))
  2045. X    {
  2046. X    case OCTAL:
  2047. X        curwp -> w_fmt_ptr = &octal_32_fmt;
  2048. X        break;
  2049. X
  2050. X    case DECIMAL:
  2051. X        curwp -> w_fmt_ptr = &decimal_32_fmt;
  2052. X        break;
  2053. X
  2054. X    case HEX:
  2055. X        curwp -> w_fmt_ptr = &hex_32_fmt;
  2056. X        break;
  2057. X
  2058. X    case BINARY:
  2059. X        curwp -> w_fmt_ptr = &binary_32_fmt;
  2060. X        break;
  2061. X
  2062. X    default:
  2063. X        return (TRUE);
  2064. X        break;
  2065. X    }
  2066. X
  2067. X    /* if we are in the middle of a search then use the proper format struc */
  2068. X    if (read_pat_mode)
  2069. X        curwp -> w_fmt_ptr = curwp -> w_fmt_ptr -> r_srch_fmt;
  2070. X
  2071. X    move_ptr (curwp, 0L, TRUE, TRUE, TRUE);
  2072. X    wind_on_dot (curwp);
  2073. X    curwp -> w_flag = WFHARD;
  2074. X    update ();
  2075. X    return (TRUE);
  2076. X}
  2077. X
  2078. X/*
  2079. X* Display byte swaped.   This command causes the bytes
  2080. X* that are displayed in WORD and DWORD mode to be swaped
  2081. X* in the way that the INTEL microprocessors do it.
  2082. X*/
  2083. Xbool dispswapbyte (f, n, k)
  2084. X{
  2085. X    if ((curwp -> w_fmt_ptr -> r_size) == BYTES)
  2086. X        return (TRUE);
  2087. X
  2088. X    if (curwp -> w_intel_mode)
  2089. X        curwp -> w_intel_mode = FALSE;
  2090. X    else
  2091. X        curwp -> w_intel_mode = TRUE;
  2092. X
  2093. X    curwp -> w_flag = WFHARD;
  2094. X    update ();
  2095. X    return (TRUE);
  2096. X}
  2097. X
  2098. X/*
  2099. X* Yank text back from the kill buffer. This
  2100. X* is really easy. All of the work is done by the
  2101. X* standard insert routines. All you do is run the loop,
  2102. X* and check for errors. 
  2103. X* An attempt has been made to fix the cosmetic bug
  2104. X* associated with a yank when dot is on the top line of
  2105. X* the window (nothing moves, because all of the new
  2106. X* text landed off screen).
  2107. X*/
  2108. Xbool yank (f, n, k)
  2109. X{
  2110. X    register D16    c;
  2111. X    register A32    i;
  2112. X    char        buf[NCOL], buf1[NCOL];
  2113. X
  2114. X    if (n < 0)
  2115. X        return (FALSE);
  2116. X    while (n--)
  2117. X    {
  2118. X        i = 0;
  2119. X        save_buf_home ();
  2120. X        while ((c = get_save_char ()) != (D16)-1)
  2121. X        {
  2122. X            if (linsert (1, c) == FALSE)
  2123. X                return (FALSE);
  2124. X            if ((i & 0x2ff) == 0)
  2125. X            {
  2126. X                sprintf (buf1, MSG_procing, R_POS_FMT(curwp));
  2127. X                sprintf (buf, buf1, (ulong)i);
  2128. X                writ_echo (buf);
  2129. X                /* check if we should quit */
  2130. X                if (ttkeyready ())
  2131. X                {
  2132. X                    wind_on_dot_all();
  2133. X                    if (ttgetc () == CTL_G)
  2134. X                        return (FALSE);
  2135. X                }
  2136. X            }
  2137. X            ++i;
  2138. X        }
  2139. X    }
  2140. X    /* update buffer display */
  2141. X    if ((blistp -> b_nwnd != 0) &&
  2142. X        (blistp -> b_type == BTLIST))
  2143. X        listbuffers ();
  2144. X
  2145. X    curwp -> w_flag |= WFHARD;
  2146. X    return (TRUE);
  2147. X}
  2148. X
  2149. X/*
  2150. X*   Link windows.   pvr
  2151. X*   This function toggles the window linking function.
  2152. X*   When linking is enabled all windows that look at 
  2153. X*   the same buffer will be forced to have the same 
  2154. X*   dot position.   Each window is then moved to be
  2155. X*   positioned on the dot.   Thus when a user moves
  2156. X*   arround a buffer all other views into that buffer 
  2157. X*   will follow.
  2158. X*/
  2159. X
  2160. Xbool linkwind ()
  2161. X
  2162. X{
  2163. X    char    buf[NCOL];
  2164. X
  2165. X    if (curwp -> w_bufp -> b_flag & BFLINK)
  2166. X    {
  2167. X        curwp -> w_bufp -> b_flag &= ~(BFLINK & 0xff);
  2168. X        sprintf (buf, MSG_lnk, curwp -> w_bufp -> b_bname, MSG_unlink);
  2169. X    }
  2170. X    else
  2171. X    {
  2172. X        curwp -> w_bufp -> b_flag |= BFLINK;
  2173. X        sprintf (buf, MSG_lnk, curwp -> w_bufp -> b_bname, MSG_link);
  2174. X    }
  2175. X    writ_echo (buf);
  2176. X    return (TRUE);
  2177. X}
  2178. X/*
  2179. X*   Print all bad keys to the screen and beep 
  2180. X*/
  2181. Xvoid    bad_key (key)
  2182. Xint     key;
  2183. X{
  2184. X    char    buf[NCOL];
  2185. X
  2186. X    ttbeep ();
  2187. X    sprintf (buf, MSG_bad_key);
  2188. X    keyname (&buf[strlen (buf)], key);
  2189. X    sprintf (&buf[strlen (buf)], ", %X", key);
  2190. X    writ_echo (buf);
  2191. X}
  2192. X
  2193. X/*
  2194. X *    Combine sequential bytes from the rest of the windows
  2195. X *    into this window.   This is useful in combining PROM
  2196. X *    image files from odd and even bytes into one file.
  2197. X */
  2198. Xbool    n_way_combine (f, n, k)
  2199. X{
  2200. X    WINDOW * dest_wp, *src_wp;
  2201. X    BUFFER *src_bp;
  2202. X    A32    dotp;
  2203. X    D8    byt;
  2204. X    int j = 0;
  2205. X    char        buf[NCOL], buf1[NCOL];
  2206. X
  2207. X    /* save the destination window for later restore */
  2208. X    dest_wp = curwp;
  2209. X
  2210. X    if ((BUF_SIZE (curwp)) != (A32)0)
  2211. X    {
  2212. X        writ_echo (MSG_w_not_empty);
  2213. X        return(FALSE);
  2214. X    }
  2215. X    /* Current window must be empty, modifiable and not the only one. */
  2216. X    if ((BUF_SIZE (curwp) != 0) ||
  2217. X        (curwp -> w_wndp == NULL) ||
  2218. X        (curwp -> w_bufp -> b_flag & (BFVIEW | BFSLOCK)))
  2219. X    {
  2220. X        writ_echo (MSG_w_not_empty);
  2221. X        return(FALSE);
  2222. X    }
  2223. X
  2224. X
  2225. X
  2226. X
  2227. X    for (;;)
  2228. X    {
  2229. X        /* step to the next window after the destination window */
  2230. X        nextwind();
  2231. X
  2232. X        /* as I cycle around the windows skip the destination window */
  2233. X        if (curwp == dest_wp)
  2234. X        {
  2235. X            continue;
  2236. X        }
  2237. X        byt = DOT_CHAR(curwp) & 0xff;
  2238. X        dotp = DOT_POS(curwp);   /* get the current dot position */
  2239. X        /* move the dot position ahead in current buffer */
  2240. X        if (move_ptr (curwp, 1L, TRUE, FALSE, TRUE) == FALSE)
  2241. X        {
  2242. X            /* did we advance? */
  2243. X            if (DOT_POS(curwp) == dotp)
  2244. X            {
  2245. X                wind_on_dot_all();
  2246. X                writ_echo (MSG_ok);
  2247. X                return (TRUE);   /* done all that we could */
  2248. X            }
  2249. X        }
  2250. X
  2251. X        src_wp = curwp;
  2252. X        src_bp = curwp -> w_bufp;
  2253. X        curwp = dest_wp;
  2254. X        curbp = dest_wp -> w_bufp;
  2255. X        if (linsert (1, byt) == FALSE)
  2256. X        {
  2257. X            wind_on_dot_all();
  2258. X            return (FALSE);    /* insert failed for some reason */
  2259. X        }
  2260. X        curwp = src_wp;
  2261. X        curbp = src_bp;
  2262. X        if ((j++ & 0x2ff) == 0)
  2263. X        {
  2264. X            sprintf (buf1, MSG_procing, R_POS_FMT(curwp));
  2265. X            sprintf (buf, buf1, dotp);
  2266. X            writ_echo (buf);
  2267. X            /* check if we should quit */
  2268. X            if (ttkeyready ())
  2269. X            {
  2270. X                wind_on_dot_all();
  2271. X                if (ttgetc () == CTL_G)
  2272. X                    return (FALSE);
  2273. X            }
  2274. X        }
  2275. X    }
  2276. X}
  2277. X
  2278. X/*
  2279. X *    Split the current buffer into the rest of the windows.
  2280. X *    This is useful in splitting a binary file into PROM
  2281. X *    image files.
  2282. X */
  2283. Xbool    n_way_split (f, n, k)
  2284. X{
  2285. X    WINDOW  *src_wp;
  2286. X    A32     b_size;
  2287. X    D8    byt;
  2288. X    int j = 0;
  2289. X    char        buf[NCOL], buf1[NCOL];
  2290. X
  2291. X    /* save the source window and buffer for later restore */
  2292. X    src_wp = curwp;
  2293. X
  2294. X    /* step to the next window after the source window */
  2295. X    nextwind();
  2296. X
  2297. X    /* check that all the destination windows are empty and modifiable */
  2298. X    for (;;)
  2299. X    {
  2300. X        if ((BUF_SIZE (curwp) != 0) ||
  2301. X            (curwp -> w_bufp -> b_flag & (BFVIEW | BFSLOCK)))
  2302. X        {
  2303. X            writ_echo (MSG_w_not_empty);
  2304. X            return(FALSE);
  2305. X        }
  2306. X
  2307. X        /* force all windows to be refreshed */
  2308. X        lchange (WFHARD);
  2309. X        /* step to the next window */
  2310. X        nextwind();
  2311. X        /* stop after one pass around the windows */
  2312. X        if (curwp == src_wp)
  2313. X            break;
  2314. X    }
  2315. X
  2316. X    b_size = BUF_SIZE(src_wp);  /* get the buffer size */
  2317. X
  2318. X    /* do the split until source is exhausted */
  2319. X    for (;;)
  2320. X    {
  2321. X        /* step to the next window after the source window */
  2322. X        nextwind();
  2323. X
  2324. X        /* current window cannot be the source */
  2325. X        if (curwp == src_wp)
  2326. X            continue;
  2327. X
  2328. X        byt = DOT_CHAR(src_wp) & 0xff;   /* get the byte to copy */
  2329. X
  2330. X        /* are we at the end of the buffer */
  2331. X        if (b_size == DOT_POS(src_wp))
  2332. X        {
  2333. X            wind_on_dot_all();
  2334. X            writ_echo (MSG_ok);
  2335. X            return (TRUE);
  2336. X        }
  2337. X        if (linsert (1, byt) == FALSE)
  2338. X        {
  2339. X            wind_on_dot_all();
  2340. X            return (FALSE);
  2341. X        }
  2342. X        if ((j++ & 0x2ff) == 0)
  2343. X        {
  2344. X            sprintf (buf1, MSG_procing, R_POS_FMT(src_wp));
  2345. X            sprintf (buf, buf1, DOT_POS(src_wp));
  2346. X            writ_echo (buf);
  2347. X            /* check if we should quit */
  2348. X            if (ttkeyready ())
  2349. X            {
  2350. X                wind_on_dot_all();
  2351. X                if (ttgetc () == CTL_G)
  2352. X                    return (FALSE);
  2353. X            }
  2354. X        }
  2355. X        if (move_ptr (src_wp, 1L, TRUE, FALSE, TRUE) == FALSE)
  2356. X        {
  2357. X            wind_on_dot_all();
  2358. X            writ_echo (MSG_ok);
  2359. X            return (TRUE);    /* hit the end of the source buffer */
  2360. X        }
  2361. X    }
  2362. X}
  2363. X
  2364. Xvoid wind_on_dot_all ()
  2365. X{
  2366. X    WINDOW  *wp;
  2367. X
  2368. X    wp = curwp;
  2369. X    do
  2370. X    {
  2371. X        wind_on_dot (curwp);
  2372. X        nextwind();
  2373. X    }    while (wp != curwp);
  2374. X}
  2375. END_OF_FILE
  2376.   if test 28521 -ne `wc -c <'random.c'`; then
  2377.     echo shar: \"'random.c'\" unpacked with wrong size!
  2378.   fi
  2379.   # end of 'random.c'
  2380. fi
  2381. if test -f 'spawn.c' -a "${1}" != "-c" ; then 
  2382.   echo shar: Will not clobber existing file \"'spawn.c'\"
  2383. else
  2384.   echo shar: Extracting \"'spawn.c'\" \(1390 characters\)
  2385.   sed "s/^X//" >'spawn.c' <<'END_OF_FILE'
  2386. X/*
  2387. X*    MS-DOS spawn command.com
  2388. X*/
  2389. X#include        "def.h"
  2390. X
  2391. Xextern    char    MSG_shell[];
  2392. Xextern    char    MSG_def_shell[];
  2393. Xextern    char    MSG_pmpt[];
  2394. Xextern    char    MSG_pt[];
  2395. Xextern    char    MSG_pme[];
  2396. Xextern    char    MSG_null[];
  2397. X
  2398. X/* #include     <dos.h> */
  2399. X#if MSDOS
  2400. X#include        "process.h"
  2401. X#endif
  2402. Xchar   *cspec = NULL;           /* Command string.      */
  2403. Xchar   *pspec = NULL;
  2404. X
  2405. X/*
  2406. X* Create a subjob with a copy
  2407. X* of the command intrepreter in it. When the
  2408. X* command interpreter exits, mark the screen as
  2409. X* garbage so that you do a full repaint.
  2410. X*/
  2411. Xbool spawncli (f, n, k)
  2412. X{
  2413. X#if MSDOS
  2414. X
  2415. X    char   *getenv ();
  2416. X    char    old_prompt[NCOL];
  2417. X    char    prompt_line[NCOL];
  2418. X
  2419. X    ttcolor (CTEXT);            /* Normal color.        */
  2420. X    ttmove (nrow - 1, 0);       /* Last line.           */
  2421. X    ttflush ();
  2422. X    ttcooked ();
  2423. X#ifndef IBM
  2424. X    strcpy (prompt_line, MSG_pmpt);
  2425. X    pspec = getenv (MSG_pt);
  2426. X    strcpy (old_prompt, pspec);
  2427. X    strcat (prompt_line, pspec);
  2428. X    if (strlen (prompt_line - strlen (MSG_pme)) >= 64)
  2429. X    /* VERY rude, but setenv not found */
  2430. X    {
  2431. X        if (putenv (MSG_pmpt) == -1)
  2432. X            exit (1);
  2433. X    }
  2434. X    else
  2435. X        if (putenv (prompt_line) == -1)
  2436. X            exit (1);
  2437. X
  2438. X#endif
  2439. X    if (!cspec && !(cspec = getenv (MSG_shell)))/* jam */
  2440. X        cspec = MSG_def_shell;
  2441. X    spawnl (P_WAIT, cspec, MSG_null, NULL);
  2442. X    putenv (MSG_pme);
  2443. X    if (putenv (old_prompt) == -1)
  2444. X        exit (1);
  2445. X    ttraw ();
  2446. X    sgarbf = TRUE;
  2447. X#endif
  2448. X    return (TRUE);
  2449. X}
  2450. X
  2451. END_OF_FILE
  2452.   if test 1390 -ne `wc -c <'spawn.c'`; then
  2453.     echo shar: \"'spawn.c'\" unpacked with wrong size!
  2454.   fi
  2455.   # end of 'spawn.c'
  2456. fi
  2457. echo shar: End of archive 4 \(of 9\).
  2458. cp /dev/null ark4isdone
  2459. MISSING=""
  2460. for I in 1 2 3 4 5 6 7 8 9 ; do
  2461.     if test ! -f ark${I}isdone ; then
  2462.     MISSING="${MISSING} ${I}"
  2463.     fi
  2464. done
  2465. if test "${MISSING}" = "" ; then
  2466.     echo You have unpacked all 9 archives.
  2467.     rm -f ark[1-9]isdone ark[1-9][0-9]isdone
  2468. else
  2469.     echo You still must unpack the following archives:
  2470.     echo "        " ${MISSING}
  2471. fi
  2472. exit 0
  2473. exit 0 # Just in case...
  2474.