home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 October / usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso / misc / volume41 / vim / part17 < prev    next >
Text File  |  1993-12-21  |  37KB  |  1,565 lines

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