home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 October / usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso / misc / volume44 / vim / part07 < prev    next >
Encoding:
Internet Message Format  |  1994-08-16  |  68.3 KB

  1. From: mool@oce.nl (Bram Moolenaar)
  2. Newsgroups: comp.sources.misc
  3. Subject: v44i026:  vim - Vi IMproved editor, v3.0, Part07/26
  4. Date: 16 Aug 1994 21:17:56 -0500
  5. Organization: Sterling Software
  6. Sender: kent@sparky.sterling.com
  7. Approved: kent@sparky.sterling.com
  8. Message-ID: <32rs0k$kcm@sparky.sterling.com>
  9. X-Md4-Signature: 327b850d2f6314ae9071ae181a1ec6c9
  10.  
  11. Submitted-by: mool@oce.nl (Bram Moolenaar)
  12. Posting-number: Volume 44, Issue 26
  13. Archive-name: vim/part07
  14. Environment: UNIX, AMIGA, MS-DOS, Windows NT
  15. Supersedes: vim: Volume 41, Issue 50-75
  16.  
  17. #! /bin/sh
  18. # This is a shell archive.  Remove anything before this line, then feed it
  19. # into a shell via "sh file" or similar.  To overwrite existing files,
  20. # type "sh file -c".
  21. # Contents:  vim/src/screen.c vim/src/tcconfig.tc.UU vim/src/version.c
  22. # Wrapped by kent@sparky on Mon Aug 15 21:44:01 1994
  23. PATH=/bin:/usr/bin:/usr/ucb:/usr/local/bin:/usr/lbin:$PATH ; export PATH
  24. echo If this archive is complete, you will see the following message:
  25. echo '          "shar: End of archive 7 (of 26)."'
  26. if test -f 'vim/src/screen.c' -a "${1}" != "-c" ; then 
  27.   echo shar: Will not clobber existing file \"'vim/src/screen.c'\"
  28. else
  29.   echo shar: Extracting \"'vim/src/screen.c'\" \(46442 characters\)
  30.   sed "s/^X//" >'vim/src/screen.c' <<'END_OF_FILE'
  31. X/* vi:ts=4:sw=4
  32. X *
  33. X * VIM - Vi IMproved        by Bram Moolenaar
  34. X *
  35. X * Read the file "credits.txt" for a list of people who contributed.
  36. X * Read the file "uganda.txt" for copying and usage conditions.
  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 char_u     *Nextscreen = NULL;     /* What is currently on the screen. */
  51. Xstatic char_u     **LinePointers = NULL;    /* array of pointers into Nextscreen */
  52. X
  53. X/*
  54. X * Cline_height is set (in cursupdate) to the number of physical
  55. X * lines taken by the line the cursor is on. We use this to avoid extra calls
  56. X * to plines(). The optimized routine updateline()
  57. X * makes sure that the size of the cursor line hasn't changed. If so, lines
  58. X * below the cursor will move up or down and we need to call the routine
  59. X * updateScreen() to examine the entire screen.
  60. X */
  61. Xstatic int        Cline_height;            /* current size of cursor line */
  62. X
  63. Xstatic int        Cline_row;                /* starting row of the cursor line on screen */
  64. X
  65. Xstatic FPOS        old_cursor = {0, 0};    /* last known end of visual part */
  66. Xstatic int        oldCurswant = 0;        /* last known value of Curswant */
  67. Xstatic int        canopt;                    /* TRUE when cursor goto can be optimized */
  68. Xstatic int        invert = 0;                /* set to INVERTCODE when inverting */
  69. X
  70. X#define INVERTCODE        0x80
  71. X
  72. Xstatic int win_line __ARGS((WIN *, linenr_t, int, int));
  73. Xstatic void screen_char __ARGS((char_u *, int, int));
  74. Xstatic void screenalloc __ARGS((int));
  75. Xstatic void screenclear2 __ARGS((void));
  76. Xstatic int screen_ins_lines __ARGS((int, int, int, int));
  77. X
  78. X/*
  79. X * updateline() - like updateScreen() but only for cursor line
  80. X *
  81. X * This determines whether or not we need to call updateScreen() to examine
  82. X * the entire screen for changes. This occurs if the size of the cursor line
  83. X * (in rows) hasn't changed.
  84. X */
  85. X    void
  86. Xupdateline()
  87. X{
  88. X    int         row;
  89. X    int         n;
  90. X
  91. X    if (must_redraw)        /* must redraw whole screen */
  92. X    {
  93. X        updateScreen(must_redraw);
  94. X        return;
  95. X    }
  96. X
  97. X    screenalloc(TRUE);        /* allocate screen buffers if size changed */
  98. X
  99. X    if (Nextscreen == NULL || RedrawingDisabled)
  100. X        return;
  101. X
  102. X    screen_start();            /* init cursor position of screen_char() */
  103. X    cursor_off();
  104. X
  105. X    (void)set_highlight('v');
  106. X    row = win_line(curwin, curwin->w_cursor.lnum, Cline_row, curwin->w_height);
  107. X
  108. X    if (row == curwin->w_height + 1)            /* line too long for window */
  109. X        updateScreen(VALID_TO_CURSCHAR);
  110. X    else
  111. X    {
  112. X        n = row - Cline_row;
  113. X        if (n != Cline_height)        /* line changed size */
  114. X        {
  115. X            if (n < Cline_height)     /* got smaller: delete lines */
  116. X                win_del_lines(curwin, row, Cline_height - n, FALSE, TRUE);
  117. X            else                    /* got bigger: insert lines */
  118. X                win_ins_lines(curwin, Cline_row + Cline_height, n - Cline_height, FALSE, TRUE);
  119. X            updateScreen(VALID_TO_CURSCHAR);
  120. X        }
  121. X    }
  122. X}
  123. X
  124. X/*
  125. X * updateScreen()
  126. X *
  127. X * Based on the current value of curwin->w_topline, transfer a screenfull
  128. X * of stuff from Filemem to Nextscreen, and update curwin->w_botline.
  129. X */
  130. X
  131. X    void
  132. XupdateScreen(type)
  133. X    int             type;
  134. X{
  135. X    WIN                *wp;
  136. X
  137. X    screenalloc(TRUE);        /* allocate screen buffers if size changed */
  138. X    if (Nextscreen == NULL)
  139. X        return;
  140. X
  141. X    if (must_redraw)
  142. X    {
  143. X        if (type < must_redraw)        /* use maximal type */
  144. X            type = must_redraw;
  145. X        must_redraw = 0;
  146. X    }
  147. X
  148. X    if (type == CURSUPD)        /* update cursor and then redraw NOT_VALID*/
  149. X    {
  150. X        curwin->w_lsize_valid = 0;
  151. X        cursupdate();            /* will call updateScreen() */
  152. X        return;
  153. X    }
  154. X    if (curwin->w_lsize_valid == 0 && type != CLEAR)
  155. X        type = NOT_VALID;
  156. X
  157. X     if (RedrawingDisabled)
  158. X    {
  159. X        must_redraw = type;        /* remember type for next time */
  160. X        return;
  161. X    }
  162. X
  163. X    /*
  164. X     * if the screen was scrolled up when displaying a message, scroll it down
  165. X     */
  166. X    if (msg_scrolled)
  167. X    {
  168. X        clear_cmdline = TRUE;
  169. X        if (msg_scrolled > Rows - 5)        /* clearing is faster */
  170. X            type = CLEAR;
  171. X        else if (type != CLEAR)
  172. X        {
  173. X            if (screen_ins_lines(0, 0, msg_scrolled, (int)Rows) == FAIL)
  174. X                type = CLEAR;
  175. X            win_rest_invalid(firstwin);        /* should do only first/last few */
  176. X        }
  177. X        msg_scrolled = 0;
  178. X    }
  179. X
  180. X    /*
  181. X     * reset cmdline_row now (may have been changed temporarily)
  182. X     */
  183. X    compute_cmdrow();
  184. X
  185. X    if (type == CLEAR)            /* first clear screen */
  186. X    {
  187. X        screenclear();            /* will reset clear_cmdline */
  188. X        type = NOT_VALID;
  189. X    }
  190. X
  191. X    if (clear_cmdline)
  192. X        gotocmdline(TRUE, NUL);    /* first clear cmdline */
  193. X
  194. X/* return if there is nothing to do */
  195. X    if ((type == VALID && curwin->w_topline == curwin->w_lsize_lnum[0]) ||
  196. X            (type == INVERTED && old_cursor.lnum == curwin->w_cursor.lnum &&
  197. X                    old_cursor.col == curwin->w_cursor.col && curwin->w_curswant == oldCurswant))
  198. X        return;
  199. X
  200. X    curwin->w_redr_type = type;
  201. X
  202. X/*
  203. X * go from top to bottom through the windows, redrawing the ones that need it
  204. X */
  205. X    cursor_off();
  206. X    for (wp = firstwin; wp; wp = wp->w_next)
  207. X    {
  208. X        if (wp->w_redr_type)
  209. X            win_update(wp);
  210. X        if (wp->w_redr_status)
  211. X            win_redr_status(wp);
  212. X    }
  213. X    if (redraw_cmdline)
  214. X        showmode();
  215. X}
  216. X
  217. X/*
  218. X * update a single window
  219. X *
  220. X * This may cause the windows below it also to be redrawn
  221. X */
  222. X    void
  223. Xwin_update(wp)
  224. X    WIN        *wp;
  225. X{
  226. X    int                type = wp->w_redr_type;
  227. X    register int    row;
  228. X    register int    endrow;
  229. X    linenr_t        lnum;
  230. X    linenr_t        lastline = 0; /* only valid if endrow != Rows -1 */
  231. X    int                done;        /* if TRUE, we hit the end of the file */
  232. X    int                didline;    /* if TRUE, we finished the last line */
  233. X    int             srow = 0;    /* starting row of the current line */
  234. X    int             idx;
  235. X    int             i;
  236. X    long             j;
  237. X
  238. X    if (type == NOT_VALID)
  239. X    {
  240. X        wp->w_redr_status = TRUE;
  241. X        wp->w_lsize_valid = 0;
  242. X    }
  243. X
  244. X    idx = 0;
  245. X    row = 0;
  246. X    lnum = wp->w_topline;
  247. X
  248. X    /* The number of rows shown is w_height. */
  249. X    /* The default last row is the status/command line. */
  250. X    endrow = wp->w_height;
  251. X
  252. X    if (type == VALID || type == VALID_TO_CURSCHAR)
  253. X    {
  254. X        /*
  255. X         * We handle two special cases:
  256. X         * 1: we are off the top of the screen by a few lines: scroll down
  257. X         * 2: wp->w_topline is below wp->w_lsize_lnum[0]: may scroll up
  258. X         */
  259. X        if (wp->w_topline < wp->w_lsize_lnum[0])    /* may scroll down */
  260. X        {
  261. X            j = wp->w_lsize_lnum[0] - wp->w_topline;
  262. X            if (j < wp->w_height - 2)                /* not too far off */
  263. X            {
  264. X                lastline = wp->w_lsize_lnum[0] - 1;
  265. X                i = plines_m_win(wp, wp->w_topline, lastline);
  266. X                if (i < wp->w_height - 2)        /* less than a screen off */
  267. X                {
  268. X                    /*
  269. X                     * Try to insert the correct number of lines.
  270. X                     * If not the last window, delete the lines at the bottom.
  271. X                     * win_ins_lines may fail.
  272. X                     */
  273. X                    if (win_ins_lines(wp, 0, i, FALSE, wp == firstwin) == OK &&
  274. X                                                    wp->w_lsize_valid)
  275. X                    {
  276. X                        endrow = i;
  277. X
  278. X                        if ((wp->w_lsize_valid += j) > wp->w_height)
  279. X                            wp->w_lsize_valid = wp->w_height;
  280. X                        for (idx = wp->w_lsize_valid; idx - j >= 0; idx--)
  281. X                        {
  282. X                            wp->w_lsize_lnum[idx] = wp->w_lsize_lnum[idx - j];
  283. X                            wp->w_lsize[idx] = wp->w_lsize[idx - j];
  284. X                        }
  285. X                        idx = 0;
  286. X                    }
  287. X                }
  288. X                else if (lastwin == firstwin)    /* far off: clearing the screen is faster */
  289. X                    screenclear();
  290. X            }
  291. X            else if (lastwin == firstwin)    /* far off: clearing the screen is faster */
  292. X                screenclear();
  293. X        }
  294. X        else                            /* may scroll up */
  295. X        {
  296. X            j = -1;
  297. X            for (i = 0; i < wp->w_lsize_valid; i++) /* try to find wp->w_topline in wp->w_lsize_lnum[] */
  298. X            {
  299. X                if (wp->w_lsize_lnum[i] == wp->w_topline)
  300. X                {
  301. X                    j = i;
  302. X                    break;
  303. X                }
  304. X                row += wp->w_lsize[i];
  305. X            }
  306. X            if (j == -1)    /* wp->w_topline is not in wp->w_lsize_lnum */
  307. X            {
  308. X                row = 0;
  309. X                if (lastwin == firstwin)
  310. X                    screenclear();   /* far off: clearing the screen is faster */
  311. X            }
  312. X            else
  313. X            {
  314. X                /*
  315. X                 * Try to delete the correct number of lines.
  316. X                 * wp->w_topline is at wp->w_lsize_lnum[i].
  317. X                 */
  318. X                if ((row == 0 || win_del_lines(wp, 0, row, FALSE, wp == firstwin) == OK) && wp->w_lsize_valid)
  319. X                {
  320. X                    srow = row;
  321. X                    row = 0;
  322. X                    for (;;)
  323. X                    {
  324. X                        if (type == VALID_TO_CURSCHAR && lnum == wp->w_cursor.lnum)
  325. X                                break;
  326. X                        if (row + srow + (int)wp->w_lsize[j] >= wp->w_height)
  327. X                                break;
  328. X                        wp->w_lsize[idx] = wp->w_lsize[j];
  329. X                        wp->w_lsize_lnum[idx] = lnum++;
  330. X
  331. X                        row += wp->w_lsize[idx++];
  332. X                        if ((int)++j >= wp->w_lsize_valid)
  333. X                            break;
  334. X                    }
  335. X                    wp->w_lsize_valid = idx;
  336. X                }
  337. X                else
  338. X                    row = 0;        /* update all lines */
  339. X            }
  340. X        }
  341. X        if (endrow == wp->w_height && idx == 0)     /* no scrolling */
  342. X                wp->w_lsize_valid = 0;
  343. X    }
  344. X
  345. X    done = didline = FALSE;
  346. X    screen_start();    /* init cursor position of screen_char() */
  347. X
  348. X    if (VIsual.lnum)                /* check if we are updating the inverted part */
  349. X    {
  350. X        linenr_t    from, to;
  351. X
  352. X    /* find the line numbers that need to be updated */
  353. X        if (wp->w_cursor.lnum < old_cursor.lnum)
  354. X        {
  355. X            from = wp->w_cursor.lnum;
  356. X            to = old_cursor.lnum;
  357. X        }
  358. X        else
  359. X        {
  360. X            from = old_cursor.lnum;
  361. X            to = wp->w_cursor.lnum;
  362. X        }
  363. X    /* if in block mode and changed column or wp->w_curswant: update all lines */
  364. X        if (Visual_block && (wp->w_cursor.col != old_cursor.col || wp->w_curswant != oldCurswant))
  365. X        {
  366. X            if (from > VIsual.lnum)
  367. X                from = VIsual.lnum;
  368. X            if (to < VIsual.lnum)
  369. X                to = VIsual.lnum;
  370. X        }
  371. X
  372. X        if (from < wp->w_topline)
  373. X            from = wp->w_topline;
  374. X        if (to >= wp->w_botline)
  375. X            to = wp->w_botline - 1;
  376. X
  377. X    /* find the minimal part to be updated */
  378. X        if (type == INVERTED)
  379. X        {
  380. X            while (lnum < from)                        /* find start */
  381. X            {
  382. X                row += wp->w_lsize[idx++];
  383. X                ++lnum;
  384. X            }
  385. X            srow = row;
  386. X            for (j = idx; j < wp->w_lsize_valid; ++j)    /* find end */
  387. X            {
  388. X                if (wp->w_lsize_lnum[j] == to + 1)
  389. X                {
  390. X                    endrow = srow;
  391. X                    break;
  392. X                }
  393. X                srow += wp->w_lsize[j];
  394. X            }
  395. X            old_cursor = wp->w_cursor;
  396. X            oldCurswant = wp->w_curswant;
  397. X        }
  398. X    /* if we update the lines between from and to set old_cursor */
  399. X        else if (lnum <= from && (endrow == wp->w_height || lastline >= to))
  400. X        {
  401. X            old_cursor = wp->w_cursor;
  402. X            oldCurswant = wp->w_curswant;
  403. X        }
  404. X    }
  405. X
  406. X    (void)set_highlight('v');
  407. X
  408. X    /*
  409. X     * Update the screen rows from "row" to "endrow".
  410. X     * Start at line "lnum" which is at wp->w_lsize_lnum[idx].
  411. X     */
  412. X    for (;;)
  413. X    {
  414. X        if (lnum > wp->w_buffer->b_ml.ml_line_count)        /* hit the end of the file */
  415. X        {
  416. X            done = TRUE;
  417. X            break;
  418. X        }
  419. X        srow = row;
  420. X        row = win_line(wp, lnum, srow, endrow);
  421. X        if (row > endrow)    /* past end of screen */
  422. X        {
  423. X            wp->w_lsize[idx] = plines_win(wp, lnum);    /* we may need the size of that */
  424. X            wp->w_lsize_lnum[idx++] = lnum;        /* too long line later on */
  425. X            break;
  426. X        }
  427. X
  428. X        wp->w_lsize[idx] = row - srow;
  429. X        wp->w_lsize_lnum[idx++] = lnum;
  430. X        if (++lnum > wp->w_buffer->b_ml.ml_line_count)
  431. X        {
  432. X            done = TRUE;
  433. X            break;
  434. X        }
  435. X
  436. X        if (row == endrow)
  437. X        {
  438. X            didline = TRUE;
  439. X            break;
  440. X        }
  441. X    }
  442. X    if (idx > wp->w_lsize_valid)
  443. X        wp->w_lsize_valid = idx;
  444. X
  445. X    /* Do we have to do off the top of the screen processing ? */
  446. X    if (endrow != wp->w_height)
  447. X    {
  448. X        row = 0;
  449. X        for (idx = 0; idx < wp->w_lsize_valid && row < wp->w_height; idx++)
  450. X            row += wp->w_lsize[idx];
  451. X
  452. X        if (row < wp->w_height)
  453. X        {
  454. X            done = TRUE;
  455. X        }
  456. X        else if (row > wp->w_height)        /* Need to blank out the last line */
  457. X        {
  458. X            lnum = wp->w_lsize_lnum[idx - 1];
  459. X            srow = row - wp->w_lsize[idx - 1];
  460. X            didline = FALSE;
  461. X        }
  462. X        else
  463. X        {
  464. X            lnum = wp->w_lsize_lnum[idx - 1] + 1;
  465. X            didline = TRUE;
  466. X        }
  467. X    }
  468. X
  469. X    wp->w_empty_rows = 0;
  470. X    /*
  471. X     * If we didn't hit the end of the file, and we didn't finish the last
  472. X     * line we were working on, then the line didn't fit.
  473. X     */
  474. X    if (!done && !didline)
  475. X    {
  476. X        if (lnum == wp->w_topline)
  477. X        {
  478. X            /*
  479. X             * Single line that does not fit!
  480. X             * Fill last line with '@' characters.
  481. X             */
  482. X            screen_fill(wp->w_winpos + wp->w_height - 1, wp->w_winpos + wp->w_height, 0, (int)Columns, '@', '@');
  483. X            wp->w_botline = lnum + 1;
  484. X        }
  485. X        else
  486. X        {
  487. X            /*
  488. X             * Clear the rest of the screen and mark the unused lines.
  489. X             */
  490. X            screen_fill(wp->w_winpos + srow, wp->w_winpos + wp->w_height, 0, (int)Columns, '@', ' ');
  491. X            wp->w_botline = lnum;
  492. X            wp->w_empty_rows = wp->w_height - srow;
  493. X        }
  494. X    }
  495. X    else
  496. X    {
  497. X        /* make sure the rest of the screen is blank */
  498. X        /* put '~'s on rows that aren't part of the file. */
  499. X        screen_fill(wp->w_winpos + row, wp->w_winpos + wp->w_height, 0, (int)Columns, '~', ' ');
  500. X        wp->w_empty_rows = wp->w_height - row;
  501. X
  502. X        if (done)                /* we hit the end of the file */
  503. X            wp->w_botline = wp->w_buffer->b_ml.ml_line_count + 1;
  504. X        else
  505. X            wp->w_botline = lnum;
  506. X    }
  507. X
  508. X    wp->w_redr_type = 0;
  509. X}
  510. X
  511. X/*
  512. X * mark all status lines for redraw; used after first :cd
  513. X */
  514. X    void
  515. Xstatus_redraw_all()
  516. X{
  517. X    WIN        *wp;
  518. X
  519. X    for (wp = firstwin; wp; wp = wp->w_next)
  520. X        wp->w_redr_status = TRUE;
  521. X    updateScreen(NOT_VALID);
  522. X}
  523. X
  524. X/*
  525. X * Redraw the status line of window wp.
  526. X *
  527. X * If inversion is possible we use it. Else '=' characters are used.
  528. X */
  529. X    void
  530. Xwin_redr_status(wp)
  531. X    WIN        *wp;
  532. X{
  533. X    int        row;
  534. X    int        col;
  535. X    char_u    *p;
  536. X    int        len;
  537. X    int        fillchar;
  538. X
  539. X    if (wp->w_status_height)                    /* if there is a status line */
  540. X    {
  541. X        if (set_highlight('s') == OK)            /* can highlight */
  542. X        {
  543. X            fillchar = ' ';
  544. X            start_highlight();
  545. X        }
  546. X        else                                    /* can't highlight, use '=' */
  547. X            fillchar = '=';
  548. X
  549. X        screen_start();            /* init cursor position */
  550. X        row = wp->w_winpos + wp->w_height;
  551. X        col = 0;
  552. X        p = wp->w_buffer->b_xfilename;
  553. X        if (p == NULL)
  554. X            p = (char_u *)"[No File]";
  555. X        else
  556. X        {
  557. X            home_replace(p, NameBuff, MAXPATHL);
  558. X            p = NameBuff;
  559. X        }
  560. X        len = STRLEN(p);
  561. X        if (wp->w_buffer->b_changed)
  562. X            len += 4;
  563. X        if (len > ru_col - 1)
  564. X        {
  565. X            screen_outchar('<', row, 0);
  566. X            p += len - (ru_col - 1) + 1;
  567. X            len = (ru_col - 1);
  568. X            col = 1;
  569. X        }
  570. X        screen_msg(p, row, col);
  571. X        if (wp->w_buffer->b_changed)
  572. X            screen_msg((char_u *)" [+]", row, len - 4);
  573. X        screen_fill(row, row + 1, len, ru_col, fillchar, fillchar);
  574. X
  575. X        stop_highlight();
  576. X        win_redr_ruler(wp, TRUE);
  577. X    }
  578. X    else    /* no status line, can only be last window */
  579. X        redraw_cmdline = TRUE;
  580. X    wp->w_redr_status = FALSE;
  581. X}
  582. X
  583. X/*
  584. X * display line "lnum" of window 'wp' on the screen
  585. X * Start at row "startrow", stop when "endrow" is reached.
  586. X * Return the number of last row the line occupies.
  587. X */
  588. X
  589. X    static int
  590. Xwin_line(wp, lnum, startrow, endrow)
  591. X        WIN                *wp;
  592. X        linenr_t        lnum;
  593. X        int             startrow;
  594. X        int             endrow;
  595. X{
  596. X    char_u             *screenp;
  597. X    int                c;
  598. X    int                col;                /* visual column on screen */
  599. X    long            vcol;                /* visual column for tabs */
  600. X    int                row;                /* row in the window, excluding w_winpos */
  601. X    int                screen_row;            /* row on the screen, including w_winpos */
  602. X    char_u            *ptr;
  603. X    char_u            extra[16];            /* "%ld" must fit in here */
  604. X    char_u            *p_extra;
  605. X    int             n_extra;
  606. X    int                n_spaces = 0;
  607. X
  608. X    int                fromcol, tocol;        /* start/end of inverting */
  609. X    int                noinvcur = FALSE;    /* don't invert the cursor */
  610. X    int                temp;
  611. X    FPOS            *top, *bot;
  612. X
  613. X    row = startrow;
  614. X    screen_row = row + wp->w_winpos;
  615. X    col = 0;
  616. X    vcol = 0;
  617. X    fromcol = -10;
  618. X    tocol = MAXCOL;
  619. X    canopt = TRUE;
  620. X    if (VIsual.lnum && wp == curwin)            /* visual active in this window */
  621. X    {
  622. X        if (ltoreq(wp->w_cursor, VIsual))        /* Visual is after wp->w_cursor */
  623. X        {
  624. X            top = &wp->w_cursor;
  625. X            bot = &VIsual;
  626. X        }
  627. X        else                            /* Visual is before wp->w_cursor */
  628. X        {
  629. X            top = &VIsual;
  630. X            bot = &wp->w_cursor;
  631. X        }
  632. X        if (Visual_block)                        /* block mode */
  633. X        {
  634. X            if (lnum >= top->lnum && lnum <= bot->lnum)
  635. X            {
  636. X                fromcol = getvcol(wp, top, 2);
  637. X                temp = getvcol(wp, bot, 2);
  638. X                if (temp < fromcol)
  639. X                    fromcol = temp;
  640. X
  641. X                if (wp->w_curswant != MAXCOL)
  642. X                {
  643. X                    tocol = getvcol(wp, top, 3);
  644. X                    temp = getvcol(wp, bot, 3);
  645. X                    if (temp > tocol)
  646. X                        tocol = temp;
  647. X                    ++tocol;
  648. X                }
  649. X            }
  650. X        }
  651. X        else                            /* non-block mode */
  652. X        {
  653. X            if (lnum > top->lnum && lnum <= bot->lnum)
  654. X                fromcol = 0;
  655. X            else if (lnum == top->lnum)
  656. X                fromcol = getvcol(wp, top, 2);
  657. X            if (lnum == bot->lnum)
  658. X                tocol = getvcol(wp, bot, 3) + 1;
  659. X
  660. X            if (VIsual.col == VISUALLINE)        /* linewise */
  661. X            {
  662. X                if (fromcol > 0)
  663. X                    fromcol = 0;
  664. X                tocol = VISUALLINE;
  665. X            }
  666. X        }
  667. X            /* if the cursor can't be switched off, don't invert the character
  668. X                        where the cursor is */
  669. X        if ((T_CI == NULL || *T_CI == NUL) && lnum == wp->w_cursor.lnum)
  670. X            noinvcur = TRUE;
  671. X
  672. X        if (tocol <= wp->w_leftcol)            /* inverting is left of screen */
  673. X            fromcol = 0;
  674. X        else if (fromcol >= 0 && fromcol < wp->w_leftcol)    /* start of invert is left of screen */
  675. X            fromcol = wp->w_leftcol;
  676. X
  677. X        /* if inverting in this line, can't optimize cursor positioning */
  678. X        if (fromcol >= 0)
  679. X            canopt = FALSE;
  680. X    }
  681. X
  682. X    ptr = ml_get_buf(wp->w_buffer, lnum, FALSE);
  683. X    if (!wp->w_p_wrap)        /* advance to first character to be displayed */
  684. X    {
  685. X        while (vcol < wp->w_leftcol && *ptr)
  686. X            vcol += chartabsize(*ptr++, vcol);
  687. X        if (vcol > wp->w_leftcol)
  688. X        {
  689. X            n_spaces = vcol - wp->w_leftcol;    /* begin with some spaces */
  690. X            vcol = wp->w_leftcol;
  691. X        }
  692. X    }
  693. X    screenp = LinePointers[screen_row];
  694. X    if (wp->w_p_nu)
  695. X    {
  696. X        sprintf((char *)extra, "%7ld ", (long)lnum);
  697. X        p_extra = extra;
  698. X        n_extra = 8;
  699. X        vcol -= 8;        /* so vcol is 0 when line number has been printed */
  700. X    }
  701. X    else
  702. X    {
  703. X        p_extra = NULL;
  704. X        n_extra = 0;
  705. X    }
  706. X    for (;;)
  707. X    {
  708. X        if (!canopt)    /* Visual in this line */
  709. X        {
  710. X            if (((vcol == fromcol && !(noinvcur && vcol == wp->w_virtcol)) ||
  711. X                    (noinvcur && vcol == wp->w_virtcol + 1 && vcol >= fromcol)) &&
  712. X                    vcol < tocol)
  713. X                start_highlight();        /* start highlighting */
  714. X            else if (invert && (vcol == tocol || (noinvcur && vcol == wp->w_virtcol)))
  715. X                stop_highlight();        /* stop highlighting */
  716. X        }
  717. X
  718. X        /* Get the next character to put on the screen. */
  719. X        /*
  720. X         * The 'extra' array contains the extra stuff that is inserted to
  721. X         * represent special characters (non-printable stuff).
  722. X         */
  723. X
  724. X        if (n_extra)
  725. X        {
  726. X            c = *p_extra++;
  727. X            n_extra--;
  728. X        }
  729. X        else if (n_spaces)
  730. X        {
  731. X            c = ' ';
  732. X            n_spaces--;
  733. X        }
  734. X        else
  735. X        {
  736. X            if ((c = *ptr++) < ' ' || (c > '~' && c <= 0xa0))
  737. X            {
  738. X                /*
  739. X                 * when getting a character from the file, we may have to turn it
  740. X                 * into something else on the way to putting it into 'Nextscreen'.
  741. X                 */
  742. X                if (c == TAB && !wp->w_p_list)
  743. X                {
  744. X                    /* tab amount depends on current column */
  745. X                    n_spaces = (int)wp->w_buffer->b_p_ts - vcol % (int)wp->w_buffer->b_p_ts - 1;
  746. X                    c = ' ';
  747. X                }
  748. X                else if (c == NUL && wp->w_p_list)
  749. X                {
  750. X                    p_extra = (char_u *)"";
  751. X                    n_extra = 1;
  752. X                    c = '$';
  753. X                }
  754. X                else if (c != NUL)
  755. X                {
  756. X                    p_extra = transchar(c);
  757. X                    n_extra = charsize(c) - 1;
  758. X                    c = *p_extra++;
  759. X                }
  760. X            }
  761. X        }
  762. X
  763. X        if (c == NUL)
  764. X        {
  765. X            if (invert)
  766. X            {
  767. X                if (vcol == 0)    /* invert first char of empty line */
  768. X                {
  769. X                    if (*screenp != (' ' ^ INVERTCODE))
  770. X                    {
  771. X                            *screenp = (' ' ^ INVERTCODE);
  772. X                            screen_char(screenp, screen_row, col);
  773. X                    }
  774. X                    ++screenp;
  775. X                    ++col;
  776. X                }
  777. X                stop_highlight();
  778. X            }
  779. X            /* 
  780. X             * blank out the rest of this row, if necessary
  781. X             */
  782. X            while (col < Columns && *screenp == ' ')
  783. X            {
  784. X                ++screenp;
  785. X                ++col;
  786. X            }
  787. X            if (col < Columns)
  788. X            {
  789. X                screen_fill(screen_row, screen_row + 1, col, (int)Columns, ' ', ' ');
  790. X                col = Columns;
  791. X            }
  792. X            row++;
  793. X            screen_row++;
  794. X            break;
  795. X        }
  796. X        if (col >= Columns)
  797. X        {
  798. X            col = 0;
  799. X            ++row;
  800. X            ++screen_row;
  801. X            if (!wp->w_p_wrap)
  802. X                break;
  803. X            if (row == endrow)        /* line got too long for screen */
  804. X            {
  805. X                ++row;
  806. X                break;
  807. X            }
  808. X            screenp = LinePointers[screen_row];
  809. X        }
  810. X
  811. X        /*
  812. X         * Store the character in Nextscreen.
  813. X         * Be careful with characters where (c ^ INVERTCODE == ' '), they may be
  814. X         * confused with spaces inserted by scrolling.
  815. X         */
  816. X        if (*screenp != (c ^ invert) || c == (' ' ^ INVERTCODE))
  817. X        {
  818. X            *screenp = (c ^ invert);
  819. X            screen_char(screenp, screen_row, col);
  820. X        }
  821. X        ++screenp;
  822. X        col++;
  823. X        vcol++;
  824. X    }
  825. X
  826. X    if (invert)
  827. X        stop_highlight();
  828. X    return (row);
  829. X}
  830. X
  831. X/*
  832. X * output a single character directly to the screen
  833. X * update NextScreen
  834. X * Note: must do screen_start() before this!
  835. X */
  836. X    void
  837. Xscreen_outchar(c, row, col)
  838. X    int        c;
  839. X    int        row, col;
  840. X{
  841. X    char_u        buf[2];
  842. X
  843. X    buf[0] = c;
  844. X    buf[1] = NUL;
  845. X    screen_msg(buf, row, col);
  846. X}
  847. X    
  848. X/*
  849. X * put string '*msg' on the screen at position 'row' and 'col'
  850. X * update NextScreen
  851. X * Note: only outputs within one row, message is truncated at screen boundary!
  852. X * Note: must do screen_start() before this!
  853. X * Note: caller must make sure that row is valid!
  854. X */
  855. X    void
  856. Xscreen_msg(msg, row, col)
  857. X    char_u    *msg;
  858. X    int        row;
  859. X    int        col;
  860. X{
  861. X    char_u    *screenp;
  862. X
  863. X    screenp = LinePointers[row] + col;
  864. X    while (*msg && col < Columns)
  865. X    {
  866. X        if (*screenp != (*msg ^ invert) || *msg == (' ' ^ INVERTCODE))
  867. X        {
  868. X            *screenp = (*msg ^ invert);
  869. X            screen_char(screenp, row, col);
  870. X        }
  871. X        ++screenp;
  872. X        ++col;
  873. X        ++msg;
  874. X    }
  875. X}
  876. X
  877. X/*
  878. X * last cursor position known by screen_char
  879. X */
  880. Xstatic int    oldrow, oldcol;        /* old cursor position */
  881. X
  882. X/*
  883. X * reset cursor position. Use whenever cursor moved before calling screen_char.
  884. X */
  885. X    void
  886. Xscreen_start()
  887. X{
  888. X    oldcol = 9999;
  889. X}
  890. X
  891. X/*
  892. X * set_highlight - set highlight depending on 'highlight' option and context.
  893. X *
  894. X * return FAIL if highlighting is not possible, OK otherwise
  895. X */
  896. X    int
  897. Xset_highlight(context)
  898. X    int        context;
  899. X{
  900. X    int        len;
  901. X    int        i;
  902. X    int        mode;
  903. X
  904. X    len = STRLEN(p_hl);
  905. X    for (i = 0; i < len; i += 3)
  906. X        if (p_hl[i] == context)
  907. X            break;
  908. X    if (i < len)
  909. X        mode = p_hl[i + 1];
  910. X    else
  911. X        mode = 'i';
  912. X    switch (mode)
  913. X    {
  914. X        case 'b':    highlight = T_TB;        /* bold */
  915. X                    unhighlight = T_TP;
  916. X                    break;
  917. X        case 's':    highlight = T_SO;        /* standout */
  918. X                    unhighlight = T_SE;
  919. X                    break;
  920. X        case 'n':    highlight = NULL;        /* no highlighting */
  921. X                    unhighlight = NULL;
  922. X                    break;
  923. X        default:    highlight = T_TI;        /* invert/reverse */
  924. X                    unhighlight = T_TP;
  925. X                    break;
  926. X    }
  927. X    if (highlight == NULL || *highlight == NUL ||
  928. X                        unhighlight == NULL || *unhighlight == NUL)
  929. X    {
  930. X        highlight = NULL;
  931. X        return FAIL;
  932. X    }
  933. X    return OK;
  934. X}
  935. X
  936. X    void
  937. Xstart_highlight()
  938. X{
  939. X    if (highlight != NULL)
  940. X    {
  941. X        outstr(highlight);
  942. X        invert = INVERTCODE;
  943. X    }
  944. X}
  945. X
  946. X    void
  947. Xstop_highlight()
  948. X{
  949. X    if (invert)
  950. X    {
  951. X        outstr(unhighlight);
  952. X        invert = 0;
  953. X    }
  954. X}
  955. X
  956. X/*
  957. X * put character '*p' on the screen at position 'row' and 'col'
  958. X */
  959. X    static void
  960. Xscreen_char(p, row, col)
  961. X        char_u    *p;
  962. X        int     row;
  963. X        int     col;
  964. X{
  965. X    int            c;
  966. X    int            noinvcurs;
  967. X
  968. X    /*
  969. X     * Outputting the last character on the screen may scrollup the screen.
  970. X     * Don't to it!
  971. X     */
  972. X    if (row == Rows - 1 && col == Columns - 1)
  973. X        return;
  974. X    if (oldcol != col || oldrow != row)
  975. X    {
  976. X        /* check if no cursor movement is allowed in standout mode */
  977. X        if (invert && !p_wi && (T_MS == NULL || *T_MS == NUL))
  978. X            noinvcurs = 7;
  979. X        else
  980. X            noinvcurs = 0;
  981. X
  982. X        /*
  983. X         * If we're on the same row (which happens a lot!), try to
  984. X         * avoid a windgoto().
  985. X         * If we are only a few characters off, output the
  986. X         * characters. That is faster than cursor positioning.
  987. X         * This can't be used when inverting (a part of) the line.
  988. X         */
  989. X        if (oldrow == row && oldcol < col)
  990. X        {
  991. X            register int i;
  992. X
  993. X            i = col - oldcol;
  994. X            if (i <= 4 + noinvcurs && canopt)
  995. X            {
  996. X                while (i)
  997. X                {
  998. X                    c = *(p - i--);
  999. X                    outchar(c ^ invert);
  1000. X                }
  1001. X            }
  1002. X            else
  1003. X            {
  1004. X                if (noinvcurs)
  1005. X                    stop_highlight();
  1006. X            
  1007. X                if (T_CRI && *T_CRI)    /* use tgoto interface! jw */
  1008. X                    OUTSTR(tgoto((char *)T_CRI, 0, i));
  1009. X                else
  1010. X                    windgoto(row, col);
  1011. X            
  1012. X                if (noinvcurs)
  1013. X                    start_highlight();
  1014. X            }
  1015. X            oldcol = col;
  1016. X        }
  1017. X        else
  1018. X        {
  1019. X            if (noinvcurs)
  1020. X                stop_highlight();
  1021. X            windgoto(oldrow = row, oldcol = col);
  1022. X            if (noinvcurs)
  1023. X                start_highlight();
  1024. X        }
  1025. X    }
  1026. X    /*
  1027. X     * For weird invert mechanism: output (un)highlight before every char
  1028. X     * Lots of extra output, but works.
  1029. X     */
  1030. X    if (p_wi)
  1031. X    {
  1032. X        if (invert)                                      
  1033. X            outstr(highlight);                            
  1034. X        else                                             
  1035. X            outstr(unhighlight);
  1036. X    }
  1037. X    outchar(*p ^ invert);
  1038. X    oldcol++;
  1039. X}
  1040. X
  1041. X/*
  1042. X * Fill the screen from 'start_row' to 'end_row', from 'start_col' to 'end_col'
  1043. X * with character 'c1' in first column followed by 'c2' in the other columns.
  1044. X */
  1045. X    void
  1046. Xscreen_fill(start_row, end_row, start_col, end_col, c1, c2)
  1047. X    int     start_row, end_row;
  1048. X    int        start_col, end_col;
  1049. X    int        c1, c2;
  1050. X{
  1051. X    int                row;
  1052. X    int                col;
  1053. X    char_u            *screenp;
  1054. X    int                did_delete = FALSE;
  1055. X    int                c;
  1056. X
  1057. X    if (start_row >= end_row || start_col >= end_col)    /* nothing to do */
  1058. X        return;
  1059. X
  1060. X    c1 ^= invert;
  1061. X    c2 ^= invert;
  1062. X    for (row = start_row; row < end_row; ++row)
  1063. X    {
  1064. X            /* try to use delete-line termcap code */
  1065. X        if (c2 == ' ' && end_col == Columns && T_EL != NULL && *T_EL != NUL)
  1066. X        {
  1067. X            /*
  1068. X             * check if we really need to clear something
  1069. X             */
  1070. X            col = start_col;
  1071. X            screenp = LinePointers[row] + start_col;
  1072. X            if (c1 != ' ')                        /* don't clear first char */
  1073. X            {
  1074. X                ++col;
  1075. X                ++screenp;
  1076. X            }
  1077. X            while (col < end_col && *screenp == ' ')    /* skip blanks */
  1078. X            {
  1079. X                ++col;
  1080. X                ++screenp;
  1081. X            }
  1082. X            if (col < end_col)                    /* something to be cleared */
  1083. X            {
  1084. X                windgoto(row, col);
  1085. X                outstr(T_EL);
  1086. X            }
  1087. X            did_delete = TRUE;
  1088. X        }
  1089. X
  1090. X        screen_start();            /* init cursor position of screen_char() */
  1091. X        screenp = LinePointers[row] + start_col;
  1092. X        c = c1;
  1093. X        for (col = start_col; col < end_col; ++col)
  1094. X        {
  1095. X            if (*screenp != c)
  1096. X            {
  1097. X                *screenp = c;
  1098. X                if (!did_delete || c != ' ')
  1099. X                    screen_char(screenp, row, col);
  1100. X            }
  1101. X            ++screenp;
  1102. X            c = c2;
  1103. X        }
  1104. X        if (row == Rows - 1)
  1105. X        {
  1106. X            redraw_cmdline = TRUE;
  1107. X            if (c1 == ' ' && c2 == ' ')
  1108. X                clear_cmdline = FALSE;
  1109. X        }
  1110. X    }
  1111. X}
  1112. X
  1113. X/*
  1114. X * recompute all w_botline's. Called after Rows changed.
  1115. X */
  1116. X    void
  1117. Xcomp_Botline_all()
  1118. X{
  1119. X    WIN        *wp;
  1120. X
  1121. X    for (wp = firstwin; wp; wp = wp->w_next)
  1122. X        comp_Botline(wp);
  1123. X}
  1124. X
  1125. X/*
  1126. X * compute wp->w_botline. Can be called after wp->w_topline changed.
  1127. X */
  1128. X    void
  1129. Xcomp_Botline(wp)
  1130. X    WIN            *wp;
  1131. X{
  1132. X    linenr_t    lnum;
  1133. X    int            done = 0;
  1134. X
  1135. X    for (lnum = wp->w_topline; lnum <= wp->w_buffer->b_ml.ml_line_count; ++lnum)
  1136. X    {
  1137. X        if ((done += plines_win(wp, lnum)) > wp->w_height)
  1138. X            break;
  1139. X    }
  1140. X    wp->w_botline = lnum;        /* wp->w_botline is the line that is just below the window */
  1141. X}
  1142. X
  1143. X    static void
  1144. Xscreenalloc(clear)
  1145. X    int        clear;
  1146. X{
  1147. X    static int        old_Rows = 0;
  1148. X    static int        old_Columns = 0;
  1149. X    register int    i;
  1150. X    WIN                *wp;
  1151. X    int                outofmem = FALSE;
  1152. X
  1153. X    /*
  1154. X     * Allocation of the screen buffers is done only when the size changes
  1155. X     * and when Rows and Columns have been set.
  1156. X     */
  1157. X    if ((Nextscreen != NULL && Rows == old_Rows && Columns == old_Columns) || Rows == 0 || Columns == 0)
  1158. X        return;
  1159. X
  1160. X    comp_col();            /* recompute columns for shown command and ruler */
  1161. X    old_Rows = Rows;
  1162. X    old_Columns = Columns;
  1163. X
  1164. X    /*
  1165. X     * If we're changing the size of the screen, free the old arrays
  1166. X     */
  1167. X    free(Nextscreen);
  1168. X    free(LinePointers);
  1169. X    for (wp = firstwin; wp; wp = wp->w_next)
  1170. X        win_free_lsize(wp);
  1171. X
  1172. X    Nextscreen = (char_u *)malloc((size_t) (Rows * Columns));
  1173. X    LinePointers = (char_u **)malloc(sizeof(char_u *) * Rows);
  1174. X    for (wp = firstwin; wp; wp = wp->w_next)
  1175. X    {
  1176. X        if (win_alloc_lsize(wp) == FAIL)
  1177. X        {
  1178. X            outofmem = TRUE;
  1179. X            break;
  1180. X        }
  1181. X    }
  1182. X
  1183. X    if (Nextscreen == NULL || LinePointers == NULL || outofmem)
  1184. X    {
  1185. X        emsg(e_outofmem);
  1186. X        free(Nextscreen);
  1187. X        Nextscreen = NULL;
  1188. X    }
  1189. X    else
  1190. X    {
  1191. X        for (i = 0; i < Rows; ++i)
  1192. X            LinePointers[i] = Nextscreen + i * Columns;
  1193. X    }
  1194. X
  1195. X    if (clear)
  1196. X        screenclear2();
  1197. X}
  1198. X
  1199. X    void
  1200. Xscreenclear()
  1201. X{
  1202. X    screenalloc(FALSE);            /* allocate screen buffers if size changed */
  1203. X    screenclear2();
  1204. X}
  1205. X
  1206. X    static void
  1207. Xscreenclear2()
  1208. X{
  1209. X    if (starting || Nextscreen == NULL)
  1210. X        return;
  1211. X
  1212. X    outstr(T_ED);                /* clear the display */
  1213. X
  1214. X                                /* blank out Nextscreen */
  1215. X    memset((char *)Nextscreen, ' ', (size_t)(Rows * Columns));
  1216. X
  1217. X    win_rest_invalid(firstwin);
  1218. X    clear_cmdline = FALSE;
  1219. X    if (must_redraw == CLEAR)        /* no need to clear again */
  1220. X        must_redraw = NOT_VALID;
  1221. X}
  1222. X
  1223. X/*
  1224. X * check cursor for a valid lnum
  1225. X */
  1226. X    void
  1227. Xcheck_cursor()
  1228. X{
  1229. X    if (curwin->w_cursor.lnum > curbuf->b_ml.ml_line_count)
  1230. X        curwin->w_cursor.lnum = curbuf->b_ml.ml_line_count;
  1231. X    if (curwin->w_cursor.lnum <= 0)
  1232. X        curwin->w_cursor.lnum = 1;
  1233. X}
  1234. X
  1235. X    void
  1236. Xcursupdate()
  1237. X{
  1238. X    linenr_t        p;
  1239. X    long             nlines;
  1240. X    int             i;
  1241. X    int             temp;
  1242. X
  1243. X    screenalloc(TRUE);        /* allocate screen buffers if size changed */
  1244. X
  1245. X    if (Nextscreen == NULL)
  1246. X        return;
  1247. X
  1248. X    check_cursor();
  1249. X    if (bufempty())             /* special case - file is empty */
  1250. X    {
  1251. X        curwin->w_topline = 1;
  1252. X        curwin->w_cursor.lnum = 1;
  1253. X        curwin->w_cursor.col = 0;
  1254. X        curwin->w_lsize[0] = 0;
  1255. X        if (curwin->w_lsize_valid == 0)        /* don't know about screen contents */
  1256. X            updateScreen(NOT_VALID);
  1257. X        curwin->w_lsize_valid = 1;
  1258. X    }
  1259. X    else if (curwin->w_cursor.lnum < curwin->w_topline)
  1260. X    {
  1261. X/*
  1262. X * If the cursor is above the top of the screen, scroll the screen to
  1263. X * put it at the top of the screen.
  1264. X * If we weren't very close to begin with, we scroll more, so that
  1265. X * the line is close to the middle.
  1266. X */
  1267. X        temp = curwin->w_height / 2 - 1;
  1268. X        if (temp < 2)
  1269. X            temp = 2;
  1270. X        if (curwin->w_topline - curwin->w_cursor.lnum >= temp)        /* not very close */
  1271. X        {
  1272. X            p = curwin->w_cursor.lnum;
  1273. X            i = plines(p);
  1274. X            temp += i;
  1275. X                                /* count lines for 1/2 screenheight */
  1276. X            while (i < curwin->w_height + 1 && i < temp && p > 1)
  1277. X                i += plines(--p);
  1278. X            curwin->w_topline = p;
  1279. X            if (i > curwin->w_height)        /* cursor line won't fit, backup one line */
  1280. X                ++curwin->w_topline;
  1281. X        }
  1282. X        else if (p_sj > 1)        /* scroll at least p_sj lines */
  1283. X        {
  1284. X            for (i = 0; i < p_sj && curwin->w_topline > 1; i += plines(--curwin->w_topline))
  1285. X                ;
  1286. X        }
  1287. X        if (curwin->w_topline > curwin->w_cursor.lnum)
  1288. X            curwin->w_topline = curwin->w_cursor.lnum;
  1289. X        updateScreen(VALID);
  1290. X    }
  1291. X    else if (curwin->w_cursor.lnum >= curwin->w_botline)
  1292. X    {
  1293. X/*
  1294. X * If the cursor is below the bottom of the screen, scroll the screen to
  1295. X * put the cursor on the screen.
  1296. X * If the cursor is less than a screenheight down
  1297. X * compute the number of lines at the top which have the same or more
  1298. X * rows than the rows of the lines below the bottom
  1299. X */
  1300. X        nlines = curwin->w_cursor.lnum - curwin->w_botline + 1;
  1301. X        if (nlines <= curwin->w_height + 1)
  1302. X        {
  1303. X                /* get the number or rows to scroll minus the number of
  1304. X                                free '~' rows */
  1305. X            temp = plines_m(curwin->w_botline, curwin->w_cursor.lnum) - curwin->w_empty_rows;
  1306. X            if (temp <= 0)                /* curwin->w_empty_rows is larger, no need to scroll */
  1307. X                nlines = 0;
  1308. X            else if (temp > curwin->w_height)        /* more than a screenfull, don't scroll */
  1309. X                nlines = temp;
  1310. X            else
  1311. X            {
  1312. X                    /* scroll minimal number of lines */
  1313. X                if (temp < p_sj)
  1314. X                    temp = p_sj;
  1315. X                for (i = 0, p = curwin->w_topline; i < temp && p < curwin->w_botline; ++p)
  1316. X                    i += plines(p);
  1317. X                if (i >= temp)                /* it's possible to scroll */
  1318. X                    nlines = p - curwin->w_topline;
  1319. X                else                        /* below curwin->w_botline, don't scroll */
  1320. X                    nlines = 9999;
  1321. X            }
  1322. X        }
  1323. X
  1324. X        /*
  1325. X         * Scroll up if the cursor is off the bottom of the screen a bit.
  1326. X         * Otherwise put it at 1/2 of the screen.
  1327. X         */
  1328. X        if (nlines >= curwin->w_height / 2 && nlines > p_sj)
  1329. X        {
  1330. X            p = curwin->w_cursor.lnum;
  1331. X            temp = curwin->w_height / 2 + 1;
  1332. X            nlines = 0;
  1333. X            i = 0;
  1334. X            do                /* this loop could win a contest ... */
  1335. X                i += plines(p);
  1336. X            while (i < temp && (nlines = 1) != 0 && --p != 0);
  1337. X            curwin->w_topline = p + nlines;
  1338. X        }
  1339. X        else
  1340. X            scrollup(nlines);
  1341. X        updateScreen(VALID);
  1342. X    }
  1343. X    else if (curwin->w_lsize_valid == 0)        /* don't know about screen contents */
  1344. X        updateScreen(NOT_VALID);
  1345. X    curwin->w_row = curwin->w_col = curwin->w_virtcol = i = 0;
  1346. X    for (p = curwin->w_topline; p != curwin->w_cursor.lnum; ++p)
  1347. X        if (RedrawingDisabled)        /* curwin->w_lsize[] invalid */
  1348. X            curwin->w_row += plines(p);
  1349. X        else
  1350. X            curwin->w_row += curwin->w_lsize[i++];
  1351. X
  1352. X    Cline_row = curwin->w_row;
  1353. X    if (!RedrawingDisabled && i > curwin->w_lsize_valid)
  1354. X                                /* Should only happen with a line that is too */
  1355. X                                /* long to fit on the last screen line. */
  1356. X        Cline_height = 0;
  1357. X    else
  1358. X    {
  1359. X        if (RedrawingDisabled)              /* curwin->w_lsize[] invalid */
  1360. X            Cline_height = plines(curwin->w_cursor.lnum);
  1361. X        else
  1362. X            Cline_height = curwin->w_lsize[i];
  1363. X
  1364. X        curs_columns(!RedrawingDisabled);    /* compute curwin->w_virtcol and curwin->w_col */
  1365. X        if (must_redraw)
  1366. X            updateScreen(must_redraw);
  1367. X    }
  1368. X
  1369. X    if (curwin->w_set_curswant)
  1370. X    {
  1371. X        curwin->w_curswant = curwin->w_virtcol;
  1372. X        curwin->w_set_curswant = FALSE;
  1373. X    }
  1374. X}
  1375. X
  1376. X/*
  1377. X * compute curwin->w_col and curwin->w_virtcol
  1378. X */
  1379. X    void
  1380. Xcurs_columns(scroll)
  1381. X    int scroll;            /* when TRUE, may scroll horizontally */
  1382. X{
  1383. X    int diff;
  1384. X
  1385. X    curwin->w_virtcol = getvcol(curwin, &curwin->w_cursor, 1);
  1386. X    curwin->w_col = curwin->w_virtcol;
  1387. X    if (curwin->w_p_nu)
  1388. X        curwin->w_col += 8;
  1389. X
  1390. X    curwin->w_row = Cline_row;
  1391. X    if (curwin->w_p_wrap)            /* long line wrapping, adjust curwin->w_row */
  1392. X        while (curwin->w_col >= Columns)
  1393. X        {
  1394. X            curwin->w_col -= Columns;
  1395. X            curwin->w_row++;
  1396. X        }
  1397. X    else if (scroll)    /* no line wrapping, compute curwin->w_leftcol if scrolling is on */
  1398. X                        /* if scrolling is off, curwin->w_leftcol is assumed to be 0 */
  1399. X    {
  1400. X                        /* If Cursor is in columns 0, start in column 0 */
  1401. X                        /* If Cursor is left of the screen, scroll rightwards */
  1402. X                        /* If Cursor is right of the screen, scroll leftwards */
  1403. X        if (curwin->w_cursor.col == 0)
  1404. X        {
  1405. X                        /* screen has to be redrawn with new curwin->w_leftcol */
  1406. X            if (curwin->w_leftcol != 0 && must_redraw < NOT_VALID)
  1407. X                must_redraw = NOT_VALID;
  1408. X            curwin->w_leftcol = 0;
  1409. X        }
  1410. X        else if (((diff = curwin->w_leftcol + (curwin->w_p_nu ? 8 : 0)
  1411. X                    - curwin->w_col) > 0 ||
  1412. X                    (diff = curwin->w_col - (curwin->w_leftcol + Columns) + 1) > 0))
  1413. X        {
  1414. X            if (p_ss == 0 || diff >= Columns / 2)
  1415. X                curwin->w_leftcol = curwin->w_col - Columns / 2;
  1416. X            else
  1417. X            {
  1418. X                if (diff < p_ss)
  1419. X                    diff = p_ss;
  1420. X                if (curwin->w_col < curwin->w_leftcol + 8)
  1421. X                    curwin->w_leftcol -= diff;
  1422. X                else
  1423. X                    curwin->w_leftcol += diff;
  1424. X            }
  1425. X            if (curwin->w_leftcol < 0)
  1426. X                curwin->w_leftcol = 0;
  1427. X            if (must_redraw < NOT_VALID)
  1428. X                must_redraw = NOT_VALID;    /* screen has to be redrawn with new curwin->w_leftcol */
  1429. X        }
  1430. X        curwin->w_col -= curwin->w_leftcol;
  1431. X    }
  1432. X    if (curwin->w_row > curwin->w_height - 1)    /* Cursor past end of screen */
  1433. X        curwin->w_row = curwin->w_height - 1;    /* happens with line that does not fit on screen */
  1434. X}
  1435. X
  1436. X/*
  1437. X * get virtual column number of pos
  1438. X * type = 1: where the cursor is on this character
  1439. X * type = 2: on the first position of this character (TAB)
  1440. X * type = 3: on the last position of this character (TAB)
  1441. X */
  1442. X    int
  1443. Xgetvcol(wp, pos, type)
  1444. X    WIN        *wp;
  1445. X    FPOS    *pos;
  1446. X    int        type;
  1447. X{
  1448. X    int                col;
  1449. X    int                vcol;
  1450. X    char_u           *ptr;
  1451. X    int             incr;
  1452. X    int                c;
  1453. X
  1454. X    vcol = 0;
  1455. X    ptr = ml_get_buf(wp->w_buffer, pos->lnum, FALSE);
  1456. X    for (col = pos->col; col >= 0; --col)
  1457. X    {
  1458. X        c = *ptr++;
  1459. X        if (c == NUL)        /* make sure we don't go past the end of the line */
  1460. X            break;
  1461. X
  1462. X        /* A tab gets expanded, depending on the current column */
  1463. X        incr = chartabsize(c, (long)vcol);
  1464. X
  1465. X        if (col == 0)        /* character at pos.col */
  1466. X        {
  1467. X            if (type == 3 || (type == 1 && c == TAB && State == NORMAL && !wp->w_p_list))
  1468. X                --incr;
  1469. X            else
  1470. X                break;
  1471. X        }
  1472. X        vcol += incr;
  1473. X    }
  1474. X    return vcol;
  1475. X}
  1476. X
  1477. X    void
  1478. Xscrolldown(nlines)
  1479. X    long    nlines;
  1480. X{
  1481. X    register long    done = 0;    /* total # of physical lines done */
  1482. X
  1483. X    /* Scroll up 'nlines' lines. */
  1484. X    while (nlines--)
  1485. X    {
  1486. X        if (curwin->w_topline == 1)
  1487. X            break;
  1488. X        done += plines(--curwin->w_topline);
  1489. X    }
  1490. X    /*
  1491. X     * Compute the row number of the last row of the cursor line
  1492. X     * and move it onto the screen.
  1493. X     */
  1494. X    curwin->w_row += done;
  1495. X    if (curwin->w_p_wrap)
  1496. X        curwin->w_row += plines(curwin->w_cursor.lnum) - 1 - curwin->w_virtcol / Columns;
  1497. X    while (curwin->w_row >= curwin->w_height && curwin->w_cursor.lnum > 1)
  1498. X        curwin->w_row -= plines(curwin->w_cursor.lnum--);
  1499. X}
  1500. X
  1501. X    void
  1502. Xscrollup(nlines)
  1503. X    long    nlines;
  1504. X{
  1505. X#ifdef NEVER
  1506. X    register long    done = 0;    /* total # of physical lines done */
  1507. X
  1508. X    /* Scroll down 'nlines' lines. */
  1509. X    while (nlines--)
  1510. X    {
  1511. X        if (curwin->w_topline == curbuf->b_ml.ml_line_count)
  1512. X            break;
  1513. X        done += plines(curwin->w_topline);
  1514. X        if (curwin->w_cursor.lnum == curwin->w_topline)
  1515. X            ++curwin->w_cursor.lnum;
  1516. X        ++curwin->w_topline;
  1517. X    }
  1518. X    win_del_lines(curwin, 0, done, TRUE, TRUE);
  1519. X#endif
  1520. X    curwin->w_topline += nlines;
  1521. X    if (curwin->w_topline > curbuf->b_ml.ml_line_count)
  1522. X        curwin->w_topline = curbuf->b_ml.ml_line_count;
  1523. X    if (curwin->w_cursor.lnum < curwin->w_topline)
  1524. X        curwin->w_cursor.lnum = curwin->w_topline;
  1525. X}
  1526. X
  1527. X/*
  1528. X * insert 'nlines' lines at 'row' in window 'wp'
  1529. X * if 'invalid' is TRUE the wp->w_lsize_lnum[] is invalidated.
  1530. X * if 'mayclear' is TRUE the screen will be cleared if it is faster than scrolling
  1531. X * Returns FAIL if the lines are not inserted, OK for success.
  1532. X */
  1533. X    int
  1534. Xwin_ins_lines(wp, row, nlines, invalid, mayclear)
  1535. X    WIN        *wp;
  1536. X    int        row;
  1537. X    int        nlines;
  1538. X    int        invalid;
  1539. X    int        mayclear;
  1540. X{
  1541. X    int        did_delete;
  1542. X    int        nextrow;
  1543. X    int        lastrow;
  1544. X    int        retval;
  1545. X
  1546. X    if (invalid)
  1547. X        wp->w_lsize_valid = 0;
  1548. X
  1549. X    if (RedrawingDisabled || nlines <= 0 || wp->w_height < 5)
  1550. X        return FAIL;
  1551. X    
  1552. X    if (nlines > wp->w_height - row)
  1553. X        nlines = wp->w_height - row;
  1554. X
  1555. X    if (mayclear && Rows - nlines < 5)    /* only a few lines left: redraw is faster */
  1556. X    {
  1557. X        screenclear();        /* will set wp->w_lsize_valid to 0 */
  1558. X        return FAIL;
  1559. X    }
  1560. X
  1561. X    if (nlines == wp->w_height)    /* will delete all lines */
  1562. X        return FAIL;
  1563. X
  1564. X    /*
  1565. X     * when scrolling, the message on the command line should be cleared,
  1566. X     * otherwise it will stay there forever.
  1567. X     */
  1568. X    clear_cmdline = TRUE;
  1569. X
  1570. X    /*
  1571. X     * if the terminal can set a scroll region, use that
  1572. X     */
  1573. X    if (scroll_region)
  1574. X    {
  1575. X        scroll_region_set(wp);
  1576. X        retval = screen_ins_lines(wp->w_winpos, row, nlines, wp->w_height);
  1577. X        scroll_region_reset();
  1578. X        return retval;
  1579. X    }
  1580. X
  1581. X    if (wp->w_next && p_tf)        /* don't delete/insert on fast terminal */
  1582. X        return FAIL;
  1583. X
  1584. X    /*
  1585. X     * If there is a next window or a status line, we first try to delete the
  1586. X     * lines at the bottom to avoid messing what is after the window.
  1587. X     * If this fails and there are following windows, don't do anything to avoid
  1588. X     * messing up those windows, better just redraw.
  1589. X     */
  1590. X    did_delete = FALSE;
  1591. X    if (wp->w_next || wp->w_status_height)
  1592. X    {
  1593. X        if (screen_del_lines(0, wp->w_winpos + wp->w_height - nlines, nlines, (int)Rows) == OK)
  1594. X            did_delete = TRUE;
  1595. X        else if (wp->w_next)
  1596. X            return FAIL;
  1597. X    }
  1598. X    /*
  1599. X     * if no lines deleted, blank the lines that will end up below the window
  1600. X     */
  1601. X    if (!did_delete)
  1602. X    {
  1603. X        wp->w_redr_status = TRUE;
  1604. X        redraw_cmdline = TRUE;
  1605. X        nextrow = wp->w_winpos + wp->w_height + wp->w_status_height;
  1606. X        lastrow = nextrow + nlines;
  1607. X        if (lastrow > Rows)
  1608. X            lastrow = Rows;
  1609. X        screen_fill(nextrow - nlines, lastrow - nlines, 0, (int)Columns, ' ', ' ');
  1610. X    }
  1611. X
  1612. X    if (screen_ins_lines(0, wp->w_winpos + row, nlines, (int)Rows) == FAIL)
  1613. X    {
  1614. X            /* deletion will have messed up other windows */
  1615. X        if (did_delete)
  1616. X        {
  1617. X            wp->w_redr_status = TRUE;
  1618. X            win_rest_invalid(wp->w_next);
  1619. X        }
  1620. X        return FAIL;
  1621. X    }
  1622. X
  1623. X    return OK;
  1624. X}
  1625. X
  1626. X/*
  1627. X * delete 'nlines' lines at 'row' in window 'wp'
  1628. X * If 'invalid' is TRUE curwin->w_lsize_lnum[] is invalidated.
  1629. X * If 'mayclear' is TRUE the screen will be cleared if it is faster than scrolling
  1630. X * Return OK for success, FAIL if the lines are not deleted.
  1631. X */
  1632. X    int
  1633. Xwin_del_lines(wp, row, nlines, invalid, mayclear)
  1634. X    WIN                *wp;
  1635. X    int             row;
  1636. X    int             nlines;
  1637. X    int                invalid;
  1638. X    int                mayclear;
  1639. X{
  1640. X    int            retval;
  1641. X
  1642. X    if (invalid)
  1643. X        wp->w_lsize_valid = 0;
  1644. X
  1645. X    if (RedrawingDisabled || nlines <= 0)
  1646. X        return FAIL;
  1647. X    
  1648. X    if (nlines > wp->w_height - row)
  1649. X        nlines = wp->w_height - row;
  1650. X
  1651. X    if (mayclear && Rows - nlines < 5)    /* only a few lines left: redraw is faster */
  1652. X    {
  1653. X        screenclear();        /* will set wp->w_lsize_valid to 0 */
  1654. X        return FAIL;
  1655. X    }
  1656. X
  1657. X    if (nlines == wp->w_height)    /* will delete all lines */
  1658. X        return FAIL;
  1659. X
  1660. X    /*
  1661. X     * when scrolling, the message on the command line should be cleared,
  1662. X     * otherwise it will stay there forever.
  1663. X     */
  1664. X    clear_cmdline = TRUE;
  1665. X
  1666. X    /*
  1667. X     * if the terminal can set a scroll region, use that
  1668. X     */
  1669. X    if (scroll_region)
  1670. X    {
  1671. X        scroll_region_set(wp);
  1672. X        retval = screen_del_lines(wp->w_winpos, row, nlines, wp->w_height);
  1673. X        scroll_region_reset();
  1674. X        return retval;
  1675. X    }
  1676. X
  1677. X    if (wp->w_next && p_tf)        /* don't delete/insert on fast terminal */
  1678. X        return FAIL;
  1679. X
  1680. X    if (screen_del_lines(0, wp->w_winpos + row, nlines, (int)Rows) == FAIL)
  1681. X        return FAIL;
  1682. X
  1683. X    /*
  1684. X     * If there are windows or status lines below, try to put them at the
  1685. X     * correct place. If we can't do that, they have to be redrawn.
  1686. X     */
  1687. X    if (wp->w_next || wp->w_status_height || cmdline_row < Rows - 1)
  1688. X    {
  1689. X        if (screen_ins_lines(0, wp->w_winpos + wp->w_height - nlines, nlines, (int)Rows) == FAIL)
  1690. X        {
  1691. X            wp->w_redr_status = TRUE;
  1692. X            win_rest_invalid(wp->w_next);
  1693. X        }
  1694. X    }
  1695. X    /*
  1696. X     * If this is the last window and there is no status line, redraw the
  1697. X     * command line later.
  1698. X     */
  1699. X    else
  1700. X        redraw_cmdline = TRUE;
  1701. X    return OK;
  1702. X}
  1703. X
  1704. X/*
  1705. X * window 'wp' and everything after it is messed up, mark it for redraw
  1706. X */
  1707. X    void
  1708. Xwin_rest_invalid(wp)
  1709. X    WIN            *wp;
  1710. X{
  1711. X    while (wp)
  1712. X    {
  1713. X        wp->w_lsize_valid = 0;
  1714. X        wp->w_redr_type = NOT_VALID;
  1715. X        wp->w_redr_status = TRUE;
  1716. X        wp = wp->w_next;
  1717. X    }
  1718. X    redraw_cmdline = TRUE;
  1719. X}
  1720. X
  1721. X/*
  1722. X * The rest of the routines in this file perform screen manipulations. The
  1723. X * given operation is performed physically on the screen. The corresponding
  1724. X * change is also made to the internal screen image. In this way, the editor
  1725. X * anticipates the effect of editing changes on the appearance of the screen.
  1726. X * That way, when we call screenupdate a complete redraw isn't usually
  1727. X * necessary. Another advantage is that we can keep adding code to anticipate
  1728. X * screen changes, and in the meantime, everything still works.
  1729. X */
  1730. X
  1731. X/*
  1732. X * insert lines on the screen and update Nextscreen
  1733. X * 'end' is the line after the scrolled part. Normally it is Rows.
  1734. X * When scrolling region used 'off' is the offset from the top for the region.
  1735. X * 'row' and 'end' are relative to the start of the region.
  1736. X *
  1737. X * return FAIL for failure, OK for success.
  1738. X */
  1739. X    static int
  1740. Xscreen_ins_lines(off, row, nlines, end)
  1741. X    int            off;
  1742. X    int         row;
  1743. X    int         nlines;
  1744. X    int            end;
  1745. X{
  1746. X    int         i;
  1747. X    int         j;
  1748. X    char_u        *temp;
  1749. X    int            cursor_row;
  1750. X
  1751. X    if (T_CSC != NULL && *T_CSC != NUL)        /* cursor relative to region */
  1752. X        cursor_row = row;
  1753. X    else
  1754. X        cursor_row = row + off;
  1755. X
  1756. X    screenalloc(TRUE);        /* allocate screen buffers if size changed */
  1757. X    if (Nextscreen == NULL)
  1758. X        return FAIL;
  1759. X
  1760. X    if (nlines <= 0 ||  ((T_CIL == NULL || *T_CIL == NUL) &&
  1761. X                        (T_IL == NULL || *T_IL == NUL) &&
  1762. X                        (T_SR == NULL || *T_SR == NUL || row != 0)))
  1763. X        return FAIL;
  1764. X    
  1765. X    /*
  1766. X     * It "looks" better if we do all the inserts at once
  1767. X     */
  1768. X    if (T_CIL && *T_CIL) 
  1769. X    {
  1770. X        windgoto(cursor_row, 0);
  1771. X        if (nlines == 1 && T_IL && *T_IL)
  1772. X            outstr(T_IL);
  1773. X        else
  1774. X            OUTSTR(tgoto((char *)T_CIL, 0, nlines));
  1775. X    }
  1776. X    else
  1777. X    {
  1778. X        for (i = 0; i < nlines; i++) 
  1779. X        {
  1780. X            if (i == 0 || cursor_row != 0)
  1781. X                windgoto(cursor_row, 0);
  1782. X            if (T_IL && *T_IL)
  1783. X                outstr(T_IL);
  1784. X            else
  1785. X                outstr(T_SR);
  1786. X        }
  1787. X    }
  1788. X    /*
  1789. X     * Now shift LinePointers nlines down to reflect the inserted lines.
  1790. X     * Clear the inserted lines.
  1791. X     */
  1792. X    row += off;
  1793. X    end += off;
  1794. X    for (i = 0; i < nlines; ++i)
  1795. X    {
  1796. X        j = end - 1 - i;
  1797. X        temp = LinePointers[j];
  1798. X        while ((j -= nlines) >= row)
  1799. X                LinePointers[j + nlines] = LinePointers[j];
  1800. X        LinePointers[j + nlines] = temp;
  1801. X        memset((char *)temp, ' ', (size_t)Columns);
  1802. X    }
  1803. X    return OK;
  1804. X}
  1805. X
  1806. X/*
  1807. X * delete lines on the screen and update Nextscreen
  1808. X * 'end' is the line after the scrolled part. Normally it is Rows.
  1809. X * When scrolling region used 'off' is the offset from the top for the region.
  1810. X * 'row' and 'end' are relative to the start of the region.
  1811. X *
  1812. X * Return OK for success, FAIL if the lines are not deleted.
  1813. X */
  1814. X    int
  1815. Xscreen_del_lines(off, row, nlines, end)
  1816. X    int                off;
  1817. X    int             row;
  1818. X    int             nlines;
  1819. X    int                end;
  1820. X{
  1821. X    int         j;
  1822. X    int         i;
  1823. X    char_u        *temp;
  1824. X    int            cursor_row;
  1825. X    int            cursor_end;
  1826. X
  1827. X    if (T_CSC != NULL && *T_CSC != NUL)        /* cursor relative to region */
  1828. X    {
  1829. X        cursor_row = row;
  1830. X        cursor_end = end;
  1831. X    }
  1832. X    else
  1833. X    {
  1834. X        cursor_row = row + off;
  1835. X        cursor_end = end + off;
  1836. X    }
  1837. X
  1838. X    screenalloc(TRUE);        /* allocate screen buffers if size changed */
  1839. X    if (Nextscreen == NULL)
  1840. X        return FAIL;
  1841. X
  1842. X    if (nlines <= 0 ||  ((T_DL == NULL || *T_DL == NUL) &&
  1843. X                        (T_CDL == NULL || *T_CDL == NUL) &&
  1844. X                        row != 0))
  1845. X        return FAIL;
  1846. X
  1847. X    /* delete the lines */
  1848. X    if (T_CDL && *T_CDL) 
  1849. X    {
  1850. X        windgoto(cursor_row, 0);
  1851. X        if (nlines == 1 && T_DL && *T_DL)
  1852. X            outstr(T_DL);
  1853. X        else
  1854. X            OUTSTR(tgoto((char *)T_CDL, 0, nlines));
  1855. X    } 
  1856. X    else
  1857. X    {
  1858. X        if (row == 0)
  1859. X        {
  1860. X            windgoto(cursor_end - 1, 0);
  1861. X            for (i = 0; i < nlines; i++) 
  1862. X                outchar('\n');
  1863. X        }
  1864. X        else
  1865. X        {
  1866. X            for (i = 0; i < nlines; i++) 
  1867. X            {
  1868. X                windgoto(cursor_row, 0);
  1869. X                outstr(T_DL);           /* delete a line */
  1870. X            }
  1871. X        }
  1872. X    }
  1873. X
  1874. X    /*
  1875. X     * Now shift LinePointers nlines up to reflect the deleted lines.
  1876. X     * Clear the deleted lines.
  1877. X     */
  1878. X    row += off;
  1879. X    end += off;
  1880. X    for (i = 0; i < nlines; ++i)
  1881. X    {
  1882. X        j = row + i;
  1883. X        temp = LinePointers[j];
  1884. X        while ((j += nlines) <= end - 1)
  1885. X            LinePointers[j - nlines] = LinePointers[j];
  1886. X        LinePointers[j - nlines] = temp;
  1887. X        memset((char *)temp, ' ', (size_t)Columns);
  1888. X    }
  1889. X    return OK;
  1890. X}
  1891. X
  1892. X/*
  1893. X * show the current mode and ruler
  1894. X *
  1895. X * If clear_cmdline is TRUE, clear it first.
  1896. X * If clear_cmdline is FALSE there may be a message there that needs to be
  1897. X * cleared only if a mode is shown.
  1898. X */
  1899. X    void
  1900. Xshowmode()
  1901. X{
  1902. X    int        did_clear = clear_cmdline;
  1903. X    int        need_clear = FALSE;
  1904. X
  1905. X    if ((p_smd && (State & INSERT)) || Recording)
  1906. X    {
  1907. X        gotocmdline(clear_cmdline, NUL);
  1908. X        if (p_smd)
  1909. X        {
  1910. X            if (State & INSERT)
  1911. X            {
  1912. X                msg_outstr((char_u *)"-- ");
  1913. X                if (p_ri)
  1914. X                    msg_outstr((char_u *)"REVERSE ");
  1915. X                if (State == INSERT)
  1916. X                    msg_outstr((char_u *)"INSERT --");
  1917. X                else
  1918. X                    msg_outstr((char_u *)"REPLACE --");
  1919. X                need_clear = TRUE;
  1920. X            }
  1921. X        }
  1922. X        if (Recording)
  1923. X        {
  1924. X            msg_outstr((char_u *)"recording");
  1925. X            need_clear = TRUE;
  1926. X        }
  1927. X        if (need_clear && !did_clear)
  1928. X            msg_ceol();
  1929. X    }
  1930. X    win_redr_ruler(lastwin, TRUE);
  1931. X    redraw_cmdline = FALSE;
  1932. X}
  1933. X
  1934. X/*
  1935. X * delete mode message
  1936. X */
  1937. X    void
  1938. Xdelmode()
  1939. X{
  1940. X    if (Recording)
  1941. X        MSG("recording");
  1942. X    else
  1943. X        MSG("");
  1944. X}
  1945. X
  1946. X/*
  1947. X * if ruler option is set: show current cursor position
  1948. X * if always is FALSE, only print if position has changed
  1949. X */
  1950. X    void
  1951. Xshowruler(always)
  1952. X    int        always;
  1953. X{
  1954. X    win_redr_ruler(curwin, always);
  1955. X}
  1956. X
  1957. X    void
  1958. Xwin_redr_ruler(wp, always)
  1959. X    WIN        *wp;
  1960. X    int        always;
  1961. X{
  1962. X    static linenr_t    oldlnum = 0;
  1963. X    static colnr_t    oldcol = 0;
  1964. X    char_u            buffer[30];
  1965. X    int                row;
  1966. X    int                fillchar;
  1967. X
  1968. X    if (p_ru && (redraw_cmdline || always || wp->w_cursor.lnum != oldlnum || wp->w_virtcol != oldcol))
  1969. X    {
  1970. X        cursor_off();
  1971. X        if (wp->w_status_height)
  1972. X        {
  1973. X            row = wp->w_winpos + wp->w_height;
  1974. X            if (set_highlight('s') == OK)        /* can use highlighting */
  1975. X            {
  1976. X                fillchar = ' ';
  1977. X                start_highlight();
  1978. X            }
  1979. X            else
  1980. X                fillchar = '=';
  1981. X        }
  1982. X        else
  1983. X        {
  1984. X            row = Rows - 1;
  1985. X            fillchar = ' ';
  1986. X        }
  1987. X        /*
  1988. X         * Some sprintfs return the lenght, some return a pointer.
  1989. X         * To avoid portability problems we use strlen here.
  1990. X         */
  1991. X        sprintf((char *)buffer, "%ld,%d", wp->w_cursor.lnum, (int)wp->w_cursor.col + 1);
  1992. X        if (wp->w_cursor.col != wp->w_virtcol)
  1993. X            sprintf((char *)buffer + STRLEN(buffer), "-%d", wp->w_virtcol + 1);
  1994. X
  1995. X        screen_start();            /* init cursor position */
  1996. X        screen_msg(buffer, row, ru_col);
  1997. X        screen_fill(row, row + 1, ru_col + (int)STRLEN(buffer), (int)Columns, fillchar, fillchar);
  1998. X        oldlnum = wp->w_cursor.lnum;
  1999. X        oldcol = wp->w_virtcol;
  2000. X        stop_highlight();
  2001. X    }
  2002. X}
  2003. X
  2004. X/*
  2005. X * screen_valid: Returns TRUE if there is a valid screen to write to.
  2006. X *                  Returns FALSE when starting up and screen not initialized yet.
  2007. X * Used by msg() to decide to use either screen_msg() or printf().
  2008. X */
  2009. X    int
  2010. Xscreen_valid()
  2011. X{
  2012. X    screenalloc(FALSE);        /* allocate screen buffers if size changed */
  2013. X    return (Nextscreen != NULL);
  2014. X}
  2015. END_OF_FILE
  2016.   if test 46442 -ne `wc -c <'vim/src/screen.c'`; then
  2017.     echo shar: \"'vim/src/screen.c'\" unpacked with wrong size!
  2018.   fi
  2019.   # end of 'vim/src/screen.c'
  2020. fi
  2021. if test -f 'vim/src/tcconfig.tc.UU' -a "${1}" != "-c" ; then 
  2022.   echo shar: Will not clobber existing file \"'vim/src/tcconfig.tc.UU'\"
  2023. else
  2024.   echo shar: Extracting \"'vim/src/tcconfig.tc.UU'\" \(2368 characters\)
  2025.   sed "s/^X//" >'vim/src/tcconfig.tc.UU' <<'END_OF_FILE'
  2026. Xbegin 644 vim/src/tcconfig.tc
  2027. XM5'5R8F\@0R!#;VYF:6=U<F%T:6]N($9I;&4@&@ !#1(7 1H  @$!  (    "
  2028. XM  (  0 #  (  @ $  $   4  0  !@ !   (  $ ! D  @    T  @ !  X 
  2029. XM @   !$  0 ($@ "    $P " !D %  "    %0 "  $ %@ "    %P "  $ 
  2030. XM&  "  $ 9  !  %E  $  68  0 !9P !  %H  $  6D  0 !:@ !  %K  $ 
  2031. XM 6P  0 !;0 !  %N  $  6\  0 !<  !  %Q  $  7(  0 !<P !  %T  $ 
  2032. XM 74  0 !=@ !  %W  $  7@  0 !>0 !  %Z  $  7L  0  ?  !  %]  $ 
  2033. XM 7X  0  ?P !  &   $  8(  0  A  !  &%  $  <@  0  R0 !  #*  $ 
  2034. XM <L  0  S  !  #-  $  ,X  0 !SP !  #0  $ &=$  0!DT@ ! "#5  $ 
  2035. XM -<  0  V  !  #9  $  =H  0 !VP !  #<  $  =T  0 !W@ !  #?  $ 
  2036. XM .   0  X0 !  #B  $  2P!1                                   
  2037. XM                                                         "T!
  2038. XM@ !$.EQ40UQ)3D-,541%                                        
  2039. XM                                                            
  2040. XM                                                     "X!@ !$
  2041. XM.EQ40UQ,24(                                                 
  2042. XM                                                            
  2043. XM                                                 "\!4 !624TN
  2044. XM4%)*                                                        
  2045. XM                                         # !!  S,@  ,0$% #(U
  2046. XM    ,@$% #$P,   ,P%_ $U31$]3.U=)3$1?0T%21%,                 
  2047. XM                                                            
  2048. XM                                                            
  2049. XM           T 1X *@                                      -0$>
  2050. XM "H                                      #8!'@ J            
  2051. XM                           W 1X *@                          
  2052. XM            . $> "H                                      #D!
  2053. XM'@ J                                       Z 1X *@          
  2054. XM                            .P$> "H                         
  2055. XM             #P!'@ J                                       ]
  2056. XM 8                                                          
  2057. XM                                                            
  2058. XM                                                       ^ 00 
  2059. XM.    #\!4                                                   
  2060. XM                                                         $ !
  2061. XM1 !$.EQ40P                                                  
  2062. XM                                 $$!4                       
  2063. XM                                                            
  2064. X9                         /__ @ :    
  2065. Xend
  2066. END_OF_FILE
  2067.   if test 2368 -ne `wc -c <'vim/src/tcconfig.tc.UU'`; then
  2068.     echo shar: \"'vim/src/tcconfig.tc.UU'\" unpacked with wrong size!
  2069.   else
  2070.     echo shar: Uudecoding \"'vim/src/tcconfig.tc'\" \(1690 characters\)
  2071.     cat vim/src/tcconfig.tc.UU | uudecode
  2072.     if test 1690 -ne `wc -c <'vim/src/tcconfig.tc'`; then
  2073.       echo shar: \"'vim/src/tcconfig.tc'\" uudecoded with wrong size!
  2074.     else
  2075.       rm vim/src/tcconfig.tc.UU
  2076.     fi
  2077.   fi
  2078.   # end of 'vim/src/tcconfig.tc.UU'
  2079. fi
  2080. if test -f 'vim/src/version.c' -a "${1}" != "-c" ; then 
  2081.   echo shar: Will not clobber existing file \"'vim/src/version.c'\"
  2082. else
  2083.   echo shar: Extracting \"'vim/src/version.c'\" \(15714 characters\)
  2084.   sed "s/^X//" >'vim/src/version.c' <<'END_OF_FILE'
  2085. X/* vi:ts=4:sw=4:tw=78
  2086. X *
  2087. X * VIM - Vi IMproved        by Bram Moolenaar
  2088. X *
  2089. X * Read the file "credits.txt" for a list of people who contributed.
  2090. X * Read the file "uganda.txt" for copying and usage conditions.
  2091. X */
  2092. X
  2093. X/*
  2094. X Started with Stevie version 3.6 (Fish disk 217) - GRWalter (Fred)
  2095. X
  2096. X VIM 1.0    - Changed so many things that I felt that a new name was required
  2097. X            (I didn't like the name Stevie that much: I don't have an ST).
  2098. X            - VIM stands for "Vi IMitation".
  2099. X            - New storage structure, MULTI-LEVEL undo and redo,
  2100. X            improved screen output, removed an awful number of bugs,
  2101. X            removed fixed size buffers, added counts to a lot of commands,
  2102. X            added new commands, added new options, added 'smart indent',
  2103. X            added recording mode, added script files, moved help to a file,
  2104. X            etc. etc. etc.
  2105. X            - Compiles under Manx/Aztec C 5.0. You can use "rez" to make VIM
  2106. X            resident.
  2107. X            - Bram Moolenaar (Mool)
  2108. X
  2109. X VIM 1.09 - spaces can be used in tags file instead of tabs (compatible with
  2110. X            Manx ctags).
  2111. X
  2112. X VIM 1.10 - Csh not required anymore for CTRL-D. Search options /e and /s added.
  2113. X            Shell option implemented. BS in replace mode does not delete
  2114. X            character. Backspace, wrapmargin and tags options added.
  2115. X            Added support for Manx's QuickFix mode (just like "Z").
  2116. X            The ENV: environment variables instead of the Old Manx environment
  2117. X            variables are now used, because Vim was compiled with version 5.0d
  2118. X            of the compiler. "mool" library not used anymore. Added index to
  2119. X            help screens.
  2120. X
  2121. X VIM 1.11 - removed bug that caused :e of same file, but with name in upper case,
  2122. X            to re-edit that file.
  2123. X
  2124. X VIM 1.12 - The second character of several commands (e.g. 'r', 't', 'm') not
  2125. X            :mapped anymore (UNIX vi does it like this, don't know why); Some
  2126. X            operators did not work when doing a 'l' on the last character in
  2127. X            a line (e.g. 'yl'); Added :mapping when executing registers;
  2128. X            Removed vi incompatibility from 't' and 'T' commands; :mapping! also
  2129. X            works for command line editing; Changed a few details to have Vim
  2130. X            run the macros for solving a maze and Towers of Hanoi! It now also
  2131. X            runs the Turing machine macros!
  2132. X
  2133. X VIM 1.13 - Removed a bug for !! on empty line. "$" no longer puts cursor at
  2134. X            the end of the line when combined with an operator. Added
  2135. X            automatic creation of a script file for recovery after a crash.
  2136. X            Added "-r" option. Solved bug for not detecting end of script file.
  2137. X            ".bak" is now appended, thus "main.c" and "main.h" will have
  2138. X            separate backup files.
  2139. X
  2140. X VIM 1.14 - Removed a few minor bugs. Added "-n" option to skip autoscript.
  2141. X            Made options more Vi compatible. Improved ^C handling. On serious
  2142. X            errors typahead and scripts are discarded. 'U' is now correctly
  2143. X            undone with 'u'. Fixed showmatch() handling of 'x' and '\x'.
  2144. X            Solved window size dependency for scripts by adding ":winsize"
  2145. X            commands to scripts. This version released on Fish disk 591.
  2146. X
  2147. X VIM 1.15 - No extra return in recording mode (MCHAR instead of MLINE buffer).
  2148. X            plural() argument is now a long. Search patterns shared between
  2149. X            :g, :s and /. After recovery a message is given. Overflow of mapbuf
  2150. X            is detected. Line number possible with :read. Error message when
  2151. X            characters follow a '$' in a search pattern. Cause for crash
  2152. X            removed: ":s/pat/repl/g" allocated not enough memory. Option
  2153. X            "directory" added. Option "expandtab" added. Solved showmode non-
  2154. X            functioning. Solved bug with window resizing. Removed some *NULL
  2155. X            references. CTRL-], * and # commands now skips non-identifier
  2156. X            characters. Added tag list, CTRL-T, :pop and :tags commands.
  2157. X            Added jump list, CTRL-O and CTRL-I commands. Added "shiftround"
  2158. X            option. Applied AUX and Lattice mods from Juergen Weigert.
  2159. X            Finally made linenr_t a long, files can be > 65000 lines!
  2160. X            :win command could be written to script file halfway a command.
  2161. X            Option shelltype added. With ^V no mapping anymore.
  2162. X            Added :move, :copy, :t, :mark and :k. Improved Ex address parsing.
  2163. X            Many delimiters possible with :s.
  2164. X
  2165. X VIM 1.16 - Solved bug with zero line number in Ex range. Added file-number to
  2166. X            jump list. Solved bug when scrolling downwards. Made tagstack vi
  2167. X            compatible. Cmdline editing: CTRL-U instead of '@'. Made Vim DICE
  2168. X            compatible. Included regexp improvements from Olaf Seibert,
  2169. X            mapstring() removed. Removed bug with CTRL-U in insert mode.
  2170. X            Count allowed before ". Added uppercase (file) marks. Added
  2171. X            :marks command. Added joinspaces option. Added :jumps command. Made
  2172. X            jumplist compatible with tag list. Added count to :next and :Next.
  2173. X
  2174. X VIM 1.17 - Removed '"' for Ex register name. Repaired stupid bug in tag code.
  2175. X            Now compiled with Aztec 5.2a. Changed Arpbase.h for use with 2.04
  2176. X            includes. Added repdel option. Improved :set listing. Added count
  2177. X            to 'u' and CTRL-R commands. "vi:" and "ex:" in modelines must now
  2178. X            be preceded with a blank. Option "+command" for command line and
  2179. X            :edit command added.
  2180. X
  2181. X VIM 1.18 - Screen was not updated when all lines deleted. Readfile() now
  2182. X            puts cursor on first new line. Catch strange disk label.
  2183. X            Endless "undo line missing" loop removed. With empty file 'O' would
  2184. X            cause this. Added window size reset in windexit(). Flush .vim file
  2185. X            only when buffer has been changed. Added the nice things from
  2186. X            Elvis 1.5: Added "equalprg" and "ruler" option. Added quoting.
  2187. X            Added third meaning to 'backspace' option: backspacing over start
  2188. X            of insert. Added "-c {command}" command line option. Made generating
  2189. X            of prototypes automatically. Added insert mode command CTRL-O and
  2190. X            arrow keys. CTRL-T/CTRL-D now always insert/delete indent. When
  2191. X            starting an edit on specified lnum there was redraw of first lines.
  2192. X            Added 'inputmode' option. Added CTRL-A and CTRL-S commands. '`' is
  2193. X            now exclusive (as it should be). Added digraphs as an option.
  2194. X            Changed implementation of parameters. Added :wnext command.
  2195. X            Added ':@r' command. Changed handling of CTRL-V in command line.
  2196. X            Block macros now work. Added keyword lookup command 'K'. Added
  2197. X            CTRL-N and CTRL-P to command line editing. For DOS 2.0x the Flush
  2198. X            function is used for the autoscript file; this should solve the
  2199. X            lockup bug. Added wait_return to msg() for long messages.
  2200. X
  2201. X VIM 1.19 - Changes from Juergen Weigert:
  2202. X            Terminal type no longer restricted to machine console. New
  2203. X            option -T terminal. New set option "term". Builtin termcap 
  2204. X            entries for "amiga", "ansi", "atari", "nansi", "pcterm". 
  2205. X            Ported to MSDOS. New set option "textmode" ("tx") to control 
  2206. X            CR-LF translation. CTRL-U and CTRL-D scroll half a screen full,
  2207. X            rather than 12 lines. New set option "writebackup" ("wb") to 
  2208. X            disable even the 'backup when writing' feature.
  2209. X            Ported to SunOS. Full termcap support. Does resize on SIGWINCH.
  2210. X
  2211. X            Made storage.c portable. Added reading of ".vimrc". Added
  2212. X            'helpfile' option. With quoting the first char of an empty line
  2213. X            is inverted. Optimized screen updating a bit. Startup code 
  2214. X            looks for VIMINIT variable and .vimrc file first. Added option
  2215. X            helpfile. Solved bug of inserting deletes: redefined ISSPECIAL.
  2216. X            Changed inchar() to use key codes from termcap. Added parameters
  2217. X            for terminal codes. Replaced aux device handling by amiga window
  2218. X            handling. Added optional termcap code. Added 'V', format
  2219. X            operator.
  2220. X
  2221. X VIM 1.20 - wait_return only ignores CR, LF and space. 'V' also works for
  2222. X            single line. No redrawing while formatting text. Added CTRL-Z.
  2223. X            Added usage of termcap "ks" and "ke". Fixed showmatch().
  2224. X            Added timeout option. Added newfile argument to readfile().
  2225. X
  2226. X VIM 1.21 - Added block mode. Added 'o' command for quoting. Added :set inv.
  2227. X            Added pos2ptr(). Added repeating and '$' to Quoting.
  2228. X
  2229. X VIM 1.22 - Fixed a bug in doput() with count > 1.
  2230. X            Port to linux by Juergen Weigert included.
  2231. X            More unix semantics in writeit(), forceit flag ignores errors while 
  2232. X            preparing backup file. For UNIX, backup is now copied, not moved.
  2233. X            When the current directory is not writable, vim now tries a backup
  2234. X            in the directory given with the backupdir option. For UNIX, raw mode
  2235. X            has now ICRNL turned off, that allowes ^V^M. Makefiles for BSD,
  2236. X            SYSV, and linux unified in makefile.unix. For MSDOS
  2237. X            mch_get_winsize() implemented. Reimplemented builtin termcaps in
  2238. X            term.c and term.h. set_term() now handles all cases. Even builtins
  2239. X            when TERMCAP is defined. Show "..." while doing filename completion.
  2240. X
  2241. X VIM 1.23 -    Improved MSDOS version: Added function and cursor keys to builtin 
  2242. X            pcterm. Replaced setmode by settmode, delay by vim_delay and 
  2243. X            delline by dellines to avoid name conflicts. Made F1 help key.
  2244. X            Renamed makecmdtab to mkcmdtab and cmdsearch to csearch for 
  2245. X            8 char name limit. Wildcard expansion adds *.* to names without a 
  2246. X            dot. Added shell execution.
  2247. X            For unix: writeit() overwrites readonly files when forced write,
  2248. X            more safety checks. Termcap buffer for linux now 2048 bytes.
  2249. X            Expandone() no longer appends "*" to file name. Added "graphic"
  2250. X            option. Added ':' command to quoting.
  2251. X            
  2252. X VIM 1.24    Adjusted number of spaces inserted by dojoin(). MSDOS version uses 
  2253. X            searchpath() to find helpfile. Fixed a few small problems. Fixed 
  2254. X            nasty bug in getperm() for SAS 6.0. Removed second argument from 
  2255. X            wait_return(). Script files accessed in binary mode with MSDOS. 
  2256. X            Added 'u' and 'U' commands to quoting (make upper or lower case). 
  2257. X            Added "CTRL-V [0-9]*" to enter any byte value. Fixed doput().
  2258. X            Dodis() displays register 0. Added CTRL-B to insert mode. Attempt 
  2259. X            to fix the lockup bug by adding Delay() to startscript(). -v 
  2260. X            option now implies -n option. doformat() added to improve 'V' 
  2261. X            command. Replace bool_t with int. Fixed handling of \& and ~ in
  2262. X            regsub(). Added interrupt handling in msdos.c for ctrl-break and
  2263. X            critical errors. Added scrolljump option. Added :stop. Added -d
  2264. X            argument. Fixed bug in quickfix startup from cli. Fixed enforcer
  2265. X            hit with aux:. Added CTRL-C handling to unix.c. Fixed "O<BS><CR>" 
  2266. X            bug with autoindent. Worked around :cq not working by adding a 
  2267. X            printf()!? Added default mapping for MSDOS PageUp etc. Fixed 
  2268. X            cursor position after 'Y'. Added shift-cursor commands. Changed 
  2269. X            ExpandFile() to keep names with errors. Added CLEAR and CURSUPD 
  2270. X            arguments to updateScreen(). Fixed CTRL-@ after a change command.
  2271. X            modname() changes '.' into '_'. Added emptyrows to screen.c. 
  2272. X            Fixed redo of search with offset. Added count to 'z' command. 
  2273. X            Made :so! work with :global. Added writing of cursor postition to 
  2274. X            startscript(). Minimized terminal requirements. Fixed problem 
  2275. X            with line in tags file with mixed spaces and tabs. Fixed problem 
  2276. X            with pattern "\\" in :s and :g. This version posted on Usenet.
  2277. X
  2278. X VIM 1.25    Improved error messages for :set. Open helpfile in binary mode 
  2279. X            for MSDOS. Fixed ignorecase for Unix in cstrncmp(). Fixed read 
  2280. X            from NULL with :tags after vim -t. Repaired 'z' command. Changed 
  2281. X            outnum() for >32767. In msdos.c flushbuf did write(1, .. instead 
  2282. X            of write(0, .. Added secure to fix security. Fixed pointer 
  2283. X            use after free() bug in regsub() (made :s fail under MSDOS). 
  2284. X            Added nofreeNULL(), needed for some UNIXes. Improved window 
  2285. X            resizing for Unix. Fixed messages for report == 0. Added 
  2286. X            bsdmemset(). Changed a few small things for portability. Added 
  2287. X            :list. Made '0' and '^' exclusive. Fixed regexp for /pattern* 
  2288. X            (did /(pattern)* instead of /pattern(n)*). Added "']" and "'[". 
  2289. X            Changed Delay(2L) into Delay(10L). Made 'timeout' option 
  2290. X            vi-compatible, added 'ttimeout' option. Changed TIOCSETP to 
  2291. X            TIOCSETN in unix.c. Added "ti" and "te" termcap entries, makes 
  2292. X            sun cmdtool work. Added stop- and starttermcap(). Use cooked 
  2293. X            output for listings on Amiga only. Added "starting" flag, no ~s 
  2294. X            anymore with every startup. Modname made portable; Added 
  2295. X            'shortname' option, Fixed problems with .vim file on messydos. 
  2296. X            Global .exrc/.vimrc for Unix added. Added patches for SCO Xenix. 
  2297. X            Add :w argument to list of alternate file names. Applied a few 
  2298. X            changes for HPUX. Added Flock in writeit() for safety. Command 
  2299. X            ":'a,'bm." moved to 'b instead of current line. Argument in 
  2300. X            'shell' option allowed. Re-implemented :copy and :move. Fixed 
  2301. X            BS-CR-BS on empty line bug in edit.c. -t option was ignored if 
  2302. X            there is a file ".vim". Changed amiga.c to work without 
  2303. X            arp.library for dos 2.0. Fixed "\$" and "\^" in regexp. Fixed 
  2304. X            pipe in filter command. Fixed CTRL-U and CTRL-D. With '}' indent 
  2305. X            in front of the cursor is included in the operated text. Fixed 
  2306. X            tag with '[' in search pattern. Added CTRL-V to 'r'. Fixed "tc" 
  2307. X            entry in termlib.c. term_console now default off. Added :noremap 
  2308. X            and ^V in :map argument. Replaced CTRL by Ctrl because some 
  2309. X            unixes have this already. Fixed "Empty file" message disappearing 
  2310. X            when there is no .exrc file. Added CTRL-K for entering digraphs. 
  2311. X            Removed escape codes from vim.hlp, added handling of inversion to 
  2312. X            help().
  2313. X
  2314. X VIM 1.26    For Unix: Removed global .exrc; renamed global .vimrc to vimrc.
  2315. X             Moved names of *rc and help files to makefile. Added various 
  2316. X            little changes for different kinds of Unix. Changed CR-LF 
  2317. X            handling in dosource() for MSDOS. Added :mkvimrc. Fixed 
  2318. X            WildExpand in unix.c for empty file. Fixed incompatibility with 
  2319. X            msdos share program (removed setperm(fname, 0) from fileio.c).
  2320. X            Added ":set compatible". Fixed 'history=0'.
  2321. X
  2322. X VIM 1.27    Added USE_LOCALE. Changed swapchar() to use toupper() and 
  2323. X            tolower(). Changed init order: .vimrc before EXINIT. Half-fixed 
  2324. X            lines that do not fit on screen. A few minor bug fixes. Fixed 
  2325. X            typehead bug in Read() in unix.c. Added :number. Reset IXON flag 
  2326. X            in unix.c for CTRL-Q. In tags file any Ex command can be used. Ex 
  2327. X            search command accepts same flags as normal search command. Fixed 
  2328. X            '?' in tag search pattern. 'New file' message was wrong when 'bk' 
  2329. X            and 'wb' options were both off.
  2330. X
  2331. X Vim 1.29 to 1.31 and Vim 2.0    See ../readme2.0.
  2332. X
  2333. X Vim 2.0    When reading and writing files and in some other cases use short
  2334. X             filename if ":cd" not used. Fixes problem with networks. Deleted
  2335. X            "#include <ctype.h>" from regexp.c. ":v" without argument was not
  2336. X            handled correctly in doglob(). Check for tail recursion removed
  2337. X            again, because it forbids ":map! foo ^]foo", which is OK. Removed
  2338. X            redraw on exit for msdos. Fixed return value for FullName in
  2339. X            unix.c. Call_shell does not always use cooked mode, fixes problem
  2340. X            with typing CR while doing filename completion in unix. "r<TAB>"
  2341. X            now done by edit() to make expandtab works. Implemented FullName
  2342. X            for msdos. Implemented the drive specifier for the :cd command for
  2343. X            MSDOS. Added CTRL-B and CTRL-E to command line editing. Del key
  2344. X            for msdos not mapped to "x" in command mode, could not delete last
  2345. X            char of count. Fixed screen being messed up with long commands
  2346. X            when 'sc' is set. Fixed use of CR-LF in tags file. Added check
  2347. X            for abbreviation when typing ESC or CTRL-O in insert mode. Doing
  2348. X            a ":w file" does overwrite when "file" is the current file. Unmap
  2349. X            will check for 'to' string if there is no match with 'from'
  2350. X            string; Fixes ":unab foo" after ":ab foo bar". Fixed problem in
  2351. X            addstar() for msdos: Check for negative index. Added possibility
  2352. X            to switch off undo ":set ul=-1". Allow parameters to be set to
  2353. X            numbers >32000 for machines with 16 bit ints.
  2354. X
  2355. X Vim 2.1 to 3.0: see readme3.0
  2356. X
  2357. X*/
  2358. X
  2359. Xchar           *Version = "VIM 3.0";
  2360. X#if !defined(__DATE__) || !defined(__TIME__)
  2361. Xchar           *longVersion = "Vi IMproved 3.0 by Bram Moolenaar (1994 Aug 12)";
  2362. X#else
  2363. Xchar           *longVersion = "Vi IMproved 3.0 by Bram Moolenaar (1994 Aug 12, compiled " __DATE__ " " __TIME__ ")";
  2364. X#endif
  2365. END_OF_FILE
  2366.   if test 15714 -ne `wc -c <'vim/src/version.c'`; then
  2367.     echo shar: \"'vim/src/version.c'\" unpacked with wrong size!
  2368.   fi
  2369.   # end of 'vim/src/version.c'
  2370. fi
  2371. echo shar: End of archive 7 \(of 26\).
  2372. cp /dev/null ark7isdone
  2373. MISSING=""
  2374. 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 26 ; do
  2375.     if test ! -f ark${I}isdone ; then
  2376.     MISSING="${MISSING} ${I}"
  2377.     fi
  2378. done
  2379. if test "${MISSING}" = "" ; then
  2380.     echo You have unpacked all 26 archives.
  2381.     rm -f ark[1-9]isdone ark[1-9][0-9]isdone
  2382. else
  2383.     echo You still must unpack the following archives:
  2384.     echo "        " ${MISSING}
  2385. fi
  2386. exit 0
  2387. exit 0 # Just in case...
  2388.