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

  1. Newsgroups: comp.sources.misc
  2. From: pvr@wang.com (Peter Reilley)
  3. Subject:  v26i039:  beav - Binary file editor and viewer, v1.32, Part03/09
  4. Message-ID: <1991Nov21.230151.1521@sparky.imd.sterling.com>
  5. X-Md4-Signature: 15e715dd1a5e532fcd42bad8b38f2c4d
  6. Date: Thu, 21 Nov 1991 23:01:51 GMT
  7. Approved: kent@sparky.imd.sterling.com
  8.  
  9. Submitted-by: pvr@wang.com (Peter Reilley)
  10. Posting-number: Volume 26, Issue 39
  11. Archive-name: beav/part03
  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:  display.c file.c makefile.286
  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 3 (of 9)."'
  25. if test -f 'display.c' -a "${1}" != "-c" ; then 
  26.   echo shar: Will not clobber existing file \"'display.c'\"
  27. else
  28.   echo shar: Extracting \"'display.c'\" \(30889 characters\)
  29.   sed "s/^X//" >'display.c' <<'END_OF_FILE'
  30. X/*
  31. X* The functions in this file handle redisplay. The
  32. X* redisplay system knows almost nothing about the editing
  33. X* process; the editing functions do, however, set some
  34. X* hints to eliminate a lot of the grinding. There is more
  35. X* that can be done; the "vtputc" interface is a real
  36. X* pig.  The MEMMAP
  37. X* changes things around for memory mapped video. With
  38. X* both off, the terminal is a VT52.
  39. X*/
  40. X
  41. X#include    <sys/types.h> 
  42. X#include    <sys/stat.h> 
  43. X#include    "def.h"
  44. X
  45. XD32 get_long ();
  46. XD16 get_int ();
  47. Xvoid writ_echo ();
  48. Xvoid uline ();
  49. Xvoid ucopy ();
  50. Xvoid modeline ();
  51. Xvoid bin_to_text ();
  52. Xuint fill_buf ();
  53. Xuint get_currow ();
  54. Xuint get_curcol ();
  55. X#if MSDOS
  56. Xvoid    mem_line ();
  57. X#endif
  58. X
  59. Xextern    char    MSG_prn_to[];
  60. Xextern    char    MSG_disp_r_n[];
  61. Xextern    char    MSG_11lX[];
  62. Xextern    char    MSG_11lo[];
  63. Xextern    char    MSG_11ld[];
  64. Xextern    char    MSG_03o[];
  65. Xextern    char    MSG_06o[];
  66. Xextern    char    MSG_011lo[];
  67. Xextern    char    MSG_03u[];
  68. Xextern    char    MSG_05u[];
  69. Xextern    char    MSG_010lu[];
  70. Xextern    char    MSG_02X[];
  71. Xextern    char    MSG_04X[];
  72. Xextern    char    MSG_08lX[];
  73. Xextern    char    MSG_prog_name[];
  74. Xextern    char    MSG_disp_b_lst[];
  75. Xextern    char    MSG_file[];
  76. Xextern    char    MSG_RO[];
  77. Xextern    char    MSG_WL[];
  78. Xextern    char    MSG_RW[];
  79. Xextern    char    MSG_AU[];
  80. Xextern    char    MSG_NOT_AU[];
  81. Xextern    char    MSG_curs_asc[];
  82. Xextern    char    MSG_curs_ebc[];
  83. Xextern    char    MSG_curs_hex[];
  84. Xextern    char    MSG_curs_bin[];
  85. Xextern    char    MSG_curs_dec[];
  86. Xextern    char    MSG_curs_oct[];
  87. Xextern    char    MSG_siz_8[];
  88. Xextern    char    MSG_siz_16[];
  89. Xextern    char    MSG_siz_32[];
  90. Xextern    char    MSG_siz_null[];
  91. Xextern    char    MSG_int_shift[];
  92. Xextern    char    MSG_mot_shift[];
  93. Xextern    char    MSG_print1[];
  94. Xextern    char    MSG_print2[];
  95. X#if RUNCHK
  96. Xextern    char    ERR_disp_1[];
  97. Xextern    char    ERR_disp_2[];
  98. Xextern    char    ERR_disp_3[];
  99. Xextern    char    ERR_disp_4[];
  100. Xextern    char    ERR_disp_5[];
  101. Xextern    char    ERR_disp_6[];
  102. X#endif
  103. X
  104. Xextern char ebcdic_table[];
  105. X
  106. Xextern  bool    mem_map;
  107. X
  108. X/*
  109. X* You can change these back to the types
  110. X* implied by the name if you get tight for space. If you
  111. X* make both of them "int" you get better code on the VAX.
  112. X* They do nothing if this is not Gosling redisplay, except
  113. X* for change the size of a structure that isn't used.
  114. X* A bit of a cheat.
  115. X*/
  116. X#define XCHAR   int
  117. X#define XSHORT  int
  118. X
  119. X/*
  120. X* A video structure always holds
  121. X* an array of characters whose length is equal to
  122. X* the longest line possible. Only some of this is
  123. X* used if "ncol" isn't the same as "NCOL".
  124. X*/
  125. Xtypedef struct vid
  126. X{
  127. X    short   v_hash;             /* Hash code, for compares.     */
  128. X    short   v_flag;             /* Flag word.                   */
  129. X    short   v_color;            /* Color of the line.           */
  130. X    XSHORT v_cost;      /* Cost of display.     */
  131. X    char    v_text[NCOL];       /* The actual characters.       */
  132. X}                   VIDEO;
  133. X
  134. X#define VFCHG   0x0001          /* Changed.                     */
  135. X#define VFHBAD  0x0002          /* Hash and cost are bad.       */
  136. X
  137. X/*
  138. X* SCORE structures hold the optimal
  139. X* trace trajectory, and the cost of redisplay, when
  140. X* the dynamic programming redisplay code is used.
  141. X* If no fancy redisplay, this isn't used. The trace index
  142. X* fields can be "char", and the score a "short", but
  143. X* this makes the code worse on the VAX.
  144. X*/
  145. Xtypedef struct
  146. X{
  147. X    XCHAR s_itrace;             /* "i" index for track back.    */
  148. X    XCHAR s_jtrace;             /* "j" index for trace back.    */
  149. X    XSHORT s_cost;              /* Display cost.                */
  150. X}               SCORE;
  151. X
  152. Xint     sgarbf = TRUE;          /* TRUE if screen is garbage.   */
  153. Xint     vtrow = 0;              /* Virtual cursor row.          */
  154. Xint     vtcol = 0;              /* Virtual cursor column.       */
  155. Xint     tthue = CNONE;          /* Current color.               */
  156. Xint     ttrow = HUGE;           /* Physical cursor row.         */
  157. Xint     ttcol = HUGE;           /* Physical cursor column.      */
  158. Xint     tttop = HUGE;           /* Top of scroll region.        */
  159. Xint     ttbot = HUGE;           /* Bottom of scroll region.     */
  160. Xchar    file_off_bad = FALSE;   /* Have file offsets been changed */
  161. X
  162. XVIDEO * vscreen[NROW];          /* Edge vector, virtual.        */
  163. XVIDEO * pscreen[NROW];          /* Edge vector, physical.       */
  164. XVIDEO video[2 * (NROW)];        /* Actual screen data.          */
  165. XVIDEO blanks;                   /* Blank line image.            */
  166. X
  167. X/*
  168. X* Initialize the data structures used
  169. X* by the display code. The edge vectors used
  170. X* to access the screens are set up. The operating
  171. X* system's terminal I/O channel is set up. Fill the
  172. X* "blanks" array with ASCII blanks. The rest is done
  173. X* at compile time. The original window is marked
  174. X* as needing full update, and the physical screen
  175. X* is marked as garbage, so all the right stuff happens
  176. X* on the first call to redisplay.
  177. X*/
  178. Xvoid vtinit ()
  179. X{
  180. X    register    VIDEO * vp;
  181. X    register int    i;
  182. X
  183. X    ttopen ();
  184. X    ttinit ();
  185. X    vp = &video[0];
  186. X    for (i = 0; i < NROW; ++i)
  187. X    {
  188. X        vscreen[i] = vp;
  189. X        ++vp;
  190. X        pscreen[i] = vp;
  191. X        ++vp;
  192. X    }
  193. X    blanks.v_color = CTEXT;
  194. X    for (i = 0; i < NCOL; ++i)
  195. X        blanks.v_text[i] = ' ';
  196. X}
  197. X
  198. X/*
  199. X* Tidy up the virtual display system
  200. X* in anticipation of a return back to the host
  201. X* operating system. Right now all we do is position
  202. X* the cursor to the last line, erase the line, and
  203. X* close the terminal channel.
  204. X*/
  205. Xvoid vttidy ()
  206. X{
  207. X    ttcolor (CTEXT);
  208. X    ttnowindow ();              /* No scroll window.    */
  209. X    ttmove (nrow - 1, 0);       /* Echo line.           */
  210. X    tteeol ();
  211. X    tttidy ();
  212. X    ttflush ();
  213. X    ttclose ();
  214. X}
  215. X
  216. X/*
  217. X* Move the virtual cursor to an origin
  218. X* 0 spot on the virtual display screen. I could
  219. X* store the column as a character pointer to the spot
  220. X* on the line, which would make "vtputc" a little bit
  221. X* more efficient. No checking for errors.
  222. X*/
  223. Xvoid vtmove (row, col)
  224. X{
  225. X    vtrow = row;
  226. X    vtcol = col;
  227. X}
  228. X
  229. X/*
  230. X* Write a character to the virtual display,
  231. X* dealing with long lines and the display of unprintable
  232. X* things like control characters. Also expand tabs every 8
  233. X* columns. This code only puts printing characters into
  234. X* the virtual display image. Special care must be taken when
  235. X* expanding tabs. On a screen whose width is not a multiple
  236. X* of 8, it is possible for the virtual cursor to hit the
  237. X* right margin before the next tab stop is reached. This
  238. X* makes the tab code loop if you are not careful.
  239. X* Three guesses how we found this.
  240. X*/
  241. Xvoid vtputc (c)
  242. Xregister char   c;
  243. X{
  244. X    register    VIDEO * vp;
  245. X
  246. X    vp = vscreen[vtrow];
  247. X    if (vtcol >= ncol)
  248. X        vp -> v_text[ncol - 1] = '$';
  249. X    else
  250. X        if (ISCTRL (c) != FALSE)
  251. X        {
  252. X            vtputc ('^');
  253. X            vtputc (c ^ 0x40);
  254. X        }
  255. X        else
  256. X        {
  257. X            vp -> v_text[vtcol] = c;
  258. X            vtcol++;
  259. X        }
  260. X
  261. X}
  262. X/*
  263. X* Write an entire screen line in the correct format.    pvr
  264. X*
  265. X* This code only puts printing characters into
  266. X* the virtual display image.
  267. X* Return TRUE if something was printed to the line.
  268. X*/
  269. X#define REGI  register
  270. Xbool vtputd (wp, row)
  271. XWINDOW * wp;
  272. Xint     row;                    /* line # to print to v screen */
  273. X
  274. X{
  275. X    REGI VIDEO * vp;
  276. X    REGI char   mode;
  277. X    REGI A32    row_offst;
  278. X    REGI uint   chrs_per_row,
  279. X        lin_offset,
  280. X        i,
  281. X        chrs_in_lin;
  282. X    LINE * cur_line;
  283. X    static char w_buf[128];      /* temp buffer for data */
  284. X
  285. X    vp = vscreen[vtrow];        /* point to VIDEO structure to print into */
  286. X    mode = R_TYPE(wp);          /* get type of format structure */
  287. X
  288. X    /* get number of bytes per row */
  289. X    chrs_per_row = R_BYTES(wp);
  290. X
  291. X    /* determine the offset from begining of the buffer for this line */
  292. X    row_offst = WIND_POS(wp) + (row * chrs_per_row);
  293. X
  294. X    /* search for and point to first character in buffer to be printed */
  295. X    cur_line = wp -> w_linep;   /* start with current first window line */
  296. X    while (TRUE)
  297. X    {                       /* find line with desired character */
  298. X        if (cur_line == wp -> w_bufp -> b_linep)
  299. X        {                   /* at end of buffer? */
  300. X            return (FALSE);
  301. X        }
  302. X        if (cur_line -> l_file_offset > row_offst)
  303. X        {
  304. X            /* if less than current line */
  305. X            cur_line = cur_line -> l_bp;/* step back */
  306. X        }
  307. X        else
  308. X            if ((cur_line -> l_file_offset + cur_line -> l_used) <= row_offst)
  309. X            {
  310. X                cur_line = cur_line -> l_fp;/* step ahead */
  311. X            }
  312. X            else
  313. X                break;
  314. X    }
  315. X
  316. X    lin_offset = row_offst - cur_line -> l_file_offset;/* offset into line */
  317. X
  318. X    /* get index into the current line to start reading the current row's data */
  319. X    /* copy line text into buffer */
  320. X    chrs_in_lin = fill_buf (wp, cur_line, lin_offset, w_buf, chrs_per_row);
  321. X
  322. X    /* limit line length to screen width, used in TEXT mode only */
  323. X    if (chrs_in_lin > NCOL)
  324. X        chrs_in_lin = NCOL;
  325. X
  326. X    /* Clear the line to spaces */
  327. X    for (i = 0; i < NCOL; i++)
  328. X    {
  329. X        vp -> v_text[i] = ' ';
  330. X    }
  331. X    switch (mode)
  332. X    {
  333. X    case TEXT:
  334. X        break;
  335. X    case ASCII:
  336. X    case EBCDIC:
  337. X    case BINARY:
  338. X    case HEX:
  339. X        /* print the row offset from the start of the file in HEX */
  340. X        sprintf (vp -> v_text, MSG_11lX, row_offst);/* to vid buf */
  341. X        break;
  342. X    case OCTAL:
  343. X        /* print the row offset from the start of the file */
  344. X        sprintf (vp -> v_text, MSG_11lo, row_offst);/* to vid buf */
  345. X        break;
  346. X    case DECIMAL:
  347. X        /* print the row offset from the start of the file */
  348. X        sprintf (vp -> v_text, MSG_11ld, row_offst);/* to vid buf */
  349. X        break;
  350. X#if RUNCHK
  351. X    default:
  352. X        writ_echo (ERR_disp_1);
  353. X        break;
  354. X#endif
  355. X    }
  356. X
  357. X    /* print the binary data to the text line */
  358. X    bin_to_text (w_buf, vp -> v_text, chrs_in_lin,
  359. X        wp -> w_fmt_ptr);
  360. X
  361. X    vtcol = NCOL;
  362. X    return (TRUE);
  363. X}
  364. X
  365. X/*
  366. X*   Print the contents of then binary data buffer bin_buf
  367. X*   into the proper mode of text into txt_buf.
  368. X*   Process 'len' bytes.
  369. X*
  370. X*   input:
  371. X*           bin_buf     pointer to buffer of binary data to process.
  372. X*           txt_buf     pointer to output buffer to print text result into.
  373. X*           len         length in bytes of data in bin_buf to process.
  374. X*           fmt_ptr     pointer to a ROW_FMT to use to format the data
  375. X*                       conversion and printing process.
  376. X*   output:
  377. X*           none.       
  378. X*/
  379. X
  380. Xvoid bin_to_text (bin_buf, txt_buf, len, fmt_ptr)
  381. X
  382. Xchar   *bin_buf,
  383. X*txt_buf;
  384. Xuint    len;
  385. XROW_FMT *fmt_ptr;
  386. X
  387. X{
  388. X    uchar   i,
  389. X        ch,
  390. X        k,
  391. X        j,
  392. X        mode,
  393. X        size,
  394. X        *posn;
  395. X    uint    temp_int;
  396. X    ulong   temp_long;
  397. X
  398. X    mode = fmt_ptr -> r_type;   /* get type of format structure */
  399. X    size = fmt_ptr -> r_size;   /* get size of format structure */
  400. X    posn = fmt_ptr -> r_positions;/* pointer to array of display positions */
  401. X
  402. X    switch (mode)
  403. X    {
  404. X    case TEXT:
  405. X    case ASCII:
  406. X        for (i = 0; i < len; i++)
  407. X        {
  408. X            ch = bin_buf[i];
  409. X            if ((ch >= ' ') && (ch < 0x7f))
  410. X                txt_buf[posn[0] + i] = ch;
  411. X            else
  412. X                txt_buf[posn[0] + i] = '.';
  413. X        }
  414. X        break;
  415. X
  416. X    case EBCDIC:
  417. X        for (i = 0; i < len; i++)
  418. X        {
  419. X            txt_buf[posn[0] + i] =
  420. X                0xff & ebcdic_table[0xff & bin_buf[i]];
  421. X        }
  422. X        break;
  423. X
  424. X    case OCTAL:
  425. X        switch (size)
  426. X        {
  427. X        case BYTES:     /* print octal bytes */
  428. X            for (i = 0; i < len; i++)
  429. X            {
  430. X                sprintf (&txt_buf[
  431. X                                    posn[i]], MSG_03o, 0xff & bin_buf[i]);
  432. X            }
  433. X            break;
  434. X
  435. X        case WORDS:     /* print octal words */
  436. X            k = 0;
  437. X            for (i = 0; i < len;
  438. X                i += 2)
  439. X            {
  440. X                temp_int = get_int (&bin_buf[i]);
  441. X                sprintf (&txt_buf[posn[k++]], MSG_06o, temp_int);
  442. X            }
  443. X            break;
  444. X
  445. X        case DWORDS:    /* print octal double words */
  446. X            k = 0;
  447. X            for (i = 0; i < len;
  448. X                i += 4)
  449. X            {
  450. X                temp_long = get_long (&bin_buf[i]);
  451. X                sprintf (&txt_buf[posn[k++]], MSG_011lo, temp_long);
  452. X            }
  453. X            break;
  454. X        }
  455. X        break;
  456. X
  457. X    case DECIMAL:
  458. X        switch (size)
  459. X        {
  460. X        case BYTES:     /* print decimal bytes */
  461. X            for (i = 0; i < len; i++)
  462. X            {
  463. X                sprintf (&txt_buf[
  464. X                                    posn[i]], MSG_03u, 0xff & bin_buf[i]);
  465. X            }
  466. X            break;
  467. X
  468. X        case WORDS:     /* print decimal words */
  469. X            k = 0;
  470. X            for (i = 0; i < len;
  471. X                i += 2)
  472. X            {
  473. X                temp_int = get_int (&bin_buf[i]);
  474. X                sprintf (&txt_buf[
  475. X                                    posn[k++]], MSG_05u, temp_int);
  476. X            }
  477. X            break;
  478. X
  479. X        case DWORDS:    /* print decimal double words */
  480. X            k = 0;
  481. X            for (i = 0; i < len; i += 4)
  482. X            {
  483. X                temp_long = get_long (&bin_buf[i]);
  484. X                sprintf (&txt_buf[
  485. X                                    posn[k++]], MSG_010lu, temp_long);
  486. X            }
  487. X            break;
  488. X        }
  489. X        break;
  490. X
  491. X    case HEX:
  492. X        switch (size)
  493. X        {
  494. X        case BYTES:     /* print hex bytes and ascii chars */
  495. X            for (i = 0; i < len; i++)
  496. X            {
  497. X                if ((bin_buf[i] >= ' ') && (bin_buf[i] < 0x7f))
  498. X                    txt_buf[posn[i + 16]] = 0xff & bin_buf[i];
  499. X                else
  500. X                    txt_buf[posn[i + 16]] = '.';
  501. X                sprintf (&txt_buf[posn[i]], MSG_02X, 0xff & bin_buf[i]);
  502. X            }
  503. X            break;
  504. X
  505. X        case WORDS:     /* print hex words */
  506. X            k = 0;
  507. X            for (i = 0; i < len; i += 2)
  508. X            {
  509. X                temp_int = get_int (&bin_buf[i]);
  510. X                sprintf (&txt_buf[
  511. X                                    posn[k++]], MSG_04X, temp_int);
  512. X            }
  513. X            break;
  514. X
  515. X        case DWORDS:    /* print hex double words */
  516. X            k = 0;
  517. X            for (i = 0; i < len; i += 4)
  518. X            {
  519. X                temp_long = get_long (&bin_buf[i]);
  520. X                sprintf (&txt_buf[
  521. X                                    posn[k++]], MSG_08lX, temp_long);
  522. X            }
  523. X            break;
  524. X        }
  525. X        break;
  526. X
  527. X    case BINARY:
  528. X        switch (size)
  529. X        {
  530. X        case BYTES:     /* print binary bits */
  531. X            for (i = 0; i < len; i++)
  532. X            {
  533. X                ch = bin_buf[i];/* get char to convert */
  534. X                for (k = 0; k < 8; k++)
  535. X                {
  536. X                    if (ch & 0x80)
  537. X                        txt_buf[posn[i] + k]
  538. X                            = '1';
  539. X                    else
  540. X                        txt_buf[posn[i] + k]
  541. X                            = '0';
  542. X                    ch = ch << 1;/* slide next bit into place */
  543. X                }
  544. X            }
  545. X            break;
  546. X
  547. X        case WORDS:
  548. X            j = 0;
  549. X            for (i = 0; i < len; i += 2)
  550. X            {
  551. X                temp_int = get_int (&bin_buf[i]);
  552. X
  553. X                for (k = 0; k < 16; k++)
  554. X                {
  555. X                    if (temp_int & 0x8000)
  556. X                        txt_buf[posn[j] + k]
  557. X                            = '1';
  558. X                    else
  559. X                        txt_buf[posn[j] + k]
  560. X                            = '0';
  561. X                    temp_int = temp_int << 1;
  562. X                    /* slide next bit into place */
  563. X                }
  564. X                j++;
  565. X            }
  566. X            break;
  567. X
  568. X        case DWORDS:
  569. X            j = 0;
  570. X            for (i = 0; i < len; i += 4)
  571. X            {
  572. X                temp_long = get_long (&bin_buf[i]);
  573. X                for (k = 0; k < 32; k++)
  574. X                {
  575. X                    if (temp_long & 0x80000000)
  576. X                        txt_buf[posn[j] + k]
  577. X                            = '1';
  578. X                    else
  579. X                        txt_buf[posn[j] + k]
  580. X                            = '0';
  581. X                    temp_long = temp_long << 1;
  582. X                    /* slide next bit into place */
  583. X                }
  584. X                j++;
  585. X            }
  586. X            break;
  587. X        }
  588. X        break;
  589. X#if RUNCHK
  590. X    default:
  591. X        writ_echo (ERR_disp_2);
  592. X        break;
  593. X#endif
  594. X    }
  595. X    len *= (fmt_ptr -> r_chr_per_u + 1);
  596. X    /* Clean up any garbage characters left by the sprintf's */
  597. X    for (i = 0; i < NCOL; i++)
  598. X    {
  599. X        if (txt_buf[i] == 0)
  600. X            txt_buf[i] = ' ';
  601. X    }
  602. X}
  603. X
  604. X/*
  605. X*   Get an int from the buffer.
  606. X*   Perform the Intel byte shuffle if necessary
  607. X*/
  608. X
  609. XD16 get_int (w_buf)
  610. Xuchar  *w_buf;
  611. X
  612. X{
  613. X    int     temp_int;
  614. X
  615. X    if (curwp -> w_intel_mode)
  616. X    {
  617. X        temp_int = 0xff & w_buf[1];
  618. X        temp_int <<= 8;
  619. X        temp_int |= 0xff & w_buf[0];
  620. X    }
  621. X    else
  622. X    {
  623. X        temp_int = 0xff & w_buf[0];
  624. X        temp_int <<= 8;
  625. X        temp_int |= 0xff & w_buf[1];
  626. X    }
  627. X    return (temp_int);
  628. X}
  629. X
  630. X/*
  631. X*   Get an long from the buffer.
  632. X*   Perform the Intel byte shuffle if necessary
  633. X*/
  634. X
  635. XD32 get_long (w_buf)
  636. Xuchar  *w_buf;
  637. X
  638. X{
  639. X    long    temp_long;
  640. X
  641. X    if (curwp -> w_intel_mode)
  642. X    {
  643. X        temp_long = 0xff & w_buf[3];
  644. X        temp_long <<= 8;
  645. X        temp_long |= 0xff & w_buf[2];
  646. X        temp_long <<= 8;
  647. X        temp_long |= 0xff & w_buf[1];
  648. X        temp_long <<= 8;
  649. X        temp_long |= 0xff & w_buf[0];
  650. X    }
  651. X    else
  652. X    {
  653. X        temp_long = 0xff & w_buf[0];
  654. X        temp_long <<= 8;
  655. X        temp_long |= 0xff & w_buf[1];
  656. X        temp_long <<= 8;
  657. X        temp_long |= 0xff & w_buf[2];
  658. X        temp_long <<= 8;
  659. X        temp_long |= 0xff & w_buf[3];
  660. X    }
  661. X    return (temp_long);
  662. X}
  663. X
  664. X
  665. X/*
  666. X*   Copy a length of bytes from the buffer LINEs into the designated
  667. X*   buffer.   If the current LINE does not have enough bytes then
  668. X*   advance to the next.   Return the actual number of bytes copied.
  669. X*   The number copied would be less than the number requested if
  670. X*   end of file is reached.
  671. X*/
  672. X
  673. Xuint    fill_buf (wp, lin, lin_off, w_buff, cnt)
  674. XWINDOW  *wp;
  675. XLINE    *lin;
  676. Xuint    lin_off,
  677. Xcnt;
  678. Xchar    *w_buff;
  679. X{
  680. X    REGI uint   src,
  681. X        dest,
  682. X        i;
  683. X
  684. X    src = lin_off;              /* initialize source line index */
  685. X    dest = 0;                   /* initialize destination buffer index */
  686. X
  687. X    while (TRUE)
  688. X    {
  689. X        while (src < lin -> l_used)
  690. X        {
  691. X            w_buff[dest++] = lin -> l_text[src++];/* copy byte */
  692. X
  693. X            if (dest == cnt)
  694. X            {               /* if done */
  695. X                return (cnt);   /* then leave */
  696. X            }
  697. X        }
  698. X        if (R_TYPE(wp) == TEXT)
  699. X            return (dest);   /* in text mode don't advance to next line */
  700. X
  701. X        lin = lin -> l_fp;      /* move to the next line */
  702. X        if (lin == wp -> w_bufp -> b_linep)
  703. X        {                   /* if past last line */
  704. X            {
  705. X            for (i = dest; i < cnt; ++i)
  706. X                w_buff[i] = 0;/* fill rest of buffer with zeros */
  707. X            return (dest);  /* return number of chars copied */
  708. X        }
  709. X    }
  710. X    src = 0;                /* start next LINE at first byte */
  711. X}
  712. Xreturn (0);
  713. X}
  714. X
  715. X/*
  716. X* Erase from the end of the
  717. X* software cursor to the end of the
  718. X* line on which the software cursor is
  719. X* located. The display routines will decide
  720. X* if a hardware erase to end of line command
  721. X* should be used to display this.
  722. X*/
  723. Xvoid vteeol ()
  724. X{
  725. X    register    VIDEO * vp;
  726. X
  727. X    vp = vscreen[vtrow];
  728. X    while (vtcol < ncol)
  729. X        vp -> v_text[vtcol++] = ' ';
  730. X}
  731. X
  732. X/*
  733. X* Make sure that the display is
  734. X* right. This is a three part process. First,
  735. X* scan through all of the windows looking for dirty
  736. X* ones. Check the framing, and refresh the screen.
  737. X* Second, make the
  738. X* virtual and physical screens the same.
  739. X*/
  740. Xvoid update ()
  741. X{
  742. X    register    WINDOW * wp;
  743. X    register    VIDEO * vp1;
  744. X    register    VIDEO * vp2;
  745. X    register uint    i;
  746. X    register int    hflag;
  747. X
  748. X    hflag = FALSE;              /* Not hard.            */
  749. X    wp = wheadp;
  750. X    while (wp != NULL)
  751. X    {
  752. X        /* is this window to be displayed in linked mode */
  753. X        if ((curbp -> b_flag & BFLINK) &&
  754. X            (wp -> w_bufp == curbp))
  755. X        {                   /* move dot to current window's dot position */
  756. X            wp -> w_dotp = curwp -> w_dotp;
  757. X            wp -> w_doto = curwp -> w_doto;
  758. X            move_ptr (wp, 0L, TRUE, TRUE, TRUE); /* insure dot is aligned */
  759. X            wind_on_dot (wp);   /* move window to new dot position */
  760. X        }
  761. X
  762. X        if (wp -> w_flag != 0)
  763. X
  764. X        {                   /* Need update.         */
  765. X            move_ptr (wp, 0L, FALSE, TRUE, TRUE); /* window on row boundary */
  766. X            move_ptr (wp, 0L, TRUE, TRUE, TRUE); /* dot on unit boundary */
  767. X            if ((wp -> w_flag & WFFORCE) == 0)
  768. X            {
  769. X                wind_on_dot (wp);/* position window on dot */
  770. X            }
  771. X            i = get_currow (wp); /* Redo this one line, mabey.    */
  772. X            if ((wp -> w_flag & ~WFMODE) == WFEDIT)
  773. X            {
  774. X                vscreen[i] -> v_color = CTEXT;
  775. X                vscreen[i] -> v_flag |= (VFCHG | VFHBAD);
  776. X                vtmove (i, 0);
  777. X                vtputd (wp, i - wp -> w_toprow);/* print line to the screen */
  778. X            }
  779. X            else
  780. X                if ((wp -> w_flag & ~WFMODE) == WFMOVE)
  781. X                {
  782. X                    while (i < wp -> w_toprow + wp -> w_ntrows)
  783. X                    {
  784. X                        /* paint entire window */
  785. X                        vscreen[i] -> v_color = CTEXT;
  786. X                        vscreen[i] -> v_flag |= (VFCHG | VFHBAD);
  787. X                        vtmove (i, 0);
  788. X                        /* print line to the screen */
  789. X                        if (!vtputd (wp, i - wp -> w_toprow))
  790. X                            vteeol ();
  791. X                        ++i;
  792. X                    }
  793. X                }
  794. X                else
  795. X                    if ((wp -> w_flag & (WFEDIT | WFHARD)) != 0)
  796. X                    {
  797. X                        hflag = TRUE;
  798. X                        i = wp -> w_toprow;
  799. X                        while (i < wp -> w_toprow + wp -> w_ntrows)
  800. X                        {
  801. X                            /* paint entire window */
  802. X                            vscreen[i] -> v_color = CTEXT;
  803. X                            vscreen[i] -> v_flag |= (VFCHG | VFHBAD);
  804. X                            vtmove (i, 0);
  805. X                            /* print line to the screen */
  806. X                            if (!vtputd (wp, i - wp -> w_toprow))
  807. X                                vteeol ();
  808. X                            ++i;
  809. X                        }
  810. X                    }
  811. X            if ((wp -> w_flag & WFMODE) ||
  812. X                (wp -> w_flag & WFMOVE) ||
  813. X                (wp -> w_flag & WFHARD))
  814. X                modeline (wp);
  815. X            wp -> w_flag = 0;
  816. X        }
  817. X        wp = wp -> w_wndp;
  818. X    }
  819. X    if (sgarbf != FALSE)
  820. X    {                       /* Screen is garbage.   */
  821. X        sgarbf = FALSE;         /* Erase-page clears    */
  822. X        epresf = FALSE;         /* the message area.    */
  823. X        tttop = HUGE;           /* Forget where you set */
  824. X        ttbot = HUGE;           /* scroll region.       */
  825. X        tthue = CNONE;          /* Color unknown.       */
  826. X        ttmove (0, 0);
  827. X        tteeop ();
  828. X#if MSDOS
  829. X        if (mem_map)
  830. X        {
  831. X            for (i = 0; i < nrow; ++i)
  832. X            {
  833. X                mem_line (i, vscreen[i]);
  834. X            }
  835. X        }
  836. X        else
  837. X        {
  838. X#endif
  839. X            for (i = 0; i < nrow; ++i)
  840. X            {
  841. X                uline (i, vscreen[i], &blanks);
  842. X                ucopy (vscreen[i], pscreen[i]);
  843. X            }
  844. X#if MSDOS
  845. X        }
  846. X#endif
  847. X        ttmove (get_currow (curwp), get_curcol (curwp));
  848. X        ttflush ();
  849. X        return;
  850. X    }
  851. X    for (i = 0; i < nrow; ++i)
  852. X    {                       /* Easy update.         */
  853. X        vp1 = vscreen[i];
  854. X        vp2 = pscreen[i];
  855. X        if ((vp1 -> v_flag & VFCHG) != 0)
  856. X        {
  857. X#if MSDOS
  858. X            if (mem_map)
  859. X                mem_line (i, vp1);
  860. X            else
  861. X#endif
  862. X                {
  863. X                    uline (i, vp1, vp2);
  864. X                    ucopy (vp1, vp2);
  865. X                }
  866. X        }
  867. X    }
  868. X    ttmove (get_currow (curwp), get_curcol (curwp));
  869. X    ttflush ();
  870. X}
  871. X/*
  872. X*   Get the window relative row in which the cursor will
  873. X*   appear. pvr
  874. X*/
  875. Xuint    get_currow (wp)
  876. XWINDOW * wp;
  877. X{
  878. X    A32    row;
  879. X    /* number of bytes from start of window */
  880. X    row = DOT_POS(wp) - WIND_POS(wp);
  881. X    /* number of rows down in window */
  882. X    row /= R_BYTES(wp);
  883. X    row += wp -> w_toprow;
  884. X#if RUNCHK
  885. X    if (row < wp -> w_toprow)
  886. X        printf (ERR_disp_3);
  887. X    if (row > (wp -> w_ntrows + wp -> w_toprow))
  888. X        printf (ERR_disp_4);
  889. X#endif
  890. X    return (row & 0xffff);
  891. X}
  892. X
  893. X/*
  894. X*   Get the window relative column in which the cursor will
  895. X*   appear. pvr
  896. X*/
  897. Xuint    get_curcol (wp)
  898. XWINDOW * wp;
  899. X{
  900. X    long    offset,
  901. X    index;
  902. X    uint    b_per_u, pos;
  903. X
  904. X    b_per_u = R_B_PER_U(wp);
  905. X    /* dot offset from start of buffer */
  906. X    offset = DOT_POS(wp);
  907. X    offset -= wp -> w_disp_shift;
  908. X    offset &= ~(b_per_u - 1);
  909. X    /* calculate mod of the current file position */
  910. X    index = offset & (R_BYTES(wp) - 1);
  911. X    index /= b_per_u;
  912. X    /* limit to window width */
  913. X    if (index >= NCOL)
  914. X        index = NCOL;
  915. X    pos = wp -> w_fmt_ptr -> r_positions[index] + wp -> w_unit_offset;
  916. X    return (pos);
  917. X}
  918. X#if MSDOS
  919. Xvoid    mem_line (row, vvp)
  920. Xint     row;
  921. XVIDEO * vvp;
  922. X{
  923. X    vvp -> v_flag &= ~VFCHG;    /* Changes done.        */
  924. X    ttcolor (vvp -> v_color);
  925. X    putline (row + 1, 1, ncol, &vvp -> v_text[0]);
  926. X}
  927. X#endif
  928. X/*
  929. X* Update a saved copy of a line,
  930. X* kept in a VIDEO structure. The "vvp" is
  931. X* the one in the "vscreen". The "pvp" is the one
  932. X* in the "pscreen". This is called to make the
  933. X* virtual and physical screens the same when
  934. X* display has done an update.
  935. X*/
  936. Xvoid ucopy (vvp, pvp)
  937. Xregister    VIDEO * vvp;
  938. Xregister    VIDEO * pvp;
  939. X{
  940. X    register int    i;
  941. X
  942. X    vvp -> v_flag &= ~VFCHG;    /* Changes done.        */
  943. X    pvp -> v_flag = vvp -> v_flag;/* Update model.        */
  944. X    pvp -> v_hash = vvp -> v_hash;
  945. X    pvp -> v_cost = vvp -> v_cost;
  946. X    pvp -> v_color = vvp -> v_color;
  947. X    for (i = 0; i < ncol; ++i)
  948. X        pvp -> v_text[i] = vvp -> v_text[i];
  949. X}
  950. X
  951. X/*
  952. X* Update a single line. This routine only
  953. X* uses basic functionality (no insert and delete character,
  954. X* but erase to end of line). The "vvp" points at the VIDEO
  955. X* structure for the line on the virtual screen, and the "pvp"
  956. X* is the same for the physical screen. Avoid erase to end of
  957. X* line when updating CMODE color lines, because of the way that
  958. X* reverse video works on most terminals.
  959. X*/
  960. Xvoid uline (row, vvp, pvp)
  961. XVIDEO * vvp;
  962. XVIDEO * pvp;
  963. X{
  964. X    register char  *cp1;
  965. X    register char  *cp2;
  966. X    register char  *cp3;
  967. X    register char  *cp4;
  968. X    register char  *cp5;
  969. X    register int    nbflag;
  970. X
  971. X    if (vvp -> v_color != pvp -> v_color)
  972. X    {                       /* Wrong color, do a    */
  973. X        ttmove (row, 0);        /* full redraw.         */
  974. X        ttcolor (vvp -> v_color);
  975. X        cp1 = &vvp -> v_text[0];
  976. X        cp2 = &vvp -> v_text[ncol];
  977. X        while (cp1 != cp2)
  978. X        {
  979. X            ttputc (*cp1++);
  980. X            ++ttcol;
  981. X        }
  982. X        return;
  983. X    }
  984. X    cp1 = &vvp -> v_text[0];    /* Compute left match.  */
  985. X    cp2 = &pvp -> v_text[0];
  986. X    while (cp1 != &vvp -> v_text[ncol] && cp1[0] == cp2[0])
  987. X    {
  988. X        ++cp1;
  989. X        ++cp2;
  990. X    }
  991. X    if (cp1 == &vvp -> v_text[ncol])/* All equal.           */
  992. X        return;
  993. X    nbflag = FALSE;
  994. X    cp3 = &vvp -> v_text[ncol]; /* Compute right match. */
  995. X    cp4 = &pvp -> v_text[ncol];
  996. X    while (cp3[-1] == cp4[-1])
  997. X    {
  998. X        --cp3;
  999. X        --cp4;
  1000. X        if (cp3[0] != ' ')      /* Note non-blanks in   */
  1001. X            nbflag = TRUE;      /* the right match.     */
  1002. X    }
  1003. X    cp5 = cp3;                  /* Is erase good?       */
  1004. X    if (nbflag == FALSE && vvp -> v_color == CTEXT)
  1005. X    {
  1006. X        while (cp5 != cp1 && cp5[-1] == ' ')
  1007. X            --cp5;
  1008. X        /* Alcyon hack */
  1009. X        if ((int) (cp3 - cp5) <= tceeol)
  1010. X            cp5 = cp3;
  1011. X    }
  1012. X    /* Alcyon hack */
  1013. X    ttmove (row, (int) (cp1 - &vvp -> v_text[0]));
  1014. X    ttcolor (vvp -> v_color);
  1015. X    while (cp1 != cp5)
  1016. X    {
  1017. X        ttputc (*cp1++);
  1018. X        ++ttcol;
  1019. X    }
  1020. X    if (cp5 != cp3)             /* Do erase.            */
  1021. X        tteeol ();
  1022. X}
  1023. X
  1024. X/*
  1025. X* Redisplay the mode line for
  1026. X* the window pointed to by the "wp".
  1027. X* This is the only routine that has any idea
  1028. X* of how the modeline is formatted. You can
  1029. X* change the modeline format by hacking at
  1030. X* this routine. Called by "update" any time
  1031. X* there is a dirty window.
  1032. X*/
  1033. X
  1034. Xvoid modeline (wp)
  1035. Xregister    WINDOW * wp;
  1036. X{
  1037. X    register char  *cp,
  1038. X    mode,
  1039. X    size,
  1040. X    u_posn,
  1041. X    *s;
  1042. X    register char   c;
  1043. X    register int    n;
  1044. X    register    BUFFER * bp;
  1045. X    register    A32 posn;
  1046. X
  1047. X    static char posn_buf[30] =
  1048. X    {
  1049. X        0
  1050. X    };                          /* krw */
  1051. X
  1052. X    mode = wp -> w_fmt_ptr -> r_type;/* get type of format structure */
  1053. X    size = wp -> w_fmt_ptr -> r_size;/* get size of format structure */
  1054. X
  1055. X    n = wp -> w_toprow + wp -> w_ntrows;/* Location.            */
  1056. X    vscreen[n] -> v_color = CMODE;/* Mode line color.     */
  1057. X    vscreen[n] -> v_flag |= (VFCHG | VFHBAD);/* Recompute, display.  */
  1058. X    vtmove (n, 0);              /* Seek to right line.  */
  1059. X    bp = wp -> w_bufp;
  1060. X
  1061. X    cp = MSG_prog_name;               /* Program name.  pvr    */
  1062. X    n = 5;
  1063. X    while ((c = *cp++) != 0)
  1064. X    {
  1065. X        vtputc (c);
  1066. X        ++n;
  1067. X    }
  1068. X
  1069. X    if ((bp -> b_flag & BFBAD) != 0)/* "?" if trashed.      */
  1070. X        vtputc ('?');
  1071. X    else
  1072. X        vtputc (' ');
  1073. X
  1074. X    if ((bp -> b_flag & BFCHG) != 0)/* "*" if changed.      */
  1075. X        vtputc ('*');
  1076. X    else
  1077. X        vtputc (' ');
  1078. X
  1079. X    if (insert_mode)            /* "I" if insert mode  */
  1080. X        vtputc ('I');
  1081. X    else
  1082. X        vtputc ('O');
  1083. X
  1084. X    if (bp == blistp)
  1085. X    {                       /* special list */
  1086. X        cp = MSG_disp_b_lst;
  1087. X        while ((c = *cp++) != 0)
  1088. X        {
  1089. X            vtputc (c);
  1090. X            ++n;
  1091. X        }
  1092. X        goto pad;
  1093. X    }
  1094. X
  1095. X    /* Buffer name */
  1096. X    vtputc (' ');
  1097. X    ++n;
  1098. X    cp = &bp -> b_bname[0];
  1099. X    while ((c = *cp++) != 0)
  1100. X    {
  1101. X        vtputc (c);
  1102. X        ++n;
  1103. X    }
  1104. X    while ((int) (cp - &bp -> b_bname[0]) < NBUFN)
  1105. X    {
  1106. X        vtputc (' ');
  1107. X        n++;
  1108. X        cp++;
  1109. X    }
  1110. X
  1111. X    /* File name.           */
  1112. X    vtputc (' ');
  1113. X    ++n;
  1114. X    cp = MSG_file;
  1115. X    while ((c = *cp++) != 0)
  1116. X    {
  1117. X        vtputc (c);
  1118. X        ++n;
  1119. X    }
  1120. X    cp = &bp -> b_fname[0];
  1121. X    while ((c = *cp++) != 0)
  1122. X    {
  1123. X        vtputc (c);
  1124. X        ++n;
  1125. X    }
  1126. X    cp--;
  1127. X    while ((int) (cp - &bp -> b_fname[0]) < NFILE)
  1128. X    {
  1129. X        vtputc (' ');
  1130. X        n++;
  1131. X        cp++;
  1132. X    }
  1133. X
  1134. X    if (bp -> b_flag & BFVIEW)
  1135. X        s = MSG_RO;
  1136. X    else if (bp -> b_flag & BFSLOCK)
  1137. X        s = MSG_WL;
  1138. X    else
  1139. X        s = MSG_RW;
  1140. X
  1141. X    while (*s)
  1142. X    {                       /* krw */
  1143. X        vtputc (*s++);
  1144. X        ++n;
  1145. X    }
  1146. X
  1147. X    if (auto_update && !(bp -> b_flag & BFVIEW) && bp -> b_bname[0])/* jam */
  1148. X        s = MSG_AU;
  1149. X    else
  1150. X        s = MSG_NOT_AU;
  1151. X    for (; *s && n < NCOL;)
  1152. X    {
  1153. X        vtputc (*s++);
  1154. X        ++n;
  1155. X    }
  1156. X
  1157. X    /* Insert current dot position into mode line. */
  1158. X    posn = DOT_POS(wp);
  1159. X    u_posn = R_CHR_PER_U(wp) - wp -> w_unit_offset - 1;
  1160. X    if (u_posn < 0)
  1161. X        u_posn = 0;
  1162. X    switch (mode)
  1163. X    {
  1164. X    case TEXT:
  1165. X    case ASCII:
  1166. X        sprintf (posn_buf, MSG_curs_asc, posn);
  1167. X        break;
  1168. X    case EBCDIC:
  1169. X        sprintf (posn_buf, MSG_curs_ebc, posn);
  1170. X        break;
  1171. X    case HEX:
  1172. X        sprintf (posn_buf, MSG_curs_hex, posn, u_posn);
  1173. X        break;
  1174. X    case BINARY:
  1175. X        sprintf (posn_buf, MSG_curs_bin, posn, u_posn);
  1176. X        break;
  1177. X    case DECIMAL:
  1178. X        sprintf (posn_buf, MSG_curs_dec, posn, u_posn);
  1179. X        break;
  1180. X    case OCTAL:
  1181. X        sprintf (posn_buf, MSG_curs_oct, posn, u_posn);
  1182. X        break;
  1183. X#if RUNCHK
  1184. X    default:
  1185. X        writ_echo (ERR_disp_5);
  1186. X        break;
  1187. X#endif
  1188. X    }
  1189. X
  1190. X    cp = posn_buf;
  1191. X    while ((c = *cp++) != 0)
  1192. X    {
  1193. X        vtputc (c);
  1194. X        ++n;
  1195. X    }
  1196. X
  1197. X
  1198. X    if ((mode == HEX) ||
  1199. X        (mode == DECIMAL) ||
  1200. X        (mode == OCTAL))
  1201. X    {
  1202. X        switch (size)
  1203. X        {
  1204. X        case BYTES:
  1205. X            sprintf (posn_buf, MSG_siz_8);
  1206. X            break;
  1207. X        case WORDS:
  1208. X            sprintf (posn_buf, MSG_siz_16);
  1209. X            break;
  1210. X        case DWORDS:
  1211. X            sprintf (posn_buf, MSG_siz_32);
  1212. X            break;
  1213. X#if RUNCHK
  1214. X        default:
  1215. X            writ_echo (ERR_disp_6);
  1216. X            break;
  1217. X#endif
  1218. X        }
  1219. X    }
  1220. X    else
  1221. X        sprintf (posn_buf, MSG_siz_null);
  1222. X
  1223. X    cp = posn_buf;
  1224. X    while ((c = *cp++) != 0)
  1225. X    {
  1226. X        vtputc (c);
  1227. X        ++n;
  1228. X    }
  1229. X
  1230. X    if (wp -> w_intel_mode)
  1231. X        sprintf (posn_buf, MSG_int_shift, wp -> w_disp_shift);
  1232. X    else
  1233. X        sprintf (posn_buf, MSG_mot_shift, wp -> w_disp_shift);
  1234. X    cp = posn_buf;
  1235. X    while ((c = *cp++) != 0)
  1236. X    {
  1237. X        vtputc (c);
  1238. X        ++n;
  1239. X    }
  1240. X
  1241. X
  1242. X    /* pad out */
  1243. Xpad:
  1244. X    while (n < ncol)
  1245. X    {
  1246. X        vtputc (' ');
  1247. X        ++n;
  1248. X    }
  1249. X}
  1250. X
  1251. X/*
  1252. X* write text to the echo line 
  1253. X*/
  1254. Xvoid    writ_echo (buf)
  1255. Xchar    *buf;
  1256. X{
  1257. X    int     i;
  1258. X    char    *vpp;
  1259. X    bool    fill_spac;
  1260. X
  1261. X    fill_spac = FALSE;
  1262. X    vpp = vscreen[nrow - 1] -> v_text;
  1263. X    vscreen[nrow - 1] -> v_color = CTEXT;
  1264. X    vscreen[nrow - 1] -> v_flag |= VFCHG;
  1265. X    epresf = TRUE;
  1266. X
  1267. X    for (i = 0; i < NCOL; i++)
  1268. X    {
  1269. X        if (buf[i] == 0)
  1270. X            fill_spac = TRUE;
  1271. X        if (fill_spac)
  1272. X            vpp[i] = ' ';
  1273. X        else 
  1274. X            vpp[i] = buf[i];
  1275. X    }
  1276. X#if MSDOS
  1277. X    if (mem_map)
  1278. X    {
  1279. X        mem_line (nrow - 1, vscreen[nrow - 1]);
  1280. X    }
  1281. X    else
  1282. X#endif
  1283. X        {
  1284. X            uline (nrow - 1, vscreen[nrow - 1], pscreen[nrow - 1]);
  1285. X            uline (nrow - 1, vscreen[nrow - 1], &blanks);
  1286. X            ucopy (vscreen[nrow - 1], pscreen[nrow - 1]);
  1287. X            ttflush ();
  1288. X        }
  1289. X}
  1290. X
  1291. X/*
  1292. X* Print the current buffer from mark to dot using the 
  1293. X* current window's display format.
  1294. X* Prompt for file name or io device to print to.
  1295. X*/
  1296. X
  1297. Xbool    print ()
  1298. X{
  1299. X    LINE    *dot_l_sav, *mark_l_sav, *wind_l_sav;
  1300. X    int     dot_off_sav, mark_off_sav, wind_off_sav, i;
  1301. X    char   s;
  1302. X    char    fname[NFILEN];
  1303. X    register int    nline;
  1304. X    char    buf[NFILEN], buf1[NFILEN];
  1305. X
  1306. X    /* save the original window state */
  1307. X    dot_l_sav = curwp -> w_dotp;
  1308. X    dot_off_sav = curwp -> w_doto;
  1309. X    mark_l_sav = curwp -> w_markp;
  1310. X    mark_off_sav = curwp -> w_marko;
  1311. X    wind_l_sav = curwp -> w_linep;
  1312. X    wind_off_sav = curwp -> w_loff;
  1313. X
  1314. X    /* if mark is not set then set it to location zero */
  1315. X    if (curwp -> w_markp == NULL)
  1316. X    {
  1317. X        curwp -> w_markp = curwp -> w_bufp -> b_linep -> l_fp;
  1318. X        curwp -> w_marko = 0;
  1319. X    }
  1320. X
  1321. X    nline = 0;
  1322. X    if ((s = ereply (MSG_prn_to, fname, NFILEN, NULL)) == ABORT)
  1323. X        return (s);
  1324. X    adjustcase (fname);
  1325. X    if ((s = ffwopen (fname, S_IREAD | S_IWRITE)) != FIOSUC)/* Open writes message. */
  1326. X        return (FALSE);
  1327. X
  1328. X    sprintf (buf, MSG_print1, fname);
  1329. X    writ_echo (buf);
  1330. X    /* make dot before mark */
  1331. X    if (DOT_POS(curwp) > MARK_POS(curwp))
  1332. X        swapmark ();    /* make mark first */
  1333. X
  1334. X    while (DOT_POS(curwp) <= MARK_POS(curwp))
  1335. X    {
  1336. X        /* check if we should quit */
  1337. X        if (ttkeyready ())
  1338. X        {
  1339. X            if (ttgetc () == CTL_G)   /* quit if abort was hit */
  1340. X                break;
  1341. X        }
  1342. X        nline++;
  1343. X        /* move window so that first line is on dot */
  1344. X        move_ptr (curwp, DOT_POS(curwp), FALSE, TRUE, FALSE);
  1345. X
  1346. X        if (vtputd (curwp, 0))   /* print line into video buffer */
  1347. X        {
  1348. X            for (i = NCOL; (vscreen[vtrow] -> v_text[i] < '!') ||
  1349. X                (vscreen[vtrow] -> v_text[i] > '~'); i--)
  1350. X                ;
  1351. X            i++;
  1352. X            if ((s = ffputline (vscreen[vtrow] -> v_text, i)) != FIOSUC)
  1353. X                break;
  1354. X            if ((s = ffputline (MSG_disp_r_n, 2)) != FIOSUC)
  1355. X                break;
  1356. X        }
  1357. X        else
  1358. X            break;
  1359. X        forwline (0, 1, KRANDOM);   /* advance to next line */
  1360. X    }
  1361. X    ffclose ();
  1362. X    sprintf (buf1, MSG_print2, R_POS_FMT(curwp));
  1363. X    sprintf (buf, buf1, (long) nline);
  1364. X    writ_echo (buf);
  1365. X
  1366. X    /* restore the original window state */
  1367. X    curwp -> w_dotp = dot_l_sav;
  1368. X    curwp -> w_doto = dot_off_sav;
  1369. X    curwp -> w_markp = mark_l_sav;
  1370. X    curwp -> w_marko = mark_off_sav;
  1371. X    curwp -> w_linep = wind_l_sav;
  1372. X    curwp -> w_loff = wind_off_sav;
  1373. X    curwp -> w_flag |= WFHARD;  /* insure that window is still presentable */
  1374. X    return (TRUE);
  1375. X}
  1376. END_OF_FILE
  1377.   if test 30889 -ne `wc -c <'display.c'`; then
  1378.     echo shar: \"'display.c'\" unpacked with wrong size!
  1379.   fi
  1380.   # end of 'display.c'
  1381. fi
  1382. if test -f 'file.c' -a "${1}" != "-c" ; then 
  1383.   echo shar: Will not clobber existing file \"'file.c'\"
  1384. else
  1385.   echo shar: Extracting \"'file.c'\" \(19205 characters\)
  1386.   sed "s/^X//" >'file.c' <<'END_OF_FILE'
  1387. X/*
  1388. X*  File commands.
  1389. X*/
  1390. X#include    <sys/types.h> 
  1391. X#include    <fcntl.h> 
  1392. X#include    <sys/stat.h> 
  1393. X#include        "def.h"
  1394. X
  1395. Xchar    load_file ();
  1396. Xchar    readin ();
  1397. Xvoid    makename ();
  1398. Xbool    writeout ();
  1399. Xbool    parse_f_name ();
  1400. XA32    ffseek ();
  1401. X
  1402. Xextern    char    MSG_rd_file[];
  1403. Xextern    char    MSG_trash[];
  1404. Xextern    char    MSG_ins_file[];
  1405. Xextern    char    MSG_not_fnd[];
  1406. Xextern    char    MSG_visit[];
  1407. Xextern    char    MSG_view[];
  1408. Xextern    char    MSG_buf_ex[];
  1409. Xextern    char    MSG_old_buf[];
  1410. Xextern    char    MSG_buf_nam[];
  1411. Xextern    char    MSG_cnt_cr[];
  1412. Xextern    char    MSG_reading[];
  1413. Xextern    char    MSG_read_lx[];
  1414. Xextern    char    MSG_no_mem_rd[];
  1415. Xextern    char    MSG_wr_file[];
  1416. Xextern    char    MSG_no_fn[];
  1417. Xextern    char    MSG_bk_err[];
  1418. Xextern    char    MSG_writing[];
  1419. Xextern    char    MSG_wrot_n[];
  1420. Xextern    char    MSG_fil_nam[];
  1421. Xextern    char    MSG_null[];
  1422. Xextern    char    ERR_parse_fn[];
  1423. Xextern    char    ERR_addr_neg[];
  1424. Xextern    char    ERR_f_size[];
  1425. X
  1426. Xstatic int  ughlyflag = FALSE;
  1427. X
  1428. X/*
  1429. X* Read a file into the current
  1430. X* buffer. This is really easy; all you do it
  1431. X* find the name of the file, and call the standard
  1432. X* "read a file into the current buffer" code.
  1433. X*/
  1434. Xchar    fileread ()
  1435. X{
  1436. X    register char   s;
  1437. X    char    fname[NFILEN];
  1438. X    A32     start, end;
  1439. X
  1440. X    if ((s = ereply (MSG_rd_file, fname, NFILEN, NULL)) != TRUE)
  1441. X        return (s);
  1442. X    if (parse_f_name (fname, &start, &end))
  1443. X    {
  1444. X        adjustcase (fname);
  1445. X        return (readin (fname, start, end));
  1446. X    }
  1447. X    return (TRUE);
  1448. X}
  1449. X
  1450. X
  1451. X/* insert file into current buffer - use readin, and yank
  1452. X*/
  1453. Xchar    fileinsert ()
  1454. X{
  1455. X    register char   s;
  1456. X    char    bname[NBUFN],
  1457. X    fname[NFILEN];
  1458. X    A32     start, end;
  1459. X    register char  *trash = MSG_trash;
  1460. X
  1461. X    strcpy (bname, curbp -> b_bname);/* save current buffer */
  1462. X    if ((s = _usebuffer (trash)) == 0)/* temp buffer */
  1463. X        return (s);
  1464. X    if ((s = ereply (MSG_ins_file, fname, NFILEN, NULL)) != TRUE)
  1465. X        return (s);
  1466. X    /* if file name and starting and ending addresses are good */
  1467. X    if (parse_f_name (fname, &start, &end))
  1468. X    {
  1469. X        adjustcase (fname);
  1470. X        if ((s = readin (fname, start, end)) == 0)
  1471. X        {
  1472. X            writ_echo (MSG_not_fnd);
  1473. X            _usebuffer (bname);
  1474. X            _killbuffer (trash);
  1475. X            return (s);
  1476. X        }
  1477. X        if ((s = _usebuffer (bname)) == 0)
  1478. X        {
  1479. X            _killbuffer (trash);
  1480. X            return (s);
  1481. X        }
  1482. X        if ((s = _yankbuffer (trash)) == 0)
  1483. X        {
  1484. X            _killbuffer (trash);
  1485. X            return (s);
  1486. X        }
  1487. X        writ_echo (okmsg);
  1488. X    }
  1489. X    else
  1490. X    {
  1491. X        _usebuffer (bname);
  1492. X        _killbuffer (trash);
  1493. X        return (FALSE);
  1494. X    }
  1495. X    if ((s = _killbuffer (trash)) == 0)
  1496. X        return (s);
  1497. X    wind_on_dot (curwp);
  1498. X    return (s);
  1499. X}
  1500. X
  1501. X
  1502. X/*
  1503. X* Select a file for editing.
  1504. X* Look around to see if you can find the
  1505. X* fine in another buffer; if you can find it
  1506. X* just switch to the buffer. If you cannot find
  1507. X* the file, create a new buffer, read in the
  1508. X* text, and switch to the new buffer.
  1509. X*
  1510. X* also various hacked versions for auto load, and 
  1511. X* file-vist with auto window split, and readonly (view-file) (jam)
  1512. X*/
  1513. Xchar    file_visit (f, n, k)
  1514. X{
  1515. X    char    fname[NFILEN];
  1516. X    char    s;
  1517. X    A32     start, end;
  1518. X    if ((s = ereply (MSG_visit, fname, NFILEN, NULL)) != TRUE)
  1519. X        return (s);
  1520. X    if (!parse_f_name (fname, &start, &end))
  1521. X        return (FALSE);
  1522. X
  1523. X    splitwind ();
  1524. X    return (load_file (fname, start, end));
  1525. X}
  1526. X
  1527. X
  1528. X/* like filevisit, only read only
  1529. X*/
  1530. Xchar    viewfile ()
  1531. X{
  1532. X    char    fname[NFILEN];
  1533. X    char    s;
  1534. X    A32     start, end;
  1535. X
  1536. X    if ((s = ereply (MSG_view, fname, NFILEN, NULL)) != TRUE)
  1537. X        return (s);
  1538. X    ughlyflag = TRUE;
  1539. X    if (!parse_f_name (fname, &start, &end))
  1540. X        return (FALSE);
  1541. X
  1542. X    s = load_file (fname, start, end);
  1543. X    if (s)
  1544. X        curbp -> b_flag |= BFVIEW;
  1545. X    ughlyflag = FALSE;
  1546. X    return (s);
  1547. X}
  1548. X
  1549. X
  1550. Xchar    filevisit ()
  1551. X{
  1552. X    char    fname[NFILEN];
  1553. X    char    s;
  1554. X    A32     start, end;
  1555. X
  1556. X    if ((s = ereply (MSG_visit, fname, NFILEN, NULL)) != TRUE)
  1557. X        return (s);
  1558. X    if (!parse_f_name (fname, &start, &end))
  1559. X        return (FALSE);
  1560. X
  1561. X    return (load_file (fname, start, end));
  1562. X}
  1563. X
  1564. X
  1565. Xchar    load_file (fname, start, end)       /* jam */
  1566. Xchar   *fname;
  1567. XA32     start, end;
  1568. X{
  1569. X    register    BUFFER * bp;
  1570. X    register    WINDOW * wp;
  1571. X    register    LINE * lp;
  1572. X    register int    i;
  1573. X    char        s;
  1574. X    char        bname[NBUFN];
  1575. X    extern int  initial_load;   /* jam */
  1576. X    static int  append = 0;
  1577. X
  1578. X    adjustcase (fname);
  1579. X    for (bp = bheadp; bp != NULL; bp = bp -> b_bufp)
  1580. X    {
  1581. X        if (strcmp (bp -> b_fname, fname) == 0)
  1582. X        {
  1583. X            if (ughlyflag == TRUE)
  1584. X            {
  1585. X                writ_echo (MSG_buf_ex);
  1586. X                return (FALSE);
  1587. X            }
  1588. X            if (--curbp -> b_nwnd == 0)
  1589. X            {
  1590. X                curbp -> b_type = BTFILE;
  1591. X                curbp -> b_dotp = curwp -> w_dotp;
  1592. X                curbp -> b_doto = curwp -> w_doto;
  1593. X                curbp -> b_unit_offset = curwp -> w_unit_offset;
  1594. X                curbp -> b_markp = curwp -> w_markp;
  1595. X                curbp -> b_marko = curwp -> w_marko;
  1596. X            }
  1597. X            curbp = bp;
  1598. X            curwp -> w_bufp = bp;
  1599. X            if (bp -> b_nwnd++ == 0)
  1600. X            {
  1601. X                curwp -> w_dotp = bp -> b_dotp;
  1602. X                curwp -> w_doto = bp -> b_doto;
  1603. X                curwp -> w_unit_offset = bp -> b_unit_offset;
  1604. X                curwp -> w_markp = bp -> b_markp;
  1605. X                curwp -> w_marko = bp -> b_marko;
  1606. X            }
  1607. X            else
  1608. X            {
  1609. X                wp = wheadp;
  1610. X                while (wp != NULL)
  1611. X                {
  1612. X                    if (wp != curwp && wp -> w_bufp == bp)
  1613. X                    {
  1614. X                        curwp -> w_dotp = wp -> w_dotp;
  1615. X                        curwp -> w_doto = wp -> w_doto;
  1616. X                        curwp -> w_unit_offset = wp -> w_unit_offset;
  1617. X                        curwp -> w_markp = wp -> w_markp;
  1618. X                        curwp -> w_marko = wp -> w_marko;
  1619. X                        break;
  1620. X                    }
  1621. X                    wp = wp -> w_wndp;
  1622. X                }
  1623. X            }
  1624. X            lp = curwp -> w_dotp;
  1625. X            i = curwp -> w_ntrows / 2;
  1626. X            while (i-- && lback (lp) != curbp -> b_linep)
  1627. X                lp = lback (lp);
  1628. X            curwp -> w_linep = lp;
  1629. X            curwp -> w_flag |= WFMODE | WFHARD;
  1630. X            if (kbdmop == NULL)
  1631. X            {
  1632. X                writ_echo (MSG_old_buf);
  1633. X            }
  1634. X            return (TRUE);
  1635. X        }
  1636. X    }
  1637. X
  1638. X    makename (bname, fname);    /* New buffer name.     */
  1639. X    while ((bp = bfind (bname, FALSE)) != NULL)
  1640. X    {
  1641. X        if (initial_load)       /* patch old name */
  1642. X        {
  1643. X            funky_name (bname, append++);
  1644. X            bp = NULL;
  1645. X            break;
  1646. X        }
  1647. X        s = ereply (MSG_buf_nam, bname, NBUFN, NULL);
  1648. X        if (s == ABORT)         /* ^G to just quit      */
  1649. X            return (s);
  1650. X        if (strcmp (bp -> b_bname, bname) == 0 || s == FALSE)
  1651. X        {
  1652. X            /* CR to clobber it     */
  1653. X            makename (bname, fname);
  1654. X            break;
  1655. X        }
  1656. X    }
  1657. X    if (bp == NULL && (bp = bfind (bname, TRUE)) == NULL)
  1658. X    {
  1659. X        err_echo (MSG_cnt_cr);
  1660. X        return (FALSE);
  1661. X    }
  1662. X    if (--curbp -> b_nwnd == 0)
  1663. X    {
  1664. X        /* Undisplay.           */
  1665. X        curbp -> b_type = BTFILE;
  1666. X        curbp -> b_dotp = curwp -> w_dotp;
  1667. X        curbp -> b_doto = curwp -> w_doto;
  1668. X        curbp -> b_unit_offset = curwp -> w_unit_offset;
  1669. X        curbp -> b_markp = curwp -> w_markp;
  1670. X        curbp -> b_marko = curwp -> w_marko;
  1671. X    }
  1672. X    curbp = bp;                 /* Switch to it.        */
  1673. X    curwp -> w_bufp = bp;
  1674. X    curbp -> b_nwnd++;
  1675. X    return (readin (fname, start, end));    /* Read it in.          */
  1676. X}
  1677. X
  1678. X
  1679. X/*
  1680. X* Read the file "fname" into the current buffer.
  1681. X* Make all of the text in the buffer go away, after checking
  1682. X* for unsaved changes. This is called by the "read" command, the
  1683. X* "visit" command, and the mainline (for "beav file"). If the
  1684. X* BACKUP conditional is set, then this routine also does the read
  1685. X* end of backup processing. The BFBAK flag, if set in a buffer,
  1686. X* says that a backup should be taken. It is set when a file is
  1687. X* read in, but not on a new file (you don't need to make a backup
  1688. X* copy of nothing). Return a standard status. Print a summary
  1689. X* (lines read, error message) out as well.
  1690. X*/
  1691. Xchar    readin (fname, start, end)
  1692. Xchar    fname[];
  1693. XA32     start, end;
  1694. X{
  1695. X    register    LINE * lp1;
  1696. X    register    LINE * lp2;
  1697. X    register    WINDOW * wp;
  1698. X    register    BUFFER * bp;
  1699. X    register    char   s, m;
  1700. X    long        byte_cnt;
  1701. X    LPOS        req_chars;
  1702. X    char        buf[NCOL], buf1[NCOL];
  1703. X    A32         temp;
  1704. X
  1705. X    m = TRUE;
  1706. X    byte_cnt = 0;
  1707. X    bp = curbp;                 /* Cheap.               */
  1708. X    if ((s = bclear (bp)) != TRUE)/* Might be old.        */
  1709. X        return (s);
  1710. X#if     BACKUP
  1711. X    bp -> b_flag &= ~(BFCHG | BFBAK);/* No change, backup.   */
  1712. X#else
  1713. X    bp -> b_flag &= ~BFCHG;     /* No change.           */
  1714. X#endif
  1715. X    if ((start == 0L) && (end == MAXPOS))
  1716. X        strcpy (bp -> b_fname, fname);
  1717. X    else
  1718. X        strcpy (bp -> b_fname, MSG_null);
  1719. X    bp -> b_file_size = 0;
  1720. X    bp -> b_type = BTFILE;
  1721. X    if ((s = ffropen (fname)) == FIOERR || s == FIOFNF)/* jam */
  1722. X        goto out;
  1723. X    bp -> b_file_size = file_len ();  /* get the file lenth */
  1724. X    sprintf (buf, MSG_reading, fname);/* jam */
  1725. X    writ_echo (buf);
  1726. X    temp = ffseek (start);
  1727. X    if (temp != start)
  1728. X    {
  1729. X        sprintf (buf1, ERR_f_size, R_POS_FMT(curwp));
  1730. X        sprintf (buf, buf1, temp);
  1731. X        writ_echo (buf);
  1732. X        return (FALSE);
  1733. X    }
  1734. X    /* only read the requested number of characters */
  1735. X    if ((end - start) > NLINE)
  1736. X        req_chars = NLINE;
  1737. X    else
  1738. X        req_chars = (int)(end - start);
  1739. X
  1740. X    if ((lp1 = lalloc(req_chars)) == NULL)
  1741. X    {
  1742. X        bp -> b_flag |= BFVIEW; /* if no memory set to read only mode */
  1743. X
  1744. X        m = FALSE;          /* flag memory allocation error */
  1745. X    }
  1746. X    else
  1747. X    {
  1748. X        while ((s = ffgetline (lp1->l_text, lp1->l_size, &lp1->l_used)) == FIOSUC)
  1749. X        {
  1750. X            /* this code breaks rules for knowing how lines * are stored and linked
  1751. X            together, oh well */
  1752. X            lp2 = lback (curbp -> b_linep);
  1753. X            lp2 -> l_fp = lp1;
  1754. X            lp1 -> l_fp = curbp -> b_linep;
  1755. X            lp1 -> l_bp = lp2;
  1756. X            curbp -> b_linep -> l_bp = lp1;
  1757. X            lp1 -> l_file_offset = byte_cnt;   /* file offset from begining */
  1758. X            byte_cnt += (long) lp1 -> l_used;    /* number of bytes read in    */
  1759. X            start += (long) lp1 -> l_used;
  1760. X            if (end <= start)
  1761. X                break;
  1762. X            /* stop reading after the requested number of characters */
  1763. X            if (end < start + req_chars)
  1764. X            {
  1765. X                req_chars = end - start;
  1766. X            }
  1767. X            if ((lp1 = lalloc(req_chars)) == NULL)
  1768. X            {
  1769. X                bp -> b_flag |= BFVIEW; /* if no memory set to read only mode */
  1770. X
  1771. X                m = FALSE;          /* flag memory allocation error */
  1772. X                break;
  1773. X            }
  1774. X            if ((byte_cnt & 0x7fff) == 0)
  1775. X            {
  1776. X                sprintf (buf1, MSG_read_lx, R_POS_FMT(curwp));
  1777. X                sprintf (buf, buf1, (ulong)byte_cnt);
  1778. X                writ_echo (buf);
  1779. X                /* check if we should quit */
  1780. X                if (ttkeyready ())
  1781. X                {
  1782. X                    wind_on_dot_all();
  1783. X                    if (ttgetc () == CTL_G)  /* was it an abort key? */
  1784. X                    {
  1785. X                        s = FIOERR;
  1786. X                        break;
  1787. X                    }
  1788. X                }
  1789. X            }
  1790. X        }
  1791. X    }
  1792. X    ffclose ();                 /* Ignore errors.       */
  1793. X    if (s == FIOEOF && kbdmop == NULL)
  1794. X    {
  1795. X        /* Don't zap an error.   */
  1796. X        sprintf (buf1, MSG_read_lx, R_POS_FMT(curwp));
  1797. X        sprintf (buf, buf1, byte_cnt);
  1798. X        writ_echo (buf);
  1799. X    }
  1800. X    if (m == FALSE && kbdmop == NULL)
  1801. X    {
  1802. X        /* Don't zap an error.   */
  1803. X        sprintf (buf, MSG_no_mem_rd);
  1804. X        err_echo (buf);
  1805. X    }
  1806. X
  1807. X#if     BACKUP
  1808. X    curbp -> b_flag |= BFBAK;   /* Need a backup.       */
  1809. X#endif
  1810. Xout:
  1811. X    for (wp = wheadp; wp != NULL; wp = wp -> w_wndp)
  1812. X    {
  1813. X        if (wp -> w_bufp == curbp)
  1814. X        {
  1815. X            wp -> w_linep = lforw (curbp -> b_linep);
  1816. X            wp -> w_dotp = lforw (curbp -> b_linep);
  1817. X            wp -> w_doto = 0;
  1818. X            wp -> w_unit_offset = 0;
  1819. X            wp -> w_markp = NULL;
  1820. X            wp -> w_marko = 0;
  1821. X            wp -> w_flag |= WFMODE | WFHARD;
  1822. X        }
  1823. X    }
  1824. X    /* so tell yank-buffer about it */
  1825. X    if ((blistp -> b_nwnd != 0) &&  /* update buffer display */
  1826. X    (blistp -> b_type == BTLIST))
  1827. X        listbuffers ();
  1828. X    if (s == FIOERR || s == FIOFNF)/* False if error.      */
  1829. X        return (FALSE);
  1830. X    return (TRUE);
  1831. X}
  1832. X
  1833. X
  1834. X/*
  1835. X* Take a file name, and from it
  1836. X* fabricate a buffer name. This routine knows
  1837. X* about the syntax of file names on the target system.
  1838. X* BDC1         left scan delimiter.
  1839. X* BDC2         optional second left scan delimiter.
  1840. X* BDC3         optional right scan delimiter.
  1841. X*/
  1842. Xvoid makename (bname, fname)
  1843. Xchar    bname[];
  1844. Xchar    fname[];
  1845. X{
  1846. X    register char  *cp1;
  1847. X    register char  *cp2;
  1848. X
  1849. X    cp1 = &fname[0];
  1850. X    while (*cp1 != 0)
  1851. X        ++cp1;
  1852. X#ifdef  BDC2
  1853. X    while (cp1 != &fname[0] && cp1[-1] != BDC1 && cp1[-1] != BDC2)
  1854. X        --cp1;
  1855. X#else
  1856. X    while (cp1 != &fname[0] && cp1[-1] != BDC1)
  1857. X        --cp1;
  1858. X#endif
  1859. X    cp2 = &bname[0];
  1860. X#ifdef  BDC3
  1861. X    while (cp2 != &bname[NBUFN - 1] && *cp1 != 0 && *cp1 != BDC3)
  1862. X        *cp2++ = *cp1++;
  1863. X#else
  1864. X    while (cp2 != &bname[NBUFN - 1] && *cp1 != 0)
  1865. X        *cp2++ = *cp1++;
  1866. X#endif
  1867. X    *cp2 = 0;
  1868. X}
  1869. X
  1870. X
  1871. X/*
  1872. X* Ask for a file name, and write the
  1873. X* contents of the current buffer to that file.
  1874. X* Update the remembered file name and clear the
  1875. X* buffer changed flag. This handling of file names
  1876. X* is different from the earlier versions, and
  1877. X* is more compatable with Gosling EMACS than
  1878. X* with ITS EMACS.
  1879. X*/
  1880. Xchar    filewrite ()
  1881. X{
  1882. X    register    WINDOW * wp;
  1883. X    register char   s;
  1884. X    char    fname[NFILEN];
  1885. X    A32     start, end;
  1886. X
  1887. X    if ((s = ereply (MSG_wr_file, fname, NFILEN, NULL)) != TRUE)
  1888. X        return (s);
  1889. X    if (!parse_f_name (fname, &start, &end))
  1890. X        return (FALSE);
  1891. X
  1892. X    adjustcase (fname);
  1893. X    if ((s = writeout (fname, start, end, S_IREAD | S_IWRITE)) == TRUE)
  1894. X    {
  1895. X        strcpy (curbp -> b_fname, fname);
  1896. X        curbp -> b_flag &= ~BFCHG;
  1897. X        wp = wheadp;            /* Update mode lines.   */
  1898. X        while (wp != NULL)
  1899. X        {
  1900. X            if (wp -> w_bufp == curbp)
  1901. X                wp -> w_flag |= WFMODE;
  1902. X            wp = wp -> w_wndp;
  1903. X        }
  1904. X    }
  1905. X
  1906. X#if     BACKUP
  1907. X    curbp -> b_flag &= ~BFBAK;  /* No backup.           */
  1908. X#endif
  1909. X    return (s);
  1910. X}
  1911. X
  1912. X
  1913. X/*
  1914. X* Save the contents of the current buffer back into
  1915. X* its associated file. Do nothing if there have been no changes
  1916. X* (is this a bug, or a feature). Error if there is no remembered
  1917. X* file name. If this is the first write since the read or visit,
  1918. X* then a backup copy of the file is made.
  1919. X*/
  1920. Xchar    filesave ()
  1921. X{
  1922. X    register    WINDOW * wp;
  1923. X    register char   s;
  1924. X    struct    stat    st;
  1925. X
  1926. X    if ((curbp -> b_flag & BFCHG) == 0)/* Return, no changes.  */
  1927. X        return (TRUE);
  1928. X    if (curbp -> b_fname[0] == 0)/* Must have a name.    */
  1929. X    {
  1930. X        if (!(curbp -> b_type == BTSAVE))/* yanked buffer */
  1931. X        {
  1932. X            writ_echo (MSG_no_fn);
  1933. X        }
  1934. X        return (FALSE);
  1935. X    }
  1936. X    st.st_mode = S_IREAD | S_IWRITE;    /* set default */
  1937. X#if     BACKUP
  1938. X    if ((curbp -> b_flag & BFBAK) != 0)
  1939. X    {
  1940. X        /* get the mode of the file */
  1941. X        stat (curbp -> b_fname, &st);
  1942. X
  1943. X        s = fbackupfile (curbp -> b_fname);
  1944. X        if (s == ABORT)         /* Hard error.          */
  1945. X            return (s);
  1946. X        if (s == FALSE          /* Softer error.        */
  1947. X        && (s = eyesno (MSG_bk_err)) != TRUE)
  1948. X            return (s);
  1949. X    }
  1950. X
  1951. X#endif
  1952. X    if ((s = writeout (curbp -> b_fname, 0L, MAXPOS, st.st_mode)) == TRUE)
  1953. X    {
  1954. X        curbp -> b_flag &= ~BFCHG;/* No change.           */
  1955. X        curbp -> b_flag &= ~BFBAD;/* if it was trashed, forget it now */
  1956. X        wp = wheadp;            /* Update mode lines.   */
  1957. X        while (wp != NULL)
  1958. X        {
  1959. X            if (wp -> w_bufp == curbp)
  1960. X                wp -> w_flag |= WFMODE;
  1961. X            wp = wp -> w_wndp;
  1962. X        }
  1963. X    }
  1964. X
  1965. X#if     BACKUP
  1966. X    curbp -> b_flag &= ~BFBAK;  /* No backup.           */
  1967. X#endif
  1968. X    return (s);
  1969. X}
  1970. X
  1971. X/*
  1972. X* This function performs the details of file
  1973. X* writing. Uses the file management routines in the
  1974. X* "fileio.c" package. The number of lines written is
  1975. X* displayed. Sadly, it looks inside a LINE; provide
  1976. X* a macro for this. Most of the grief is error
  1977. X* checking of some sort.
  1978. X* The file permissions are set as requested.
  1979. X*/
  1980. Xbool writeout (fn, start, end, mode)
  1981. Xchar   *fn;
  1982. XA32     start, end;
  1983. Xushort    mode;
  1984. X{
  1985. X    register    int    s, num_chars;
  1986. X    register    LINE * lp;
  1987. X    register    long   nbytes;
  1988. X    char        buf[NCOL], buf1[NCOL];
  1989. X    A32         temp;
  1990. X
  1991. X    if ((s = ffwopen (fn, mode)) != FIOSUC)/* Open writes message. */
  1992. X        return (FALSE);
  1993. X    temp = ffseek (start);
  1994. X    if (temp != start)
  1995. X    {
  1996. X        sprintf (buf1, ERR_f_size, R_POS_FMT(curwp));
  1997. X        sprintf (buf, buf1, temp);
  1998. X        writ_echo (buf);
  1999. X        return (FALSE);
  2000. X    }
  2001. X    sprintf (buf, MSG_writing, fn);/* jam */
  2002. X    writ_echo (buf);
  2003. X
  2004. X    /* insure that the help screen reflects the latest bindings */
  2005. X    if (curbp == blistp)
  2006. X        wallchart (0, 0, 0);
  2007. X
  2008. X    lp = lforw (curbp -> b_linep);/* First line. */
  2009. X    nbytes = 0;                  /* Number of bytes.  */
  2010. X    temp = end - start;         /* number of bytes to write */
  2011. X    while (lp != curbp -> b_linep)
  2012. X    {
  2013. X        if (curbp == blistp)
  2014. X        {
  2015. X            /* special list buffer */
  2016. X            num_chars = HENDCOL;    /* limit line length */
  2017. X            lp -> l_text[num_chars - 1] = '\n';
  2018. X        }
  2019. X        else
  2020. X        {
  2021. X            /* standard buffer */
  2022. X            if (nbytes + (long)llength (lp) > temp)
  2023. X                num_chars = (int)(temp - nbytes);
  2024. X            else
  2025. X                num_chars = llength (lp);
  2026. X        }
  2027. X        if ((s = ffputline (&lp -> l_text[0], num_chars)) != FIOSUC)
  2028. X            break;
  2029. X        nbytes += num_chars;
  2030. X        if (temp <= nbytes)
  2031. X            break;
  2032. X        lp = lforw (lp);
  2033. X
  2034. X        if ((nbytes & 0x7fff) == 0)
  2035. X        {
  2036. X            sprintf (buf1, MSG_wrot_n, R_POS_FMT(curwp));
  2037. X            sprintf (buf, buf1, (ulong)nbytes);
  2038. X            writ_echo (buf);
  2039. X            /* check if we should quit */
  2040. X            if (ttkeyready ())
  2041. X            {
  2042. X                wind_on_dot_all();
  2043. X                if (ttgetc () == CTL_G)  /* was it an abort key? */
  2044. X                {
  2045. X                    s = FIOERR;
  2046. X                    break;
  2047. X                }
  2048. X            }
  2049. X        }
  2050. X    }
  2051. X    if (s == FIOSUC)
  2052. X    {
  2053. X        /* No write error. */
  2054. X        s = ffclose ();
  2055. X        if (s == FIOSUC && kbdmop == NULL)
  2056. X        {
  2057. X            sprintf (buf1, MSG_wrot_n, R_POS_FMT(curwp));
  2058. X            sprintf (buf, buf1, (long) nbytes);
  2059. X            writ_echo (buf);
  2060. X        }
  2061. X    }
  2062. X    else /* Ignore close error   */
  2063. X        ffclose ();             /* if a write error.    */
  2064. X    curbp -> b_file_size = nbytes;  /* update file size */
  2065. X    if ((blistp -> b_nwnd != 0) &&  /* update buffer display */
  2066. X    (blistp -> b_type == BTLIST))
  2067. X        listbuffers ();
  2068. X    if (s != FIOSUC)            /* Some sort of error.  */
  2069. X        return (FALSE);
  2070. X    return (TRUE);
  2071. X}
  2072. X
  2073. X/*
  2074. X* The command allows the user
  2075. X* to modify the file name associated with
  2076. X* the current buffer. It is like the "f" command
  2077. X* in UNIX "ed". The operation is simple; just zap
  2078. X* the name in the BUFFER structure, and mark the windows
  2079. X* as needing an update. You can type a blank line at the
  2080. X* prompt if you wish.
  2081. X*/
  2082. Xchar    filename ()
  2083. X{
  2084. X    register    WINDOW * wp;
  2085. X    register char   s;
  2086. X    char    fname[NFILEN];
  2087. X    A32     start, end;
  2088. X
  2089. X    if ((s = ereply (MSG_fil_nam, fname, NFILEN, NULL)) == ABORT)
  2090. X        return (s);
  2091. X    if (!parse_f_name (fname, &start, &end))
  2092. X        return (FALSE);
  2093. X
  2094. X    adjustcase (fname);
  2095. X    curbp -> b_flag |= BFCHG;   /* jam - on name change, set modify */
  2096. X    BUF_START(curwp) = start;
  2097. X    l_fix_up (curbp -> b_linep -> l_fp); /* adjust file offsets from first line */
  2098. X    strcpy (curbp -> b_fname, fname);/* Fix name.            */
  2099. X    wp = wheadp;                /* Update mode lines.   */
  2100. X    while (wp != NULL)
  2101. X    {
  2102. X        if (wp -> w_bufp == curbp)
  2103. X            wp -> w_flag |= WFMODE;
  2104. X        wp = wp -> w_wndp;
  2105. X    }
  2106. X#if     BACKUP
  2107. X    curbp -> b_flag &= ~BFBAK;  /* No backup.           */
  2108. X#endif
  2109. X    return (TRUE);
  2110. X}
  2111. X
  2112. X/*
  2113. X*   Get the length parameters that were entered with the file name.
  2114. X*   There can be the file name only.
  2115. X*   There can be a file name and a starting position.
  2116. X*   There can be a name a starting position and an ending position.
  2117. X*   There can be a name a starting position and a length.
  2118. X*
  2119. X*   input:
  2120. X*       fn      pointer to file name string to parse.
  2121. X*
  2122. X*   output:
  2123. X*       fn      pointer to null terminated file name.
  2124. X*       start   pointer to the starting point in file (default = 0)
  2125. X*       end     pointer to the end point in file (default = -1)
  2126. X*       return  FALSE if file name or addresses are bad.
  2127. X*/
  2128. Xbool    parse_f_name (fn, start, end)
  2129. Xchar    *fn;
  2130. XA32     *start, *end;
  2131. X{
  2132. X    char    buf[NFILEN], buf1[NCOL], fmt[NCOL];
  2133. X    int     i_cnt;
  2134. X
  2135. X    /* build up format string according to the current screen format */
  2136. X    sprintf (fmt, "%s %s %s", "%s", R_POS_FMT(curwp), R_POS_FMT(curwp));
  2137. X
  2138. X    *start = 0L;
  2139. X    *end = MAXPOS;
  2140. X    sscanf (fn, fmt, buf, start, end);
  2141. X
  2142. X    if (*end != MAXPOS)
  2143. X    {
  2144. X        for (i_cnt = strlen (fn) - 1; i_cnt >= 0; i_cnt--)
  2145. X        {
  2146. X            if (fn[i_cnt] == '+')
  2147. X            {
  2148. X                *end += *start;
  2149. X                break;
  2150. X            }
  2151. X        }
  2152. X    }
  2153. X    /* start should preceed end */
  2154. X    if (*start > *end)
  2155. X    {
  2156. X        sprintf (buf1, ERR_parse_fn, R_POS_FMT(curwp), R_POS_FMT(curwp));
  2157. X        sprintf (buf, buf1, *start, *end);
  2158. X        writ_echo (buf);
  2159. X        return (FALSE);
  2160. X    }
  2161. X
  2162. X    /* error if addresses are negative */
  2163. X    if ((*start < 0) || (*end < 0))
  2164. X    {
  2165. X        writ_echo (ERR_addr_neg);
  2166. X        return (FALSE);
  2167. X    }
  2168. X
  2169. X    /* deposit null terminated file name */
  2170. X    strcpy (fn, buf);
  2171. X    return (TRUE);
  2172. X}
  2173. END_OF_FILE
  2174.   if test 19205 -ne `wc -c <'file.c'`; then
  2175.     echo shar: \"'file.c'\" unpacked with wrong size!
  2176.   fi
  2177.   # end of 'file.c'
  2178. fi
  2179. if test -f 'makefile.286' -a "${1}" != "-c" ; then 
  2180.   echo shar: Will not clobber existing file \"'makefile.286'\"
  2181. else
  2182.   echo shar: Extracting \"'makefile.286'\" \(676 characters\)
  2183.   sed "s/^X//" >'makefile.286' <<'END_OF_FILE'
  2184. X# This is a makefile for 286 xenix
  2185. XCFLAGS=     -O -Ml -DUNIX -DNOPROTO -DNORENAME
  2186. X
  2187. XOFILES=        basic.o ebcdic.o fileio.o region.o text.o wangpc.o \
  2188. X    buffer.o echo.o main.o search.o tty.o window.o \
  2189. X    cinfo.o extend.o kbd.o spawn.o ttyio.o termio.o tcap.o word.o \
  2190. X    display.o file.o line.o random.o symbol.o ttykbd.o format.o
  2191. X
  2192. X
  2193. XCFILES=     basic.c ebcdic.c fileio.c region.c text.c wangpc.c \
  2194. X    buffer.c echo.c format.c main.c search.c tty.c window.c \
  2195. X    cinfo.c extend.c kbd.c spawn.c ttyio.c termio.c tcap.c word.c \
  2196. X    display.c file.c line.c random.c symbol.c ttykbd.c
  2197. X
  2198. XHFILES=     def.h
  2199. X
  2200. Xbeav:     $(OFILES)
  2201. X    $(CC) $(CFLAGS) $(OFILES) -ltermcap -lc -o beav
  2202. X
  2203. X(OFILES):  $(HFILES)
  2204. X
  2205. END_OF_FILE
  2206.   if test 676 -ne `wc -c <'makefile.286'`; then
  2207.     echo shar: \"'makefile.286'\" unpacked with wrong size!
  2208.   fi
  2209.   # end of 'makefile.286'
  2210. fi
  2211. echo shar: End of archive 3 \(of 9\).
  2212. cp /dev/null ark3isdone
  2213. MISSING=""
  2214. for I in 1 2 3 4 5 6 7 8 9 ; do
  2215.     if test ! -f ark${I}isdone ; then
  2216.     MISSING="${MISSING} ${I}"
  2217.     fi
  2218. done
  2219. if test "${MISSING}" = "" ; then
  2220.     echo You have unpacked all 9 archives.
  2221.     rm -f ark[1-9]isdone ark[1-9][0-9]isdone
  2222. else
  2223.     echo You still must unpack the following archives:
  2224.     echo "        " ${MISSING}
  2225. fi
  2226. exit 0
  2227. exit 0 # Just in case...
  2228.