home *** CD-ROM | disk | FTP | other *** search
/ DP Tool Club 15 / CD_ASCQ_15_070894.iso / maj / swag / textedit.swg < prev    next >
Text File  |  1994-05-26  |  74KB  |  2 lines

  1. 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╔═
  2.  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 }π