|

How to write an editor - Chapter 2 - by Aiwendil
Users, no matter how annoying, are always to take into consideration
The screen, here we have a thing that actually are tricky in linux since a screen can be just about anywhere from 1*2 to 255*255 chars, I will assume that you will solve that problem for youself and also another nice problem, that linux usually tend to expand tabs and such itself.
screen.pas are what we are working with in this part unless otherwise specified. also, it is assumed that you use the unit buffers specified in part1 and the unit CRT or equialant, what we need are the routines gotoxy and clrscr.
First we need to define a type for windowed controls, in dos this step is skipped by most programmers and inserted later with a great effort, in linux you almost must implement this right away since the size of the screen can vary a lot, using this approach will also make it lots easier to implement multiple document interface.
TYPE tWindow = RECORD
XPos : Byte;
YPos : Byte;
XLength : Byte;
YLength : Byte;
BufferList : tBufferList;
END;
There, it is pretty straightforward, I know that YLength would be more correct to call YHeight instead but I prefer to keep the code uniform instead of correct according to some rules one don't really have to pay attention to while coding.
First we need a procedure to init the tWindow to nice defaults;
PROCEDURE InitWindow(VAR Window:tWindow);
BEGIN
WITH Window DO BEGIN
XPos := 1;
YPos := 1;
XLength := 80;
YLength:=25;
InitBufferList(BufferList);
END;
END;
Ok, that wasn't so hard, and I doubt you need to have that one explained.
Now, time to make the partial update-routine, this one will be called upon frequently so here it is to favour speed over memory.
PROCEDURE WindowUpdate(CurX,CurY,X,XLen,Depth:Byte;Dir:Boolean;
VAR Buffer:pBuffer);
{CurX/CurY is the row/column to start writing on.
X is on which position in Data to start with.
XLen is the number of chars to write for each line.
Depth is the number of levels to go.
Dir is which direction to go. True = Next, False = Prev.
Buffer is the the first Buffer to work with}
VAR TmpBuffer : pBuffer;
B : Byte;
S : STRING;
BEGIN
IF (Depth=0) OR (X=0) OR (XLen=0) THEN Exit;
TmpBuffer:=Buffer;
FOR B:=1 TO Depth DO BEGIN
GotoXY(CurX,CurY+B-1);
FillChar(S[1],XLen,' ');
IF TmpBuffer<>NIL THEN S:=Copy(GetBufferData(TmpBuffer),X,XLen);
S[0]:=Chr(XLen);
Write(S);
IF TmpBuffer<>NIL THEN
IF Dir THEN TmpBuffer:=BufferNext(TmpBuffer)
ELSE TmpBuffer:=BufferPrev(TmpBuffer);
END;
END;
The above procedure will have a rather fun bug on many but not all systems, let's see if you can figure it out and catch it :)
And now an updater for the entire window
PROCEDURE UpdateEntireWindow(X:Byte;Dir:Boolean;VAR Buffer:pBuffer;
Window:tWindow);
{for explanation of parameters see WindowUpdate.
Window is the tWindow we have to work with}
BEGIN
WITH Window DO WindowUpdate(XPos, YPos, X, XLength, YLength, True,
Buffer);
END;
Hmm, that seems to be about what we need to have in screens.pas, oh well, most likely I will write an addendum to this one.
End of part2.
Back to previous page
|