The existing Textwindow-units in SWAG were too simple, and FreeVision is complicated and not ready yet.
This module emulates the Modula2 counterpart A BIT. The module is still under development, but the raw core stands, the rest is changing window colors, implementing shades etc, moving etc.
Opposed to the Modula2(TopSpeeds, not the ISO) version, this module is
Other comments:
The old Runtime-204 bug has been fixed, there are no bugs as far as I know. A very simple errorhandling system has been setup to detect corrupted windows and weird coordinates
The system isn't waterproof, and can be turned of with a conditional. If you however use good coordinates, everything works.
The current system is temporarily I think. If you have suggestions how to handle this kind of errors (create runtime error, do nothing on error(but try to fix data), maybe even signals), let me know.
FPC DOS/Go32v2
(no special Go32V2 bugs afaik). When you use crazy numbers of windows(>50,100), and open and close them without doing much (which delays), screen can flicker a bit. I tried to reduce this by buffering output on the stack, but that wasn't so successful. Anyway, the routine which caused the flicker doesn't reflect a real application anyway, it is more a benchmarking/testing routine.
Dos version opens and closes 500 windows in 5 seconds on a Cyrix P166+
FPC DOS/Go32v1
Status unknown. I use RTL procedures Go32.DosMemGet and -Put, but these do exist under Go32V1. Another incompability might be the assembler procedures (which set/get the cursorsize) for Dos in ELib. If you test under Go32V1, let me know.
Borland Pascal DOS
(no bugs, except that FPC-Crt standard issues highvideo, and Bp-Crt not, which results in blinking attributes.)
I don't test BP as much as the other OSes, so maybe the newest additions may cause some problems.
FPC Linux
Writing to bottom right character (Width,Height) scrolls the screen and messes up screen. Haven't found a working workaround yet.
Linux version seems fast enough now, but I'm running on a Cyrix P166+
The unit is more than usable under Linux, and even faster than make menuconfig (textwindowed kernel-configuration, see your kernel source). Make Menuconfig updates the screen to often. The Crt of the FPC/Linux is very good, and since Ewindow is based on it, it inherites those advantages.
I haven't tried running a program that uses EWindow via a telnet connection, since my second computer is offline.
The release 0.99.8 requires Crt.pp to be patched (See devel directory, only change: virtual screen moved from implementation to interface), newer snapshots (0.99.9 since mid-october) won't have this problem.
Other OS'es not implemented yet, I just wrote a letter to Dan for OS/2 help, and got some response. At least now I'm sure it's possible, and not extremely much work. The OS/2 port will depend on me be able to test under OS/2. IOW, do I get OS/2 installed? :-)
The old approach when redrawing a screen is to
| yyyyyyyy xxxxxxxxx zzzzzzzzz |
On the other hand, the TopSpeed RTL is to good to allow such bugs. I used this module for years, and never saw one flaw. What am I missing! At least I see why such complicated textwindowing units aren't included in SWAG :-)
I still will try to implement above algoritm, since it's the best, but for inbetween I implemented another system, which is much faster than the old one, but a bit slower than the new algoritm, but simpler, mainly because it doesn't require the windowlist (and with that a lot procedures more) to be changed.
The current implementation also only redraw the parts of the screen that have changed, but writes bottom up, which is slower because all windows in the range which is rewritten, are redrawn, instead of only the top ones. Under Dos this is no problem. Under Linux, with it's terminal driven screen it is, so I changed the unit to do the building up of the screen in (fast) memory, not directly on the screen, which is a lot faster.
Maybe it's slow on 386/33's etc, but above 486 DX2/66 speed won't be a problem.
The bottomline is:
(Style definitions are not shown because it contains a lot of high ascii, and will get mangled)
Styles are small arrays with all characters needed to make frames in textwindows. The exact definition may change, so please use one of the predefined styles if you can.
Coordinates
AbsCoord= INTEGER;
RelCoord= INTEGER;
As you can see the above definitions aren't very complex, their main purpose is to let clearly see in the definition what are coordinates for the entire screen (e.g. window-positions), and which ones are positions IN windows. (e.g. cursorposition).
Right now all positions are AbsCoords, even the one marked with RelCoord. The positions typed with RelCoord are scheduled to become real relative coordinates somewhere in the future.
THE main type of this unit. A WinType is a type which describes a certain window. You should never directly manipulate a WinType parameter, or the record it points to. Use the EWindow procedures to achieve what you want.
A WinDef describes all parameters needed to open a new window:
WinDef = RECORD X1,Y1, X2,Y2 : AbsCoord; Coordinates of Window to create Foreground : BYTE; Initial colors of window Background : BYTE; FrameOn : BOOLEAN; Should a frame be created for the window? FrameDef : PChar; Bordertype, POINTER TO Style FrameFore : BYTE; Colors of the frame FrameBack : BYTE; END;WinErrorType (Only exists if compiled with WindowCheck defined).
WinErrorType is an ordinal type which is passed to the errorhandler, and contains the type of error found. WinErrorType is defined as:
TYPE WinErrorType=(WinOk,XTooBig,YTooBig,NilWindow,BadIdent,NilBuffer);The values have the following meaning:
value | place where error was found | meaning |
---|---|---|
WinOk | (No error) | No error, not used, I wanted to reserve ordinal value=0) |
XTooBig | WinDef | The X2 coordinate is smaller than X1. |
YTooBig | WinDef | The Y2 coordinate is smaller than Y1. |
NilWindow | WinType | A procedure received a WinType parameter which was NIL, which isn't allowed for that procedure. |
BadIdent | WinType | A corrupt WinType record was detected |
NilBuffer | WinType | An unallocated (NIL) Window buffer was detected(which will trash next rewrite). |
ScreenTooWide | When updating screen | The screen you tried to update is too wide (probably >132 characters). Increase the InternalBufferSize constant in procedure UpdateScreen to avoid this. I put 132 there to keep memoryusage down. |
VAR Height Width : INTEGER; WinError : WinErrorProc Procedure variable, the errorhandler.Height and Width are the dimensions of the text-mode screen
VAR FullScreen: WinType;"Background window", filled with screen as it was when the unit initialised. (Under dos, empty under Linux, I don't know how to get the startup screen under Linux). Can be used as a normal window.
VAR WinError : WinErrorProcProcedure variable which points to the default errorhandler. Follow above link (WinErrorProc) to find-out more about errorhandling.
Declaration
FUNCTION WinOpen(WD : WinDef):WinType;
Description
Opens a window described by a WinDef, and puts it on top.
The returnvalue is used by the unit for further operations on that window. You'll have to save it.
Notes:
See also WinClose
Example:
CONST WD:WinDef=(X1:10;Y1:13;X2:45;Y2:25;Foreground:White;Background:Black; Frameon:TRUE; FrameDef:Style1;FrameFore:Yellow;FrameBack:Blue); VAR Win : WinType; BEGIN Win:=EWindow.WinOpen(WD); {Open the window} SetTitle(Win,'Window 1'); {Set the title on this framewindow (FRAMEON=TRUE)} Readln; EWindow.WinClose(Win); {Close the @$$%@ Window} END.
Declaration
PROCEDURE WinClose(VAR W:WinType);
Description
Closes the Window associated with the WinType. NIL is assigned to the WinType parameter
Notes:
See also WinOpen
Example:
See WinOpen
Declaration
PROCEDURE SetTitle(W:WinType;Title:PChar);
Description
Sets the title of the window, only use this on Frame-windows. The title is showed in the upper frame-part (centered)
Example:
See WinOpen
Declaration
PROCEDURE Use(VAR W:WinType); Description
Puts the window on top, so that it can be written. Window must be WinOpen first.
Example:
BEGIN Win:=EWindow.WinOpen(WD); {Open the window} Win2:=Ewindow.WinOpen(Win2); {opens a second window, which is on top} Use(Win); {Puts window 1 back on top, so it can be written} EWindow.WinClose(Win2); {You don't have to use a window to close it} EWindow.WinClose(Win); {Close the other Window} END.
Declaration
PROCEDURE Hide(W:WinType);
Description
Hides the window (makes it invisible) Makes the next window in line on top, but that is not 100% defined. You should always issue a Use command after a Hide command.
Notes
BEGIN Win:=EWindow.WinOpen(WD); {Open the window} Hide(Win); {makes Window invisible} ReadLn; UnHide(W); {Makes Window visible again} Readln; EWindow.WinClose(Win); {Close the @$$%@ Window} END.
Declaration
PROCEDURE UnHide(W:WinType);
Description
Unhides the window (makes it visible again). Doesn't put it on top, you should always issue a Use command after an UnHide command.
Notes See Hide
Example: See Hide
Declaration
PROCEDURE Change(W: WinType; OX1,OY1,OX2,OY2: AbsCoord);
Description
Change changes the dimensions and/or position of window W to top left corner (OX1,OY1) and bottom right corner (OX2,OY2).
Only contents which fit in new window are copied, if the new window is bigger, the rest is filled with spaces with the current attributes for that window. If you resize to a smaller dimension, the surplus is lost
See Also WinMove
Example:
BEGIN Win:=EWindow.WinOpen(WD); {Open the window} ReadLn; Change(Win,1,10,20,20); {Change dimensions to (1,10) (20,20)} ReadLn; EWindow.WinClose(Win); {Close the @$$%@ Window} END.
Declaration
PROCEDURE WinMove(W: WinType; OX1,OY1: AbsCoord);
Description
WinMove move a window so that top left of the window is on position (OX1,OY1)
WinMove is faster than Change, cause it doesn't resizes.
See Also Change
Example:
BEGIN Win:=EWindow.WinOpen(WD); {Open the window} ReadLn; WinMove(Win,1,10); {WinMove dimensions to (1,10)} ReadLn; EWindow.WinClose(Win); {Close the @$$%@ Window} END.
Declaration
PROCEDURE Clear(W:WinType);
Description
Clears a window with the proper attributes, and performs a GotoXY(1,1);
Crt.ClrScr may seem work right in Dosmode, but maybe it won't on other
platforms. Clear is also faster, and allows you to clear a window which
is not on top.
Example:
BEGIN Win:=EWindow.WinOpen(WD); {Open the window} Writeln('text'); ReadLn; Clear(Win); {Clear the window} ReadLn; EWindow.WinClose(Win); {Close the @$$%@ Window} END.
Declaration
FUNCTION WinClone(W:WinType):WinType;
Description
Clone window W, hide de clone and return the cloned window.
Example:
VAR Win1,Win2 :WinType; BEGIN Win:=EWindow.WinOpen(WD); {Open the window} ReadLn; Win2:=WinClone(Win); {Clear the window} Writeln('text'); {Write text to the original window} WinMove(Win2,10,10); {Move Win2 to another position} Unhide(Win2); {Unhide it} Use(Win2); {Put on top and redirect output to it} writeln('Not the same text'); ReadLn; EWindow.WinClose(Win); {Close the @$$%@ Window} EWindow.WinClose(Win2); {Close the @$$%@ Window} END.
Declaration
PROCEDURE WrapWrite(CONST Towrite:String);
PROCEDURE WrapWriteLn(CONST Towrite:String);
Description
Writes string Towrite to the current Window, and tries to wrap the text in it. WrapWriteLn adds a linefeed.
Example:
VAR Win1,Win2 :WinType; BEGIN Win:=EWindow.WinOpen(WD); {Open the window} WrapWriteln('A longer text than which will fit into this window on one line I hope'); ReadLn; EWindow.WinClose(Win); {Close the @$$%@ Window} END.