{ WINDOWS.INC: Window Routines }

{==========================================================================}
{ (c) Copyright Waterline Software Developent V.O.F. 1990-1994             }
{                                                                          }
{    Waterline Software Development V.O.F.                                 }
{    Wouter Sluislaan 12                                                   }
{    1461 AC  Zuidoostbeemster                                             }
{    The Netherlands                                                       }
{                                                                          }
{ It not allowed to use this user interface in any program not owned by    }
{ the Waterline Software Development V.O.F.                                }
{ Special conditions apply to programs distributed by the Waterline        }
{ Software Development V.O.F. If the source code of any of these programs  }
{ is distributed as well, it is NOT allowed to use the user interface in   }
{ your own programs. Violators may be prosecuted!                          }
{                                                                          }
{ Please contact the Waterline Software Development V.O.F. at the above    }
{ address for your licence to use the "Ramon" user interface. You will get }
{ the most recent copy of the "Ramon" user interface and the "Ramon" user  }
{ interface expert for free. This program helps you design your user       }
{ interfaces at an instance.                                               }
{                                                                          }
{ This copyright notice should remain in this file and all files that are  }
{ part of the user interface "Ramon".                                      }
{==========================================================================}

TYPE WindowRecordPtr = ^WindowRecord;
     WindowRecord    = RECORD
                             PrevWindowRecordPtr : WindowRecordPtr;
                             WindowSize,
                             StartOffset,
                             LineLength          : WORD;
                             Lines               : XYType;
                             DataBufferPtr       : POINTER;
                       END;

VAR CurrWindowRecordPtr : WindowRecordPtr;


{--------------------------------------------------------------------------}
{ WindowPush                                                               }
{                                                                          }
{ Sla een deel van het tekst scherm op op de heap om later te kunnen her-  }
{ stellen. Zowel de kleuren als de tekens worden opgeslagen.               }
{                                                                          }
PROCEDURE WindowPush (X,Y,LX,LY : XYType);

TYPE DataBuf = ARRAY[0..16383] OF BYTE;

VAR NewWindowRecordPtr : WindowRecordPtr;
    AddToNextLine,

{ De X variabelen zijn voor het ASM block. Vanuit Assembler is het me nog  }
{ niet gelukt bij de Structure Members van een VAR Pointer te komen...     }
    XStartOffset,
    XLineLength,
    XLines             : WORD;
    XDataBufferPtr     : ^DataBuf;

{$IFDEF PLATFORM_OS2}
    YLp      : XYType;
    {$IFNDEF FPC}
    BufLen   : SmallWord;
    {$ELSE}
    BufLen   : WORD;
    {$ENDIF}
    StorePos : WORD;
{$ENDIF}

{$IFDEF PLATFORM_WIN32}
     YLp, XLp  : XYType;
     HOutput   : HANDLE;
     Coordinate: COORD;
     Len       : LPDWORD;
     StoredPos : WORD;
     Temp      : PChar;
     WAttr     : LPWORD;
{$ENDIF}

BEGIN
     GetMem (NewWindowRecordPtr,SizeOf (WindowRecord));
     NewWindowRecordPtr^.PrevWindowRecordPtr:=CurrWindowRecordPtr;
     CurrWindowRecordPtr:=NewWindowRecordPtr;

     WITH CurrWindowRecordPtr^ DO
     BEGIN
          StartOffset:=((Y-1)*Video.Cols+X-1)*2;
          XStartOffset:=StartOffset;

          LineLength:=(LX+2)*2;
          XLineLength:=LineLength;

          Lines:=LY+1;
          XLines:=Lines;

          WindowSize:=LineLength*Lines;

          GetMem (NewWindowRecordPtr^.DataBufferPtr,WindowSize);
          XDataBufferPtr:=DataBufferPtr;

          AddToNextLine:=Video.Cols*2-LineLength;
     END; { with }

     {$IFDEF PLATFORM_OS2}
     StorePos:=0;
     FOR YLp:=1 TO XLines DO
     BEGIN
          BufLen:=XLineLength;
          VioReadCellStr (XDataBufferPtr^[StorePos],BufLen,Y-1+YLp-1,X-1,0);
          Inc (StorePos,XLineLength);
     END;
     {$ENDIF}

     {$IFDEF PLATFORM_WIN32}
     HOutput := GetStdHandle (STD_OUTPUT_HANDLE);

     StoredPos := 0;
     GetMem (Temp, 1);
     FOR YLp := 1 TO XLines DO
     BEGIN
          FOR XLp := 1 TO LX+2 DO
          BEGIN
               Coordinate.Y := Y-1+YLp-1;
               Coordinate.X := X-1+XLp-1;

               ReadConsoleOutputCharacterA (HOutput, Temp, 1, Coordinate, Len);
               XDataBufferPtr^[StoredPos] := BYTE (Temp[0]);

               ReadConsoleOutputAttribute (HOutput, WAttr, 1, Coordinate, Len);
               XDataBufferPtr^[StoredPos+1] := BYTE (Temp[0]);

               Inc (StoredPos, 2);
          END;
     END;
     FreeMem (Temp, 1);
     {$ENDIF}

     {$IFDEF PLATFORM_DOS_ALL}
     ASM
        PUSH DS

        MOV AX,Video.Base
        MOV DS,AX
        MOV SI,XStartOffset

        LES DI,XDataBufferPtr
        MOV AX,AddToNextLine

        MOV CX,XLines

        @@1:
        PUSH CX

        MOV CX,XLineLength
        REP MOVSB

        ADD SI,AX

        POP CX
        LOOP @@1

        POP DS
     END;
     {$ENDIF}
END;


{--------------------------------------------------------------------------}
{ WindowPop                                                                }
{                                                                          }
{ Haal het laatste op de heap opgeslagen window terug en herstel daarmee   }
{ het schermdeel ervan. Het op de heap gebruikte geheugen wordt daarna     }
{ weer vrijgegeven.                                                        }
{                                                                          }
PROCEDURE WindowPop;

TYPE DataBuf = ARRAY[0..16383] OF BYTE;

VAR EraseRecordPtr : WindowRecordPtr;
    AddToNextLine,
    XStartOffset,
    XLines,
    XLineLength    : WORD;
    XDataBufferPtr : ^DataBuf;

{$IFDEF PLATFORM_OS2}
    Y,X,
    YLp    : XYType;
    GetPos : WORD;
{$ENDIF}

{$IFDEF PLATFORM_WIN32}
     Y, X      : XYType;
     YLp, XLp  : XYType;
     HOutput   : HANDLE;
     Coordinate: COORD;
     Len       : LPDWORD;
     GetPos    : WORD;
     Temp      : PChar;
     WAttr     : Word;
{$ENDIF}


BEGIN
     IF (CurrWindowRecordPtr = NIL) THEN Exit;

     WITH CurrWindowRecordPtr^ DO
     BEGIN
          XLines:=Lines;
          XLineLength:=LineLength;
          XStartOffset:=StartOffset;
          XDataBufferPtr:=DataBufferPtr;
          AddToNextLine:=Video.Cols*2-LineLength;
     END; { with }

     {$IFDEF PLATFORM_OS2_OR_WIN32}
     GetPos:=0;
     XStartOffset:=XStartOffset DIV 2;
     Y:=(XStartOffset DIV Video.Cols);
     X:=XStartOffset-Y*Video.Cols;
     {$ENDIF}

     {$IFDEF PLATFORM_OS2}
     FOR YLp:=1 TO XLines DO
     BEGIN
          VioWrtCellStr (@XDataBufferPtr^[GetPos],XLineLength,Y+YLp-1,X,0);
          Inc (GetPos,XLineLength);
     END;
     {$ENDIF}

     {$IFDEF PLATFORM_WIN32}
     HOutput := GetStdHandle (STD_OUTPUT_HANDLE);
     
     GetPos := 0;

     GetMem (Temp, 1);
     FOR YLp := 1 TO XLines DO
     BEGIN
          FOR XLp := 1 TO (XLineLength DIV 2) DO
          BEGIN
               Coordinate.Y := Y-1+YLp-1;
               Coordinate.X := X-1+XLp-1;
               
               Temp^ := CHAR (XDataBufferPtr^[GetPos]);
               WriteConsoleOutputCharacterA (HOutput, Temp, 1, Coordinate, Len);
              
               WAttr := WORD (BYTE (CHAR (XDataBufferPtr^ [GetPos])));
               WriteConsoleOutputAttribute (HOutput, WAttr, 1, Coordinate, Len);

               Inc (GetPos, 2);
          END;
     END;

     Freemem (Temp, 1);
     {$ENDIF}

     {$IFDEF PLATFORM_DOS_ALL}
     ASM
        PUSH DS

        MOV AX,Video.Base
        MOV ES,AX
        MOV DI,XStartOffset

        LDS SI,XDataBufferPtr

        MOV AX,AddToNextLine

        MOV CX,XLines
        @@1:
        PUSH CX

        MOV CX,XLineLength
        REP MOVSB

        ADD DI,AX

        POP CX
        LOOP @@1

        POP DS
     END;
     {$ENDIF}

     WITH CurrWindowRecordPtr^ DO
          FreeMem (DataBufferPtr,WindowSize);

     EraseRecordPtr:=CurrWindowRecordPtr;
     CurrWindowRecordPtr:=CurrWindowRecordPtr^.PrevWindowRecordPtr;
     FreeMem (EraseRecordPtr,SizeOf (WindowRecord));
END;
