home *** CD-ROM | disk | FTP | other *** search
/ Source Code 1994 March / Source_Code_CD-ROM_Walnut_Creek_March_1994.iso / compsrcs / misc / volume37 / vim / part11 < prev    next >
Encoding:
Text File  |  1993-04-23  |  41.3 KB  |  1,478 lines

  1. Newsgroups: comp.sources.misc
  2. From: mool@oce.nl (Bram Moolenaar)
  3. Subject: v37i011:  vim - Vi IMitation editor v1.27, Part11/24
  4. Message-ID: <1993Apr25.013353.22206@sparky.imd.sterling.com>
  5. X-Md4-Signature: 7dd7d0eb0e36ace8b947b5eeca1077f9
  6. Date: Sun, 25 Apr 1993 01:33:53 GMT
  7. Approved: kent@sparky.imd.sterling.com
  8.  
  9. Submitted-by: mool@oce.nl (Bram Moolenaar)
  10. Posting-number: Volume 37, Issue 11
  11. Archive-name: vim/part11
  12. Environment: UNIX, AMIGA, MS-DOS
  13.  
  14. #! /bin/sh
  15. # This is a shell archive.  Remove anything before this line, then unpack
  16. # it by saving it into a file and typing "sh file".  To overwrite existing
  17. # files, type "sh file -c".  You can also feed this as standard input via
  18. # unshar, or by typing "sh <file", e.g..  If this archive is complete, you
  19. # will see the following message at the end:
  20. #        "End of archive 11 (of 23)."
  21. # Contents:  vim/doc/index vim/src/storage.c
  22. # Wrapped by mool@oce-rd2 on Mon Apr 19 15:50:10 1993
  23. PATH=/bin:/usr/bin:/usr/ucb ; export PATH
  24. if test -f 'vim/doc/index' -a "${1}" != "-c" ; then 
  25.   echo shar: Will not clobber existing file \"'vim/doc/index'\"
  26. else
  27. echo shar: Extracting \"'vim/doc/index'\" \(18631 characters\)
  28. sed "s/^X//" >'vim/doc/index' <<'END_OF_FILE'
  29. Xindex of vim commands for
  30. X 1. insert mode
  31. X 2. VI commands (normal mode)
  32. X 3. command line editing
  33. X 4. EX commands
  34. X
  35. X(for an overview of options see the end of reference.doc)
  36. X
  37. X1. INSERT MODE
  38. X==============
  39. X
  40. Xchar        action
  41. X-----------------------------------------------------------------------
  42. X^@        insert previously inserted text and stop insert {vi: up to 128
  43. X        chars}
  44. X^A        insert previously inserted text {vi: no ^A}
  45. X^B <0-9a-z>    insert contents of register <0-9a-z> {not in vi}
  46. X^D        delete one shiftwidth of indent in the current line {vi: 
  47. X        only after auto-indent}
  48. X^E        insert the character which is below the cursor
  49. X^H <BS>        delete character before the cursor {vi: does not cross lines,
  50. X        does not delete autoindents}
  51. X^J <LF>        begin new line
  52. X^K {char1} {char2} enter digraph (only when compiled with it) {vi: no digraphs}
  53. X^O        execute a single command and return to insert mode
  54. X^M <CR>        begin new line
  55. X^R        insert the character which is above the cursor
  56. X^T        insert one shiftwidth of indent in current line {vi: only in 
  57. X        autoindent}
  58. X^U        delete all entered characters in the current line
  59. X^V        insert next non-digit literally, insert three digit decimal 
  60. X        number as a single byte.
  61. X^W        delete word before the cursor
  62. X^[ <ESC>    end insert mode
  63. X<DEL>        same as ^H <BS>
  64. X<C_UP>        cursor one line up
  65. X<C_DOWN>    cursor one line down
  66. X<C_LEFT>    cursor one character left
  67. X<C_RIGHT>    cursor one character right
  68. X<SC_UP>        one screenfull backward
  69. X<SC_DOWN>    one screenfull forward
  70. X<SC_LEFT>    cursor one word left
  71. X<SC_RIGHT>    cursor one word right
  72. X{char1}<BS>{char2} enter digraph (only when compiled with it and 'digraph' 
  73. X        option set) {vi: no digraphs}
  74. X
  75. X
  76. X2. VI COMMANDS
  77. X==============
  78. X
  79. XCHAR means non-blank char
  80. XWORD means sequences of non-blank chars
  81. XN is number entered before the command
  82. X<move> is a cursor movement command
  83. XNmove is the text that is moved over with a cursor movement command
  84. XSECTION is a section that possibly starts with '}' instead of '{'
  85. X
  86. Xnote: 1 = cursor movement command; 2 = can be undone/redone
  87. X
  88. Xchar        note    vim normal mode (vi: what the unix vi does)
  89. X------------------------------------------------------------------------------
  90. X^@            error
  91. X^A        2    add N to number at/after cursor {vi: no ^A}
  92. X^B        1    scroll N screens Backwards
  93. X^C            interrupt current (search) command
  94. X^D            scroll Down N lines (default: half a screen)
  95. X^E            scroll N lines upwards (N lines Extra)
  96. X^F        1    scroll N screens Forward
  97. X^G            display current file name and position
  98. X^H <BS>        1    cursor N chars to the left
  99. X^I <TAB>    1    go to N newer entry in jump list
  100. X^J <LF>        1    cursor N lines downward
  101. X^K            error
  102. X^L            redraw screen
  103. X^M <CR>        1    cursor to the first CHAR N lines lower
  104. X^N        1    cursor N lines downward
  105. X^O        1    go to N older entry in jump list
  106. X^P        1    cursor N lines upward
  107. X^Q            start blockwise quoting (vi: no quoting)
  108. X^R        2    redo changes which were undone with 'u' (vi: no redo)
  109. X^S        2    subtract N from number at/after cursor {vi: no ^S}
  110. X^T            jump to N older Tag in tag list
  111. X^U            scroll N lines Upwards (default: half a screen)
  112. X^V            error
  113. X^W            error
  114. X^X            error
  115. X^Y            scroll N lines downwards
  116. X^Z            suspend program (or start new shell)
  117. X^[ <ESC>        error
  118. X^\            error
  119. X^]            :ta to ident under cursor
  120. X^^            edit Nth alternate file (equivalent to :e #N)
  121. X^_            error
  122. X
  123. X<SPACE>        1    cursor N chars to the right
  124. X!<move><filter>        filter Nmove text through the "filter" command
  125. X!!<filter>        filter N lines through the "filter" command
  126. X"<a-zA-Z0-9.>        use buffer <a-zA-Z0-9.> for next delete, yank or put
  127. X            (upper case to append)(<.> only works for put)
  128. X#        1    search backward for the Nth occurrence of the ident under
  129. X            the cursor {not in vi}
  130. X$        1    cursor to the end of line N from the cursor
  131. X%        1    find the next (curly/square) bracket on this line and go
  132. X            to its match. With count: go to N percentage in the file.
  133. X&        2    repeat last :s
  134. X'<a-zA-Z>    1    cursor to the first CHAR on the line with mark <a-zA-Z>
  135. X'[        1    cursor to the first CHAR on the line of the start of 
  136. X            last operated text or start of putted text
  137. X']        1    cursor to the first CHAR on the line of the end of 
  138. X            last operated text or end of putted text
  139. X''        1    cursor to the first CHAR of the line where the cursor was
  140. X            before the latest jump.
  141. X(        1    cursor N sentences backward
  142. X)        1    cursor N sentences forward
  143. X*        1    search forward for the Nth occurrence of the ident under
  144. X            the cursor {not in vi}
  145. X+        1    cursor to the first CHAR N lines lower
  146. X,        1    repeat latest f, t, F or T in opposite direction N times
  147. X-        1    cursor to the first CHAR N lines higher
  148. X.        2    repeat last change with count replaced by N
  149. X/<pattern>    1    search forward for the Nth occurrence of <pattern>
  150. X0        1    cursor to the first char of the line
  151. X1            prepend to command to give a count
  152. X2            "
  153. X3            "
  154. X4            "
  155. X5            "
  156. X6            "
  157. X7            "
  158. X8            "
  159. X9            "
  160. X:            Ex command (see below)        
  161. X;        1    repeat latest f, t, F or T N times
  162. X<<move>        2    shift the Nmove lines one shiftwidth leftwards
  163. X<<        2    shift N lines one shiftwidth leftwards
  164. X=<move>        2    filter Nmove lines through "indent" (vi: when option
  165. X            'lisp' is set autoindent Nmove lines)
  166. X==        2    filter N lines through "indent"
  167. X><move>        2    shift Nmove lines one shiftwidth rightwards
  168. X>>        2    shift N lines one shiftwidth rightwards
  169. X?<pattern>    1    search backward for the Nth previous occurrence of
  170. X            <pattern>
  171. X@<a-z>        2    execute the contents of named buffer <a-z> N times
  172. X@@        2    repeat the previous @<a-z> N times
  173. XA        2    append text at the end of the line N times
  174. XB        1    cursor N WORDS backward
  175. X<"x>C        2    change from the cursor position to the end of the line,
  176. X            and N-1 more lines [into buffer x]; synonym for c$
  177. X<"x>D        2    delete the characters under the cursor until the end of
  178. X            the line and N-1 more lines [into buffer x]; synonym for d$
  179. XE        1    cursor forward to the end of WORD N
  180. XF<char>            cursor to the Nth occurrence of <char> to the left
  181. XG        1    cursor to line N, default last line
  182. XH        1    cursor to line N from top of screen
  183. XI        2    insert text before the first CHAR on the line N times
  184. XJ        2    Join N lines; default is 2
  185. XK            lookup Keyword under the cursor with "keywordprg"
  186. XL        1    cursor to line N from bottom of screen
  187. XM        1    cursor to middle line of screen
  188. XN        1    repeat the latest '/' or '?' N times in opposite
  189. X            direction
  190. XO        2    begin a new line above the cursor and insert text, repeat
  191. X            N times (vi: blank N screen lines)
  192. X<"x>P        2    put the text [from buffer x] before the cursor N times
  193. XQ            start quoting lines (vi: go to Ex mode)
  194. XR        2    enter replace mode: overtype existing characters, repeat the
  195. X            entered text N-1 times
  196. X<"x>S        2    delete N lines [into buffer x] and start insert; synonym
  197. X            for ^cc or 0cc, depending on autoindent
  198. XT<char>        1    cursor till after Nth occurrence of <char> to the left
  199. XU        2    undo all latest changes on one line (vi: while not moved
  200. X            off of it)
  201. X            While quoting: make lowercase
  202. XV<move>        2    Join N lines and re-format them
  203. XW        1    cursor N WORDS forward
  204. X<"x>X        2    delete N characters before the cursor [into buffer x]
  205. X<"x>Y            yank N lines [into buffer x]; synonym for yy
  206. XZZ            store current file, if modified, and exit        
  207. X[[        1    cursor N sections backward
  208. X[]        1    cursor N SECTIONS backward
  209. X\            error
  210. X]]        1    cursor N sections forward
  211. X][        1    cursor N SECTIONS forward
  212. X^        1    cursor to the first CHAR of the line
  213. X_        1    cursor to the first CHAR N - 1 lines lower
  214. X`<a-zA-Z>    1    cursor to the mark <a-zA-Z>
  215. X`[        1    cursor to the start of last operated text or start of 
  216. X            putted text
  217. X`]        1    cursor to the end of last operated text or end of 
  218. X            putted text
  219. X``        1    cursor to the position before latest jump
  220. Xa        2    append text after the cursor N times
  221. Xb        1    cursor N words backward
  222. X<"x>c<move>    2    delete Nmove text [into buffer x] and start insert
  223. X<"x>cc        2    delete N lines [into buffer x] and start insert
  224. X<"x>d<move>    2    delete Nmove text [into buffer x]
  225. X<"x>dd        2    delete N lines [into buffer x]
  226. Xe        1    cursor forward to the end of word N
  227. Xf<char>        1    cursor to Nth occurrence of <char> to the right
  228. Xg            error
  229. Xh        1    cursor N chars to the left
  230. Xi        2    insert text before the cursor N times
  231. Xj        1    cursor N lines downward
  232. Xk        1    cursor N lines upward
  233. Xl        1    cursor N chars to the right
  234. Xm<a-z>            set mark <a-z> at cursor position        
  235. Xn        1    repeat the latest '/' or '?' N times
  236. Xo        2    begin a new line below the cursor and insert text, repeat
  237. X            N times (vi: blank N screen lines)
  238. X            While quoting: cursor moves other end
  239. X<"x>p        2    put the text [from buffer x] after the cursor N times
  240. Xq            start quoting characters
  241. Xr<char>        2    replace N chars by <char>
  242. X<"x>s        2    (substitute) delete N characters [into buffer x] and
  243. X            start insert
  244. Xt<char>        1    cursor till before Nth occurrence of <char> to the right
  245. Xu        2    undo changes (vi: only one level)
  246. X            While quoting: make uppercase
  247. Xv<a-zA-Z>        record typed characters into named buffer <a-zA-Z>
  248. X            (upper case to append)
  249. Xv            stops recording (vi: no recording)
  250. Xw        1    cursor N words forward
  251. X<"x>x        2    delete N characters under and after the cursor [into
  252. X            buffer x]
  253. X<"x>y<move>        yank Nmove text [into buffer x]
  254. X<"x>yy            yank N lines [into buffer x]
  255. Xz<CR>            redraw, cursor line to top of window        
  256. Xz.            redraw, cursor line to center of window
  257. Xz-            redraw, cursor line at bottom of window
  258. X{        1    cursor N paragraphs backward
  259. X|        1    cursor to column N
  260. X}        1    cursor N paragraphs forward
  261. X~        2    option notildeop: switch case of N characters under
  262. X            cursor and move the cursor N characters to the right
  263. X            (vi: no count)
  264. X~<move>            option tildeop: switch case of Nmove text (vi: no tildeop
  265. X            option)
  266. X<DEL>            when entering a number: remove the last digit
  267. X<HELP>            show the file vim:vim.hlp page by page (vi: no help)
  268. X<C_UP>        1    move cursor N lines upwards
  269. X<C_DOWN>    1    move cursor N lines downwards
  270. X<C_LEFT>    1    move cursor N chars to the left
  271. X<C_RIGHT>    1    move cursor N chars to the right
  272. X<SC_UP>        1    scroll N screens Backwards (same as ^B)
  273. X<SC_DOWN>    1    scroll N screens Forwards (same as ^F)
  274. X<SC_LEFT>    1    cursor N words backward (same as b)
  275. X<SC_RIGHT>    1    cursor N words forward (same as w)
  276. X
  277. X
  278. X3. command line editing
  279. X=======================
  280. X
  281. XGet to the command line with the ':', '!', '/' or '?' commands.
  282. XNormal characters are inserted at the current cursor position.
  283. X(vi: can only alter last character in the line)
  284. X
  285. X^D        list filenames that match the pattern in front of the cursor
  286. X^H        delete the character in front of the cursor
  287. X^N        only after an <ESC> with multiple matches: go to next match
  288. X^P        only after an <ESC> with multiple matches: go to previous match
  289. X^V        insert next non-digit literally, insert three digit decimal 
  290. X        number as a single byte. {Vi: type the CTRL-V twice to get one}
  291. X<ESC>           do filename completion on the pattern in front of the cursor
  292. X@        remove all characters
  293. X<DEL>        delete the character under the cursor
  294. X<C_UP>        recall previous command line from history
  295. X<C_DOWN>    recall next command line from history
  296. X<C_LEFT>    cursor left
  297. X<C_RIGHT>    cursor right
  298. X<SC_LEFT>    cursor one word left
  299. X<SC_RIGHT>    cursor one word right
  300. X
  301. X
  302. X4. EX commands
  303. X==============
  304. X
  305. Xlines that start with " or # are ignored
  306. X
  307. X<range> stands for a series of line specifiers, separated with ',' or ';'.
  308. XWhen separated with ';' the cursor position will be set to that line before
  309. Xinterpreting the next line specifier.
  310. XThe default line specifier (for most commands) is the Cursor position.
  311. Xline numbers may be specified with:
  312. X    <number>    the absolute line number
  313. X    .        the current line
  314. X    $        the last line in the file
  315. X    %        equal to 1,$ (the entire file)
  316. X    't        position of mark t
  317. X    /<pattern>    the next line where <pattern> matches
  318. X    ?<pattern>    the previous line where <pattern> matches
  319. XEach may be followed (several times) by '+' or '-' and an optional number.
  320. XThis number is added or subtracted from the preceding line number.
  321. Xif the number is omitted, 1 is used.
  322. XExamples:
  323. X    .+3        three lines below the cursor
  324. X    /that+1        the line below the next line containing "that"
  325. X    .,$        from current line until end of file
  326. X
  327. XIn the commands below the characters in square brackets are optional.
  328. X
  329. X:<range>        set the cursor on the (last) specified line number
  330. X
  331. X:a[ppend]        {vi: append text}
  332. X
  333. X:ar[gs]            print the file list, with the current file in []
  334. X
  335. X:cc [nr]        Display error [nr] (default is same error)
  336. X
  337. X:cd            print the current directory name {vi: no such command}
  338. X:cd <path>        change the current directory to <path>
  339. X
  340. X:cf            read error file (from errorfile option)
  341. X
  342. X:c[hange]        {vi: replace lines}
  343. X
  344. X:ch[dir]        same as :cd
  345. X
  346. X:cn            display next error
  347. X
  348. X:[range]co[py] {address} copy lines from [range] to {address}
  349. X
  350. X:cp            display previous error
  351. X
  352. X:cq            Quit without writing and return an error code
  353. X
  354. X:[<range>]d[elete] [x] [count]
  355. X            delete <range> lines (default: current line)
  356. X
  357. X:dig[raph]        display currently defined digraphs {not in vi}
  358. X
  359. X:dig[raph] {char1}{char2} {number} ...
  360. X            define the character pair {char1} {char2} to be the 
  361. X            digraph for character {number}. {number} is entered 
  362. X            as digits.
  363. X
  364. X:di[splay]        display the contents of numbered and named buffers
  365. X            {vi: no such command}
  366. X
  367. X:e[dit] [file]        edit 'file' (default: current file), unless changes have
  368. X            been made {vi: allow +n to start at certain position}
  369. X:e[dit]! [file]        edit 'file' (default: current file) always
  370. X
  371. X:ex            same as :edit
  372. X
  373. X:f[ile]            prints the current file name and some more info
  374. X:f[ile] <name>        sets current file name to <name>
  375. X:files            lists the alternate file names
  376. X
  377. X:<range>g[lobal]/<pattern>/<cmd>
  378. X            execute the EX command <cmd> on the lines where <pattern>
  379. X            matches
  380. X:<range>g[lobal]!/<pattern>/<cmd>
  381. X            execute the EX command <cmd> on the lines where <pattern>
  382. X            does not match
  383. X
  384. X:h[elp]            show the help file page by page {vi: no help}
  385. X
  386. X:i[nsert]        {vi: insert text}
  387. X
  388. X:<range>j[oin]        join <range> lines
  389. X
  390. X:ju[mps]        print jump list {vi: no such command}
  391. X
  392. X:[range]k<a-z>        set mark without a space
  393. X
  394. X:l[ist]            {vi: list lines}
  395. X
  396. X:map <lhs> <rhs>    map the key sequence <lhs> to <rhs> in normal mode
  397. X:map! <lhs> <rhs>    map the key sequence <lhs> to <rhs> in insert mode
  398. X
  399. X:[range]ma[rk] <a-z>    set mark
  400. X
  401. X:marks            list all marks {vi: no such command}
  402. X
  403. X:mk[exrc]        write options to .exrc file
  404. X:mkv[imrc]        write options to .vimrc file {not in vi}
  405. X
  406. X:[range]m[ove] {address} move lines from [range] to {address}
  407. X
  408. X:n[ext]            edit next file, unless changes have been made
  409. X:n[ext]!        edit next file
  410. X:n[ext] <filelist>    define <filelist> as the new list of files and edit
  411. X            the first one, unless changes have been made
  412. X:n[ext]! <filelist>    define <filelist> as the new list of files and edit
  413. X            the first one {vi: +command to start editing at a
  414. X            specified position}
  415. X
  416. X:noremap <lhs> <rhs>    map the key sequence <lhs> to <rhs> in normal mode, 
  417. X            disallow remapping of <rhs> {not in vi}
  418. X:noremap! <lhs> <rhs>    map the key sequence <lhs> to <rhs> in insert mode,
  419. X            disallow remapping of <rhs> {not in vi}
  420. X
  421. X:nu[mber]        {vi: print specified lines with their line number}
  422. X
  423. X:N[ext]            edit previous file in file list, unless changes have
  424. X            been made
  425. X:N[ext]!        edit previous file in file list
  426. X
  427. X:o[pen]            {vi: start editing in open mode}
  428. X
  429. X:[count]po[p][!]    jump to [count] older tag in tag list {vi: no such command}
  430. X
  431. X:pres[erve]        {vi: emergency exit}
  432. X
  433. X:<range>p[rint]        print the specified lines
  434. X
  435. X:pu[t] [x]        insert text from buffer [x] below current line
  436. X:pu[t]! [x]        insert text from buffer [x] above current line
  437. X
  438. X:pr[evious]        same as :Next
  439. X
  440. X:q[uit]         quit, unless changes have been made
  441. X:q[uit]!        quit always, without writing
  442. X
  443. X:r[ead] <name>        insert the file <name> below the cursor
  444. X:r[ead]!<cmd>        excute <cmd> and insert its standard output below the
  445. X            cursor
  446. X
  447. X:rec[over]        {vi: recover a file after a crash or :preserve}
  448. X
  449. X:rew[ind]        start editing the first file in the file list, unless
  450. X            changes have been made
  451. X:rew[ind]!        start editing the first file in the file list
  452. X
  453. X:se[t]            show all modified options {vi: non-default options}
  454. X:se[t] all        show all options
  455. X:se[t] <option>        set toggle option on, show value of string or number
  456. X            option
  457. X:se[t] no<option>    set toggle option off
  458. X:se[t] inv<option>    invert toggle option
  459. X:se[t] <option>=<value> set string or number option to <value>
  460. X:se[t] <option>?    show value of <option>
  461. X
  462. X:sh[ell]        escape to a shell {vi: shell name from option 'shell'}
  463. X
  464. X:so[urce] <file>    read EX commands from <file>
  465. X:so[urce]! <file>    read VI commands from <file> {vi: no such command}
  466. X
  467. X:st[op][!]        suspend the editor
  468. X
  469. X:<range>s[ubstitute]/<pattern>/<string>/<option>
  470. X            for each line in <range> replace the first occurrence of
  471. X            <pattern> by <string>; with <option> 'g' all occurrences
  472. X            on the line are replaced; with <option> 'c' each
  473. X            replace has to be confirmed
  474. X:<range>s[ubstitute]    repeat last :substitute
  475. X
  476. X:t            synonym for copy
  477. X
  478. X:ta[g] <ident>        search for <indent> in the tags file and execute
  479. X            the accompanying command, unless changes have been made
  480. X:ta[g]! <ident>        search for <indent> in the tags file and execute
  481. X            the accompanying command
  482. X
  483. X:[count]ta[g][!]    jump to [count] newer tag in tag list {vi: no such command}
  484. X
  485. X:tags            print the tag list {vi: no such command}
  486. X
  487. X:una[bbreviate]        {vi: remove from abbreviation list}
  488. X
  489. X:u[ndo]            undo last change
  490. X
  491. X:unm[ap] <lhs>        remove the mapping of <lhs> for normal mode
  492. X:unm[ap]! <lhs>        remove the mapping of <lhs> for insert mode
  493. X
  494. X:ve[rsion]        print the version number of the editor
  495. X
  496. X:<range>v[global]/<pattern>/<cmd>
  497. X            execute the EX command <cmd> on the lines where <pattern>
  498. X            does not match
  499. X
  500. X:vi[sual]        {vi: switch from EX or open to visual mode}
  501. X
  502. X:wi[nsize] <width> <height>
  503. X            Set effective window size to <width> columns and <height>
  504. X            rows. Does not change actual window size. Should only be
  505. X            used from script files. {vi: no such command}
  506. X
  507. X:<range>w[rite][!]    write the specified lines to the current file
  508. X:<range>w[rite]    <file>    write the specified lines to <file>, unless it
  509. X            already exists
  510. X:<range>w[rite]! <file>    write the specified lines to <file>
  511. X:<range>w[rite][!] >>    append the specified lines to the current file
  512. X:<range>w[rite][!] >> <file>
  513. X            append the specified lines to <file>
  514. X:<range>w[rite] !<cmd>    execute <cmd> with <range> lines as standard input
  515. X
  516. X:wq            write the current file and exit if no more files
  517. X:wq!            write the current file and exit
  518. X:wq <file>        write to <file> and exit if no more files
  519. X:wq! <file>        write to <file> and exit
  520. X
  521. X:x[it][!] [file]    same as :wq, but write only when changes have been made
  522. X
  523. X:y[ank] [x]        copy lines into buffer [x]
  524. X
  525. X:z            {vi: print some lines}
  526. X
  527. X:@<reg>            execute contents of buffer <reg> as an Ex command 
  528. X            {only in some versions of vi}
  529. X
  530. X:@@            repeat last :@<reg> command.
  531. X
  532. X:![!]<cmd> [!][<arg>]    execute <cmd> with the shell, replace the optional bangs
  533. X            with the previously given command, append the optional
  534. X            <arg>
  535. X:<range>![!]<cmd> [!][<arg>]
  536. X            filter <range> lines through <cmd>, replace the optional bangs
  537. X            with the previously given command, append the optional
  538. X            <arg>
  539. X
  540. X:<            shift left
  541. X
  542. X:>            shift right
  543. X
  544. X:=            print the line number
  545. X
  546. X:&            same as :substitute
  547. X
  548. X:~            {vi: do a substitute on the previous regular expression}
  549. END_OF_FILE
  550. if test 18631 -ne `wc -c <'vim/doc/index'`; then
  551.     echo shar: \"'vim/doc/index'\" unpacked with wrong size!
  552. fi
  553. # end of 'vim/doc/index'
  554. fi
  555. if test -f 'vim/src/storage.c' -a "${1}" != "-c" ; then 
  556.   echo shar: Will not clobber existing file \"'vim/src/storage.c'\"
  557. else
  558. echo shar: Extracting \"'vim/src/storage.c'\" \(19504 characters\)
  559. sed "s/^X//" >'vim/src/storage.c' <<'END_OF_FILE'
  560. X/* vi:ts=4:sw=4
  561. X *
  562. X * VIM - Vi IMitation
  563. X *
  564. X * Code Contributions By:    Bram Moolenaar            mool@oce.nl
  565. X *                            Tim Thompson            twitch!tjt
  566. X *                            Tony Andrews            onecom!wldrdg!tony 
  567. X *                            G. R. (Fred) Walter        watmath!watcgl!grwalter 
  568. X */
  569. X
  570. X/*
  571. X * storage.c: allocation of lines and management of them
  572. X *
  573. X * part 1: storage allocation for the lines and blocks of the current file
  574. X * part 2: managing of the pointer blocks
  575. X */
  576. X
  577. X#include "vim.h"
  578. X#include "globals.h"
  579. X#include "proto.h"
  580. X
  581. X/***************************************************************************
  582. X * part 1: storage allocation for the lines and blocks of the current file *
  583. X ***************************************************************************/
  584. X
  585. X/*
  586. X * Memory is allocated in relatively large blocks. These blocks are linked
  587. X * in the allocated block list, headed by m_ahead. They are all freed
  588. X * when abandoning a file.
  589. X *
  590. X * The available chunks of memory are kept in the free chunk list, headed
  591. X * by m_fhead. This is a circular list. m_search points to the chunk before the
  592. X * chunk that was freed/allocated the last time. alloc_line() gets a chunk
  593. X * from the free list; free_line() returns a chunk to the free list.
  594. X */
  595. X
  596. X    /* on the Amiga the blocksize must not be a multiple of 256 */
  597. X    /* with MS-Dos the blocksize must be larger than 255 */
  598. X    /* For Unix it does not really matter */
  599. X#define MEMBLOCKSIZE 2044
  600. X
  601. Xtypedef struct m_info info_t;
  602. X
  603. X/*
  604. X * There are two types of in-use memory chunks:
  605. X *    1. those that are allocated by readfile(). These are always preceded
  606. X *        by a NUL character and end in a NUL character. The chunk must not
  607. X *        contain other NUL characters. The preceding NUL is used to
  608. X *        determine the chunk type. The ending NUL is used to determine the
  609. X *        end of the chunk. The preceding NUL is not part of the chunk, the
  610. X *        ending NUL is. 
  611. X *  2. the other chunks have been allocated with alloc_line(). They are
  612. X *        preceded by a non-NUL character. This is used to determine the chunk
  613. X *        type. The non-NUL may be part of a size field or may be an extra 0xff
  614. X *        byte. The chunk always ends in a NUL character and may also contain
  615. X *        a NUL character. The size field contains the size of the chunk,
  616. X *        including the size field. The trailing NUL may be used by a possibly
  617. X *        follwing type 1 chunk. The preceding size, the optional 0xff and the
  618. X *        trailing NUL are all part of the chunk.
  619. X *
  620. X * When the chunk is not in-use it is preceded with the m_info structure.
  621. X * The m_next field links it in the free chunk list. It must still end in
  622. X * a NUL byte, because it may be followed by a type 1 chunk!
  623. X *
  624. X * When in-use we must make sure there is a non-NUL byte in front of type
  625. X * 2 chunks.
  626. X *
  627. X * On the Amiga this means that the size must not be a multiple of 256.
  628. X * This is done by multiplying the size by 2 and adding one.
  629. X *
  630. X * On MS-DOS the size must be larger than 255. This is done by adding 256
  631. X * to the size.
  632. X *
  633. X * On Unix systems an extra 0xff byte is added. This costs 4 bytes because
  634. X * pointers must be kept long-aligned.
  635. X *
  636. X * On most unix systems structures have to be longword aligned.
  637. X * On most other systems they are short (16 bit) aligned.
  638. X */
  639. X
  640. X#ifdef UNIX
  641. X# define ALIGN_LONG        /* 32 bit alignment and use filler byte */
  642. X#else
  643. X# ifdef AMIGA
  644. X#  define LOWBYTE        /* size must not be multiple of 256 */
  645. X# else
  646. X#  ifdef MSDOS
  647. X#   define HIGHBYTE        /* size must be larger than 255 */
  648. X#  else
  649. X    you must define something!
  650. X#  endif
  651. X# endif
  652. X#endif
  653. X
  654. Xstruct m_info
  655. X{
  656. X#ifdef ALIGN_LONG
  657. X    u_long     m_size;    /* size of the chunk (including m_info) */
  658. X#else
  659. X    u_short  m_size;    /* size of the chunk (including m_info) */
  660. X#endif
  661. X    info_t    *m_next;    /* pointer to next free chunk in the list */
  662. X};
  663. X
  664. X#ifdef ALIGN_LONG
  665. X    /* size of m_size + room for 0xff byte */
  666. X# define M_OFFSET (sizeof(u_long) * 2)
  667. X#else
  668. X    /* size of m_size */
  669. X# define M_OFFSET (sizeof(u_short))
  670. X#endif
  671. X
  672. Xstatic char     *m_ahead = NULL;        /* head of allocated memory block list */
  673. X
  674. Xstatic info_t m_fhead = {0, NULL};    /* head of free chunk list */
  675. X
  676. Xstatic info_t *m_search = NULL;     /* pointer to chunk before previously
  677. X                                       allocated/freed chunk */
  678. X
  679. X#ifdef DEBUG
  680. X# ifdef AMIGA
  681. Xm_error()
  682. X{
  683. X    printf("list error\n");
  684. X}
  685. X# endif
  686. X
  687. Xcheck_list()
  688. X{
  689. X# ifdef AMIGA
  690. X    register info_t *mp;
  691. X
  692. X    for (mp = &m_fhead; ; )
  693. X    {
  694. X        /*
  695. X         * adjust these addresses for the actual available memory!
  696. X         */
  697. X        if (mp >= 0x080000L && mp < 0x200000L ||
  698. X            mp >= 0x400000L && mp < 0xc00000 ||
  699. X            mp >= 0xc80000 || mp->m_next->m_size > 23000)
  700. X        {
  701. X            m_error();
  702. X            return 1;
  703. X        }
  704. X        mp = mp->m_next;
  705. X        if (mp == &m_fhead)
  706. X            break;
  707. X    }
  708. X# endif
  709. X    return 0;
  710. X}
  711. X#endif    /* DEBUG */
  712. X
  713. X/*
  714. X * Allocate a block of memory and link it in the allocated list, so that
  715. X * the block will be freed when abandoning the file.
  716. X */
  717. X    char *
  718. Xm_blockalloc(size, message)
  719. X    u_long    size;
  720. X    int        message;
  721. X{
  722. X    char *p;
  723. X
  724. X    p = lalloc(size + sizeof(char *), message);
  725. X    if (p != NULL)
  726. X    {
  727. X        *(char **)p = m_ahead;
  728. X        m_ahead = p;
  729. X        p += sizeof(char *);
  730. X    }
  731. X    return p;
  732. X}
  733. X
  734. X/*
  735. X * free all allocated memory blocks
  736. X */
  737. X    void
  738. Xm_blockfree()
  739. X{
  740. X    char *p, *np;
  741. X
  742. X    for (p = m_ahead; p != NULL; p = np)
  743. X    {
  744. X        np = *(char **)p;
  745. X        free(p);
  746. X    }
  747. X    m_ahead = NULL;
  748. X    m_search = NULL;
  749. X}
  750. X
  751. X/*
  752. X * Free a chunk of memory which was
  753. X *  1. inserted with readfile(); these are preceded with a NUL byte
  754. X *  2. allocated with alloc_line(); these are preceded with a non-NUL byte
  755. X * Insert the chunk into the free list, keeping it sorted on address.
  756. X */
  757. X    void
  758. Xfree_line(ptr)
  759. X    char *ptr;
  760. X{
  761. X    info_t            *mp;
  762. X    register info_t *next;
  763. X    info_t            *prev, *curr;
  764. X    long            len;
  765. X
  766. X#ifdef DEBUG
  767. X    if (check_list())
  768. X        return;
  769. X#endif
  770. X    if (ptr == NULL || ptr == IObuff)
  771. X        return;    /* illegal address can happen in out-of-memory situations */
  772. X
  773. X    if (*(ptr - 1) == NUL)        /* type 1 chunk: no size field */
  774. X    {
  775. X#ifdef ALIGN_LONG        /* use longword alignment */
  776. X        long c;
  777. X
  778. X        len = strlen(ptr) + 1;
  779. X        if ((c = ((long)ptr & 3)) != 0)     /* lose some bytes */
  780. X        {
  781. X            c = 4 - c;
  782. X            ptr += c;
  783. X            len -= c;
  784. X        }
  785. X#else            /* use short (16 bit) alignment */
  786. X        len = strlen(ptr) + 1;
  787. X        if ((long)ptr & 1)                    /* lose a byte */
  788. X        {
  789. X            ++ptr;
  790. X            --len;
  791. X        }
  792. X#endif    /* ALIGN_LONG */
  793. X
  794. X        /* we must be able to store size, pointer and a trailing NUL */
  795. X        /* otherwise we can't fit it in the free list */
  796. X        if (len <= (long)sizeof(info_t))
  797. X            return;            /* these bytes are not used until you quit the file */
  798. X        mp = (info_t *)ptr;
  799. X        mp->m_size = len;
  800. X    }
  801. X#ifdef ALIGN_LONG
  802. X    else if ((*(ptr - 1) & 0xff) == 0xff)    /* type 2 chunk: has size field */
  803. X    {
  804. X        mp = (info_t *)(ptr - M_OFFSET);
  805. X    }
  806. X    else
  807. X    {
  808. X        emsg("Illegal chunk");
  809. X        return;
  810. X    }
  811. X#endif
  812. X#ifdef LOWBYTE
  813. X    else             /* type 2 chunk: has size field */
  814. X    {
  815. X        mp = (info_t *)(ptr - M_OFFSET);
  816. X        mp->m_size >>= 1;
  817. X    }
  818. X#endif
  819. X#ifdef HIGHBYTE
  820. X    else             /* type 2 chunk: has size field */
  821. X    {
  822. X        mp = (info_t *)(ptr - M_OFFSET);
  823. X        mp->m_size -= 256;
  824. X    }
  825. X#endif
  826. X
  827. X    curr = NULL;
  828. X    /* if mp is smaller than m_search->m_next we start at m_fhead */
  829. X    if (mp < (m_search->m_next))
  830. X        next = &m_fhead;
  831. X    else
  832. X        next = m_search;
  833. X    do
  834. X    {
  835. X        prev = curr;
  836. X        curr = next;
  837. X        next = next->m_next;
  838. X    }
  839. X    while (mp > next && next != &m_fhead);
  840. X
  841. X/* if *mp and *next are concatenated, join them into one chunk */
  842. X    if ((char *)mp + mp->m_size == (char *)next)
  843. X    {
  844. X        mp->m_size += next->m_size;
  845. X        mp->m_next = next->m_next;
  846. X    }
  847. X    else
  848. X        mp->m_next = next;
  849. X
  850. X/* if *curr and *mp are concatenated, join them */
  851. X    if (prev != NULL && (char *)curr + curr->m_size == (char *)mp)
  852. X    {
  853. X        curr->m_size += mp->m_size;
  854. X        curr->m_next = mp->m_next;
  855. X        m_search = prev;
  856. X    }
  857. X    else
  858. X    {
  859. X        curr->m_next = mp;
  860. X        m_search = curr;    /* put m_search before freed chunk */
  861. X    }
  862. X#ifdef DEBUG
  863. X    check_list();
  864. X#endif
  865. X}
  866. X
  867. X/*
  868. X * Allocate and initialize a new line structure with room for at least
  869. X * 'size' characters.
  870. X */
  871. X    char *
  872. Xalloc_line(size)
  873. X    register unsigned size;
  874. X{
  875. X    register info_t *mp, *mprev, *mp2;
  876. X    int         size_align;
  877. X
  878. X#ifdef DEBUG
  879. X    if (m_search != NULL && check_list())
  880. X        return NULL;
  881. X#endif
  882. X/*
  883. X * Add room for size field, optional 0xff byte and trailing NUL byte.
  884. X * Adjust for minimal size (must be able to store info_t
  885. X * plus a trailing NUL, so the chunk can be released again)
  886. X */
  887. X    size += M_OFFSET + 1;
  888. X    if (size < sizeof(info_t) + 1)
  889. X      size = sizeof(info_t) + 1;
  890. X
  891. X/*
  892. X * round size up for alignment
  893. X */
  894. X#ifdef ALIGN_LONG            /* use longword alignment */
  895. X    size_align = (size + 3) & ~3;
  896. X#else /* ALIGN_LONG */    /* use short (16 bit) alignment */
  897. X    size_align = (size + 1) & ~1;
  898. X#endif    /* ALIGN_LONG */
  899. X
  900. X/* if m_search is NULL we have to initialize the free list */
  901. X    if (m_search == NULL)
  902. X    {
  903. X        m_search = &m_fhead;
  904. X        m_fhead.m_next = &m_fhead;
  905. X    }
  906. X
  907. X/* search for space in free list */
  908. X    mprev = m_search;
  909. X    for (mp = m_search->m_next; mp->m_size < size; mp = mp->m_next)
  910. X    {
  911. X        if (mp == m_search)
  912. X        {
  913. X            int        n = (size_align > (MEMBLOCKSIZE / 4) ? size_align : MEMBLOCKSIZE);
  914. X
  915. X            mp = (info_t *)m_blockalloc((u_long)n, TRUE);
  916. X            if (mp == NULL)
  917. X                return (NULL);
  918. X#ifdef HIGHBYTE
  919. X            mp->m_size = n + 256;
  920. X#endif
  921. X#ifdef LOWBYTE
  922. X            mp->m_size = (n << 1) + 1;
  923. X#endif
  924. X#ifdef ALIGN_LONG
  925. X            mp->m_size = n;
  926. X            *((u_char *)mp + M_OFFSET - 1) = 0xff;
  927. X#endif
  928. X            free_line((char *)mp + M_OFFSET);
  929. X            mp = m_search;
  930. X        }
  931. X        mprev = mp;
  932. X    }
  933. X
  934. X/* if the chunk we found is large enough, split it up in two */
  935. X    if ((long)mp->m_size - size_align >= (long)(sizeof(info_t) + 1))
  936. X    {
  937. X        mp2 = (info_t *)((char *)mp + size_align);
  938. X        mp2->m_size = mp->m_size - size_align;
  939. X        mp2->m_next = mp->m_next;
  940. X        mprev->m_next = mp2;
  941. X        mp->m_size = size_align;
  942. X    }
  943. X    else                    /* remove *mp from the free list */
  944. X    {
  945. X        mprev->m_next = mp->m_next;
  946. X    }
  947. X    m_search = mprev;
  948. X
  949. X#ifdef HIGHBYTE
  950. X    mp->m_size += 256;
  951. X#endif
  952. X#ifdef LOWBYTE
  953. X    mp->m_size = (mp->m_size << 1) + 1;
  954. X#endif
  955. X    mp = (info_t *)((char *)mp + M_OFFSET);
  956. X#ifdef ALIGN_LONG
  957. X    *((u_char *)mp - 1) = 0xff;            /* mark type 2 chunk */
  958. X#endif
  959. X    *(char *)mp = NUL;                    /* set the first byte to NUL */
  960. X#ifdef DEBUG
  961. X    check_list();
  962. X#endif
  963. X
  964. X    return ((char *)mp);
  965. X}
  966. X
  967. X/*
  968. X * save_line(): allocate memory with alloc_line() and copy the
  969. X * string 'src' into it.
  970. X */
  971. X    char *
  972. Xsave_line(src)
  973. X    register char *src;
  974. X{
  975. X    register char *dst;
  976. X    register unsigned len;
  977. X
  978. X    len = strlen(src);
  979. X    if ((dst = alloc_line(len)) != NULL)
  980. X        memmove(dst, src, (size_t)(len + 1));
  981. X    return (dst);
  982. X}
  983. X
  984. X/******************************************
  985. X * part 2: managing of the pointer blocks *
  986. X ******************************************/
  987. X
  988. Xtypedef struct block block_t;
  989. X
  990. X#ifdef BLOCK_SIZE
  991. X# undef BLOCK_SIZE    /* for Linux: is in limits.h */
  992. X#endif
  993. X
  994. X#define BLOCK_SIZE 40
  995. X
  996. Xstruct block
  997. X{
  998. X    u_short  b_count;                /* current number of pointers in b_ptr */
  999. X    block_t *b_next;                /* pointer to next block */
  1000. X    block_t *b_prev;                /* pointer to previous block */
  1001. X    char    *b_ptr[BLOCK_SIZE];        /* pointers to the lines */
  1002. X    char     b_flags[BLOCK_SIZE];    /* see below */
  1003. X};
  1004. X
  1005. X#define B_MARKED    0x01        /* mark for :global command */
  1006. X
  1007. Xstatic block_t *first_block;    /* pointer to first block in block list */
  1008. Xstatic block_t *last_block;        /* pointer to last block in block list */
  1009. X
  1010. Xstatic block_t *curr_block;        /* block used by nr2ptr */
  1011. Xstatic linenr_t curr_count;        /* first line number of block curr_block */
  1012. X
  1013. Xstatic block_t *alloc_block __ARGS((void));
  1014. X
  1015. X    static block_t *
  1016. Xalloc_block()
  1017. X{
  1018. X    block_t *p;
  1019. X
  1020. X    p = (block_t *)(alloc_line((unsigned)sizeof(block_t)));
  1021. X    if (p != NULL)
  1022. X    {
  1023. X        memset((char *)p, 0, sizeof(block_t));
  1024. X    }
  1025. X    return (p);
  1026. X}
  1027. X
  1028. X/*
  1029. X * filealloc() - construct an initial empty file buffer
  1030. X */
  1031. X    void
  1032. Xfilealloc()
  1033. X{
  1034. X    first_block = last_block = alloc_block();
  1035. X    if (first_block == NULL || (first_block->b_ptr[0] = alloc_line(0)) == NULL)
  1036. X        getout(1);
  1037. X    first_block->b_count = 1;
  1038. X    Curpos.lnum = 1;
  1039. X    Curswant = Curpos.col = 0;
  1040. X    Topline = 1;
  1041. X    Botline = 2;
  1042. X    line_count = 1;
  1043. X    curr_count = 0;
  1044. X    clrallmarks();
  1045. X    clrtags();
  1046. X}
  1047. X
  1048. X/*
  1049. X * freeall() - free the current buffer
  1050. X *
  1051. X * Free all lines in the current buffer.
  1052. X */
  1053. X    void
  1054. Xfreeall()
  1055. X{
  1056. X    m_blockfree();
  1057. X    line_count = 0;
  1058. X    s_ins(0, 0, TRUE);    /* invalidate Line arrays */
  1059. X    u_clearall();
  1060. X}
  1061. X
  1062. X/*
  1063. X * Get the pointer to the line 'nr'.
  1064. X * This function is used a lot for sequential access (writeit, search),
  1065. X * so that is what it is optimized for.
  1066. X */
  1067. X    char *
  1068. Xnr2ptr(nr)
  1069. X    register linenr_t nr;
  1070. X{
  1071. X    register linenr_t count;
  1072. X    register block_t *bp = NULL;
  1073. X
  1074. X    if ((count = curr_count) == 0 || nr >= count + (bp = curr_block)->b_count || nr < count)
  1075. X    {
  1076. X        if (nr < 1 || nr > line_count)
  1077. X        {
  1078. X            emsg("nr2ptr: illegal nr");
  1079. X            return (IObuff);    /* always return a valid ptr */
  1080. X        }
  1081. X
  1082. X        /*
  1083. X         * three ways to find the pointer:
  1084. X         * 1. first pointer in the next block (fast for sequential access)
  1085. X         * 2. search forward
  1086. X         * 3. search backward
  1087. X         */
  1088. X        if (count && nr == count + bp->b_count)        /* in next block */
  1089. X        {
  1090. X            count = nr;
  1091. X            bp = bp->b_next;
  1092. X        }
  1093. X        else if (nr <= (count + line_count) / 2 ||
  1094. X                (nr <= count && nr <= count / 2))
  1095. X        {
  1096. X                                                    /* search forward */
  1097. X            if (nr < count || count == 0)
  1098. X            {
  1099. X                count = 1;
  1100. X                bp = first_block;
  1101. X            }
  1102. X            while (bp != NULL)
  1103. X            {
  1104. X                count += bp->b_count;
  1105. X                if (nr < count)
  1106. X                {
  1107. X                    count -= bp->b_count;
  1108. X                    break;
  1109. X                }
  1110. X                bp = bp->b_next;
  1111. X            }
  1112. X        }
  1113. X        else
  1114. X        {                                            /* search backward */
  1115. X            if (nr < count)
  1116. X                bp = bp->b_prev;
  1117. X            else
  1118. X            {
  1119. X                bp = last_block;
  1120. X                count = line_count + 1;
  1121. X            }
  1122. X            while (bp != NULL)
  1123. X            {
  1124. X                count -= bp->b_count;
  1125. X                if (nr >= count)
  1126. X                    break;
  1127. X                bp = bp->b_prev;
  1128. X            }
  1129. X        }
  1130. X        
  1131. X        if (bp == NULL)
  1132. X        {
  1133. X            emsg("nr2ptr: strorage corrupt");
  1134. X            curr_count = 0;
  1135. X            return (IObuff);
  1136. X        }
  1137. X        curr_count = count;
  1138. X        curr_block = bp;
  1139. X    }
  1140. X    return (bp->b_ptr[nr - count]);
  1141. X}
  1142. X
  1143. X/*
  1144. X * pos2ptr: get pointer to position 'pos'
  1145. X */
  1146. X    char *
  1147. Xpos2ptr(pos)
  1148. X    FPOS    *pos;
  1149. X{
  1150. X    return (nr2ptr(pos->lnum) + pos->col);
  1151. X}
  1152. X
  1153. X/*
  1154. X * set the B_MARKED flag for line 'lnum'
  1155. X */
  1156. X    void
  1157. Xsetmarked(lnum)
  1158. X    linenr_t lnum;
  1159. X{
  1160. X    nr2ptr(lnum);
  1161. X    curr_block->b_flags[lnum - curr_count] |= B_MARKED;
  1162. X}
  1163. X
  1164. X/*
  1165. X * find the first line with its B_MARKED flag set
  1166. X */
  1167. X    linenr_t
  1168. Xfirstmarked()
  1169. X{
  1170. X    register block_t    *bp;
  1171. X    register linenr_t    lnum;
  1172. X    register int        i;
  1173. X
  1174. X    for (bp = first_block, lnum = 1; bp != NULL; bp = bp->b_next)
  1175. X        for (i = 0; i < bp->b_count; ++i, ++lnum)
  1176. X            if (bp->b_flags[i] & B_MARKED)
  1177. X            {
  1178. X                bp->b_flags[i] &= ~B_MARKED;
  1179. X                return lnum;
  1180. X            }
  1181. X    return (linenr_t) 0;
  1182. X}
  1183. X
  1184. X/*
  1185. X * clear all B_MARKED flags
  1186. X */
  1187. X    void
  1188. Xclearmarked()
  1189. X{
  1190. X    register block_t    *bp;
  1191. X    register int        i;
  1192. X
  1193. X    for (bp = first_block; bp != NULL; bp = bp->b_next)
  1194. X        for (i = bp->b_count; --i >= 0; )
  1195. X                bp->b_flags[i] &= ~B_MARKED;
  1196. X}
  1197. X
  1198. X/*
  1199. X * a pointer to a line is converted into a line number
  1200. X * we start at line number 'start'
  1201. X * this is a bit slow, but it is used for marks and undo only
  1202. X */
  1203. X    linenr_t
  1204. Xptr2nr(ptr, start)
  1205. X    char *ptr;
  1206. X    linenr_t start;
  1207. X{
  1208. X    block_t *bp;
  1209. X    register linenr_t nr;
  1210. X    register char **pp;
  1211. X    register int    i;
  1212. X
  1213. X    if (ptr == NULL)
  1214. X        return (linenr_t)0;
  1215. X
  1216. X    if (start == 0)
  1217. X        start = 1;
  1218. X    nr2ptr(start);        /* set curr_block and curr_count */
  1219. X
  1220. X    for (nr = curr_count, bp = curr_block; bp != NULL; bp = bp->b_next)
  1221. X        for (pp = bp->b_ptr, i = bp->b_count; --i >= 0; ++nr)
  1222. X            if (*pp++ == ptr)
  1223. X                return (nr);
  1224. X    return (linenr_t)0;
  1225. X}
  1226. X
  1227. X/*
  1228. X * appendline: add a line
  1229. X *    return TRUE when succesful
  1230. X */
  1231. X    int
  1232. Xappendline(after, s)
  1233. X    linenr_t    after;
  1234. X    char        *s;
  1235. X{
  1236. X    register block_t    *bp;
  1237. X    block_t             *nbp;
  1238. X    linenr_t            count;
  1239. X    register int        i;
  1240. X
  1241. X    if (s == NULL)        /* don't insert NULL pointers! */
  1242. X        return FALSE;
  1243. X    if (after == 0)     /* insert in front of first line */
  1244. X    {
  1245. X        bp = first_block;
  1246. X        count = 1;
  1247. X        if (bufempty())     /* simply replace dummy line */
  1248. X        {
  1249. X            free_line(bp->b_ptr[0]);
  1250. X            bp->b_ptr[0] = s;
  1251. X            return TRUE;
  1252. X        }
  1253. X        curr_count = 0; /* curr_block will become invalid */
  1254. X    }
  1255. X    else
  1256. X    {
  1257. X        (void)nr2ptr(after);    /* find block */
  1258. X        bp = curr_block;
  1259. X        count = curr_count;
  1260. X    }
  1261. X
  1262. X    ++line_count;
  1263. X    i = bp->b_count;
  1264. X    if (i < BLOCK_SIZE)            /* there is place in the current block */
  1265. X/* move ptrs one place forward to make space for new one */
  1266. X    {
  1267. X        register char **pp;
  1268. X        register char *fp;
  1269. X
  1270. X        pp = &(bp->b_ptr[i]);
  1271. X        fp = &(bp->b_flags[i]);
  1272. X        for (i += count - after - 1; --i >= 0; --pp, --fp)
  1273. X        {
  1274. X            *pp = *(pp - 1);
  1275. X            *fp = *(fp - 1);
  1276. X        }
  1277. X        *pp = s;
  1278. X        *fp = 0;
  1279. X        ++bp->b_count;
  1280. X        return TRUE;
  1281. X    }
  1282. X
  1283. X/* need to allocate a new block */
  1284. X    nbp = alloc_block();
  1285. X    if (nbp == NULL)
  1286. X    {
  1287. X        --line_count;
  1288. X        free_line(s);
  1289. X        return FALSE;
  1290. X    }
  1291. X
  1292. X/* put new block in linked list */
  1293. X    if (after == 0) /* put new block in front of linked list */
  1294. X    {
  1295. X        bp->b_prev = nbp;
  1296. X        nbp->b_next = bp;
  1297. X        first_block = nbp;
  1298. X        nbp->b_ptr[0] = s;
  1299. X        nbp->b_count = 1;
  1300. X        return TRUE;
  1301. X    }
  1302. X
  1303. X    /* insert new block in linked list after bp */
  1304. X    nbp->b_next = bp->b_next;
  1305. X    bp->b_next = nbp;
  1306. X    nbp->b_prev = bp;
  1307. X    if (nbp->b_next == NULL)
  1308. X        last_block = nbp;
  1309. X    else
  1310. X        nbp->b_next->b_prev = nbp;
  1311. X
  1312. X    if (after - count + 1 == BLOCK_SIZE) /* put s in new block */
  1313. X    {
  1314. X        nbp->b_ptr[0] = s;
  1315. X        nbp->b_count = 1;
  1316. X        return TRUE;
  1317. X    }
  1318. X
  1319. X    /* move some ptrs from full block to new block */
  1320. X    {
  1321. X        register int j = 0;
  1322. X
  1323. X        bp->b_count = after - count + 1;    /* number of ptrs remaining */
  1324. X        i = BLOCK_SIZE - bp->b_count;        /* number of ptrs to be moved */
  1325. X        nbp->b_count = i;
  1326. X        while (--i >= 0)
  1327. X        {
  1328. X            j = bp->b_count + i;
  1329. X            nbp->b_ptr[i] = bp->b_ptr[j];
  1330. X            nbp->b_flags[i] = bp->b_flags[j];
  1331. X        }
  1332. X        bp->b_ptr[j] = s;
  1333. X        bp->b_flags[j] = 0;
  1334. X        ++bp->b_count;
  1335. X        return TRUE;
  1336. X    }
  1337. X}
  1338. X
  1339. X/*
  1340. X * delsline: delete line from storage
  1341. X *
  1342. X * the line is turned over to the caller
  1343. X */
  1344. X    char *
  1345. Xdelsline(nr, delmarks)
  1346. X    linenr_t    nr;
  1347. X    int            delmarks;
  1348. X{
  1349. X    char    *ptr;
  1350. X    register block_t    *bp;
  1351. X    register char **pp;
  1352. X    register char *fp;
  1353. X    register int i;
  1354. X
  1355. X    if (nr < 1 || nr > line_count)
  1356. X    {
  1357. X        emsg("delsline: nr wrong");
  1358. X        return (alloc_line(0));
  1359. X    }
  1360. X    ptr = nr2ptr(nr);
  1361. X    if (delmarks)
  1362. X        adjustmark(ptr, NULL);            /* remove marks for this line */
  1363. X    bp = curr_block;
  1364. X    if (line_count == 1)    /* don't delete the last line in the file */
  1365. X    {
  1366. X        bp->b_ptr[0] = alloc_line(0);
  1367. X        return (ptr);
  1368. X    }
  1369. X    --line_count;
  1370. X
  1371. X    /* move the rest of the ptrs in this block one down */
  1372. X    pp = &(bp->b_ptr[nr - curr_count]);
  1373. X    fp = &(bp->b_flags[nr - curr_count]);
  1374. X    for (i = bp->b_count + curr_count - nr - 1; --i >= 0; ++pp, ++fp)
  1375. X    {
  1376. X        *pp = *(pp + 1);
  1377. X        *fp = *(fp + 1);
  1378. X    }
  1379. X    if (--bp->b_count == 0) /* the block became empty, remove it from the list */
  1380. X    {
  1381. X        if (bp->b_prev == NULL)
  1382. X            first_block = bp->b_next;
  1383. X        else
  1384. X            bp->b_prev->b_next = bp->b_next;
  1385. X        if (bp->b_next == NULL)
  1386. X            last_block = bp->b_prev;
  1387. X        else
  1388. X            bp->b_next->b_prev = bp->b_prev;
  1389. X        free_line((char *)bp);
  1390. X        curr_count = 0; /* curr_block invalid */
  1391. X    }
  1392. X    return (ptr);
  1393. X}
  1394. X
  1395. X/*
  1396. X * replace the line "lnum" with the line "new".
  1397. X * return the old line (which should be freed by the caller)
  1398. X */
  1399. X    char *
  1400. Xreplaceline(lnum, new)
  1401. X    linenr_t lnum;
  1402. X    char *new;
  1403. X{
  1404. X    char *old;
  1405. X
  1406. X    old = nr2ptr(lnum);
  1407. X    if (new == NULL || curr_count == 0)    /* we don't want NULL pointers in the list */
  1408. X        return (alloc_line(0)); /* be friendly to the caller */
  1409. X
  1410. X    curr_block->b_ptr[lnum - curr_count] = new;
  1411. X    curr_block->b_flags[lnum - curr_count] = 0;
  1412. X    adjustmark(old, new);
  1413. X    return (old);
  1414. X}
  1415. X
  1416. X/*
  1417. X * canincrease(n) - returns TRUE if the current line can be increased 'n'
  1418. X * bytes
  1419. X *
  1420. X * This routine returns immediately if the requested space is available. If not,
  1421. X * it attempts to allocate the space and adjust the data structures
  1422. X * accordingly. If everything fails it returns FALSE.
  1423. X */
  1424. X    int
  1425. Xcanincrease(n)
  1426. X    int    n;
  1427. X{
  1428. X    register char    *old;
  1429. X    register char    *new;        /* pointer to new space */
  1430. X    register unsigned newsize;
  1431. X
  1432. X    old = nr2ptr(Curpos.lnum);
  1433. X    newsize = strlen(old) + n;
  1434. X
  1435. X    new = alloc_line(newsize);
  1436. X    if (new == NULL)
  1437. X        return FALSE;
  1438. X
  1439. X    strcpy(new, old);
  1440. X    adjustmark(old, new);
  1441. X    free_line(old);
  1442. X    curr_block->b_ptr[Curpos.lnum - curr_count] = new;
  1443. X    curr_block->b_flags[Curpos.lnum - curr_count] = 0;
  1444. X
  1445. X    return TRUE;
  1446. X}
  1447. END_OF_FILE
  1448. if test 19504 -ne `wc -c <'vim/src/storage.c'`; then
  1449.     echo shar: \"'vim/src/storage.c'\" unpacked with wrong size!
  1450. fi
  1451. # end of 'vim/src/storage.c'
  1452. fi
  1453. echo shar: End of archive 11 \(of 23\).
  1454. cp /dev/null ark11isdone
  1455. MISSING=""
  1456. for I in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 ; do
  1457.     if test ! -f ark${I}isdone ; then
  1458.     MISSING="${MISSING} ${I}"
  1459.     fi
  1460. done
  1461. if test "${MISSING}" = "" ; then
  1462.     echo You have unpacked all 23 archives.
  1463.     rm -f ark[1-9]isdone ark[1-9][0-9]isdone
  1464. else
  1465.     echo You still need to unpack the following archives:
  1466.     echo "        " ${MISSING}
  1467. fi
  1468. ##  End of shell archive.
  1469. exit 0
  1470. -------------8<----------------8<----------------8<---------------8<--------
  1471. Bram Moolenaar                             | DISCLAIMER:  This  note  does  not
  1472. Oce Nederland B.V., Research & Development | necessarily represent the position
  1473. p.o. box 101, 5900 MA  Venlo               | of  Oce-Nederland  B.V.  Therefore
  1474. The Netherlands        phone +31 77 594077 | no liability or responsibility for
  1475. UUCP: mool@oce.nl        fax +31 77 595450 | whatever will be accepted.
  1476.  
  1477. exit 0 # Just in case...
  1478.