home *** CD-ROM | disk | FTP | other *** search
/ Source Code 1994 March / Source_Code_CD-ROM_Walnut_Creek_March_1994.iso / compsrcs / misc / volume33 / xvi / part12 < prev    next >
Encoding:
Text File  |  1992-11-01  |  55.8 KB  |  2,406 lines

  1. Newsgroups: comp.sources.misc
  2. From: jmd@cyclone.bt.co.uk (John Downey)
  3. Subject:  v33i021:  xvi - portable multi-window vi-like editor, Part12/18
  4. Message-ID: <1992Oct24.172418.2156@sparky.imd.sterling.com>
  5. X-Md4-Signature: 8f7374fee308f770ad8c61be57b7067c
  6. Date: Sat, 24 Oct 1992 17:24:18 GMT
  7. Approved: kent@sparky.imd.sterling.com
  8.  
  9. Submitted-by: jmd@cyclone.bt.co.uk (John Downey)
  10. Posting-number: Volume 33, Issue 21
  11. Archive-name: xvi/part12
  12. Environment: Unix, MS-DOS, OS/2, QNX
  13.  
  14. #! /bin/sh
  15. # This is a shell archive.  Remove anything before this line, then feed it
  16. # into a shell via "sh file" or similar.  To overwrite existing files,
  17. # type "sh file -c".
  18. # Contents:  xvi/doc/xvi.1 xvi/src/edit.c xvi/src/termcap.h
  19. #   xvi/src/unix.c
  20. # Wrapped by kent@sparky on Thu Oct 22 09:03:43 1992
  21. PATH=/bin:/usr/bin:/usr/ucb:/usr/local/bin:/usr/lbin ; export PATH
  22. echo If this archive is complete, you will see the following message:
  23. echo '          "shar: End of archive 12 (of 18)."'
  24. if test -f 'xvi/doc/xvi.1' -a "${1}" != "-c" ; then 
  25.   echo shar: Will not clobber existing file \"'xvi/doc/xvi.1'\"
  26. else
  27.   echo shar: Extracting \"'xvi/doc/xvi.1'\" \(14933 characters\)
  28.   sed "s/^X//" >'xvi/doc/xvi.1' <<'END_OF_FILE'
  29. X.TH XVI 1 19/6/1992 Unix
  30. X.nh
  31. X.rm hy
  32. X.SH NAME
  33. Xxvi \- multi-file text editor
  34. X.SH SYNOPSIS
  35. X.B xvi
  36. X{
  37. X.B \-s
  38. X.I parameter-assignment
  39. X}
  40. X[
  41. X.B \-t
  42. X.I tag
  43. X|
  44. X.BI + number
  45. X|
  46. X.BI +/ pattern
  47. X]
  48. X{
  49. X.I filename
  50. X\&.\|.\|.
  51. X}
  52. X.SH DESCRIPTION
  53. X\fBXvi\fP (pronounced \fIecks-vee-eye\fP)
  54. Xis a free, portable, multi-window implementation of the popular
  55. X.BR vi (1)
  56. Xeditor.
  57. XIt has some useful enhancements, although, as described below,
  58. Xnot all of
  59. X.BR vi 's
  60. Xfeatures have been implemented yet, and some things work differently from
  61. X.BR vi .
  62. X.SH OPTIONS
  63. XThe following command-line options are available:
  64. X.TP
  65. X\fB\-s\fP \fIparameter-assignment\fP
  66. XSet the value of the specified parameter at startup.
  67. XThe assignment has the same form as when given as an editor command,
  68. Xi.e:
  69. X.RS
  70. X.TP
  71. X\fIname\fB=\fIstring\fP
  72. Xfor string parameters
  73. X.TP
  74. X\fIname\fB=\fInumber\fP
  75. Xfor numeric parameters
  76. X.TP
  77. X\fIname\fP
  78. Xto turn a Boolean parameter on
  79. X.TP
  80. X\fBno\fP\fIname\fP
  81. Xto turn a Boolean parameter off
  82. X.RE
  83. X.TP
  84. X\fB\-t\fP \fItag\fP
  85. XEdit the file containing the definition specified as \fItag\fP,
  86. Xat the start of the definition (as per \fBvi\fP).
  87. X.TP
  88. X\fB+\fP\fInumber\fP
  89. XGo to the specified line number of the file being edited.
  90. X.TP
  91. X\fB+\fP/\fIpattern\fP
  92. XGo to the first occurrence of the specified \fIpattern\fP within
  93. Xthe file being edited.
  94. X.LP
  95. XThe \fB\-r\fP command line option is not supported.
  96. X.SH ENHANCEMENTS
  97. X.SS Multiple buffers and windows
  98. X.LP
  99. XA
  100. X.I buffer
  101. Xis the internal object
  102. Xwhich holds a file in memory, while a
  103. X.I window
  104. Xis an area of the
  105. Xscreen which shows part of a buffer.
  106. XEvery window references a buffer, even if no file is being edited.
  107. XThe following commands are
  108. Xavailable for operating on buffers and windows:
  109. X.IP \fB:buffer\fP
  110. Xcreate a new buffer in a new window;
  111. Xcan be followed by a filename, which will be edited in the new buffer.
  112. X.IP \fB:split\fP
  113. Xcreate a new window on to the current buffer by
  114. Xsplitting the current window in half.
  115. XThe two resulting windows are similar to
  116. X.I viewports
  117. Xon to a single editing buffer,
  118. Xin that changes made in one window are reflected in the other one.
  119. X.IP \fB:close\fP
  120. Xclose the current window;
  121. Xwill also close the buffer if this is the last window on to it.
  122. X.IP "\fB:x\fP\ /\ \fBZZ\fP"
  123. Xclose only the current window.
  124. XIf the window is the only one on to the buffer,
  125. Xthe buffer will be closed as well,
  126. Xwriting it first if it is modified.
  127. X.IP \fBg\fP
  128. Xmove to the next window.
  129. X.IP \fB^W\fP
  130. Xincrease the size of the current window
  131. X(may be given a numeric prefix, default is one line).
  132. X.IP \fB^T\fP
  133. Xdecrease the size of the current window
  134. X(may be given a numeric prefix, default is one line).
  135. X.IP \fB^O\fP
  136. Xmake the current window as large as possible.
  137. X.IP \fB^]\fP
  138. Xas for
  139. X.BR vi ,
  140. Xbut create a new buffer window if appropriate
  141. X(and if
  142. X.B autosplit
  143. Xallows).
  144. X.LP
  145. XNote that the
  146. X.B :quit
  147. Xcommand quits out of the editor, not out of a window.
  148. XThe
  149. X.B :close
  150. Xcommand is thus the equivalent of
  151. X.B :quit
  152. Xfor windows.
  153. XThere
  154. Xis no equivalent of
  155. X.B :x
  156. Xor
  157. X.B ZZ
  158. Xfor the whole editor; these have been
  159. Xhijacked for operations on windows.
  160. X.LP
  161. XThe numeric
  162. X.B autosplit
  163. Xparameter specifies the maximum number
  164. Xof buffer windows that will be created automatically whenever you
  165. Xeither edit more than one file, or use tags to edit a different file.
  166. X.LP
  167. XUndo works per buffer, as do marks; yank/put and redo (the
  168. X.B .
  169. Xcommand)
  170. Xwork over all buffers, i.e. you can delete from one buffer and put
  171. Xthe text into a different buffer.
  172. X.SS "File preservation"
  173. X.LP
  174. XRather than use
  175. X.BR vi 's
  176. XUnix-specific method
  177. Xfor preservation,
  178. X.B xvi
  179. Xdoes periodic preservation of all files
  180. Xcurrently being edited into temporary files in the same directory.
  181. XIt
  182. Xtries to do this when you aren't typing, so that you won't
  183. Xnotice the short delay when the temporary file is written out.
  184. XObviously, only changed files are preserved in this way, and
  185. Xthe temporary file is removed once the real file has been successfully
  186. Xwritten.
  187. X.SS "8-bit character support"
  188. X.LP
  189. XCharacters with the top bit set are accepted by
  190. X.BR xvi ,
  191. Xbut
  192. Xit is not yet possible to have null
  193. X(\(fm\^\e\^0\^\(fm)
  194. Xbytes in a file buffer.
  195. XHow characters are displayed can be controlled by
  196. Xthe \fBcchars\fP and \fBmchars\fP
  197. Xparameters, which, if set, cause
  198. Xcontrol and meta-characters
  199. Xrespectively 
  200. Xto be
  201. Xoutput unchanged;
  202. Xotherwise they are shown as sequences of printable characters.
  203. X.LP
  204. XTabs are normally displayed as a series of spaces of the appropriate
  205. Xlength (according to the \fBtabstops\fP parameter);
  206. Xsetting \fBlist\fP mode will cause them to be displayed as control
  207. Xcharacters, as will unsetting the \fBtabs\fP parameter.
  208. XHow the tab character is displayed is then under the control of
  209. Xthe \fBcchars\fP parameter.
  210. X.LP
  211. XYou can use the
  212. X.B ^_
  213. X(control-underscore) command to flip the
  214. Xtop bit of the character the cursor is on.
  215. XThis may be useful on systems where it is otherwise impossible
  216. Xto enter 8-bit characters.
  217. X.SS "File formats"
  218. X.LP
  219. X.B Xvi
  220. Xcan read and write text files in non-Unix formats.
  221. XThe current format is given by the value of the
  222. X.B format
  223. Xparameter, which
  224. Xmay be set to "\fBunix\fP", "\fBmsdos\fP", etc.
  225. XTo see a list of available formats, type
  226. X.IP
  227. X.B ":se fmt=?"
  228. X.SS "Extended regular expressions"
  229. X.LP
  230. X.BR vi 's
  231. X.B magic
  232. Xparameter is superseded by the
  233. X.B regextype
  234. Xparameter,
  235. Xwhich can take the following values:
  236. X.IP \fBtags\fP
  237. Xonly
  238. X.B ^
  239. Xand
  240. X.B $
  241. Xare significant (used for tags)
  242. X.IP \fBgrep\fP
  243. Xlike
  244. X.BR grep (1),
  245. Xbut with
  246. X.B \e\^<
  247. Xand
  248. X.B \e\|\^>
  249. Xadded
  250. X.IP \fBegrep\fP
  251. Xlike
  252. X.BR egrep (1),
  253. Xbut with
  254. X.B \e\^<
  255. Xand
  256. X.B \e\|\^>
  257. Xadded
  258. X.LP
  259. XThe default is
  260. X.BR grep .
  261. X.LP
  262. XNote that it is still possible to set or unset \fBmagic\fP
  263. Xas in \fBvi\fP; this will simply result in \fBregextype\fP
  264. Xbeing set as appropriate.
  265. X.LP
  266. XThe \fBsections\fP and \fBparagraphs\fP parameters define
  267. X.BR egrep -style
  268. Xpatterns to search for, rather than
  269. X.BR vi 's
  270. Xsimplistic (and
  271. X.BR troff -dependent)
  272. Xcharacter pairs.
  273. X.SS "Improved replace mode"
  274. X.LP
  275. XThe
  276. X.B R
  277. Xcommand acts more intelligently when you press return \(em
  278. Xit leaves the rest of the current line alone,
  279. Xand just starts
  280. Xreplacing text on the next line,
  281. Xstarting at the screen column
  282. Xwhere you first typed
  283. X.BR R .
  284. X.SS "Command re-execution"
  285. X.LP
  286. XAs well as the normal named (conjugate) buffers,
  287. Xand the default one (named
  288. X.BR @ ),
  289. Xthere exist several extra ones named
  290. X.BR : ,
  291. X.BR / ,
  292. X.B ?
  293. Xand
  294. X.BR ! ,
  295. Xwhich contain the last command lines typed to each of the given
  296. Xcommands.
  297. XSo for instance,
  298. X.B @:
  299. Xwill re-execute the last \fBex\fP command, or you can insert
  300. Xit into your buffer, edit it and then re-execute it (e.g. with
  301. X.BR dd\^@@ ).
  302. X.SS Jumpscroll
  303. XWhen multiple windows are used,
  304. X.B xvi
  305. Xnormally has to be able to scroll individual windows
  306. Xwithout scrolling the whole screen.
  307. XThis can be very inefficient
  308. Xon terminals
  309. Xwithout
  310. Xscrolling regions,
  311. Xso the
  312. X.B jumpscroll
  313. Xparameter
  314. Xis provided to control the editor's scrolling behaviour.
  315. XIt can be set to one of:
  316. X.TP
  317. X.B off
  318. XWhen the cursor moves outside a window's boundaries,
  319. Xand the new position is near enough,
  320. Xthe window will scroll to the new position.
  321. X.TP
  322. X.B on
  323. XWhen the cursor moves outside a window's boundaries,
  324. Xthe window will always jump to the new position.
  325. X.TP
  326. X.B auto
  327. XA window will scroll only if it can do so efficiently;
  328. Xotherwise it will jump.
  329. X.LP
  330. XThe default value is
  331. X.BR auto .
  332. X.LP
  333. XOn ISA-type systems which have memory-mapped displays,
  334. Xhardware character generators
  335. Xand reasonably fast processors,
  336. X.B jumpscroll
  337. Xshould generally be set to
  338. X.BR off ;
  339. Xhowever,
  340. Xon LCD screens or other displays with a long image persistence,
  341. Xthis may actually make the text more difficult to read,
  342. Xand many users may be more comfortable with it turned
  343. X.BR on .
  344. X.LP
  345. XExplicit scroll commands (e.g.
  346. X.B ^D
  347. Xand
  348. X.BR ^E )
  349. Xare not affected by
  350. Xthe \fBjumpscroll\fP parameter.
  351. X.SS Colour
  352. X.LP
  353. XThere are four new parameters to control screen colours:
  354. X.ta 1.25i
  355. X.LP
  356. X\fBcolour\fP    colour used for text
  357. X.LP
  358. X\fBstatuscolour\fP    colour used for status lines
  359. X.LP
  360. X\fBroscolour\fP        as
  361. X.BR statuscolour ,
  362. Xbut for readonly files
  363. X.LP
  364. X\fBsystemcolour\fP    colour used for system mode
  365. X(i.e. subshells and after termination)
  366. X.LP
  367. X.DT
  368. XThese parameters are numeric, and the value means different
  369. Xthings on different operating systems.
  370. XOn Unix, it is an index into the
  371. X.BR termcap (5)
  372. Xentries "\fBc0\fP" to "\fBc9\fP",
  373. Xwhich are assumed to be colour-setting
  374. Xescape sequences if they are present.
  375. XIf they are not present,
  376. X"\fBso\fP"
  377. X(begin standout mode)
  378. Xand
  379. X"\fBse\fP"
  380. X(end standout mode)
  381. Xare used instead.
  382. XValues of 0 and 1 give normal text,
  383. Xwhereas 2 and above give standout mode.
  384. X.LP
  385. XThe default colour for
  386. Xthe
  387. X.B roscolour
  388. Xparameter will generally involve red
  389. Xif colours are available;
  390. Xthis is intended
  391. Xto provide a warning to the user that writing the file
  392. Xmay not be possible.
  393. X.SS "On-line help"
  394. X.LP
  395. XA primitive help facility is available; the
  396. X.B :help
  397. Xcommand
  398. Xsimply creates a new
  399. Xbuffer window on to a standard help file.
  400. XThe name of the file which is edited
  401. Xis given by the
  402. X.B helpfile
  403. Xstring parameter;
  404. Xthe default on Unix versions is
  405. X\fB"/usr/lib/xvi.help"\fP.
  406. XNote that the help file buffer will be marked "not editable"
  407. Xwhen it is created, which prevents accidental overwriting
  408. Xof the help file even when the file permissions would allow it.
  409. X.SS Miscellaneous
  410. X.LP
  411. XThe command
  412. X.B :wn
  413. X(write file and edit next) is provided, as in \fBPC-vi\fP.
  414. X.LP
  415. XThe new
  416. X.B edit
  417. Xparameter controls whether a buffer can be modified.
  418. XThis may be used to implement a nicer version of
  419. X.BR view (1)
  420. Xthan the
  421. Xstandard
  422. X.B vi
  423. Xversion, since it won't fool you into thinking that editing
  424. Xthe buffer is in any way safe.
  425. XBe warned:
  426. Xonce having set
  427. X.BR noedit ,
  428. Xit is not possible to do a
  429. X.B ":set edit"
  430. Xany more.
  431. XIt's a one-way street.
  432. X.LP
  433. XIn insert and replace modes,
  434. X.B ^A
  435. Xhas the same meaning as
  436. X.B ^@
  437. Xin vi, except that it
  438. Xworks at any time,
  439. Xnot just for the first character.
  440. XAlso, typing
  441. X.BI ^B x
  442. Xwhere
  443. X.I x
  444. Xis the name of a conjugate buffer, inserts the contents of that
  445. Xbuffer into the input stream at that point.
  446. XThe buffer named 
  447. X.B <
  448. Xalways contains the last thing inserted,
  449. Xso that
  450. X.B ^B<
  451. Xis the same as
  452. X.BR ^A .
  453. X.SH LIMITATIONS
  454. X.SS "Ex mode"
  455. X.LP
  456. XThe main area in which \fBxvi\fP is lacking is \fBvi\fP's
  457. X.B ex
  458. Xmode,
  459. Xwhich is not implemented at all (and neither are \fBedit\fP, \fBe\fP,
  460. Xor \fBopen\fP modes).
  461. XHowever, many of the \fBex\fP commands are available in
  462. X.B vi
  463. Xmode
  464. Xas colon commands;
  465. Xthe colon commands that have not been implemented
  466. Xare mostly those which offer
  467. Xthe same functionality as other commands in \fBvi\fP mode.
  468. X.LP
  469. XIn particular,
  470. X.BR abbreviate ,
  471. X.BR append ,
  472. X.BR change ,
  473. X.BR ex ,
  474. X.BR insert ,
  475. X.BR join ,
  476. X.BR open ,
  477. X.BR recover ,
  478. X.BR unabbreviate ,
  479. X.BR undo ,
  480. X.BR write>> ,
  481. X.B z
  482. Xand
  483. X.B |
  484. Xhave not been implemented as colon commands yet.
  485. X.SS "Vi mode"
  486. X.LP
  487. XIn
  488. X.B vi
  489. Xmode, the
  490. X.B U
  491. Xand
  492. X.B =
  493. Xcommands are not implemented,
  494. Xalthough there is no real reason why they shouldn't be,
  495. Xwhilst
  496. X.B Q
  497. Xis inappropriate in the context of
  498. X.BR xvi ,
  499. Xsince there is no
  500. X.B ex
  501. Xmode.
  502. X.SS Parameters
  503. X.LP
  504. XMany of
  505. X.BR vi 's
  506. Xparameters
  507. Xhave not been implemented;
  508. Xthe command
  509. X.B ":se all"
  510. Xgives a complete list, with current values,
  511. Xof those that have been.
  512. X.SS Miscellaneous
  513. X.LP
  514. XRepeat counts before insertions don't work.
  515. X.LP
  516. XAppending to named buffers is not yet implemented.
  517. X.LP
  518. XTyping \fB^Q\fP in input mode does not mean the same as \fB^V\fP;
  519. Xit just inserts a `\fB^Q\fR', assuming it gets as far as the editor at all.
  520. X.LP
  521. XTyping \fB^W\fP in insert mode does not back up one word as in \fBvi\fP.
  522. X.LP
  523. XIt is not possible to interrupt the editor while it is
  524. Xperforming certain operations.
  525. XIf you start off a big global command, you have to wait for it to finish.
  526. X.LP
  527. XFlags and counts after \fBex\fP mode commands are not supported.
  528. X.LP
  529. XIt is not possible to read the output of a system command using
  530. X.IP
  531. X\fB:r\ !\fP\fIcommand\fP
  532. X.LP
  533. Xor to write into a command using
  534. X.IP
  535. X\fB:w\ !\fP\fIcommand\fP.
  536. X.LP
  537. XRegular expressions, although implemented (see above),
  538. Xdo not support the \fB~\fP metacharacter;
  539. Xalso, the \fB\e\^u\fP and \fB\e\^l\fP escape sequences are not supported in
  540. Xsubstitute replacement patterns.
  541. XNewlines included on the right hand side of a substitution
  542. Xdo not currently cause the line to be split;
  543. Xthe newline character is literally inserted into the line.
  544. X.LP
  545. XThe \fB:global\fP command only supports the commands [\fBlps&~d\fP].
  546. X.SH "OTHER DIFFERENCES FROM VI"
  547. XThe
  548. X.B XVINIT
  549. Xenvironment variable is read instead of
  550. X.BR EXINIT .
  551. XWhilst no files are sourced
  552. Xautomatically,
  553. Xusers who wish to have a startup file can arrange it very easily.
  554. X.BR sh (1)
  555. Xor
  556. X.BR ksh (1)
  557. Xusers should add this line to their
  558. X.BR "$HOME/.profile" :
  559. X.IP
  560. X.BI "XVINIT=\(fmsource " xvi-startup-file "\(fm; export XVINIT"
  561. X.LP
  562. X.BR csh (1)
  563. Xusers should add this to their
  564. X.BR "$HOME/.login" :
  565. X.IP
  566. X.BI "setenv XVINIT \(fmsource " xvi-startup-file \(fm
  567. X.LP
  568. XThe \fBtags\fP parameter can be used to specify multiple tags files;
  569. Xthese can be separated by either
  570. X``\^\e\ \|''
  571. X(backslash space) or
  572. X``,''
  573. X(comma).
  574. X.LP
  575. XAlternate files are handled slightly differently,
  576. Xowing to the presence of buffer and window handling.
  577. XEssentially, when you close a buffer, its filename
  578. Xis remembered as the alternate file;
  579. Xwhen you invoke the \fB^^\fP or \fB:e\ #\fP commands,
  580. Xthis file is re-edited.
  581. XNote that \fB^^\fP edits the alternate file in a new buffer window,
  582. Xif \fBautosplit\fP allows.
  583. X.LP
  584. XHitting the escape key while in the command line does not terminate input;
  585. Xinstead, it cancels input, returning the prompt to the beginning
  586. Xof the line.
  587. XThis applies to input for
  588. X.BR : ,
  589. X.BR / ,
  590. X.B ?
  591. Xand
  592. X.BR ! .
  593. X.SH "FILES"
  594. X.DS
  595. X.ta 1.5i
  596. X\fB/usr/lib/xvi.help\fP    Default help file.
  597. X.DE
  598. X.SH "SEE ALSO"
  599. X.BR ex (1),
  600. X.BR vi (1),
  601. X.BR termcap (5).
  602. X.br
  603. X.IR "Summary of Differences between Vi and Xvi" .
  604. X.SH BUGS
  605. X.IP \(bu
  606. XWhen the cursor is on the last word of a buffer,
  607. Xthe command
  608. X.B dw 
  609. Xleaves the last character of the word undeleted.
  610. X.IP \(bu
  611. XSome screen updates do not get shown properly when buffers are split,
  612. Xand certain commands (e.g.
  613. X.BR x )
  614. Xare executed.
  615. X.IP \(bu
  616. XIf you do something like
  617. X\fBcf.WORD\fR\^<\^\fIesc\fR\^>
  618. Xand then redo it, and the
  619. X.B f.
  620. Xfails, then the
  621. X\fBWORD\fR\^<\^\fIesc\fR\^>
  622. Xgets taken as normal input.
  623. XThe rest of the input should really be cancelled when part of a redo fails.
  624. X.IP \(bu
  625. XA command of the form
  626. X.B :/pat/;+1m.
  627. Xwill not work because the
  628. Xeditor incorrectly detects a conflict between source and destination.
  629. X.IP \(bu
  630. XThe editor
  631. Xin its present form
  632. Xis very inefficient in terms of CPU cycles.
  633. X.IP \(bu
  634. XMost
  635. X.BR termcap (5)
  636. Xterminal descriptions are only tested with
  637. X.BR vi (1)
  638. X(and possibly
  639. X.BR rogue (6)).
  640. XSince
  641. X.B xvi
  642. Xis, in some ways, more demanding than
  643. X.B vi
  644. Xin its use of
  645. X.B termcap
  646. Xcapabilities, it sometimes exposes bugs or inadequacies in
  647. X.B termcap
  648. Xentries.
  649. XThis applies especially to scrolling regions.
  650. X.SH AVAILABILITY
  651. X.LP
  652. X.B Xvi
  653. Xhas been ported to \%MS-DOS, OS/2, QNX and many different versions of Unix.
  654. XSource code is available from the authors.
  655. X.SH AUTHORS
  656. X.LP
  657. XChris and John Downey.
  658. X.LP
  659. XDerived from STEVIE, written by Tim Thompson and Tony Andrews.
  660. END_OF_FILE
  661.   if test 14933 -ne `wc -c <'xvi/doc/xvi.1'`; then
  662.     echo shar: \"'xvi/doc/xvi.1'\" unpacked with wrong size!
  663.   fi
  664.   # end of 'xvi/doc/xvi.1'
  665. fi
  666. if test -f 'xvi/src/edit.c' -a "${1}" != "-c" ; then 
  667.   echo shar: Will not clobber existing file \"'xvi/src/edit.c'\"
  668. else
  669.   echo shar: Extracting \"'xvi/src/edit.c'\" \(13730 characters\)
  670.   sed "s/^X//" >'xvi/src/edit.c' <<'END_OF_FILE'
  671. X/* Copyright (c) 1990,1991,1992 Chris and John Downey */
  672. X#ifndef lint
  673. Xstatic char *sccsid = "@(#)edit.c    2.4 (Chris & John Downey) 8/26/92";
  674. X#endif
  675. X
  676. X/***
  677. X
  678. X* program name:
  679. X    xvi
  680. X* function:
  681. X    PD version of UNIX "vi" editor, with extensions.
  682. X* module name:
  683. X    edit.c
  684. X* module function:
  685. X    Insert and replace mode handling.
  686. X* history:
  687. X    STEVIE - ST Editor for VI Enthusiasts, Version 3.10
  688. X    Originally by Tim Thompson (twitch!tjt)
  689. X    Extensive modifications by Tony Andrews (onecom!wldrdg!tony)
  690. X    Heavily modified by Chris & John Downey
  691. X
  692. X***/
  693. X
  694. X#include "xvi.h"
  695. X
  696. Xstatic    void    end_replace P((int));
  697. X
  698. X/*
  699. X * Position of start of insert. This is used
  700. X * to prevent backing up past the starting point.
  701. X */
  702. Xstatic    Posn    Insertloc;
  703. X
  704. X/*
  705. X * This flexbuf is used to hold the current insertion text.
  706. X */
  707. Xstatic    Flexbuf    Insbuff;
  708. X
  709. X/*
  710. X * Replace-mode stuff.
  711. X */
  712. Xstatic    enum    {
  713. X        replace_one,    /* replace command was an 'r' */
  714. X        got_one,    /* normal ending state for replace_one */
  715. X        overwrite    /* replace command was an 'R' */
  716. X}        repstate;
  717. X
  718. Xstatic    char    *saved_line;    /*
  719. X                 * record of old line before replace
  720. X                 * started; note that, if
  721. X                 * (repstate != overwrite), this
  722. X                 * should never be referenced.
  723. X                 */
  724. Xstatic    int    nchars;        /* no of chars in saved_line */
  725. Xstatic    int    start_index;    /* index into line where we entered replace */
  726. Xstatic    int    start_column;    /* virtual col corresponding to start_index */
  727. X
  728. X/*
  729. X * Process the given character, in insert mode.
  730. X */
  731. Xbool_t
  732. Xi_proc(c)
  733. Xint    c;
  734. X{
  735. X    register Posn    *curpos;
  736. X    static bool_t    literal_next = FALSE;
  737. X    static bool_t    wait_buffer = FALSE;
  738. X
  739. X    curpos = curwin->w_cursor;
  740. X
  741. X    if (wait_buffer || (!literal_next && c == CTRL('A'))) {
  742. X    /*
  743. X     * Add contents of named buffer, or the last
  744. X     * insert buffer if CTRL('A') was typed.
  745. X     */
  746. X    if (!wait_buffer) {
  747. X        c = '<';
  748. X    }
  749. X    yp_stuff_input(curwin, c, TRUE);
  750. X    wait_buffer = FALSE;
  751. X    return(FALSE);
  752. X
  753. X    } else if (!literal_next) {
  754. X    /*
  755. X     * This switch is for special characters; we skip over
  756. X     * it for normal characters, or for literal-next mode.
  757. X     */
  758. X    switch (c) {
  759. X    case ESC:    /* an escape ends input mode */
  760. X    {
  761. X        char    *cltext;
  762. X
  763. X        cltext = curpos->p_line->l_text;
  764. X
  765. X        curwin->w_set_want_col = TRUE;
  766. X
  767. X        /*
  768. X         * If there is only auto-indentation
  769. X         * on the current line, delete it.
  770. X         */
  771. X        if (curpos->p_index == indentchars &&
  772. X        cltext[indentchars] == '\0') {
  773. X        replchars(curwin, curpos->p_line, 0, indentchars, "");
  774. X        begin_line(curwin, FALSE);
  775. X        }
  776. X        indentchars = 0;
  777. X
  778. X        /*
  779. X         * The cursor should end up on the last inserted
  780. X         * character. This is an attempt to match the real
  781. X         * 'vi', but it may not be quite right yet.
  782. X         */
  783. X        while (one_left(curwin, FALSE) &&
  784. X                gchar(curwin->w_cursor) == '\0') {
  785. X        ;
  786. X        }
  787. X
  788. X        State = NORMAL;
  789. X
  790. X        end_command(curwin);
  791. X
  792. X        (void) yank_str('<', flexgetstr(&Insbuff), FALSE);
  793. X        flexclear(&Insbuff);
  794. X
  795. X        if (!(echo & e_CHARUPDATE)) {
  796. X        echo |= e_CHARUPDATE;
  797. X        move_window_to_cursor(curwin);
  798. X        cursupdate(curwin);
  799. X        }
  800. X        update_buffer(curbuf);
  801. X        return(TRUE);
  802. X    }
  803. X
  804. X    case CTRL('T'):
  805. X    case CTRL('D'):
  806. X        /*
  807. X         * If we're at the beginning of the line, or just
  808. X         * after autoindent characters, move one shiftwidth
  809. X         * left (CTRL('D')) or right (CTRL('T')).
  810. X         */
  811. X        if (curpos->p_index <= indentchars) {
  812. X        Line    *lp;
  813. X        int    ind;
  814. X
  815. X        lp = curpos->p_line;
  816. X        ind = get_indent(curpos->p_line);
  817. X        ind += (c == CTRL('D') ? (ind < Pn(P_shiftwidth) ?
  818. X                         -ind :
  819. X                         -Pn(P_shiftwidth)) :
  820. X                    Pn(P_shiftwidth));
  821. X        indentchars = set_indent(lp, ind);
  822. X        move_cursor(curwin, curpos->p_line, indentchars);
  823. X        cursupdate(curwin);
  824. X        updateline(curwin);
  825. X        (void) flexaddch(&Insbuff, c);
  826. X        } else {
  827. X        beep(curwin);
  828. X        }
  829. X        return(TRUE);
  830. X
  831. X    case '\b':
  832. X    case DEL:
  833. X        /*
  834. X         * Can't backup past starting point.
  835. X         */
  836. X        if (curpos->p_line == Insertloc.p_line &&
  837. X                curpos->p_index <= Insertloc.p_index) {
  838. X        beep(curwin);
  839. X        return(TRUE);
  840. X        }
  841. X
  842. X        /*
  843. X         * Can't backup to a previous line.
  844. X         */
  845. X        if (curpos->p_line != Insertloc.p_line && curpos->p_index <= 0) {
  846. X        beep(curwin);
  847. X        return(TRUE);
  848. X        }
  849. X        (void) one_left(curwin, FALSE);
  850. X        if (curpos->p_index < indentchars)
  851. X        indentchars--;
  852. X        replchars(curwin, curpos->p_line, curpos->p_index, 1, "");
  853. X        (void) flexaddch(&Insbuff, '\b');
  854. X        cursupdate(curwin);
  855. X        if (curwin->w_col == 0) {
  856. X        /*
  857. X         * Make sure backspacing over a physical line
  858. X         * break updates the screen correctly.
  859. X         */
  860. X        update_buffer(curbuf);
  861. X        } else {
  862. X        updateline(curwin);
  863. X        }
  864. X        return(TRUE);
  865. X
  866. X    case '\r':
  867. X    case '\n':
  868. X        {
  869. X        int    i;
  870. X        int    previndex;
  871. X        Line    *prevline;
  872. X
  873. X        (void) flexaddch(&Insbuff, '\n');
  874. X
  875. X        i = indentchars;
  876. X        prevline = curpos->p_line;
  877. X        previndex = curpos->p_index;
  878. X
  879. X        if (openfwd(TRUE) == FALSE) {
  880. X            stuff("%c", ESC);
  881. X            show_error(curwin,
  882. X                "No buffer space - returning to command mode");
  883. X            return(TRUE);
  884. X        }
  885. X
  886. X        /*
  887. X         * If the previous line only had
  888. X         * auto-indent on it, delete it.
  889. X         */
  890. X        if (i == previndex) {
  891. X            replchars(curwin, prevline, 0, i, "");
  892. X        }
  893. X
  894. X        move_window_to_cursor(curwin);
  895. X        cursupdate(curwin);
  896. X        update_buffer(curbuf);
  897. X        }
  898. X        return(TRUE);
  899. X
  900. X    case CTRL('B'):
  901. X        wait_buffer = TRUE;
  902. X        return(FALSE);
  903. X        break;
  904. X
  905. X    case CTRL('V'):
  906. X        (void) flexaddch(&Insbuff, CTRL('V'));
  907. X        literal_next = TRUE;
  908. X        return(FALSE);
  909. X    }
  910. X    }
  911. X
  912. X    /*
  913. X     * If we get here, we want to insert the character into the buffer.
  914. X     */
  915. X
  916. X    /*
  917. X     * We may already have been in literal-next mode.
  918. X     * Careful not to reset this until after we need it.
  919. X     */
  920. X    literal_next = FALSE;
  921. X
  922. X    /*
  923. X     * Deal with wrapmargin.
  924. X     *
  925. X     * OK, so it isn't really right yet.
  926. X     */
  927. X    if ((c == ' ' || c == '\t') && Pn(P_wrapmargin) != 0 &&
  928. X    curwin->w_cursor->p_index >= curwin->w_ncols - Pn(P_wrapmargin)) {
  929. X    (void) i_proc('\n');
  930. X    /*
  931. X     * We shouldn't really be putting the newline
  932. X     * in the redo buffer, so we change it to the
  933. X     * character we actually got.
  934. X     */
  935. X    flexrmchar(&Insbuff);
  936. X    (void) flexaddch(&Insbuff, c);
  937. X    return(TRUE);
  938. X    }
  939. X
  940. X    /*
  941. X     * Do the actual insertion of the new character.
  942. X     */
  943. X    replchars(curwin, curpos->p_line, curpos->p_index, 0, mkstr(c));
  944. X
  945. X    /*
  946. X     * Update the screen.
  947. X     */
  948. X    s_inschar(curwin, c);
  949. X    updateline(curwin);
  950. X
  951. X    /*
  952. X     * Put the character into the insert buffer.
  953. X     */
  954. X    (void) flexaddch(&Insbuff, c);
  955. X
  956. X    /*
  957. X     * If showmatch mode is set, check for right parens
  958. X     * and braces. If there isn't a match, then beep.
  959. X     * If there is a match AND it's on the screen,
  960. X     * flash to it briefly.
  961. X     *
  962. X     * These characters included to make this
  963. X     * source file work okay with showmatch: [ { (
  964. X     */
  965. X    if (Pb(P_showmatch) && (c == ')' || c == '}' || c == ']')) {
  966. X    Posn    *lpos, csave;
  967. X
  968. X    lpos = showmatch();
  969. X    if (lpos == NULL) {
  970. X        beep(curwin);
  971. X    } else if (!earlier(lpos->p_line, curwin->w_topline) &&
  972. X               earlier(lpos->p_line, curwin->w_botline)) {
  973. X        /*
  974. X         * Show the match if it's on screen.
  975. X         */
  976. X        update_buffer(curbuf);
  977. X
  978. X        csave = *curpos;
  979. X        move_cursor(curwin, lpos->p_line, lpos->p_index);
  980. X        cursupdate(curwin);
  981. X        wind_goto(curwin);
  982. X
  983. X        delay();
  984. X
  985. X        move_cursor(curwin, csave.p_line, csave.p_index);
  986. X        cursupdate(curwin);
  987. X    }
  988. X    }
  989. X
  990. X    /*
  991. X     * Finally, move the cursor right one space.
  992. X     */
  993. X    (void) one_right(curwin, TRUE);
  994. X
  995. X    return(TRUE);
  996. X}
  997. X
  998. X/*
  999. X * This function is the interface provided for functions in
  1000. X * normal mode to go into insert mode. We only come out of
  1001. X * insert mode when the user presses escape.
  1002. X *
  1003. X * The parameter is a flag to say whether we should start
  1004. X * at the start of the line.
  1005. X *
  1006. X * Note that we do not have to call start_command() as the
  1007. X * caller does that for us - this is so the caller can include
  1008. X * any other stuff (e.g. an initial delete) into the command.
  1009. X */
  1010. Xvoid
  1011. Xstartinsert(startln)
  1012. Xint    startln;    /* if set, insert point really at start of line */
  1013. X{
  1014. X    Insertloc = *curwin->w_cursor;
  1015. X    if (startln)
  1016. X    Insertloc.p_index = 0;
  1017. X    flexclear(&Insbuff);
  1018. X    State = INSERT;
  1019. X}
  1020. X
  1021. X/*
  1022. X * Process the given character, in replace mode.
  1023. X */
  1024. Xbool_t
  1025. Xr_proc(c)
  1026. Xint    c;
  1027. X{
  1028. X    Posn        *curpos;
  1029. X    static bool_t    literal_next = FALSE;
  1030. X    static bool_t    wait_buffer = FALSE;
  1031. X
  1032. X    curpos = curwin->w_cursor;
  1033. X
  1034. X    if (wait_buffer || (!literal_next && c == CTRL('A'))) {
  1035. X    /*
  1036. X     * Add contents of named buffer, or the last
  1037. X     * insert buffer if CTRL('A') was typed.
  1038. X     */
  1039. X    if (!wait_buffer) {
  1040. X        c = '<';
  1041. X    }
  1042. X    yp_stuff_input(curwin, c, TRUE);
  1043. X    wait_buffer = FALSE;
  1044. X    return(FALSE);
  1045. X
  1046. X    } else if (!literal_next) {
  1047. X    switch (c) {
  1048. X    case ESC:            /* an escape ends input mode */
  1049. X        end_replace(c);
  1050. X        return(TRUE);
  1051. X
  1052. X    case '\b':            /* back space */
  1053. X    case DEL:
  1054. X        if (repstate == overwrite &&
  1055. X        curwin->w_virtcol > start_column) {
  1056. X        (void) one_left(curwin, FALSE);
  1057. X        replchars(curwin, curpos->p_line,
  1058. X                curpos->p_index, 1,
  1059. X                (curpos->p_index < nchars) ?
  1060. X                mkstr(saved_line[curpos->p_index]) : "");
  1061. X        updateline(curwin);
  1062. X        (void) flexaddch(&Insbuff, '\b');
  1063. X        } else {
  1064. X        beep(curwin);
  1065. X        if (repstate == replace_one) {
  1066. X            end_replace(c);
  1067. X        }
  1068. X        }
  1069. X        return(TRUE);
  1070. X
  1071. X    case K_LARROW:            /* left arrow */
  1072. X        if (repstate == overwrite && curwin->w_virtcol > start_column &&
  1073. X                        one_left(curwin, FALSE)) {
  1074. X        (void) flexaddch(&Insbuff, c);
  1075. X        return(TRUE);
  1076. X        } else {
  1077. X        beep(curwin);
  1078. X        if (repstate == replace_one) {
  1079. X            end_replace(c);
  1080. X        }
  1081. X        return(FALSE);
  1082. X        }
  1083. X
  1084. X    case K_RARROW:            /* right arrow */
  1085. X        if (repstate == overwrite && one_right(curwin, FALSE)) {
  1086. X        (void) flexaddch(&Insbuff, c);
  1087. X        return(TRUE);
  1088. X        } else {
  1089. X        beep(curwin);
  1090. X        if (repstate == replace_one) {
  1091. X            end_replace(c);
  1092. X        }
  1093. X        return(FALSE);
  1094. X        }
  1095. X
  1096. X    case '\r':            /* new line */
  1097. X    case '\n':    
  1098. X        if (curpos->p_line->l_next == curbuf->b_lastline &&
  1099. X                        repstate == overwrite) {
  1100. X        /*
  1101. X         * Don't allow splitting of last line of
  1102. X         * buffer in overwrite mode. Why not?
  1103. X         */
  1104. X        beep(curwin);
  1105. X        return(TRUE);
  1106. X        }
  1107. X
  1108. X        if (repstate == replace_one) {
  1109. X        echo &= ~e_CHARUPDATE;
  1110. X        if (openfwd(TRUE) == FALSE) {
  1111. X            show_error(curwin, "No buffer space!");
  1112. X            return(TRUE);
  1113. X        }
  1114. X
  1115. X        (void) flexaddch(&Insbuff, c);
  1116. X
  1117. X        /*
  1118. X         * Having split the line, we must
  1119. X         * delete the character which was
  1120. X         * supposed to be replaced with
  1121. X         * the newline.
  1122. X         */
  1123. X        replchars(curwin, curpos->p_line, curpos->p_index, 1, "");
  1124. X        repstate = got_one;
  1125. X        end_replace('\n');
  1126. X
  1127. X        } else {
  1128. X        (void) flexaddch(&Insbuff, '\n');
  1129. X
  1130. X        (void) onedown(curwin, 1L);
  1131. X
  1132. X        /*
  1133. X         * This is wrong, but it's difficult
  1134. X         * to get it right.
  1135. X         */
  1136. X        coladvance(curwin, start_column);
  1137. X
  1138. X        free(saved_line);
  1139. X        saved_line = strsave(curpos->p_line->l_text);
  1140. X        if (saved_line == NULL) {
  1141. X            State = NORMAL;
  1142. X            return(TRUE);
  1143. X        }
  1144. X        nchars = strlen(saved_line);
  1145. X        }
  1146. X
  1147. X        return(TRUE);
  1148. X
  1149. X    case CTRL('B'):
  1150. X        wait_buffer = TRUE;
  1151. X        return(FALSE);
  1152. X        break;
  1153. X
  1154. X    case CTRL('V'):    
  1155. X        (void) flexaddch(&Insbuff, CTRL('V'));
  1156. X        literal_next = TRUE;
  1157. X        return(TRUE);
  1158. X    }
  1159. X    }
  1160. X
  1161. X    /*
  1162. X     * If we get here, we want to insert the character into the buffer.
  1163. X     */
  1164. X
  1165. X    /*
  1166. X     * We may already have been in literal-next mode.
  1167. X     * Careful not to reset this until after we need it.
  1168. X     */
  1169. X    literal_next = FALSE;
  1170. X
  1171. X    /*
  1172. X     * Put the character into the insert buffer.
  1173. X     */
  1174. X    (void) flexaddch(&Insbuff, c);
  1175. X
  1176. X    if (repstate == overwrite || repstate == replace_one) {
  1177. X    replchars(curwin, curpos->p_line, curpos->p_index, 1, mkstr(c));
  1178. X    updateline(curwin);
  1179. X    (void) one_right(curwin, TRUE);
  1180. X    }
  1181. X
  1182. X    /*
  1183. X     * If command was an 'r', leave replace mode after one character.
  1184. X     */
  1185. X    if (repstate == replace_one) {
  1186. X    repstate = got_one;
  1187. X    end_replace(c);
  1188. X    }
  1189. X
  1190. X    return(TRUE);
  1191. X}
  1192. X
  1193. X/*
  1194. X * This function is the interface provided for functions in
  1195. X * normal mode to go into replace mode. We only come out of
  1196. X * replace mode when the user presses escape, or when they
  1197. X * used the 'r' command and typed a single character.
  1198. X *
  1199. X * The parameter is the command character which took us into replace mode.
  1200. X */
  1201. Xvoid
  1202. Xstartreplace(c)
  1203. Xint    c;
  1204. X{
  1205. X    if (!start_command(curwin)) {
  1206. X    return;
  1207. X    }
  1208. X    start_index = curwin->w_cursor->p_index;
  1209. X    start_column = curwin->w_virtcol;
  1210. X
  1211. X    if (c == 'r') {
  1212. X    repstate = replace_one;
  1213. X    saved_line = NULL;
  1214. X    } else {
  1215. X    repstate = overwrite;
  1216. X    saved_line = strsave(curwin->w_cursor->p_line->l_text);
  1217. X    if (saved_line == NULL) {
  1218. X        beep(curwin);
  1219. X        end_command(curwin);
  1220. X        return;
  1221. X    }
  1222. X    nchars = strlen(saved_line);
  1223. X
  1224. X    /*
  1225. X     * Initialize Insbuff. Note that we don't do this if the
  1226. X     * command was 'r', because they might type ESC to abort
  1227. X     * the command, in which case we shouldn't change Insbuff.
  1228. X     */
  1229. X    flexclear(&Insbuff);
  1230. X
  1231. X    }
  1232. X    State = REPLACE;
  1233. X}
  1234. X
  1235. Xstatic void
  1236. Xend_replace(c)
  1237. X    int    c;
  1238. X{
  1239. X    Posn    *curpos;
  1240. X    char    *cltext;
  1241. X
  1242. X    curpos = curwin->w_cursor;
  1243. X
  1244. X    State = NORMAL;
  1245. X    end_command(curwin);
  1246. X
  1247. X    /*
  1248. X     * If (repstate == replace_one), they must have typed 'r', then
  1249. X     * thought better of it & typed ESC; so we shouldn't complain or
  1250. X     * change the buffer, the cursor position, or Insbuff.
  1251. X     */
  1252. X    if (repstate != replace_one) {
  1253. X
  1254. X    (void) yank_str('<', flexgetstr(&Insbuff), FALSE);
  1255. X    flexclear(&Insbuff);
  1256. X
  1257. X    /*
  1258. X     * Free the saved line if necessary.
  1259. X     */
  1260. X    if (repstate == overwrite) {
  1261. X        free(saved_line);
  1262. X    }
  1263. X
  1264. X    /*
  1265. X     * The cursor should end up on the
  1266. X     * last replaced character.
  1267. X     */
  1268. X    cltext = curpos->p_line->l_text;
  1269. X    while (one_left(curwin, FALSE) && gchar(curwin->w_cursor) == '\0') {
  1270. X        ;
  1271. X    }
  1272. X
  1273. X    if (!(echo & e_CHARUPDATE)) {
  1274. X        echo |= e_CHARUPDATE;
  1275. X        move_window_to_cursor(curwin);
  1276. X        cursupdate(curwin);
  1277. X    }
  1278. X    update_buffer(curbuf);
  1279. X    }
  1280. X}
  1281. X
  1282. Xchar *
  1283. Xmkstr(c)
  1284. Xint    c;
  1285. X{
  1286. X    static    char    s[2];
  1287. X
  1288. X    s[0] = c;
  1289. X    s[1] = '\0';
  1290. X
  1291. X    return(s);
  1292. X}
  1293. END_OF_FILE
  1294.   if test 13730 -ne `wc -c <'xvi/src/edit.c'`; then
  1295.     echo shar: \"'xvi/src/edit.c'\" unpacked with wrong size!
  1296.   fi
  1297.   # end of 'xvi/src/edit.c'
  1298. fi
  1299. if test -f 'xvi/src/termcap.h' -a "${1}" != "-c" ; then 
  1300.   echo shar: Will not clobber existing file \"'xvi/src/termcap.h'\"
  1301. else
  1302.   echo shar: Extracting \"'xvi/src/termcap.h'\" \(2356 characters\)
  1303.   sed "s/^X//" >'xvi/src/termcap.h' <<'END_OF_FILE'
  1304. X/* Copyright (c) 1990,1991,1992 Chris and John Downey */
  1305. X/***
  1306. X
  1307. X* @(#)termcap.h    2.1 (Chris & John Downey) 7/29/92
  1308. X
  1309. X* program name:
  1310. X    xvi
  1311. X* function:
  1312. X    PD version of UNIX "vi" editor, with extensions.
  1313. X* module name:
  1314. X    termcap.h
  1315. X* module function:
  1316. X    Definitions for termcap terminal interface module.
  1317. X* history:
  1318. X    STEVIE - ST Editor for VI Enthusiasts, Version 3.10
  1319. X    Originally by Tim Thompson (twitch!tjt)
  1320. X    Extensive modifications by Tony Andrews (onecom!wldrdg!tony)
  1321. X    Heavily modified by Chris & John Downey
  1322. X
  1323. X***/
  1324. X
  1325. X/*
  1326. X * Size of screen.
  1327. X */
  1328. Xextern    unsigned int    LI;
  1329. Xextern    unsigned int    CO;
  1330. X
  1331. X#define Rows        LI
  1332. X#define Columns     CO
  1333. X
  1334. X/*
  1335. X * Standout glitch - see termcap.c.
  1336. X */
  1337. Xextern    int        SG;
  1338. X
  1339. X#define SLINE_GLITCH    ((unsigned int) SG)
  1340. X
  1341. X/*
  1342. X * For the moment, inchar just maps to the routine provided
  1343. X * by the system interface module.
  1344. X */
  1345. X#define inchar(t)    inch(t)
  1346. X
  1347. X/*
  1348. X * There are no termcap capabilities for these:
  1349. X */
  1350. X#define invis_cursor()        /* invisible cursor (very optional) */
  1351. X#define vis_cursor()        /* visible cursor (very optional) */
  1352. X
  1353. X/*
  1354. X * In the current implementation, this doesn't have to do anything.
  1355. X */
  1356. X#define tty_close()
  1357. X
  1358. Xextern    int        cost_goto;    /* cost of using tty_goto() */
  1359. X
  1360. Xextern    bool_t        can_scroll_area;/* true if has scroll regions */
  1361. Xextern    bool_t        can_del_line;    /* true if we can delete lines */
  1362. Xextern    bool_t        can_ins_line;    /* true if we can insert lines */
  1363. Xextern    bool_t        can_inschar;    /* true if we can insert characters */
  1364. X
  1365. X/*
  1366. X * Colour handling is possible if we have termcap,
  1367. X * using the entries c0 .. c9 (not documented).
  1368. X */
  1369. X#define DEF_SYSCOLOUR    0
  1370. X#define DEF_COLOUR    1
  1371. X#define DEF_STCOLOUR    2
  1372. X#define DEF_ROSCOLOUR    3
  1373. X
  1374. Xextern    void        outchar P((int c));
  1375. Xextern    void        outstr P((char *s));
  1376. Xextern    void        alert P((void));
  1377. Xextern    void        flush_output P((void));
  1378. Xextern    void        set_colour P((int c));
  1379. Xextern    void        tty_goto P((int row, int col));
  1380. Xextern    void        tty_linefeed P((void));
  1381. Xextern    void        insert_line P((void));
  1382. Xextern    void        delete_line P((void));
  1383. Xextern    void        inschar P((int));
  1384. Xextern    void        erase_line P((void));
  1385. Xextern    void        erase_display P((void));
  1386. Xextern    void        scroll_up P((int start_row, int end_row, int nlines));
  1387. Xextern    void        scroll_down P((int start_row, int end_row, int nlines));
  1388. Xextern    void        tty_open P((unsigned int *, unsigned int *));
  1389. Xextern    void        tty_startv P((void));
  1390. Xextern    void        tty_endv P((void));
  1391. END_OF_FILE
  1392.   if test 2356 -ne `wc -c <'xvi/src/termcap.h'`; then
  1393.     echo shar: \"'xvi/src/termcap.h'\" unpacked with wrong size!
  1394.   fi
  1395.   # end of 'xvi/src/termcap.h'
  1396. fi
  1397. if test -f 'xvi/src/unix.c' -a "${1}" != "-c" ; then 
  1398.   echo shar: Will not clobber existing file \"'xvi/src/unix.c'\"
  1399. else
  1400.   echo shar: Extracting \"'xvi/src/unix.c'\" \(20793 characters\)
  1401.   sed "s/^X//" >'xvi/src/unix.c' <<'END_OF_FILE'
  1402. X/* Copyright (c) 1990,1991,1992 Chris and John Downey */
  1403. X#ifndef lint
  1404. Xstatic char *sccsid = "@(#)unix.c    2.1 (Chris & John Downey) 7/29/92";
  1405. X#endif
  1406. X
  1407. X/***
  1408. X
  1409. X* program name:
  1410. X    xvi
  1411. X* function:
  1412. X    PD version of UNIX "vi" editor, with extensions.
  1413. X* module name:
  1414. X    unix.c
  1415. X* module function:
  1416. X    System interface routines for all versions of UNIX.
  1417. X* history:
  1418. X    STEVIE - ST Editor for VI Enthusiasts, Version 3.10
  1419. X    Originally by Tim Thompson (twitch!tjt)
  1420. X    Extensive modifications by Tony Andrews (onecom!wldrdg!tony)
  1421. X    Heavily modified by Chris & John Downey
  1422. X
  1423. X***/
  1424. X
  1425. X#include "xvi.h"
  1426. X
  1427. X#ifndef SIGINT
  1428. X#   include <signal.h>        /* get signals for call_shell() */
  1429. X#endif
  1430. X
  1431. X#ifdef    BSD
  1432. X#   include <sys/wait.h>    /* get wait stuff for call_shell() */
  1433. X    typedef    union wait Wait_t;
  1434. X#else
  1435. X    typedef    int Wait_t;
  1436. X#endif
  1437. X
  1438. X/*
  1439. X * CTRL is defined by sgtty.h (or by a file it includes)
  1440. X * so we undefine it here to avoid conflicts with the
  1441. X * version defined in "xvi.h".
  1442. X */
  1443. X#undef    CTRL
  1444. X
  1445. X#ifdef    sun
  1446. X#   ifndef TERMIOS
  1447. X#    define    TERMIOS
  1448. X#   endif
  1449. X#endif
  1450. X
  1451. X#ifdef TERMIOS
  1452. X#   ifndef TERMIO
  1453. X#    define    TERMIO
  1454. X#   endif
  1455. X#endif
  1456. X
  1457. X#ifdef    TERMIO
  1458. X#   ifdef    TERMIOS
  1459. X#    include <termios.h>
  1460. X   typedef struct termios    Termstate;
  1461. X#    define getstate(p)    ((void) tcgetattr(0, (p)))
  1462. X#    define setstate(p)    ((void) tcsetattr(0, TCSANOW, (p)))
  1463. X#    define w_setstate(p)    ((void) tcsetattr(0, TCSADRAIN, (p)))
  1464. X#   else    /* no TERMIOS */
  1465. X#    include <termio.h>
  1466. X   typedef struct termio    Termstate;
  1467. X#    define getstate(p)    ((void) ioctl(0,TCGETA,(char *)(p)))
  1468. X#    define setstate(p)    ((void) ioctl(0,TCSETA,(char *)(p)))
  1469. X#    define w_setstate(p)    ((void) ioctl(0,TCSETAW,(char *)(p)))
  1470. X#   endif    /* no TERMIOS */
  1471. X
  1472. X    /*
  1473. X     * Table of line speeds ... exactly 16 long, and the CBAUD mask
  1474. X     * is 017 (i.e. 15) so we will never access outside the array.
  1475. X     */
  1476. X    short    speeds[] = {
  1477. X    /* B0 */    0,
  1478. X    /* B50 */    50,
  1479. X    /* B75 */    75,
  1480. X    /* B110 */    110,
  1481. X    /* B134 */    134,
  1482. X    /* B150 */    150,
  1483. X    /* B200 */    200,
  1484. X    /* B300 */    300,
  1485. X    /* B600 */    600,
  1486. X    /* B1200 */    1200,
  1487. X    /* B1800 */    1800,
  1488. X    /* B2400 */    2400,
  1489. X    /* B4800 */    4800,
  1490. X    /* B9600 */    9600,
  1491. X    /* EXTA */    19200,        /* not defined at V.2 */
  1492. X    /* EXTB */    38400,        /* not defined at V.2 */
  1493. X    };
  1494. X
  1495. X#else    /* not TERMIO */
  1496. X
  1497. X#   include <sgtty.h>
  1498. X    typedef struct sgttyb    Termstate;
  1499. X
  1500. X    static    struct    tchars    ckd_tchars, raw_tchars;
  1501. X    static    struct    ltchars    ckd_ltchars, raw_ltchars;
  1502. X
  1503. X#   ifdef FD_SET
  1504. X#    define    fd_set_type    fd_set
  1505. X#   else        /* FD_SET not defined */
  1506. X    /*
  1507. X     * BSD 4.2 doesn't have these macros.
  1508. X     */
  1509. X    typedef int fd_set_type;
  1510. X#    define    FD_ZERO(p)    (*(p) = 0)
  1511. X#    define    FD_SET(f,p)    (*(p) |= (1 << (f)))
  1512. X#   endif        /* FD_SET not defined */
  1513. X#endif    /* not TERMIO */
  1514. X
  1515. Xstatic    Termstate    cooked_state, raw_state;
  1516. X
  1517. X#undef    CTRL
  1518. X
  1519. X#ifdef    SETVBUF_AVAIL
  1520. X    /*
  1521. X     * Output buffer to save function calls.
  1522. X     */
  1523. X    static    char    outbuffer[128];
  1524. X#endif
  1525. X
  1526. X#ifdef MEMTEST
  1527. X#   include <sys/resource.h>
  1528. X#endif        /* MEMTEST */
  1529. X
  1530. X/*
  1531. X * Expected for termcap's benefit.
  1532. X */
  1533. Xshort        ospeed;            /* tty's baud rate */
  1534. X
  1535. X/*
  1536. X * We sometimes use a lot of system calls while trying to read from
  1537. X * the keyboard; these are needed to make our automatic buffer
  1538. X * preservation and input timeouts work properly. Nevertheless, it
  1539. X * is possible that, with this much overhead, a reasonably fast typist
  1540. X * could get ahead of us, so we do a small amount of input buffering
  1541. X * to reduce the number of system calls.
  1542. X *
  1543. X * This variable gives the number of characters in the buffer.
  1544. X */
  1545. Xstatic int    kb_nchars;
  1546. X
  1547. X/*
  1548. X * Get a single byte from the keyboard.
  1549. X *
  1550. X * If the keyboard input buffer is empty, & read() fails or times out,
  1551. X * return EOF.
  1552. X */
  1553. Xstatic int
  1554. Xkbgetc()
  1555. X{
  1556. X    static unsigned char    kbuf[48];
  1557. X    static unsigned char    *kbp;
  1558. X
  1559. X    if (kb_nchars <= 0) {
  1560. X    int nread;
  1561. X
  1562. X    if ((nread = read(0, (char *) kbuf, sizeof kbuf)) <= 0) {
  1563. X        return EOF;
  1564. X    } else {
  1565. X        kb_nchars = nread;
  1566. X        kbp = kbuf;
  1567. X    }
  1568. X    }
  1569. X    --kb_nchars;
  1570. X    return(*kbp++);
  1571. X}
  1572. X
  1573. X#ifdef TERMIO
  1574. X
  1575. X/*
  1576. X * Set a timeout on standard input. 0 means no timeout.
  1577. X *
  1578. X * This depends on raw_state having been properly initialized, which
  1579. X * should have been done by sys_startv().
  1580. X */
  1581. Xstatic void
  1582. Xinput_timeout(msec)
  1583. Xlong    msec;
  1584. X{
  1585. X    int        vtime;
  1586. X    static int    lastvtime;
  1587. X
  1588. X    /*
  1589. X     * If the device state hasn't been changed since last time, we
  1590. X     * don't need to do anything.
  1591. X     */
  1592. X    if ((vtime = (msec + 99) / 100) != lastvtime) {
  1593. X    lastvtime = vtime;
  1594. X    raw_state.c_cc[VMIN] = (vtime == 0 ? 1 : 0);
  1595. X    raw_state.c_cc[VTIME] = vtime;
  1596. X    setstate(&raw_state);
  1597. X    }
  1598. X}
  1599. X
  1600. X#endif    /* TERMIO */
  1601. X
  1602. X/*
  1603. X * Get a character from the keyboard.
  1604. X *
  1605. X * Make sure screen is updated first.
  1606. X */
  1607. Xint
  1608. Xinch(timeout)
  1609. Xlong    timeout;
  1610. X{
  1611. X    int        c;
  1612. X
  1613. X    /*
  1614. X     * If we had characters left over from last time, return one.
  1615. X     *
  1616. X     * Note that if this happens, we don't call flush_output().
  1617. X     */
  1618. X    if (kb_nchars > 0) {
  1619. X    return(kbgetc());
  1620. X    }
  1621. X
  1622. X    /*
  1623. X     * Need to get a character. First, flush output to the screen.
  1624. X     */
  1625. X    flush_output();
  1626. X
  1627. X#ifdef TERMIO
  1628. X    if (timeout != 0) {
  1629. X    input_timeout(timeout);
  1630. X    c = kbgetc();
  1631. X    input_timeout(0L);
  1632. X    return(c);
  1633. X    }
  1634. X#else    /* no TERMIO */
  1635. X    if (timeout != 0) {
  1636. X    struct timeval    tv;
  1637. X    fd_set_type    readfds;
  1638. X
  1639. X    tv.tv_sec = (long) (timeout / 1000);
  1640. X    tv.tv_usec = ((long) timeout * 1000) % (long) 1000000;
  1641. X
  1642. X    FD_ZERO(&readfds);
  1643. X    FD_SET(0, &readfds);
  1644. X
  1645. X    /*
  1646. X     * If select does not return 0, some input is available
  1647. X     * (ignoring the possibility of errors). Otherwise, we
  1648. X     * timed out, so return EOF.
  1649. X     */
  1650. X    if (select(1, &readfds, (fd_set_type *) NULL,
  1651. X            (fd_set_type *) NULL, &tv) == 0) {
  1652. X        return(EOF);
  1653. X    }
  1654. X    }
  1655. X#endif    /* no TERMIO */
  1656. X
  1657. X    /*
  1658. X     * Keep trying until we get at least one character.
  1659. X     */
  1660. X    while ((c = kbgetc()) == EOF)
  1661. X    ;
  1662. X
  1663. X    return(c);
  1664. X}
  1665. X
  1666. X#if !(defined(__STDC__) || (defined(ultrix) && defined(mips)))
  1667. X/*
  1668. X * If we have ANSI C, we should have strerror() anyway. Also, Ultrix
  1669. X * on DECStations provides it.
  1670. X */
  1671. Xconst char *
  1672. Xstrerror(err)
  1673. Xint    err;
  1674. X{
  1675. X    extern char    *sys_errlist[];
  1676. X    extern int    sys_nerr;
  1677. X
  1678. X    return(
  1679. X    err == 0 ?
  1680. X        "No error"
  1681. X        :
  1682. X        (err > 0 && err < sys_nerr) ?
  1683. X        sys_errlist[err]
  1684. X        :
  1685. X        "Unknown error"
  1686. X    );
  1687. X}
  1688. X
  1689. X#endif /* !(defined(__STDC__) || (defined(ultrix) && defined(mips))) */
  1690. X
  1691. Xstatic int
  1692. Xrunvp(args)
  1693. Xchar    **args;
  1694. X{
  1695. X    int        pid;
  1696. X    Wait_t    status;
  1697. X
  1698. X    pid = fork();
  1699. X    switch (pid) {
  1700. X    case -1:        /* fork() failed */
  1701. X    return(-1);
  1702. X
  1703. X    case 0:            /* this is the child */
  1704. X    (void) signal(SIGINT, SIG_DFL);
  1705. X    (void) signal(SIGQUIT, SIG_DFL);
  1706. X    (void) execvp(args[0], args);
  1707. X
  1708. X    /*
  1709. X     * Couldn't do it ... use standard output functions here
  1710. X     * because none of xvi's higher-level functions are usable
  1711. X     * from this module.
  1712. X     */
  1713. X    (void) fputs("\007Can't execute ", stdout);
  1714. X    (void) fputs(args[0], stdout);
  1715. X    (void) fputs("\n(", stdout);
  1716. X    (void) fputs(strerror(errno), stdout);
  1717. X    (void) fputs(")\nHit return to continue", stdout);
  1718. X    (void) fflush(stdout);
  1719. X    (void) getc(stdin);
  1720. X    exit(1);
  1721. X
  1722. X    default:        /* this is the parent */
  1723. X    while (wait(&status) != pid)
  1724. X        ;
  1725. X    return(0);
  1726. X    }
  1727. X}
  1728. X
  1729. Xint
  1730. Xcall_shell(sh)
  1731. Xchar    *sh;
  1732. X{
  1733. X    static char    *args[] = { NULL, NULL };
  1734. X
  1735. X    args[0] = sh;
  1736. X    return(runvp(args));
  1737. X}
  1738. X
  1739. Xint
  1740. Xcall_system(command)
  1741. Xchar    *command;
  1742. X{
  1743. X    static char    *args[] = { NULL, "-c", NULL, NULL };
  1744. X
  1745. X    if (Ps(P_shell) == NULL) {
  1746. X    (void) puts("\007Can't execute command without SHELL parameter");
  1747. X    return(-1);
  1748. X    }
  1749. X    args[0] = Ps(P_shell);
  1750. X    args[2] = command;
  1751. X    return(runvp(args));
  1752. X}
  1753. X
  1754. X#ifdef ITIMER_REAL
  1755. X    static int
  1756. X    nothing()
  1757. X    {
  1758. X    return(0);
  1759. X    }
  1760. X#endif
  1761. X
  1762. X/*
  1763. X * Delay for a short time - preferably less than 1 second.
  1764. X * This is for use by showmatch, which wants to hold the
  1765. X * cursor over the matching bracket for just long enough
  1766. X * that it will be seen.
  1767. X */
  1768. Xvoid
  1769. Xdelay()
  1770. X{
  1771. X#ifdef ITIMER_REAL
  1772. X    struct itimerval    timer;
  1773. X    
  1774. X    (void) signal(SIGALRM, nothing);
  1775. X
  1776. X    /*
  1777. X     * We want to pause for 200 msec (1/5th of a second) here,
  1778. X     * as this seems like a reasonable figure. Note that we can
  1779. X     * assume that the implementation will have defined tv_usec
  1780. X     * of a type large enough to hold up to 999999, since that's
  1781. X     * the largest number of microseconds we can possibly need.
  1782. X     */
  1783. X    timer.it_interval.tv_sec = 0;
  1784. X    timer.it_interval.tv_usec = 0;
  1785. X    timer.it_value.tv_sec = 0;
  1786. X    timer.it_value.tv_usec = 200000;
  1787. X    if (setitimer(ITIMER_REAL, &timer, (struct itimerval *) NULL) == -1)
  1788. X    return;
  1789. X    (void) pause();
  1790. X
  1791. X    timer.it_interval.tv_sec = 0;
  1792. X    timer.it_interval.tv_usec = 0;
  1793. X    (void) setitimer(ITIMER_REAL, &timer, (struct itimerval *) NULL);
  1794. X#else /* not ITIMER_REAL */
  1795. X    sleep(1);
  1796. X#endif /* not ITIMER_REAL */
  1797. X}
  1798. X
  1799. X/*
  1800. X * Initialise the terminal so that we can do single-character
  1801. X * input and output, with no strange mapping, and no echo of
  1802. X * input characters.
  1803. X *
  1804. X * This must be done before any screen-based i/o is performed.
  1805. X */
  1806. Xvoid
  1807. Xsys_init()
  1808. X{
  1809. X#ifdef    TIOCGWINSZ
  1810. X    struct winsize    winsz;    /* for getting window wize */
  1811. X#endif
  1812. X
  1813. X    /*
  1814. X     * What the device driver thinks the window's dimensions are.
  1815. X     */
  1816. X    unsigned int    rows = 0;
  1817. X    unsigned int    columns = 0;
  1818. X
  1819. X#ifdef MEMTEST
  1820. X    {
  1821. X    static struct rlimit dlimit = { 400 * 1024, 400 * 1024 };
  1822. X
  1823. X    (void) setrlimit(RLIMIT_DATA, &dlimit);
  1824. X    }
  1825. X#endif        /* MEMTEST */
  1826. X
  1827. X    /*
  1828. X     * Set up tty flags in raw and cooked structures.
  1829. X     * Do this before any termcap-initialisation stuff
  1830. X     * so that start sequences can be sent.
  1831. X     */
  1832. X#ifdef    TERMIO
  1833. X
  1834. X    getstate(&cooked_state);
  1835. X    raw_state = cooked_state;
  1836. X#   ifdef   POSIX
  1837. X    raw_state.c_oflag &= ~(OPOST
  1838. X#    ifdef    ONLCR
  1839. X                | ONLCR
  1840. X#    endif
  1841. X#    ifdef    OXTABS
  1842. X                | OXTABS
  1843. X#    endif
  1844. X                );
  1845. X    raw_state.c_iflag &= ~(ICRNL | IGNCR | INLCR);
  1846. X    raw_state.c_lflag &= ~(ICANON | ECHO | ECHOE | ECHOK | ECHONL
  1847. X#    ifdef    ECHOCTL
  1848. X                | ECHOCTL
  1849. X#    endif
  1850. X#    ifdef    ECHOPRT
  1851. X                | ECHOPRT
  1852. X#    endif
  1853. X#    ifdef    ECHOKE
  1854. X                | ECHOKE
  1855. X#    endif
  1856. X                );
  1857. X#   else    /* not POSIX */
  1858. X    /*
  1859. X     * Assume this is a Sun, but it might not be ...
  1860. X     */
  1861. X    raw_state.c_oflag &= ~(OLCUC | ONLCR | OCRNL | ONLRET | XTABS);
  1862. X    raw_state.c_iflag &= ~(ICRNL | IGNCR | INLCR);
  1863. X    raw_state.c_lflag &= ~(ICANON | XCASE | ECHO | ECHOE | ECHOK |
  1864. X           ECHONL | ECHOCTL | ECHOPRT | ECHOKE);
  1865. X#   endif
  1866. X    raw_state.c_cc[VMIN] = 1;
  1867. X    raw_state.c_cc[VTIME] = 0;
  1868. X#   ifdef    TERMIOS
  1869. X#    ifdef        VDISCARD
  1870. X        raw_state.c_cc[VDISCARD] = 0;
  1871. X#    endif
  1872. X    raw_state.c_cc[VSUSP] = 0;
  1873. X#   endif    /* TERMIOS */
  1874. X
  1875. X#else    /* not TERMIO */
  1876. X
  1877. X    /*
  1878. X     * Probably a BSD system; we must
  1879. X     *    turn off echo,
  1880. X     *    set cbreak mode (not raw because we lose
  1881. X     *        typeahead when switching modes),
  1882. X     *    turn off tab expansion on output (in case termcap
  1883. X     *        puts out any tabs in cursor motions etc),
  1884. X     *    turn off CRMOD so we get \r and \n as they are typed,
  1885. X     * and
  1886. X     *    turn off nasty interrupt characters like ^Y so that
  1887. X     *        we get the control characters we want.
  1888. X     *
  1889. X     * All this has to be put back as it was when we go into
  1890. X     * system mode; a pain, but we have to get it right.
  1891. X     */
  1892. X    (void) ioctl(0, TIOCGETP, (char *) &cooked_state);
  1893. X    raw_state = cooked_state;
  1894. X    raw_state.sg_flags |= CBREAK;
  1895. X    raw_state.sg_flags &= ~ (ECHO | XTABS | CRMOD);
  1896. X
  1897. X    (void) ioctl(0, TIOCGETC, (char *) &ckd_tchars);
  1898. X    raw_tchars = ckd_tchars;
  1899. X    raw_tchars.t_quitc = -1;
  1900. X
  1901. X    (void) ioctl(0, TIOCGLTC, (char *) &ckd_ltchars);
  1902. X    raw_ltchars = ckd_ltchars;
  1903. X    raw_ltchars.t_flushc = -1;
  1904. X    raw_ltchars.t_lnextc = -1;
  1905. X    raw_ltchars.t_suspc = -1;
  1906. X    raw_ltchars.t_dsuspc = -1;
  1907. X
  1908. X#endif    /* not TERMIO */
  1909. X
  1910. X#ifdef    SETVBUF_AVAIL
  1911. X    /*
  1912. X     * Set output buffering to avoid calling _flsbuf()
  1913. X     * for every character sent to the screen.
  1914. X     */
  1915. X    setvbuf(stdout, outbuffer, _IOFBF, sizeof(outbuffer));
  1916. X#endif
  1917. X
  1918. X    /*
  1919. X     * This is for termcap's benefit.
  1920. X     */
  1921. X#ifdef    TERMIO
  1922. X#   ifdef    POSIX
  1923. X    ospeed = cooked_state.c_ospeed;
  1924. X#   else    /* not POSIX */
  1925. X    ospeed = speeds[cooked_state.c_cflag & CBAUD];
  1926. X#   endif
  1927. X#else
  1928. X    ospeed = cooked_state.sg_ospeed;
  1929. X#endif
  1930. X
  1931. X#ifdef    TIOCGWINSZ
  1932. X    /*
  1933. X     * Find out how big the kernel thinks the window is.
  1934. X     * These values (if they are non-zero) will override
  1935. X     * any settings obtained by the terminal interface code.
  1936. X     */
  1937. X    (void) ioctl(0, TIOCGWINSZ, (char *) &winsz);
  1938. X    rows = winsz.ws_row;
  1939. X    columns = winsz.ws_col;
  1940. X#else
  1941. X    rows = columns = 0;
  1942. X#endif
  1943. X
  1944. X    /*
  1945. X     * Now set up the terminal interface.
  1946. X     */
  1947. X    tty_open(&rows, &columns);
  1948. X
  1949. X    /*
  1950. X     * Go into raw/cbreak mode, and do any initialisation stuff.
  1951. X     */
  1952. X    sys_startv();
  1953. X}
  1954. X
  1955. Xstatic enum { m_SYS = 0, m_VI = 1 } curmode;
  1956. X
  1957. X/*
  1958. X * Set terminal into the mode it was in when we started.
  1959. X *
  1960. X * sys_endv() can be called when we're already in system mode, so we
  1961. X * have to check.
  1962. X */
  1963. Xvoid
  1964. Xsys_endv()
  1965. X{
  1966. X    if (curmode == m_SYS)
  1967. X    return;
  1968. X    tty_goto((int) Rows - 1, 0);
  1969. X    set_colour(Pn(P_systemcolour));
  1970. X    erase_line();
  1971. X    tty_endv();
  1972. X
  1973. X    (void) fflush(stdout);
  1974. X
  1975. X    /*
  1976. X     * Restore terminal modes.
  1977. X     */
  1978. X#ifdef    TERMIO
  1979. X    w_setstate(&cooked_state);
  1980. X#else
  1981. X    (void) ioctl(0, TIOCSETN, (char *) &cooked_state);
  1982. X    (void) ioctl(0, TIOCSETC, (char *) &ckd_tchars);
  1983. X    (void) ioctl(0, TIOCSLTC, (char *) &ckd_ltchars);
  1984. X#endif
  1985. X    curmode = m_SYS;
  1986. X}
  1987. X
  1988. X/*
  1989. X * Set terminal to raw/cbreak mode.
  1990. X */
  1991. Xvoid
  1992. Xsys_startv()
  1993. X{
  1994. X    if (curmode == m_VI)
  1995. X    return;
  1996. X#ifdef    TERMIO
  1997. X    w_setstate(&raw_state);
  1998. X#else
  1999. X    (void) ioctl(0, TIOCSETN, (char *) &raw_state);
  2000. X    (void) ioctl(0, TIOCSETC, (char *) &raw_tchars);
  2001. X    (void) ioctl(0, TIOCSLTC, (char *) &raw_ltchars);
  2002. X#endif
  2003. X
  2004. X    tty_startv();
  2005. X
  2006. X    set_colour(Pn(P_colour));
  2007. X
  2008. X    curmode = m_VI;
  2009. X}
  2010. X
  2011. X/*
  2012. X * "Safe" form of exit - doesn't leave the tty in yillruction mode.
  2013. X */
  2014. Xvoid
  2015. Xsys_exit(code)
  2016. Xint    code;
  2017. X{
  2018. X    sys_endv();
  2019. X    tty_close();
  2020. X    (void) fclose(stdin);
  2021. X    (void) fclose(stdout);
  2022. X    (void) fclose(stderr);
  2023. X
  2024. X    /*
  2025. X     * This is desperation really.
  2026. X     * On some BSD systems, calling exit() here produces a core dump.
  2027. X     */
  2028. X    _exit(code);
  2029. X}
  2030. X
  2031. X/*
  2032. X * This is a routine that can be passed to tputs() (in the termcap
  2033. X * library): it does the same thing as putchar().
  2034. X */
  2035. Xvoid
  2036. Xfoutch(c)
  2037. Xint    c;
  2038. X{
  2039. X    putchar(c);
  2040. X}
  2041. X
  2042. X/*
  2043. X * Construct unique name for temporary file, to be used as a backup
  2044. X * file for the named file.
  2045. X */
  2046. Xchar *
  2047. Xtempfname(srcname)
  2048. Xchar    *srcname;
  2049. X{
  2050. X    char    tailname[MAXNAMLEN + 1];
  2051. X    char    *srctail;
  2052. X    char    *endp;
  2053. X    char    *retp;
  2054. X    unsigned    headlen;
  2055. X    unsigned    rootlen;
  2056. X    unsigned    indexnum = 0;
  2057. X
  2058. X    if ((srctail = strrchr(srcname, '/')) == NULL) {
  2059. X    srctail = srcname;
  2060. X    } else {
  2061. X    srctail++;
  2062. X    }
  2063. X    headlen = srctail - srcname;
  2064. X
  2065. X    /*
  2066. X     * Make copy of filename's tail & change it from "wombat" to
  2067. X     * "#wombat.tmp".
  2068. X     */
  2069. X    tailname [0] = '#';
  2070. X    (void) strncpy(& tailname [1], srctail, sizeof tailname - 1);
  2071. X    tailname [sizeof tailname - 1] = '\0';
  2072. X    endp = tailname + strlen(tailname);
  2073. X
  2074. X    /*
  2075. X     * Don't let name get too long.
  2076. X     */
  2077. X    if (endp > & tailname [sizeof tailname - 5]) {
  2078. X    endp = & tailname [sizeof tailname - 5];
  2079. X    }
  2080. X    rootlen = endp - tailname;
  2081. X
  2082. X    /*
  2083. X     * Now allocate space for new pathname.
  2084. X     */
  2085. X    retp = alloc(headlen + rootlen + 5);
  2086. X    if (retp == NULL) {
  2087. X    return(NULL);
  2088. X    }
  2089. X
  2090. X    /*
  2091. X     * Copy name to new storage, leaving space for ".tmp"
  2092. X     * (or ".xxx") suffix ...
  2093. X     */
  2094. X    if (headlen > 0) {
  2095. X    (void) memcpy(retp, srcname, (int) headlen);
  2096. X    }
  2097. X    (void) memcpy(&retp[headlen], tailname, (int) rootlen);
  2098. X
  2099. X    /*
  2100. X     * ... & make endp point to the space we're leaving for the suffix.
  2101. X     */
  2102. X    endp = &retp[headlen + rootlen];
  2103. X    strcpy(endp++, ".tmp");
  2104. X    while (access(retp, 0) == 0) {
  2105. X    /*
  2106. X     * Keep trying this until we get a unique file name.
  2107. X     */
  2108. X    Flexbuf suffix;
  2109. X
  2110. X    flexnew(&suffix);
  2111. X    (void) lformat(&suffix, "%03u", ++indexnum);
  2112. X    (void) strncpy(endp, flexgetstr(&suffix), 3);
  2113. X    flexdelete(&suffix);
  2114. X    }
  2115. X    return retp;
  2116. X}
  2117. X
  2118. X/*
  2119. X * Fork off children thus:
  2120. X *
  2121. X * [CHILD 1] --- pipe1 ---> [CHILD 2] --- pipe2 ---> [PARENT]
  2122. X *    |                        |                        |
  2123. X *    V                        V                        V
  2124. X * writefunc                exec(cmd)                readfunc
  2125. X *
  2126. X * connecting the pipes to stdin/stdout as appropriate.
  2127. X *
  2128. X * We assume that on entry to this function, file descriptors 0, 1 and 2
  2129. X * are already open, so we do not have to deal with the possibility of
  2130. X * them being allocated as pipe descriptors.
  2131. X */
  2132. Xbool_t
  2133. Xsys_pipe(cmd, writefunc, readfunc)
  2134. Xchar    *cmd;
  2135. Xint    (*writefunc) P((FILE *));
  2136. Xlong    (*readfunc) P((FILE *));
  2137. X{
  2138. X    int        pd1[2], pd2[2];        /* descriptors for pipes 1 and 2 */
  2139. X    int        pid1, pid2;        /* process ids for children 1 and 2 */
  2140. X    int        died;
  2141. X    int        retval;
  2142. X    FILE    *fp;
  2143. X    Wait_t    status;
  2144. X    static char    *args[] = { NULL, "-c", NULL, NULL };
  2145. X
  2146. X    if (Ps(P_shell) == NULL) {
  2147. X    return(FALSE);
  2148. X    }
  2149. X    args[0] = Ps(P_shell);
  2150. X    args[2] = cmd;
  2151. X
  2152. X    /*
  2153. X     * Initialise these values so we can work out what has happened
  2154. X     * so far if we have to goto fail for any reason.
  2155. X     */
  2156. X    pd1[0] = pd1[1] = pd2[0] = pd2[1] = -1;
  2157. X    pid1 = pid2 = -1;
  2158. X
  2159. X    if (pipe(pd1) == -1) {
  2160. X    goto fail;
  2161. X    }
  2162. X
  2163. X    switch (pid1 = fork()) {
  2164. X    case -1:                    /* error */
  2165. X    goto fail;
  2166. X
  2167. X    case 0:                    /* child 1 */
  2168. X    /*
  2169. X     * Fdopen pipe1 to get a stream.
  2170. X     */
  2171. X    (void) close(pd1[0]);
  2172. X    fp = fdopen(pd1[1], "w");
  2173. X    if (fp == NULL) {
  2174. X        exit(1);
  2175. X    }
  2176. X
  2177. X    /*
  2178. X     * Call writefunc.
  2179. X     */
  2180. X    (void) (*writefunc)(fp);
  2181. X    (void) fclose(fp);
  2182. X
  2183. X    /*
  2184. X     * Our work is done.
  2185. X     */
  2186. X    exit(0);
  2187. X
  2188. X    default:                    /* parent */
  2189. X    (void) close(pd1[1]);
  2190. X    break;
  2191. X    }
  2192. X
  2193. X    if (pipe(pd2) == -1) {
  2194. X    goto fail;
  2195. X    }
  2196. X    switch (pid2 = fork()) {
  2197. X    case -1:                    /* error */
  2198. X    goto fail;
  2199. X
  2200. X    case 0:                        /* child 2 */
  2201. X
  2202. X    /*
  2203. X     * Rearrange file descriptors onto stdin/stdout/stderr.
  2204. X     */
  2205. X    (void) close(pd1[1]);
  2206. X    (void) close(pd2[0]);
  2207. X
  2208. X    (void) close(0);
  2209. X    (void) dup(pd1[0]);        /* dup2(pd1[0], 0) */
  2210. X    (void) close(pd1[0]);
  2211. X
  2212. X    (void) close(1);
  2213. X    (void) dup(pd2[1]);        /* dup2(pd2[1], 1) */
  2214. X    (void) close(pd2[1]);
  2215. X
  2216. X    (void) close(2);
  2217. X    (void) dup(1);            /* dup2(1, 2) */
  2218. X    
  2219. X    /*
  2220. X     * Exec the command.
  2221. X     */
  2222. X    (void) execvp(args[0], args);
  2223. X    exit(1);
  2224. X
  2225. X    default:                    /* parent */
  2226. X    (void) close(pd1[0]);
  2227. X    (void) close(pd2[1]);
  2228. X    pd1[0] = pd2[1] = -1;
  2229. X    fp = fdopen(pd2[0], "r");
  2230. X    if (fp == NULL) {
  2231. X        goto fail;
  2232. X    }
  2233. X    (void) (*readfunc)(fp);
  2234. X    (void) fclose(fp);
  2235. X    break;
  2236. X    }
  2237. X
  2238. X    /*
  2239. X     * Finally, clean up the children.
  2240. X     */
  2241. X    retval = TRUE;
  2242. X    goto cleanup;
  2243. X
  2244. Xfail:
  2245. X    /*
  2246. X     * Come here if anything fails (if we are the original process).
  2247. X     * Close any open pipes and goto cleanup to reap the child processes.
  2248. X     */
  2249. X    if (pd1[0] >= 0) {
  2250. X    (void) close(pd1[0]);
  2251. X    (void) close(pd1[1]);
  2252. X    }
  2253. X    if (pd2[0] >= 0) {
  2254. X    (void) close(pd2[0]);
  2255. X    (void) close(pd2[1]);
  2256. X    }
  2257. X    retval = FALSE;
  2258. X
  2259. Xcleanup:
  2260. X    /*
  2261. X     * Come here whether or not we failed, to clean up the children ...
  2262. X     */
  2263. X#ifdef    WIFEXITED
  2264. X#   define    FAILED(s)    (!WIFEXITED(s) || (s).w_retcode != 0)
  2265. X#else
  2266. X#   define    FAILED(s)    ((s) != 0)
  2267. X#endif
  2268. X#ifndef WTERMSIG
  2269. X#   ifdef   WIFSIGNALED
  2270. X#    define    WTERMSIG(s)    (WIFSIGNALED(s) ? (s).w_termsig : 0)
  2271. X#   else
  2272. X#    define    WTERMSIG(s)    ((s) & 0177)
  2273. X#   endif
  2274. X#endif
  2275. X    while ((died = wait(&status)) != -1) {
  2276. X    if (died == pid1 || died == pid2) {
  2277. X        /*
  2278. X         * If child 1 was killed with SIGPIPE -
  2279. X         * because child 2 exited before reading all
  2280. X         * of its input - it isn't necessarily an
  2281. X         * error.
  2282. X         */
  2283. X        if (
  2284. X        FAILED(status)
  2285. X        &&
  2286. X        (
  2287. X            died == pid2
  2288. X            ||
  2289. X            WTERMSIG(status) != SIGPIPE
  2290. X        )
  2291. X        ) {
  2292. X        retval = FALSE;
  2293. X        }
  2294. X    }
  2295. X    }
  2296. X
  2297. X    return(retval);
  2298. X}
  2299. X
  2300. Xchar *
  2301. Xfexpand(name)
  2302. Xchar    *name;
  2303. X{
  2304. X    static char    meta[] = "*?[]~${}`";
  2305. X    char    *cp;
  2306. X    int        pd[2];
  2307. X    int        has_meta;
  2308. X
  2309. X    has_meta = FALSE;
  2310. X    for (cp = meta; *cp != '\0'; cp++) {
  2311. X    if (strchr(name, *cp) != NULL) {
  2312. X        has_meta = TRUE;
  2313. X        break;
  2314. X    }
  2315. X    }
  2316. X    if (!has_meta) {
  2317. X    return(name);
  2318. X    }
  2319. X
  2320. X    if (Ps(P_shell) == NULL) {
  2321. X    return(name);
  2322. X    }
  2323. X    if (pipe(pd) == -1) {
  2324. X    return(name);
  2325. X    }
  2326. X    fflush(stdout);
  2327. X    switch (fork()) {
  2328. X    case -1:                /* error */
  2329. X    return(name);
  2330. X
  2331. X    case 0:                /* child */
  2332. X    {
  2333. X    static char    *args[] = {
  2334. X        NULL,            /* path of shell */
  2335. X        "-c",
  2336. X        NULL,            /* echo %s */
  2337. X        NULL,
  2338. X    };
  2339. X    Flexbuf        cmd;
  2340. X    int        errout;
  2341. X
  2342. X    args[0] = Ps(P_shell);
  2343. X    flexnew(&cmd);
  2344. X    (void) lformat(&cmd, "echo %s", name);
  2345. X    args[2] = flexgetstr(&cmd);
  2346. X    (void) fclose(stdout);
  2347. X    (void) fclose(stderr);
  2348. X    (void) close(pd[0]);
  2349. X    while (dup(pd[1]) < 2)        /* redirect both stdout & stderr */
  2350. X        ;
  2351. X    (void) close(pd[1]);
  2352. X    (void) close(0);
  2353. X    (void) execvp(args[0], args);
  2354. X    puts(name);
  2355. X    exit(0);
  2356. X    }
  2357. X    default:                /* parent */
  2358. X    {
  2359. X    Wait_t        status;
  2360. X    FILE        *pfp;
  2361. X    static Flexbuf    newname;
  2362. X    register int    c;
  2363. X
  2364. X    flexclear(&newname);
  2365. X    (void) close(pd[1]);
  2366. X    pfp = fdopen(pd[0], "r");
  2367. X    if (pfp != NULL) {
  2368. X        while ((c = getc(pfp)) != EOF && c != '\n') {
  2369. X        if (!flexaddch(&newname, c)) {
  2370. X            break;
  2371. X        }
  2372. X        }
  2373. X    }
  2374. X    (void) fclose(pfp);
  2375. X    (void) wait(&status);
  2376. X    if (flexempty(&newname)) {
  2377. X        return(name);
  2378. X    }
  2379. X    return(flexgetstr(&newname));
  2380. X    }
  2381. X    }
  2382. X}
  2383. END_OF_FILE
  2384.   if test 20793 -ne `wc -c <'xvi/src/unix.c'`; then
  2385.     echo shar: \"'xvi/src/unix.c'\" unpacked with wrong size!
  2386.   fi
  2387.   # end of 'xvi/src/unix.c'
  2388. fi
  2389. echo shar: End of archive 12 \(of 18\).
  2390. cp /dev/null ark12isdone
  2391. MISSING=""
  2392. for I in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 ; do
  2393.     if test ! -f ark${I}isdone ; then
  2394.     MISSING="${MISSING} ${I}"
  2395.     fi
  2396. done
  2397. if test "${MISSING}" = "" ; then
  2398.     echo You have unpacked all 18 archives.
  2399.     rm -f ark[1-9]isdone ark[1-9][0-9]isdone
  2400. else
  2401.     echo You still must unpack the following archives:
  2402.     echo "        " ${MISSING}
  2403. fi
  2404. exit 0
  2405. exit 0 # Just in case...
  2406.