home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 October / usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso / misc / volume37 / vim / part16 < prev    next >
Text File  |  1993-04-24  |  33KB  |  1,457 lines

  1. Newsgroups: comp.sources.misc
  2. From: mool@oce.nl (Bram Moolenaar)
  3. Subject: v37i016:  vim - Vi IMitation editor v1.27, Part16/24
  4. Message-ID: <1993Apr25.013557.22618@sparky.imd.sterling.com>
  5. X-Md4-Signature: 37a900c81fff958138824e54f27d10be
  6. Date: Sun, 25 Apr 1993 01:35:57 GMT
  7. Approved: kent@sparky.imd.sterling.com
  8.  
  9. Submitted-by: mool@oce.nl (Bram Moolenaar)
  10. Posting-number: Volume 37, Issue 16
  11. Archive-name: vim/part16
  12. Environment: UNIX, AMIGA, MS-DOS
  13.  
  14. #! /bin/sh
  15. # This is a shell archive.  Remove anything before this line, then unpack
  16. # it by saving it into a file and typing "sh file".  To overwrite existing
  17. # files, type "sh file -c".  You can also feed this as standard input via
  18. # unshar, or by typing "sh <file", e.g..  If this archive is complete, you
  19. # will see the following message at the end:
  20. #        "End of archive 16 (of 23)."
  21. # Contents:  vim/src/screen.c
  22. # Wrapped by mool@oce-rd2 on Mon Apr 19 15:50:12 1993
  23. PATH=/bin:/usr/bin:/usr/ucb ; export PATH
  24. if test -f 'vim/src/screen.c' -a "${1}" != "-c" ; then 
  25.   echo shar: Will not clobber existing file \"'vim/src/screen.c'\"
  26. else
  27. echo shar: Extracting \"'vim/src/screen.c'\" \(29501 characters\)
  28. sed "s/^X//" >'vim/src/screen.c' <<'END_OF_FILE'
  29. X/* vi:ts=4:sw=4
  30. X *
  31. X * VIM - Vi IMitation
  32. X *
  33. X * Code Contributions By:    Bram Moolenaar            mool@oce.nl
  34. X *                            Tim Thompson            twitch!tjt
  35. X *                            Tony Andrews            onecom!wldrdg!tony 
  36. X *                            G. R. (Fred) Walter        watmath!watcgl!grwalter 
  37. X */
  38. X
  39. X/*
  40. X * screen.c: code for displaying on the screen
  41. X */
  42. X
  43. X#include "vim.h"
  44. X#include "globals.h"
  45. X#include "proto.h"
  46. X#include "param.h"
  47. X
  48. Xchar *tgoto __PARMS((char *cm, int col, int line));
  49. X
  50. Xstatic u_char     *Nextscreen = NULL;     /* What's to be put on the screen. */
  51. Xstatic int         NumLineSizes = 0;        /* # of active LineSizes */
  52. Xstatic linenr_t *LineNumbers = NULL;    /* Pointer to the line for LineSizes */
  53. Xstatic u_char     *LineSizes = NULL;        /* Number of rows the lines occupy */
  54. Xstatic u_char     **LinePointers = NULL;    /* array of pointers into Netscreen */
  55. X
  56. X/*
  57. X * The following variable is set (in cursupdate) to the number of physical
  58. X * lines taken by the line the cursor is on. We use this to avoid extra calls
  59. X * to plines(). The optimized routine updateline()
  60. X * makes sure that the size of the cursor line hasn't changed. If so, lines
  61. X * below the cursor will move up or down and we need to call the routine
  62. X * updateScreen() to examine the entire screen.
  63. X */
  64. Xstatic int        Cline_size;             /* size (in rows) of the cursor line */
  65. Xstatic int        Cline_row;                /* starting row of the cursor line */
  66. Xint                redraw_msg = TRUE;        /* TRUE when "insert mode" needs updating */
  67. Xstatic FPOS        oldCurpos = {0, 0};        /* last known end of quoted part */
  68. Xstatic int        oldCurswant = 0;        /* last known value of Curswant */
  69. Xstatic int        canopt;                    /* TRUE when cursor goto can be optimized */
  70. Xstatic int        emptyrows = 0;            /* number of '~' rows on screen */
  71. X
  72. Xstatic int screenline __ARGS((linenr_t, int, int));
  73. Xstatic void screenchar __ARGS((u_char *, int, int));
  74. Xstatic void screenfill __ARGS((int, int));
  75. X
  76. X/*
  77. X * updateline() - like updateScreen() but only for cursor line
  78. X *
  79. X * This determines whether or not we need to call updateScreen() to examine
  80. X * the entire screen for changes. This occurs if the size of the cursor line
  81. X * (in rows) hasn't changed.
  82. X */
  83. X    void
  84. Xupdateline()
  85. X{
  86. X    int         row;
  87. X    int         n;
  88. X
  89. X    screenalloc();        /* allocate screen buffers if size changed */
  90. X
  91. X    if (Nextscreen == NULL || RedrawingDisabled)
  92. X        return;
  93. X
  94. X    screenchar(NULL, 0, 0);    /* init cursor position of screenchar() */
  95. X    outstr(T_CI);                /* disable cursor */
  96. X
  97. X    row = screenline(Curpos.lnum, Cline_row, (int)Rows - 1);
  98. X
  99. X    outstr(T_CV);                /* enable cursor again */
  100. X
  101. X    if (row == Rows)            /* line too long for screen */
  102. X        updateScreen(VALID_TO_CURSCHAR);
  103. X    else
  104. X    {
  105. X        n = row - Cline_row;
  106. X        if (n != Cline_size)        /* line changed size */
  107. X        {
  108. X            if (n < Cline_size)     /* got smaller: delete lines */
  109. X                    s_del(row, Cline_size - n, FALSE);
  110. X            else                    /* got bigger: insert lines */
  111. X                    s_ins(Cline_row + Cline_size, n - Cline_size, FALSE);
  112. X
  113. X            updateScreen(VALID_TO_CURSCHAR);
  114. X        }
  115. X    }
  116. X}
  117. X
  118. X/*
  119. X * updateScreen()
  120. X *
  121. X * Based on the current value of Topline, transfer a screenfull of stuff from
  122. X * Filemem to Nextscreen, and update Botline.
  123. X */
  124. X
  125. X    void
  126. XupdateScreen(type)
  127. X    int             type;
  128. X{
  129. X    register int    row;
  130. X    register int    endrow;
  131. X    linenr_t        lnum;
  132. X    linenr_t        lastline = 0; /* only valid if endrow != Rows -1 */
  133. X    int                done;        /* if TRUE, we hit the end of the file */
  134. X    int                didline;    /* if TRUE, we finished the last line */
  135. X    int             srow = 0;    /* starting row of the current line */
  136. X    int             idx;
  137. X    int             i;
  138. X    long             j;
  139. X    static int        postponed_not_valid = FALSE;
  140. X    register u_char *screenp;
  141. X
  142. X    screenalloc();        /* allocate screen buffers if size changed */
  143. X
  144. X    if (Nextscreen == NULL)
  145. X        return;
  146. X
  147. X    if (type == CLEAR)        /* first clear screen */
  148. X    {
  149. X        screenclear();
  150. X        type = NOT_VALID;
  151. X    }
  152. X    if (type == CURSUPD)    /* update cursor and then redraw */
  153. X    {
  154. X        NumLineSizes = 0;
  155. X        cursupdate();        /* will call updateScreen(VALID) */
  156. X        return;
  157. X    }
  158. X    if (NumLineSizes == 0)
  159. X        type = NOT_VALID;
  160. X
  161. X     if (RedrawingDisabled)
  162. X    {
  163. X        if (type == NOT_VALID)
  164. X            postponed_not_valid = TRUE;        /* use NOT_VALID next time */
  165. X        return;
  166. X    }
  167. X
  168. X    if (postponed_not_valid)
  169. X    {
  170. X        type = NOT_VALID;
  171. X        postponed_not_valid = FALSE;
  172. X    }
  173. X
  174. X/* return if there is nothing to do */
  175. X    if ((type == VALID && Topline == LineNumbers[0]) ||
  176. X            (type == INVERTED && oldCurpos.lnum == Curpos.lnum &&
  177. X                    oldCurpos.col == Curpos.col))
  178. X        return;
  179. X
  180. X    if (type == NOT_VALID)
  181. X    {
  182. X        redraw_msg = TRUE;
  183. X        NumLineSizes = 0;
  184. X    }
  185. X
  186. X    idx = 0;
  187. X    row = 0;
  188. X    lnum = Topline;
  189. X    outstr(T_CI);                /* disable cursor */
  190. X
  191. X    /* The number of rows shown is Rows-1. */
  192. X    /* The default last row is the status/command line. */
  193. X    endrow = Rows - 1;
  194. X
  195. X    if (type == VALID || type == VALID_TO_CURSCHAR)
  196. X    {
  197. X        /*
  198. X         * We handle two special cases:
  199. X         * 1: we are off the top of the screen by a few lines: scroll down
  200. X         * 2: Topline is below LineNumbers[0]: may scroll up
  201. X         */
  202. X        if (Topline < LineNumbers[0])    /* may scroll down */
  203. X        {
  204. X            j = LineNumbers[0] - Topline;
  205. X            if (j < Rows - 3)                /* not too far off */
  206. X            {
  207. X                lastline = LineNumbers[0] - 1;
  208. X                i = plines_m(Topline, lastline);
  209. X                if (i < Rows - 3)        /* less than a screen off */
  210. X                {
  211. X                    /*
  212. X                     * Try to insert the correct number of lines.
  213. X                     * This may fail and the screen may have been cleared.
  214. X                     */
  215. X                    if (s_ins(0, i, FALSE) && NumLineSizes)
  216. X                    {
  217. X                        endrow = i;
  218. X
  219. X                        if ((NumLineSizes += j) > Rows - 1)
  220. X                            NumLineSizes = Rows - 1;
  221. X                        for (idx = NumLineSizes; idx - j >= 0; idx--)
  222. X                        {
  223. X                            LineNumbers[idx] = LineNumbers[idx - j];
  224. X                            LineSizes[idx] = LineSizes[idx - j];
  225. X                        }
  226. X                        idx = 0;
  227. X                    }
  228. X                }
  229. X                else        /* far off: clearing the screen is faster */
  230. X                    screenclear();
  231. X            }
  232. X            else        /* far off: clearing the screen is faster */
  233. X                screenclear();
  234. X        }
  235. X        else                            /* may scroll up */
  236. X        {
  237. X            j = -1;
  238. X            for (i = 0; i < NumLineSizes; i++) /* try to find Topline in LineNumbers[] */
  239. X            {
  240. X                if (LineNumbers[i] == Topline)
  241. X                {
  242. X                    j = i;
  243. X                    break;
  244. X                }
  245. X                row += LineSizes[i];
  246. X            }
  247. X            if (j == -1)    /* Topline is not in LineNumbers */
  248. X            {
  249. X                row = 0;
  250. X                screenclear();   /* far off: clearing the screen is faster */
  251. X            }
  252. X            else
  253. X            {
  254. X                /*
  255. X                 * Try to delete the correct number of lines.
  256. X                 * Topline is at LineNumbers[i].
  257. X                 */
  258. X                if ((row == 0 || s_del(0, row, FALSE)) && NumLineSizes)
  259. X                {
  260. X                    srow = row;
  261. X                    row = 0;
  262. X                    for (;;)
  263. X                    {
  264. X                        if (type == VALID_TO_CURSCHAR && lnum == Curpos.lnum)
  265. X                                break;
  266. X                        if (row + srow + LineSizes[j] >= Rows - 1)
  267. X                                break;
  268. X                        LineSizes[idx] = LineSizes[j];
  269. X                        LineNumbers[idx] = lnum++;
  270. X
  271. X                        row += LineSizes[idx++];
  272. X                        if (++j >= NumLineSizes)
  273. X                            break;
  274. X                    }
  275. X                    NumLineSizes = idx;
  276. X                }
  277. X                else
  278. X                    row = 0;        /* update all lines */
  279. X            }
  280. X        }
  281. X        if (endrow == Rows - 1 && idx == 0)     /* no scrolling */
  282. X                NumLineSizes = 0;
  283. X    }
  284. X
  285. X    done = didline = FALSE;
  286. X    screenchar(NULL, 0, 0);    /* init cursor position of screenchar() */
  287. X
  288. X    if (Quote.lnum)                /* check if we are updating the inverted part */
  289. X    {
  290. X        linenr_t    from, to;
  291. X
  292. X    /* find the line numbers that need to be updated */
  293. X        if (Curpos.lnum < oldCurpos.lnum)
  294. X        {
  295. X            from = Curpos.lnum;
  296. X            to = oldCurpos.lnum;
  297. X        }
  298. X        else
  299. X        {
  300. X            from = oldCurpos.lnum;
  301. X            to = Curpos.lnum;
  302. X        }
  303. X    /* if in block mode and changed column or Curswant: update all lines */
  304. X        if (Quote_block && (Curpos.col != oldCurpos.col || Curswant != oldCurswant))
  305. X        {
  306. X            if (from > Quote.lnum)
  307. X                from = Quote.lnum;
  308. X            if (to < Quote.lnum)
  309. X                to = Quote.lnum;
  310. X        }
  311. X
  312. X        if (from < Topline)
  313. X            from = Topline;
  314. X        if (to >= Botline)
  315. X            to = Botline - 1;
  316. X
  317. X    /* find the minimal part to be updated */
  318. X        if (type == INVERTED)
  319. X        {
  320. X            while (lnum < from)                        /* find start */
  321. X            {
  322. X                row += LineSizes[idx++];
  323. X                ++lnum;
  324. X            }
  325. X            srow = row;
  326. X            for (j = idx; j < NumLineSizes; ++j)    /* find end */
  327. X            {
  328. X                if (LineNumbers[j] == to + 1)
  329. X                {
  330. X                    endrow = srow;
  331. X                    break;
  332. X                }
  333. X                srow += LineSizes[j];
  334. X            }
  335. X            oldCurpos = Curpos;
  336. X            oldCurswant = Curswant;
  337. X        }
  338. X    /* if we update the lines between from and to set oldCurpos */
  339. X        else if (lnum <= from && (endrow == Rows - 1 || lastline >= to))
  340. X        {
  341. X            oldCurpos = Curpos;
  342. X            oldCurswant = Curswant;
  343. X        }
  344. X    }
  345. X
  346. X    /*
  347. X     * Update the screen rows from "row" to "endrow".
  348. X     * Start at line "lnum" which is at LineNumbers[idx].
  349. X     */
  350. X    for (;;)
  351. X    {
  352. X            if (lnum > line_count)        /* hit the end of the file */
  353. X            {
  354. X                done = TRUE;
  355. X                break;
  356. X            }
  357. X            srow = row;
  358. X            row = screenline(lnum, srow, endrow);
  359. X            if (row > endrow)    /* past end of screen */
  360. X            {
  361. X                LineSizes[idx] = plines(lnum);    /* we may need the size of that */
  362. X                LineNumbers[idx++] = lnum;        /* too long line later on */
  363. X                break;
  364. X            }
  365. X
  366. X            LineSizes[idx] = row - srow;
  367. X            LineNumbers[idx++] = lnum;
  368. X            if (++lnum > line_count)
  369. X            {
  370. X                done = TRUE;
  371. X                break;
  372. X            }
  373. X
  374. X            if (row == endrow)
  375. X            {
  376. X                didline = TRUE;
  377. X                break;
  378. X            }
  379. X    }
  380. X    if (idx > NumLineSizes)
  381. X        NumLineSizes = idx;
  382. X
  383. X    /* Do we have to do off the top of the screen processing ? */
  384. X    if (endrow != Rows - 1)
  385. X    {
  386. X        row = 0;
  387. X        for (idx = 0; idx < NumLineSizes && row < (Rows - 1); idx++)
  388. X            row += LineSizes[idx];
  389. X
  390. X        if (row < (Rows - 1))
  391. X        {
  392. X            done = TRUE;
  393. X        }
  394. X        else if (row > (Rows - 1))        /* Need to blank out the last line */
  395. X        {
  396. X            lnum = LineNumbers[idx - 1];
  397. X            srow = row - LineSizes[idx - 1];
  398. X            didline = FALSE;
  399. X        }
  400. X        else
  401. X        {
  402. X            lnum = LineNumbers[idx - 1] + 1;
  403. X            didline = TRUE;
  404. X        }
  405. X    }
  406. X
  407. X    emptyrows = 0;
  408. X    /*
  409. X     * If we didn't hit the end of the file, and we didn't finish the last
  410. X     * line we were working on, then the line didn't fit.
  411. X     */
  412. X    if (!done && !didline)
  413. X    {
  414. X        if (lnum == Topline)
  415. X        {
  416. X            /*
  417. X             * Single line that does not fit!
  418. X             * Fill last line with '@' characters.
  419. X             */
  420. X            screenp = LinePointers[Rows - 2];
  421. X            for (i = 0; i < Columns; ++i)
  422. X            {
  423. X                if (*screenp != '@')
  424. X                {
  425. X                    *screenp = '@';
  426. X                    screenchar(screenp, (int)(Rows - 2), i);
  427. X                }
  428. X                ++screenp;
  429. X            }
  430. X            Botline = lnum + 1;
  431. X        }
  432. X        else
  433. X        {
  434. X            /*
  435. X             * Clear the rest of the screen and mark the unused lines.
  436. X             */
  437. X            screenfill(srow, '@');
  438. X            Botline = lnum;
  439. X        }
  440. X    }
  441. X    else
  442. X    {
  443. X        /* make sure the rest of the screen is blank */
  444. X        /* put '~'s on rows that aren't part of the file. */
  445. X        screenfill(row, '~');
  446. X        emptyrows = Rows - row - 1;
  447. X
  448. X        if (done)                /* we hit the end of the file */
  449. X            Botline = line_count + 1;
  450. X        else
  451. X            Botline = lnum;
  452. X    }
  453. X
  454. X    if (redraw_msg)
  455. X    {
  456. X        showmode();
  457. X        redraw_msg = FALSE;
  458. X    }
  459. X
  460. X    outstr(T_CV);                /* enable cursor again */
  461. X}
  462. X
  463. Xstatic int        invert;        /* shared by screenline() and screenchar() */
  464. X
  465. X/*
  466. X * Move line "lnum" to the screen.
  467. X * Start at row "startrow", stop when "endrow" is reached.
  468. X * Return the number of last row the line occupies.
  469. X */
  470. X
  471. X    static int
  472. Xscreenline(lnum, startrow, endrow)
  473. X        linenr_t        lnum;
  474. X        int             startrow;
  475. X        int             endrow;
  476. X{
  477. X    register u_char  *screenp;
  478. X    register u_char   c;
  479. X    register int    col;                /* visual column on screen */
  480. X    register int    vcol;                /* visual column for tabs */
  481. X    register int    row;
  482. X    register u_char *ptr;
  483. X    char            extra[16];
  484. X    char            *p_extra;
  485. X    int             n_extra;
  486. X
  487. X    int                fromcol, tocol;        /* start/end of inverting */
  488. X    int                temp;
  489. X    FPOS            *top, *bot;
  490. X
  491. X    row = startrow;
  492. X    col = 0;
  493. X    vcol = 0;
  494. X    invert = FALSE;
  495. X    fromcol = tocol = -10;
  496. X    ptr = (u_char *)nr2ptr(lnum);
  497. X    canopt = TRUE;
  498. X    if (Quote.lnum)                    /* quoting active */
  499. X    {
  500. X        if (ltoreq(Curpos, Quote))        /* Quote is after Curpos */
  501. X        {
  502. X            top = &Curpos;
  503. X            bot = &Quote;
  504. X        }
  505. X        else                            /* Quote is before Curpos */
  506. X        {
  507. X            top = &Quote;
  508. X            bot = &Curpos;
  509. X        }
  510. X        if (Quote_block)                        /* block mode */
  511. X        {
  512. X            if (lnum >= top->lnum && lnum <= bot->lnum)
  513. X            {
  514. X                fromcol = getvcol(top, 2);
  515. X                temp = getvcol(bot, 2);
  516. X                if (temp < fromcol)
  517. X                    fromcol = temp;
  518. X
  519. X                if (Curswant == 29999)
  520. X                    tocol = 29999;
  521. X                else
  522. X                {
  523. X                    tocol = getvcol(top, 3);
  524. X                    temp = getvcol(bot, 3);
  525. X                    if (temp > tocol)
  526. X                        tocol = temp;
  527. X                    ++tocol;
  528. X                }
  529. X            }
  530. X        }
  531. X        else                            /* non-block mode */
  532. X        {
  533. X            if (lnum > top->lnum && lnum <= bot->lnum)
  534. X                fromcol = 0;
  535. X            if (lnum == top->lnum)
  536. X                fromcol = getvcol(top, 2);
  537. X            if (lnum == bot->lnum)
  538. X                tocol = getvcol(bot, 3) + 1;
  539. X
  540. X            if (Quote.col == QUOTELINE)        /* linewise */
  541. X            {
  542. X                if (fromcol > 0)
  543. X                    fromcol = 0;
  544. X                if (tocol > 0)
  545. X                    tocol = QUOTELINE;
  546. X            }
  547. X        }
  548. X        /* if inverting in this line, can't optimize cursor positioning */
  549. X        if (fromcol >= 0 || tocol >= 0)
  550. X            canopt = FALSE;
  551. X    }
  552. X    screenp = LinePointers[row];
  553. X    if (p_nu)
  554. X    {
  555. X        sprintf(extra, "%7ld ", (long)lnum);
  556. X        p_extra = extra;
  557. X        n_extra = 8;
  558. X        vcol = -8;        /* so vcol is 0 when line number has been printed */
  559. X
  560. X    }
  561. X    else
  562. X    {
  563. X        p_extra = NULL;
  564. X        n_extra = 0;
  565. X    }
  566. X    for (;;)
  567. X    {
  568. X        if (vcol == fromcol)    /* start inverting */
  569. X        {
  570. X            invert = TRUE;
  571. X            outstr(T_TI);
  572. X        }
  573. X        if (vcol == tocol)        /* stop inverting */
  574. X        {
  575. X            invert = FALSE;
  576. X            outstr(T_TP);
  577. X        }
  578. X
  579. X        /* Get the next character to put on the screen. */
  580. X        /*
  581. X         * The 'extra' array contains the extra stuff that is inserted to
  582. X         * represent special characters (tabs, and other non-printable stuff.
  583. X         * The order in the 'extra' array is reversed.
  584. X         */
  585. X
  586. X        if (n_extra > 0)
  587. X        {
  588. X            c = (u_char)*p_extra++;
  589. X            n_extra--;
  590. X        }
  591. X        else
  592. X        {
  593. X            if ((c = *ptr++) < ' ' || (c > '~' && c < 0xa0))
  594. X            {
  595. X                /*
  596. X                 * when getting a character from the file, we may have to turn it
  597. X                 * into something else on the way to putting it into 'Nextscreen'.
  598. X                 */
  599. X                if (c == TAB && !p_list)
  600. X                {
  601. X                    p_extra = spaces;
  602. X                    /* tab amount depends on current column */
  603. X                    n_extra = (int)p_ts - vcol % (int)p_ts - 1;
  604. X                    c = ' ';
  605. X                }
  606. X                else if (c == NUL && p_list)
  607. X                {
  608. X                    extra[0] = NUL;
  609. X                    p_extra = extra;
  610. X                    n_extra = 1;
  611. X                    c = '$';
  612. X                }
  613. X                else if (c != NUL)
  614. X                {
  615. X                    p_extra = (char *)transchar(c);
  616. X                    n_extra = charsize(c) - 1;
  617. X                    c = (u_char)*p_extra++;
  618. X                }
  619. X            }
  620. X        }
  621. X
  622. X        if (c == NUL)
  623. X        {
  624. X            if (invert)
  625. X            {
  626. X                if (vcol == 0)    /* invert first char of empty line */
  627. X                {
  628. X                    if (*screenp != (' ' ^ 0x80))
  629. X                    {
  630. X                            *screenp = (' ' ^ 0x80);
  631. X                            screenchar(screenp, row, col);
  632. X                    }
  633. X                    ++screenp;
  634. X                    ++col;
  635. X                }
  636. X                outstr(T_TP);
  637. X                invert = FALSE;
  638. X            }
  639. X            /* 
  640. X             * blank out the rest of this row
  641. X             * could also use clear-to-end-of-line, but it is slower
  642. X             * on an Amiga
  643. X             */
  644. X            while (col < Columns)
  645. X            {
  646. X                if (*screenp != ' ')
  647. X                {
  648. X                        *screenp = ' ';
  649. X                        screenchar(screenp, row, col);
  650. X                }
  651. X                ++screenp;
  652. X                ++col;
  653. X            }
  654. X            row++;
  655. X            break;
  656. X        }
  657. X        if (col >= Columns)
  658. X        {
  659. X            col = 0;
  660. X            if (++row == endrow)        /* line got too long for screen */
  661. X            {
  662. X                ++row;
  663. X                break;
  664. X            }
  665. X            screenp = LinePointers[row];
  666. X        }
  667. X        /* store the character in Nextscreen */
  668. X        if (!invert)
  669. X        {
  670. X            if (*screenp != c)
  671. X            {
  672. X                *screenp = c;
  673. X                screenchar(screenp, row, col);
  674. X            }
  675. X        }
  676. X        else
  677. X        {
  678. X            if (*screenp != (c ^ 0x80))
  679. X            {
  680. X                *screenp = c ^ 0x80;
  681. X                screenchar(screenp, row, col);
  682. X            }
  683. X        }
  684. X        ++screenp;
  685. X        col++;
  686. X        vcol++;
  687. X    }
  688. X
  689. X    if (invert)
  690. X    {
  691. X        outstr(T_TP);
  692. X        invert = FALSE;
  693. X    }
  694. X    return (row);
  695. X}
  696. X
  697. X/*
  698. X * put character '*p' on the screen at position 'row' and 'col'
  699. X */
  700. X    static void
  701. Xscreenchar(p, row, col)
  702. X        u_char    *p;
  703. X        int     row;
  704. X        int     col;
  705. X{
  706. X    static int    oldrow, oldcol;        /* old cursor position */
  707. X    int            c;
  708. X
  709. X    if (p == NULL)                    /* initialize cursor position */
  710. X    {
  711. X        oldrow = oldcol = -1;
  712. X        return;
  713. X    }
  714. X    if (oldcol != col || oldrow != row)
  715. X    {
  716. X        /*
  717. X         * If we're on the same row (which happens a lot!), try to
  718. X         * avoid a windgoto().
  719. X         * If we are only a few characters off, output the
  720. X         * characters. That is faster than cursor positioning.
  721. X         * This can't be used when inverting (a part of) the line.
  722. X         */
  723. X        if (oldrow == row && oldcol < col)
  724. X        {
  725. X            register int i;
  726. X
  727. X            i = col - oldcol;
  728. X            if (i <= 4 && canopt)
  729. X            {
  730. X                while (i)
  731. X                {
  732. X                    c = *(p - i--);
  733. X                    outchar(c);
  734. X                }
  735. X            }
  736. X            else if (T_CRI && *T_CRI)    /* use tgoto interface! jw */
  737. X                outstr(tgoto(T_CRI, 0, i));
  738. X            else
  739. X                windgoto(row, col);
  740. X            
  741. X            oldcol = col;
  742. X        }
  743. X        else
  744. X            windgoto(oldrow = row, oldcol = col);
  745. X    }
  746. X    if (invert)
  747. X        outchar(*p ^ 0x80);
  748. X    else
  749. X        outchar(*p);
  750. X    oldcol++;
  751. X}
  752. X
  753. X/*
  754. X * Fill the screen at 'srow' with character 'c' followed by blanks.
  755. X */
  756. X    static void
  757. Xscreenfill(srow, c)
  758. X        int     srow;
  759. X        int        c;
  760. X{
  761. X        register int row;
  762. X        register int col;
  763. X        register u_char *screenp;
  764. X
  765. X        for (row = srow; row < (Rows - 1); ++row)
  766. X        {
  767. X            screenp = LinePointers[row];
  768. X            if (*screenp != c)
  769. X            {
  770. X                *screenp = c;
  771. X                screenchar(screenp, row, 0);
  772. X            }
  773. X            ++screenp;
  774. X            for (col = 1; col < Columns; ++col)
  775. X            {
  776. X                if (*screenp != ' ')
  777. X                {
  778. X                    *screenp = ' ';
  779. X                    screenchar(screenp, row, col);
  780. X                }
  781. X                ++screenp;
  782. X            }
  783. X        }
  784. X}
  785. X
  786. X/*
  787. X * compute Botline. Can be called after Topline or Rows changed.
  788. X */
  789. X    void
  790. Xcomp_Botline()
  791. X{
  792. X    linenr_t    lnum;
  793. X    int            done = 0;
  794. X
  795. X    for (lnum = Topline; lnum <= line_count; ++lnum)
  796. X    {
  797. X        if ((done += plines(lnum)) >= Rows)
  798. X            break;
  799. X    }
  800. X    Botline = lnum;        /* Botline is the line that is just below the window */
  801. X}
  802. X
  803. X/*
  804. X * prt_line() - print the given line
  805. X * returns the number of characters written.
  806. X */
  807. X    int
  808. Xprt_line(s)
  809. X    char           *s;
  810. X{
  811. X    register int    si = 0;
  812. X    register char    c;
  813. X    register int    col = 0;
  814. X
  815. X    char            extra[16];
  816. X    int             n_extra = 0;
  817. X    int             n;
  818. X
  819. X    for (;;)
  820. X    {
  821. X        if (n_extra > 0)
  822. X            c = extra[--n_extra];
  823. X        else {
  824. X            c = s[si++];
  825. X            if (c == TAB && !p_list)
  826. X            {
  827. X                strcpy(extra, "                ");
  828. X                /* tab amount depends on current column */
  829. X                n_extra = (p_ts - 1) - col % p_ts;
  830. X                c = ' ';
  831. X            }
  832. X            else if (c == NUL && p_list)
  833. X            {
  834. X                extra[0] = NUL;
  835. X                n_extra = 1;
  836. X                c = '$';
  837. X            }
  838. X            else if (c != NUL && (n = charsize(c)) > 1)
  839. X            {
  840. X                char             *p;
  841. X
  842. X                n_extra = 0;
  843. X                p = transchar(c);
  844. X                /* copy 'ch-str'ing into 'extra' in reverse */
  845. X                while (n > 1)
  846. X                    extra[n_extra++] = p[--n];
  847. X                c = p[0];
  848. X            }
  849. X        }
  850. X
  851. X        if (c == NUL)
  852. X            break;
  853. X
  854. X        outchar(c);
  855. X        col++;
  856. X    }
  857. X    return col;
  858. X}
  859. X
  860. X    void
  861. Xscreenalloc()
  862. X{
  863. X    static int        old_Rows = 0;
  864. X    static int        old_Columns = 0;
  865. X    register int    i;
  866. X
  867. X    /*
  868. X     * Allocation of the sceen buffers is done only when the size changes
  869. X     */
  870. X    if (Nextscreen != NULL && Rows == old_Rows && Columns == old_Columns)
  871. X        return;
  872. X
  873. X    old_Rows = Rows;
  874. X    old_Columns = Columns;
  875. X
  876. X    /*
  877. X     * If we're changing the size of the screen, free the old arrays
  878. X     */
  879. X    if (Nextscreen != NULL)
  880. X        free((char *)Nextscreen);
  881. X    if (LinePointers != NULL)
  882. X        free((char *)LinePointers);
  883. X    if (LineNumbers != NULL)
  884. X        free((char *) LineNumbers);
  885. X    if (LineSizes != NULL)
  886. X        free(LineSizes);
  887. X
  888. X    Nextscreen = (u_char *)malloc((size_t) (Rows * Columns));
  889. X    LineNumbers = (linenr_t *) malloc((size_t) (Rows * sizeof(linenr_t)));
  890. X    LineSizes = (u_char *)malloc((size_t) Rows);
  891. X    LinePointers = (u_char **)malloc(sizeof(u_char *) * Rows);
  892. X
  893. X    if (Nextscreen == NULL || LineNumbers == NULL || LineSizes == NULL ||
  894. X                                                LinePointers == NULL)
  895. X    {
  896. X        emsg(e_outofmem);
  897. X        if (Nextscreen != NULL)
  898. X            free((char *)Nextscreen);
  899. X        Nextscreen = NULL;
  900. X    }
  901. X    else
  902. X    {
  903. X        for (i = 0; i < Rows; ++i)
  904. X                LinePointers[i] = Nextscreen + i * Columns;
  905. X    }
  906. X
  907. X    screenclear();
  908. X}
  909. X
  910. X    void
  911. Xscreenclear()
  912. X{
  913. X    register u_char  *np;
  914. X    register u_char  *end;
  915. X
  916. X    if (starting || Nextscreen == NULL)
  917. X        return;
  918. X
  919. X    outstr(T_ED);                /* clear the display */
  920. X
  921. X    np = Nextscreen;
  922. X    end = Nextscreen + Rows * Columns;
  923. X
  924. X    /* blank out Nextscreen */
  925. X    while (np != end)
  926. X        *np++ = ' ';
  927. X
  928. X    /* clear screen info */
  929. X    NumLineSizes = 0;
  930. X}
  931. X
  932. X    void
  933. Xcursupdate()
  934. X{
  935. X    linenr_t        p;
  936. X    long             nlines;
  937. X    int             i;
  938. X    int             temp;
  939. X
  940. X    screenalloc();        /* allocate screen buffers if size changed */
  941. X
  942. X    if (Nextscreen == NULL)
  943. X        return;
  944. X
  945. X    if (Curpos.lnum > line_count)
  946. X        Curpos.lnum = line_count;
  947. X    if (bufempty())             /* special case - file is empty */
  948. X    {
  949. X        Topline = 1;
  950. X        Curpos.lnum = 1;
  951. X        Curpos.col = 0;
  952. X        for (i = 0; i < Rows; i++)
  953. X            LineSizes[i] = 0;
  954. X        if (NumLineSizes == 0)        /* don't know about screen contents */
  955. X            updateScreen(NOT_VALID);
  956. X        NumLineSizes = 1;
  957. X    }
  958. X    else if (Curpos.lnum < Topline)
  959. X    {
  960. X        /*
  961. X         * If the cursor is above the top of the screen, scroll the screen to
  962. X         * put it at the top of the screen.
  963. X         * If we weren't very close to begin with, we scroll more, so that
  964. X         * the line is close to the middle.
  965. X         */
  966. X        temp = Rows / 3;
  967. X        if (Topline - Curpos.lnum >= temp)
  968. X        {
  969. X            p = Curpos.lnum;
  970. X            for (i = 0; i < temp && p > 1; i += plines(--p))
  971. X                ;
  972. X            Topline = p;
  973. X        }
  974. X        else if (p_sj > 1)        /* scroll at least p_sj lines */
  975. X        {
  976. X            for (i = 0; i < p_sj && Topline > 1; i += plines(--Topline))
  977. X                ;
  978. X
  979. X        }
  980. X        if (Topline > Curpos.lnum)
  981. X            Topline = Curpos.lnum;
  982. X        updateScreen(VALID);
  983. X    }
  984. X    else if (Curpos.lnum >= Botline)
  985. X    {
  986. X        nlines = Curpos.lnum - Botline + 1;
  987. X        /*
  988. X         * compute the number of lines at the top which have the same or more
  989. X         * rows than the rows of the lines below the bottom
  990. X         */
  991. X        if (nlines <= Rows)
  992. X        {
  993. X                /* get the number or rows to scroll minus the number of
  994. X                                free '~' rows */
  995. X            temp = plines_m(Botline, Curpos.lnum) - emptyrows;
  996. X            if (temp <= 0)
  997. X                nlines = 0;
  998. X            else
  999. X            {
  1000. X                    /* scroll minimal number of lines */
  1001. X                if (temp < p_sj)
  1002. X                    temp = p_sj;
  1003. X                for (i = 0, p = Topline; i < temp && p < Botline; ++p)
  1004. X                    i += plines(p);
  1005. X                nlines = p - Topline;
  1006. X            }
  1007. X        }
  1008. X
  1009. X        /*
  1010. X         * Scroll up if the cursor is off the bottom of the screen a bit.
  1011. X         * Otherwise put it at 2/3 of the screen.
  1012. X         */
  1013. X        if (nlines > Rows / 3 && nlines > p_sj)
  1014. X        {
  1015. X            p = Curpos.lnum;
  1016. X            temp = (2 * Rows) / 3;
  1017. X            nlines = 0;
  1018. X            i = 0;
  1019. X            do                /* this loop could win a contest ... */
  1020. X                i += plines(p);
  1021. X            while (i < temp && (nlines = 1) != 0 && --p != 0);
  1022. X            Topline = p + nlines;
  1023. X        }
  1024. X        else
  1025. X            scrollup(nlines);
  1026. X        updateScreen(VALID);
  1027. X    }
  1028. X    else if (NumLineSizes == 0)        /* don't know about screen contents */
  1029. X        updateScreen(NOT_VALID);
  1030. X    Cursrow = Curscol = Cursvcol = i = 0;
  1031. X    for (p = Topline; p != Curpos.lnum; ++p)
  1032. X        if (RedrawingDisabled)        /* LineSizes[] invalid */
  1033. X            Cursrow += plines(p);
  1034. X        else
  1035. X            Cursrow += LineSizes[i++];
  1036. X
  1037. X    Cline_row = Cursrow;
  1038. X    if (!RedrawingDisabled && i > NumLineSizes)
  1039. X                                /* Should only happen with a line that is too */
  1040. X                                /* long to fit on the last screen line. */
  1041. X        Cline_size = 0;
  1042. X    else
  1043. X    {
  1044. X        if (RedrawingDisabled)      /* LineSizes[] invalid */
  1045. X            Cline_size = plines(Curpos.lnum);
  1046. X        else
  1047. X            Cline_size = LineSizes[i];
  1048. X
  1049. X        curs_columns();        /* compute Cursvcol and Curscol */
  1050. X    }
  1051. X
  1052. X    if (set_want_col)
  1053. X    {
  1054. X        Curswant = Cursvcol;
  1055. X        set_want_col = FALSE;
  1056. X    }
  1057. X    showruler(0);
  1058. X}
  1059. X
  1060. X/*
  1061. X * compute Curscol and Cursvcol
  1062. X */
  1063. X    void
  1064. Xcurs_columns()
  1065. X{
  1066. X    Cursvcol = getvcol(&Curpos, 1);
  1067. X    Curscol = Cursvcol;
  1068. X    if (p_nu)
  1069. X        Curscol += 8;
  1070. X
  1071. X    Cursrow = Cline_row;
  1072. X    while (Curscol >= Columns)
  1073. X    {
  1074. X        Curscol -= Columns;
  1075. X        Cursrow++;
  1076. X    }
  1077. X    if (Cursrow > Rows - 2)        /* Cursor past end of screen */
  1078. X        Cursrow = Rows - 2;        /* happens with line that does not fit on screen */
  1079. X}
  1080. X
  1081. X/*
  1082. X * get virtual column number of pos
  1083. X * type = 1: where the cursor is on this character
  1084. X * type = 2: on the first position of this character
  1085. X * type = 3: on the last position of this character
  1086. X */
  1087. X    int
  1088. Xgetvcol(pos, type)
  1089. X    FPOS    *pos;
  1090. X    int        type;
  1091. X{
  1092. X    int                col;
  1093. X    int                vcol;
  1094. X    u_char           *ptr;
  1095. X    int             incr;
  1096. X    u_char            c;
  1097. X
  1098. X    vcol = 0;
  1099. X    ptr = (u_char *)nr2ptr(pos->lnum);
  1100. X    for (col = pos->col; col >= 0; --col)
  1101. X    {
  1102. X        c = *ptr++;
  1103. X        if (c == NUL)        /* make sure we don't go past the end of the line */
  1104. X            break;
  1105. X
  1106. X        /* A tab gets expanded, depending on the current column */
  1107. X        incr = chartabsize(c, vcol);
  1108. X
  1109. X        if (col == 0)        /* character at pos.col */
  1110. X        {
  1111. X            if (type == 3 || (type == 1 && c == TAB && State == NORMAL && !p_list))
  1112. X                --incr;
  1113. X            else
  1114. X                break;
  1115. X        }
  1116. X        vcol += incr;
  1117. X    }
  1118. X    return vcol;
  1119. X}
  1120. X
  1121. X    void
  1122. Xscrolldown(nlines)
  1123. X    long    nlines;
  1124. X{
  1125. X    register long    done = 0;    /* total # of physical lines done */
  1126. X
  1127. X    /* Scroll up 'nlines' lines. */
  1128. X    while (nlines--)
  1129. X    {
  1130. X        if (Topline == 1)
  1131. X            break;
  1132. X        done += plines(--Topline);
  1133. X    }
  1134. X    /*
  1135. X     * Compute the row number of the last row of the cursor line
  1136. X     * and move it onto the screen.
  1137. X     */
  1138. X    Cursrow += done + plines(Curpos.lnum) - 1 - Cursvcol / Columns;
  1139. X    while (Cursrow >= Rows - 1 && Curpos.lnum > 1)
  1140. X        Cursrow -= plines(Curpos.lnum--);
  1141. X}
  1142. X
  1143. X    void
  1144. Xscrollup(nlines)
  1145. X    long    nlines;
  1146. X{
  1147. X#ifdef NEVER
  1148. X    register long    done = 0;    /* total # of physical lines done */
  1149. X
  1150. X    /* Scroll down 'nlines' lines. */
  1151. X    while (nlines--)
  1152. X    {
  1153. X        if (Topline == line_count)
  1154. X            break;
  1155. X        done += plines(Topline);
  1156. X        if (Curpos.lnum == Topline)
  1157. X            ++Curpos.lnum;
  1158. X        ++Topline;
  1159. X    }
  1160. X    s_del(0, done, TRUE);
  1161. X#endif
  1162. X    Topline += nlines;
  1163. X    if (Topline > line_count)
  1164. X        Topline = line_count;
  1165. X    if (Curpos.lnum < Topline)
  1166. X        Curpos.lnum = Topline;
  1167. X}
  1168. X
  1169. X/*
  1170. X * The rest of the routines in this file perform screen manipulations. The
  1171. X * given operation is performed physically on the screen. The corresponding
  1172. X * change is also made to the internal screen image. In this way, the editor
  1173. X * anticipates the effect of editing changes on the appearance of the screen.
  1174. X * That way, when we call screenupdate a complete redraw isn't usually
  1175. X * necessary. Another advantage is that we can keep adding code to anticipate
  1176. X * screen changes, and in the meantime, everything still works.
  1177. X */
  1178. X
  1179. X/*
  1180. X * s_ins(row, nlines, invalid) - insert 'nlines' lines at 'row'
  1181. X * if 'invalid' is TRUE the LineNumbers[] is invalidated.
  1182. X * Returns 0 if the lines are not inserted, 1 for success.
  1183. X */
  1184. X    int
  1185. Xs_ins(row, nlines, invalid)
  1186. X    int         row;
  1187. X    int         nlines;
  1188. X    int            invalid;
  1189. X{
  1190. X    int         i;
  1191. X    int         j;
  1192. X    u_char        *temp;
  1193. X
  1194. X    screenalloc();        /* allocate screen buffers if size changed */
  1195. X
  1196. X    if (Nextscreen == NULL)
  1197. X        return 0;
  1198. X
  1199. X    if (invalid)
  1200. X        NumLineSizes = 0;
  1201. X
  1202. X    if (nlines > (Rows - 1 - row))
  1203. X        nlines = Rows - 1 - row;
  1204. X
  1205. X    if (RedrawingDisabled || nlines <= 0 ||
  1206. X                        ((T_CIL == NULL || *T_CIL == NUL) &&
  1207. X                        (T_IL == NULL || *T_IL == NUL) &&
  1208. X                        (T_SR == NULL || *T_SR == NUL || row != 0)))
  1209. X        return 0;
  1210. X    
  1211. X    if (Rows - nlines < 5)    /* only a few lines left: redraw is faster */
  1212. X    {
  1213. X        screenclear();        /* will set NumLineSizes to 0 */
  1214. X        return 0;
  1215. X    }
  1216. X
  1217. X    /*
  1218. X     * It "looks" better if we do all the inserts at once
  1219. X     */
  1220. X    if (T_CIL && *T_CIL) 
  1221. X    {
  1222. X        windgoto(row, 0);
  1223. X        if (nlines == 1 && T_IL && *T_IL)
  1224. X            outstr(T_IL);
  1225. X        else
  1226. X            outstr(tgoto(T_CIL, 0, nlines));
  1227. X    }
  1228. X    else
  1229. X    {
  1230. X        for (i = 0; i < nlines; i++) 
  1231. X        {
  1232. X            if (i == 0 || row != 0)
  1233. X                windgoto(row, 0);
  1234. X            if (T_IL && *T_IL)
  1235. X                outstr(T_IL);
  1236. X            else
  1237. X                outstr(T_SR);
  1238. X        }
  1239. X    }
  1240. X    windgoto((int)Rows - 1, 0);        /* delete any garbage that may have */
  1241. X    clear_line();                    /* been shifted to the bottom line */
  1242. X    redraw_msg = TRUE;
  1243. X
  1244. X    /*
  1245. X     * Now shift LinePointers nlines down to reflect the inserted lines.
  1246. X     * Clear the inserted lines.
  1247. X     */
  1248. X    for (i = 0; i < nlines; ++i)
  1249. X    {
  1250. X        j = Rows - 2 - i;
  1251. X        temp = LinePointers[j];
  1252. X        while ((j -= nlines) >= row)
  1253. X                LinePointers[j + nlines] = LinePointers[j];
  1254. X        LinePointers[j + nlines] = temp;
  1255. X        memset(temp, ' ', (size_t)Columns);
  1256. X    }
  1257. X    return 1;
  1258. X}
  1259. X
  1260. X/*
  1261. X * s_del(row, nlines, invalid) - delete 'nlines' lines at 'row'
  1262. X * If 'invalid' is TRUE LineNumbers[] is ivalidated.
  1263. X * Return 1 for success, 0 if the lines are not deleted.
  1264. X */
  1265. X    int
  1266. Xs_del(row, nlines, invalid)
  1267. X    int             row;
  1268. X    int             nlines;
  1269. X    int            invalid;
  1270. X{
  1271. X    int             j;
  1272. X    int             i;
  1273. X    u_char        *temp;
  1274. X
  1275. X    screenalloc();        /* allocate screen buffers if size changed */
  1276. X
  1277. X    if (Nextscreen == NULL)
  1278. X        return 0;
  1279. X
  1280. X    if (invalid)
  1281. X        NumLineSizes = 0;
  1282. X
  1283. X    if (nlines > (Rows - 1 - row))
  1284. X        nlines = Rows - 1 - row;
  1285. X
  1286. X    if (RedrawingDisabled || nlines <= 0 ||
  1287. X                ((T_DL == NULL || *T_DL == NUL) &&
  1288. X                (T_CDL == NULL || *T_CDL == NUL) &&
  1289. X                row != 0))
  1290. X        return 0;
  1291. X
  1292. X    if (Rows - nlines < 5)    /* only a few lines left: redraw is faster */
  1293. X    {
  1294. X        screenclear();        /* will set NumLineSizes to 0 */
  1295. X        return 0;
  1296. X    }
  1297. X
  1298. X    windgoto((int)Rows - 1, 0);        /* delete any garbage that may be */
  1299. X    clear_line();                    /* on the bottom line */
  1300. X    redraw_msg = TRUE;
  1301. X
  1302. X    /* delete the lines */
  1303. X    if (T_CDL && *T_CDL) 
  1304. X    {
  1305. X        windgoto(row, 0);
  1306. X        if (nlines == 1 && T_DL && *T_DL)
  1307. X            outstr(T_DL);
  1308. X        else
  1309. X            outstr(tgoto(T_CDL, 0, nlines));
  1310. X    } 
  1311. X    else
  1312. X    {
  1313. X        if (row == 0)
  1314. X        {
  1315. X            for (i = 0; i < nlines; i++) 
  1316. X                outchar('\n');
  1317. X        }
  1318. X        else
  1319. X        {
  1320. X            for (i = 0; i < nlines; i++) 
  1321. X            {
  1322. X                windgoto(row, 0);
  1323. X                outstr(T_DL);           /* delete a line */
  1324. X            }
  1325. X        }
  1326. X    }
  1327. X
  1328. X    /*
  1329. X     * Now shift LinePointers nlines up to reflect the deleted lines.
  1330. X     * Clear the deleted lines.
  1331. X     */
  1332. X    for (i = 0; i < nlines; ++i)
  1333. X    {
  1334. X        j = row + i;
  1335. X        temp = LinePointers[j];
  1336. X        while ((j += nlines) < Rows - 1)
  1337. X                LinePointers[j - nlines] = LinePointers[j];
  1338. X        LinePointers[j - nlines] = temp;
  1339. X        memset(temp, ' ', (size_t)Columns);
  1340. X    }
  1341. X    return 1;
  1342. X}
  1343. X
  1344. X    void
  1345. Xshowmode()
  1346. X{
  1347. X        if ((p_mo && (State == INSERT || State == REPLACE)) || Recording)
  1348. X        {
  1349. X                gotocmdline(TRUE, NUL);
  1350. X                if (p_mo)
  1351. X                {
  1352. X                    if (State == INSERT)
  1353. X                        outstrn("-- INSERT --");
  1354. X                    if (State == REPLACE)
  1355. X                        outstrn("-- REPLACE --");
  1356. X                }
  1357. X                if (Recording)
  1358. X                        outstrn("recording");
  1359. X        }
  1360. X        showruler(1);
  1361. X}
  1362. X
  1363. X/*
  1364. X * delete mode message
  1365. X */
  1366. X    void
  1367. Xdelmode()
  1368. X{
  1369. X    if (Recording)
  1370. X        msg("recording");
  1371. X    else
  1372. X        msg("");
  1373. X}
  1374. X
  1375. X/*
  1376. X * if ruler option is set: show current cursor position
  1377. X * if always is FALSE, only print if position has changed
  1378. X */
  1379. X    void
  1380. Xshowruler(always)
  1381. X    int        always;
  1382. X{
  1383. X    static linenr_t    oldlnum = 0;
  1384. X    static colnr_t    oldcol = 0;
  1385. X    static int        oldlen = 0;
  1386. X    int                newlen;
  1387. X    char            buffer[20];
  1388. X
  1389. X    if (p_ru && (redraw_msg || always || Curpos.lnum != oldlnum || Cursvcol != oldcol))
  1390. X    {
  1391. X        windgoto((int)Rows - 1, (int)Columns - 22);
  1392. X        /*
  1393. X         * Some sprintfs return the lenght, some return a pointer.
  1394. X         * To avoid portability problems we use strlen here.
  1395. X         */
  1396. X        sprintf(buffer, "%ld,%d", Curpos.lnum, Cursvcol + 1);
  1397. X        newlen = strlen(buffer);
  1398. X        outstrn(buffer);
  1399. X        while (newlen < oldlen)
  1400. X        {
  1401. X            outchar(' ');
  1402. X            --oldlen;
  1403. X        }
  1404. X        oldlen = newlen;
  1405. X        oldlnum = Curpos.lnum;
  1406. X        oldcol = Cursvcol;
  1407. X        redraw_msg = FALSE;
  1408. X    }
  1409. X}
  1410. X
  1411. X/*
  1412. X * Clear a line. The cursor must be at the first char of the line.
  1413. X */
  1414. X    void
  1415. Xclear_line()
  1416. X{
  1417. X    register int i;
  1418. X
  1419. X    if (T_EL != NULL && *T_EL != NUL)
  1420. X        outstr(T_EL);
  1421. X    else
  1422. X        for (i = 1; i < Columns; ++i)
  1423. X            outchar(' ');
  1424. X}
  1425. X
  1426. END_OF_FILE
  1427. if test 29501 -ne `wc -c <'vim/src/screen.c'`; then
  1428.     echo shar: \"'vim/src/screen.c'\" unpacked with wrong size!
  1429. fi
  1430. # end of 'vim/src/screen.c'
  1431. fi
  1432. echo shar: End of archive 16 \(of 23\).
  1433. cp /dev/null ark16isdone
  1434. MISSING=""
  1435. for I in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 ; do
  1436.     if test ! -f ark${I}isdone ; then
  1437.     MISSING="${MISSING} ${I}"
  1438.     fi
  1439. done
  1440. if test "${MISSING}" = "" ; then
  1441.     echo You have unpacked all 23 archives.
  1442.     rm -f ark[1-9]isdone ark[1-9][0-9]isdone
  1443. else
  1444.     echo You still need to unpack the following archives:
  1445.     echo "        " ${MISSING}
  1446. fi
  1447. ##  End of shell archive.
  1448. exit 0
  1449. -------------8<----------------8<----------------8<---------------8<--------
  1450. Bram Moolenaar                             | DISCLAIMER:  This  note  does  not
  1451. Oce Nederland B.V., Research & Development | necessarily represent the position
  1452. p.o. box 101, 5900 MA  Venlo               | of  Oce-Nederland  B.V.  Therefore
  1453. The Netherlands        phone +31 77 594077 | no liability or responsibility for
  1454. UUCP: mool@oce.nl        fax +31 77 595450 | whatever will be accepted.
  1455.  
  1456. exit 0 # Just in case...
  1457.