language-Modula2-0.1: examples/Modula-2_Libraries/PMOS/sources/new/docread.mod
MODULE DocRead;
(********************************************************)
(* *)
(* Program to display documentation files *)
(* *)
(* Programmer: P. Moylan *)
(* Last edited: 11 December 1994 *)
(* Status: Just started, incomplete *)
(* *)
(* At present I'm just playing around with ideas; *)
(* it would take a lot of work to turn this into *)
(* a hypertext reader. *)
(* Thought: we need to distinguish between *)
(* hypertext files and "raw text" files - e.g. in *)
(* the latter we should keep the existing line *)
(* breaks, in the former we should treat carriage *)
(* return characters like whitespace. *)
(* *)
(* Such details can however wait until I've done *)
(* improvements to the menu system, i.e. for now *)
(* this is a test program for menus. *)
(* *)
(********************************************************)
FROM TaskControl IMPORT
(* proc *) CreateTask;
FROM Semaphores IMPORT
(* type *) Semaphore,
(* proc *) CreateSemaphore, Wait, Signal;
FROM Windows IMPORT
(* type *) Window, Colour, FrameType, DividerType, Rectangle,
(* proc *) OpenWindow, CloseWindow, WriteString, PressAnyKey,
WriteChar, WriteLn, WindowLocation;
FROM NumericIO IMPORT
(* proc *) WriteCard;
FROM Menus IMPORT
(* type *) Menu, ItemText, MenuOption, MO, OffEdgeOption,
(* proc *) CreateMenu, PositionMenu, SelectFromMenu, DestroyMenu,
SetOptions, OffEdge;
FROM IOErrorCodes IMPORT
(* type *) ErrorCode;
FROM FileSys IMPORT
(* type *) File,
(* proc *) OpenFile, CloseFile, EOF, ReadByte,
SetPosition, SavePosition;
(************************************************************************)
TYPE
CharSet = SET OF CHAR;
CONST
alphanum = CharSet {"A".."Z", "a".."z", "0".."9"};
VAR
done: Semaphore;
(************************************************************************)
(* FILE DISPLAY PROCEDURES *)
(************************************************************************)
PROCEDURE BackSpace (f: File);
(* Moves backwards by one byte in file f. *)
VAR dummy: ErrorCode;
BEGIN
dummy := SetPosition (f, SavePosition(f) - 1);
END BackSpace;
(************************************************************************)
PROCEDURE SkipBlanks (f: File);
(* Skips over nonsignificant characters in file f. *)
CONST BlankChars = CharSet {CHR(0), CHR(10), " "};
BEGIN
WHILE CHAR(ReadByte(f)) IN BlankChars DO
(* nothing *)
END (*WHILE*);
BackSpace (f);
END SkipBlanks;
(************************************************************************)
PROCEDURE ReadWord (f: File; VAR (*OUT*) word: ARRAY OF CHAR;
VAR (*OUT*) terminator: CHAR): CARDINAL;
(* Reads an alphanumeric string, returns the string in "word" and *)
(* the trailing nonalphanumeric character in "terminator". The *)
(* function result is the length of "word". *)
CONST Nul = CHR(0);
VAR j: CARDINAL; ch: CHAR;
BEGIN
SkipBlanks(f);
j := 0; terminator := CHR(0);
LOOP
IF j > HIGH(word) THEN EXIT(*LOOP*) END(*IF*);
ch := ReadByte (f);
IF ch IN alphanum THEN
word[j] := ch; INC(j);
ELSE
terminator := ch; word[j] := Nul; EXIT (*LOOP*);
END (*IF*);
END (*LOOP*);
RETURN j;
END ReadWord;
(************************************************************************)
PROCEDURE DisplayFile (w: Window; f: File);
(* Displays file f in window w. The file and window must already *)
(* be open. *)
CONST Space = " ";
VAR R: Rectangle;
row, col, maxrow, maxcol, length: CARDINAL;
word: ARRAY [0..79] OF CHAR;
terminator: CHAR;
BEGIN
WriteLn (w);
WriteString (w, "Procedure DisplayFile not yet written.");
R := WindowLocation (w);
maxrow := R.bottom - R.top + 1;
maxcol := R.right - R.left + 1;
row := 1; col := 0;
LOOP
IF EOF(f) THEN EXIT(*LOOP*) END (*IF*);
IF row > maxrow THEN EXIT (*LOOP*) END(*IF*);
length := ReadWord (f, word, terminator);
IF terminator <> Space THEN INC(length) END(*IF*);
IF col+length > maxcol THEN
WriteLn (w); INC (row); col := 0;
END (*IF*);
WriteString (w, word);
IF terminator <> Space THEN
WriteChar (w, terminator);
END (*IF*);
INC (col, length);
IF (word[0] <> CHR(0)) AND (col < maxcol) THEN
WriteChar (w, Space); INC(col);
END (*IF*);
END (*LOOP*);
END DisplayFile;
(************************************************************************)
PROCEDURE DoDisplay (filename: ARRAY OF CHAR);
(* Displays the given file. *)
VAR w: Window; f: File; status: ErrorCode;
BEGIN
OpenWindow (w, white, magenta, 5, 20, 0, 79, noframe, nodivider);
status := OpenFile (f, filename, FALSE);
WriteLn (w); WriteString (w, "Entered procedure DoDisplay");
IF status <> OK THEN
WriteLn (w); WriteString (w, "Can't open file ");
WriteString (w, filename);
ELSE
DisplayFile (w, f);
END (*IF*);
PressAnyKey (w);
CloseFile (f);
CloseWindow (w);
END DoDisplay;
(************************************************************************)
PROCEDURE DisplayTask;
BEGIN
DoDisplay ("..\doc\status.doc");
Signal (done);
END DisplayTask;
(************************************************************************)
(* MENU OPERATIONS *)
(* At present this part of the program is just a test of Menus. *)
(************************************************************************)
PROCEDURE Actions2 (option: CARDINAL);
(* Implements the actions on submenu number 2. *)
BEGIN
END Actions2;
(************************************************************************)
PROCEDURE MenuTask;
(* Runs as a separate task, picking up menu commands. *)
VAR topmenu, menu1, menu2: Menu; w: Window;
topmenutext: ARRAY [0..5] OF ItemText;
menu1text: ARRAY [0..1] OF ItemText;
menu2text: ARRAY [0..2] OF ItemText;
result: CARDINAL;
BEGIN
OpenWindow (w, black, white, 21, 24, 50, 79, noframe, nodivider);
(* Create top-level menu. *)
topmenutext[0] := "TOP MENU";
topmenutext[1] := " \File";
topmenutext[2] := " \Options";
topmenutext[3] := " dummy\3";
topmenutext[4] := " dummy\4";
topmenutext[5] := " dummy\5";
CreateMenu (topmenu, 5, topmenutext, 5);
SetOptions (topmenu, MO{MNoTitle,MNoBorder,MNoClose,MNoKeyBack,
MFastSelect});
OffEdge (topmenu, stick, return, wrap, wrap);
PositionMenu (topmenu, 0, 0, 0, 79);
(* Create subsidiary menus. *)
menu1text[0] := "MENU 1";
menu1text[1] := "E\xit";
CreateMenu (menu1, 1, menu1text, 1);
SetOptions (menu1, MO{MNoTitle,MFastSelect});
OffEdge (menu1, escape, wrap, stick, escape);
PositionMenu (menu1, 1, 3, 0, 10);
menu2text[0] := "MENU 2";
menu2text[1] := "Page \up";
menu2text[2] := "Page \down";
CreateMenu (menu2, 1, menu2text, 2);
SetOptions (menu2, MO{MNoTitle,MFastSelect});
OffEdge (menu2, escape, wrap, escape, escape);
PositionMenu (menu2, 1, 4, 14, 24);
REPEAT
result := SelectFromMenu (topmenu);
WriteLn (w);
WriteString (w, "Selected top menu item ");
WriteCard (w, result);
CASE result OF
| 1: result := SelectFromMenu(menu1);
result := 1 - result;
| 2: Actions2 (SelectFromMenu(menu2));
END (*CASE*);
UNTIL result = 0;
DestroyMenu (menu1);
DestroyMenu (topmenu);
(* PressAnyKey (w); *)
CloseWindow (w);
Signal (done);
END MenuTask;
(************************************************************************)
(* MAIN PROGRAM *)
(************************************************************************)
BEGIN
CreateSemaphore (done, 0);
(* CreateTask (DisplayTask, 2, "display task"); *)
CreateTask (MenuTask, 3, "menu task");
Wait (done);
(* Wait (done); *)
END DocRead.