home *** CD-ROM | disk | FTP | other *** search
/ NetNews Usenet Archive 1992 #27 / NN_1992_27.iso / spool / alt / sources / 2589 < prev    next >
Encoding:
Text File  |  1992-11-20  |  52.6 KB  |  2,363 lines

  1. Newsgroups: alt.sources
  2. Path: sparky!uunet!spool.mu.edu!sol.ctr.columbia.edu!eff!world!jhallen
  3. From: jhallen@world.std.com (Joseph H Allen)
  4. Subject: JOE 1.0.5 Part 1 of 10
  5. Message-ID: <By2ME0.KoH@world.std.com>
  6. Organization: The World Public Access UNIX, Brookline, MA
  7. Date: Sat, 21 Nov 1992 14:46:48 GMT
  8. Lines: 2353
  9.  
  10. Submitted-by: jhallen@world.std.com
  11. Archive-name: joe1.0.5part1
  12.  
  13. To unpack the archive:  strip the news headers and trailers off of each 
  14. posting and concatenate them into a single file.  then execute the shell 
  15. archive with 'sh filename'
  16.  
  17.  
  18. A new version of Joe's Own Editor is complete.  Get is by anonymous ftp to 
  19. world.std.com, file: src/editors/joe1.0.5.tar.Z.  Also look for it on 
  20. 'alt.sources' This has a number of fixes and new features: 
  21.  
  22. - Rectangle/Column mode.  I think I've made a very good implementation of 
  23. this stuff.  It's really neat, I could have used this earlier.  When this 
  24. mode is selected, the normal block commands (including filter block through 
  25. unix command) and insert file work on rectangles.  Also if overtype mode is 
  26. set, these commands overtype instead.  Also when rectangle mode is set, 
  27. indent and unindent will work with the insertion/deletion point as the 
  28. left side of the rectangle instead of the beginning of the lines.
  29.  
  30. - Can set tab width
  31.  
  32. - Can set indent/unindent step column-width and fill character
  33.  
  34. - ^K ;  now does a tags file search
  35.  
  36. - if there's only one help screen defined, then ^KH immediatly turns on help
  37. instead of giving a menu
  38.  
  39. - same deal with TAB completion- if only one item matches, it does a simple
  40. completion
  41.  
  42. - unnamed files get the name first given to save file ^K D
  43.  
  44. - joe is now in a subdirectory in the tar archive.  Also as you can see,
  45. I'm including the version number along with the name
  46.  
  47. - the problems with the optimizer on Xenix and with back-tab on SCO UNIX are
  48. fixed.  You still have to use 'ttysv' with SCO UNIX- I need to get access to
  49. a SCO UNIX machine to make a tty interface for it.  I think the posix tty 
  50. interface is probably pretty close.
  51.  
  52. - string searches were crashing when they got to the end of the file.  this 
  53. is fixed now.  
  54.  
  55. Hex dump edit mode, fixed record length edit more and a new 'man' page are 
  56. on the way.
  57.  
  58. The only major features which I feel are still missing are shell windows and 
  59. background loading/demand loading.  These are going to be mess as far as 
  60. portability so they'll probably take a while.
  61.  
  62.  
  63. #!/bin/sh
  64. # This is a shell archive (produced by shar 3.50)
  65. # To extract the files from this archive, save it to a file, remove
  66. # everything above the "!/bin/sh" line above, and type "sh file_name".
  67. #
  68. # made 11/21/1992 14:33 UTC by jhallen@world
  69. # Source directory /tmp/j/joe
  70. #
  71. # existing files will NOT be overwritten unless -c is specified
  72. #
  73. # This shar contains:
  74. # length  mode       name
  75. # ------ ---------- ------------------------------------------
  76. #   5471 -rw------- INFO
  77. #   5257 -rw------- README
  78. #  24715 -rw------- b.c
  79. #  10590 -rw------- b.h
  80. #  12881 -rw------- blocks.c
  81. #   2144 -rw------- blocks.h
  82. #  13764 -rw------- bw.c
  83. #   1252 -rw------- bw.h
  84. #   1152 -rw------- config.h
  85. #   1273 -rw------- config16.h
  86. #   1152 -rw------- config32.h
  87. #   1391 -rw------- config86.h
  88. #  12488 -rw------- copying
  89. #  32824 -rw------- edfuncs.c
  90. #   1933 -rw------- edfuncs.h
  91. #   8056 -rw------- heap.c
  92. #   3883 -rw------- heap.h
  93. #   4291 -rw------- help.c
  94. #   1306 -rw------- help.h
  95. #  19130 -rw------- joerc
  96. #  11368 -rw------- kbd.c
  97. #   2999 -rw------- kbd.h
  98. #   2755 -rw------- macro.c
  99. #   1344 -rw------- macro.h
  100. #  10617 -rw------- main.c
  101. #   1140 -rw------- main.h
  102. #   1179 -rw------- makefile
  103. #   2874 -rw------- menu.c
  104. #   1318 -rw------- menu.h
  105. #   1505 -rw------- msdir.c
  106. #   1513 -rw------- olddir.c
  107. #   2984 -rw------- pathfunc.c
  108. #   2548 -rw------- pathfunc.h
  109. #   7010 -rw------- pattern.c
  110. #    841 -rw------- pattern.h
  111. #   2503 -rw------- poshist.c
  112. #    908 -rw------- poshist.h
  113. #   4996 -rw------- pw.c
  114. #   1442 -rw------- pw.h
  115. #    846 -rw------- queue.c
  116. #   3442 -rw------- queue.h
  117. #  12354 -rw------- random.c
  118. #    134 -rw------- random.h
  119. #   1259 -rw------- reg.c
  120. #   8187 -rw------- regex.c
  121. #    879 -rw------- regex.h
  122. #  26464 -rw------- scrn.c
  123. #   7538 -rw------- scrn.h
  124. #   6687 -rw------- tab.c
  125. #   1173 -rw------- tab.h
  126. #   4577 -rw------- termcap
  127. #  10843 -rw------- termcap.c
  128. #   6116 -rw------- termcap.h
  129. #   1592 -rw------- termidx.c
  130. #   2705 -rw------- terminfo.c
  131. #   1341 -rw------- todojoe
  132. #   2733 -rw------- toomany.c
  133. #   1322 -rw------- toomany.h
  134. #   5951 -rw------- tty.h
  135. #   5407 -rw------- ttybsd.c
  136. #   4717 -rw------- ttyhpux.c
  137. #   1705 -rw------- ttymsdos.c
  138. #   5008 -rw------- ttyposix.c
  139. #   4269 -rw------- ttysv.c
  140. #   4223 -rw------- ttyxenix.c
  141. #   6362 -rw------- tw.c
  142. #   1265 -rw------- tw.h
  143. #   5709 -rw------- undo.c
  144. #   1901 -rw------- undo.h
  145. #   6830 -rw------- va.c
  146. #  11674 -rw------- va.h
  147. #  11446 -rw------- vfile.c
  148. #   9358 -rw------- vfile.h
  149. #  10956 -rw------- vs.c
  150. #  13819 -rw------- vs.h
  151. #  13930 -rw------- w.c
  152. #   5765 -rw------- w.h
  153. #   1902 -rw------- zstr.c
  154. #   1044 -rw------- zstr.h
  155. #  19130 -rw------- .joerc
  156. #
  157. # ============= INFO ==============
  158. if test -f 'INFO' -a X"$1" != X"-c"; then
  159.     echo 'x - skipping INFO (File already exists)'
  160. else
  161. echo 'x - extracting INFO (Text)'
  162. sed 's/^X//' << 'SHAR_EOF' > 'INFO' &&
  163. X                           Joe's Own Editor 1.0.5
  164. X
  165. X
  166. Get it by anonymous ftp
  167. from: 'world.std.com', file '/src/editors/joe1.0.5.tar.Z'
  168. X
  169. If you have questions, problems or suggestions,
  170. send email to: 'jhallen@world.std.com'
  171. X
  172. X
  173. X    JOE is a sane ASCII text screen editor for UNIX.  It is designed to 
  174. make use of the power and versitility of UNIX, but also to be easy to use.  
  175. It has the feel of most IBM PC editors.  The key sequences are remeniscent 
  176. of WordStar and TURBO-PASCAL.  It also has the features UNIX user's should 
  177. expect: makes full use of termcap/terminfo, is designed to work well over 
  178. slow networks and low baud rate modems, designed to reduce installation 
  179. headaches, and has the best features of vi.
  180. X
  181. X    JOE is most useful for editing unformatted text, such as USENET news 
  182. articles and for editing block-structured languages such as C and PASCAL.  
  183. JOE is ideal for new or casual users but is also is also a powerful enough 
  184. to please experienced users.
  185. X
  186. Features:
  187. X
  188. X    Full termcap/terminfo support.  Will work on any terminal except for
  189. overstrike terminals.  A new termcap library is supplied which can use an 
  190. index file to make it faster then terminfo.  A number of terminfo extensions 
  191. are supported and the GNU extensions to the termcap language are also 
  192. supported.  JOE is not picky about the completeness of the termcap entries, 
  193. it knows what the defaults are.
  194. X
  195. X    Non-nonsense installation.  JOE has both ^H and DEL mapped to 
  196. backspace and ^Q and ^S are not used.  JOE compiles to 120-190K on most 
  197. systems.
  198. X
  199. X    Powerful optimal screen update.  Uses scrolling regions the way they 
  200. are supposed to be used (I.E., without building insert and delete line with 
  201. them) and uses a powerful line shifting (insert/delete character) algorithm 
  202. which works if text goes past the ends of lines.  Has defered screen update 
  203. to handle typeahead.
  204. X
  205. X    VI-style unix integration.  You can filter a highlighted block 
  206. through a UNIX command.  Also, each place in joe which accepts a file name 
  207. (including the command line) will also accept: 
  208. X
  209. X        !command        to pipe into or out of a command
  210. X        >>filename        to append to a file
  211. X        filename,start,size    to edit a portion of a file/device
  212. X        -            to use stdin or stdout
  213. X
  214. X    Also, filenames on the command line may be preceeded by +nnn to 
  215. start editing at a specified line.
  216. X
  217. X    Orthoganality.  Each prompt is actually a normal edit buffer and a 
  218. copy of a history buffer.  You can use all of the normal edit commands to 
  219. create file names and search strings.  You can use the up arrow key (or 
  220. search backwards and any other appropriate edit command) to go back through 
  221. the history of previous responses.  
  222. X
  223. X    Powerful buffering system.  JOE uses a doubly linked list of gap 
  224. buffers which can spill into /tmp directory files.  You can edit file of any 
  225. size up to the amount of free disk space and there are no line-length 
  226. restrictions.  Since the buffering system is block-based, JOE will incur 
  227. only a minimum of swapping on heavily loaded systems.
  228. X
  229. X    TAB-completion and file selection menus.  If you hit tab in a file 
  230. name prompt, the name is either completed or a menu of possible matches 
  231. appears.
  232. X
  233. X    Nice help system.  When you ask for help, you get a menu of help 
  234. screens to shoose from (all definable in an initialization file).   Once a 
  235. help screen is selected, the help remains on while you continue to use the 
  236. editor.  Here is the first help screen:
  237. X
  238. CURSOR           GO TO            BLOCK      DELETE   MISC         EXIT
  239. ^B left ^F right ^U  prev. screen ^KB begin  ^D char. ^KJ reformat ^KX save
  240. ^P up   ^N down  ^V  next screen  ^KK end    ^Y line  ^TT overtype ^C  abort
  241. ^Z previous word ^A  beg. of line ^KM move   ^W >word `   Ctrl-    ^KZ shell
  242. ^X next word     ^E  end of line  ^KC copy   ^O word< ^   Meta-    FILE
  243. SEARCH           ^KU top of file  ^KW file   ^J >line ^R  retype   ^KE new
  244. ^KF find text    ^KV end of file  ^KY delete ^_ undo  ^@  insert   ^KR insert
  245. ^L  find next    ^KL to line No.  ^K/ filter ^^ redo               ^KD save
  246. X
  247. X    Powerful set of editing commands.  Including:
  248. X
  249. X        - search and replace system, including powerful regular 
  250. X          expressions (including matching of balanced C expressions).
  251. X
  252. X        - tag search
  253. X
  254. X        - paragraph format
  255. X
  256. X        - undo and redo
  257. X
  258. X        - position history allows you to get back to previous
  259. X          editing contexts and allows you to quickly flip between
  260. X          editing contexts
  261. X
  262. X        - multiple keyboard macros
  263. X
  264. X        - multiple windows
  265. X
  266. X        - block move/copy/delete/filter
  267. X
  268. X        - rectangle mode
  269. X
  270. X        - overtype/insert modes
  271. X
  272. X        - indent/unindent
  273. X
  274. X        - goto matching ( [ {
  275. X
  276. X        - auto-indent mode
  277. X
  278. X    Plus many options can be set:
  279. X
  280. X        - row and column number can be shown on status line
  281. X
  282. X        - can have EMACS-style cursor recentering on scrolls
  283. X
  284. X        - characters between 160-254 can be shown as-is for
  285. X          scandinavian characters
  286. X
  287. X        - Final newline can be forced on end of file
  288. X
  289. X        - Can start with a help screen on
  290. X
  291. X        - No. of PgUp/PgDn lines to keep can be specified
  292. X
  293. X        - Left/Right margin settings
  294. X
  295. X        - Tab width
  296. X
  297. X        - Indentation step and character
  298. X
  299. X    JOE will soon have:
  300. X
  301. X        Hex dump edit mode
  302. X
  303. X        Fixed record length edit mode
  304. X
  305. X        Shell windows and background/demand file-loading
  306. X
  307. /*  jhallen@world.std.com */     /* Amazing */            /* Joseph H. Allen */
  308. int a[1817];main(z,p,q,r){for(p=80;q+p-80;p-=2*a[p])for(z=9;z--;)q=3&(r=time(0)
  309. +r*57)/7,q=q?q-1?q-2?1-p%79?-1:0:p%79-77?1:0:p<1659?79:0:p>158?-79:0,q?!a[p+q*2
  310. ]?a[p+=a[p+=q]=q]=q:0:0;for(;q++-1817;)printf(q%79?"%c":"%c\n"," #"[!a[q-1]]);}
  311. SHAR_EOF
  312. chmod 0600 INFO ||
  313. echo 'restore of INFO failed'
  314. Wc_c="`wc -c < 'INFO'`"
  315. test 5471 -eq "$Wc_c" ||
  316.     echo 'INFO: original size 5471, current size' "$Wc_c"
  317. fi
  318. # ============= README ==============
  319. if test -f 'README' -a X"$1" != X"-c"; then
  320.     echo 'x - skipping README (File already exists)'
  321. else
  322. echo 'x - extracting README (Text)'
  323. sed 's/^X//' << 'SHAR_EOF' > 'README' &&
  324. This is Joe's Own Editor.  See the INFO file if you don't know what this is.
  325. X
  326. Installation proceedure
  327. =-=-=-=-=-=-=-=-=-=-=-=
  328. X
  329. X    Decide on the name of the global keymap file if you don't want it
  330. X    to be '/usr/local/lib/joerc' and modify the 'JOERC=' in the
  331. X    'makefile'.  If you're a mere user, copy the joerc file into
  332. X    $HOME/.joerc
  333. X
  334. X    Type 'make' followed by one of the following system names:
  335. X
  336. X        xenix        for xenix 386 systems
  337. X
  338. X        posix        for posix conformant systems (use this for
  339. X                linux)
  340. X
  341. X        bsd        for BSD UNIX
  342. X
  343. X        sv        for old system V UNIX
  344. X
  345. X        hpux        for HPUX systems
  346. X
  347. X    Then type 'make install' to install joe in
  348. X    /usr/local/bin and /usr/local/lib
  349. X
  350. X    Type 'make clean' eliminate the .o files
  351. X
  352. X    Copy termcap to .termcap in your home directory if you want to
  353. X    use it instead of /etc/termcap (see below).
  354. X
  355. X    Set the baud rate properly (see below).
  356. X
  357. ** SCO UNIX users **
  358. X
  359. Use the 'make sv', but first edit 'ttysv.c' and add these lines:
  360. X    #include <sys/types.h>
  361. X    #include <sys/stream.h>
  362. X    #include <sys/ptem.h>
  363. X    #undef SIGCONT
  364. X
  365. You may also wish to use the terminfo database.  See below.
  366. X
  367. USEAGE:    joe filenames
  368. X
  369. X    Optionally preceed each filename with +nnn to start at specified 
  370. line number.  
  371. X
  372. ** IMPORTANT **
  373. X
  374. The baud rate must be correctly set or either typeahead will not interrupt 
  375. the screen update and scrolling wont be used or there will be annoying 
  376. delays in the screen update.  If you can't set the baud rate correctly with 
  377. 'stty', give a numeric value in the environment variable 'BAUD'.  
  378. X
  379. The baud rate '38400' or 'extb' means infinite to joe.  Use it for X windows
  380. and hardware console ttys.  No delays will be generated and scrolling will
  381. not be used.
  382. X
  383. Use the LINES and COLUMNS environment variables if you need the terminal
  384. size to be different than whatever the termcap entry or stty says.
  385. X
  386. Since most people use terminal emulators, JOE does not send out pad 
  387. characters.  If you're using a real terminal and the padding matters, set 
  388. the environment variable DOPADDING.
  389. X
  390. A termcap file is included with JOE.  You might consider updating your own 
  391. termcap file with the entries in it, particularly if you use ANSI/VT100ish 
  392. terminals.  JOE understands some capabilities which are not usually supplied 
  393. in normal termcap (see below).
  394. X
  395. X                                 VARIATIONS
  396. X                                 =-=-=-=-=-
  397. X
  398. Termcap/Terminfo
  399. =-=-=-=-=-=-=-=-
  400. X
  401. X    JOE prefers to use the termcap terminal capability database.  You
  402. have if the file '/etc/termcap' exists.  If it doesn't you can use the
  403. 'termcap' file supplied with joe by copying it to /etc.
  404. X
  405. X    Termcap is better than terminfo because it is a more open standard. 
  406. Programs can directly access the termcap database and future versions of
  407. terminfo may require programs to use curses.  The only argument in
  408. terminfo's favour is that it is faster than termcap.  To fix this problem,
  409. JOE will use a termcap index file if it exists and if it is up to date.
  410. X
  411. X    This is the proceedure to make the termcap index file:
  412. X
  413. X        make termidx
  414. X        ./termidx </etc/termcap >/etc/termcap.idx
  415. X
  416. X    The /etc/termcap.idx is a text file which you can look at if you're
  417. curious.
  418. X
  419. X    JOE supports the GNU extensions to the termcap language and also
  420. understands several new capabilities:
  421. X
  422. X        AL DL IC DC RI LE UP DO SF SR
  423. X
  424. X            Versions of the standard capabilities which accept
  425. X            an argument.  For example, RI with and argument of
  426. X            7 should move the cursor 7 positions to the right.
  427. X
  428. X        rr
  429. X
  430. X            Set this flag if the cursor is restricted to move
  431. X            only within the scrolling regions.  This is an optional
  432. X            mode on vt220s and several clones assume that this
  433. X            mode is always on.
  434. X
  435. X        cb
  436. X
  437. X            Like the 'cv' capability, but the cursor goes to the
  438. X            beginning of the specified line.  Like 'ESC [ n H' in
  439. X            ansi/vt100.
  440. X
  441. X    But if you really must use the terminfo database, change the
  442. 'termcap.o' file in the OBJS list in the makefile to 'terminfo.o'.  You'll 
  443. also have to add '-ltinfo', '-lterminfo' or '-lcurses' to the appropriate link
  444. line (lines beginning with $(CC)) in the make file.
  445. X
  446. VOID trouble
  447. =-=-=-=-=-=-
  448. X
  449. X    If you're using an old C compiler which doesn't like the 'void'
  450. type, uncomment the '#define void int' line from the config.h file.
  451. X
  452. No diropen library
  453. =-=-=-=-=-=-=-=-=-
  454. X
  455. X    Add 'olddir.o' to the object file list in the makefile.
  456. X
  457. 16-bit systems / MS-DOS systems
  458. =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
  459. X
  460. X    The 16-bit segmented system support is not quite finished yet.  If
  461. you really want to try, copy 'config86.h' to config.h and try compiling with
  462. ttymsdos.h or ttyxenix.h for Xenix 86/286 systems.  Use large model.
  463. X
  464. X    I still have to make the UNDO system use edit buffers (which use a
  465. linked list of small blocks) instead of large malloc blocks to store the
  466. records.  
  467. X
  468. X    Also for MS-DOS you have to go through ansi/nansi/zansi.sys.  There
  469. also needs to be an \etc\termcap file and a \tmp directory.  Soon I'll make
  470. a direct screen access version.  Also there's a 'msdir.c' module for making
  471. the turbo-C directory access functions look like unix opendir functions. 
  472. You'll probably have to make even more changes (like no password file
  473. support) to get it to work.
  474. X
  475. X    If someone sends me information about tty drivers on QNX or
  476. coherent, I'll be happy to try to make JOE work for them (also, do they
  477. support large model?)
  478. SHAR_EOF
  479. chmod 0600 README ||
  480. echo 'restore of README failed'
  481. Wc_c="`wc -c < 'README'`"
  482. test 5257 -eq "$Wc_c" ||
  483.     echo 'README: original size 5257, current size' "$Wc_c"
  484. fi
  485. # ============= b.c ==============
  486. if test -f 'b.c' -a X"$1" != X"-c"; then
  487.     echo 'x - skipping b.c (File already exists)'
  488. else
  489. echo 'x - extracting b.c (Text)'
  490. sed 's/^X//' << 'SHAR_EOF' > 'b.c' &&
  491. /* Buffer management
  492. X   Copyright (C) 1992 Joseph H. Allen
  493. X
  494. This file is part of JOE (Joe's Own Editor)
  495. X
  496. JOE is free software; you can redistribute it and/or modify it under the 
  497. terms of the GNU General Public License as published by the Free Software 
  498. Foundation; either version 1, or (at your option) any later version.  
  499. X
  500. JOE is distributed in the hope that it will be useful, but WITHOUT ANY 
  501. WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 
  502. FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more 
  503. details.  
  504. X
  505. You should have received a copy of the GNU General Public License along with 
  506. JOE; see the file COPYING.  If not, write to the Free Software Foundation, 
  507. 675 Mass Ave, Cambridge, MA 02139, USA.  */ 
  508. X
  509. #include <stdio.h>
  510. #include <pwd.h>
  511. #include <errno.h>
  512. #include "config.h"
  513. #include "heap.h"
  514. #include "blocks.h"
  515. #include "w.h"
  516. #include "tty.h"
  517. #include "scrn.h"
  518. #include "undo.h"
  519. #include "vs.h"
  520. #include "zstr.h"
  521. #include "main.h"
  522. #include "bw.h"
  523. #include "b.h"
  524. X
  525. extern int errno;
  526. int force=0;
  527. X
  528. char buffer[1024];
  529. X
  530. /********************/
  531. /* Buffer GAP stuff */
  532. /********************/
  533. X
  534. /* Get size of gap (amount of free space) */
  535. X
  536. #define GGAPSZ(hdr) ((hdr)->ehole-(hdr)->hole)
  537. X
  538. /* Get number of characters in gap buffer */
  539. X
  540. #define GSIZE(hdr) (SEGSIZ-GGAPSZ(hdr))
  541. X
  542. /* Set position of gap */
  543. X
  544. static void gstgap(hdr,ptr,ofst)
  545. H *hdr;
  546. char *ptr;
  547. int ofst;
  548. {
  549. if(ofst>hdr->hole)
  550. X mfwrd(ptr+hdr->hole,ptr+hdr->ehole,ofst-hdr->hole), vchanged(ptr);
  551. else if(ofst<hdr->hole)
  552. X mbkwd(ptr+hdr->ehole-(hdr->hole-ofst),ptr+ofst,hdr->hole-ofst), vchanged(ptr);
  553. hdr->ehole=ofst+hdr->ehole-hdr->hole;
  554. hdr->hole=ofst;
  555. }
  556. X
  557. /* Insert a block */
  558. X
  559. static void ginsm(hdr,ptr,ofst,blk,size)
  560. H *hdr;
  561. char *ptr;
  562. int ofst;
  563. char *blk;
  564. int size;
  565. {
  566. if(ofst!=hdr->hole) gstgap(hdr,ptr,ofst);
  567. mcpy(ptr+hdr->hole,blk,size);
  568. hdr->hole+=size;
  569. vchanged(ptr);
  570. }
  571. X
  572. /* Delete characters */
  573. X
  574. static void gdel(hdr,ptr,ofst,size)
  575. H *hdr;
  576. char *ptr;
  577. int ofst;
  578. int size;
  579. {
  580. if(ofst!=hdr->hole) gstgap(hdr,ptr,ofst);
  581. hdr->ehole+=size;
  582. }
  583. X
  584. /* Read block */
  585. X
  586. static void grmem(hdr,ptr,ofst,blk,size)
  587. H *hdr;
  588. char *ptr;
  589. int ofst;
  590. char *blk;
  591. int size;
  592. {
  593. if(ofst<hdr->hole)
  594. X if(size>hdr->hole-ofst)
  595. X  mcpy(blk,ptr+ofst,hdr->hole-ofst),
  596. X  mcpy(blk+hdr->hole-ofst,ptr+hdr->ehole,size-(hdr->hole-ofst));
  597. X else mcpy(blk,ptr+ofst,size);
  598. else mcpy(blk,ptr+ofst+hdr->ehole-hdr->hole,size);
  599. }
  600. X
  601. /**************************************/
  602. /* Header and text segment allocation */
  603. /**************************************/
  604. X
  605. static long salloc(b)
  606. B *b;
  607. {
  608. if(b->fretxt)
  609. X {
  610. X long addr=b->fretxt;
  611. X long *adr=(long *)vlock(b->text,addr);
  612. X b->fretxt= *adr;
  613. X vunlock(adr);
  614. X return addr;
  615. X }
  616. else return valloc(b->text,(long)SEGSIZ);
  617. }
  618. X
  619. static H frhdrs={{&frhdrs,&frhdrs}};
  620. X
  621. static H *halloc()
  622. {
  623. if(qempty(H,link,&frhdrs))
  624. X {
  625. X H *h;
  626. X int x;
  627. X h=(H *)malloc(sizeof(H)*64);
  628. X for(x=0;x!=64;++x) enquef(H,link,&frhdrs,h+x);
  629. X }
  630. return deque(H,link,frhdrs.link.next);
  631. }
  632. X
  633. static void sfree(b,addr)
  634. B *b;
  635. long addr;
  636. {
  637. long *adr=(long *)vlock(b->text,addr);
  638. *adr=b->fretxt;
  639. vchanged(adr); vunlock(adr);
  640. b->fretxt=addr;
  641. }
  642. X
  643. /**********************/
  644. /* Pointer allocation */
  645. /**********************/
  646. X
  647. static P frptrs={{&frptrs,&frptrs}};
  648. X
  649. static P *palloc()
  650. {
  651. if(qempty(P,link,&frptrs))
  652. X {
  653. X P *h;
  654. X int x;
  655. X h=(P *)malloc(sizeof(P)*64);
  656. X for(x=0;x!=64;++x) enquef(P,link,&frptrs,h+x);
  657. X }
  658. return deque(P,link,frptrs.link.next);
  659. }
  660. X
  661. static void pfree(p)
  662. P *p;
  663. {
  664. enquef(P,link,&frptrs,p);
  665. }
  666. X
  667. /****************************/
  668. /* Buffer creation/deletion */
  669. /****************************/
  670. X
  671. /* Doubly linked list of buffers */
  672. X
  673. static B bufs={{&bufs,&bufs}};
  674. int tabwidth=8;
  675. X
  676. B *bmk()
  677. {
  678. B *new=(B *)malloc(sizeof(B));
  679. new->tab=tabwidth;
  680. new->backup=1;
  681. new->chnged=0;
  682. new->count=1;
  683. new->name=0;
  684. new->fretxt=0;
  685. new->bof=palloc();
  686. izque(P,link,new->bof);
  687. new->text=vtmp();
  688. new->bof->b=new;
  689. new->bof->owner=0;
  690. new->bof->ofst=0;
  691. new->bof->byte=0;
  692. new->bof->line=0;
  693. new->bof->col=0;
  694. new->bof->xcol=0;
  695. new->bof->lbyte=0;
  696. new->bof->hdr=halloc();
  697. new->bof->hdr->hole=0;
  698. new->bof->hdr->ehole=SEGSIZ;
  699. izque(H,link,new->bof->hdr);
  700. new->bof->hdr->seg=salloc(new);
  701. new->bof->ptr=vlock(new->text,new->bof->hdr->seg);
  702. new->eof=pdup(new->bof);
  703. undomk(new);
  704. enquef(B,link,&bufs,new);
  705. return new;
  706. }
  707. X
  708. /* Find loaded file */
  709. X
  710. B *bfind(name)
  711. char *name;
  712. {
  713. B *b;
  714. for(b=bufs.link.next;b!=&bufs;b=b->link.next)
  715. X if(b->name && !zcmp(name,b->name))
  716. X  {
  717. X  ++b->count;
  718. X  return b;
  719. X  }
  720. return 0;
  721. }
  722. X
  723. void brm(b)
  724. B *b;
  725. {
  726. if(!--b->count)
  727. X {
  728. X undorm(b);
  729. X splicef(H,link,&frhdrs,b->bof->hdr);
  730. X while(!qempty(P,link,b->bof)) prm(b->bof->link.next);
  731. X prm(b->bof);
  732. X if(b->name) free(b->name);
  733. X vclose(b->text);
  734. X free(deque(B,link,b));
  735. X }
  736. }
  737. X
  738. /**********************/
  739. /* Pointer management */
  740. /**********************/
  741. X
  742. P *pset(n,p)
  743. P *n, *p;
  744. {
  745. n->b=p->b;
  746. n->ofst=p->ofst;
  747. n->hdr=p->hdr;
  748. if(n->ptr) vunlock(n->ptr); n->ptr=p->ptr; vupcount(n->ptr);
  749. n->byte=p->byte;
  750. n->line=p->line;
  751. n->col=p->col;
  752. n->xcol=p->xcol;
  753. n->lbyte=p->lbyte;
  754. return n;
  755. }
  756. X
  757. P *pdup(p)
  758. P *p;
  759. {
  760. P *n=palloc();
  761. n->ptr=0;
  762. n->owner=0;
  763. enquef(P,link,p,n);
  764. return pset(n,p);
  765. }
  766. X
  767. P *pdupown(p,o)
  768. P *p;
  769. P **o;
  770. {
  771. P *n=palloc();
  772. n->ptr=0;
  773. n->owner=o;
  774. enquef(P,link,p,n);
  775. pset(n,p);
  776. if(*o) prm(*o);
  777. *o=n;
  778. return n;
  779. }
  780. X
  781. P *pbof(p)
  782. P *p;
  783. {
  784. return pset(p,p->b->bof);
  785. }
  786. X
  787. P *peof(p)
  788. P *p;
  789. {
  790. return pset(p,p->b->eof);
  791. }
  792. X
  793. void prm(p)
  794. P *p;
  795. {
  796. if(!p) return;
  797. if(p->owner) *p->owner=0;
  798. vunlock(p->ptr);
  799. pfree(deque(P,link,p));
  800. }
  801. X
  802. int pisbof(p)
  803. P *p;
  804. {
  805. return p->hdr==p->b->bof->hdr && !p->ofst;
  806. }
  807. X
  808. int piseof(p)
  809. P *p;
  810. {
  811. return p->hdr==p->b->bof->hdr->link.prev;
  812. }
  813. X
  814. int piseol(p)
  815. P *p;
  816. {
  817. if(p->hdr==p->b->bof->hdr->link.prev) return 1;
  818. if(p->ofst>=p->hdr->hole)
  819. X { if(p->ptr[p->ofst+p->hdr->ehole-p->hdr->hole]=='\n') return 1; }
  820. else if(p->ptr[p->ofst]=='\n') return 1;
  821. return 0;
  822. }
  823. X
  824. int pisbol(p)
  825. P *p;
  826. {
  827. char c;
  828. if(p->hdr==p->b->bof->hdr && !p->ofst) return 1;
  829. c=prgetcn(p); pfwrdn(p,(long)1);
  830. return c=='\n';
  831. }
  832. X
  833. int pisbow(p)
  834. P *p;
  835. {
  836. P *q=pdup(p);
  837. int c=brc(p);
  838. int d=prgetcn(q);
  839. prm(q);
  840. if((c>='a' && c<='z' || c>='A' && c<='Z' || c>='0' && c<='9') &&
  841. X !(d>='a' && d<='z' || d>='A' && d<='Z' || d>='0' && d<='9')) return 1;
  842. return 0;
  843. }
  844. X
  845. int piseow(p)
  846. P *p;
  847. {
  848. P *q=pdup(p);
  849. int d=brc(q);
  850. int c=prgetcn(q);
  851. prm(q);
  852. if((c>='a' && c<='z' || c>='A' && c<='Z' || c>='0' && c<='9') &&
  853. X !(d>='a' && d<='z' || d>='A' && d<='Z' || d>='0' && d<='9')) return 1;
  854. return 0;
  855. }
  856. X
  857. int pnext(p)
  858. P *p;
  859. {
  860. if(p->hdr==p->b->bof->hdr->link.prev) return 0;
  861. p->hdr=p->hdr->link.next; p->ofst=0;
  862. vunlock(p->ptr); p->ptr=vlock(p->b->text,p->hdr->seg);
  863. return GSIZE(p->hdr)!=0;
  864. }
  865. X
  866. int pprev(p)
  867. P *p;
  868. {
  869. if(p->hdr==p->b->bof->hdr) return 0;
  870. p->hdr=p->hdr->link.prev;
  871. p->ofst=GSIZE(p->hdr);
  872. vunlock(p->ptr); p->ptr=vlock(p->b->text,p->hdr->seg);
  873. return p->ofst;
  874. }
  875. X
  876. int pgetcn(p)
  877. P *p;
  878. {
  879. unsigned char c;
  880. if(p->ofst==GSIZE(p->hdr)) return MAXINT;
  881. if(p->ofst>=p->hdr->hole) c=p->ptr[p->ofst+p->hdr->ehole-p->hdr->hole];
  882. else c=p->ptr[p->ofst];
  883. if(++p->ofst==GSIZE(p->hdr)) pnext(p); 
  884. return c;
  885. }
  886. X
  887. int pgetc(p)
  888. P *p;
  889. {
  890. unsigned char c;
  891. if(p->ofst==GSIZE(p->hdr)) return MAXINT;
  892. if(p->ofst>=p->hdr->hole) c=p->ptr[p->ofst+p->hdr->ehole-p->hdr->hole];
  893. else c=p->ptr[p->ofst];
  894. if(++p->ofst==GSIZE(p->hdr)) pnext(p); 
  895. ++p->byte;
  896. if(c=='\n') ++p->line, p->col=0, p->lbyte=0;
  897. else
  898. X {
  899. X ++p->lbyte;
  900. X if(c=='\t') p->col+=p->b->tab-p->col%p->b->tab;
  901. X else ++p->col;
  902. X }
  903. return c;
  904. }
  905. X
  906. P *pfwrdn(p,n)
  907. P *p;
  908. long n;
  909. {
  910. while(n>=GSIZE(p->hdr)-p->ofst)
  911. X {
  912. X int adj=GSIZE(p->hdr)-p->ofst;
  913. X if(!adj) break;
  914. X n-=adj;
  915. X pnext(p);
  916. X }
  917. if(n>GSIZE(p->hdr)-p->ofst) return 0;
  918. p->ofst+=n;
  919. return p;
  920. }
  921. X
  922. P *pfwrd(p,n)
  923. P *p;
  924. long n;
  925. {
  926. int c;
  927. while(n--) if(pgetc(p)== MAXINT) return 0;
  928. return p;
  929. }
  930. X
  931. int prgetcn(p)
  932. P *p;
  933. {
  934. unsigned char c;
  935. if(!p->ofst) if(!pprev(p)) return MAXINT;
  936. --p->ofst;
  937. if(p->ofst>=p->hdr->hole)
  938. X c=p->ptr[p->ofst+p->hdr->ehole-p->hdr->hole];
  939. else c=p->ptr[p->ofst];
  940. return c;
  941. }
  942. X
  943. int prgetc(p)
  944. P *p;
  945. {
  946. unsigned char c;
  947. if(!p->ofst) if(!pprev(p)) return MAXINT;
  948. --p->ofst;
  949. if(p->ofst>=p->hdr->hole) c=p->ptr[p->ofst+p->hdr->ehole-p->hdr->hole];
  950. else c=p->ptr[p->ofst];
  951. --p->byte;
  952. if(c=='\n')
  953. X {
  954. X --p->line;
  955. X pfcol(p);
  956. X }
  957. else if(c=='\t') pfcol(p);
  958. else
  959. X {
  960. X --p->lbyte;
  961. X --p->col;
  962. X }
  963. return c;
  964. }
  965. X
  966. P *pbkwdn(p,n)
  967. P *p;
  968. long n;
  969. {
  970. while(n>p->ofst)
  971. X {
  972. X n-=p->ofst;
  973. X if(!pprev(p)) break;
  974. X }
  975. if(n>p->ofst) return 0;
  976. p->ofst-=n;
  977. return p;
  978. }
  979. X
  980. P *pbkwdf(p,n)
  981. P *p;
  982. long n;
  983. {
  984. while(n--)
  985. X {
  986. X if(!p->ofst) if(!pprev(p)) return 0;
  987. X --p->ofst;
  988. X --p->byte;
  989. X if(p->ofst>=p->hdr->hole)
  990. X  {
  991. X  if('\n'==p->ptr[p->ofst+p->hdr->ehole-p->hdr->hole])
  992. X  --p->line;
  993. X  }
  994. X else if('\n'==p->ptr[p->ofst]) --p->line;
  995. X }
  996. return p;
  997. }
  998. X
  999. P *pfcol(p)
  1000. P *p;
  1001. {
  1002. H *hdr=p->hdr;
  1003. int ofst=p->ofst;
  1004. pboln(p);
  1005. while(p->ofst!=ofst || p->hdr!=hdr) pgetc(p);
  1006. return p;
  1007. }
  1008. X
  1009. P *pbkwd(p,n)
  1010. P *p;
  1011. long n;
  1012. {
  1013. P *y=pbkwdf(p,n);
  1014. pfcol(p);
  1015. return y;
  1016. }
  1017. X
  1018. P *pbol(p)
  1019. P *p;
  1020. {
  1021. if(p->lbyte) pbkwdn(p,p->lbyte);
  1022. p->byte-=p->lbyte; p->lbyte=0; p->col=0;
  1023. return p;
  1024. }
  1025. X
  1026. P *pboln(p)
  1027. P *p;
  1028. {
  1029. if(pprevl(p)) pgetc(p);
  1030. p->col=0; p->lbyte=0;
  1031. return p;
  1032. }
  1033. X
  1034. P *peol(p)
  1035. P *p;
  1036. {
  1037. while(p->hdr!=p->b->bof->hdr->link.prev)
  1038. X {
  1039. X unsigned char c;
  1040. X if(p->ofst>=p->hdr->hole) c=p->ptr[p->ofst+p->hdr->ehole-p->hdr->hole];
  1041. X else c=p->ptr[p->ofst];
  1042. X if(c=='\n') break;
  1043. X else
  1044. X  {
  1045. X  ++p->byte;
  1046. X  ++p->ofst;
  1047. X  ++p->lbyte;
  1048. X  if(c=='\t') p->col+=p->b->tab-p->col%p->b->tab;
  1049. X  else ++p->col;
  1050. X  if(p->ofst==GSIZE(p->hdr)) pnext(p); 
  1051. X  }
  1052. X }
  1053. return p;
  1054. }
  1055. X
  1056. P *pnextl(p)
  1057. P *p;
  1058. {
  1059. char c;
  1060. do
  1061. X {
  1062. X if(p->ofst==GSIZE(p->hdr)) if(!pnext(p)) return 0;
  1063. X if(p->ofst>=p->hdr->hole) c=p->ptr[p->ofst+p->hdr->ehole-p->hdr->hole];
  1064. X else c=p->ptr[p->ofst];
  1065. X ++p->byte; ++p->ofst;
  1066. X }
  1067. X while(c!='\n');
  1068. ++p->line;
  1069. p->col=0; p->lbyte=0;
  1070. if(p->ofst==GSIZE(p->hdr)) pnext(p);
  1071. return p;
  1072. }
  1073. X
  1074. P *pprevl(p)
  1075. P *p;
  1076. {
  1077. char c;
  1078. do
  1079. X {
  1080. X if(!p->ofst) if(!pprev(p)) return 0;
  1081. X --p->ofst; --p->byte;
  1082. X if(p->ofst>=p->hdr->hole) c=p->ptr[p->ofst+p->hdr->ehole-p->hdr->hole];
  1083. X else c=p->ptr[p->ofst];
  1084. X }
  1085. X while(c!='\n');
  1086. --p->line;
  1087. return p;
  1088. }
  1089. X
  1090. P *pline(p,line)
  1091. P *p;
  1092. long line;
  1093. {
  1094. if(line>p->b->eof->line) { pset(p,p->b->eof); return p; }
  1095. if(line<Iabs(p->line-line)) pset(p,p->b->bof);
  1096. if(Iabs(p->b->eof->line-line)<Iabs(p->line-line)) pset(p,p->b->eof);
  1097. if(p->line==line) { pbol(p); return p; }
  1098. while(line>p->line) pnextl(p);
  1099. if(line<p->line)
  1100. X {
  1101. X while(line<p->line) pprevl(p);
  1102. X pboln(p);
  1103. X }
  1104. p->lbyte=0; p->col=0;
  1105. return p;
  1106. }
  1107. X
  1108. P *pcol(p,goalcol)
  1109. P *p;
  1110. long goalcol;
  1111. {
  1112. if(p->lbyte) pbol(p);
  1113. do
  1114. X {
  1115. X unsigned char c;
  1116. X int wid;
  1117. X if(p->ofst==GSIZE(p->hdr)) break;
  1118. X if(p->ofst>=p->hdr->hole) c=p->ptr[p->ofst+p->hdr->ehole-p->hdr->hole];
  1119. X else c=p->ptr[p->ofst];
  1120. X if(c=='\n') break;
  1121. X if(c=='\t') wid=p->b->tab-p->col%p->b->tab;
  1122. X else wid=1;
  1123. X if(p->col+wid>goalcol) break;
  1124. X if(++p->ofst==GSIZE(p->hdr)) pnext(p); 
  1125. X ++p->byte; ++p->lbyte; p->col+=wid;
  1126. X } while(p->col!=goalcol);
  1127. return p;
  1128. }
  1129. X
  1130. P *pfindrn(p,s,len)
  1131. P *p;
  1132. char *s;
  1133. {
  1134. P *q=pdup(p);
  1135. char *os;
  1136. int olen;
  1137. if(!len) return p;
  1138. q=pdup(p);
  1139. do
  1140. X {
  1141. X pset(q,p);
  1142. X os=s; olen=len;
  1143. X while(olen--) if(*os++!=pgetc(q)) break;
  1144. X if(olen== -1)
  1145. X  {
  1146. X  prm(q);
  1147. X  return p;
  1148. X  }
  1149. X } while(pbkwdf(p,1L));
  1150. prm(q);
  1151. return 0;
  1152. }
  1153. X
  1154. P *pfindrni(p,s,len)
  1155. P *p;
  1156. char *s;
  1157. {
  1158. P *q=pdup(p);
  1159. char *os;
  1160. int olen;
  1161. if(!len) return p;
  1162. q=pdup(p);
  1163. do
  1164. X {
  1165. X pset(q,p);
  1166. X os=s; olen=len;
  1167. X while(olen--) if(toup(*os++)!=toup(pgetc(q))) break;
  1168. X if(olen== -1)
  1169. X  {
  1170. X  prm(q);
  1171. X  return p;
  1172. X  }
  1173. X } while(pbkwdf(p,1L));
  1174. prm(q);
  1175. return 0;
  1176. }
  1177. X
  1178. P *pfindfn(p,s,len)
  1179. P *p;
  1180. char *s;
  1181. {
  1182. P *q=pdup(p);
  1183. char *os;
  1184. int olen;
  1185. int c;
  1186. if(!len) return p;
  1187. q=pdup(p);
  1188. while( (c=pgetc(p)) != MAXINT )
  1189. X if(c==s[0])
  1190. X  {
  1191. X  pset(q,p);
  1192. X  os=s+1; olen=len-1;
  1193. X  while(olen--) if(*os++!=pgetc(q)) break;
  1194. X  if(olen== -1)
  1195. X   {
  1196. X   prm(q);
  1197. X   prgetc(p);
  1198. X   return p;
  1199. X   }
  1200. X  }
  1201. prm(q);
  1202. return 0;
  1203. }
  1204. X
  1205. P *pfindfni(p,s,len)
  1206. P *p;
  1207. char *s;
  1208. {
  1209. P *q=pdup(p);
  1210. char *os;
  1211. int olen;
  1212. int c;
  1213. if(!len) return p;
  1214. q=pdup(p);
  1215. while( (c=pgetc(p)) != MAXINT )
  1216. X if(toup(c)==toup(s[0]))
  1217. X  {
  1218. X  pset(q,p);
  1219. X  os=s+1; olen=len-1;
  1220. X  while(olen--) if(toup(*os++)!=toup(pgetc(q))) break;
  1221. X  if(olen== -1)
  1222. X   {
  1223. X   prm(q);
  1224. X   prgetc(p);
  1225. X   return p;
  1226. X   }
  1227. X  }
  1228. prm(q);
  1229. return 0;
  1230. }
  1231. X
  1232. /******************************/
  1233. /* Getting data from a buffer */
  1234. /******************************/
  1235. X
  1236. int brc(p)
  1237. P *p;
  1238. {
  1239. if(p->hdr==p->b->bof->hdr->link.prev) return MAXINT;
  1240. if(p->ofst>=p->hdr->hole) return p->ptr[p->ofst+p->hdr->ehole-p->hdr->hole];
  1241. else return p->ptr[p->ofst];
  1242. }
  1243. X
  1244. char *brmem(p,blk,size)
  1245. P *p;
  1246. char *blk;
  1247. int size;
  1248. {
  1249. char *bk=blk;
  1250. P *np;
  1251. int amnt;
  1252. np=pdup(p);
  1253. while(size>(amnt=GSIZE(np->hdr)-np->ofst))
  1254. X {
  1255. X grmem(np->hdr,np->ptr,np->ofst,bk,amnt);
  1256. X bk+=amnt;
  1257. X size-=amnt;
  1258. X if(!pnext(np)) break;
  1259. X }
  1260. if(size<(amnt=GSIZE(np->hdr)-np->ofst)) amnt=size;
  1261. if(amnt) grmem(np->hdr,np->ptr,np->ofst,bk,amnt);
  1262. prm(np);
  1263. return blk;
  1264. }
  1265. X
  1266. char *brs(p,size)
  1267. P *p;
  1268. int size;
  1269. {
  1270. char *s=(char *)malloc(size+1);
  1271. s[size]=0;
  1272. return brmem(p,s,size);
  1273. }
  1274. X
  1275. char *brvs(p,size)
  1276. P *p;
  1277. int size;
  1278. {
  1279. char *s=vstrunc(NULL,size);
  1280. return brmem(p,s,size);
  1281. }
  1282. X
  1283. int bsavefd(p,fd,size)
  1284. P *p;
  1285. long size;
  1286. {
  1287. P *np=pdup(p);
  1288. int amnt;
  1289. while(size>(amnt=GSIZE(np->hdr)-np->ofst))
  1290. X {
  1291. X if(np->ofst<np->hdr->hole)
  1292. X  {
  1293. X  if(write(fd,np->ptr+np->ofst,np->hdr->hole-np->ofst)<0) return -5;
  1294. X  if(write(fd,np->ptr+np->hdr->ehole,SEGSIZ-np->hdr->ehole)<0) return -5;
  1295. X  }
  1296. X else if(write(fd,np->ptr+np->ofst+GGAPSZ(np->hdr),amnt)<0) return -5;
  1297. X size-=amnt;
  1298. X if(!pnext(np)) break;
  1299. X }
  1300. if(size<(amnt=GSIZE(np->hdr)-np->ofst)) amnt=size;
  1301. if(amnt)
  1302. X if(np->ofst<np->hdr->hole)
  1303. X  if(amnt>np->hdr->hole-np->ofst)
  1304. X   {
  1305. X   if(write(fd,np->ptr+np->ofst,np->hdr->hole-np->ofst)<0) return -5;
  1306. X   if(write(fd,np->ptr+np->hdr->ehole,amnt-np->hdr->hole+np->ofst)<0) return -5;
  1307. X   }
  1308. X  else
  1309. X   {
  1310. X   if(write(fd,np->ptr+np->ofst,amnt)<0) return -5;
  1311. X   }
  1312. X else if(write(fd,np->ptr+np->ofst+GGAPSZ(np->hdr),amnt)<0) return -5;
  1313. prm(np);
  1314. return 0; /* Check status returned by fwrite */
  1315. }
  1316. X
  1317. char *parsens(s,skip,amnt)
  1318. char *s;
  1319. long *skip, *amnt;
  1320. {
  1321. char *n=vsncpy(NULL,0,sz(s));
  1322. int x,y;
  1323. *skip=0;
  1324. *amnt= MAXLONG;
  1325. for(x=sLEN(n)-1;x>0 && (n[x]>='0' && n[x]<='9' || n[x]=='x' || n[x]=='X');--x);
  1326. if(n[x]==',')
  1327. X {
  1328. X int c;
  1329. X n[x]=0;
  1330. X if(n[x+1]=='x' || n[x+1]=='X') sscanf(n+x+2,"%lx",skip);
  1331. X else if(n[x+1]=='0' && (n[x+2]=='x' || n[x+2]=='X')) sscanf(n+x+3,"%lx",skip);
  1332. X else if(n[x+1]=='0') sscanf(n+x+1,"%lo",skip);
  1333. X else sscanf(n+x+1,"%d",skip);
  1334. X for(--x;x>0 && (n[x]>='0' && n[x]<='9' || n[x]=='x' || n[x]=='X');--x);
  1335. X if(n[x]==',')
  1336. X  {
  1337. X  n[x]=0;
  1338. X  *amnt= *skip;
  1339. X  if(n[x+1]=='x' || n[x+1]=='X') sscanf(n+x+2,"%lx",skip);
  1340. X  else if(n[x+1]=='0' && (n[x+2]=='x' || n[x+2]=='X')) sscanf(n+x+3,"%lx",skip);
  1341. X  else if(n[x+1]=='0') sscanf(n+x+1,"%lo",skip);
  1342. X  else sscanf(n+x+1,"%d",skip);
  1343. X  }
  1344. X }
  1345. if(n[0]=='~')
  1346. X {
  1347. X for(x=1;n[x] && n[x]!='/';++x);
  1348. X if(n[x]=='/')
  1349. X  if(x==1)
  1350. X   {
  1351. X   char *z;
  1352. X   s=getenv("HOME");
  1353. X   z=vsncpy(NULL,0,sz(s));
  1354. X   z=vsncpy(z,sLEN(z),sz(n+x));
  1355. X   vsrm(n);
  1356. X   n=z;
  1357. X   }
  1358. X  else
  1359. X   {
  1360. X   struct passwd *passwd;
  1361. X   n[x]=0;
  1362. X   passwd=getpwnam(n+1);
  1363. X   n[x]='/';
  1364. X   if(passwd)
  1365. X    {
  1366. X    char *z=vsncpy(NULL,0,sz(passwd->pw_dir));
  1367. X    z=vsncpy(z,sLEN(z),sz(n+x));
  1368. X    vsrm(n);
  1369. X    n=z;
  1370. X    }
  1371. X   }
  1372. X }
  1373. return n;
  1374. }
  1375. X
  1376. int bsave(p,s,size)
  1377. P *p;
  1378. char *s;
  1379. long size;
  1380. {
  1381. FILE *f;
  1382. int flg;
  1383. long skip,amnt;
  1384. s=parsens(s,&skip,&amnt);
  1385. if(amnt<size) size=amnt;
  1386. if(s[0]=='!')
  1387. X {
  1388. X nescape(maint->t);
  1389. X ttclsn();
  1390. X f=popen(s+1,"w");
  1391. X }
  1392. else if(s[0]=='>' && s[1]=='>') f=fopen(s+2,"a");
  1393. else if(!zcmp(s,"-"))
  1394. X {
  1395. X nescape(maint->t);
  1396. X ttclsn();
  1397. X f=stdout;
  1398. X }
  1399. else
  1400. X if(skip || amnt!=MAXLONG) f=fopen(s,"r+");
  1401. X else f=fopen(s,"w");
  1402. if(!f)
  1403. X {
  1404. X if(s[0]=='!') ttopnn(), nreturn(maint->t);
  1405. X return -4;
  1406. X }
  1407. fflush(f);
  1408. X
  1409. if(skip && lseek(fileno(f),skip,0)<0) { flg= -3; goto err; }
  1410. X
  1411. flg=bsavefd(p,fileno(f),size);
  1412. if(force && size && !skip && amnt==MAXINT)
  1413. X {
  1414. X P *q=pdup(p);
  1415. X char nl='\n';
  1416. X pfwrdn(p,size-1);
  1417. X if(brc(p)!='\n')
  1418. X  if(write(fileno(f),&nl,1)<0) flg= -5;
  1419. X }
  1420. err:;
  1421. if(s[0]=='!') pclose(f);
  1422. else if(zcmp(s,"-")) fclose(f);
  1423. else fflush(f);
  1424. if(s[0]=='!' || !zcmp(s,"-")) ttopnn(), nreturn(maint->t);
  1425. return flg;
  1426. }
  1427. X
  1428. /*******************************/
  1429. /* Deleting data from a buffer */
  1430. /*******************************/
  1431. X
  1432. static void fixup(p,amnt,nlines,hdr,hdramnt)
  1433. P *p;
  1434. long amnt;
  1435. long nlines;
  1436. H *hdr;
  1437. int hdramnt;
  1438. {
  1439. P *pp;
  1440. int flg;
  1441. if(!p->lbyte) flg=0;
  1442. else flg=1;
  1443. scrdel(p->b,p->line,nlines,flg);
  1444. for(pp=p->link.next;pp!=p;pp=pp->link.next)
  1445. X if(pp->byte>=p->byte)
  1446. X  if(pp->byte<=p->byte+amnt) pset(pp,p);
  1447. X  else
  1448. X   {
  1449. X   if(pp->hdr==hdr) pp->ofst-=hdramnt;
  1450. X   if(pp->line==p->line+nlines) pp->col=~(long)0;
  1451. X   pp->byte-=amnt;
  1452. X   pp->line-=nlines;
  1453. X   }
  1454. for(pp=p->link.next;pp!=p;pp=pp->link.next)
  1455. X if(pp->col==~(long)0) pfcol(pp);
  1456. p->b->chnged=1;
  1457. }
  1458. X
  1459. static void frchn(b,h)
  1460. B *b;
  1461. H *h;
  1462. {
  1463. H *a;
  1464. a=h; do
  1465. X sfree(b,a->seg),
  1466. X a=a->link.next;
  1467. X while(a!=h);
  1468. splicef(H,link,&frhdrs,h);
  1469. }
  1470. X
  1471. P *bdel(from,to)
  1472. P *from, *to;
  1473. {
  1474. long nlines=to->line-from->line;/* No. EOLs to delete */
  1475. long amnt=to->byte-from->byte;    /* No. bytes to delete */
  1476. int toamnt;            /* Amount delete from segment in 'to' */
  1477. if(from->byte==to->byte) return from;
  1478. undodel(from,amnt);
  1479. if(from->hdr==to->hdr)
  1480. X {
  1481. X gdel(from->hdr,from->ptr,from->ofst,(int)amnt);
  1482. X toamnt=amnt;
  1483. X }
  1484. else
  1485. X {
  1486. X H *a;
  1487. X toamnt=to->ofst;
  1488. X /* Delete beginning of to */
  1489. X gstgap(to->hdr,to->ptr,to->ofst);
  1490. X to->hdr->hole=0;
  1491. X
  1492. X /* Delete end of from */
  1493. X if(from->ofst)
  1494. X  {
  1495. X  a=from->hdr;
  1496. X  gstgap(from->hdr,from->ptr,from->ofst);
  1497. X  from->hdr->ehole=SEGSIZ;
  1498. X  }
  1499. X else a=from->hdr->link.prev;
  1500. X
  1501. X /* From now points to header/segment of to */
  1502. X from->hdr=to->hdr;
  1503. X vunlock(from->ptr); from->ptr=to->ptr; vupcount(to->ptr);
  1504. X from->ofst=0;
  1505. X
  1506. X /* Delete headers/segments between a and to->hdr */
  1507. X if(a->link.next!=to->hdr)
  1508. X  frchn(to->b,snip(H,link,a->link.next,to->hdr->link.prev));
  1509. X }
  1510. X
  1511. fixup(from,amnt,nlines,to->hdr,toamnt);
  1512. return from;
  1513. }
  1514. X
  1515. /********************************/
  1516. /* Inserting data into a buffer */
  1517. /********************************/
  1518. X
  1519. /* Split a block at p's ofst */
  1520. /* p is placed in the new block such that it points to the same text but with
  1521. X * p->ofst==0
  1522. X */
  1523. X
  1524. static void bsplit(p)
  1525. P *p;
  1526. {
  1527. if(p->ofst)
  1528. X {
  1529. X H *hdr;
  1530. X char *ptr;
  1531. X P *pp;
  1532. X
  1533. X hdr=halloc();
  1534. X hdr->seg=salloc(p->b);
  1535. X ptr=vlock(p->b->text,hdr->seg);
  1536. X
  1537. X gstgap(p->hdr,p->ptr,p->ofst);
  1538. X mcpy(ptr,p->ptr+p->hdr->ehole,SEGSIZ-p->hdr->ehole);
  1539. X vchanged(ptr);
  1540. X hdr->hole=SEGSIZ-p->hdr->ehole;
  1541. X hdr->ehole=SEGSIZ;
  1542. X p->hdr->ehole=SEGSIZ;
  1543. X
  1544. X enquef(H,link,p->hdr,hdr);
  1545. X vunlock(p->ptr);
  1546. X
  1547. X for(pp=p->link.next;pp!=p;pp=pp->link.next)
  1548. X  if(pp->hdr==p->hdr && pp->ofst>=p->ofst)
  1549. X   {
  1550. X   pp->hdr=hdr;
  1551. X   vunlock(pp->ptr); pp->ptr=ptr; vupcount(ptr);
  1552. X   pp->ofst-=p->ofst;
  1553. X   }
  1554. X
  1555. X p->ptr=ptr;
  1556. X p->hdr=hdr;
  1557. X p->ofst=0;
  1558. X }
  1559. }
  1560. X
  1561. static void inschn(p,a)
  1562. P *p;
  1563. H *a;
  1564. {
  1565. bsplit(p);
  1566. p->hdr=spliceb(H,link,p->hdr,a);
  1567. vunlock(p->ptr); p->ptr=vlock(p->b->text,a->seg);
  1568. }
  1569. X
  1570. static H *bldchn(b,blk,size)
  1571. B *b;
  1572. char *blk;
  1573. int size;
  1574. {
  1575. H anchor, *l;
  1576. izque(H,link,&anchor);
  1577. do
  1578. X {
  1579. X char *ptr;
  1580. X int amnt;
  1581. X ptr=vlock(b->text,(l=halloc())->seg=salloc(b));
  1582. X if(size>SEGSIZ) amnt=SEGSIZ;
  1583. X else amnt=size;
  1584. X mcpy(ptr,blk,amnt);
  1585. X vchanged(ptr); vunlock(ptr);
  1586. X l->hole=amnt; l->ehole=SEGSIZ;
  1587. X enqueb(H,link,&anchor,l);
  1588. X blk+=amnt; size-=amnt;
  1589. X }
  1590. X while(size);
  1591. l=anchor.link.next;
  1592. deque(H,link,&anchor);
  1593. return l;
  1594. }
  1595. X
  1596. static void fixup1(p,amnt,nlines,hdr,hdramnt)
  1597. P *p;
  1598. long amnt;
  1599. long nlines;
  1600. H *hdr;
  1601. int hdramnt;
  1602. {
  1603. P *pp;
  1604. int flg;
  1605. if(!p->lbyte) flg=0;
  1606. else flg=1;
  1607. scrins(p->b,p->line,nlines,flg);
  1608. for(pp=p->link.next;pp!=p;pp=pp->link.next)
  1609. X if(pp->byte==p->byte && pp!=p->b->eof) pset(pp,p);
  1610. X else if(pp->byte>p->byte || pp==p->b->eof)
  1611. X  {
  1612. X  pp->byte+=amnt;
  1613. X  if(pp->line==p->line) pp->col=~(long)0;
  1614. X  pp->line+=nlines;
  1615. X  if(pp->hdr==hdr) pp->ofst+=hdramnt;
  1616. X  }
  1617. for(pp=p->link.next;pp!=p;pp=pp->link.next) if(pp->col==~(long)0) pfcol(pp);
  1618. undoins(p,amnt);
  1619. p->b->chnged=1;
  1620. }
  1621. X
  1622. P *binsm(p,blk,amnt)
  1623. P *p;
  1624. char *blk;
  1625. int amnt;
  1626. {
  1627. long nlines=mcnt(blk,'\n',amnt);
  1628. H *h=0;
  1629. int hdramnt;
  1630. if(p->hdr!=p->b->eof->hdr && amnt<=GGAPSZ(p->hdr))
  1631. X {
  1632. X h=p->hdr;
  1633. X hdramnt=amnt;
  1634. X ginsm(p->hdr,p->ptr,p->ofst,blk,amnt);
  1635. X }
  1636. else if(p->hdr==p->b->eof->hdr &&
  1637. X        p->b->bof->hdr != p->b->eof->hdr &&
  1638. X        amnt<=GGAPSZ(p->hdr->link.prev))
  1639. X {
  1640. X pprev(p); 
  1641. X ginsm(p->hdr,p->ptr,p->ofst,blk,amnt);
  1642. X }
  1643. else
  1644. X {
  1645. X H *a=bldchn(p->b,blk,amnt);
  1646. X inschn(p,a);
  1647. X }
  1648. fixup1(p,(long)amnt,nlines,h,hdramnt);
  1649. return p;
  1650. }
  1651. X
  1652. P *binsc(p,c)
  1653. P *p;
  1654. char c;
  1655. {
  1656. return binsm(p,&c,1);
  1657. }
  1658. X
  1659. P *binss(p,s)
  1660. P *p;
  1661. char *s;
  1662. {
  1663. return binsm(p,s,zlen(s));
  1664. }
  1665. X
  1666. P *binsb(p,from,to)
  1667. P *p, *from, *to;
  1668. {
  1669. P *dp=pdup(p);
  1670. P *sp=pdup(from);
  1671. int amnt;
  1672. if(p->b==from->b && p->byte>=from->byte && p->byte<to->byte)
  1673. X {
  1674. X P *mid=pdup(dp);
  1675. X while(mid->byte-sp->byte>=1024)
  1676. X  {
  1677. X  brmem(sp,buffer,1024);
  1678. X  binsm(dp,buffer,1024);
  1679. X  pfwrdn(sp,(long)1024), sp->byte+=1024;
  1680. X  pfwrdn(dp,(long)1024), dp->byte+=1024;
  1681. X  }
  1682. X if(amnt=mid->byte-sp->byte)
  1683. X  {
  1684. X  brmem(sp,buffer,amnt);
  1685. X  binsm(dp,buffer,amnt);
  1686. X  pfwrdn(sp,(long)amnt), sp->byte+=amnt;
  1687. X  pfwrdn(dp,(long)amnt), dp->byte+=amnt;
  1688. X  }
  1689. X prm(mid);
  1690. X pset(sp,dp);
  1691. X pset(dp,to);
  1692. X }
  1693. while(to->byte-sp->byte>=1024)
  1694. X {
  1695. X brmem(sp,buffer,1024);
  1696. X binsm(dp,buffer,1024);
  1697. X pfwrdn(sp,(long)1024), sp->byte+=1024;
  1698. X pfwrdn(dp,(long)1024), dp->byte+=1024;
  1699. X }
  1700. if(amnt=to->byte-sp->byte)
  1701. X {
  1702. X brmem(sp,buffer,amnt);
  1703. X binsm(dp,buffer,amnt);
  1704. X }
  1705. prm(dp);
  1706. prm(sp);
  1707. return p;
  1708. }
  1709. X
  1710. static int bkread(fi,buff,size)
  1711. char *buff;
  1712. int size;
  1713. {
  1714. int a,b;
  1715. if(!size) return -1;
  1716. for(a=b=0;(a<size) && ((b=read(fi,buff+a,size-a))>0);a+=b);
  1717. return (b<0) ? -1 : a;
  1718. }
  1719. X
  1720. static H *rdchn(b,fi,linesp,totala,max)
  1721. B *b;
  1722. long *linesp;
  1723. long *totala;
  1724. long *max;
  1725. {
  1726. H anchor, *l;
  1727. long lines=0, total=0;
  1728. char *ptr;
  1729. int amnt;
  1730. long vseg;
  1731. char *seg;
  1732. izque(H,link,&anchor);
  1733. while((amnt=bkread(fi,seg=vlock(b->text,vseg=salloc(b)),*max>=SEGSIZ?SEGSIZ:(int)*max))>0)
  1734. X {
  1735. X total+=amnt;
  1736. X *max-=amnt;
  1737. X lines+=mcnt(seg,'\n',amnt);
  1738. X vchanged(seg); vunlock(seg);
  1739. X l=halloc();
  1740. X l->seg=vseg;
  1741. X l->hole=amnt;
  1742. X l->ehole=SEGSIZ;
  1743. X enqueb(H,link,&anchor,l);
  1744. X }
  1745. sfree(b,vseg);
  1746. vunlock(seg);
  1747. if(amnt<0) return 0;
  1748. *linesp=lines;
  1749. *totala=total;
  1750. l=anchor.link.next;
  1751. deque(H,link,&anchor);
  1752. return l;
  1753. }
  1754. X
  1755. int binsfd(p,fd,max)
  1756. P *p;
  1757. long max;
  1758. {
  1759. long nlines;
  1760. long amnt;
  1761. int flg;
  1762. H *a;
  1763. if(a=rdchn(p->b,fd,&nlines,&amnt,&max))
  1764. X {
  1765. X if(amnt)
  1766. X  {
  1767. X  inschn(p,a);
  1768. X  fixup1(p,amnt,nlines,NULL,0);
  1769. X  }
  1770. X return 0;
  1771. X }
  1772. return -2;
  1773. }
  1774. X
  1775. int binsf(p,s)
  1776. P *p;
  1777. char *s;
  1778. {
  1779. FILE *fi;
  1780. int flg;
  1781. long skip,amnt;
  1782. s=parsens(s,&skip,&amnt);
  1783. if(s[0]=='!')
  1784. X {
  1785. X nescape(maint->t);
  1786. X ttclsn();
  1787. X fi=popen(s+1,"r");
  1788. X }
  1789. else if(!zcmp(s,"-")) fi=stdin;
  1790. else fi=fopen(s,"r");
  1791. if(!fi)
  1792. X {
  1793. X if(s[0]=='!') ttopnn(), nreturn(maint->t);
  1794. X if(errno==ENOENT) return -1;
  1795. X else return -4;
  1796. X }
  1797. if(skip)
  1798. X {
  1799. X if(lseek(fileno(fi),skip,0)<0)
  1800. X  {
  1801. X  int r;
  1802. X  while(skip>1024)
  1803. X   {
  1804. X   r=read(fileno(fi),buffer,1024);
  1805. X   if(r!= -1) skip-=r;
  1806. X   else { flg= -3; goto err; }
  1807. X   }
  1808. X  while(skip)
  1809. X   {
  1810. X   r=read(fileno(fi),buffer,(int)skip);
  1811. X   if(r!= -1) skip-=r;
  1812. X   else { flg= -3; goto err; }
  1813. X   }
  1814. X  }
  1815. X }
  1816. flg=binsfd(p,fileno(fi),amnt);
  1817. err:;
  1818. if(s[0]=='!') pclose(fi);
  1819. else if(zcmp(s,"-")) fclose(fi);
  1820. if(s[0]=='!') ttopnn(), nreturn(maint->t);
  1821. vsrm(s);
  1822. return flg;
  1823. }
  1824. X
  1825. int bload(b,s)
  1826. B *b;
  1827. char *s;
  1828. {
  1829. int rtval;
  1830. long skip,amnt;
  1831. inundo=1;
  1832. rtval=binsf(b->bof,s);
  1833. inundo=0;
  1834. b->name=zdup(s);
  1835. if(rtval)
  1836. X {
  1837. X b->backup=1;
  1838. X b->chnged=0;
  1839. X return rtval;
  1840. X }
  1841. b->chnged=0;
  1842. b->backup=0;
  1843. s=parsens(s,&skip,&amnt);
  1844. if(!zcmp(s,"-")) b->backup=1, b->chnged=1;
  1845. else if(s[0]=='!') b->backup=1;
  1846. else if(skip || amnt!=MAXLONG) b->backup=1;
  1847. vsrm(s);
  1848. return rtval;
  1849. }
  1850. X
  1851. /* View chain */
  1852. X
  1853. void check(b)
  1854. B *b;
  1855. {
  1856. H *h;
  1857. for(h=b->bof->hdr->link.next;h!=b->bof->hdr;h=h->link.next)
  1858. X {
  1859. X printf("\r%8.8X: prev=%X next=%X seq=%lX hole=%d ehole=%d\r\n",
  1860. X        h,h->link.prev,h->link.next,h->seg,h->hole,h->ehole);
  1861. X }
  1862. printf("\r%8.8X: prev=%X next=%X seq=%lX hole=%d ehole=%d\r\n",
  1863. X       h,h->link.prev,h->link.next,h->seg,h->hole,h->ehole);
  1864. }
  1865. X
  1866. /* View pointers */
  1867. X
  1868. void checkp(b)
  1869. B *b;
  1870. {
  1871. P *p;
  1872. printf("\rPointers\r\n");
  1873. for(p=b->bof->link.next;p!=b->bof;p=p->link.next)
  1874. X {
  1875. X if(p==b->bof) printf("\rBof: ");
  1876. X else if(p==b->eof) printf("\rEof: ");
  1877. X else printf("\r");
  1878. X  printf("Byte=%ld Hdr=%X Ofst=%d Line=%ld Col=%ld Lbyte=%ld\r\n",
  1879. X     p->byte,p->hdr,p->ofst,p->line,p->col,p->lbyte);
  1880. X }
  1881. if(p==b->bof) printf("\rBof: ");
  1882. else if(p==b->eof) printf("\rEof: ");
  1883. else printf("\r");
  1884. printf("Byte=%ld Hdr=%X Ofst=%d Line=%ld Col=%ld Lbyte=%ld\r\n",p->byte,p->hdr,p->ofst,p->line,p->col,p->lbyte);
  1885. }
  1886. X
  1887. /* Refigure column numbers */
  1888. X
  1889. void refigure()
  1890. {
  1891. B *b;
  1892. P *p;
  1893. for(b=bufs.link.next;b!=&bufs;b=b->link.next)
  1894. X {
  1895. X p=b->bof; do
  1896. X  pfcol(p), p->xcol=p->col;
  1897. X  while(p=p->link.next, p!=b->bof);
  1898. X }
  1899. }
  1900. X
  1901. /* Save edit buffers when editor dies */
  1902. X
  1903. void ttsig(sig)
  1904. {
  1905. long tim=time(0);
  1906. B *b;
  1907. FILE *f=fopen("DEADJOE","a");
  1908. fprintf(f,"\n*** Modified files in JOE when it aborted on %s",ctime(&tim));
  1909. if(sig) fprintf(f,"*** JOE was aborted by signal %d\n",sig);
  1910. else fprintf(f,"*** JOE was aborted because the terminal closed\n");
  1911. fflush(f);
  1912. for(b=bufs.link.next;b!=&bufs;b=b->link.next)
  1913. X if(b->chnged)
  1914. X  {
  1915. X  if(b->name) fprintf(f,"\n*** File \'%s\'\n",b->name);
  1916. X  else fprintf(f,"\n*** File \'(Unnamed)\'\n",b->name);
  1917. X   fflush(f);
  1918. X  bsavefd(b->bof,fileno(f),b->eof->byte);
  1919. X  }
  1920. _exit(1);
  1921. }
  1922. SHAR_EOF
  1923. chmod 0600 b.c ||
  1924. echo 'restore of b.c failed'
  1925. Wc_c="`wc -c < 'b.c'`"
  1926. test 24715 -eq "$Wc_c" ||
  1927.     echo 'b.c: original size 24715, current size' "$Wc_c"
  1928. fi
  1929. # ============= b.h ==============
  1930. if test -f 'b.h' -a X"$1" != X"-c"; then
  1931.     echo 'x - skipping b.h (File already exists)'
  1932. else
  1933. echo 'x - extracting b.h (Text)'
  1934. sed 's/^X//' << 'SHAR_EOF' > 'b.h' &&
  1935. /* Buffer management
  1936. X   Copyright (C) 1992 Joseph H. Allen
  1937. X
  1938. This file is part of JOE (Joe's Own Editor)
  1939. X
  1940. JOE is free software; you can redistribute it and/or modify it under the 
  1941. terms of the GNU General Public License as published by the Free Software 
  1942. Foundation; either version 1, or (at your option) any later version.  
  1943. X
  1944. JOE is distributed in the hope that it will be useful, but WITHOUT ANY 
  1945. WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 
  1946. FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more 
  1947. details.  
  1948. X
  1949. You should have received a copy of the GNU General Public License along with 
  1950. JOE; see the file COPYING.  If not, write to the Free Software Foundation, 
  1951. 675 Mass Ave, Cambridge, MA 02139, USA.  */ 
  1952. X
  1953. X
  1954. #ifndef _Ib
  1955. #define _Ib 1
  1956. X
  1957. #include "config.h"
  1958. #include "queue.h"
  1959. #include "vfile.h"
  1960. #include "undo.h"
  1961. X
  1962. typedef struct header H;
  1963. typedef struct point P;
  1964. typedef struct buffer B;
  1965. X
  1966. #define HDRSIZ 16        /* Text segment header size */
  1967. #define SEGSIZ 1024        /* Text segment size */
  1968. X
  1969. /* A text segment header */
  1970. X
  1971. struct header
  1972. X {
  1973. X LINK(H) link;            /* Doubly-linked list of headers */
  1974. X long seg;            /* Virtual address of text segment */
  1975. X unsigned short hole;        /* Offset to hole */
  1976. X unsigned short ehole;        /* Offset to text following hole */
  1977. X };
  1978. X
  1979. /* A buffer */
  1980. X
  1981. extern int force;
  1982. extern char *stdio;        /* If file name is set to this, use stdio */
  1983. X
  1984. struct buffer
  1985. X {
  1986. X LINK(B) link;            /* Doubly-linked list of buffers */
  1987. X VFILE *text;            /* Software virtual memory for this buffer */
  1988. X long fretxt;            /* Linked list of free text */
  1989. X P *bof;            /* Address of BOF pointer */
  1990. X P *eof;            /* Address of EOF pointer */
  1991. X char *name;            /* File name/0 for unnamed/stdio */
  1992. X int count;            /* Reference count */
  1993. X int chnged;            /* Set if changed since last save */
  1994. X int backup;            /* Set if backup file needn't be written */
  1995. X UNDO *undo;            /* Undo storage */
  1996. X int tab;            /* Tab width */
  1997. X };
  1998. X
  1999. /* A pointer */
  2000. X
  2001. struct point
  2002. X {
  2003. X LINK(P) link;            /* Doubly-linked list of pointers */
  2004. X
  2005. X /* Physical section of pointer
  2006. X  * These must be absolutely correct for the pointer to actually be pointing
  2007. X  * anywhere */
  2008. X B *b;                /* Buffer this pointer is in */
  2009. X int ofst;            /* Byte offset into current segment */
  2010. X char *ptr;            /* Address of current segment */
  2011. X H *hdr;            /* Address of segment's header */
  2012. X
  2013. X /* Logical section
  2014. X  * These give more information about the pointer's location.  Sometimes
  2015. X  * one or more of these may not be correctly updated */
  2016. X long byte;            /* Byte offset from beginning of file */
  2017. X long line;            /* Line number */
  2018. X long col;            /* Column number */
  2019. X long xcol;            /* Extended column number */
  2020. X long lbyte;            /* Byte number */
  2021. X P **owner;            /* Owner of this pointer */
  2022. X };
  2023. X
  2024. /*******************************/
  2025. /* Buffer management functions */
  2026. /*******************************/
  2027. X
  2028. /* B *bmk(void);
  2029. X * Create a new empty buffer.
  2030. X * The following variables get these initializations:
  2031. X *     name            NULL
  2032. X *     reference count 1
  2033. X *     backup flag     1
  2034. X *     changed flag    0
  2035. X */
  2036. B *bmk();
  2037. X
  2038. /* B *bfind(char *name);
  2039. X * Find file.  Returns with buffer of already loaded file or 0.  If the
  2040. X * file is found, the buffer's reference count is incremented.
  2041. X */
  2042. B *bfind();
  2043. X
  2044. /* void brm(B *b);
  2045. X * Decrement a buffer's reference count.  If it reaches zero, eliminate the
  2046. X * buffer.
  2047. X */
  2048. void brm();
  2049. X
  2050. /********************************/
  2051. /* Pointer management functions */
  2052. /********************************/
  2053. X
  2054. /* P *pdup(P *p);
  2055. X * Duplicate a pointer.  The new pointer's owner is set to NULL.
  2056. X */
  2057. P *pdup();
  2058. X
  2059. /* P *pdupown(P *p,P **o);
  2060. X * Duplicate pointer and set ownership of pointer
  2061. X */
  2062. P *pdupown();
  2063. X
  2064. /* P *pset(P *p,P *n);
  2065. X * Force a pointer p to point to the same place as another pointer n.
  2066. X * Caution: this assumes that the original pointer p is pointing to a
  2067. X * valid locked text segment.  If it doesn't, you must clear p->ptr
  2068. X * before calling this function.
  2069. X */
  2070. P *pset();
  2071. X
  2072. /* P *peof(P *p);
  2073. X * Force a pointer to point to the end of file
  2074. X */
  2075. P *peof();
  2076. X
  2077. /* P *pbof(P *p);
  2078. X * Force a pointer to point to the beginning of file
  2079. X */
  2080. P *pbof();
  2081. X
  2082. /* void prm(P *p);
  2083. X * Remove a pointer.  Clears the pointer's owner address.
  2084. X */
  2085. void prm();
  2086. X
  2087. /* int pisbof(P *p);
  2088. X * Return true if pointer is at beginning of file
  2089. X * This can be used on pointers with incorrect logical sections
  2090. X */
  2091. int pisbof();
  2092. X
  2093. /* int piseof(P *p);
  2094. X * Return true if pointer is at end of file
  2095. X * Ok to use if the pointer's logical section is incorrect or if the buffer's
  2096. X * end of file pointer is incorrect.
  2097. X */
  2098. int piseof();
  2099. X
  2100. /* int pisbol(P *p);
  2101. X * Return true if pointer is at beginning of line.
  2102. X * Ok to use if the pointer's logical section is incorrect.
  2103. X */
  2104. int pisbol();
  2105. X
  2106. /* int piseol(P *p);
  2107. X * Return true if pointer is at end of line
  2108. X * This can be used if the pointer's logical section is incorrect.  It can
  2109. X * also be used if the buffer's end of file pointer is incorrect.
  2110. X */
  2111. int piseol();
  2112. X
  2113. /* int pisbow(P *p);
  2114. X * Return true if pointer is at beginning of a word
  2115. X */
  2116. int pisbow();
  2117. X
  2118. /* int piseow(P *p);
  2119. X * Return true if pointer is at end of word
  2120. X */
  2121. int piseow();
  2122. X
  2123. /* int pnext(P *p);
  2124. X * Advance pointer to beginning of next segment.  Only updates physical part
  2125. X * of pointer.  Returns false if the pointer was at or reached end of buffer.
  2126. X */
  2127. int pnext();
  2128. X
  2129. /* int pprev(P *p);
  2130. X * Set pointer to after end of previous segment.  Only updates physical part of
  2131. X * pointer.  Returns false if pointer was at or reached beginning of buffer.
  2132. X * Warning: this function sets the pointer to an invalid place.  Only use this
  2133. X * if p->ofst will be subsequently decremented before any characters are read.
  2134. X */
  2135. int pprev();
  2136. X
  2137. /* int pgetcn(P *p);
  2138. X * Get character at pointer and advance pointer.  Only updates physical
  2139. X * section of pointer.  Workds ok if buffer's end of file pointer is
  2140. X * incorrect.  Returns -1 if pointer was at end of buffer.
  2141. X */
  2142. int pgetcn();
  2143. X
  2144. /* int pgetc(P *p);
  2145. X * Get character at pointer and advance pointer.  Returns -1 if pointer
  2146. X * was at end of file.  Works ok if buffer's end of file pointer is incorrect.
  2147. X */
  2148. int pgetc();
  2149. X
  2150. /* P *pfwrdn(P *p,long n);
  2151. X * Advance pointer by n characters.  Only the physical section of the pointer
  2152. X * is updated.  Works ok if buffer's end of buffer pointer is incorrect.
  2153. X */
  2154. P *pfwrdn();
  2155. X
  2156. /* P *pfwrd(P *p,long n);
  2157. X * Advance pointer by n characters.  If the pointer goes past the end of the
  2158. X * buffer, the pointer is set to the end of the buffer and 0 is returned
  2159. X * instead of the pointer.
  2160. X */
  2161. P *pfwrd();
  2162. X
  2163. /* int prgetcn(P *p);
  2164. X * Move pointer back one and return character that position.  Returns -1
  2165. X * if pointer was at beginning of file.  Only updates physical part of
  2166. X * pointer.
  2167. X */
  2168. int prgetcn();
  2169. X
  2170. /* int prgetc(P *p);
  2171. X * Move pointer back one and return character at that position.  Returns -1
  2172. X * if pointer was at beginning of file.
  2173. X */
  2174. int prgetc();
  2175. X
  2176. /* P *pbkwdn(P *p,long n);
  2177. X * Move pointer back n characters.  Returns 0 on attempt to go before
  2178. X * beginning of buffer.  Only updates physical section of pointer.
  2179. X */
  2180. P *pbkwdn();
  2181. X
  2182. /* P *pbkwdf(P *p,long n);
  2183. X * Move pointer back n characters.  Returns 0 on attempt to go before
  2184. X * beginning of buffer.  Only updates line number part of logical section
  2185. X * of pointer.
  2186. X */
  2187. P *pbkwdf();
  2188. X
  2189. /* P *pfcol(P *p);
  2190. X * Determine and set column number of line byte number parts of logical
  2191. X * section of p.  Works ok if end of file pointer is incorrect.
  2192. X */
  2193. P *pfcol();
  2194. X
  2195. /* P *pbkwd(P *p,long n);
  2196. X * Move pointer back n characters.  Returns 0 if attempt to move before
  2197. X * beginning of buffer.
  2198. X */
  2199. P *pbkwd();
  2200. X
  2201. /* P *pbol(P *p);
  2202. X * Set pointer to beginning of line.  'lbyte' of logical part of pointer
  2203. X * must be correct.
  2204. X */
  2205. P *pbol();
  2206. X
  2207. /* P *pboln(P *p);
  2208. X * Set pointer to beginning of line.  Works ok if logical part of pointer
  2209. X * is not correct.
  2210. X */
  2211. P *pboln();
  2212. X
  2213. /* P *peol(P *p);
  2214. X * Set pointer to end of line.  Works ok if end of buffer pointer is
  2215. X * incorrect.
  2216. X */
  2217. P *peol();
  2218. X
  2219. /* P *pnextl(P *p);
  2220. X * Set pointer to beginning of next line or end of last line.  Returns 0
  2221. X * for end of last line.  Column number section of logical part of pointer
  2222. X * is not set.
  2223. X */
  2224. P *pnextl();
  2225. X
  2226. /* P *pprevl(P *p);
  2227. X * Set pointer to end of previous line or beginning of first line.  Returns
  2228. X * 0 if we got to the beginning part of the first line.  Column number
  2229. X * section of logicl part of pointer is not set.
  2230. X */
  2231. P *pprevl();
  2232. X
  2233. /* P *pline(P *p,long line);
  2234. X * Goto beginning of given line number.  Line number part of logical section
  2235. X * of pointer (and eof pointer) must be correct.
  2236. X */
  2237. P *pline();
  2238. X
  2239. /* P *pcol(P *p,long col);
  2240. X * Goto given column number.  The original column number (and lbyte) need
  2241. X * not be correct.
  2242. X */
  2243. P *pcol();
  2244. X
  2245. /* P *pfindrn(P *p,char *s,int len);
  2246. X * Search reverse for string
  2247. X */
  2248. P *pfindrn();
  2249. X
  2250. /* P *pfindrni(P *p,char *s,int len);
  2251. X * Search reverse for string case insensitive
  2252. X */
  2253. P *pfindrni();
  2254. X
  2255. /* P *pfindfn(P *p,char *s,int len);
  2256. X * Find first occurance of string s/len beginning at p.  If found, returns
  2257. X * p pointing to beginning of string.  If not found, returns 0.
  2258. X */
  2259. P *pfindfn();
  2260. X
  2261. /* P *pfindfni(P *p,char *s,int len);
  2262. X * Case insensitive version of above
  2263. X */
  2264. P *pfindfni();
  2265. X
  2266. /* int brc(P *p);
  2267. X * Read character at a pointer or return -1 if pointer was at end of the buffer
  2268. X */
  2269. int brc();
  2270. X
  2271. /* char *brmem(P *p,char *blk,int size);
  2272. X * Read characters into a memory block
  2273. X */
  2274. char *brmem();
  2275. X
  2276. /* char *brs(P *p,int size);
  2277. X * Read a zero terminated string into an malloc block and return the malloc
  2278. X * block
  2279. X */
  2280. char *brs();
  2281. X
  2282. /* char *brvs(P *p,int size);
  2283. X * Read a variable length string
  2284. X */
  2285. char *brvs();
  2286. X
  2287. /* char *parsens(char *s,long skip,long amnt);
  2288. X * Parse file name.
  2289. X */
  2290. char *parsens();
  2291. X
  2292. /* int bsavefd(P *p,int fd,long size);
  2293. X * Write 'size' bytes beginning at 'p' to 'fd'.
  2294. X */
  2295. int bsavefd();
  2296. X
  2297. /* int bsave(P *p,char *name,long size);
  2298. X * Save characters into a file
  2299. X */
  2300. int bsave();
  2301. X
  2302. /* P *bdel(P *from,P *to);
  2303. X * Delete characters from a buffer
  2304. X */
  2305. X
  2306. P *bdel();
  2307. X
  2308. /* P *binsc(P *p,char c);
  2309. X * Insert a character into a buffer
  2310. X */
  2311. P *binsc();
  2312. X
  2313. /* P *binsm(P *p,char *blk,int size);
  2314. X * Insert a memory block into a buffer
  2315. X */
  2316. P *binsm();
  2317. X
  2318. /* P *binss(P *p,char *s);
  2319. X * Insert zero terminated string into a buffer
  2320. X */
  2321. P *binss();
  2322. X
  2323. /* P *binsb(P *p,P *from,P *to);
  2324. X * Insert characters from another buffer
  2325. X */
  2326. P *binsb();
  2327. X
  2328. /* int binsfd(P *p,int fd,long max);
  2329. X * Insert a file into a buffer.  No more than 'max' bytes are loaded from
  2330. X * the file.
  2331. X */
  2332. int binsfd();
  2333. X
  2334. /* int binsf(P *p,char *name);
  2335. X * Insert a file into a buffer
  2336. X */
  2337. int binsf();
  2338. X
  2339. /* int bload(B *b,char *s);
  2340. X * Load a file into a buffer
  2341. X */
  2342. int bload();
  2343. X
  2344. void refigure();
  2345. X
  2346. #endif
  2347. SHAR_EOF
  2348. chmod 0600 b.h ||
  2349. echo 'restore of b.h failed'
  2350. Wc_c="`wc -c < 'b.h'`"
  2351. test 10590 -eq "$Wc_c" ||
  2352.     echo 'b.h: original size 10590, current size' "$Wc_c"
  2353. fi
  2354. # ============= blocks.c ==============
  2355. if test -f 'blocks.c' -a X"$1" != X"-c"; then
  2356.     echo 'x - skipping blocks.c (File already exists)'
  2357. else
  2358. echo 'x - extracting blocks.c (Text)'
  2359. sed 's/^X//' << 'SHAR_EOF' > 'blocks.c' &&
  2360.