[comp.sources.amiga] v89i134: stevie - vi editor clone v3.6, Part05/06

page%swap@Sun.COM (Bob Page) (05/12/89)

Submitted-by: grwalter@watmath.waterloo.edu (Fred Walter)
Posting-number: Volume 89, Issue 134
Archive-name: editors/stevie36.5

# This is a shell archive.
# Remove anything above and including the cut line.
# Then run the rest of the file through 'sh'.
# Unpacked files will be owned by you and have default permissions.
#----cut here-----cut here-----cut here-----cut here----#
#!/bin/sh
# shar: SHell ARchive
# Run the following text through 'sh' to create:
#	regexp.cat.uu
#	regexp.h
#	regmagic.h
#	regsub.c
#	s_io.c
#	screen.c
#	search.c
# This is archive 5 of a 6-part kit.
# This archive created: Thu May 11 19:41:28 1989
echo "extracting regexp.cat.uu"
sed 's/^X//' << \SHAR_EOF > regexp.cat.uu
X
Xbegin 644 regexp.cat
XM"@H*"E)%1T584"@S*2`@("`@("`@("`@("`@("!,:6)R87)Y($9U;F-T:6]NR
XM<R`@("`@("`@("`@("`@(%)%1T584"@S*0H*"@I."$Y!"$%-"$U%"$4*("`@6
XM("!R96=C;VUP+"!R96=E>&5C+"!R96=S=6(L(')E9V5R<F]R("T@<F5G=6QA1
XM<B!E>'!R97-S:6]N"B`@("`@:&%N9&QE<@H*4PA360A93@A.3PA/4`A04PA3&
XM20A)4PA3"B`@("`@(P@C:0AI;@AN8PAC;`AL=0AU9`AD90AE(#P(/'((<F4(Y
XM96<(9V4(97@(>'`(<"X(+F@(:#X(/@H*("`@("!R"')E"&5G"&=E"&5X"'APO
XM"'`@*@@J<@AR90AE9PAG8PAC;PAO;0AM<`AP*`@H90AE>`AX<`AP*0@I"B`@T
XM("`@8PAC:`AH80AA<@AR("H(*F4(97@(>'`(<#L(.PH*("`@("!I"&EN"&YT.
XM"'0@<@AR90AE9PAG90AE>`AX90AE8PAC*`@H<`AP<@AR;PAO9PAG+`@L(',(]
XM<W0(='((<FD(:6X(;F<(9RD(*0H@("`@('((<F4(96<(9V4(97@(>'`(<"`JW
XM""IP"'!R"')O"&]G"&<["#L*("`@("!C"&-H"&AA"&%R"'(@*@@J<PAS=`AT@
XM<@AR:0AI;@AN9PAG.P@["@H@("`@('((<F4(96<(9W,(<W4(=6((8B@(*'`("
XM<'((<F\(;V<(9RP(+"!S"'-O"&]U"'5R"')C"&-E"&4L""P@9`AD90AE<PASZ
XM=`AT*0@I"B`@("`@<@AR90AE9PAG90AE>`AX<`AP("H(*G`(<'((<F\(;V<(?
XM9SL(.PH@("`@(&,(8V@(:&$(87((<B`J""IS"'-O"&]U"'5R"')C"&-E"&4[T
XM"#L*("`@("!C"&-H"&AA"&%R"'(@*@@J9`AD90AE<PAS=`AT.P@["@H@("`@7
XM('((<F4(96<(9V4(97((<G((<F\(;W((<B@(*&T(;7,(<V<(9RD(*0H@("`@2
XM(&,(8V@(:&$(87((<B`J""IM"&US"'-G"&<["#L*"D0(1$4(15,(4T,(0U((H
XM4DD(25`(4%0(5$D(24\(3TX(3@H@("`@(%1H97-E(&9U;F-T:6]N<R!I;7!L6
XM96UE;G0*("`@("!?"&5?"&=?"')?"&5?"'`H,2DM<W1Y;&4*("`@("!R96=U6
XM;&%R(&5X<')E<W-I;VYS(&%N9"!S=7!P;W)T:6YG(&9A8VEL:71I97,N"@H@/
XM("`@(%\(4E\(95\(9U\(8U\(;U\(;5\(<`H@("`@(&-O;7!I;&5S(&$@<F5G#
XM=6QA<B!E>'!R97-S:6]N(&EN=&\@82!S=')U8W1U<F4@;V8@='EP90H@("`@Q
XM(%\(<E\(95\(9U\(95\(>%\(<"P*("`@("!A;F0@<F5T=7)N<R!A('!O:6YT<
XM97(@=&\@:70N"B`@("`@5&AE('-P86-E(&AA<R!B965N(&%L;&]C871E9"!UP
XM<VEN9PH@("`@(%\(;5\(85\(;%\(;%\(;U\(8R@S*0H@("`@(&%N9"!M87D@E
XM8F4@<F5L96%S960@8GD*("`@("!?"&9?"')?"&5?"&4N"@H@("`@(%\(4E\(1
XM95\(9U\(95\(>%\(95\(8PH@("`@(&UA=&-H97,@82!.54PM=&5R;6EN871E)
XM9"!?"'-?"'1?"')?"&E?"&Y?"&<@86=A:6YS="!T:&4@8V]M<&EL960@<F5GX
XM=6QA<B!E>'!R97-S:6]N"B`@("`@:6X@7PAP7PAR7PAO7PAG+@H@("`@($ETN
XM(')E='5R;G,@,2!F;W(@<W5C8V5S<R!A;F0@,"!F;W(@9F%I;'5R92P@86YD5
XM(&%D:G5S=',@=&AE(&-O;G1E;G1S(&]F"B`@("`@7PAP7PAR7PAO7PAG)W,@Z
XM7PAS7PAT7PAA7PAR7PAT7PAP(&%N9"!?"&5?"&Y?"&1?"'`@*'-E92!B96QO%
XM=RD@86-C;W)D:6YG;'DN"@H@("`@(%1H92!M96UB97)S(&]F(&$*("`@("!?<
XM"')?"&5?"&=?"&5?"'A?"'`*("`@("!S=')U8W1U<F4@:6YC;'5D92!A="!LV
XM96%S="!T:&4@9F]L;&]W:6YG("AN;W0@;F5C97-S87)I;'D@:6X@;W)D97(IV
XM.@H*("`@("`@("`@(&-H87(@*G-T87)T<%M.4U5"15A073L*("`@("`@("`@6
XM(&-H87(@*F5N9'!;3E-50D584%T["@H@("`@('=H97)E"B`@("`@7PA.7PA3O
XM7PA57PA"7PA%7PA87PA0"B`@("`@:7,@9&5F:6YE9"`H87,@,3`I(&EN('1HU
XM92!H96%D97(@9FEL92X*"@H*1F]R;6%T=&5D(#@X+S$R+S,P("`@("`@("`@^
XM("`@;&]C86P@("`@("`@("`@("`@("`@("`@("`@("`@("`@(#$*#`H*"@I2,
XM14=%6%`H,RD@("`@("`@("`@("`@("`@3&EB<F%R>2!&=6YC=&EO;G,@("`@K
XM("`@("`@("`@("!214=%6%`H,RD*"@H*("`@("!/;F-E(&$@<W5C8V5S<V9UQ
XM;"!?"')?"&5?"&=?"&5?"'A?"&5?"&,@:&%S(&)E96X@9&]N92!U<VEN9R!TV
XM:&4@7PAR7PAE7PAG7PAE7PAX7PAP+`H@("`@(&5A8V@@7PAS7PAT7PAA7PAR_
XM7PAT7PAP+5\(95\(;E\(9%\(<"!P86ER(&1E<V-R:6)E<R!O;F4@<W5B<W1RG
XM:6YG"B`@("`@=VET:&EN('1H92!?"'-?"'1?"')?"&E?"&Y?"&<L"B`@("`@3
XM=VET:"!T:&4@7PAS7PAT7PAA7PAR7PAT7PAP('!O:6YT:6YG('1O('1H92!FW
XM:7)S="!C:&%R86-T97(@;V8@=&AE('-U8G-T<FEN9R!A;F0*("`@("!T:&4@$
XM7PAE7PAN7PAD7PAP('!O:6YT:6YG('1O('1H92!F:7)S="!C:&%R86-T97(@D
XM9F]L;&]W:6YG('1H92!S=6)S=')I;F<N"B`@("`@5&AE(#!T:"!S=6)S=')I$
XM;F<@:7,@=&AE('-U8G-T<FEN9R!O9B!?"'-?"'1?"')?"&E?"&Y?"&<@=&AAF
XM="!M871C:&5D('1H92!W:&]L90H@("`@(')E9W5L87(@97AP<F5S<VEO;BX*.
XM("`@("!4:&4@;W1H97)S(&%R92!T:&]S92!S=6)S=')I;F=S('1H870@;6%TX
XM8VAE9"!P87)E;G1H97-I>F5D(&5X<')E<W-I;VYS"B`@("`@=VET:&EN('1H&
XM92!R96=U;&%R(&5X<')E<W-I;VXL('=I=&@@<&%R96YT:&5S:7IE9"!E>'!RD
XM97-S:6]N<R!N=6UB97)E9`H@("`@(&EN(&QE9G0M=&\M<FEG:'0@;W)D97(@Y
XM;V8@=&AE:7(@;W!E;FEN9R!P87)E;G1H97-E<RX*"B`@("`@7PA27PAE7PAG8
XM7PAS7PAU7PAB"B`@("`@8V]P:65S(%\(<U\(;U\(=5\(<E\(8U\(92!T;R!?)
XM"&1?"&5?"'-?"'0L(&UA:VEN9R!S=6)S=&ET=71I;VYS(&%C8V]R9&EN9R!T>
XM;R!T:&4*("`@("!M;W-T(')E8V5N="!?"')?"&5?"&=?"&5?"'A?"&5?"&,@2
XM<&5R9F]R;65D('5S:6YG(%\(<%\(<E\(;U\(9RX*("`@("!%86-H(&EN<W1A&
XM;F-E(&]F(&`F)R!I;B!?"'-?"&]?"'5?"')?"&-?"&4@:7,@<F5P;&%C960@&
XM8GD@=&AE('-U8G-T<FEN9PH@("`@(&EN9&EC871E9"!B>2!?"'-?"'1?"&%?#
XM"')?"'1?"'!;7P@P72!A;F0*("`@("!?"&5?"&Y?"&1?"'!;7P@P72X*("`@B
XM("!%86-H(&EN<W1A;F-E(&]F(&!<7PAN)RP@=VAE<F4@7PAN(&ES(&$@9&EG@
XM:70L(&ES(')E<&QA8V5D(&)Y"B`@("`@=&AE('-U8G-T<FEN9R!I;F1I8V%T(
XM960@8GD*("`@("!?"'-?"'1?"&%?"')?"'1?"'!;7PAN72!A;F0*("`@("!??
XM"&5?"&Y?"&1?"'!;7PAN72X*("`@("!4;R!G970@82!L:71E<F%L(&`F)R!O6
XM<B!@7%\(;B<@:6YT;R!?"&1?"&5?"'-?"'0L('!R969I>"!I="!W:71H(&!<?
XM)SL*("`@("!T;R!G970@82!L:71E<F%L(&!<)R!P<F5C961I;F<@8"8G(&]R_
XM(&!<7PAN)RP@<')E9FEX(&ET('=I=&@*("`@("!A;F]T:&5R(&!<)RX*"B`@K
XM("`@7PA27PAE7PAG7PAE7PAR7PAR7PAO7PAR"B`@("`@:7,@8V%L;&5D('=HJ
XM96YE=F5R(&%N(&5R<F]R(&ES(&1E=&5C=&5D(&EN(%\(<E\(95\(9U\(8U\(7
XM;U\(;5\(<"P@7PAR7PAE7PAG7PAE7PAX7PAE7PAC+`H@("`@(&]R(%\(<E\(Q
XM95\(9U\(<U\(=5\(8BX*("`@("!4:&4@9&5F875L="!?"')?"&5?"&=?"&5?N
XM"')?"')?"&]?"'(@=W)I=&5S('1H92!S=')I;F<@7PAM7PAS7PAG+`H@("`@J
XM('=I=&@@82!S=6ET86)L92!I;F1I8V%T;W(@;V8@;W)I9VEN+`H@("`@(&]N#
XM('1H92!S=&%N9&%R9`H@("`@(&5R<F]R(&]U='!U=`H@("`@(&%N9"!I;G9OP
XM:V5S(%\(95\(>%\(:5\(="@R*2X*("`@("!?"%)?"&5?"&=?"&5?"')?"')?$
XM"&]?"'(*("`@("!C86X@8F4@<F5P;&%C960@8GD@=&AE('5S97(@:68@;W1H(
XM97(@86-T:6]N<R!A<F4@9&5S:7)A8FQE+@H*4@A210A%1PA'50A53`A,00A!]
XM4@A2($4(15@(6%`(4%((4D4(15,(4U,(4TD(24\(3TX(3B!3"%-9"%E."$Y4\
XM"%1!"$%8"%@*("`@("!!(')E9W5L87(@97AP<F5S<VEO;B!I<R!Z97)O(&]RH
XM(&UO<F4@7PAB7PAR7PAA7PAN7PAC7PAH7PAE7PAS+"!S97!A<F%T960@8GD@1
XM8'PG+@H@("`@($ET(&UA=&-H97,@86YY=&AI;F<@=&AA="!M871C:&5S(&]NR
XM92!O9B!T:&4@8G)A;F-H97,N"@H@("`@($$@8G)A;F-H(&ES('IE<F\@;W(@/
XM;6]R92!?"'!?"&E?"&5?"&-?"&5?"',L(&-O;F-A=&5N871E9"X*("`@("!),
XM="!M871C:&5S(&$@;6%T8V@@9F]R('1H92!F:7)S="P@9F]L;&]W960@8GD@Z
XM82!M871C:"!F;W(@=&AE('-E8V]N9"P@971C+@H*("`@("!!('!I96-E(&ES_
XM(&%N(%\(85\(=%\(;U\(;2!P;W-S:6)L>2!F;VQL;W=E9"!B>2!@*B<L(&`K0
XM)RP@;W(@8#\G+@H@("`@($%N(&%T;VT@9F]L;&]W960@8GD@8"HG(&UA=&-H'
XM97,@82!S97%U96YC92!O9B`P(&]R(&UO<F4@;6%T8VAE<R!O9B!T:&4@871OJ
XM;2X*("`@("!!;B!A=&]M(&9O;&QO=V5D(&)Y(&`K)R!M871C:&5S(&$@<V5Q]
XM=65N8V4@;V8@,2!O<B!M;W)E(&UA=&-H97,@;V8@=&AE(&%T;VTN"B`@("`@N
XM06X@871O;2!F;VQL;W=E9"!B>2!@/R<@;6%T8VAE<R!A(&UA=&-H(&]F('1H!
XM92!A=&]M+"!O<B!T:&4@;G5L;"!S=')I;F<N"@H@("`@($%N(&%T;VT@:7,@4
XM82!R96=U;&%R(&5X<')E<W-I;VX@:6X@<&%R96YT:&5S97,@*&UA=&-H:6YGO
XM(&$@;6%T8V@@9F]R('1H90H@("`@(')E9W5L87(@97AP<F5S<VEO;BDL(&$@X
XM7PAR7PAA7PAN7PAG7PAE("AS964@8F5L;W<I+"!@+B<*("`@("`H;6%T8VAI`
XM;F<@86YY('-I;F=L92!C:&%R86-T97(I+"!@7B<@*&UA=&-H:6YG('1H92!N(
XM=6QL('-T<FEN9R!A="!T:&4*("`@("!B96=I;FYI;F<@;V8@=&AE(&EN<'5T;
XM('-T<FEN9RDL(&`D)R`H;6%T8VAI;F<@=&AE(&YU;&P@<W1R:6YG(&%T('1H.
XM90H*"@I&;W)M871T960@.#@O,3(O,S`@("`@("`@("`@("!L;V-A;"`@("`@2
XM("`@("`@("`@("`@("`@("`@("`@("`@,@H,"@H*"E)%1T584"@S*2`@("`@?
XM("`@("`@("`@("!,:6)R87)Y($9U;F-T:6]N<R`@("`@("`@("`@("`@(%)%%
XM1T584"@S*0H*"@H@("`@(&5N9"!O9B!T:&4@:6YP=70@<W1R:6YG*2P@82!@J
XM7"<@9F]L;&]W960@8GD@82!S:6YG;&4@8VAA<F%C=&5R("AM871C:&EN9PH@G
XM("`@('1H870@8VAA<F%C=&5R*2P@;W(@82!S:6YG;&4@8VAA<F%C=&5R('=I$
XM=&@@;F\@;W1H97(@<VEG;FEF:6-A;F-E"B`@("`@*&UA=&-H:6YG('1H870@L
XM8VAA<F%C=&5R*2X*"B`@("`@02!?"')?"&%?"&Y?"&=?"&4@:7,@82!S97%U$
XM96YC92!O9B!C:&%R86-T97)S(&5N8VQO<V5D(&EN(&!;72<N"B`@("`@270@(
XM;F]R;6%L;'D@;6%T8VAE<R!A;GD@<VEN9VQE(&-H87)A8W1E<B!F<F]M('1H:
XM92!S97%U96YC92X*("`@("!)9B!T:&4@<V5Q=65N8V4@8F5G:6YS('=I=&@@3
XM8%XG+`H@("`@(&ET(&UA=&-H97,@86YY('-I;F=L92!C:&%R86-T97(@7PANI
XM7PAO7PAT(&9R;VT@=&AE(')E<W0@;V8@=&AE('-E<75E;F-E+@H@("`@($EF:
XM('1W;R!C:&%R86-T97)S(&EN('1H92!S97%U96YC92!A<F4@<V5P87)A=&5D\
XM(&)Y(&`M)RP@=&AI<R!I<R!S:&]R=&AA;F0*("`@("!F;W(@=&AE(&9U;&P@_
XM;&ES="!O9B!!4T-)22!C:&%R86-T97)S(&)E='=E96X@=&AE;0H@("`@("AE)
XM+F<N(&!;,"TY72<@;6%T8VAE<R!A;GD@9&5C:6UA;"!D:6=I="DN"B`@("`@&
XM5&\@:6YC;'5D92!A(&QI=&5R86P@8%TG(&EN('1H92!S97%U96YC92P@;6%KO
XM92!I="!T:&4@9FER<W0@8VAA<F%C=&5R"B`@("`@*&9O;&QO=VEN9R!A('!O[
XM<W-I8FQE(&!>)RDN"B`@("`@5&\@:6YC;'5D92!A(&QI=&5R86P@8"TG+"!MJ
XM86ME(&ET('1H92!F:7)S="!O<B!L87-T(&-H87)A8W1E<BX*"D$(04T(34((Q
XM0DD(24<(1U4(54D(250(5%D(60H@("`@($EF(&$@<F5G=6QA<B!E>'!R97-S^
XM:6]N(&-O=6QD(&UA=&-H('1W;R!D:69F97)E;G0@<&%R=',@;V8@=&AE(&EN2
XM<'5T('-T<FEN9RP*("`@("!I="!W:6QL(&UA=&-H('1H92!O;F4@=VAI8V@@>
XM8F5G:6YS(&5A<FQI97-T+@H@("`@($EF(&)O=&@@8F5G:6X@:6X@=&AE('-AV
XM;64@<&QA8V4@("`@8G5T(&UA=&-H(&1I9F9E<F5N="!L96YG=&AS+"!O<B!M5
XM871C:`H@("`@('1H92!S86UE(&QE;F=T:"!I;B!D:69F97)E;G0@=V%Y<RP@Q
XM;&EF92!G971S(&UE<W-I97(L(&%S(&9O;&QO=W,N"@H@("`@($EN(&=E;F5R;
XM86PL('1H92!P;W-S:6)I;&ET:65S(&EN(&$@;&ES="!O9B!B<F%N8VAE<R!AM
XM<F4@8V]N<VED97)E9"!I;@H@("`@(&QE9G0M=&\M<FEG:'0@;W)D97(L('1HB
XM92!P;W-S:6)I;&ET:65S(&9O<B!@*B<L(&`K)RP@86YD(&`_)R!A<F4*("`@E
XM("!C;VYS:61E<F5D(&QO;F=E<W0M9FER<W0L(&YE<W1E9"!C;VYS=')U8W1S8
XM(&%R92!C;VYS:61E<F5D(&9R;VT@=&AE"B`@("`@;W5T97)M;W-T(&EN+"!A-
XM;F0@8V]N8V%T96YA=&5D(&-O;G-T<G5C=',@87)E(&-O;G-I9&5R960@;&5F"
XM=&UO<W0M9FER<W0N"B`@("`@5&AE(&UA=&-H('1H870@=VEL;"!B92!C:&]S/
XM96X@:7,@=&AE(&]N92!T:&%T('5S97,@=&AE(&5A<FQI97-T"B`@("`@<&]S9
XM<VEB:6QI='D@:6X@=&AE(&9I<G-T(&-H;VEC92!T:&%T(&AA<R!T;R!B92!MX
XM861E+@H@("`@($EF('1H97)E(&ES(&UO<F4@=&AA;B!O;F4@8VAO:6-E+"!TP
XM:&4@;F5X="!W:6QL(&)E(&UA9&4@:6X@=&AE('-A;64@;6%N;F5R"B`@("`@+
XM*&5A<FQI97-T('!O<W-I8FEL:71Y*2!S=6)J96-T('1O('1H92!D96-I<VEOY
XM;B!O;B!T:&4@9FER<W0@8VAO:6-E+@H@("`@($%N9"!S;R!F;W)T:"X*"B`@1
XM("`@1F]R(&5X86UP;&4L(&`H86)\82EB*F,G(&-O=6QD(&UA=&-H(&!A8F,GW
XM(&EN(&]N92!O9B!T=V\@=V%Y<RX*("`@("!4:&4@9FER<W0@8VAO:6-E(&EST
XM(&)E='=E96X@8&%B)R!A;F0@8&$G.R!S:6YC92!@86(G(&ES(&5A<FQI97(L2
XM(&%N9"!D;V5S"B`@("`@;&5A9"!T;R!A('-U8V-E<W-F=6P@;W9E<F%L;"!MD
XM871C:"P@:70@:7,@8VAO<V5N+@H@("`@(%-I;F-E('1H92!@8B<@:7,@86QRT
XM96%D>2!S<&]K96X@9F]R+`H@("`@('1H92!@8BHG(&UU<W0@;6%T8V@@:71S*
XM(&QA<W0@<&]S<VEB:6QI='DM+71H92!E;7!T>2!S=')I;F<M+7-I;F-E"B`@&
XM("`@:70@;75S="!R97-P96-T('1H92!E87)L:65R(&-H;VEC92X*"B`@("`@.
XM26X@=&AE('!A<G1I8W5L87(@8V%S92!W:&5R92!N;R!@?"=S(&%R92!P<F5SK
XM96YT(&%N9"!T:&5R92!I<R!O;FQY(&]N90H@("`@(&`J)RP@8"LG+"!O<B!@8
XM/R<L('1H92!N970@969F96-T(&ES('1H870@=&AE(&QO;F=E<W0@<&]S<VEBA
XM;&4*("`@("!M871C:"!W:6QL(&)E(&-H;W-E;BX*("`@("!3;R!@86(J)RP@A
XM<')E<V5N=&5D('=I=&@@8'AA8F)B8GDG+"!W:6QL(&UA=&-H(&!A8F)B8B<N6
XM"B`@("`@3F]T92!T:&%T(&EF(&!A8BHG(&ES('1R:65D(&%G86EN<W0@8'AAH
XM8GEA8F)B>B<L(&ET"B`@("`@=VEL;"!M871C:"!@86(G(&IU<W0@869T97(@=
XM8'@G+"!D=64@=&\@=&AE(&)E9VEN<RUE87)L:65S="!R=6QE+@H@("`@("A)L
XM;B!E9F9E8W0L('1H92!D96-I<VEO;B!O;B!W:&5R92!T;R!S=&%R="!T:&4@`
XM;6%T8V@@:7,@=&AE(&9I<G-T(&-H;VEC90H@("`@('1O(&)E(&UA9&4L(&AE!
XM;F-E('-U8G-E<75E;G0@8VAO:6-E<R!M=7-T(')E<W!E8W0@:70@979E;B!IV
XM9B!T:&ES(&QE861S('1H96T*("`@("!T;R!L97-S+7!R969E<G)E9"!A;'1E+
XM<FYA=&EV97,N*0H*4PA310A%10A%($$(04P(3%,(4T\(3PH@("`@(&5G<F5P$
XM*#$I+"!E>'!R*#$I"@H*"@H*1F]R;6%T=&5D(#@X+S$R+S,P("`@("`@("`@%
XM("`@;&]C86P@("`@("`@("`@("`@("`@("`@("`@("`@("`@(#,*#`H*"@I2.
XM14=%6%`H,RD@("`@("`@("`@("`@("`@3&EB<F%R>2!&=6YC=&EO;G,@("`@K
XM("`@("`@("`@("!214=%6%`H,RD*"@H*1`A$20A)00A!1PA'3@A.3PA/4PA39
XM5`A420A)0PA#4PA3"B`@("`@7PA27PAE7PAG7PAC7PAO7PAM7PAP(')E='5R@
XM;G,@3E5,3"!F;W(@82!F86EL=7)E"B`@("`@*%\(<E\(95\(9U\(95\(<E\(]
XM<E\(;U\(<B!P97)M:71T:6YG*2P*("`@("!W:&5R92!F86EL=7)E<R!A<F4@1
XM<WEN=&%X(&5R<F]R<RP@97AC965D:6YG(&EM<&QE;65N=&%T:6]N(&QI;6ETA
XM<RP*("`@("!O<B!A<'!L>6EN9R!@*R<@;W(@8"HG('1O(&$@<&]S<VEB;'DM8
XM;G5L;"!O<&5R86YD+@H*2`A(20A)4PA35`A43PA/4@A260A9"B`@("`@0F]TQ
XM:"!C;V1E(&%N9"!M86YU86P@<&%G92!W97)E"B`@("`@=W)I='1E;B!A="!5%
XM(&]F(%0N"B`@("`@5&AE>2!A<F4@:6YT96YD960@=&\@8F4@8V]M<&%T:6)LC
XM92!W:71H('1H92!"96QL(%8X(%\(<E\(95\(9U\(95\(>%\(<"@S*2P*("`@>
XM("!B=70@87)E(&YO="!D97)I=F5D(&9R;VT@0F5L;"!C;V1E+@H*0@A"50A5%
XM1PA'4PA3"B`@("`@16UP='D@8G)A;F-H97,@86YD(&5M<'1Y(')E9W5L87(@W
XM97AP<F5S<VEO;G,@87)E(&YO="!P;W)T86)L92!T;R!6."X*"B`@("`@5&AEY
XM(')E<W1R:6-T:6]N(&%G86EN<W0*("`@("!A<'!L>6EN9R!@*B<@;W(@8"LG/
XM('1O(&$@<&]S<VEB;'DM;G5L;"!O<&5R86YD(&ES(&%N(&%R=&EF86-T(&]F8
XM('1H90H@("`@('-I;7!L:7-T:6,@:6UP;&5M96YT871I;VXN"@H@("`@($1OG
XM97,@;F]T('-U<'!O<G0@7PAE7PAG7PAR7PAE7PAP)W,@;F5W;&EN92US97!A^
XM<F%T960@8G)A;F-H97,["B`@("`@;F5I=&AE<B!D;V5S('1H92!6."!?"')?\
XM"&5?"&=?"&5?"'A?"'`H,RDL('1H;W5G:"X*"B`@("`@1'5E('1O(&5M<&AA*
XM<VES(&]N"B`@("`@8V]M<&%C=&YE<W,@86YD('-I;7!L:6-I='DL"B`@("`@F
XM:70G<R!N;W0@<W1R:6MI;F=L>2!F87-T+@H@("`@($ET(&1O97,@9VEV92!SD
XM<&5C:6%L(&%T=&5N=&EO;B!T;R!H86YD;&EN9R!S:6UP;&4@8V%S97,@<75I4
XM8VML>2X*"@H*"@H*"@H*"@H*"@H*"@H*"@H*"@H*"@H*"@I&;W)M871T960@3
XM.#@O,3(O,S`@("`@("`@("`@("!L;V-A;"`@("`@("`@("`@("`@("`@("`@?
X+("`@("`@("`@-`H@^
X``
Xend
Xsize 8651
SHAR_EOF
echo "extracting regexp.h"
sed 's/^X//' << \SHAR_EOF > regexp.h
X/*
X * NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE
X *
X * This is NOT the original regular expression code as written by
X * Henry Spencer. This code has been modified specifically for use
X * with the STEVIE editor, and should not be used apart from compiling
X * STEVIE. If you want a good regular expression library, get the
X * original code. The copyright notice that follows is from the
X * original.
X *
X * NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE
X *
X * Definitions etc. for regexp(3) routines.
X *
X * Caveat:  this is V8 regexp(3) [actually, a reimplementation thereof],
X * not the System V one.
X */
X#define NSUBEXP  10
Xtypedef struct regexp {
X    char           *startp[NSUBEXP];
X    char           *endp[NSUBEXP];
X    char            regstart;	/* Internal use only. */
X    char            reganch;	/* Internal use only. */
X    char           *regmust;	/* Internal use only. */
X    int             regmlen;	/* Internal use only. */
X    char            program[1];	/* Unwarranted chumminess with compiler. */
X}               regexp;
X
Xextern regexp  *regcomp();
Xextern int      regexec();
Xextern void     regsub();
Xextern void     regerror();
X
X#ifndef	ORIGINAL
Xextern int      reg_ic;		/* set non-zero to ignore case in searches */
X#endif
SHAR_EOF
echo "extracting regmagic.h"
sed 's/^X//' << \SHAR_EOF > regmagic.h
X/*
X * NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE
X *
X * This is NOT the original regular expression code as written by
X * Henry Spencer. This code has been modified specifically for use
X * with the STEVIE editor, and should not be used apart from compiling
X * STEVIE. If you want a good regular expression library, get the
X * original code. The copyright notice that follows is from the
X * original.
X *
X * NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE
X *
X * The first byte of the regexp internal "program" is actually this magic
X * number; the start node begins in the second byte.
X */
X#define	MAGIC	0234
SHAR_EOF
echo "extracting regsub.c"
sed 's/^X//' << \SHAR_EOF > regsub.c
X/*
X * NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE
X *
X * This is NOT the original regular expression code as written by
X * Henry Spencer. This code has been modified specifically for use
X * with the STEVIE editor, and should not be used apart from compiling
X * STEVIE. If you want a good regular expression library, get the
X * original code. The copyright notice that follows is from the
X * original.
X *
X * NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE
X *
X * regsub
X *
X *      Copyright (c) 1986 by University of Toronto.
X *      Written by Henry Spencer.  Not derived from licensed software.
X *
X *      Permission is granted to anyone to use this software for any
X *      purpose on any computer system, and to redistribute it freely,
X *      subject to the following restrictions:
X *
X *      1. The author is not responsible for the consequences of use of
X *              this software, no matter how awful, even if they arise
X *              from defects in it.
X *
X *      2. The origin of this software must not be misrepresented, either
X *              by explicit claim or by omission.
X *
X *      3. Altered versions must be plainly marked as such, and must not
X *              be misrepresented as being the original software.
X *
X * $Log:        regsub.c,v $
X * Revision 1.2  88/04/28  08:11:25  tony
X * First modification of the regexp library. Added an external variable
X * 'reg_ic' which can be set to indicate that case should be ignored.
X * Added a new parameter to regexec() to indicate that the given string
X * comes from the beginning of a line and is thus eligible to match
X * 'beginning-of-line'.
X * 
X */
X
X#include "env.h"
X
X#ifdef  MEGAMAX
Xoverlay "regexp"
X#endif
X
X#include <stdio.h>
X#include "regexp.h"
X#include "regmagic.h"
X
X#ifndef CHARBITS
X#define UCHARAT(p)      ((int)*(unsigned char *)(p))
X#else
X#define UCHARAT(p)      ((int)*(p)&CHARBITS)
X#endif
X
X/*
X - regsub - perform substitutions after a regexp match
X */
Xvoid
Xregsub(prog, source, dest)
X    regexp         *prog;
X    char           *source;
X    char           *dest;
X{
X    register char  *src;
X    register char  *dst;
X    register char   c;
X    register int    no;
X    register int    len;
X    extern char    *strncpy();
X
X    if (prog == NULL || source == NULL || dest == NULL) {
X	regerror("NULL parm to regsub");
X	return;
X    }
X    if (UCHARAT(prog->program) != MAGIC) {
X	regerror("damaged regexp fed to regsub");
X	return;
X    }
X    src = source;
X    dst = dest;
X    while ((c = *src++) != '\0') {
X	if (c == '&')
X	    no = 0;
X	else if (c == '\\' && '0' <= *src && *src <= '9')
X	    no = *src++ - '0';
X	else
X	    no = -1;
X	if (no < 0) {		/* Ordinary character. */
X	    if (c == '\\' && (*src == '\\' || *src == '&'))
X		c = *src++;
X	    *dst++ = c;
X	} else if (prog->startp[no] != NULL && prog->endp[no] != NULL) {
X	    len = prog->endp[no] - prog->startp[no];
X	    (void) strncpy(dst, prog->startp[no], len);
X	    dst += len;
X	    if (len != 0 && *(dst - 1) == '\0') {	/* strncpy hit NUL. */
X		regerror("damaged match string");
X		return;
X	    }
X	}
X    }
X    *dst = '\0';
X}
SHAR_EOF
echo "extracting s_io.c"
sed 's/^X//' << \SHAR_EOF > s_io.c
X/*
X * s_io() - routines that do screen I/O or effect what we think is
X *          on the screen.
X *
X * By G. R. (Fred) Walter    watmath!watcgl!grwalter 
X */
X
X#include "stevie.h"
X
X/*
X * screen_ins(row, nlines, total_rows) - insert 'nlines' lines at 'row' 
X *
X * NOTE: this routine assumes it is called with valid arguments.
X */
X
Xstatic void
Xscreen_ins(row, nlines, total_rows)
X    int             row;
X    int             nlines;
X    int             total_rows;
X{
X    if (nlines < 1 || (row + nlines) > total_rows)
X	return;
X
X#ifndef T_IL_B
X    {
X	int             i;
X
X	for (i = 0; i < nlines; i++) {
X	    windgoto(row, 0);
X	    outstr(T_IL);
X	}
X    }
X#else
X    windgoto(row, 0);
X    outstr(T_IL);
X    if (nlines >= 10)
X	outchar((char) (nlines / 10 + '0'));
X    outchar((char) (nlines % 10 + '0'));
X    outstr(T_IL_B);
X#endif
X
X    /* delete any garbage that may have been shifted to the status line */
X    windgoto(total_rows - 1, 0);
X    outstr(T_EL);
X}
X
X/*
X * screen_del(row, nlines, total_rows) - delete 'nlines' lines at 'row' 
X *
X * NOTE: this routine assumes it is called with valid arguments.
X */
X
Xstatic void
Xscreen_del(row, nlines, total_rows)
X    int             row;
X    int             nlines;
X    int             total_rows;
X{
X    if (nlines < 1 || (row + nlines) > total_rows)
X	return;
X
X    /* delete any garbage that may have been on the status line */
X    windgoto(total_rows - 1, 0);
X    outstr(T_EL);
X
X#ifndef T_DL_B
X    {
X	int             i;
X
X	for (i = 0; i < nlines; i++) {
X	    windgoto(row, 0);
X	    outstr(T_DL);	/* delete a line */
X	}
X    }
X#else
X    windgoto(row, 0);
X    outstr(T_DL);
X    if (nlines >= 10)
X	outchar((char) (nlines / 10 + '0'));
X    outchar((char) (nlines % 10 + '0'));
X    outstr(T_DL_B);
X#endif
X}
X
X/*
X * screen_refresh()
X *
X * Based on the current value of Topchar, refresh the contents of the screen
X * and update Botchar.
X */
X
Xstatic void
Xscreen_refresh(type)
X    int             type;
X{
X    char           *ptr;
X    int             total_rows;
X    int             row;
X    int             col;
X    LINE           *memp;
X    LPtr            start;
X    bool_t          off_top;
X    bool_t          done;	/* if TRUE, we hit the end of the file */
X    bool_t          didline;	/* if TRUE, we finished the last line */
X    int             lno;	/* number of the line we're doing */
X    int             coff;
X    int             idx;
X    int             i;
X    int             j;
X
X    if (NumLineSizes <= 0)
X	type = NOT_VALID;
X
X    if (!RedrawingDisabled)
X	outstr(T_CI);
X
X    off_top = FALSE;
X    idx = 0;
X    row = 0;
X    total_rows = Rows - 1;
X    memp = Topchar->linep;
X
X    if ((type == VALID) || (type == VALID_TO_CURSCHAR)) {
X	j = -1;
X	for (i = 0; i < NumLineSizes; i++) {
X	    if (LinePointers[i] == memp) {
X		j = i;
X		break;
X	    }
X	    row += LineSizes[i];
X	}
X	if (j == -1) {
X	    /* Are we off the top of the screen by one line ? */
X	    if (memp->next == LinePointers[0]) {
X		i = plines(Topchar->linep->s);
X		if (i < (total_rows)) {
X		    off_top = TRUE;
X		    for (idx = NumLineSizes; idx > 0; idx--) {
X			LinePointers[idx] = LinePointers[idx - 1];
X			LineSizes[idx] = LineSizes[idx - 1];
X		    }
X		    LineSizes[idx] = (char) i;
X		    if (!RedrawingDisabled)
X			screen_ins(0, i, Rows);
X		}
X	    }
X	    row = 0;
X	} else if (j == 0 && type == VALID) {
X	    if (!RedrawingDisabled)
X		outstr(T_CV);
X	    return;
X	} else {
X	    if (!RedrawingDisabled)
X		screen_del(0, row, Rows);
X	    row = 0;
X	    for (;;) {
X		LineSizes[idx] = LineSizes[j];
X		LinePointers[idx] = LinePointers[j];
X
X		if (type == VALID_TO_CURSCHAR) {
X		    if (LinePointers[idx] == Curschar->linep) {
X			memp = LinePointers[idx];
X			break;
X		    }
X		}
X		j++;
X		if (j >= NumLineSizes) {
X		    memp = LinePointers[idx];
X		    if (memp->next != Fileend->linep) {
X			row += LineSizes[idx];
X			idx++;
X			memp = memp->next;
X		    }
X		    break;
X		}
X		row += LineSizes[idx];
X		idx++;
X	    }
X	}
X    }
X    coff = 0;
X    if (P(P_NU)) {
X	coff = 8;
X	start.linep = memp;
X	lno = cntllines(Filemem, &start);
X    }
X    didline = TRUE;
X    done = FALSE;
X
X    for (;;) {
X	ptr = format_line(memp->s, &col);
X	i = 1 + ((col - 1) / Columns);
X	if ((row + i) <= total_rows) {
X	    LinePointers[idx] = memp;
X	    LineSizes[idx++] = (char) i;
X	    if (!RedrawingDisabled) {
X		windgoto(row, 0);
X
X		if (P(P_NU))
X		    outstr(mkline(lno++));
X		outstr(ptr);
X
X		j = col + coff;
X		col = j % Columns;
X		if ((col != 0) || (j == 0)) {
X#ifdef T_END_L
X		    windgoto(row + i - 1, col);
X		    outstr(T_END_L);
X#else
X		    for (; col < Columns; col++)
X			outchar(' ');
X#endif
X		}
X	    }
X	    row += i;
X	    if (memp->next != Fileend->linep) {
X		memp = memp->next;
X	    } else {
X		done = TRUE;
X		break;
X	    }
X	    if (off_top)
X		break;
X	} else {
X	    didline = FALSE;
X	    break;
X	}
X    }
X
X    /* Do we have to do off the top of the screen processing ? */
X    if (off_top && !done) {
X	row = 0;
X	for (idx = 0; idx <= NumLineSizes && row < total_rows; idx++) {
X	    row += LineSizes[idx];
X	}
X
X	idx--;
X
X	if (row < total_rows) {
X	    done = TRUE;
X	    idx++;
X	} else if (row > total_rows) {
X	    row -= LineSizes[idx];
X	    didline = FALSE;
X	    memp = LinePointers[idx];
X	} else {
X	    didline = TRUE;
X	    memp = LinePointers[idx]->next;
X	    idx++;
X	}
X    }
X    NumLineSizes = idx;
X
X    /*
X     * If we didn't hit the end of the file, and we didn't finish the last
X     * line we were working on, then the line didn't fit. 
X     */
X    if (!done && !didline) {
X	if (!RedrawingDisabled) {
X	    /* Clear the rest of the screen. */
X#ifdef T_END_D
X	    windgoto(row, 0);
X	    outstr(T_END_D);
X#else
X	    screen_del(row, total_rows - row, Rows);
X	    windgoto(row, 0);
X#endif
X	    /* put '@'s on rows that are part of a line that's too long */
X	    for (; row < total_rows; row++)
X		outstr("@\n\r");
X	}
X	Botchar->linep = memp;
X    } else {
X	if (!RedrawingDisabled && !off_top) {
X	    /* Clear the rest of the screen. */
X#ifdef T_END_D
X	    windgoto(row, 0);
X	    outstr(T_END_D);
X#else
X	    screen_del(row, total_rows - row, Rows);
X	    windgoto(row, 0);
X#endif
X	    /* put '~'s on rows that aren't part of the file. */
X	    for (; row < total_rows; row++)
X		outstr("~\n\r");
X	}
X	if (done)		/* we hit the end of the file */
X	    *Botchar = *Fileend;
X	else
X	    Botchar->linep = memp;	/* FIX - prev? */
X    }
X
X    if (!RedrawingDisabled)
X	outstr(T_CV);
X}
X
X/*
X * s_refresh()
X *
X * Based on the current value of Curschar, (if necessary) update Topchar and
X * Botchar and refresh the screen contensts.
X */
X
Xvoid
Xs_refresh(type)
X    int             type;
X{
X    LPtr           *p;
X    LPtr           *pp;
X    int             i;
X    int             nlines;
X    int             refreshed;
X
X    refreshed = FALSE;
X
X    if (bufempty()) {		/* special case - file is empty */
X	*Topchar = *Filemem;
X	*Curschar = *Filemem;
X	screen_refresh(NOT_VALID);
X	return;
X    }
X    if (NumLineSizes < 0) {
X	type = NOT_VALID;
X    }
X    if (type != VALID) {
X	screen_refresh(type);
X	refreshed = TRUE;
X	type = VALID;
X    }
X    if (LINEOF(Curschar) < LINEOF(Topchar)) {
X	nlines = cntllines(Curschar, Topchar);
X	/*
X	 * if the cursor is above the top of the screen, put it at the top of
X	 * the screen.. 
X	 */
X	*Topchar = *Curschar;
X	Topchar->index = 0;
X	/*
X	 * ... and, if we weren't very close to begin with, we scroll so that
X	 * the line is close to the middle. 
X	 */
X	if (nlines > Rows / 3) {
X	    p = Topchar;
X	    for (i = 0; i < Rows / 3; i += plines(p->linep->s)) {
X		pp = prevline(p);
X		if (pp == NULL)
X		    break;
X		p = pp;
X	    }
X	    *Topchar = *p;
X	}
X	screen_refresh(VALID);
X    } else if (LINEOF(Curschar) >= LINEOF(Botchar)) {
X	nlines = cntllines(Botchar, Curschar);
X	/*
X	 * If the cursor is off the bottom of the screen, put it at the top
X	 * of the screen.. ... and back up 
X	 */
X	if (nlines > Rows / 3) {
X	    p = Curschar;
X	    for (i = 0; i < (2 * Rows) / 3; i += plines(p->linep->s)) {
X		pp = prevline(p);
X		if (pp == NULL)
X		    break;
X		p = pp;
X	    }
X	    *Topchar = *p;
X	} else {
X	    scrollup(nlines);
X	}
X	screen_refresh(VALID);
X    } else if (refreshed == FALSE) {
X	screen_refresh(type);
X    }
X    /* Check if we are below Botchar (this can occur). */
X    if (LINEOF(Curschar) == LINEOF(Botchar)) {
X	pp = nextline(Topchar);
X	if (pp != NULL) {
X	    Topchar->linep = pp->linep;
X	    screen_refresh(VALID);
X	}
X    } else if (LINEOF(Curschar) > LINEOF(Botchar)) {
X	nlines = cntllines(Botchar, Curschar);
X	/*
X	 * If the cursor is off the bottom of the screen, put it at the top
X	 * of the screen.. ... and back up 
X	 */
X	if (nlines > Rows / 3) {
X	    p = Curschar;
X	    for (i = 0; i < (2 * Rows) / 3; i += plines(p->linep->s)) {
X		pp = prevline(p);
X		if (pp == NULL)
X		    break;
X		p = pp;
X	    }
X	    *Topchar = *p;
X	} else {
X	    scrollup(nlines);
X	}
X	screen_refresh(VALID);
X    }
X}
X
X/*
X * s_clear() - clear the screen and mark the stored information as invalid.
X */
Xvoid
Xs_clear()
X{
X    outstr(T_ED);		/* clear the display */
X    S_NOT_VALID;
X}
X
X/*
X * Update_Botchar()
X *
X * Based on the current value of Topchar update Botchar.
X */
X
Xvoid
XUpdate_Botchar()
X{
X    int             row;
X    LINE           *memp;
X    int             total_rows;
X    int             i;
X
X    row = 0;
X    total_rows = Rows - 1;
X    memp = Topchar->linep;
X
X    for (;;) {
X	i = plines(memp->s);
X	if ((row + i) <= total_rows) {
X	    row += i;
X	    memp = memp->next;
X	    if (memp == Fileend->linep)
X		break;
X	} else {
X	    break;
X	}
X    }
X    Botchar->linep = memp;
X
X    MustUpdateBotchar = FALSE;
X}
X
X#ifdef DONTINCLUDEANYMORE
X/*
X * NotValidFromCurschar()
X *
X * Mark the lines in NumLinePointers and NumLineSizes from Curschar on as
X * not valid.
X */
X
Xvoid
XNotValidFromCurschar()
X{
X    register int    idx;
X    register unsigned long num;
X
X    S_VALID_TO_CURSCHAR;
X
X    num = LINEOF(Curschar);
X    for (idx = 0; idx < NumLineSizes; idx++) {
X	if (LinePointers[idx]->num >= num)
X	    break;
X    }
X    NumLineSizes = idx;
X}
X#endif
SHAR_EOF
echo "extracting screen.c"
sed 's/^X//' << \SHAR_EOF > screen.c
X/*
X * STEVIE - Simply Try this Editor for VI Enthusiasts
X *
X * Code Contributions By : Tim Thompson           twitch!tjt
X *                         Tony Andrews           onecom!wldrdg!tony 
X *                         G. R. (Fred) Walter    watmath!watcgl!grwalter 
X */
X
X#include "stevie.h"
X
X/*
X * The following variable is set (in cursupdate) to the number of physical
X * lines taken by the line the cursor is on. We use this to avoid extra calls
X * to plines(). The optimized routine updateline() makes sure that the size of
X * the cursor line hasn't changed. If so, lines below the cursor will move up
X * or down and we need to call the routine s_refresh() to examine the
X * entire screen. 
X */
Xstatic int      Cline_size;	/* size (in rows) of the cursor line */
Xstatic int      Cline_row;	/* starting row of the cursor line */
X
X/*
X * updateline() - like s_refresh() but only for cursor line 
X *
X * This determines whether or not we need to call s_refresh() to examine
X * the entire screen for changes. This occurs if the size of the cursor line
X * (in rows) has changed.
X */
Xstatic void
Xupdateline()
X{
X    char           *ptr;
X    int             col;
X    int             size;
X    int             j;
X
X    if (RedrawingDisabled)	/* Is this the correct action ? */
X	return;
X
X    ptr = format_line(Curschar->linep->s, &col);
X
X    size = 1 + ((col - 1) / Columns);
X    if (Cline_size == size) {
X	outstr(T_CI);
X	windgoto(Cline_row, 0);
X	if (P(P_NU)) {
X	    /*
X	     * This should be done more efficiently. 
X	     */
X	    outstr(mkline(cntllines(Filemem, Curschar)));
X	}
X	outstr(ptr);
X
X	j = col + (P(P_NU) ? 8 : 0);
X	col = j % Columns;
X	if ((col != 0) || (j == 0)) {
X#ifdef T_END_L
X	    windgoto(Cline_row + size - 1, col);
X	    outstr(T_END_L);
X#else
X	    for (; col < Columns; col++)
X		outchar(' ');
X#endif
X	}
X	outstr(T_CV);
X    } else {
X	s_refresh(VALID_TO_CURSCHAR);
X    }
X}
X
Xvoid
Xcursupdate(type)
X    int             type;
X{
X    register char   c;
X    register int    incr;
X    register int    i;
X    register int    didincr;
X
X    if (MustUpdateBotchar == TRUE)
X	Update_Botchar();
X
X    if (NumLineSizes < 0) {
X	s_refresh(NOT_VALID);
X    } else {
X        if (LineNotValid == TRUE)
X	    updateline();
X
X	if (type != UPDATE_CURSOR) {
X	    s_refresh(type);
X        } else if (ValidToCurschar == TRUE) {
X	    s_refresh(VALID_TO_CURSCHAR);
X        } else if (CheckTopcharAndBotchar == TRUE) {
X	    s_refresh(VALID);
X        }
X    }
X
X    CheckTopcharAndBotchar = FALSE;
X    MustUpdateBotchar = FALSE;
X    ValidToCurschar = FALSE;
X    LineNotValid = FALSE;
X
X    Cursrow = Curscol = Cursvcol = i = 0;
X    for (i = 0; i < NumLineSizes; i++) {
X	if (LinePointers[i] == Curschar->linep)
X	    break;
X	Cursrow += LineSizes[i];
X    }
X
X    if (P(P_NU))
X	Curscol = 8;
X
X    Cline_row = Cursrow;
X    Cline_size = LineSizes[i];
X
X    for (i = 0; i <= Curschar->index; i++) {
X	c = Curschar->linep->s[i];
X	/* A tab gets expanded, depending on the current column */
X	if (c == TAB && !P(P_LS))
X	    incr = P(P_TS) - (Cursvcol % P(P_TS));
X	else
X	    incr = chars[c].ch_size;
X	Curscol += incr;
X	Cursvcol += incr;
X	if (Curscol >= Columns) {
X	    Curscol -= Columns;
X	    Cursrow++;
X	    didincr = TRUE;
X	} else
X	    didincr = FALSE;
X    }
X    if (didincr)
X	Cursrow--;
X
X    if (c == TAB && State == NORMAL && !P(P_LS)) {
X	Curscol--;
X	Cursvcol--;
X    } else {
X	Curscol -= incr;
X	Cursvcol -= incr;
X    }
X    if (Curscol < 0)
X	Curscol += Columns;
X
X    if (set_want_col) {
X	Curswant = Cursvcol;
X	set_want_col = FALSE;
X    }
X}
SHAR_EOF
echo "extracting search.c"
sed 's/^X//' << \SHAR_EOF > search.c
X/*
X * STEVIE - Simply Try this Editor for VI Enthusiasts
X *
X * Code Contributions By : Tim Thompson           twitch!tjt
X *                         Tony Andrews           onecom!wldrdg!tony 
X *                         G. R. (Fred) Walter    watmath!watcgl!grwalter 
X */
X
X#include "stevie.h"
X/* modified Henry Spencer's regular expression routines */
X#include "regexp.h"
X
X#ifdef  MEGAMAX
Xoverlay "search"
X#endif
X
X/*
X * This file contains various searching-related routines. These fall into
X * three groups: string searches (for /, ?, n, and N), character searches
X * within a single line (for f, F, t, T, etc), and "other" kinds of searches
X * like the '%' command, and 'word' searches. 
X */
X
X/*
X * String searches 
X *
X * The actual searches are done using Henry Spencer's regular expression
X * library. 
X */
X
X#define BEGWORD "([^a-zA-Z0-9_]|^)"	/* replaces "\<" in search strings */
X#define ENDWORD "([^a-zA-Z0-9_]|$)"	/* likewise replaces "\>" */
X
Xbool_t begword;			/* does the search include a 'begin word'
X				 * match */
X
X/*
X * mapstring(s) - map special backslash sequences 
X */
Xstatic char    *
Xmapstring(s)
X    register char  *s;
X{
X    static char     ns[MAX_COLUMNS + 1];
X    register char  *p;
X
X    begword = FALSE;
X
X    for (p = ns; *s; s++) {
X	if ((*s == '(') || (*s == ')')) {
X	    *p++ = '\\';
X	    *p++ = *s;
X	    continue;
X	}
X	if (*s != '\\') {	/* not an escape */
X	    *p++ = *s;
X	    continue;
X	}
X	switch (*++s) {
X	  case '/':
X	    *p++ = '/';
X	    break;
X
X	  case '<':
X	    strcpy(p, BEGWORD);
X	    p += strlen(BEGWORD);
X	    begword = TRUE;
X	    break;
X
X	  case '>':
X	    strcpy(p, ENDWORD);
X	    p += strlen(ENDWORD);
X	    break;
X
X	  default:
X	    *p++ = '\\';
X	    *p++ = *s;
X	    break;
X	}
X    }
X    *p = NUL;
X
X    return ns;
X}
X
Xstatic LPtr    *
Xbcksearch(str)
X    char           *str;
X{
X    static LPtr     infile;
X    register LPtr  *p;
X    regexp         *prog;
X    register char  *s;
X    register int    i;
X    bool_t          want_start = (*str == '^');	/* looking for start of line? */
X    register char  *match;
X
X    /* make sure str isn't empty */
X    if (str == NULL || *str == NUL)
X	return NULL;
X
X    prog = regcomp(str);
X    if (prog == NULL) {
X	emsg("Invalid search string");
X	return NULL;
X    }
X    p = Curschar;
X    dec(p);
X
X    if (begword)		/* so we don't get stuck on one match */
X	dec(p);
X
X    i = (want_start) ? 0 : p->index;
X
X    do {
X	s = p->linep->s;
X
X	if (regexec(prog, s, TRUE)) {	/* match somewhere on line */
X
X	    if (want_start) {	/* could only have been one */
X		infile.linep = p->linep;
X		infile.index = (int) (prog->startp[0] - s);
X		free((char *) prog);
X		return (&infile);
X	    }
X	    /*
X	     * Now, if there are multiple matches on this line, we have to
X	     * get the last one. Or the last one before the cursor, if we're
X	     * on that line. 
X	     */
X
X	    match = prog->startp[0];
X
X	    while (regexec(prog, prog->endp[0], FALSE)) {
X		if ((i >= 0) && ((prog->startp[0] - s) > i))
X		    break;
X		match = prog->startp[0];
X	    }
X
X	    if ((i >= 0) && ((match - s) > i)) {
X		i = -1;
X		continue;
X	    }
X	    infile.linep = p->linep;
X	    infile.index = (int) (match - s);
X	    free((char *) prog);
X	    return (&infile);
X	}
X	i = -1;
X
X    } while ((p = prevline(p)) != NULL);
X
X    /*
X     * If wrapscan isn't set, bag the search now 
X     */
X    if (!P(P_WS)) {
X	free((char *) prog);
X	return NULL;
X    }
X    /* search backward from the end of the file */
X    p = prevline(Fileend);
X    do {
X	s = p->linep->s;
X
X	if (regexec(prog, s, TRUE)) {	/* match somewhere on line */
X
X	    if (want_start) {	/* could only have been one */
X		infile.linep = p->linep;
X		infile.index = (int) (prog->startp[0] - s);
X		free((char *) prog);
X		return (&infile);
X	    }
X	    /*
X	     * Now, if there are multiple matches on this line, we have to
X	     * get the last one. 
X	     */
X
X	    match = prog->startp[0];
X
X	    while (regexec(prog, prog->endp[0], FALSE))
X		match = prog->startp[0];
X
X	    infile.linep = p->linep;
X	    infile.index = (int) (match - s);
X	    free((char *) prog);
X	    return (&infile);
X	}
X	if (p->linep == Curschar->linep)
X	    break;
X
X    } while ((p = prevline(p)) != NULL);
X
X    free((char *) prog);
X    return NULL;
X}
X
Xstatic LPtr    *
Xfwdsearch(str)
X    char           *str;
X{
X    static LPtr     infile;
X    LPtr           *p;
X    regexp         *prog;
X    bool_t          want_start = (*str == '^');	/* looking for start of line? */
X
X    char           *s;
X    int             i;
X
X    prog = regcomp(str);
X    if (prog == NULL) {
X	emsg("Invalid search string");
X	return NULL;
X    }
X    p = Curschar;
X    i = Curschar->index + 1;
X    do {
X	s = p->linep->s + i;
X	i = 0;
X
X	if (regexec(prog, s, i == 0)) {	/* got a match */
X	    /*
X	     * If we wanted the start of a line and we aren't really there,
X	     * then a match doesn't count. 
X	     */
X	    if (want_start && (s != p->linep->s))
X		continue;
X
X	    infile.linep = p->linep;
X	    infile.index = (int) (prog->startp[0] - p->linep->s);
X	    free((char *) prog);
X	    return (&infile);
X	}
X    } while ((p = nextline(p)) != NULL);
X
X    /*
X     * If wrapscan isn't set, then don't scan from the beginning of the file.
X     * Just return failure here. 
X     */
X    if (!P(P_WS)) {
X	free((char *) prog);
X	return NULL;
X    }
X    /* search from the beginning of the file to Curschar */
X    for (p = Filemem; p != NULL; p = nextline(p)) {
X	s = p->linep->s;
X
X	if (regexec(prog, s, TRUE)) {	/* got a match */
X	    infile.linep = p->linep;
X	    infile.index = (int) (prog->startp[0] - s);
X	    free((char *) prog);
X	    return (&infile);
X	}
X	if (p->linep == Curschar->linep)
X	    break;
X    }
X
X    free((char *) prog);
X    return (NULL);
X}
X
Xstatic char    *laststr = NULL;
Xstatic int      lastsdir;
X
Xstatic LPtr    *
Xssearch(dir, str)
X    int             dir;	/* FORWARD or BACKWARD */
X    char           *str;
X{
X    LPtr           *pos;
X
X    reg_ic = P(P_IC);		/* tell the regexp routines how to search */
X
X    if (laststr != str) {
X	if (laststr != NULL)
X	    free(laststr);
X	laststr = strsave(str);
X    }
X    lastsdir = dir;
X
X    if (dir == BACKWARD)
X	pos = bcksearch(mapstring(str));
X    else
X	pos = fwdsearch(mapstring(str));
X
X    /*
X     * This is kind of a kludge, but its needed to make 'beginning of word'
X     * searches land on the right place. 
X     */
X    if (pos != NULL && begword) {
X	if (pos->index != 0)
X	    pos->index += 1;
X    }
X    return pos;
X}
X
Xbool_t
Xdosearch(dir, str)
X    int             dir;
X    char           *str;
X{
X    LPtr           *p;
X
X    S_CHECK_TOPCHAR_AND_BOTCHAR;
X
X    if ((p = ssearch(dir, str)) == NULL) {
X	msg("Pattern not found");
X	return (FALSE);
X    } else {
X	LPtr            savep;
X
X	/* if we're backing up, we make sure the line we're on */
X	/* is on the screen. */
X	setpcmark();
X	*Curschar = savep = *p;
X
X	return (TRUE);
X    }
X}
X
Xvoid
Xsearchagain(dir)
X    int             dir;
X{
X    if (laststr == NULL)
X	beep();
X    else
X	dosearch(dir, laststr);
X
X    lastsdir = dir;
X}
X
X#define OTHERDIR(x)     (((x) == FORWARD) ? BACKWARD : FORWARD)
X
Xbool_t
Xrepsearch(flag)
X    bool_t          flag;
X{
X    int             dir = lastsdir;
X    bool_t          found;
X
X    if (laststr == NULL) {
X	beep();
X	return FALSE;
X    }
X    found = dosearch(flag ? OTHERDIR(lastsdir) : lastsdir, laststr);
X
X    /*
X     * We have to save and restore 'lastsdir' because it gets munged by
X     * ssearch() and winds up saving the wrong direction from here if 'flag'
X     * is true. 
X     */
X    lastsdir = dir;
X
X    return (found);
X}
X
X/*
X * regerror - called by regexp routines when errors are detected. 
X */
Xvoid
Xregerror(s)
X    char           *s;
X{
X    emsg(s);
X}
X
X/*
X * dosub(lp, up, cmd)
X *
X * Perform a substitution from line 'lp' to line 'up' using the
X * command pointed to by 'cmd' which should be of the form:
X *
X * /pattern/substitution/g
X *
X * The trailing 'g' is optional and, if present, indicates that multiple
X * substitutions should be performed on each line, if applicable.
X * The usual escapes are supported as described in the regexp docs.
X */
X
Xvoid
Xdosub(lp, up, cmd)
X    LPtr           *lp, *up;
X    char           *cmd;
X{
X    LINE           *cp;
X    char           *pat, *sub;
X    regexp         *prog;
X    int             nsubs;
X    bool_t          do_all;	/* do multiple substitutions per line */
X    int             n;
X
X    /*
X     * If no range was given, do the current line. If only one line was
X     * given, just do that one. 
X     */
X    if (lp->linep == NULL)
X	*up = *lp = *Curschar;
X    else {
X	if (up->linep == NULL)
X	    *up = *lp;
X    }
X
X    pat = ++cmd;		/* skip the initial '/' */
X
X    while (*cmd) {
X	if (cmd[0] == '/' && cmd[-1] != '\\') {
X	    *cmd++ = NUL;
X	    break;
X	}
X	cmd++;
X    }
X
X    if (*pat == NUL) {
X	emsg("NULL pattern specified");
X	return;
X    }
X    sub = cmd;
X
X    do_all = FALSE;
X
X    while (*cmd) {
X	if (cmd[0] == '/' && cmd[-1] != '\\') {
X	    do_all = (cmd[1] == 'g');
X	    *cmd = NUL;
X	    break;
X	}
X	cmd++;
X    }
X
X    reg_ic = P(P_IC);		/* set "ignore case" flag appropriately */
X
X    prog = regcomp(pat);
X    if (prog == NULL) {
X	emsg("Invalid search string");
X	return;
X    }
X    nsubs = 0;
X
X    ResetBuffers();
X    n = RowNumber(lp);
X
X    cp = lp->linep;
X    for (; cp != Fileend->linep && cp != NULL; cp = cp->next, n++) {
X	if (regexec(prog, cp->s, TRUE)) {	/* a match on this line */
X	    char           *ns, *sns, *p;
X
X	    /*
X	     * Save the line that was last changed for the final cursor
X	     * position (just like the real vi). 
X	     */
X	    Curschar->linep = cp;
X
X	    /*
X	     * Get some space for a temporary buffer to do the substitution
X	     * into. 
X	     */
X	    sns = ns = alloc(2048);
X	    if (ns == NULL)
X		break;
X
X	    *sns = NUL;
X
X	    p = cp->s;
X
X	    do {
X		for (ns = sns; *ns; ns++);
X		/*
X		 * copy up to the part that matched 
X		 */
X		while (p < prog->startp[0])
X		    *ns++ = *p++;
X
X		regsub(prog, sub, ns);
X
X		/*
X		 * continue searching after the match 
X		 */
X		p = prog->endp[0];
X
X	    } while (regexec(prog, p, FALSE) && do_all);
X
X	    for (ns = sns; *ns; ns++);
X
X	    /*
X	     * copy the rest of the line, that didn't match 
X	     */
X	    while (*p)
X		*ns++ = *p++;
X
X	    *ns = NUL;
X
X	    AppendPositionToUndoUndobuff(0, n);
X	    AppendPositionToUndobuff(0, n);
X	    AppendToUndoUndobuff("c$");
X	    AppendToUndobuff("c$");
X	    AppendToUndoUndobuff(sns);
X	    AppendToUndobuff(cp->s);
X	    AppendToUndoUndobuff(ESC_STR);
X	    AppendToUndobuff(ESC_STR);
X
X	    free(cp->s);	/* free the original line */
X	    cp->s = strsave(sns);	/* and save the modified str */
X	    cp->size = strlen(cp->s) + 1;
X	    free(sns);		/* free the temp buffer */
X	    nsubs++;
X	}
X	if (cp == up->linep)
X	    break;
X    }
X
X    if (nsubs) {
X	CHANGED;
X	S_NOT_VALID;
X	AppendPositionToUndoUndobuff(0, 1);
X	AppendPositionToUndobuff(0, 1);
X	beginline(TRUE);
X	if (nsubs >= P(P_RP))
X	    smsg("%d substitution%c", nsubs, (nsubs > 1) ? 's' : ' ');
X    } else
X	msg("No match");
X
X    free((char *) prog);
X}
X
X/*
X * doglob(cmd)
X *
X * Execute a global command of the form:
X *
X * g/pattern/X
X *
X * where 'x' is a command character, currently one of the following:
X *
X * d    Delete all matching lines
X * p    Print all matching lines
X *
X * The command character (as well as the trailing slash) is optional, and
X * is assumed to be 'p' if missing.
X */
X
Xvoid
Xdoglob(lp, up, cmd)
X    LPtr           *lp, *up;
X    char           *cmd;
X{
X    LINE           *cp;
X
X    char           *pat;
X    regexp         *prog;
X    int             ndone;
X    char            cmdchar = NUL;	/* what to do with matching lines */
X    int             nu;
X    int             nuu = 0;
X
X    /*
X     * If no range was given, do every line. If only one line was given, just
X     * do that one. 
X     */
X    if (lp->linep == NULL) {
X	*lp = *Filemem;
X	*up = *Fileend;
X    } else {
X	if (up->linep == NULL)
X	    *up = *lp;
X    }
X
X    pat = ++cmd;		/* skip the initial '/' */
X
X    while (*cmd) {
X	if (cmd[0] == '/' && cmd[-1] != '\\') {
X	    cmdchar = cmd[1];
X	    *cmd = NUL;
X	    break;
X	}
X	cmd++;
X    }
X    if (cmdchar == NUL)
X	cmdchar = 'p';
X
X    reg_ic = P(P_IC);		/* set "ignore case" flag appropriately */
X
X    if (cmdchar != 'd' && cmdchar != 'p') {
X	emsg("Invalid command character");
X	return;
X    }
X    prog = regcomp(pat);
X    if (prog == NULL) {
X	emsg("Invalid search string");
X	return;
X    }
X    msg("");
X    ndone = 0;
X
X    nu = RowNumber(lp);
X    if (cmdchar == 'd') {
X	ResetBuffers();
X	nuu = nu;
X    }
X    cp = lp->linep;
X    for (; cp != Fileend->linep && cp != NULL; cp = cp->next, nu++) {
X	if (regexec(prog, cp->s, TRUE)) {	/* a match on this line */
X	    Curschar->linep = cp;
X	    Curschar->index = 0;
X
X	    switch (cmdchar) {
X
X	      case 'd':	/* delete the line */
X		AppendPositionToUndoUndobuff(0, nuu);
X		AppendToUndoUndobuff("dd");
X		if (buf1line() && (ndone == 0)) {
X		    AppendToUndobuff("a");
X		} else if (buf1line()) {
X		    AppendToUndobuff("j");
X		    AppendToUndobuff("I");
X		} else if (cp->next == Fileend->linep) {
X		    AppendPositionToUndobuff(0, nu);
X		    AppendToUndobuff("o");
X		} else {
X		    AppendPositionToUndobuff(0, nu);
X		    AppendToUndobuff("O");
X		}
X		AppendToUndobuff(cp->s);
X		AppendToUndobuff(ESC_STR);
X
X		delline(1);
X		break;
X
X	      case 'p':	/* print the line */
X		if (P(P_NU)) {
X		    outstr(mkline(nu));
X		}
X		outstr(T_CV);
X		outstr(format_line(cp->s, (int *) NULL));
X		outstr(T_CI);
X		outstr("\r\n");
X		break;
X	    }
X	    ndone++;
X	} else if (cmdchar == 'd') {
X	    nuu++;
X	}
X	if (cp == up->linep)
X	    break;
X    }
X
X    if (ndone) {
X	switch (cmdchar) {
X
X	  case 'd':
X	    S_NOT_VALID;
X	    AppendPositionToUndobuff(0, 1);
X	    if (ndone >= P(P_RP))
X		smsg("%d fewer line%c", ndone,
X		     (ndone > 1) ? 's' : ' ');
X	    break;
X
X	  case 'p':
X	    wait_return();
X	    break;
X	}
X	stuffReadbuff("^");
X    } else
X	msg("No match");
X
X    free((char *) prog);
X}
X
X/*
X * Character Searches 
X */
X
Xstatic char     lastc = NUL;	/* last character searched for */
Xstatic int      lastcdir;	/* last direction of character search */
Xstatic int      lastctype;	/* last type of search ("find" or "to") */
X
X/*
X * searchc(c, dir, type) 
X *
X * Search for character 'c', in direction 'dir'. If type is 0, move to the
X * position of the character, otherwise move to just before the char. 
X */
Xbool_t
Xsearchc(c, dir, type)
X    char            c;
X    int             dir;
X    int             type;
X{
X    LPtr            save;
X
X    save = *Curschar;		/* save position in case we fail */
X    lastc = c;
X    lastcdir = dir;
X    lastctype = type;
X
X    /*
X     * On 'to' searches, skip one to start with so we can repeat searches in
X     * the same direction and have it work right. 
X     */
X    if (type)
X	(dir == FORWARD) ? oneright() : oneleft();
X
X    while ((dir == FORWARD) ? oneright() : oneleft()) {
X	if (gchar(Curschar) == c) {
X	    if (type)
X		(dir == FORWARD) ? oneleft() : oneright();
X	    return TRUE;
X	}
X    }
X    *Curschar = save;
X    return FALSE;
X}
X
Xbool_t
Xcrepsearch(flag)
X    int             flag;
X{
X    int             dir = lastcdir;
X    int             rval;
X
X    if (lastc == NUL)
X	return FALSE;
X
X    rval = searchc(lastc, flag ? OTHERDIR(lastcdir) : lastcdir, lastctype);
X
X    lastcdir = dir;		/* restore dir., since it may have changed */
X
X    return rval;
X}
X
X/*
X * "Other" Searches 
X */
X
X/*
X * showmatch - move the cursor to the matching paren or brace 
X */
XLPtr           *
Xshowmatch()
X{
X    static LPtr     pos;
X    int             (*move) (), inc(), dec();
X    char            initc = gchar(Curschar);	/* initial char */
X    char            findc;	/* terminating char */
X    char            c;
X    int             count = 0;
X
X    pos = *Curschar;		/* set starting point */
X
X    switch (initc) {
X
X      case '(':
X	findc = ')';
X	move = inc;
X	break;
X      case ')':
X	findc = '(';
X	move = dec;
X	break;
X      case '{':
X	findc = '}';
X	move = inc;
X	break;
X      case '}':
X	findc = '{';
X	move = dec;
X	break;
X      case '[':
X	findc = ']';
X	move = inc;
X	break;
X      case ']':
X	findc = '[';
X	move = dec;
X	break;
X      default:
X	return (LPtr *) NULL;
X    }
X
X    while ((*move) (&pos) != -1) {	/* until end of file */
X	c = gchar(&pos);
X	if (c == initc)
X	    count++;
X	else if (c == findc) {
X	    if (count == 0)
X		return &pos;
X	    count--;
X	}
X    }
X    return (LPtr *) NULL;	/* never found it */
X}
X
X/*
X * findfunc(dir) - Find the next function in direction 'dir' 
X *
X * Return TRUE if a function was found. 
X */
Xbool_t
Xfindfunc(dir)
X    int             dir;
X{
X    LPtr           *curr;
X
X    S_CHECK_TOPCHAR_AND_BOTCHAR;
X
X    curr = Curschar;
X
X    do {
X	curr = (dir == FORWARD) ? nextline(curr) : prevline(curr);
X
X	if (curr != NULL && curr->linep->s[0] == '{') {
X	    setpcmark();
X	    *Curschar = *curr;
X	    return TRUE;
X	}
X    } while (curr != NULL);
X
X    return FALSE;
X}
X
X/*
X * The following routines do the word searches performed by the 'w', 'W',
X * 'b', 'B', 'e', and 'E' commands. 
X */
X
X/*
X * To perform these searches, characters are placed into one of three
X * classes, and transitions between classes determine word boundaries. 
X *
X * The classes are: 
X *
X * 0 - white space 1 - letters, digits, and underscore 2 - everything else 
X */
X
Xstatic int      stype;		/* type of the word motion being performed */
X
X#define C0(c)   (((c) == ' ') || ((c) == '\t') || ((c) == NUL))
X#define C1(c)   (isalpha(c) || isdigit(c) || ((c) == '_'))
X
X/*
X * cls(c) - returns the class of character 'c' 
X *
X * The 'type' of the current search modifies the classes of characters if a 'W',
X * 'B', or 'E' motion is being done. In this case, chars. from class 2 are
X * reported as class 1 since only white space boundaries are of interest. 
X */
Xstatic int
Xcls(c)
X    char            c;
X{
X    if (C0(c))
X	return 0;
X
X    if (C1(c))
X	return 1;
X
X    /*
X     * If stype is non-zero, report these as class 1. 
X     */
X    return (stype == 0) ? 2 : 1;
X}
X
X
X/*
X * fwd_word(pos, type) - move forward one word 
X *
X * Returns the resulting position, or NULL if EOF was reached. 
X */
XLPtr           *
Xfwd_word(p, type)
X    LPtr           *p;
X    int             type;
X{
X    static LPtr     pos;
X    int             sclass = cls(gchar(p));	/* starting class */
X
X    S_CHECK_TOPCHAR_AND_BOTCHAR;
X
X    pos = *p;
X
X    stype = type;
X
X    /*
X     * We always move at least one character. 
X     */
X    if (inc(&pos) == -1)
X	return NULL;
X
X    if (sclass != 0) {
X	while (cls(gchar(&pos)) == sclass) {
X	    if (inc(&pos) == -1)
X		return NULL;
X	}
X	/*
X	 * If we went from 1 -> 2 or 2 -> 1, return here. 
X	 */
X	if (cls(gchar(&pos)) != 0)
X	    return &pos;
X    }
X    /* We're in white space; go to next non-white */
X
X    while (cls(gchar(&pos)) == 0) {
X	/*
X	 * We'll stop if we land on a blank line 
X	 */
X	if (pos.index == 0 && pos.linep->s[0] == NUL)
X	    break;
X
X	if (inc(&pos) == -1)
X	    return NULL;
X    }
X
X    return &pos;
X}
X
X/*
X * bck_word(pos, type) - move backward one word 
X *
X * Returns the resulting position, or NULL if top-of-file was reached. 
X */
XLPtr           *
Xbck_word(p, type)
X    LPtr           *p;
X    int             type;
X{
X    static LPtr     pos;
X    int             sclass = cls(gchar(p));	/* starting class */
X
X    S_CHECK_TOPCHAR_AND_BOTCHAR;
X
X    pos = *p;
X
X    stype = type;
X
X    if (dec(&pos) == -1)
X	return NULL;
X
X    /*
X     * If we're in the middle of a word, we just have to back up to the start
X     * of it. 
X     */
X    if (cls(gchar(&pos)) == sclass && sclass != 0) {
X	/*
X	 * Move backward to start of the current word 
X	 */
X	while (cls(gchar(&pos)) == sclass) {
X	    if (dec(&pos) == -1)
X		return NULL;
X	}
X	inc(&pos);		/* overshot - forward one */
X	return &pos;
X    }
X    /*
X     * We were at the start of a word. Go back to the start of the prior
X     * word. 
X     */
X
X    while (cls(gchar(&pos)) == 0) {	/* skip any white space */
X	/*
X	 * We'll stop if we land on a blank line 
X	 */
X	if (pos.index == 0 && pos.linep->s[0] == NUL)
X	    return &pos;
X
X	if (dec(&pos) == -1)
X	    return NULL;
X    }
X
X    sclass = cls(gchar(&pos));
X
X    /*
X     * Move backward to start of this word. 
X     */
X    while (cls(gchar(&pos)) == sclass) {
X	if (dec(&pos) == -1)
X	    return NULL;
X    }
X    inc(&pos);			/* overshot - forward one */
X
X    return &pos;
X}
X
X/*
X * end_word(pos, type) - move to the end of the word 
X *
X * There is an apparent bug in the 'e' motion of the real vi. At least on the
X * System V Release 3 version for the 80386. Unlike 'b' and 'w', the 'e'
X * motion crosses blank lines. When the real vi crosses a blank line in an
X * 'e' motion, the cursor is placed on the FIRST character of the next
X * non-blank line. The 'E' command, however, works correctly. Since this
X * appears to be a bug, I have not duplicated it here. 
X *
X * Returns the resulting position, or NULL if EOF was reached. 
X */
XLPtr           *
Xend_word(p, type)
X    LPtr           *p;
X    int             type;
X{
X    static LPtr     pos;
X    int             sclass = cls(gchar(p));	/* starting class */
X
X    S_CHECK_TOPCHAR_AND_BOTCHAR;
X
X    pos = *p;
X
X    stype = type;
X
X    if (inc(&pos) == -1)
X	return NULL;
X
X    /*
X     * If we're in the middle of a word, we just have to move to the end of
X     * it. 
X     */
X    if (cls(gchar(&pos)) == sclass && sclass != 0) {
X	/*
X	 * Move forward to end of the current word 
X	 */
X	while (cls(gchar(&pos)) == sclass) {
X	    if (inc(&pos) == -1)
X		return NULL;
X	}
X	dec(&pos);		/* overshot - forward one */
X	return &pos;
X    }
X    /*
X     * We were at the end of a word. Go to the end of the next word. 
X     */
X
X    while (cls(gchar(&pos)) == 0) {	/* skip any white space */
X	if (inc(&pos) == -1)
X	    return NULL;
X    }
X
X    sclass = cls(gchar(&pos));
X
X    /*
X     * Move forward to end of this word. 
X     */
X    while (cls(gchar(&pos)) == sclass) {
X	if (inc(&pos) == -1)
X	    return NULL;
X    }
X    dec(&pos);			/* overshot - forward one */
X
X    return &pos;
X}
SHAR_EOF
echo "End of archive 5 (of 6)"
# if you want to concatenate archives, remove anything after this line
exit