SWAGOLX.EXE (c) 1993 GDSOFT ALL RIGHTS RESERVED 00013 TEXT EDITING ROUTINES 1 05-28-9314:08ALL SWAG SUPPORT TEAM Center Text IMPORT 5 F╔╧x {π>Anyways, does anyone here have a quick and easy Procedure orπ>Function For centering Text?π}ππProgram CenterIt_Demo;ππUsesπ Crt;ππ{ Display a String centered on the screen. }πProcedure DisplayCenter(st_Temp : String; by_Yaxis : Byte);πbeginπ GotoXY(((Succ(Lo(WindMax)) - Length(st_Temp)) div 2), by_Yaxis);π Writeln(st_Temp);πend; {DisplayCenter. }ππVarπ by_OldAttr : Byte;ππbeginπ ClrScr;π DisplayCenter('The Spirit of Elvis says... Hi!', 10);π ReadKey;πend.π 2 05-28-9314:08ALL SWAG SUPPORT TEAM Another Center Text IMPORT 3 F╔╠V { Center Text }ππUses Crt;πVarπ s : String;π i : Integer;πbeginπ Write('String? ');π readln(s);π i := (succ(lo(windmax)) - length(s)) shr 1;π gotoXY(i,10);π Write(s);πend.π 3 05-28-9314:08ALL CHRIS BRATENE Force Text Format IMPORT 14 F╔8ë {π> - How can I get TP to make what ever the user enters in to CAPS or │π> NONCAPS? Example: │π> Enter Name -> ChRiS BrAtEnE │π> Your name is Chris Bratene? (Y/n)? │πππI just wrote a routine that does this on the fly, so to speak, Forπanother user, and I haven't erased it yet, so here it is (slightlyπmodified, so that it Forces lowerCase, too):π}ππUsesπ Crt;ππProcedure Backspace;πbeginπ Write(#8' '#8)πend;ππFunction LoCase(ch : Char) : Char;πbeginπ if ch in ['A'..'Z'] thenπ LoCase := Char(ord(ch)+32)π elseπ LoCase := ch;πend;ππProcedure Dibble(Var st : String);π{ Forces upperCase For first letter in each Word,π lowerCase For other letters. }πVarπ len : Byte Absolute st;π ch : Char;ππ Function ForceCap : Boolean;π beginπ ForceCap := (len = 0) or (st[len] = ' ');π end;ππbeginπ st := '';π Repeatπ ch := ReadKey;π if ForceCap thenπ ch := upCase(ch)π elseπ ch := LoCase(ch);π Case ch ofπ #8 : if len > 0 thenπ beginπ Backspace;π dec(len);π end;π #27 : While len > 0 doπ beginπ BackSpace;π dec(len);π end;π #0 : ch := ReadKey;ππ elseπ beginπ Write(ch);π st := st + ch;π end;ππ end;π Until ch in [#13,#27];ππ Writeln;ππend;πππVarπ st : String;ππbegin { test }π Writeln;π Write('Enter String: ');π Dibble(st);π Writeln(st);πend.π 4 05-28-9314:08ALL SWAG SUPPORT TEAM Word wrap #1 IMPORT 12 F╔á {This was a Programming contest Program- BTW, this is to VanπSlingerhead, not to Mike...π}πProgram Wordwrap; πUses Crt,Printer; πConstπ max = 10; πVarπ ch : Char;π arr : Array[1..800] of Char;π small,π s : String;π w,π len,π counter : Integer; πbeginπ w := 1;π Writeln; Writeln;π Repeatπ arr[w] := ReadKey;π inc(w);π if arr[w-1] = #8 thenπ beginπ Write(#8' '#8);π if w > 2 thenπ dec(w,2)π elseπ w:= 1;π end { if }π elseπ Write(arr[w-1]);π Until arr[w-1] = #13;π arr[w-1] := ' ';ππ dec(w);π Writeln; Writeln;π For counter := 1 to w doπ Write(arr[counter]);ππ small := '';π len := 0;π Writeln(lst);π Writeln(lst,'123456789012345678901234567890123456789012345');π Writeln(lst,' ^ ^ ^ ^ ^');π For counter := 1 to w doπ beginπ if arr[counter] <> ' ' thenπ beginπ small := small + arr[counter];π inc(len);π endπ elseπ if len <= 45 thenπ beginπ Write(lst,small,' ');π small := '';π inc(len);π endπ elseπ beginπ Writeln(lst);π Write(lst,small,' ');π len := length(small)+1;π small := '';π end; { else }π end; πend.ππ 5 05-28-9314:08ALL SWAG SUPPORT TEAM Word Wrap #2 IMPORT 18 F╔a╞ {π> P.S. A pre-made Unit to do a Word-wrap Function might also be nice.π}ππUnit WordWrap;ππInterfaceππUsesπ Crt;ππTypeπ Strn80 = String[80];ππConstπ MaxWordLineLength : Byte = 80;ππVarπ WordLine : Strn80;π Index1 : Byte;π Index2 : Byte;ππProcedure ResetWrapStrn;πProcedure WrapStrn (InputStrn: Strn80);ππImplementationππProcedure ResetWrapStrn;πbeginπ Index1 := 0;π Index2 := 0;π Wordline := '';πend;ππProcedure WrapStrn (InputStrn: Strn80);πVarπ Count : Byte;π InputChar : Char;πbeginπ For Count := 1 to Length (InputStrn) doπ beginπ InputChar := InputStrn[Count];π Case InputChar OFπ ^H: {Write destructive backspace & remove Char from WordLine}π beginπ Write(^H,' ',^H);π DELETE(WordLine,(LENGTH(WordLine) - 1),1)π end;π #0: {user pressed a Function key, so dismiss it}π beginπ InputChar := ReadKey; {Function keys send two-Char scan code!}π InputChar := ' 'π end;π #13: { it is an enter key.. reset everything and start on a new line}π beginπ Writeln;π Index1 := 0; Index2 := 0; Wordline := '';π end;π else {InputChar contains a valid Char, so deal With it}π beginπ Write(InputChar);π WordLine := (WordLine + InputChar);π if (LENGTH(WordLine) >= (MaxWordLineLength - 1)) thenπ {we have to do a Word-wrap}π beginπ Index1 := (MaxWordLineLength - 1);π While ((WordLine[Index1] <> ' ') and (WordLine[Index1] <> '-')π and (Index1 <> 0)) DOπ Index1 := (Index1 - 1);π if (Index1 = 0) then {whoah, no space was found to split line!}π Index1 := (MaxWordLineLength - 1); {forces split}π DELETE(WordLine,1,Index1);π For Index2 := 1 to LENGTH(WordLine) DOπ Write(^H,' ',^H);π Writeln;π Write(WordLine)π endπ endπ end; {CASE InputChar}π end;πend;ππbegin {WordWrap}π{Initialize the Program.}πWordLine := '';πIndex1 := 0;πIndex2 := 0;πend.π 6 05-28-9314:08ALL SWAG SUPPORT TEAM Word Wrap #3 IMPORT 28 F╔╠₧ Varπ S : String;ππFunction Wrap(Var st: String; maxlen: Byte; justify: Boolean): String;π { returns a String of no more than maxlen Characters With the last }π { Character being the last space beFore maxlen. On return st now has }π { the remaining Characters left after the wrapping. }π Constπ space = #32;π Varπ len : Byte Absolute st;π x,π oldlen,π newlen : Byte;ππ Function JustifiedStr(s: String; max: Byte): String;ππ { Justifies String s left and right to length max. if there is more }π { than one trailing space, only the right most space is deleted. The}π { remaining spaces are considered "hard". #255 is used as the Char }π { used For padding purposes. This will enable easy removal in any }π { editor routine. }ππ Constπ softSpace = #255;π Varπ jstr : String;π len : Byte Absolute jstr;π beginπ jstr := s;π While (jstr[1] = space) and (len > 0) do { delete all leading spaces }π delete(jstr,1,1);π if jstr[len] = space thenπ dec(len); { Get rid of trailing space }π if not ((len = max) or (len = 0)) then beginπ x := pos('.',jstr); { Attempt to start padding at sentence break }π if (x = 0) or (x =len) then { no period or period is at length }π x := 1; { so start at beginning }π if pos(space,jstr) <> 0 then Repeat { ensure at least 1 space }π if jstr[x] = space then { so add a soft space }π insert(softSpace,jstr,x+1);π x := succ(x mod len); { if eoln is reached return and do it again }π Until len = max; { Until the wanted String length is achieved }π end; { if not ... }π JustifiedStr := jstr;π end; { JustifiedStr }πππ begin { Wrap }π if len <= maxlen then begin { no wrapping required }π Wrap := st;π len := 0;π end else beginπ oldlen := len; { save the length of the original String }π len := succ(maxlen); { set length to maximum }π Repeat { find last space in st beFore or at maxlen }π dec(len);π Until (st[len] = space) or (len = 0);π if len = 0 then { no spaces in st, so chop at maxlen }π len := maxlen;π if justify thenπ Wrap := JustifiedStr(st,maxlen)π elseπ Wrap := st;π newlen := len; { save the length of the newly wrapped String }π len := oldlen; { and restore it to original length beFore }π Delete(st,1,newlen); { getting rid of the wrapped portion }π end;π end; { Wrap }ππbeginπ S :=π'By Far the easiest way to manage a database is to create an '+π'index File. An index File can take many Forms and its size will depend '+π'upon how many Records you want in the db. The routines that follow '+π'assume no more than 32760 Records.';ππWhile length(S) <> 0 doπ Writeln(Wrap(S,60,True));πend.ππWhilst this is tested and known to work on the example String, no furtherπtesting than that has been done. I suggest you test it a great deal moreπbeFore being satisfied that it is OK.ππ 7 08-17-9308:51ALL SWAG SUPPORT TEAM Text Wrapping and JustifyIMPORT 28 F╔π≈ Uses CRT;πvarπ S : string;ππfunction Wrap(var st: string; maxlen: byte; justify: boolean): string;π { returns a string of no more than maxlen characters with the last }π { character being the last space before maxlen. On return st now has }π { the remaining characters left after the wrapping. }π constπ space = #32;π varπ len : byte absolute st;π x,π oldlen,π newlen : byte;ππ function JustifiedStr(s: string; max: byte): string;ππ { Justifies string s left and right to length max. If there is more }π { than one trailing space, only the right most space is deleted. The}π { remaining spaces are considered "hard". #255 is used as the char }π { used for padding purposes. This will enable easy removal in any }π { editor routine. }ππ constπ softSpace = #255;π varπ jstr : string;π len : byte absolute jstr;π beginπ jstr := s;π while (jstr[1] = space) and (len > 0) do { delete all leading spaces }π delete(jstr,1,1);π if jstr[len] = space thenπ dec(len); { Get rid of trailing space }π if not ((len = max) or (len = 0)) then beginπ x := pos('.',jstr); { Attempt to start padding at sentence break }π if (x = 0) or (x =len) then { no period or period is at length }π x := 1; { so start at beginning }π if pos(space,jstr) <> 0 then repeat { ensure at least 1 space }π if jstr[x] = space then { so add a soft space }π insert(softSpace,jstr,x+1);π x := succ(x mod len); { if eoln is reached return and do it again }π until len = max; { until the wanted string length is achieved }π end; { if not ... }π JustifiedStr := jstr;π end; { JustifiedStr }πππ begin { Wrap }π if len <= maxlen then begin { no wrapping required }π Wrap := st;π len := 0;π end else beginπ oldlen := len; { save the length of the original string }π len := succ(maxlen); { set length to maximum }π repeat { find last space in st before or at maxlen }π dec(len);π until (st[len] = space) or (len = 0);π if len = 0 then { no spaces in st, so chop at maxlen }π len := maxlen;π if justify thenπ Wrap := JustifiedStr(st,maxlen)π elseπ Wrap := st;π newlen := len; { save the length of the newly wrapped string }π len := oldlen; { and restore it to original length before }π Delete(st,1,newlen); { getting rid of the wrapped portion }π end;π end; { Wrap }ππbeginπ S :=π'By far the easiest way to manage a database is to create an '+π'index file. An index file can take many forms and its size will depend '+π'upon how many records you want in the db. The routines that follow '+π'assume no more than 32760 records.';ππwhile length(S) <> 0 doπ writeln(Wrap(S,75,true));πReadkey;πend.ππWhilst this is tested and known to work on the example string, no furtherπtesting than that has been done. I suggest you test it a great deal moreπbefore being satisfied that it is OK.ππ 8 08-27-9322:12ALL BRIAN PAPE Write String in ASM IMPORT 9 F╔}f {πBRIAN PAPEππOk, I was writing a little program that I was trying to make as small asπpossible, so I wrote this little WriteString function. Since I'm not anπassembly language mogul by any stretch of the imagination, could one ofπyou assembly wizards out there tell me if this is Ok. I mean, it worksπfine (and saves almost 1k over linking in the writeln code), but I wantπto make sure that I'm not trashing a register or something that needs toπbe preserved. Thanks... BTW, anybody, go ahead and use it if itπdoesn't crash!π}ππprocedure WriteString(s : string); assembler;πasmπ push dsπ mov ah, 40h { DOS fcn call 40h write string to file handle }ππ mov dx, seg sπ mov ds, dxπ mov bx, offset sππ mov dx, bx { now put the offset into dx for the fcn call }π inc dx { plus 1, to avoid the length byte }π mov cl, [bx] { cl is length to write }π xor ch, chππ mov bx, 1 { file handle to write to }π int 21hπ pop dsπend;ππ 9 02-03-9407:05ALL MIKE COPELAND Text Word Wrap IMPORT 25 F╔ƒΓ π{π Here's some code I found in this echo a number of years ago - I don'tπrecall who should get credit for it. I put it into my own program,πwhich uses some other Units, and I hope I've sanitized it enough to makeπit generic...ππUses a FASTWRITE routine that can be found in SWAG G.D. 02/01/94 }πππprogram WordWrap;πuses CRT;πconstπ FKeyCode = #00;π Space = ' ';π Hyphen = '-';π BackSpace = #08;π C_R = #13;π MaxWordLineLength = 60;π MAXLINES = 6; { Maximum # of lines in "box" }πvarπ WordLine : string[MaxWordLineLength];π Index1 : byte;π Index2 : byte;π InputChar : char;π LINE : byte; { current output line }π LC : byte; { Line Count }π I : Word;π S1 : string;π LA : array[1..MAXLINES] of string[MaxWordLineLength];πbeginπ WordLine := ''; Index1 := 0; Index2 := 0; InputChar := Space;π ClrScr; Write ('Enter text (',MAXLINES:0,' line maximum): ');π for I := 1 to MAXLINES do { clear storage array }π LA[I] := '';π InputChar := ReadKey;π LC := 1; LINE := 6; gotoXY (1,20); { work area }π while LC <= MAXLINES doπ beginπ case InputChar ofπ #13 : begin { C/R - terminate line }π S1 := WordLine;π Writeln (S1); LA[LC] := S1; Inc(LC);π gotoXY (1,20); ClrEol; WordLine := ''π end;π BackSpace:π beginπ Write(BackSpace,Space,BackSpace);π if Length(WordLine) > 0 then Dec(WordLine[0])π end;π FKeyCode: { flush function key }π beginπ InputChar := ReadKey; InputChar := Spaceπ endπ else { valid char }π beginπ Write(InputChar); WordLine := WordLine+InputChar;π if (Length(WordLine) >= (MaxWordLineLength - 1)) thenπ begin { have to do a word-wrap }π Index1 := MaxWordLineLength-1;π while ((WordLine[Index1] <> Space) andπ (WordLine[Index1] <> Hyphen) andπ (Index1 <> 0))π do Dec(Index1);π if (Index1 = 0) then {no space was found to split!}π Index1 := (MaxWordLineLength-1); {forces split}π S1 := Copy(WordLine,1,Index1);π Delete(WordLine,1,Index1);π for Index2 := 1 TO LENGTH(WordLine) doπ Write(BackSpace,Space,BackSpace);π FastWrite (1,LINE,LONORM,S1); Inc(LINE);π LA[LC] := S1; Inc(LC);π gotoXY (1,20) ClrEol; Write(WordLine)π endπ endπ end; {case InputChar}π InputChar := ReadKey {Get next key from user}π end; {while (InputChar <> CarriageReturn)}πend.π 10 02-03-9416:07ALL SWAG SUPPORT TEAM Justification Routine IMPORT 23 F╔═
UNIT JUSTIFY;ππINTERFACEππPROCEDURE JustifyLine (VAR LINE : STRING; Printwidth : BYTE);ππIMPLEMENTATIONππPROCEDURE JustifyLine (VAR LINE : STRING; Printwidth : BYTE);π{ justify line to a length of printwidth by putting extra blanks betweenπ words, from right to left. The line currently has one blank between words.}ππVARπ blanks, {# of blanks to be inserted}π gaps, {# of gaps between words}π n, {amount to expand 1 gap}π dest, {new place for moved char}π source : INTEGER; {source column of that char}π len : BYTE ABSOLUTE Line;ππBEGIN {justify}ππ IF (LINE > '') AND (len < printwidth) THENπ BEGINπ {set hard spaces for indents}π source := 1;π WHILE (LINE [source] = ' ') AND (source < len) DOπ BEGINπ LINE [source] := #0;π INC(source);π END;ππ {count # of gaps between words}π gaps := 0;π FOR source := 1 TO len DOπ IF LINE [source] = ' ' THEN gaps := SUCC (gaps);ππ {find # of blanks needed to stretch the line}π blanks := printwidth - len;π {shift characters to the right, distributing extra blanks}π {between the words (in the gaps)}π dest := printwidth;π source := len;π WHILE gaps > 0 DOπ BEGIN {expand line}π IF LINE [source] <> ' ' THENπ BEGIN {shift char}π LINE [dest] := LINE [source]; {move char, leave blank}π LINE [source] := ' ';π ENDπ ELSEπ BEGIN {leave blanks}π {find # of blanks for this gap, skip that many}π {(now blank) columns}π n := blanks DIV gaps;π dest := dest - n;π gaps := PRED (gaps);π blanks := blanks - n;π END;π {step to next source and dest characters}π source := PRED (source);π dest := PRED (dest)π END; {expand line}ππ LINE[0] := CHR(printwidth);π FOR source := 1 TO len DOπ IF LINE [source] = #0 THEN LINE [source] := #32;π END;ππ END; {justify procedure}πEND. 11 04-06-9407:44ALL SEAN PALMER 7K Text Editor (GHOSTED) IMPORT 84 F╔¼s {πSEAN PALMERππ> Can anyone (please, it's important) , post here an example of a sourceπ> code that will show a Text File , and let me scroll it (Up , Down ) ?π> Also I need an example of a simple editor.ππTry this For an example. Turbo Pascal 6.0+ source.πCompiles to a 7K Text editor. Neat?π}ππ{$A-,B-,D-,E-,F-,G-,I-,L-,N-,O-,R-,S-,V-,X+}π{$M $C00,0,0}ππProgram ghostEd; {Ghost Editor v0.4 (C) 1993 Sean L. Palmer}ππConstπ version = '0.4';π maxF = $3FFF; {only handles small Files!}π txtColor = $B;π vSeg : Word = $B800;ππVarπ nLines : Byte;π halfPage : Byte;π txt : Array [0..maxF] of Char;π crs,π endF,π pgBase,π lnBase : Integer;π x, y : Word;π update : Boolean;π theFile : File;π ticks : Word Absolute $40 : $6C; {ticks happen 18.2 times/second}ππProcedure syncTick;πVarπ i : Word;πbeginπ i := ticks;π Repeat Until i <> ticks;πend;ππFunction readKey : Char; Assembler;πAsmπ mov ah, $07π int $21πend;ππFunction keyPressed : Boolean; Assembler;πAsmπ mov ah, $Bπ int $21π and al, $FEπend;ππProcedure moveScrUp(s, d, n : Word); Assembler;πAsmπ mov cx, nπ push dsπ mov ax, vSegπ mov es, axπ mov ds, axπ mov si, sπ shl si, 1π mov di, dπ shl di, 1π cldπ repz movsw {attr too!}π pop dsπ @X:πend;ππProcedure moveScrDn(s, d, n : Word); Assembler;πAsmπ mov cx, nπ push dsπ mov ax, vSegπ mov es, axπ mov ds, axπ mov si, sπ add si, cxπ shl si, 1π mov di, dπ add di, cxπ shl di, 1π stdπ repz movsw {attr too!}π pop dsπ @X:πend;ππProcedure moveScr(Var s; d, n : Word); Assembler;πAsmπ mov cx, nπ jcxz @Xπ push dsπ mov ax, vSegπ mov es, axπ mov di, dπ shl di, 1π lds si, sπ cldπ @L:π movsbπ inc diπ loop @Lπ pop dsπ @X:πend;ππProcedure fillScr(d, n : Word; c : Char); Assembler;πAsmπ mov cx, nπ jcxz @Xπ mov ax, vSegπ mov es, axπ mov di, dπ shl di, 1π mov al, cπ cldπ @L:π stosbπ inc diπ loop @Lπ @X:πend;ππProcedure fillAttr(d, n : Word; c : Byte); Assembler;πAsmπ mov cx, nπ jcxz @Xπ mov ax, vSegπ mov es, axπ mov di, dπ shl di, 1π mov al, cπ cldπ @L:π inc diπ stosbπ loop @Lπ @X:πend;ππProcedure cls;πbeginπ fillAttr(80, pred(nLines) * 80, txtColor);π fillScr(80, pred(nLines) * 80, ' ');πend;ππProcedure scrollUp;πbeginπ moveScrUp(320, 160, pred(nLines) * 160);π fillScr(pred(nLines) * 160, 80, ' ');πend;ππProcedure scrollDn;πbeginπ moveScrDn(160, 320, pred(nLines) * 320);π fillScr(160, 80, ' ');πend;ππ{put cursor after preceding CR or at 0}πFunction scanCrUp(i : Integer) : Integer; Assembler;πAsmπ mov di, iπ mov cx, diπ add di, offset txtπ mov ax, dsπ mov es, axπ std;π mov al, $Dπ dec diπ repnz scasbπ jnz @Sπ inc diπ @S:π inc diπ sub di, offset txtπ mov ax, diπend;ππ{put cursor on next CR or endF}πFunction scanCrDn(i:Integer):Integer;Assembler;Asmπ mov di, iπ mov cx, endFπ sub cx, diπ inc cxπ add di, offset txtπ mov ax, dsπ mov es, axπ cldπ mov al, $Dπ repnz scasbπ dec diπ sub di, offset txtπ mov ax, diπend;ππProcedure findxy;πbeginπ lnBase := scanCrUp(crs);π x := crs - lnBase;π y := 1;π pgBase := lnBase;π While (pgBase > 0) and (y < halfPage) doπ beginπ pgBase := scanCrUp(pred(pgBase));π inc(y);π end;πend;ππProcedure display;πVarπ i, j, k, oldY : Integer;πbeginπ findXY;π if update thenπ beginπ update := False;π j := pgBase;π i := 1;π While (j <= endf) and (i < pred(nLines)) doπ beginπ k := scanCrDn(j);π moveScr(txt[j], i * 80, k - j);π fillScr(i * 80 + k - j, 80 - k + j, ' ');π fillAttr(i * 80, 80, txtColor);π j := succ(k);π inc(i);π end;π if i < pred(nLines) thenπ beginπ fillScr(i * 80, 80 * pred(nLines - i), 'X');π fillAttr(i * 80, 80 * pred(nLines - i), 1);π end;π endπ elseπ beginπ i := scanCrDn(lnBase) - lnBase;π moveScr(txt[lnBase], y * 80, i);π fillScr(y * 80 + i, 80 - i, ' ');π end;πend;ππProcedure title;πConstπ menuStr : String = 'Ghost Editor v' + version + '-(C) Sean Palmer 1993';πbeginπ fillAttr(0, 80, $70);π fillScr(0, 80, ' ');π MoveScr(MenuStr[1], 1, length(MenuStr));πend;ππProcedure error(s : String);πbeginπ fillattr(0, 80, $CE);π fillScr(0, 80, ' ');π moveScr(s[1], 1, length(s));π Write(^G);π ReadKey;π title;πend;ππProcedure tooBigErr;πbeginπ error('File too big');πend;ππProcedure insChar(c : Char); forward;πProcedure delChar; forward;πProcedure backChar; forward;ππProcedure trimLine;πVarπ i, t, b : Integer;πbeginπ i := crs;π b := scanCrDn(crs);π t := scanCrUp(crs);π crs := b;π While txt[crs] = ' ' doπ beginπ delChar;π if i > crs thenπ dec(i);π if crs > 0 thenπ dec(crs);π end;π crs := i;πend;ππProcedure checkWrap(c : Integer);πVarπ i, t, b : Integer;πbeginπ b := scanCrDn(c);π t := scanCrUp(c);π i := b;π if i - t >= 79 thenπ beginπ i := t + 79;π Repeatπ dec(i);π Until (txt[i] = ' ') or (i = t);π if i = t thenπ backChar {just disallow lines that long With no spaces}π elseπ beginπ txt[i] := ^M; {change sp into cr, to wrap}π update := True;π if (b < endF) and (txt[b] = ^M) and (txt[succ(b)] <> ^M) thenπ beginπ txt[b] := ' '; {change cr into sp, to append wrapped part to nextπline} checkWrap(b); {recursively check next line since it got stuffπadded} end;π end;π end;πend;ππProcedure changeLines;πbeginπ trimLine;π update := True; {signal to display to redraw}πend;ππProcedure insChar(c : Char);πbeginπ if endf = maxF thenπ beginπ tooBigErr;π exit;π end;π move(txt[crs], txt[succ(crs)], endf - crs);π txt[crs] := c;π inc(crs);π inc(endf);π if c = ^M thenπ changeLines;π checkWrap(crs);πend;ππProcedure delChar;πbeginπ if crs = endf thenπ Exit;π if txt[crs] = ^M thenπ changeLines;π move(txt[succ(crs)], txt[crs], endf - crs);π dec(endf);π checkWrap(crs);πend;ππProcedure addLF;πVarπ i : Integer;πbeginπ For crs := endF downto 1 doπ if txt[pred(crs)] = ^M thenπ beginπ insChar(^J);π dec(crs);π end;πend;ππProcedure stripLF;πVarπ i : Integer;πbeginπ For crs := endF downto 0 doπ if txt[crs] = ^J thenπ delChar;πend;ππProcedure WriteErr;πbeginπ error('Write Error');πend;ππProcedure saveFile;πbeginπ addLF;π reWrite(theFile, 1);π if ioresult <> 0 thenπ WriteErrπ elseπ beginπ blockWrite(theFile, txt, endf);π if ioresult <> 0 thenπ WriteErr;π close(theFile);π end;πend;ππProcedure newFile;πbeginπ crs := 0;π endF := 0;π update := True;πend;ππProcedure readErr;πbeginπ error('Read Error');πend;ππProcedure loadFile;πVarπ i, n : Integer;πbeginπ reset(theFile, 1);π if ioresult <> 0 thenπ newFileπ elseπ beginπ n := Filesize(theFile);π if n > maxF thenπ beginπ tooBigErr;π n := maxF;π end;π blockread(theFile, txt, n, i);π if i < n thenπ readErr;π close(theFile);π crs := 0;π endf := i;π update := True;π stripLF;π end;πend;ππProcedure signOff;πVarπ f : File;π i, n : Integer;πbeginπ assign(f, 'signoff.txt');π reset(f, 1);π if ioresult <> 0 thenπ error('No SIGNOFF.TXT defined') {no macro defined}π elseπ beginπ n := Filesize(f);π blockread(f, txt[endF], n, i);π if i < n thenπ readErr;π close(f);π inc(endf, i);π update := True;π i := crs;π stripLF;π crs := i; {stripLF messes With crs}π end;πend;ππProcedure goLf;πbeginπ if crs > 0 thenπ dec(crs);π if txt[crs] = ^M thenπ changeLines;πend;ππProcedure goRt;πbeginπ if txt[crs] = ^M thenπ changeLines;π if crs < endf thenπ inc(crs);πend;ππProcedure goCtrlLf;πVarπ c : Char;πbeginπ Repeatπ goLf;π c := txt[crs];π Until (c <= ' ') or (crs = 0);πend;ππProcedure goCtrlRt;πVarπ c : Char;πbeginπ Repeatπ goRt;π c := txt[crs];π Until (c <= ' ') or (crs >= endF);πend;ππProcedure goUp;πVarπ i : Integer;πbeginπ if lnBase > 0 thenπ beginπ changeLines;π lnBase := scanCrUp(pred(lnBase));π crs := lnBase;π i := scanCrDn(crs) - crs;π if i >= x thenπ inc(crs, x)π elseπ inc(crs,i);π end;πend;ππProcedure goDn;πVarπ i : Integer;πbeginπ changeLines;π crs := scanCrDn(crs);π if crs >= endF thenπ Exit;π inc(crs);π lnBase := crs;π i := scanCrDn(crs) - crs;π if i >= x thenπ inc(crs, x)π elseπ inc(crs, i);πend;ππProcedure goPgUp;πVarπ i : Byte;πbeginπ For i := halfPage downto 0 doπ goUp;πend;ππProcedure goPgDn;πVarπ i : Byte;πbeginπ For i := halfPage downto 0 doπ goDn;πend;ππProcedure goHome;πbeginπ crs := scanCrUp(crs);πend;ππProcedure goend;πbeginπ crs := scanCrDn(crs);πend;ππProcedure backChar;πbeginπ if (crs > 0) thenπ beginπ goLf;π delChar;π end;πend;ππProcedure deleteLine;πVarπ i : Integer;πbeginπ i := scanCrDn(crs);π crs := scanCrUp(crs);π if i < endF thenπ beginπ move(txt[succ(i)], txt[crs], endf - i);π dec(endF);π end;π dec(endf, i - crs);π changeLines;πend;ππProcedure flipCursor;πVarπ j, k, l : Word;πbeginπ j := succ((y * 80 + x) shl 1);π l := mem[vSeg : j]; {save attr under cursor}π mem[vSeg : j] := $7B;π if not KeyPressed thenπ syncTick;π mem[vSeg : j] := l;π if not KeyPressed thenπ syncTick;πend;ππProcedure edit;πVarπ c : Char;πbeginπ Repeatπ display;π Repeatπ flipcursor;π Until KeyPressed;ππ c := ReadKey;π if c = #0 thenπ Case ReadKey ofπ #59 : signOff;π #75 : goLf;π #77 : goRt;π #115 : goCtrlLf;π #116 : goCtrlRt;π #72 : goUp;π #80 : goDn;π #83 : delChar;π #73 : goPgUp;π #81 : goPgDn;π #71 : goHome;π #79 : goend;π endπ elseπ Case c ofπ ^[ : saveFile;π ^H : backChar;π ^C : {abortFile};π ^Y : deleteLine;π elseπ insChar(c);π end;π Until (c = ^[) or (c = ^C);πend;ππFunction getRows : Byte; Assembler;πAsmπ mov ax, $1130π xor dx, dxπ int $10π or dx, dxπ jnz @Sπ mov dx, 24π @S: {cga/mda don't have this fn}π inc dxπ mov al, dlπend;ππVarπ oldMode : Byte;πbeginπ Asmπ mov ah, $Fπ int $10π mov oldMode, alπ end; {save old Gr mode}ππ if oldMode = 7 thenπ vSeg := $B000; {check For Mono}ππ nLines := getRows;π halfPage := pred(nLines shr 1);π cls;π title;ππ if paramCount = 0 thenπ error('Need Filename as parameter')π elseπ beginπ Asmπ mov bh, 0π mov dl, 0π mov dh, nLinesπ mov ah, 2π int $10π end; {put cursor of}ππ assign(theFile, paramStr(1));π loadFile;π edit;π end;πend.π 12 05-25-9408:24ALL JASON KING Word Wrap SWAG9405 19 F╔ {πBT>Hello All...ππBT> Ok once again I have reached a brick wall in my program... What IπBT>was trying to do, was to make Word Wrap actully work... Turns out I wasπBT>barking up the wrong tree... If you have examples on how to do this... ThπBT>please replyπBT>and let me know...ππWhat I'm about to describe assumes you either have a loop ofπprocedure/function that'll read in one line as it works on a line byπline basis.... What I've always done (for wordwrap) is when entering aπline, it stores each character into a holding string that'll contain theπfinal line, you also have a string that contains the wrapped text, ifπthe user presses space, you clear the string holding the wrapped text,πand if they reach the end of the line, you erase as many characters asπthe length of the string holding the wrapped text...ππExample (untested):ππ(uses the CRT unit)π}ππProcedure GetLineWithWrap(var Line,Wrap: String);πConst Cr=#13;π BS=#8;π EraseChar=#8+#32+#8;ππVar HoldLine,HoldWrap: String;π Ch: Char;π Count: Byte;ππBeginπ HoldWrap:='';π HoldLine:='';π if length(line)<>0 then beginπ HoldLine:=Line;π Write(Line) end;π Repeatπ While not keypressed do;π Ch:=Readkey;π If WhereX=80 and then beginπ For Count:=1 to Length(HoldWrap) Write(EraseChar);π HoldLine:=Copy(HoldLine,1,Length(HoldLine)-Length(HoldWrap)-1);π Line:=HoldLine;π If Ch=#32 then Wrap:='' else Wrap:=HoldWrap+ch;π Exit End;π Case Ch ofπ #13 : {nothing, but don't want it added to the line};π #8 : If length(HoldLine)>0 then beginπ Write(EraseChar);π If Length(HoldLine)>1 thenπ HoldLine:=Copy(HoldLine,1,Length(HoldLine)-1)π else HoldLine:='';π If Length(HoldWrap)>1 thenπ HoldWrap:=Copy(HoldWrap,1,Length(HoldWrap)-1)π else HoldWrap:='';π End;π #32 : Beginπ HoldLine:=HoldLine+' ';π HoldWrap:='' end;π Else HoldLine:=HoldLine+Ch End;π Until Ch=#13;π Line:=HoldLine;π Wrap:='';π End;π 13 05-26-9406:17ALL MIKE PERRY Full Screen Editor IMPORT 312 F╔ πUnit MPEditor; { VERSION 1.0 May 14, 1994 }π{ A general full-screen text editor that should compile under varyingπ versions of Borland's Turbo Pascal, relying solely on the CRTπ (and System) units.ππ (c) 1994, Michael Perry / Progressive Computer Services, Inc.π All rights reserved worldwide.ππ LICENSE: This code is NOT Public Domain; It can be freelyπ distributed as long as it is not modified in anyπ form. If you incorporate any part of the code intoπ a program, please credit Mike Perry in the program;π No other remuneration or consideration necessary,π although it would be nice to get a "thank you" postcard.π If you have suggestions or enhancements (please do)π send them to me and I'll make sure that you getπ credit and that this unit will be continually updated.ππ Author: Mike Perry / Progressive Computer Services, Inc.π PO Box 7638, Metairie, LA 70010 USAπ BBS: (504) 835-0085 FAX: (504) 834-2160π Fidonet: 1:396/21 Cserve: 71127,2105 AOL: Arpegi0π Internet: 71127.2105@compuserve.com PAN: MIKEPERRYπ Unison: MIKEPππ USAGE: MPEDITOR manipulates text in an allocated area of memoryπ specified by the TXT^ pointer. To incorporate this unitπ into your program, simply copy your text into the array ofπ byte specified by TXT^ and call the appropriate procedures.π Supported commands:π Arrow keys for cursor movement, INS, DEL, PgUp, PgDnπ CTRL-(left/right) moves cursor to next word;π ^Y = delete line,π ^B = reformat text from cursor to end of paragraphπ Ctrl-PgUp = go to top of fileπ Ctrl-PgDn = go to end of fileπ NOTES:π % Statements in the unit which are commented out pertain to featuresπ and options which are either for demonstration purposes or haveπ yet to be implemented; look for updates soon.π % This editor unit assumes that linefeed characters (#10) areπ stripped from the input prior to editing. If you importπ data to be edited, make sure you convert CR+LF to CR!!π % The following routines are critical to performance and ifπ implemented in ASM would improve efficiency of the unit:π GET_LINE_DATA, SET_POSITION, SET_CURSORπ If you can help, contact me at the addresses at the top.π}π{$R-} { range checking off - causes error when referencing buffer array }ππ{ If you want to implement your own screen i/o routines, look for theπ USEQWIK directive which identifies areas in the program where you canπ make modifications to suit your objective }π{-$DEFINE USEQWIK} { implements FAST direct screen writing / requires }π { Eagle Performance Software's QWIK screen units }π { available as Shareware }πINTERFACEππ{$IFDEF USEQWIK}π USES CRT,Qwik;π{$ELSE}π USES CRT;π{$ENDIF}ππCONSTπ TEXTMAX:WORD= 40000; { Maximum size of text editing buffer in bytes }π CR = 13; { ordinal value used to indicate a new line }π SPACE = 32; { ordinal value used to indicate a space }π REFORMAT = 2; { ordinal value to initiate reformat command / CTRL-B }π TABSIZE = 5; { tab stop every five characters }ππTYPEπ TXT_TYPE = ARRAY [1..1] OF BYTE;ππVARπ TXT : ^TXT_TYPE; { TEXT BUFFER, pointer to memory block }ππ { operational status variables ------(set during operation)------------- }π TEXTSIZE : LONGINT; { size of txt array in use / max current index }π POSITION : LONGINT; { index of current (cursor) position in TXT array }π WINTOP : LONGINT; { index position in buffer of top of text window }π XLINE : BOOLEAN; { TRUE if cursor position outside of data area }π INSERTON : BOOLEAN; { TRUE indicates insert mode on }π VROW,π VCOLUMN : BYTE; { VIRTUAL ROW/COLUMN position within editing area }π WIDTH,π HEIGHT : BYTE; { width and height of current editing window }π SCRBUMP : BYTE; { chars to bump over display / not to exceedπWIDTH! }π OFFSET : LONGINT; { screen display offset, column position to beginπdisplaying }π{ MARKSTART,π MARKEND : LONGINT; { start/end index of marked text / NOT IMPLEMENTEDπ}π { operational configuration vars ----(set by user)----------------------- }π MARKATTR, { marked text attribute }π BACKATTR, { background text window attribute }π NORMATTR, { attribute values for normal & hilighted text }π BORDATTR : WORD; { attribute value for border }π R1,C1, { row,column of upper left coord of edit window }π R2,C2 : BYTE; { row,column of lower right coord on edit win }π MAXCOLUMN : LONGINT; { maximum line length/column size, 0=No Limit }π{ MAXROW : LONGINT; { maximum number of lines allowed, 0=No Limit }ππ { prototypes ------------------------------------------------------------ }ππ {FUNCTION GETINPUT(VAR FUNCTIONKEY:BOOLEAN):BYTE; NEAR }π {FUNCTION SPACES(COUNT:BYTE):STRING; NEAR }π {PROCEDURE CLEAR_TXT; NEAR }π FUNCTION GETTEXTEND:LONGINT;π FUNCTION INITIALIZE_TXT(VAR PTXT:POINTER;SIZE:LONGINT):BOOLEAN;π PROCEDURE DISPOSE_TXT(VAR PTXT:POINTER;SIZE:LONGINT);π {PROCEDURE DRAW_BOX(R1,C1,R2,C2:BYTE); NEAR }π {PROCEDURE INITIALIZE_WINDOW(R1,C1,R2,C2:BYTE); NEAR }π {PROCEDURE CLEAR_WINDOW; NEAR }π {PROCEDURE CLEAR_LINE; NEAR }π {PROCEDURE BUMP_TXT(COUNT:LONGINT); NEAR }π {PROCEDURE DEL_CHARS(COUNT:LONGINT); NEAR }π {PROCEDURE GET_LINE_DATA(POS:LONGINT; VAR STARTINDEX,ENDINDEX,COL:LONGINT);}π {PROCEDURE STUFF_TXT(s:string); NEAR }π FUNCTION WINBOTTOM:LONGINT;π {PROCEDURE SHOW_LINE; NEAR }π PROCEDURE SHOW_TXT;π PROCEDURE DISPLAY_TXT(VAR PT:POINTER);π PROCEDURE SCROLLUP(LINES:BYTE);π PROCEDURE SCROLLDOWN(LINES:BYTE);π {PROCEDURE SET_POSITION; NEAR }π {PROCEDURE SET_CURSOR; NEAR }π {PROCEDURE WORD_WRAP(startpoint,endpoint,length:LONGINT);}π {FUNCTION LINEUP:LONGINT; NEAR }π {FUNCTION LINEDOWN:LONGINT; NEAR }π PROCEDURE READ_TXT(VAR PT:POINTER;FILENAME:STRING;VAR TEXTSIZE:LONGINT);π {PROCEDURE DIRECTION(C:BYTE); NEAR }π {FUNCTION PARSE_INPUT:BYTE; NEAR }π PROCEDURE SETUP_TEXT_SETTINGS(Row1,Column1,Row2,Column2:BYTE;DRAWBOX:BOOLEAN) ;π PROCEDURE EDIT(PT:POINTER;VAR RETURNCODE:BYTE);ππIMPLEMENTATIONππ(***************************************************************************)πFUNCTION GETINPUT(VAR FUNCTIONKEY:BOOLEAN):BYTE;π{ read keyboard and return character/function key }πVAR CH: CHAR;πBEGINπ CH:=ReadKey;π IF (CH=#0) THENπ BEGINπ CH:=ReadKey;π FUNCTIONKEY:=TRUE;π ENDπ ELSE FUNCTIONKEY:=FALSE;π GETINPUT:=ORD(CH);πEND;π(***************************************************************************)πFUNCTION SPACES(COUNT:BYTE):STRING;π{ returns COUNT number of spaces }π{ NOTE: Unpredictable results if count exceeds 255!! }πvar temp:string;πBEGINπ TEMP:='';π WHILE COUNT>0 DO BEGINπ TEMP:=TEMP+#32;π DEC(COUNT);π END;π SPACES:=TEMP;πEND;π(***************************************************************************)πPROCEDURE CLEAR_TXT;π{ zeros the text array & associated values }πBEGINπ fillchar(txt^,TEXTMAX,0);π textsize:=0;π position:=1;πEND;π(***************************************************************************)πFUNCTION GETTEXTEND:LONGINT;π{ find the end of text by looking for null characterπ %% This is a technique that I use to identify the actual size ofπ a text buffer; if you're reading data from a disk structure,π unless you save the actual size, you'll need to determine it.π I make sure any unused area in my text buffer is padded withπ nuls }πvar I:longint;πBEGINπ FOR I:=1 TO TEXTMAX DOπ IF TXT^[I]=0 THEN BEGINπ GETTEXTEND:=I-1;π EXIT;π END;π GETTEXTEND:=TEXTSIZE;πEND;π(***************************************************************************)πFUNCTION INITIALIZE_TXT(VAR PTXT:POINTER;SIZE:LONGINT):BOOLEAN;π{ create/allocate memory for text buffer }πBEGINπ if MaxAvail < SIZE thenπ INITIALIZE_TXT:=FALSE { not enough available memory }π else BEGINπ GETMEM(PTXT,SIZE);π INITIALIZE_TXT:=TRUE;π TEXTMAX:=SIZE; { set max size of text }π TXT:=PTXT; { establish pointer for routines }π CLEAR_TXT; { zero text }π END;πEND;ππ(***************************************************************************)πPROCEDURE DISPOSE_TXT(VAR PTXT:POINTER;SIZE:LONGINT);π{ disposes text buffer }πBEGINπ FREEMEM(PTXT,SIZE);πEND;π(***************************************************************************)πPROCEDURE DRAW_BOX(R1,C1,R2,C2:BYTE);π{ surrounds the specified area with a box }π{ NOTE! There are no checks to make sure the box area isn't off the screen!π and this (and other) routines must be slightly modified if you wantπ the text area to fill up the entire screen due to anomolies withπ TP's WINDOW function }πvar I:byte;πBEGINπ{$IFDEF USEQWIK}π { draw horizontal line }π FOR I:=(C1-1) TO (C2+1) DO BEGINπ qwrite(R1-1,I,BORDATTR,'─');π qwrite(R2+1,I,BORDATTR,'─');π END;π { draw vertical line }π FOR I:=(R1-1) TO (R2+1) DO BEGINπ QWRITE(I,C1-1,BORDATTR,'│');π QWRITE(I,C2+1,BORDATTR,'│');π END;π QWRITE(R1-1,C1-1,BORDATTR,'┌');π QWRITE(R2+1,C1-1,BORDATTR,'└');π QWRITE(R1-1,C2+1,BORDATTR,'┐');π QWRITE(R2+1,C2+1,BORDATTR,'┘');π{$ELSE}π TEXTATTR:=BORDATTR;π { draw horizontal line }π FOR I:=(C1-1) TO (C2+1) DO BEGINπ GOTOXY(I,R1-1); WRITE('─');π GOTOXY(I,R2+1); WRITE('─');π END;π { draw vertical line }π FOR I:=(R1-1) TO (R2+1) DO BEGINπ GOTOXY(C1-1,I); WRITE('│');π GOTOXY(C2+1,I); WRITE('│');π END;π GOTOXY(c1-1,r1-1); WRITE('┌');π GOTOXY(c1-1,r2+1); WRITE('└');π GOTOXY(c2+1,r1-1); WRITE('┐');π GOTOXY(c2+1,r2+1); WRITE('┘');π TEXTATTR:=NORMATTR;π{$ENDIF}πEND;π(***************************************************************************)πPROCEDURE INITIALIZE_WINDOW(R1,C1,R2,C2:BYTE);π{ defines text window and clears screen }πBEGINπ{$IFNDEF USEQWIK}π WINDOW(C1,R1,C2+1,R2);π{$ENDIF}πEND;π(***************************************************************************)πPROCEDURE CLEAR_WINDOW;π{ clears the current text window }πBEGINπ{$IFDEF USEQWIK}π QFILL(r1,c1,HEIGHT,WIDTH,BACKATTR,#32);π{$ELSE}π textattr:=backattr;π{ since TP forces an unwanted scroll when writing to the lower right cornerπ of a window, we create a window 1-column larger and init a smaller one whenπ we want to clear the screen, there is an extra column defined in theπ working window so that unwanted scrolls are not accomplished }π WINDOW(C1,R1,C2,R2);π CLRSCR;π WINDOW(C1,R1,C2+1,R2);π{$ENDIF}πEND;π(***************************************************************************)πPROCEDURE CLEAR_LINE;π{ clears the current line }πBEGINπ{$IFDEF USEQWIK}π QFILL(R1+VROW-1,C1,1,WIDTH,BACKATTR,#32);π { FYI, the arguments for QFILL are:π QFILL(row,column,rows,columns,attribute,char); }π{$ELSE}π TEXTATTR:=BACKATTR;π WINDOW(C1,R1,C2,R2);π gotoxy(1,vrow); clreol;π WINDOW(C1,R1,C2+1,R2);π{$ENDIF}πEND;π(***************************************************************************)πPROCEDURE BUMP_TXT(COUNT:LONGINT);π{ moves text at POSITION index over COUNT bytes, for inserting data }π{ this procedure does NOT change, position or cursor indexes }πVAR I:LONGINT;πBEGINπ inc(textsize,COUNT);π for i:=textsize downto position do { move everything forward 1 }π txt^[i]:=txt^[i-COUNT];πEND;π(***************************************************************************)πPROCEDURE DEL_CHARS(COUNT:LONGINT);π{ erase COUNT chars at position, shorten text array }πvar I:longint;πBEGINπ FOR I:=POSITION TO (TEXTSIZE-1) DOπ TXT^[I]:=TXT^[I+COUNT];π DEC(TEXTSIZE,COUNT);πEND;ππ(***************************************************************************)πPROCEDURE GET_LINE_DATA(POS:LONGINT; VAR STARTINDEX,ENDINDEX,COL:LONGINT);π{ given the array index (position), calculate the start & ending index of theπ current line, also returning VIRTUAL column position on the current lineππ procedure returns: 1,1,1 if at the top of the file;π procedure returns: textsize,textsize,1 at bottom of fileππ This is one procedure, that if implemented in ASM would improve theπ overall performance of this unit (I'm open to suggestions).π}πVAR i:longint;πBEGINπ startindex:=0; endindex:=0; col:=0;π if pos<1 then exit; { invalid position }π if pos>textsize then begin { at end of text }π endindex:=textsize+1;π end else beginπ for i:=pos to textsize do { find end of line index }π if txt^[i]=CR then begin { found CR at end of line }π endindex:=i;π i:=textsize; { force end of loop }π end;π if endindex=0 then endindex:=textsize+1; { last line obviously }π end;π { find beginning of line index }π for i:=(endindex-1) downto 1 do { FOR checks=endvalue, if not increments! }π if txt^[i]=CR then begin { found CR at beginning of line }π startindex:=i+1; { index of previous CR+1 }π i:=1; { force end of loop }π end;π if startindex=0 then startindex:=1; { begin of line is top of text }ππ col:=pos-startindex+1; { calculate VIRTUAL column position }πEND;π(***************************************************************************)πPROCEDURE STUFF_TXT(s:string);π{ add string/char to txt array, bump POSITION up one }πVAR j,b1,e1,col1:longint; t:byte;πBEGINπ t:=length(s);π if ((inserton) or (txt^[position]=CR)) and ((textsize+t)>textmax) thenπbegin { no more room }π write(#7); exit;π end;ππ{ if xline, and text added, make sure to bump position to the end of line }π IF (XLINE) THEN BEGIN { pad the short line with spaces to the position }π GET_LINE_DATA(POSITION, b1,e1,col1);π j:=(offset+vcolumn)-(e1-b1+1); { number of spaces to pad }π IF ((textsize+t+j)>textmax) then BEGIN { check for avail space }π write(#7); exit;π END;π bump_txt(j);π for b1:=position to (position+j-1) doπ txt^[b1]:=SPACE;π XLINE:=FALSE;π POSITION:=POSITION+J;π END;ππ if (inserton) OR (txt^[position]=CR) thenπ if (position<=textsize) then begin { insert }π bump_txt(t);π FOR J:=1 TO T DO BEGINπ txt^[position]:=ORD(S[J]); { add/replace character }π INC(POSITION); { move pointer up one }π INC(VCOLUMN);π END;π exit;π end else begin { append / position > textsize }π FOR J:=1 TO T DO BEGINπ inc(textsize);π txt^[textsize]:=ORD(S[J]);π INC(VCOLUMN);π END;π position:=textsize+1; { position pointer at end of text }π endπ else if position<=textsize then begin { overwrite }π FOR J:=1 TO T DO BEGINπ txt^[position]:=ORD(S[J]); { overwrite current position }π inc(position); { move pointer one over }π END;π INC(VCOLUMN,T);π end else begin { append }π if ((textsize+T)>=textmax) then begin { can't append if buffer full }π write(#7);π exit;π end;π FOR J:=1 TO T DO BEGINπ inc(textsize);π txt^[textsize]:=ORD(S[J]);π END;π position:=textsize+1;π INC(VCOLUMN,T);π end;πEND;π(***************************************************************************)πFUNCTION WINBOTTOM:LONGINT;π{ returns the text array index value of the last character in the text window }πvar i:longint; linecount:byte;πBEGINπ LINECOUNT:=0;π FOR I:=WINTOP TO TEXTSIZE DO BEGINπ IF TXT^[I]=CR THEN INC(LINECOUNT);π IF LINECOUNT=HEIGHT THEN BEGIN { found last line in text window }π WINBOTTOM:=I;π EXIT;π END;π END; { for loop thru text }π WINBOTTOM:=TEXTSIZE; { end before last text line found, so text ends inπwindow }πEND;ππ(***************************************************************************)πPROCEDURE SHOW_LINE;π{ rewrites the current line to the window }πVAR I,b1,e1,col1:longint; S:STRING;πBEGINπ GET_LINE_DATA(position, b1,e1,col1);π IF (B1>TEXTSIZE) THEN BEGIN CLEAR_LINE; EXIT; END; { nothing there }π col1:=(offset+b1+width-1); if col1>textsize then col1:=textsize; {eol pos}π S:='';π for i:=(offset+b1) to col1 {(offset+b1+width-1)} do beginπ if txt^[i]=CR then i:=col1 {(offset+b1+width-1)} { force end }π else beginπ s:=s+chr(txt^[i]);π end;π end;π CLEAR_LINE;π{$ifdef USEQWIK}π QWRITE(R1+VROW-1,C1,NORMATTR,S);π GOTORC(R1+VROW-1,C1+VCOLUMN-1);π{$ELSE}π TEXTATTR:=NORMATTR;π GOTOXY(1,VROW); WRITE(S);π GOTOXY(VCOLUMN,VROW);π{$ENDIF}πEND;π(***************************************************************************)πPROCEDURE SHOW_TXT;π{ display text to screen areaπ sets VROW and VCOLUMN to match displayed area where positionπ is and moves cursor to that location }πvar I,R,C,CWIDTH:LONGINT;πBEGINπ R:=1; C:=1; { set start row/column }π CWIDTH:=0;π CLEAR_WINDOW;ππ { % hide cursor }π FOR I:=WINTOP TO TEXTSIZE DO BEGINπ IF (R>HEIGHT) OR (I>TEXTSIZE) THEN begin { check for outside verticalπboundaries OR end }π {$IFDEF USEQWIK}π GOTORC(R1+VROW-1,C1+VCOLUMN-1);π {$ELSE}π GOTOXY(VCOLUMN,VROW);π {$ENDIF}π EXIT; { done, filled window }π END;π IF (TXT^[I]=CR) THEN BEGIN { -------------- check for carriage return }π INC(R); { bump row down }π CWIDTH:=0;π C:=1;π{ % IF TXT^[I+1]=10 THEN INC(I); { check for additional LF / skip over }ππ END ELSE BEGIN { ----------------------------------- printable char }π INC(CWIDTH);π IF CWIDTH>OFFSET THEN { if screen offset in effect }π IF C<= WIDTH THEN BEGIN { if line not off the screen }π{$IFDEF USEQWIK}π QWRITE(R1+R-1,C1+C-1,NORMATTR,CHR(TXT^[I]));π{$ELSE}π GOTOXY(C,R); textattr:=normattr;π WRITE(CHR(TXT^[I]));π{$ENDIF}π INC(C);π END else INC(C); { increment column counter anyway even though notπprinted }π END;π IF I>TEXTSIZE THEN I:=TEXTSIZE; { if bumped past, set to end loop }π END; { FOR loop }π{$IFDEF USEQWIK}π GOTORC(R1+VROW-1,C1+VCOLUMN-1);π{$ELSE}π GOTOXY(VCOLUMN,VROW);π{$ENDIF}π EXIT;πEND;π(***************************************************************************)πPROCEDURE DISPLAY_TXT(VAR PT:POINTER);π{ display text, specified by pointerπ can be used by an external viewing routine }πVAR TEMP:POINTER;πBEGINπ TEMP:=addr(TXT);π TXT:=PT;π SHOW_TXT;π TXT:=TEMP;πEND;π(***************************************************************************)πPROCEDURE SCROLLUP(LINES:BYTE);π{ scroll screen up x lines; does not change cursor or text pointer }πvar i,b1,e1,col1,LINECOUNT:longint;πBEGINπ LINECOUNT:=0;π FOR I:=WINTOP DOWNTO 1 DO BEGINπ if txt^[i]=CR then begin { found end of prev line }π INC(LINECOUNT);π IF (LINECOUNT=LINES) THEN BEGINπ GET_LINE_DATA(I, b1,e1,col1);π WINTOP:=B1;π EXIT;π END;π END; { cr found }π END; { for loop }π WINTOP:=1;πEND;π(***************************************************************************)πPROCEDURE SCROLLDOWN(LINES:BYTE);π{ scroll screen down x lines, does not change cursor or text pointer }πvar i,b1,e1,col1,LINECOUNT:longint;πBEGINπ linecount:=0;π for i:=WINTOP to textsize do beginπ if txt^[i]=CR then beginπ { i=index pos of CR of next line }π inc(linecount);π if (linecount=lines) {or (i=textsize)} then beginπ WINTOP:=i+1;π SHOW_TXT;π EXIT;π end; { found specified number of lines }π end; { if CR found }π end; { loop thru text }πEND;ππ(***************************************************************************)πPROCEDURE SET_POSITION;π{ sets POSITION index based on cursor location and WINTOP index }πvar I,b1,e1,col1,R,LINECOUNT:longint;πBEGINπ R:=1; LINECOUNT:=1;π FOR I:=WINTOP TO TEXTSIZE DO BEGINπ if (VROW=R) then begin { line cursor on found }π GET_LINE_DATA(I, b1,e1,col1);π IF ((E1-B1+1) < (VCOLUMN+OFFSET)) THEN BEGINπ POSITION:=E1;π XLINE:=TRUE;π END ELSE BEGINπ POSITION:=B1+VCOLUMN-1;π XLINE:=FALSE;π END;π EXIT;π end; { cursor line found }π if txt^[i]=CR then beginπ INC(R);π INC(LINECOUNT);π end;π END; { for loop thru text }π POSITION:=TEXTSIZE+1; { assuming cursor at end of text then }π VROW:=LINECOUNT; { not sure if this should be here, but takes careπ of case where scrolling causes most of screen toπ be past the end of file (where the cursor pos is)π }π GET_LINE_DATA(POSITION, b1,e1,col1);π IF (VCOLUMN>COL1) THEN XLINE:=TRUE ELSE BEGINπ POSITION:=B1+VCOLUMN+OFFSET-1;π XLINE:=FALSE;π END;πEND;π(***************************************************************************)πPROCEDURE SET_CURSOR;π{ finds position and sets VCOLUMN & VROW and OFFSET appropriately in window }π{ ALWAYS sets XLINE to FALSE }πvar i,b1,e1,col1,R,C:longint; screenchanged:BOOLEAN;πBEGINπ R:=1; C:=1; SCREENCHANGED:=FALSE; XLINE:=FALSE;π FOR I:=WINTOP TO TEXTSIZE+1 DO BEGINπ IF I=POSITION THEN BEGIN { found it ------------------------ }π if (c>offset) and (c<=(offset+width)) then begin { in window }π dec(c,offset);π end else BEGINπ SCREENCHANGED:=TRUE;π IF (C<=WIDTH) THEN BEGINπ OFFSET:=0;π END ELSE BEGINπ OFFSET:=(C-WIDTH)+SCRBUMP;π C:=WIDTH-SCRBUMP;π END;π END;π VCOLUMN:=C;π VROW:=R;π IF (SCREENCHANGED) THEN SHOW_TXT elseπ{$IFDEF USEQWIK}π GOTORC(R1+VROW-1,C1+VCOLUMN-1);π{$ELSE}π GOTOXY(VCOLUMN,VROW);π{$ENDIF}π EXIT;π END; { position found }π IF TXT^[I]=CR THEN BEGINπ INC(R); C:=1;π END ELSE INC(C);π IF (R>HEIGHT) {OR (R<1)} THEN BEGINπ GET_LINE_DATA(WINTOP, b1,e1,col1);π WINTOP:=E1+1;π R:=HEIGHT;π SCREENCHANGED:=TRUE;π END;π END; { for }πEND;π(***************************************************************************)πPROCEDURE WORD_WRAP(startpoint,endpoint,length:LONGINT);π{ word wrap a section of text }πvar ccount,i,spacepos,lastcr:longint; showit:boolean;πBEGINπ IF LENGTH=0 THEN EXIT; { no length specified so get outta here }π SPACEPOS:=0; SHOWIT:=FALSE; CCOUNT:=0; LASTCR:=-1;π FOR I:=STARTPOINT TO (ENDPOINT-1) DO BEGINπ INC(CCOUNT);π IF TXT^[I]=SPACE THEN SPACEPOS:=I;π IF TXT^[I]=CR THEN { end wrap when to CRs follow, otherwise -> space }π IF LASTCR=(I-1) THEN BEGINπ TXT^[I-1]:=CR; { restore prev CR }π SET_CURSOR;π SHOW_TXT;π EXIT;π END ELSE BEGINπ TXT^[I]:=SPACE;π SPACEPOS:=I;π LASTCR:=I;π END;π IF (CCOUNT)>LENGTH THEN BEGIN { past point }π IF SPACEPOS=0 THEN BEGIN { force a CR }π SPACEPOS:=POSITION; { save pos }π POSITION:=I;π BUMP_TXT(1); { insert 1 byte at position }π INC(ENDPOINT);π POSITION:=SPACEPOS; { restore pos }π TXT^[I]:=CR;π CCOUNT:=0;π END ELSE BEGINπ TXT^[SPACEPOS]:=CR; { turn last space into a CR }π CCOUNT:=I-SPACEPOS; { calc next line len w/wrap }π END;π SHOWIT:=TRUE;π END; { line past length }π END; { for }π IF SHOWIT THEN BEGINπ SET_CURSOR;π SHOW_TXT;π END;πEND;ππ(***************************************************************************)πFUNCTION LINEUP:LONGINT;π{ returns new index in file, one line up }π{ MOVES cursor on screen as well }πvar b1,b2,e1,e2, col1,col2,len1,len2:longint;πBEGINπ GET_LINE_DATA(position, b1,e1,col1); { get data on current line }π len1:=e1-b1+1; { length of line + CR }π if b1=1 then BEGIN { check for top of text }π LINEUP:=POSITION; EXIT;π END;π GET_LINE_DATA(B1-1, b2,e2,col2); { get data on previous line }π len2:=e2-b2+1;π IF (XLINE) THEN BEGINπ col2:=b2+vcolumn+offset-1; { in case of move to non-xline, set position }π END ELSEπ col2:=b2+col1-1; { index position of one line up, tentative }ππ if col2<1 then col2:=1 else { top of file }π if (col2>e2) then begin { previous line shorter than current line }π col2:=e2; { make one line up, end of previous line }π XLINE:=TRUE;π end else beginπ XLINE:=FALSE;π end;π LINEUP:=COL2;ππ IF (WINTOP>col2) THEN BEGIN { scroll the screen up }π WINTOP:=B2;π SHOW_TXT;π END ELSE DEC(VROW); { bump cursor up }π{$IFDEF USEQWIK}π GOTORC(R1+VROW-1,C1+VCOLUMN-1);π{$ELSE}π GOTOXY(VCOLUMN,VROW);π{$ENDIF}πEND;π(***************************************************************************)πFUNCTION LINEDOWN:LONGINT;π{ returns new index in file, one line down }π{ MOVES cursor on screen as well }πvar b1,b2,e1,e2, col1,col2,len1,len2:longint;πBEGINπ GET_LINE_DATA(position, b1,e1,col1); { get data on current line }π len1:=e1-b1+1; { calc length of line incl. CR }π if e1>=textsize then begin { can't go down on last line }π LINEDOWN:=POSITION; EXIT;π end;π GET_LINE_DATA(e1+1, b2,e2,col2); { get data on next line }π len2:=e2-b2+1;ππ IF (XLINE) THEN BEGINπ col2:=b2+vcolumn+offset-1; { in case of move to non-xline, set position }π END ELSEπ col2:=b2+col1-1; { index position of one line down, tentative }ππ if (col2>e2) then begin { next line position is past end of next line }π col2:=e2; { make one line down, end of next line }π xline:=TRUE;π end else beginπ xline:=FALSE;π end;π LINEDOWN:=COL2;ππ IF (VROW=HEIGHT) THEN BEGIN { down off screen, scroll text up }π SCROLLDOWN(1); {WINTOP:=B2;}π END ELSE INC(VROW); { bump screen down }π{$IFDEF USEQWIK}π GOTORC(R1+VROW-1,C1+VCOLUMN-1);π{$ELSE}π GOTOXY(VCOLUMN,VROW);π{$ENDIF}πEND;π(***************************************************************************)πPROCEDURE READ_TXT(VAR PT:POINTER;FILENAME:STRING;VAR TEXTSIZE:LONGINT);π{ reads text from file into buffer, strips LFs }π{ HORRIBLY SLOW, but not intended to be a real part of this unit }πVARπ F :FILE OF BYTE;π PTXT :^TXT_TYPE;πBEGINπ PTXT:=PT;π ASSIGN(F,FILENAME);π RESET(F);π TEXTSIZE:=0;π IF IORESULT<>0 THEN EXIT;π IF EOF(F) THEN BEGIN CLOSE(F); EXIT; END;π WHILE NOT(EOF(F)) DO BEGINπ INC(TEXTSIZE);π READ(F,PTXT^[TEXTSIZE]);π if (Ptxt^[textsize]=10) then beginπ dec(textsize); { remove LFs }π end;π IF TEXTSIZE>=TEXTMAX THEN BEGINπ CLOSE(F);π EXIT;π END;π END;π CLOSE(F);πEND;ππ(***************************************************************************)πPROCEDURE DIRECTION(C:BYTE);π{ act on direction keys }πvar b1,e1,col1:longint; T:BYTE;πBEGINπ case C ofπ 72:begin { up }π POSITION:=LINEUP;π end;π 80:begin { down }π POSITION:=LINEDOWN;π end;π 75:begin { left }π if position=1 then beginπ write(#7);π exit;π end;π if (xline) then beginπ dec(vcolumn);π { check to see if moved onto text }π get_line_data(position,b1,e1,col1);π if (offset+vcolumn)=(e1-b1+1) then beginπ xline:=FALSE;π end;π end else begin { not xline }π if txt^[position-1]=CR then begin { back up one line? }π get_line_data(position-1,b1,e1,col1);π vcolumn:=col1;π if col1>width then begin { left to prev line off screen }π offset:=col1-width+2;π vcolumn:=col1-offset;π SHOW_TXT;π end else offset:=0;π dec(vrow)π end else beginπ dec(vcolumn);π end;π dec(position);π end; { xline }π if (vcolumn<1) and (offset>0) then beginπ vcolumn:=1;π dec(offset);π SHOW_TXT;π end;π{$IFDEF USEQWIK}π GOTORC(R1+VROW-1,C1+VCOLUMN-1);π{$ELSE}π GOTOXY(VCOLUMN,VROW);π{$ENDIF}π end;π 77:begin { right }π if (xline) then beginπ inc(vcolumn);π end else beginπ inc(position);π inc(vcolumn);π if (txt^[position-1]=CR) OR ((position-1)>=TEXTSIZE) then beginπ{ at eol }π dec(position);π xline:=true;π end;π end;ππ IF (MAXCOLUMN>0) AND ((VCOLUMN+OFFSET)>MAXCOLUMN) THEN BEGINπ GET_LINE_DATA(POSITION,b1,e1,col1);π IF E1>=TEXTSIZE THEN BEGINπ DEC(VCOLUMN);π END ELSE BEGINπ POSITION:=E1+1;π SET_CURSOR;π EXIT;π END;π END;ππ if vcolumn>width then begin { moved outside window }π inc(offset);π dec(vcolumn);π SHOW_TXT;π end;π{$IFDEF USEQWIK}π GOTORC(R1+VROW-1,C1+VCOLUMN-1);π{$ELSE}π GOTOXY(VCOLUMN,VROW);π{$ENDIF}π end;π 71:begin { HOME, to beginning of current line }π GET_LINE_DATA(POSITION,B1,E1,COL1);π POSITION:=B1; VCOLUMN:=1;π IF OFFSET>0 THEN BEGINπ OFFSET:=0;π SHOW_TXT;π END;π{$IFDEF USEQWIK}π GOTORC(R1+VROW-1,C1+VCOLUMN-1);π{$ELSE}π GOTOXY(VCOLUMN,VROW);π{$ENDIF}π XLINE:=FALSE;π end;π 79:begin { END, to end of current line }π GET_LINE_DATA(POSITION,B1,E1,COL1);π POSITION:=E1;π { calculate offset & cursor position }π IF (E1-(B1+OFFSET)+1)>WIDTH THEN BEGIN { off screen }π offset:=(e1-b1+1)-width+2; {SCRBUMP}π vcolumn:=width-2; {SCRBUMP}π SHOW_TXT;π END ELSE VCOLUMN:=((E1-B1+1)-offset);π{$IFDEF USEQWIK}π GOTORC(R1+VROW-1,C1+VCOLUMN-1);π{$ELSE}π GOTOXY(VCOLUMN,VROW);π{$ENDIF}π end;π 73:begin { PGUP, up one screen }π IF (WINTOP=1) THEN BEGINπ POSITION:=1;π VCOLUMN:=1; VROW:=1;π{$IFDEF USEQWIK}π GOTORC(R1+VROW-1,C1+VCOLUMN-1);π{$ELSE}π GOTOXY(VCOLUMN,VROW);π{$ENDIF}π END ELSE BEGINπ SCROLLUP(HEIGHT);π SET_POSITION;π SHOW_TXT;π END;π end;π 81:begin { PGDN, down one screen }π IF (WINBOTTOM=TEXTSIZE) THEN BEGINπ POSITION:=TEXTSIZE+1;π SET_CURSOR;π END ELSE BEGINπ SCROLLDOWN(HEIGHT);π SET_POSITION;π SHOW_TXT;π END;π end;π 82:BEGINπ INSERTON:=NOT(INSERTON); { INS toggle insert status }π{ % IF (INSERTON) THEN GETBLOCKCURSOR ELSE GETUNDERLINECURSOR;}π END;π 83:BEGIN { DEL }π T:=ORD(TXT^[POSITION]);π IF POSITION=TEXTSIZE+1 THEN EXIT;π IF (XLINE) THEN BEGIN { hitting DEL past eol, special case }π STUFF_TXT(#0);π DEC(POSITION);π DEC(VCOLUMN);π DEL_CHARS(1);π END;π DEL_CHARS(1);π IF (T=CR) OR (POSITION>=TEXTSIZE) THEN SHOW_TXT ELSE SHOW_LINE;π END;π 132:begin { CTRL-PgUP - top of text }π POSITION:=1; VROW:=1; VCOLUMN:=1; XLINE:=FALSE;π IF (WINTOP=1) AND (OFFSET=0) THENπ{$IFDEF USEQWIK}π GOTORC(R1+VROW-1,C1+VCOLUMN-1)π{$ELSE}π GOTOXY(VCOLUMN,VROW)π{$ENDIF}π ELSE BEGINπ WINTOP:=1; OFFSET:=0;π SHOW_TXT;π END;π end;π 115:begin { CTRL <- }π if position<3 then exit;π for col1:=(position-2) downto 1 doπ if (txt^[col1]=SPACE) then beginπ position:=col1+1;π if position<wintop then beginπ wintop:=1;π { this could be avoided if set-cursor started at 1 instead of wintop,π but it would reduce overal performance }π set_cursor;π show_txtπ end elseπ set_cursor;π exit;π end;π end;π 116:begin { CTRL -> }π if position>=textsize then exit;π for col1:=position+1 to textsize doπ if (txt^[col1]=SPACE) then beginπ position:=col1+1;π set_cursor;π exit;π end;π end;π 118:begin { CTRL-PgDN - end of text }π position:=textsize+1;π SET_CURSOR;π end;π 67:BEGIN { F9 }π END;π end; { case }πend;ππ(***************************************************************************)πFUNCTION PARSE_INPUT:BYTE;π{ main encapsulation of editing routine, read keys and act }πvar c :byte;π fkey :boolean;π leaving :boolean;π b1,e1,col1:longint;π{ RETURNS:π 1=ESCπ 2=ALT-Xπ 3=F1π 4=F10π 5=F2π}πBEGINπ LEAVING:=FALSE;π REPEATπ c:=getinput(fkey);ππ IF (C=27) OR ((FKEY) AND (C IN [59,45,60,68])) THEN BEGIN { exitπconditions }π IF C=27 THEN PARSE_INPUT:=1 ELSE { esc }π IF C=45 THEN PARSE_INPUT:=2 ELSE { Alt-X }π IF C=59 THEN PARSE_INPUT:=3 ELSE { F1 }π IF C=68 THEN PARSE_INPUT:=4 ELSE { F10 }π IF C=60 THEN PARSE_INPUT:=5; { F2 }π EXIT;π END ELSEπ IF (FKEY) THEN BEGIN { ------------------ eval FNC & CURSOR keys ----- }π DIRECTION(C);π END { if function key pressed }π ELSE BEGIN { alphanumeric key - process data }π CASE C OF { check alpha keys }π REFORMAT:BEGIN { CTRL-B, 02, REFORMAT }π GET_LINE_DATA(POSITION,b1,e1,col1);π WORD_WRAP(B1,TEXTSIZE,MAXCOLUMN);π END;π CR:begin { carriage return }π IF (INSERTON) OR (POSITION>TEXTSIZE) THEN BEGINπ OFFSET:=0;π INC(VROW);π IF VROW>HEIGHT THEN BEGINπ SCROLLDOWN(1);π DEC(VROW);π END;π STUFF_TXT(CHR(C));π VCOLUMN:=1;π SHOW_TXT;π end ELSE BEGIN { enter pressed with overwrite on }π GET_LINE_DATA(POSITION,B1,E1,COL1);π POSITION:=E1+1;π OFFSET:=0;π SET_CURSOR;π show_txt;π END;π END;π 08:IF POSITION<>1 THEN BEGIN { backspace }π IF (XLINE) THEN BEGIN { can't erase dead zone }π DEC(VCOLUMN); { just move cursor left }π SET_POSITION;π END ELSE BEGINπ DEC(POSITION);π IF TXT^[POSITION]=CR THEN BEGIN { backspace/erase line }π DEL_CHARS(1);π SET_CURSOR;π SHOW_TXT;π END ELSE BEGINπ DEL_CHARS(1);π DEC(VCOLUMN);π IF (VCOLUMN=0) THENπ IF (OFFSET>=SCRBUMP) THEN BEGINπ DEC(OFFSET,SCRBUMP); VCOLUMN:=SCRBUMP;π SHOW_TXT;π END ELSE BEGINπ OFFSET:=0; SET_CURSOR;π SHOW_TXT;π ENDπ ELSE SHOW_LINE;π END;π END; { xline / else }π{$IFDEF USEQWIK}π GOTORC(R1+VROW-1,C1+VCOLUMN-1);π{$ELSE}π GOTOXY(VCOLUMN,VROW);π{$ENDIF}π END;π 09:BEGIN { TAB }π GET_LINE_DATA(POSITION, b1,e1,col1);π col1:=tabsize-((position-b1) mod tabsize); { spaces to next tabπstop }π IF (INSERTON) THEN BEGINπ stuff_txt(SPACES(COL1));π SHOW_LINE;π END ELSE BEGINπ INC(VCOLUMN,COL1);π IF VCOLUMN>WIDTH THEN BEGINπ INC(OFFSET,SCRBUMP);π DEC(VCOLUMN,SCRBUMP);π SHOW_TXT;π END;π IF (POSITION+COL1)>E1 THEN BEGINπ POSITION:=E1; XLINE:=TRUE;π END ELSE begin POSITION:=POSITION+COL1; XLINE:=FALSE; END;π{$IFDEF USEQWIK}π GOTORC(R1+VROW-1,C1+VCOLUMN-1);π{$ELSE}π GOTOXY(VCOLUMN,VROW);π{$ENDIF}π END;π END;π 25:BEGIN { CTRL-Y / ERASE LINE }π GET_LINE_DATA(POSITION, b1,e1,col1);π IF E1>TEXTSIZE THEN E1:=E1-B1 ELSE E1:=E1-B1+1;π POSITION:=B1; { E1:=E1-B1+1; }π OFFSET:=0; VCOLUMN:=1;π DEL_CHARS(E1);π SHOW_TXT;π IF POSITION>TEXTSIZE THEN POSITION:=TEXTSIZE+1;π END;π ELSE BEGIN {------------------ unspecific alphanumeric char }π STUFF_TXT(CHR(C)); { store it }π IF MAXCOLUMN=0 THEN BEGIN { check for column boundaries }π IF VCOLUMN>WIDTH THEN BEGINπ INC(OFFSET,SCRBUMP);π DEC(VCOLUMN,SCRBUMP);π SHOW_TXT;π END;π END ELSE BEGIN { limited screen/line size }π SHOW_LINE;π IF ((VCOLUMN+OFFSET)>MAXCOLUMN+1) THEN BEGIN { hit edge limit }π get_line_data(position,b1,e1,col1);π word_wrap(b1,textsize,MAXCOLUMN);π END ELSE BEGINπ IF VCOLUMN>WIDTH THEN BEGIN { maxcolumn>width but set }π INC(OFFSET,SCRBUMP);π DEC(VCOLUMN,SCRBUMP);π SHOW_TXT;π END;π END;π END;π SHOW_LINE;π END;π END; { case }π END { alpha key }π UNTIL LEAVING;πEND;ππ(***************************************************************************)πPROCEDURE SETUP_TEXT_SETTINGS(Row1,Column1,Row2,Column2:BYTE;DRAWBOX:BOOLEAN);π{ sets appropriate system values for text window }πBEGINπ R1:=ROW1; C1:=COLUMN1; R2:=ROW2; C2:=COLUMN2; { set global position of win }π{ % these are arbitrary attribute values - tweak them to suit your tastes }π NORMATTR:=37; { % }π BACKATTR:=37; { % }π BORDATTR:=36; { % }π OFFSET:=0;π INSERTON:=TRUE;π XLINE:=FALSE;π HEIGHT:=R2-R1+1; { current height of text window }π WIDTH:=C2-C1+1; { current width (in columns) of text window }π SCRBUMP:=WIDTH DIV 2;π VROW:=1; { virtual row and column of cursor inside text window }π VCOLUMN:=1;ππ{ % maxcolumn sets automatic formatting and word wrapping !! }π{ MAXCOLUMN:=WIDTH; { set to 0 to disable word wrap and line length limits }π MAXCOLUMN:=0; { no word wrapping }ππ position:=1;π wintop:=1;π IF DRAWBOX THEN BEGINπ DRAW_BOX(R1,C1,R2,C2);π { DRAW_BOX must be prior to initialize window if not using qwik }π INITIALIZE_WINDOW(R1,C1,R2,C2);π END;πEND;π(***************************************************************************)πPROCEDURE EDIT(PT:POINTER;VAR RETURNCODE:BYTE);π{ Edit text; assumes text has already been initialized }πBEGINπ TXT:=PT; { assign specified text pointer to working name }π SHOW_TXT;ππ RETURNCODE:=PARSE_INPUT;π{ RETURNCODE the following values based on keys pressed:π 1=ESCπ 2=ALT-Xπ 3=F1π 4=F10π 5=F2π}πEND;π(***************************************************************************)πEND. { Unit MPEDITOR.PAS }π