home *** CD-ROM | disk | FTP | other *** search
- (* ------------------------------------------------------ *)
- (* MODEDIT.MOD *)
- (* FST-Editor, die erste... *)
- (* (c) 1991 W.Rinke & TOOLBOX *)
- (* ------------------------------------------------------ *)
- MODULE ModEdit;
-
- (* $L+ *)
-
- IMPORT InOut;
- IMPORT ASCII;
- IMPORT Keyboard;
-
- FROM SYSTEM IMPORT ADR;
- FROM System IMPORT GetArg, Move;
- FROM Strings IMPORT Length, Concat, Delete, Append,
- Insert, Copy;
- FROM Windows IMPORT Window, OpenWindow,
- SelectWindow, CloseWindow;
- FROM Display IMPORT DisplayString, ReadCharAttr,
- displayAttr,
- line0, col0, lineN, colN,
- ScrollUp, DisplayLine,
- DisplayBuffer,
- ReadScreen, WriteScreen,
- displayPtr, Goto;
- FROM Keyboard IMPORT KeyPressed, GetKey, GetKeyCh;
- FROM NumberConversion IMPORT CardToString;
- FROM FileSystem IMPORT Response, File, Lookup, Close,
- Reset, Rewrite, Rename,
- ReadChar, WriteChar,
- WriteNBytes;
- FROM Storage IMPORT ALLOCATE, DEALLOCATE;
-
- (* ------------------------------------------------------ *)
-
- CONST
- MAXLINES = 15600;
-
- TYPE
- STRING = ARRAY [0..80] OF CHAR;
- StrPtr = POINTER TO STRING;
-
- VAR
- Lines : ARRAY [1..MAXLINES] OF StrPtr;
- FirstOnScreen : CARDINAL;
- TextLine : CARDINAL;
- TextCol : CARDINAL;
- MaxLine : CARDINAL;
- TextMaxY : CARDINAL;
-
- InfoBuffer : ARRAY [0..79] OF CARDINAL;
- ErrorMessage : ARRAY [1..6] OF STRING;
- InfoMessage : STRING;
- InfoColor : CARDINAL;
- ErrorColor : CARDINAL;
- TextColor : CARDINAL;
- EntryColor : CARDINAL;
- LastMode : CARDINAL;
-
- Done : BOOLEAN;
- InsertMode : BOOLEAN;
- Modified : BOOLEAN;
- FileName : STRING;
- NextFile : STRING;
- TextFile : File;
-
- (* ------------------------------------------------------ *)
-
- PROCEDURE ClrScr; (* ok *)
- BEGIN
- ScrollUp(0, line0, col0, lineN, colN, displayAttr);
- (* löscht das Fenster mit den aktuellen Koordinaten *)
- (* analog zu Turbo Pascal. *)
- END ClrScr;
-
- (* ------------------------------------------------------ *)
-
- PROCEDURE Wait; (* ok *)
- VAR
- c : CHAR;
- BEGIN
- REPEAT UNTIL KeyPressed(); GetKey(c);
- END Wait;
-
- (* ------------------------------------------------------ *)
-
- PROCEDURE UpString(VAR s : STRING); (* ok *)
- VAR
- i : CARDINAL;
- BEGIN
- FOR i := 0 TO Length(s) DO
- s[i] := CAP(s[i]);
- END;
- END UpString;
-
- (* ------------------------------------------------------ *)
-
- PROCEDURE GetParams(VAR s : STRING); (* ok *)
- VAR
- l : CARDINAL;
- BEGIN
- GetArg(s, l);
- UpString(s);
- END GetParams;
-
- (* ------------------------------------------------------ *)
-
- PROCEDURE Init;
- VAR
- c : CHAR;
- BEGIN
- ReadCharAttr(c, LastMode);
-
- InfoColor := 3FH; (* Cyan/White *)
- TextColor := 1EH; (* Blue/Yellow *)
- ErrorColor := 4FH; (* Red/White *)
- EntryColor := 70H; (* LightGray/Black *)
-
- ErrorMessage[1] := 'Datei nicht gefunden';
- ErrorMessage[2] := 'Lesefehler';
- ErrorMessage[3] := 'Fehler beim Speichern';
- ErrorMessage[4] := 'Laufwerk nicht bereit';
- ErrorMessage[5] := 'Text paßt nicht in den Speicher';
- ErrorMessage[6] := 'Programm normal beendet';
-
- InsertMode := TRUE;
- TextLine := 1; TextCol := 1; TextMaxY := 24;
-
- InfoMessage := ' Datei: ';
- GetParams(FileName);
- UpString(FileName);
- Append(InfoMessage, FileName);
- Modified := FALSE;
- IF Length(FileName) > 0 THEN
- IF NOT LoadFile(FileName) THEN
- InitEmptyText;
- END;
- END;
- Goto(0, 0); ClrScr;
- END Init;
-
- (* ------------------------------------------------------ *)
-
- PROCEDURE QuitProgram; (* ok *)
- BEGIN
- displayAttr := LastMode;
- ClrScr;
- Done := TRUE;
- (* Löst das Problem mit der HALTED-message *)
- END QuitProgram;
-
- (* ------------------------------------------------------ *)
-
- PROCEDURE HelpScreen; (* ok *)
- VAR
- w : Window;
- a : CARDINAL;
- c : CHAR;
- BEGIN
- a := InfoColor;
- displayAttr := InfoColor;
- OpenWindow(w, 6, 20, 20, 61, TRUE, ' Hilfe ');
- SelectWindow(w, TRUE);
- DisplayString('Spezielle Befehle des toolbox-Editors: ',
- 0, 1, a);
- DisplayString('-------------------------------------- ',
- 1, 1, a);
- DisplayString(' ',
- 2, 1, a);
- DisplayString(' <F2> Sichern ',
- 3, 1, a);
- DisplayString(' <F3> Laden ',
- 4, 1, a);
- DisplayString(' <Alt>-<F2> Sichern als ',
- 5, 1, a);
- DisplayString(' <Ctrl>-<Home> Textanfang ',
- 6, 1, a);
- DisplayString(' <Crtl>-<End> Textende ',
- 7, 1, a);
- DisplayString(' <Ins> Einfügen/Überschreiben ',
- 8, 1, a);
- DisplayString(' <Ctrl>-<N> Zeile einfügen ',
- 9, 1, a);
- DisplayString(' <Ctrl>-<Y> Zeile löschen ',
- 10, 1, a);
- DisplayString(' ',
- 11, 1, a);
- DisplayString(' weiter mit beliebiger Taste ... ',
- 12, 1, a);
- Wait;
- CloseWindow(w);
- displayAttr := TextColor;
- END HelpScreen;
-
- (* ------------------------------------------------------ *)
-
- PROCEDURE UpdateInfoLine; (* ok *)
- VAR
- Info, sLine, sCol : STRING;
- BEGIN
- Info := '[';
- IF Modified THEN
- Append(Info, 17C);
- ELSE
- Append(Info, ' ');
- END;
- Append(Info, '] F1=Hilfe Pos: ');
- CardToString(TextLine, sLine, 5);
- CardToString(TextCol, sCol, 2);
- Append(Info, sLine);
- Append(Info, ':');
- Append(Info, sCol);
- Append(Info, ' Modus: ');
- IF InsertMode THEN
- Append(Info, 'INS ');
- ELSE
- Append(Info, 'OVR ');
- END;
- Append(Info, ' Datei: ');
- Append(Info, InfoMessage);
- DisplayLine(Info, 24, InfoColor);
- END UpdateInfoLine;
-
- (* ------------------------------------------------------ *)
-
- PROCEDURE SaveInfoLine; (* ok *)
- BEGIN
- ReadScreen(ADR(displayPtr^[24]), ADR(InfoBuffer), 80);
- END SaveInfoLine;
-
- (* ------------------------------------------------------ *)
-
- PROCEDURE RestoreInfoLine; (* ok *)
- BEGIN
- WriteScreen(ADR(InfoBuffer), ADR(displayPtr^[24]), 80);
- END RestoreInfoLine;
-
- (* ------------------------------------------------------ *)
-
- PROCEDURE ShowError(Nr : CARDINAL; Fatal : BOOLEAN);
- VAR (* ok *)
- ErrLine : STRING;
- c : CHAR;
- BEGIN
- SaveInfoLine;
- Concat(ErrorMessage[Nr], ' - Taste...', ErrLine);
- DisplayLine(ErrLine, 24, ErrorColor);
- Wait;
- RestoreInfoLine;
- IF Fatal THEN QuitProgram; END;
- END ShowError;
-
- (* ------------------------------------------------------ *)
-
- PROCEDURE ToggleInsert; (* ok *)
- BEGIN
- InsertMode := NOT InsertMode;
- UpdateInfoLine;
- END ToggleInsert;
-
- (* ------------------------------------------------------ *)
-
- PROCEDURE GetFileName(VAR FName : STRING; Msg : STRING);
- VAR (* ok *)
- Entry : STRING;
- LeftStop : CARDINAL;
- c : CHAR;
- BEGIN
- SaveInfoLine;
- Entry := ''; FName := '';
- Concat(' Eingabe -> ', Msg, Entry);
- LeftStop := Length(Entry);
- LOOP
- DisplayLine(Entry, 24, EntryColor);
- GetKey(c);
- IF c = ASCII.bs THEN
- IF Length(Entry) - LeftStop > 0 THEN
- Delete(Entry, Length(Entry)-1, 1);
- Delete(FName, Length(FName)-1, 1);
- END;
- ELSIF c = ASCII.cr THEN
- EXIT;
- ELSE
- c := CAP(c);
- Append(Entry, c); Append(FName, c);
- DisplayLine(Entry, 24, EntryColor);
- END;
- END;
- RestoreInfoLine;
- END GetFileName;
-
- (* ------------------------------------------------------ *)
-
- PROCEDURE GetNewLine; (* ok *)
- BEGIN
- INC(MaxLine);
- NewStr(Lines[MaxLine]);
- END GetNewLine;
-
- (* ------------------------------------------------------ *)
-
- PROCEDURE NewStr(VAR p : StrPtr);
- BEGIN
- ALLOCATE(p, SIZE(p^));
- IF p = NIL THEN ShowError(5, TRUE); END;
- END NewStr;
-
- PROCEDURE DisposeStr(p : StrPtr);
- BEGIN
- IF p <> NIL THEN DEALLOCATE(p, SIZE(p^)); END;
- END DisposeStr;
-
- (* ------------------------------------------------------ *)
-
- PROCEDURE InitEmptyText; (* ok *)
- VAR
- i : CARDINAL;
- BEGIN
- MaxLine := 0;
- displayAttr := TextColor; ClrScr;
- FOR i := 1 TO TextMaxY DO
- GetNewLine;
- Lines[i]^ := '';
- END; (* sonst bringt Scroll wirre *)
- (* Zeichen auf den Bildschirm. *)
- FirstOnScreen := 1;
- TextLine := 1;
- TextCol := 1;
- END InitEmptyText;
-
- (* ------------------------------------------------------ *)
-
- PROCEDURE Scroll(Val : INTEGER); (* ok *)
- VAR
- n : CARDINAL;
- BEGIN
- IF MaxLine = 0 THEN RETURN; END;
- IF (INTEGER(FirstOnScreen) + Val) < 1 THEN
- FirstOnScreen := 1; TextLine := 1;
- ELSE
- FirstOnScreen :=
- CARDINAL(INTEGER(FirstOnScreen) + Val);
- TextLine :=
- CARDINAL(INTEGER(TextLine) + Val);
- IF FirstOnScreen > (MaxLine - TextMaxY + 1) THEN
- FirstOnScreen := (MaxLine - TextMaxY + 1);
- (* na, Gerald ? *)
- END;
- IF TextLine > MaxLine THEN
- TextLine := MaxLine;
- END;
- END;
- UpdateInfoLine;
- IF Val = 1 THEN
- (* das Zeilenpaket, das in der zweiten Zeile *)
- (* beginnt und in der vorletzten Zeile endet, *)
- (* komplett um eine Zeile nach oben verschieben. *)
- Move(ADR(displayPtr^[1]), ADR(displayPtr^[0]),
- (TextMaxY - 1) * 160); (* 23 * 80 * 2 Byte *)
-
- (* neue letzte Zeile aus dem DateiPuffer holen *)
- DisplayLine(Lines[FirstOnScreen + TextMaxY - 1]^,
- TextMaxY - 1, TextColor); (* ok *)
- ELSIF Val = -1 THEN
- Move(ADR(displayPtr^[0]), ADR(displayPtr^[1]),
- (TextMaxY - 1) * 160);
-
- (* neue erste Zeile aus dem Dateipuffer holen *)
- DisplayLine(Lines[FirstOnScreen]^, 0, TextColor);
- ELSE
- FOR n := FirstOnScreen TO
- FirstOnScreen + TextMaxY - 1 DO
- DisplayLine(Lines[n]^, n-FirstOnScreen, TextColor);
- END;
- END;
- END Scroll;
-
- (* ------------------------------------------------------ *)
-
- PROCEDURE LoadFile(Name : STRING) : BOOLEAN; (* ok *)
- VAR
- n : CARDINAL;
- s : STRING;
- c : CHAR;
- BEGIN
- Lookup(TextFile, Name, TRUE); (* neue Datei *)
- InitEmptyText; (* ok *)
- IF TextFile.eof THEN
- RETURN FALSE; (* ok *)
- ELSE
- n := 0;
- MaxLine := 0;
- SaveInfoLine;
- Concat(' Lade Datei ', Name, s);
- DisplayLine(s, 24, InfoColor);
- WHILE NOT TextFile.eof DO
- s := '';
- REPEAT
- ReadChar(TextFile, c);
- IF c >= ' ' THEN Append(s, c); END;
- (* Steuercodes nicht aufnehmen *)
- UNTIL (c = ASCII.EOL) OR TextFile.eof;
- GetNewLine;
- Lines[MaxLine]^ := s;
- END;
- Close(TextFile);
- RestoreInfoLine;
- FirstOnScreen := 0;
- TextLine := 1;
- TextCol := 1;
- Scroll(0); Goto(0, 0);
- RETURN TRUE;
- END;
- END LoadFile;
-
- (* ------------------------------------------------------- *)
-
- PROCEDURE F3Key; (* ok *)
- BEGIN
- UpdateInfoLine;
- GetFileName(NextFile, 'Datei laden: ');
- IF Length(NextFile) > 0 THEN
- IF LoadFile(NextFile) THEN
- FileName := NextFile;
- InfoMessage := FileName;
- Modified := FALSE;
- UpdateInfoLine;
- ELSE
- ShowError(1, FALSE);
- END;
- END;
- END F3Key;
-
- (* ------------------------------------------------------ *)
-
- PROCEDURE SaveFile(Name : STRING) : BOOLEAN; (* ok *)
- VAR
- Info : STRING;
- i, j : CARDINAL;
- Buffer : STRING;
- BEGIN
- SaveInfoLine;
- Info := ' Speichere Datei ';
- Append(Info, Name);
- Append(Info, '...');
- DisplayLine(Info, 24, InfoColor);
- Lookup(TextFile, Name, TRUE);
- Rewrite(TextFile);
- FOR i := 1 TO MaxLine DO
- Buffer := Lines[i]^;
- WriteNBytes(TextFile, ADR(Buffer), Length(Buffer), j);
- IF j <> Length(Buffer) THEN
- Close(TextFile);
- RETURN FALSE;
- END;
- (* Bis hier sind die Zeilenumbrüche verloren ... *)
- WriteChar(TextFile, ASCII.CR);
- WriteChar(TextFile, ASCII.LF); (* ok *)
- END;
- Close(TextFile);
- RestoreInfoLine;
- Modified := FALSE;
- RETURN TRUE;
- END SaveFile;
-
- (* ------------------------------------------------------ *)
-
- PROCEDURE AltF2Key; (* ok *)
- BEGIN
- GetFileName(NextFile, ' Datei speichern als: ');
- IF Length(NextFile) <> 0 THEN
- FileName := NextFile;
- IF NOT SaveFile(FileName) THEN
- ShowError(3, FALSE);
- END;
- InfoMessage := FileName;
- UpdateInfoLine;
- END;
- END AltF2Key;
-
- (* ------------------------------------------------------ *)
- (* geht unter FST Modula in die Hose ... *)
-
- PROCEDURE ReleaseLine;
- BEGIN
- DisposeStr(Lines[MaxLine]);
- DEC(MaxLine);
- END ReleaseLine;
-
- (* ------------------------------------------------------ *)
-
- PROCEDURE DeleteLine(Line : CARDINAL);
- VAR
- i : CARDINAL;
- BEGIN
- IF MaxLine > 0 THEN
- FOR i := Line TO MaxLine - 1 DO
- Lines[i] := Lines[i+1];
- END;
- (* ReleaseLine; *)
- (* Erstmal sehen, ob der Heap das verträgt ... *)
- END;
- END DeleteLine;
-
- (* ------------------------------------------------------ *)
-
- PROCEDURE InsertLine(Line : CARDINAL); (* ok *)
- VAR
- i : CARDINAL;
- Last : StrPtr;
- BEGIN
- GetNewLine;
- Last := Lines[MaxLine];
- FOR i := MaxLine-1 TO Line BY -1 DO
- Lines[i+1] := Lines[i];
- END;
- Lines[Line] := Last;
- Lines[Line]^ := '';
- END InsertLine;
-
- (* ------------------------------------------------------ *)
-
- PROCEDURE EnterKey; (* ok *)
- VAR
- s1, s2 : STRING;
- BEGIN
- IF InsertMode THEN
- Copy(Lines[TextLine]^, 0, TextCol-1, s1);
- Copy(Lines[TextLine]^, TextCol-1,
- Length(Lines[TextLine]^), s2);
- InsertLine(TextLine);
- Lines[TextLine]^ := s1;
- Lines[TextLine+1]^ := s2;
- TextCol := 1;
- IF TextLine - FirstOnScreen <= TextMaxY - 2 THEN
- INC(TextLine);
- END;
- Scroll(0);
- ELSE
- IF TextLine < MaxLine THEN
- TextCol := 1;
- IF TextLine - FirstOnScreen > TextMaxY - 2 THEN
- Scroll(1);
- ELSE
- INC(TextLine);
- END;
- ELSE
- GetNewLine;
- Lines[MaxLine]^ := '';
- END;
- END;
- END EnterKey;
-
- (* ------------------------------------------------------ *)
-
- PROCEDURE EditLine(y : CARDINAL; x : CARDINAL; ch : CHAR);
- BEGIN (* ok *)
- IF (ch > 31C) AND (ch < 377C) THEN
- IF InsertMode THEN
- IF Length(Lines[y]^) < 80 THEN
- Insert(ch, Lines[y]^, x-1);
- INC(TextCol);
- END;
- ELSE
- Lines[y]^[x-1] := ch;
- INC(TextCol);
- IF TextCol > 80 THEN
- TextCol := 1;
- INC(TextLine);
- END;
- END;
- Scroll(0);
- END;
- END EditLine;
-
- (* ------------------------------------------------------ *)
-
- PROCEDURE DeleteKey; (* ok *)
- VAR
- L1, L2 : CARDINAL;
- s : STRING;
- BEGIN
- L1 := Length(Lines[TextLine]^);
- IF TextLine + 1 <= MaxLine THEN
- L2 := Length(Lines[TextLine + 1]^);
- END;
- IF TextCol < L1 THEN
- Delete(Lines[TextLine]^, TextCol-1, 1);
- Scroll(0);
- ELSE
- IF TextLine + 1 > MaxLine THEN RETURN; END;
- IF L2 <= 80 - L1 THEN
- Concat(Lines[TextLine]^, Lines[TextLine+1]^,
- Lines[TextLine]^);
- DeleteLine(TextLine+1);
- Scroll(0);
- ELSE
- Copy(Lines[TextLine+1]^, 0, 80-L1, s);
- Concat(Lines[TextLine]^, s, Lines[TextLine]^);
- Delete(Lines[TextLine+1]^, 1, 80-L1);
- Scroll(0);
- END;
- END;
- END DeleteKey;
-
- (* ------------------------------------------------------ *)
-
- PROCEDURE BSKey; (* ok *)
- VAR
- L1, L0 : CARDINAL;
- s : STRING;
- BEGIN
- L1 := Length(Lines[TextLine]^);
- IF TextLine > 1 THEN
- L0 := Length(Lines[TextLine - 1]^);
- END;
- IF TextCol > 1 THEN
- Delete(Lines[TextLine]^, TextCol-2, 1); (* ok *)
- DEC(TextCol);
- Scroll(0);
- ELSE
- IF TextLine = 1 THEN RETURN; END;
- IF L0 <= 80 - L1 THEN
- TextCol := L0 + 1;
- Concat(Lines[TextLine-1]^, Lines[TextLine]^,
- Lines[TextLine]^);
- DEC(TextLine);
- DeleteLine(TextLine); (* hier ist jetzt noch ein kleiner bug *)
- Scroll(0);
- ELSE
- Copy(Lines[TextLine]^, 1, 80-L0, s);
- Concat(Lines[TextLine-1]^, s, Lines[TextLine-1]^);
- Delete(Lines[TextLine]^, 1, 80-L0);
- Scroll(0);
- END;
- END;
- END BSKey;
-
- (* ------------------------------------------------------ *)
- (* Hauptsteuerleiste *)
-
- PROCEDURE Edit;
- VAR
- Done : BOOLEAN;
- c : CHAR;
- BEGIN
- Done := FALSE;
- REPEAT
- UpdateInfoLine;
- Goto(TextLine - FirstOnScreen, TextCol - 1);
- GetKeyCh(c);
- CASE c OF
- ASCII.esc : ShowError(6, FALSE); (* normal *)
- Done := TRUE; (* ok *)
- | ASCII.cr : EnterKey; (* ok *)
- Modified := TRUE;
- | ASCII.bs : BSKey; (* ok *)
- Modified := TRUE;
- | ASCII.CtrlN : InsertLine(TextLine); (* ok *)
- Modified := TRUE;
- Scroll(0);
- | ASCII.CtrlY : DeleteLine(TextLine); (* ok *)
- Modified := TRUE;
- Scroll(0);
- | Keyboard.F1 : HelpScreen; (* ok *)
- | Keyboard.F2 : IF NOT SaveFile(FileName) THEN
- ShowError(3, FALSE);
- END; (* ok *)
- | Keyboard.AF2 : AltF2Key; (* ok *)
- | Keyboard.F3 : F3Key; (* ok *)
- | Keyboard.AltX : Done := SaveFile(FileName);
- | Keyboard.Ins : ToggleInsert; (* ok *)
- | Keyboard.Del : DeleteKey; (* ok *)
- | Keyboard.Down : IF TextLine < MaxLine THEN
- IF TextLine - FirstOnScreen >
- TextMaxY - 2 THEN
- Scroll(1);
- ELSE
- INC(TextLine);
- END;
- END; (* ok *)
- | Keyboard.Up : IF TextLine > 1 THEN
- IF TextLine <
- FirstOnScreen + 1 THEN
- Scroll(-1);
- ELSE
- DEC(TextLine);
- END;
- END; (* ok *)
- | Keyboard.Left : IF TextCol > 1 THEN
- DEC(TextCol);
- END; (* ok *)
- | Keyboard.Right : IF TextCol < 80 THEN
- INC(TextCol);
- END; (* ok *)
- | Keyboard.Home : TextCol := 1; (* ok *)
- | Keyboard.End : TextCol :=
- Length(Lines[TextLine]^)+1;
- | Keyboard.PgUp : Scroll(1-TextMaxY); (* ok *)
- | Keyboard.PgDn : Scroll(TextMaxY-1); (* ok *)
- | Keyboard.CtrlEnd : FirstOnScreen :=
- MaxLine - TextMaxY + 1;
- TextLine := MaxLine;
- Scroll(0); (* ok *)
- | Keyboard.CtrlHome : TextLine := 1;
- FirstOnScreen := 1;
- Scroll(0); (* ok *)
- ELSE
- Modified := TRUE;
- EditLine(TextLine, TextCol, c); (* ok *)
- END;
- UNTIL Done;
- IF Modified THEN (* wat mutt, dat mutt! *)
- (* Zumindest fragen: "geänderte Datei speichern?" *)
- END;
- END Edit;
-
- (* ------------------------------------------------------ *)
-
- BEGIN
- Init;
- Edit;
- QuitProgram;
- END ModEdit.
-
- (* ------------------------------------------------------ *)
- (* Ende von MODEDIT.MOD *)
-