Browse Source

* Brings OS/2 directory up to date.

daniel 27 years ago
parent
commit
12fb25a920

+ 11 - 11
rtl/os2/atx.pas

@@ -1,15 +1,15 @@
 program atx;
 program atx;
 
 
-var	f:text;
-	s:string;
+var f:text;
+    s:string;
 
 
 begin
 begin
-	assign(f,'c:\autoexec.bat');
-	reset(f);
-	while not eof(f) do
-		begin
-			readln(f,s);
-			writeln(s);
-		end;
-	close(f);
-end.
+    assign(f,'c:\autoexec.bat');
+    reset(f);
+    while not eof(f) do
+        begin
+            readln(f,s);
+            writeln(s);
+        end;
+    close(f);
+end.

+ 0 - 1
rtl/os2/bind.btm

@@ -1 +0,0 @@
-emxbind -k64 -o %1.exe %1 -aim -s5120

+ 8 - 8
rtl/os2/calc_e.pas

@@ -2,14 +2,14 @@ program calc_e;
 
 
 {Calculate the number e.}
 {Calculate the number e.}
 
 
-const	fac:array[0..7] of word=(1,1,2,6,24,120,720,5040);
+const   fac:array[0..7] of word=(1,1,2,6,24,120,720,5040);
 
 
-var	e:fixed;
-	i:byte;
+var e:fixed;
+    i:byte;
 
 
 begin
 begin
-	e:=0;
-	for i:=0 to 7 do
-		e:=e+fixed(1)/fac[i];
-	writeln(e);
-end.
+    e:=0;
+    for i:=0 to 7 do
+        e:=e+fixed(1)/fac[i];
+    writeln(e);
+end.

+ 27 - 0
rtl/os2/code2.so2

@@ -0,0 +1,27 @@
+/ code2.s (emx+fpk) -- Copyright (c) 1992-1996 by Eberhard Mattes
+/                      Changed for FPK-Pascal in 1998 by Dani‰l Mantione.
+/					   This code is _not_ under the Library GNU Public
+/ 					   License, because the original is not. See copying.emx
+/	 				   for details. You should have received it with this
+/		 			   product, write the author if you haven't.
+
+		.globl  DosGetMessage
+		.globl  _msgseg32
+
+_msgseg32:
+		.byte   0xff
+		.asciz  "MSGSEG32"
+		.byte   0x01, 0x80, 0x00, 0x00
+		.long   L_tab
+
+		.align  2, 0x90
+
+DosGetMessage:
+		PROFILE_NOFRAME
+		popl    %ecx                    /* return address */
+		pushl   $_msgseg32
+		pushl   %ecx
+		jmp     _DOSCALLS$$_DOSTRUEGETMESSAGE$POINTER$PINSERTTABLE$LONGINT$PCHAR$LONGINT$LONGINT$PCHAR$LONGINT
+
+L_tab:  .short  0x0000
+        .short  0xffff

+ 16 - 0
rtl/os2/code3.so2

@@ -0,0 +1,16 @@
+/ code3.s (emx+gcc) -- Copyright (c) 1992-1996 by Eberhard Mattes
+
+#include <emx/asm386.h>
+
+        .globl  _DosQueryMessageCP
+
+_DosQueryMessageCP:
+        PROFILE_NOFRAME
+        pushl   0(%esp)
+        movl    $__msgseg32, %eax
+        xchgl   20(%esp), %eax
+        xchgl   16(%esp), %eax
+        xchgl   12(%esp), %eax
+        xchgl   8(%esp), %eax
+        movl    %eax, 4(%esp)
+        jmp     _DosIQueryMessageCP

File diff suppressed because it is too large
+ 492 - 467
rtl/os2/crt.pas


+ 8 - 8
rtl/os2/crtdemo.pas

@@ -63,19 +63,19 @@ procedure Initialize;
 { generator. Paint the help line. }
 { generator. Paint the help line. }
 begin
 begin
   OrigMode:=LastMode;                  { Remember original video mode }
   OrigMode:=LastMode;                  { Remember original video mode }
-  TextMode(_80cols+_50rows);      	   { use 43 or 50 lines on EGA/VGA }
+  TextMode(_80cols+_50rows);           { use 43 or 50 lines on EGA/VGA }
   LastCol:=Lo(WindMax)+1;              { get last column, row }
   LastCol:=Lo(WindMax)+1;              { get last column, row }
   LastRow:=Hi(WindMax)+1;
   LastRow:=Hi(WindMax)+1;
   GoToXY(1,LastRow);                   { put message line on screen }
   GoToXY(1,LastRow);                   { put message line on screen }
   TextBackground(Black);
   TextBackground(Black);
   TextColor(White);
   TextColor(White);
-  Write(' Ins-InsLine  ',
-		'Del-DelLine  ',
-		#27#24#25#26'-Cursor  ',
-		'Alt-W-Window  ',
-		'Alt-R-Random  ',
-		'Esc-Exit');
-  Dec(LastRow,80 div LastCol);         { don't write on message line }
+  Write(' Ins-InsLine  '+
+        'Del-DelLine  '+
+        #27#24#25#26'-Cursor  '+
+        'Alt-W-Window  '+
+        'Alt-R-Random  '+
+        'Esc-Exit');
+  LastRow:=lastrow-80 div LastCol;     { don't write on message line }
   Randomize;                           { init random number generator }
   Randomize;                           { init random number generator }
 end; { Init }
 end; { Init }
 
 

File diff suppressed because it is too large
+ 1038 - 1037
rtl/os2/dos.pas


File diff suppressed because it is too large
+ 511 - 421
rtl/os2/doscalls.pas


+ 0 - 19
rtl/os2/dosinit.as

@@ -1,19 +0,0 @@
-/ emx_386/dosinit.s (emx+gcc) -- Copyright (c) 1994-1996 by Eberhard Mattes
-
-/ In executables created with emxbind, the call to _dos_init will
-/ be fixed up at load time to _emx_init of emx.dll.  Under DOS,
-/ this dummy is called instead as there is no fixup.  This module
-/ must be linked statically to avoid having two fixups for the
-/ same location.
-        
-        .globl  __dos_init
-        .globl  __dos_syscall
-
-__dos_init:
-        ret     $4
-
-        .align  2, 0x90
-
-__dos_syscall:
-        int     $0x21
-        ret

+ 4 - 4
rtl/os2/emx.pas

@@ -6,7 +6,7 @@ Part of FPK Pascal runtime library for OS/2
 
 
 
 
 History:
 History:
-	2 June 1997 : Creation.
+    2 June 1997 : Creation.
 
 
 This unit is copyright (c) 1997 by Dani‰l Mantione.
 This unit is copyright (c) 1997 by Dani‰l Mantione.
 FPK Pascal is copyright (c) -1997 by Florian Klaempfl.
 FPK Pascal is copyright (c) -1997 by Florian Klaempfl.
@@ -22,9 +22,9 @@ Modifying this unit is allowed, under the following conditions:
 
 
 unit emx;
 unit emx;
 
 
-type	Pfar=record
-			segment,offset:word;
-		end;
+type    Pfar=record
+            segment,offset:word;
+        end;
 
 
 {! Don't call this one. It is used by the startup code.}
 {! Don't call this one. It is used by the startup code.}
 procedure __emxinit;
 procedure __emxinit;

+ 3 - 3
rtl/os2/extest.pas

@@ -3,6 +3,6 @@ program extest;
 uses dos;
 uses dos;
 
 
 begin
 begin
-	exec('c:\ndos.com','');
-	writeln(doserror);
-end.
+    exec('c:\ndos.com','');
+    writeln(doserror);
+end.

+ 1 - 1
rtl/os2/generic.pas

@@ -37,7 +37,7 @@ program generic;
   const
   const
      frameflags : longint = FCF_TITLEBAR+
      frameflags : longint = FCF_TITLEBAR+
                             FCF_SYSMENU+
                             FCF_SYSMENU+
-     			    FCF_SIZEBORDER+
+                    FCF_SIZEBORDER+
                             FCF_MINBUTTON+
                             FCF_MINBUTTON+
                             FCF_MAXBUTTON+
                             FCF_MAXBUTTON+
                             FCF_SHELLPOSITION+
                             FCF_SHELLPOSITION+

+ 11 - 11
rtl/os2/heapsize.pas

@@ -1,25 +1,25 @@
 program heapsize;
 program heapsize;
 
 
-var	a:longint;
+var a:longint;
 
 
 procedure writeheapsize;
 procedure writeheapsize;
 
 
 begin
 begin
-	asm
-		movl $0x7f00,%ax
-		xorl %edx,%edx
-		call ___syscall
-		mov %eax,_A
-	end;
-	writeln(a);
+    asm
+        movl $0x7f00,%ax
+        xorl %edx,%edx
+        call ___syscall
+        mov %eax,_A
+    end;
+    writeln(a);
 end;
 end;
 
 
 begin
 begin
     writeheapsize;
     writeheapsize;
     asm
     asm
-		movl $0x7f00,%ax
-		movl $327680,%edx
-		call ___syscall
+        movl $0x7f00,%ax
+        movl $327680,%edx
+        call ___syscall
     end;
     end;
     writeheapsize;
     writeheapsize;
 end.
 end.

+ 19 - 16
rtl/os2/helloos2.pas

@@ -1,21 +1,24 @@
 program helloos2;
 program helloos2;
 
 
-var	a,b:^word;
+var a,b:^word;
 
 
 begin
 begin
-		writeln('Hallo Wereld.');
-		if os_mode=osDOS then
-			writeln('We draaien onder DOS.')
-		else
-			writeln('We draaien onder OS/2.');
-		writeln('Vrij geheugen: ',memavail);
-		writeln('Grootste blok: ',maxavail);
-		writeln('Heapstart: ',longint(heaporg));
-		writeln('Heapend: ',longint(heapend));
-		getmem(a,1000);
-		getmem(b,2000);
-		a^:=2;
-		b^:=10;
-		freemem(a,1000);
-		freemem(b,2000);
+        writeln('Hallo Wereld.');
+        if os_mode=osDOS then
+            writeln('We draaien onder DOS.')
+        else
+            writeln('We draaien onder OS/2.');
+        writeln('Vrij geheugen: ',memavail);
+        writeln('Grootste blok: ',maxavail);
+        writeln('Heapstart: ',longint(heaporg));
+        writeln('Heapend: ',longint(heapend));
+        writeln('Geheugen aan het bezetten.');
+        getmem(a,1000);
+        getmem(b,2000);
+        a^:=2;
+        b^:=10;
+        writeln('Vrij geheugen: ',memavail);
+        writeln('Grootste blok: ',maxavail);
+        freemem(a,1000);
+        freemem(b,2000);
 end.
 end.

+ 455 - 0
rtl/os2/kbdcalls.pas

@@ -0,0 +1,455 @@
+{Set tabsize to 4.}
+{****************************************************************************
+
+                           KBDCALLS interface unit
+                     FPK-Pascal Runtime Library for OS/2
+                   Copyright (c) 1993,94 by Florian Kl„mpfl
+                    Copyright (c) 1997 by Dani‰l Mantione
+                      Copyright (c) 1998 by Tomas Hajny
+
+ The FPK-Pascal runtime library is distributed under the Library GNU Public
+ License v2. So is this unit. The Library GNU Public License requires you to
+ distribute the source code of this unit with any product that uses it.
+ Because the EMX library isn't under the LGPL, we grant you an exception to
+ this, and that is, when you compile a program with the FPK Pascal compiler,
+ you do not need to ship source code with that program, AS LONG AS YOU ARE
+ USING UNMODIFIED CODE! If you modify this code, you MUST change the next
+ line:
+
+ <This is an official, unmodified FPK Pascal source code file.>
+
+ Send us your modified files, we can work together if you want!
+
+ FPK-Pascal is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ Library GNU General Public License for more details.
+
+ You should have received a copy of the Library GNU General Public License
+ along with FPK-Pascal; see the file COPYING.LIB.  If not, write to
+ the Free Software Foundation, 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+
+****************************************************************************}
+
+unit KbdCalls;
+
+{ Interface library to KBDCALLS.DLL (through EMXWRAP.DLL)
+
+Changelog:
+
+    People:
+
+        TH - Tomas Hajny
+
+    Date:           Description of change:              Changed by:
+
+     -              First released version 0.99         TH
+
+Coding style:
+
+    I have tried to use the same coding style as Dani‰l Mantione in unit
+    DOSCALLS, although I can't say I would write it the same way otherwise (I
+    would write much more spaces myself, at least). Try to use it as well,
+    please. Original note by Dani‰l Mantione follows:
+
+
+    It may be well possible that coding style feels a bit strange to you.
+    Nevertheless I friendly ask you to try to make your changes not look all
+    to different. To make life easier, set your IDE to use tab characters,
+    turn optimal fill, autoindent and backspace unindents on and set a
+    tabsize of 4.}
+
+{***************************************************************************}
+interface
+{***************************************************************************}
+
+uses    strings;
+
+{$ifdef FPK}
+    {$packrecords 1}
+{$endif FPK}
+
+const
+{FnMask}
+    KR_KBDCHARIN        =$00000001;
+    KR_KBDPEEK          =$00000002;
+    KR_KBDFLUSHBUFFER   =$00000004;
+    KR_KBDGETSTATUS     =$00000008;
+    KR_KBDSETSTATUS     =$00000010;
+    KR_KBDSTRINGIN      =$00000020;
+    KR_KBDOPEN          =$00000040;
+    KR_KBDCLOSE         =$00000080;
+    KR_KBDGETFOCUS      =$00000100;
+    KR_KBDFREEFOCUS     =$00000200;
+    KR_KBDGETCP         =$00000400;
+    KR_KBDSETCP         =$00000800;
+    KR_KBDXLATE         =$00001000;
+    KR_KBDSETCUSTXT     =$00002000;
+
+{WaitFlag}
+    IO_WAIT     =0;
+        {KbdCharIn: wait for a character if one is not available}
+        {KbdGetFocus: wait for the focus}
+    IO_NOWAIT   =1;
+        {KbdCharIn: immediate return if no character is available}
+        {KbdGetFocus: do not wait for the focus}
+
+{TKbdInfo.fsMask}
+    KEYBOARD_ECHO_ON            =$0001;
+    KEYBOARD_ECHO_OFF           =$0002;
+    KEYBOARD_BINARY_MODE        =$0004;
+    KEYBOARD_ASCII_MODE         =$0008;
+    KEYBOARD_MODIFY_STATE       =$0010;
+    KEYBOARD_MODIFY_INTERIM     =$0020;
+    KEYBOARD_MODIFY_TURNAROUND  =$0040;
+    KEYBOARD_2B_TURNAROUND      =$0080;
+    KEYBOARD_SHIFT_REPORT       =$0100;
+
+{TKbdInfo.fsState/TKbdKeyInfo.fsState/TKbdTrans.fsState}
+    KBDSTF_RIGHTSHIFT           =$0001;
+    KBDSTF_LEFTSHIFT            =$0002;
+    KBDSTF_CONTROL              =$0004;
+    KBDSTF_ALT                  =$0008;
+    KBDSTF_SCROLLLOCK_ON        =$0010;
+    KBDSTF_NUMLOCK_ON           =$0020;
+    KBDSTF_CAPSLOCK_ON          =$0040;
+    KBDSTF_INSERT_ON            =$0080;
+    KBDSTF_LEFTCONTROL          =$0100;
+    KBDSTF_LEFTALT              =$0200;
+    KBDSTF_RIGHTCONTROL         =$0400;
+    KBDSTF_RIGHTALT             =$0800;
+    KBDSTF_SCROLLLOCK           =$1000;
+    KBDSTF_NUMLOCK              =$2000;
+    KBDSTF_CAPSLOCK             =$4000;
+    KBDSTF_SYSREQ               =$8000;
+
+{TKbdTrans.fbStatus}
+    KBDTRF_SHIFT_KEY_IN         =$01;   {shift status returned}
+                                        {without character    }
+    KBDTRF_EXTENDED_KEY_IN      =$02;   {extended key code }
+                                        {from the keyboard,}
+                                        {not a character   }
+    KBDTRF_CONVERSION_REQUEST   =$20;   {immediate conversion}
+                                        {requested           }
+    KBDTRF_FINAL_CHAR_IN        =$40;   {either $40 or $80 or both}
+    KBDTRF_INTERIM_CHAR_IN      =$80;   {must be present          }
+
+
+type
+{TKbdKeyInfo - character data structure for KbdCharIn and KbdPeek}
+(*   #pragma pack(2) ??? *)
+    TKbdKeyInfo=record
+        chChar:char;    {ASCII character code; the scan code received}
+                        {from the keyboard is translated to the ASCII}
+                        {character code                              }
+        chScan:byte;    {scan Code received from the keyboard}
+        fbStatus:byte;  {state of the keystroke event, see KBDTRF_*}
+        bNlsShift:byte; {NLS shift status (always 0?)}
+        fsState:word;   {shift key status, see KBDSTF_*}
+        time:longint;   {time stamp indicating when a key was pressed,}
+                        {specified in milliseconds from the time      }
+                        {the system was started                       }
+    end;
+    PKbdKeyInfo=^TKbdKeyInfo;
+
+{structure for KbdStringIn}
+    TStringInBuf=record
+        cb:word;
+        cchIn:word;
+    end;
+    PStringInBuf=TStringInBuf;
+
+{TKbdInfo structure, for KbdSet/GetStatus}
+    TKbdInfo=record
+        cb,
+        fsMask,
+        chTurnAround,
+        fsInterim,
+        fsState:word;
+    end;
+    PKbdInfo=^TKbdInfo;
+
+{structure for KbdGetHWID}
+    TKbdHWID=record
+        cb,
+        idKbd,
+        usReserved1,
+        usReserved2:word;
+    end;
+    PKbdHWID=^TKbdHWID;
+
+{structure for KbdXlate}
+(*   #pragma pack(2) ???*)
+    TKbdTrans=record
+        chChar:char;
+        chScan:byte;
+        fbStatus:byte;
+        bNlsShift:byte;
+        fsState:word;
+        time:longint;
+        fsDD:word;
+        fsXlate:word;
+        fsShift:word;
+        sZero:word;
+    end;
+    PKbdTrans=^TKbdTrans;
+
+
+{See KR_* constants for FnMask}
+function KbdRegister(ModuleName,ProcName:PChar;FnMask:longint):word;
+function KbdRegister(ModuleName,ProcName:string;FnMask:longint):word;
+
+{Deregister a keyboard subsystem previously registered within a session - only
+the process that issued the KbdRegister may issue KbdDeRegister}
+{Possible return codes:
+    0         NO_ERROR
+    411       ERROR_KBD_DEREGISTER
+    464       ERROR_KBD_DETACHED
+    504       ERROR_KBD_EXTENDED_SG}
+function KbdDeRegister:word;
+
+{Return a character data record from the keyboard}
+{Key - see TKbdKeyInfo, WaitFlag - see IO_WAIT and IO_NOWAIT constants,
+KbdHandle is the default keyboard (0) or a logical keyboard.}
+{Possible return codes are:
+    0         NO_ERROR
+    375       ERROR_KBD_INVALID_IOWAIT
+    439       ERROR_KBD_INVALID_HANDLE
+    445       ERROR_KBD_FOCUS_REQUIRED
+    447       ERROR_KBD_KEYBOARD_BUSY
+    464       ERROR_KBD_DETACHED
+    504       ERROR_KBD_EXTENDED_SG}
+{Remarks:
+* On an enhanced keyboard, the secondary enter key returns the normal
+  character 0DH and a scan code of E0H.
+* Double-byte character codes (DBCS) require two function calls to obtain the
+  entire code.
+* If shift report is set with KbdSetStatus, the CharData record returned
+  reflects changed shift information only.
+* Extended ASCII codes are identified with the status byte, bit 1 on and the
+  ASCII character code being either 00H or E0H. Both conditions must be
+  satisfied for the character to be an extended keystroke.  For extended
+  ASCII codes, the scan code byte returned is the second code (extended
+  code). Usually the extended ASCII code is the scan code of the primary key
+  that was pressed.
+* A thread in the foreground session that repeatedly polls the keyboard with
+  KbdCharIn (with no wait), can prevent all regular priority class threads
+  from executing.  If polling must be used and a minimal amount of other
+  processing is being performed, the thread should periodically yield to the
+  CPU by issuing a DosSleep call for an interval of at least 5 milliseconds.}
+function KbdCharIn(var Key:TKbdKeyInfo;WaitFlag,KbdHandle:word):word;
+
+function KbdPeek(var Key:TKbdKeyInfo;KbdHandle:word):word;
+
+function KbdStringIn(var CharBuf;var pchIn:TStringInBuf;WaitFlag:word;
+                                                          KbdHandle:word):word;
+
+{Clear the keystroke buffer}
+{KbdHandle is the default keyboard (0) or a logical keyboard.}
+{Possible return codes are:
+    0         NO_ERROR
+    439       ERROR_KBD_INVALID_HANDLE
+    445       ERROR_KBD_FOCUS_REQUIRED
+    447       ERROR_KBD_KEYBOARD_BUSY
+    464       ERROR_KBD_DETACHED
+    504       ERROR_KBD_EXTENDED_SG}
+{Remarks:
+* KbdFlushBuffer completes when the handle has access to the physical
+  keyboard (focus), or is equal to zero and no other handle has the focus.}
+function KbdFlushBuffer(KbdHandle:word):word;
+
+function KbdSetStatus(var Status:TKbdInfo;KbdHandle:word):word;
+
+function KbdGetStatus(var Status:TKbdInfo;KbdHandle:word):word;
+
+function KbdSetCp(usReserved,CodePage,KbdHandle:word):word;
+
+{Query the code page being used to translate scan codes to ASCII characters.}
+{ulReserved must be set to 0. The keyboard support returns the current code
+page for a specified keyboard handle in CodePage, it is one of the code page
+IDs specified in the CONFIG.SYS CODEPAGE= statement or 0000. KbdHandle is
+the default keyboard (0) or a logical keyboard.}
+{Possible return codes:
+    0         NO_ERROR
+    373       ERROR_KBD_PARAMETER
+    439       ERROR_KBD_INVALID_HANDLE
+    445       ERROR_KBD_FOCUS_REQUIRED
+    447       ERROR_KBD_KEYBOARD_BUSY
+    464       ERROR_KBD_DETACHED
+    504       ERROR_KBD_EXTENDED_SG}
+{Remarks:
+* CodePage is set to the currently active keyboard code page. A value of 0
+  indicates the code page translation table in use is the ROM code page
+  translation table provided by the hardware.}
+function KbdGetCp(ulReserved:longint;var CodePage:word;KbdHandle:word):word;
+
+function KbdOpen(var KbdHandle:word):word;
+
+{Close the existing logical keyboard identified by the keyboard handle}
+{KbdHandle is the default keyboard (0) or a logical keyboard}
+{Possible return codes:
+    0         NO_ERROR
+    439       ERROR_KBD_INVALID_HANDLE
+    464       ERROR_KBD_DETACHED
+    504       ERROR_KBD_EXTENDED_SG}
+{Remarks:
+* KbdClose blocks while another thread has the keyboard focus (by way of
+  KbdGetFocus) until the thread with the focus issues KbdFreeFocus.
+  Therefore, to prevent KbdClose from blocking, it is recommended that
+  KbdClose be issued only while the current thread has the focus.  For
+  example:
+    KbdGetFocus Wait until focus available on handle 0.
+    KbdClose    Close a logical keyboard handle.
+    KbdFreeFocus    Give up the focus on handle 0.}
+function KbdClose(KbdHandle:word):word;
+
+{Bind the logical keyboard to the physical keyboard.}
+{KbdHandle is the default keyboard (0) or a logical keyboard}
+{Possible return codes:
+    0         NO_ERROR
+    439       ERROR_KBD_INVALID_HANDLE
+    445       ERROR_KBD_FOCUS_REQUIRED
+    464       ERROR_KBD_DETACHED
+    504       ERROR_KBD_EXTENDED_SG}
+function KbdGetFocus(WaitFlag,KbdHandle:word):word;
+
+{Free the logical-to-physical keyboard bond created by KbdGetFocus.}
+{KbdHandle is the default keyboard (0) or a logical keyboard}
+{Possible return codes:
+    0         NO_ERROR
+    439       ERROR_KBD_INVALID_HANDLE
+    445       ERROR_KBD_FOCUS_REQUIRED
+    464       ERROR_KBD_DETACHED
+    504       ERROR_KBD_EXTENDED_SG}
+{Remarks:
+* KbdFreeFocus may be replaced by issuing KbdRegister. Unlike other keyboard
+  subsystem functions, the replaced KbdFreeFocus is called only if there is
+  an outstanding focus.}
+function KbdFreeFocus(KbdHandle:word):word;
+
+function KbdSynch (WaitFlag:word):word;
+
+function KbdSetFgnd:word;
+
+function KbdGetHWID(var HWID:TKbdHWID;KbdHandle:word):word;
+
+function KbdSetHWID(var HWID:TKbdHWID;KbdHandle:word):word;
+
+function KbdXlate(var TransData:TKbdTrans;KbdHandle:word):word;
+
+function KbdSetCustXt(var XLateTbl;KbdHandle:word):word;
+
+
+(* Following routines are not supported
+   (just have a look in some C header
+   file - you probably won't find it there either).
+KbdInit (index 2)
+KbdLoadInstance (index 6)
+KbdSwitchFgnd (index 15)
+KbdShellInit (index 16)
+KbdFree (index 19)
+*)
+
+
+{***************************************************************************}
+implementation
+{***************************************************************************}
+
+
+function KbdRegister(ModuleName,ProcName:PChar;FnMask:longint):word;
+external 'EMXWRAP' index 208;
+{external 'KBDCALLS' index 8;}
+
+function KbdRegister(ModuleName,ProcName:string;FnMask:longint):word;
+
+var A1:array[0..8] of char;
+    A2:array[0..32] of char;
+
+begin
+    if byte(ModuleName[0])>8 then byte(ModuleName[0]):=8;
+    StrPCopy(@A1,ModuleName);
+    if byte(ProcName[0])>32 then byte(ProcName[0]):=32;
+    StrPCopy(@A2,ProcName);
+    KbdRegister:=KbdRegister(@A1,@A2,FnMask);
+end;
+
+function KbdDeRegister:word;
+external 'EMXWRAP' index 220;
+{external 'KBDCALLS' index 20;}
+
+function KbdCharIn(var Key:TKbdKeyInfo;WaitFlag,KbdHandle:word):word;
+external 'EMXWRAP' index 204;
+{external 'KBDCALLS' index 4;}
+
+function KbdPeek(var Key:TKbdKeyInfo;KbdHandle:word):word;
+external 'EMXWRAP' index 222;
+{external 'KBDCALLS' index 22;}
+
+function KbdStringIn(var CharBuf;var pchIn:TStringInBuf;WaitFlag:word;
+                                                          KbdHandle:word):word;
+external 'EMXWRAP' index 209;
+{external 'KBDCALLS' index 9;}
+
+function KbdFlushBuffer(KbdHandle:word):word;
+external 'EMXWRAP' index 213;
+{external 'KBDCALLS' index 13;}
+
+function KbdSetStatus(var Status:TKbdInfo;KbdHandle:word):word;
+external 'EMXWRAP' index 211;
+{external 'KBDCALLS' index 11;}
+
+function KbdGetStatus(var Status:TKbdInfo;KbdHandle:word):word;
+external 'EMXWRAP' index 210;
+{external 'KBDCALLS' index 10;}
+
+function KbdSetCp(usReserved,CodePage,KbdHandle:word):word;
+external 'EMXWRAP' index 205;
+{external 'KBDCALLS' index 5;}
+
+function KbdGetCp(ulReserved:longint;var CodePage:word;KbdHandle:word):word;
+external 'EMXWRAP' index 203;
+{external 'KBDCALLS' index 3;}
+
+function KbdOpen(var KbdHandle:word):word;
+external 'EMXWRAP' index 223;
+{external 'KBDCALLS' index 23;}
+
+function KbdClose(KbdHandle:word):word;
+external 'EMXWRAP' index 217;
+{external 'KBDCALLS' index 17;}
+
+function KbdGetFocus(WaitFlag,KbdHandle:word):word;
+external 'EMXWRAP' index 212;
+{external 'KBDCALLS' index 12;}
+
+function KbdFreeFocus(KbdHandle:word):word;
+external 'EMXWRAP' index 218;
+{external 'KBDCALLS' index 18;}
+
+function KbdSynch (WaitFlag:word):word;
+external 'EMXWRAP' index 207;
+{external 'KBDCALLS' index 7;}
+
+function KbdSetFgnd:word;
+external 'EMXWRAP' index 221;
+{external 'KBDCALLS' index 21;}
+
+function KbdGetHWID(var HWID:TKbdHWID;KbdHandle:word):word;
+external 'EMXWRAP' index 224;
+{external 'KBDCALLS' index 24;}
+
+function KbdSetHWID(var HWID:TKbdHWID;KbdHandle:word):word;
+external 'EMXWRAP' index 225;
+{external 'KBDCALLS' index 25;}
+
+function KbdXlate(var TransData:TKbdTrans;KbdHandle:word):word;
+external 'EMXWRAP' index 214;
+{external 'KBDCALLS' index 14;}
+
+function KbdSetCustXt(var XLateTbl;KbdHandle:word):word;
+external 'EMXWRAP' index 201;
+{external 'KBDCALLS' index 1;}
+
+
+end.

+ 0 - 1
rtl/os2/mkatx.btm

@@ -1 +0,0 @@
-ld -o atx prt0.o prt1.o atx.o sysos2.o emx.a dosinit.o

+ 0 - 1
rtl/os2/mkcalc_e.btm

@@ -1 +0,0 @@
-ld -o calc_e prt0.o prt1.o calc_e.o sysos2.o emx.a dosinit.o

+ 0 - 1
rtl/os2/mkcrt.btm

@@ -1 +0,0 @@
-ld -o crtdemo prt0.o prt1.o crtdemo.o sysos2.o crt.o emx.a dosinit.o doscalls.a wrap.a

+ 0 - 1
rtl/os2/mkdumpar.btm

@@ -1 +0,0 @@
-ld -o dumppars prt0.o prt1.o dumppars.o sysos2.o emx.a dosinit.o dos.o strings.o doscalls.a

+ 0 - 1
rtl/os2/mkex.btm

@@ -1 +0,0 @@
-ld -o extest prt0.o prt1.o extest.o dos.o strings.o sysos2.o emx.a dosinit.o doscalls.a wrap.a

+ 0 - 1
rtl/os2/mkhello.btm

@@ -1 +0,0 @@
-ld -o helloos2 prt0.o prt1.o helloos2.o sysos2.o emx.a dosinit.o doscalls.a

+ 0 - 1
rtl/os2/mkhsize.btm

@@ -1 +0,0 @@
-ld -o heapsize prt0.o prt1.o heapsize.o sysos2.o emx.a dosinit.o

+ 0 - 1
rtl/os2/mkmode.btm

@@ -1 +0,0 @@
-ld -o modeinfo prt0.o prt1.o modeinfo.o sysos2.o emx.a dosinit.o wrap.a

+ 33 - 33
rtl/os2/modeinfo.pas

@@ -1,42 +1,42 @@
 program modeinfo;
 program modeinfo;
 
 
-type	viomodeinfo=record
-			cb:word;                         { length of the entire data structure }
-			fbType,                          { bit mask of mode being set }
-			color: byte;                     { number of colors (power of 2) }
-			col,                             { number of text columns }
-			row,                             { number of text rows }
-			hres,                            { horizontal resolution }
-			vres: word;                      { vertical resolution }
-			fmt_ID,                          { attribute format }
-			attrib: byte;                    { number of attributes }
-			buf_addr,
-			buf_length,
-			full_length,
-			partial_length:longint;
-			ext_data_addr:pointer;
-		end;
-		Pviomodeinfo=^viomodeinfo;
+type    viomodeinfo=record
+            cb:word;                         { length of the entire data structure }
+            fbType,                          { bit mask of mode being set }
+            color: byte;                     { number of colors (power of 2) }
+            col,                             { number of text columns }
+            row,                             { number of text rows }
+            hres,                            { horizontal resolution }
+            vres: word;                      { vertical resolution }
+            fmt_ID,                          { attribute format }
+            attrib: byte;                    { number of attributes }
+            buf_addr,
+            buf_length,
+            full_length,
+            partial_length:longint;
+            ext_data_addr:pointer;
+        end;
+        Pviomodeinfo=^viomodeinfo;
 
 
 function _VioGetMode (var Amodeinfo:viomodeinfo;viohandle:word):word;[C];
 function _VioGetMode (var Amodeinfo:viomodeinfo;viohandle:word):word;[C];
 function _VioSetMode (var Amodeinfo:viomodeinfo;viohandle:word):word;[C];
 function _VioSetMode (var Amodeinfo:viomodeinfo;viohandle:word):word;[C];
 
 
-var	mode:viomodeinfo;
+var mode:viomodeinfo;
 
 
 begin
 begin
-	mode.cb:=sizeof(mode);
-	writeln('getmode= ',_viogetmode(mode,0));
-	writeln('cb= ',mode.cb);
-	writeln('fbtype= ',mode.fbtype);
-	writeln('color= ',mode.color);
-	writeln('col= ',mode.col);
-	writeln('row= ',mode.row);
-	writeln('hres= ',mode.hres);
-	writeln('vres= ',mode.vres);
-	writeln('fmt_ID= ',mode.fmt_ID);
-	writeln('attrib= ',mode.attrib);
-	writeln('buf_addr= ',mode.buf_addr);
-	writeln('buf_length= ',mode.buf_length);
-	writeln('full_length= ',mode.full_length);
-	writeln('partial_length= ',mode.partial_length);
+    mode.cb:=sizeof(mode);
+    writeln('getmode= ',_viogetmode(mode,0));
+    writeln('cb= ',mode.cb);
+    writeln('fbtype= ',mode.fbtype);
+    writeln('color= ',mode.color);
+    writeln('col= ',mode.col);
+    writeln('row= ',mode.row);
+    writeln('hres= ',mode.hres);
+    writeln('vres= ',mode.vres);
+    writeln('fmt_ID= ',mode.fmt_ID);
+    writeln('attrib= ',mode.attrib);
+    writeln('buf_addr= ',mode.buf_addr);
+    writeln('buf_length= ',mode.buf_length);
+    writeln('full_length= ',mode.full_length);
+    writeln('partial_length= ',mode.partial_length);
 end.
 end.

+ 83 - 0
rtl/os2/o2rtlb1.pas

@@ -0,0 +1,83 @@
+program testread;
+{uses crt;}
+var
+  cadena,cadena2 : string;
+  number : real;
+begin
+  {clrscr;}
+  cadena2 := 'Previous string';
+  write ('Enter the string ');
+  readln (cadena);
+  writeln ('You entered ',cadena);
+  writeln ('Previous string was ',cadena2);
+  write ('Enter a number ');
+  readln (number);
+  writeln ('Number entered was ',number);
+  readln;
+end.
+
+{(I have retyped now because my computer is not connected to the net, but I
+think that there are no errors).
+
+Now you can do some tests:
+
+1- Compile and run the program as is (that is, using crt). You will find that
+      a) the program does not erase the screen (that is normal because we have
+commented clrscr), but the cursor goes to the first line, thus overwriting the
+screen.
+   b) While the program is expecting the string to be entered, some of the keys
+do not work correctly: Backspace advances some spaces (just like tab), tab key
+does not work and the cursor keys write garbage. (however this is only in the
+screen, because if you have erased a part of the string it will be actually
+erased).
+   c) Once you have press return, the message 'You entered...' appears in the
+same line as the text entered.
+
+2- Uncomment the clrscr call, cokpile and execute. Point a of test 1 will be
+solved (the screen is erased, so nothing is overwritten), but points b and c
+persist.
+
+3- Comment 'uses crt' and 'clrscr'. Now you will not be using crt. Now:
+   a) Point a of test 1 does not appear: the program begins to write in the
+next line, it does not overwrite anything.
+   b) Now all the keys (tab, backspace..) work as expected.
+   c) Now the message 'You entered...' appears in the following line, so point
+c of test 1 is also solved.
+   d) BUT it writes only 'You entered', WITHOUT writing the string cadena (!).
+It writes also 'Previous string was previous string', so the problem is in
+readln and not in writeln.
+
+4- To see if the problem is only in the string vars, uncomment the definition
+of number, and also the three lines at the end that deal with number. Now ld
+gives the following error message:
+
+testread.pp:0 (testread.o): undefined symbol READ_TEXT_INTEGER referenced from
+text segment.
+
+This error happens with 'uses crt' and also without it.
+
+5- Define number as word. Regardless of crt we get the following error from ld:
+
+testread.pp:0 (testread.o): undefined symbol READ_TEXT_WORD referenced from
+text segment.
+
+6- Uncomment 'uses crt' if it was commented, and change the definition of
+number as real. The program will compile, and it will print the number,
+although in the same line as the input.
+
+7- Finally, comment 'uses crt' again. This time it will also compile and link,
+but it gives a runtime error!
+
+Laufzeitfehler 106 bei 66422
+
+This error is shown before printing the number.
+
+I expect that these bug report will be useful to debug the RTL. Tonight I will
+try to work in the blockwrite problem.
+
+Best regards
+
+Ramon
+
+-- 
+}

+ 2082 - 0
rtl/os2/objects.pas

@@ -0,0 +1,2082 @@
+{**********[ SOURCE FILE OF FREE VISION ]***************}
+{                                                       }
+{   Parts Copyright (c) 1992,96 by Florian Klaempfl     }
+{   [email protected]                     }
+{                                                       }
+{   Parts Copyright (c) 1996 by Frank ZAGO              }
+{   [email protected]                                }
+{                                                       }
+{   Parts Copyright (c) 1995 by MH Spiegel              }
+{                                                       }
+{   Parts Copyright (c) 1996 by Leon de Boer            }
+{   [email protected]                                     }
+{                                                       }
+{              THIS CODE IS FREEWARE                    }
+{*******************************************************}
+
+{***************[ SUPPORTED PLATFORMS ]*****************}
+{  16 and 32 Bit compilers                              }
+{     DOS      - Turbo Pascal 7.0 +      (16 Bit)       }
+{              - FPK Pascal              (32 Bit)       }
+{     DPMI     - Turbo Pascal 7.0 +      (16 Bit)       }
+{     WINDOWS  - Turbo Pascal 7.0 +      (16 Bit)       }
+{     OS2      - Virtual Pascal 0.3 +    (32 Bit)       }
+{                SpeedPascal 1.5 G +     (32 Bit)       }
+{                C'T patch to BP         (16 Bit)       }
+{*******************************************************}
+
+UNIT Objects;
+
+{$I os.inc}
+
+{<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>}
+                                  INTERFACE
+{<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>}
+
+{ ******************************* REMARK ****************************** }
+{  FPK does not accept  $IFNDEF compiler defines and mishandles $IFDEF  }
+{  with constants. Can we please get this error fixed!!!!!              }
+{ ****************************** END REMARK *** Leon de Boer, 10May96 * }
+
+{====Compiler conditional defines to sort platforms out =============}
+{$DEFINE NotFPKPascal}                                { Predefine Not FPK }
+{$DEFINE NotOS2}                                      { Predefine NOT OS2 }
+
+{$IFDEF FPK}                                          { FPK PASCAL }
+   {$DEFINE FPKPascal}                                { Set FPK definition }
+   {$DEFINE DOS_OS}                                   { Define DOS_OS }
+   {$DEFINE CODE_32_BIT}                              { 32 BIT CODE }
+   {$UNDEF USE_BGI}                                   { Can't use BGI }
+   {$UNDEF NotFPKPascal}                              { This is FPK pascal }
+{$ENDIF}
+
+{$IFDEF MSDOS}                                        { MSDOS PLATFORM }
+   {$DEFINE DOS_OS}                                   { Define DOS_OS }
+{$ENDIF}
+
+{$IFDEF DPMI}                                         { DPMI PLATFORM }
+   {$DEFINE DOS_OS}                                   { Define DOS_OS }
+{$ENDIF}
+
+{$IFDEF Windows}                                      { WINDOWS platform }
+   {$DEFINE ADV_OS}                                   { Set as advanced }
+   {$UNDEF USE_BGI}                                   { Can't use BGI }
+{$ENDIF}
+
+{$IFDEF OS2}                                          { OS2 platform }
+   {$DEFINE ADV_OS}                                   { Set as advanced }
+   {$IFNDEF FPK}
+	{$DEFINE BPOS2}                                    { Define BPOS2 }
+   {$ENDIF FPK}
+   {$UNDEF NotOS2}                                    { This is OS2 compiler }
+   {$UNDEF USE_BGI}                                   { Can't use BGI }
+   {$UNDEF DOS_OS}
+{$ENDIF}
+
+{$IFDEF VirtualPascal}                                { VIRTUAL PASCAL }
+   {$DEFINE CODE_32_BIT}                              { 32 BIT CODE }
+   {$DEFINE ASM_32_BIT}                               { 32 BIT ASSSEMBLER }
+   {$DEFINE API_32_BIT}                               { 32 BIT API CALLS }
+   {$UNDEF BPOS2}                                     { Undefine BPOS2 }
+{$ENDIF}
+
+{$IFDEF Speed}                                        { SPEED PASCAL }
+   {$DEFINE CODE_32_BIT}                              { 32 BIT CODE }
+   {$DEFINE ASM_32_BIT}                               { 32 BIT ASSSEMBLER }
+   {$DEFINE API_32_BIT}                               { 32 BIT API CALLS }
+   {$UNDEF BPOS2}                                     { Undefine BPOS2 }
+{$ENDIF}
+{--------------------------------------------------------------------}
+
+{ ******************************* REMARK ****************************** }
+{ How about FPK accepting all the standard compiler directives even if  }
+{ It just ignores them for now!!                                        }
+{ ****************************** END REMARK *** Leon de Boer, 10May96 * }
+
+{==== Compiler directives ===========================================}
+{$IFDEF FPKPascal}                                    { FPK PASCAL }
+   {$E-}
+   {$DEFINE NoExceptions}
+   {$DEFINE SString}
+
+   CONST
+      Sw_MaxData = 128*1024*1024;                     { Maximum data size }
+
+   TYPE
+      Sw_Word    = LongInt;                           { Long integer now }
+      Sw_Integer = LongInt;                           { Long integer now }
+
+   TYPE
+      FuncPtr = FUNCTION (Item: Pointer; _EBP: Sw_Word): Boolean;
+      ProcPtr = PROCEDURE (Item: Pointer; _EBP: Sw_Word);
+
+{$ENDIF}
+{$IFDEF NotFPKPascal}                                 { ALL OTHER COMPILERS }
+   {$N-} {  No 80x87 code generation }
+   {$O+} { This unit may be overlaid }
+   {$X+} { Extended syntax is ok }
+   {$F+} { Force far calls }
+   {$A+} { Word Align Data }
+   {$G+} { 286 Code optimization - if you're on an 8088 get a real computer }
+   {$R-} { Disable range checking }
+   {$S-} { Disable Stack Checking }
+   {$I-} { Disable IO Checking }
+   {$Q-} { Disable Overflow Checking }
+   {$V-} { Turn off strict VAR strings }
+   {$B-} { Allow short circuit boolean evaluations }
+
+   {$IFNDEF CODE_32_BIT}                              { 16 BIT DEFINITIONS }
+   CONST
+      Sw_MaxData = 65520;                             { Maximum data size }
+
+   TYPE
+      Sw_Word    = Word;                              { Standard word }
+      Sw_Integer = Integer;                           { Standard integer }
+   {$ELSE}                                            { 32 BIT DEFINITIONS }
+   CONST
+      Sw_MaxData = 128*1024*1024;                     { Maximum data size }
+
+   TYPE
+      Sw_Word    = LongInt;                           { Long integer now }
+      Sw_Integer = LongInt;                           { Long integer now }
+   {$ENDIF}
+
+   TYPE
+   {$IFDEF VirtualPascal}                             { VP is different }
+      FuncPtr = FUNCTION (Item: Pointer): Boolean;
+   {$ELSE}                                            { All others }
+      FuncPtr = FUNCTION (Item: Pointer; _EBP: Sw_Word): Boolean;
+   {$ENDIF}
+
+   TYPE
+   {$IFDEF VirtualPascal}                             { VP is different }
+      ProcPtr = PROCEDURE (Item: Pointer);
+   {$ELSE}                                            { All others }
+      ProcPtr = PROCEDURE (Item: Pointer; _EBP: Sw_Word);
+   {$ENDIF}
+
+{$ENDIF}
+{---------------------------------------------------------------------}
+
+CONST
+{ÞßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßÝ}
+{Þ                         STREAM ERROR STATE MASKS                        Ý}
+{ÞÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÝ}
+   stOk         =  0;                                 { No stream error }
+   stError      = -1;                                 { Access error }
+   stInitError  = -2;                                 { Initialize error }
+   stReadError  = -3;                                 { Stream read error }
+   stWriteError = -4;                                 { Stream write error }
+   stGetError   = -5;                                 { Get object error }
+   stPutError   = -6;                                 { Put object error }
+   stSeekError  = -7;                                 { Seek error in stream }
+   stOpenError  = -8;                                 { Error opening stream }
+
+CONST
+{ÞßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßÝ}
+{Þ                       STREAM ACCESS MODE CONSTANTS                      Ý}
+{ÞÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÝ}
+   stCreate    = $3C00;                               { Create new file }
+   stOpenRead  = $3D00;                               { Read access only }
+   stOpenWrite = $3D01;                               { Write access only }
+   stOpen      = $3D02;                               { Read/write access }
+
+CONST
+{ÞßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßÝ}
+{Þ                         TCollection ERROR CODES                         Ý}
+{ÞÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÝ}
+   coIndexError = -1;                                 { Index out of range }
+   coOverflow   = -2;                                 { Overflow }
+
+CONST
+{ ******************************* REMARK ****************************** }
+{   These are completely NEW FREE VISION ONLY constants that are used   }
+{  in conjuction with CreateStream a NEW FREE VISION call. This call    }
+{  tries creating a stream in the order of the Strategy Mask and will   }
+{  return the successfully created stream or nil if it fails.           }
+{ ****************************** END REMARK *** Leon de Boer, 15May96 * }
+
+{ÞßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßÝ}
+{Þ                      STREAM CREATE STRATEGY MASKS                       Ý}
+{ÞÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÝ}
+   sa_XMSFirst   = $8000;                             { Use XMS memory 1st }
+   sa_EMSFirst   = $4000;                             { Use EMS memory 1st }
+   sa_RAMFirst   = $2000;                             { Use RAM memory 1st }
+   sa_DISKFirst  = $1000;                             { Use DISK space 1st }
+   sa_XMSSecond  = $0800;                             { Use XMS memory 2nd }
+   sa_EMSSecond  = $0400;                             { Use EMS memory 2nd }
+   sa_RAMSecond  = $0200;                             { Use RAM memory 2nd }
+   sa_DISKSecond = $0100;                             { Use DISK space 2nd }
+   sa_XMSThird   = $0080;                             { Use XMS memory 3rd }
+   sa_EMSThird   = $0040;                             { Use EMS memory 3rd }
+   sa_RAMThird   = $0020;                             { Use RAM memory 3rd }
+   sa_DISKThird  = $0010;                             { Use DISK space 3rd }
+   sa_XMSFourth  = $0008;                             { Use XMS memory 4th }
+   sa_EMSFourth  = $0004;                             { Use EMS memory 4th }
+   sa_RAMFourth  = $0002;                             { Use RAM memory 4th }
+   sa_DISKFourth = $0001;                             { Use DISK space 4th }
+
+CONST
+{ÞßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßÝ}
+{Þ                          GENERAL USE CONSTANTS                          Ý}
+{ÞÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÝ}
+{$IFDEF VirtualPascal}
+   vmtHeaderSize = 12;                                { VMT header size }
+{$ELSE}
+   vmtHeaderSize = 8;                                 { VMT header size }
+{$ENDIF}
+
+CONST
+{ÞßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßÝ}
+{Þ                   MAXIMUM COLLECTION SIZE CONSTANT                      Ý}
+{ÞÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÝ}
+   MaxCollectionSize = Sw_MaxData DIV SizeOf(Pointer);{ Max collection size }
+
+TYPE
+{ÞßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßÝ}
+{Þ                              CHARACTER SET                              Ý}
+{ÞÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÝ}
+   TCharSet = SET Of Char;                            { Character set }
+   PCharSet = ^TCharSet;                              { Character set ptr }
+
+TYPE
+{ÞßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßÝ}
+{Þ                              GENERAL ARRAYS                             Ý}
+{ÞÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÝ}
+   TByteArray = ARRAY [0..Sw_MaxData-1] Of Byte;      { Byte array }
+   PByteArray = ^TByteArray;                          { Byte array pointer }
+
+   TWordArray = ARRAY [0..Sw_MaxData DIV 2-1] Of Word;{ Word array }
+   PWordArray = ^TWordArray;                          { Word array pointer }
+
+TYPE
+{ÞßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßÝ}
+{Þ                           DOS FILENAME STRING                           Ý}
+{ÞÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÝ}
+{$IFDEF DOS_OS}                                       { DOS/DPMI DEFINE }
+   FNameStr = String[79];                             { DOS filename }
+{$ENDIF}
+{$IFDEF Windows}                                      { WINDOWS DEFINE }
+   FNameStr = PChar;                                  { Windows filename }
+{$ENDIF}
+{$IFDEF OS2}                                          { OS2 DEFINE }
+   FNameStr = String;                                 { OS2 filename }
+{$ENDIF}
+
+TYPE
+{ÞßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßÝ}
+{Þ                           DOS ASCIIZ FILENAME                           Ý}
+{ÞÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÝ}
+   AsciiZ = Array [0..255] Of Char;                   { Filename array }
+
+TYPE
+{ÞßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßÝ}
+{Þ                          GENERAL TYPE POINTERS                          Ý}
+{ÞÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÝ}
+   PByte    = ^Byte;                                  { Byte pointer }
+   PWord    = ^Word;                                  { Word pointer }
+   PLongInt = ^LongInt;                               { LongInt pointer }
+   PString  = ^String;                                { String pointer }
+
+{***************************************************************************}
+{                            RECORD DEFINITIONS                             }
+{***************************************************************************}
+TYPE
+{ÞßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßÝ}
+{Þ                         TYPE CONVERSION RECORDS                         Ý}
+{ÞÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÝ}
+   WordRec = RECORD
+     Lo, Hi: Byte;                                    { Word to bytes }
+   END;
+
+   LongRec = RECORD
+     Lo, Hi: Word;                                    { LongInt to words }
+   END;
+
+   PtrRec = RECORD
+     Ofs, Seg: Word;                                  { Pointer to words }
+   END;
+
+TYPE
+{ÞßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßÝ}
+{Þ                 TStreamRec RECORD - STREAM OBJECT RECORD                Ý}
+{ÞÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÝ}
+   PStreamRec = ^TStreamRec;                          { Stream record ptr }
+   TStreamRec = RECORD
+      ObjType: Sw_Word;                               { Object type id }
+      VmtLink: Sw_Word;                               { VMT link }
+      Load : Pointer;                                 { Object load code }
+      Store: Pointer;                                 { Object store code }
+      Next : Sw_Word;                                 { Bytes to next }
+   END;
+
+{***************************************************************************}
+{                            OBJECT DEFINITIONS                             }
+{***************************************************************************}
+
+TYPE
+{ÞßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßÝ}
+{Þ                       TPoint RECORD - POINT RECORD                      Ý}
+{ÞÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÝ}
+   TPoint = RECORD
+      X, Y: Integer;                                  { Point co-ordinates }
+   END;
+
+{ÞßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßÝ}
+{Þ                     TRect OBJECT - RECTANGLE OBJECT                     Ý}
+{ÞÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÝ}
+   TRect = OBJECT
+         A, B: TPoint;                                { Corner points }
+      FUNCTION Empty: Boolean;
+      FUNCTION Equals (R: TRect): Boolean;
+      FUNCTION Contains (P: TPoint): Boolean;
+      PROCEDURE Copy (R: TRect);
+      PROCEDURE Union (R: TRect);
+      PROCEDURE Intersect (R: TRect);
+      PROCEDURE Move (ADX, ADY: Integer);
+      PROCEDURE Grow (ADX, ADY: Integer);
+      PROCEDURE Assign (XA, YA, XB, YB: Integer);
+   END;
+   PRect = ^TRect;
+
+TYPE
+{ÞßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßÝ}
+{Þ                 TObject OBJECT - BASE ANCESTOR OBJECT                   Ý}
+{ÞÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÝ}
+   TObject = OBJECT
+      CONSTRUCTOR Init;
+      PROCEDURE Free;
+      DESTRUCTOR Done;                                               Virtual;
+   END;
+   PObject = ^TObject;
+
+TYPE
+{ ******************************* REMARK ****************************** }
+{  Two new virtual methods have been added to the object in the form of }
+{  Close and Open. The main use here is in the Disk Based Descendants   }
+{  the calls open and close the given file so these objects can be      }
+{  used like standard files. All existing code will compile and work    }
+{  completely normally oblivious to these new methods.                  }
+{ ****************************** END REMARK *** Leon de Boer, 15May96 * }
+{ÞßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßÝ}
+{Þ                TStream OBJECT - STREAM ANCESTOR OBJECT                  Ý}
+{ÞÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÝ}
+   TStream = OBJECT (TObject)
+         Status   : Integer;                          { Stream status }
+         ErrorInfo: Integer;                          { Stream error info }
+      FUNCTION Get: PObject;
+      FUNCTION StrRead: PChar;
+      FUNCTION GetPos: LongInt;                                      Virtual;
+      FUNCTION GetSize: LongInt;                                     Virtual;
+      FUNCTION ReadStr: PString;
+      PROCEDURE Close;                                               Virtual;
+      PROCEDURE Reset;
+      PROCEDURE Flush;                                               Virtual;
+      PROCEDURE Truncate;                                            Virtual;
+      PROCEDURE Put (P: PObject);
+      PROCEDURE Seek (Pos: LongInt);                                 Virtual;
+      PROCEDURE StrWrite (P: PChar);
+      PROCEDURE WriteStr (P: PString);
+      PROCEDURE Open (OpenMode: Word);                               Virtual;
+      PROCEDURE Error (Code, Info: Integer);                         Virtual;
+      PROCEDURE Read (Var Buf; Count: Sw_Word);                      Virtual;
+      PROCEDURE Write (Var Buf; Count: Sw_Word);                     Virtual;
+      PROCEDURE CopyFrom (Var S: TStream; Count: Longint);
+   END;
+   PStream = ^TStream;
+
+TYPE
+{ÞßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßÝ}
+{Þ               TDosStream OBJECT - DOS FILE STREAM OBJECT                Ý}
+{ÞÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÝ}
+   TDosStream = OBJECT (TStream)
+         Handle: Integer;                             { DOS file handle }
+         FName : AsciiZ;                              { AsciiZ filename }
+      CONSTRUCTOR Init (FileName: FNameStr; Mode: Word);
+      DESTRUCTOR Done;                                               Virtual;
+      FUNCTION GetPos: Longint;                                      Virtual;
+      FUNCTION GetSize: Longint;                                     Virtual;
+      PROCEDURE Close;                                               Virtual;
+      PROCEDURE Seek (Pos: LongInt);                                 Virtual;
+      PROCEDURE Open (OpenMode: Word);                               Virtual;
+      PROCEDURE Read (Var Buf; Count: Sw_Word);                      Virtual;
+      PROCEDURE Write (Var Buf; Count: Sw_Word);                     Virtual;
+   END;
+   PDosStream = ^TDosStream;
+
+TYPE
+{ÞßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßÝ}
+{Þ               TBufStream OBJECT - BUFFERED DOS FILE STREAM              Ý}
+{ÞÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÝ}
+   TBufStream = OBJECT (TDosStream)
+   END;
+   PBufStream = ^TBufStream;
+
+TYPE
+{ÞßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßÝ}
+{Þ                  TEmsStream OBJECT - EMS STREAM OBJECT                  Ý}
+{ÞÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÝ}
+   TEmsStream = OBJECT (TStream)
+   END;
+   PEmsStream = ^TEmsStream;
+
+TYPE
+{ÞßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßÝ}
+{Þ                  TXmsStream OBJECT - XMS STREAM OBJECT                  Ý}
+{ÞÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÝ}
+   TXmsStream = OBJECT (TStream)
+   END;
+   PXmsStream = ^TXmsStream;
+
+TYPE
+{ÞßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßÝ}
+{Þ              TMemoryStream OBJECT - MEMORY STREAM OBJECT                Ý}
+{ÞÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÝ}
+   TMemoryStream = OBJECT (TStream)
+   END;
+   PMemoryStream = ^TMemoryStream;
+
+TYPE
+  TItemList = Array [0..MaxCollectionSize - 1] Of Pointer;
+  PItemList = ^TItemList;
+
+{ ******************************* REMARK ****************************** }
+{    The changes here look worse than they are. The Sw_Integer simply   }
+{  switches between Integers and LongInts if switched between 16 and 32 }
+{  bit code. All existing code will compile without any changes.        }
+{ ****************************** END REMARK *** Leon de Boer, 10May96 * }
+
+{ÞßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßÝ}
+{Þ             TCollection OBJECT - COLLECTION ANCESTOR OBJECT             Ý}
+{ÞÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÝ}
+   TCollection = OBJECT (TObject)
+         Items: PItemList;                            { Item list pointer }
+         Count: Sw_Integer;                           { Item count }
+         Limit: Sw_Integer;                           { Item limit count }
+         Delta: Sw_Integer;                           { Inc delta size }
+      CONSTRUCTOR Init (ALimit, ADelta: Sw_Integer);
+      CONSTRUCTOR Load (Var S: TStream);
+      DESTRUCTOR Done;                                               Virtual;
+      FUNCTION At (Index: Sw_Integer): Pointer;
+      FUNCTION IndexOf (Item: Pointer): Sw_Integer;                  Virtual;
+      FUNCTION GetItem (Var S: TStream): Pointer;                    Virtual;
+      FUNCTION LastThat (Test: Pointer): Pointer;
+      FUNCTION FirstThat (Test: Pointer): Pointer;
+      PROCEDURE Pack;
+      PROCEDURE FreeAll;
+      PROCEDURE DeleteAll;
+      PROCEDURE Free (Item: Pointer);
+      PROCEDURE Insert (Item: Pointer);                              Virtual;
+      PROCEDURE Delete (Item: Pointer);
+      PROCEDURE AtFree (Index: Sw_Integer);
+      PROCEDURE FreeItem (Item: Pointer);                            Virtual;
+      PROCEDURE AtDelete (Index: Sw_Integer);
+      PROCEDURE ForEach (Action: Pointer);
+      PROCEDURE SetLimit (ALimit: Sw_Integer);                       Virtual;
+      PROCEDURE Error (Code, Info: Integer);                         Virtual;
+      PROCEDURE AtPut (Index: Sw_Integer; Item: Pointer);
+      PROCEDURE AtInsert (Index: Sw_Integer; Item: Pointer);
+      PROCEDURE Store (Var S: TStream);
+      PROCEDURE PutItem (Var S: TStream; Item: Pointer);             Virtual;
+   END;
+   PCollection = ^TCollection;
+
+TYPE
+{ÞßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßÝ}
+{Þ         TSortedCollection OBJECT - SORTED COLLECTION ANCESTOR           Ý}
+{ÞÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÝ}
+   TSortedCollection = OBJECT (TCollection)
+         Duplicates: Boolean;                         { Duplicates flag }
+      CONSTRUCTOR Init (ALimit, ADelta: Sw_Integer);
+      CONSTRUCTOR Load (Var S: TStream);
+      FUNCTION KeyOf (Item: Pointer): Pointer;                       Virtual;
+      FUNCTION IndexOf (Item: Pointer): Sw_Integer;                  Virtual;
+      FUNCTION Compare (Key1, Key2: Pointer): Sw_Integer;            Virtual;
+      FUNCTION Search (Key: Pointer; Var Index: Sw_Integer): Boolean;Virtual;
+      PROCEDURE Insert (Item: Pointer);                              Virtual;
+      PROCEDURE Store (Var S: TStream);
+   END;
+   PSortedCollection = ^TSortedCollection;
+
+TYPE
+{ÞßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßÝ}
+{Þ          TStringCollection OBJECT - STRING COLLECTION OBJECT            Ý}
+{ÞÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÝ}
+   TStringCollection = OBJECT (TSortedCollection)
+      FUNCTION GetItem (Var S: TStream): Pointer;                    Virtual;
+      FUNCTION Compare (Key1, Key2: Pointer): Sw_Integer;            Virtual;
+      PROCEDURE FreeItem (Item: Pointer);                            Virtual;
+      PROCEDURE PutItem (Var S: TStream; Item: Pointer);             Virtual;
+   END;
+   PStringCollection = ^TStringCollection;
+
+TYPE
+{ ******************************* REMARK ****************************** }
+{    This is a completely NEW FREE VISION ONLY object which holds a     }
+{  collection of strings but does not alphabetically sort them. It is   }
+{  a very useful object as you will find !!!!                           }
+{ ****************************** END REMARK *** Leon de Boer, 15May96 * }
+{ÞßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßÝ}
+{Þ        TUnSortedStrCollection - UNSORTED STRING COLLECTION OBJECT       Ý}
+{ÞÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÝ}
+   TUnSortedStrCollection = OBJECT (TStringCollection)
+      PROCEDURE Insert (Item: Pointer);                              Virtual;
+   END;
+   PUnSortedStrCollection = ^TUnSortedStrCollection;
+
+{***************************************************************************}
+{                            INTERFACE ROUTINES                             }
+{***************************************************************************}
+
+{ÞßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßÝ}
+{Þ                   DYNAMIC STRING INTERFACE ROUTINES                     Ý}
+{ÞÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÝ}
+FUNCTION NewStr (Const S: String): PString;
+PROCEDURE DisposeStr (P: PString);
+
+{ÞßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßÝ}
+{Þ                       STREAM INTERFACE ROUTINES                         Ý}
+{ÞÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÝ}
+PROCEDURE Abstract;
+PROCEDURE RegisterError;
+
+{ÞßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßÝ}
+{Þ                     NEW FREE VISION STREAM ROUTINES                     Ý}
+{ÞÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÝ}
+
+{ ******************************* REMARK ****************************** }
+{   This NEW FREE VISION call tries creating a stream in the order of   }
+{  the Strategy Mask and will return the successfully created stream    }
+{  or nil if it fails using the strategy given.                         }
+{ ****************************** END REMARK *** Leon de Boer, 15May96 * }
+FUNCTION CreateStream (Strategy: Word; ReqSize: LongInt): PStream;
+
+{ ******************************* REMARK ****************************** }
+{   As we have to provide these NEW FREE VISION CALLS as part of our    }
+{  stream support we might as well provide them on the interface! They  }
+{  mimic the behaviour of the OS2 API calls in most cases.              }
+{ ****************************** END REMARK *** Leon de Boer, 16May96 * }
+
+{ÞßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßÝ}
+{Þ                    NEW FREE VISION DOS FILE ROUTINES                    Ý}
+{ÞÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÝ}
+
+{=DosFileOpen=========================================================
+Calls the operating system to try to open the file denoted by the given
+AsciiZ filename in the requested file mode. Any error is held in
+DosStreamError and the call will return zero. If successful and no error
+occurs the call will return the file handle of the opened file.
+-> Platforms DOS/DPMI/WIN - Checked 16May96 LdB
+=====================================================================}
+FUNCTION DosFileOpen (Var FileName: AsciiZ; Mode: Word): Word;
+
+{=DosRead============================================================
+Calls the operating system to read BufferLength bytes of data from
+the file denoted by the handle to the bufferarea. Any error in attempting
+to read from the file is held in DosStreamError and returned from call.
+If the return is zero (ie no error) BytesMoved contains the number of
+bytes read from the file.
+-> Platforms DOS/DPMI/WIN - Checked 16May96 LdB
+=====================================================================}
+FUNCTION DosRead(Handle: Word; Var BufferArea; BufferLength: Sw_Word;
+Var BytesMoved: Sw_Word): Word;
+
+{=DosWrite===========================================================
+Calls the operating system to write to BufferLength bytes of data from
+the bufferarea to the file denoted by the handle. Any error in attempting
+to write to the file is held in DosStreamError and returned from call.
+If the return is zero (ie no error) BytesMoved contains the number of
+bytes written to the file.
+-> Platforms DOS/DPMI/WIN - Checked 16May96 LdB
+=====================================================================}
+FUNCTION DosWrite(Handle: Word; Var BufferArea; BufferLength: Sw_Word;
+Var BytesMoved: Sw_Word): Word;
+
+{=DosSetFilePtr======================================================
+Calls the operating system to move the file denoted by the handle to
+to the requested position. The move method can be: 0 = absolute offset;
+1 = offset from present location; 2 = offset from end of file;
+Any error is held in DosErrorStream and returned from the call.
+If the return is zero (ie no error) NewPos contains the new absolute
+file position.
+-> Platforms DOS/DPMI/WIN - Checked 16May96 LdB
+=====================================================================}
+FUNCTION DosSetFilePtr (Handle: Word; Pos: LongInt; MoveType: Word;
+Var NewPos: LongInt): Word;
+
+{=DosClose===========================================================
+Calls the operating system to close the file handle provided. Any error
+in attempting to close file is held DosErrorStream.
+-> Platforms DOS/DPMI/WIN - Checked 16May96 LdB
+=====================================================================}
+PROCEDURE DosClose (Handle: Word);
+
+CONST
+{ÞßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßÝ}
+{Þ                      INITIALIZED PUBLIC VARIABLES                       Ý}
+{ÞÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÝ}
+   StreamError: Pointer = Nil;                        { Stream error ptr }
+{$IFDEF NotFPKPascal}
+   DosStreamError: Sw_Word = $0;                      { Dos stream error }
+{$ENDIF}
+
+{ ******************************* REMARK ****************************** }
+{  FPK does not accept local variables with it's assembler which means  }
+{  these have to be global. Can we please get this error fixed!!!!!     }
+{ ****************************** END REMARK *** Leon de Boer, 10May96 * }
+{$IFDEF FPKPascal}                                    { FPK Pascal compiler }
+VAR HoldEBP: Sw_Word; TransferHandle: Sw_Word;
+    DosStreamError: Sw_Word ;                         { Dos stream error }
+{$ENDIF}
+
+
+{<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>}
+                                IMPLEMENTATION
+{<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>}
+{$IFDEF Windows}                                      { WINDOWS CODE }
+USES WinTypes, WinProcs;                              { Standard units }
+{$ENDIF}
+
+{$IFDEF Speed}                                        { SPEED PASCAL CODE }
+USES BseDos;                                          { Speed Pascal def }
+{$ENDIF}
+
+{$IFDEF VirtualPascal}                                { VIRTUAL PASCAL CODE }
+USES OS2Base;                                         { Virtual Pascal base }
+{$ENDIF}
+
+{$IFDEF BPOS2}                                        { C'T PATCH TO BP CODE }
+
+   FUNCTION DosClose (Handle: Word): Word; FAR;
+     EXTERNAL 'DOSCALLS' Index 59;                    { Dos close function }
+
+   FUNCTION DosOpen (FileName: PChar; Var Handle: Word;
+     Var ActionTaken: Word; FileSize: LongInt;
+     FileAttr: Word; OpenFlag, OpenMode: Word;
+     Reserved: Pointer): Word; FAR;
+     EXTERNAL 'DOSCALLS' Index 70;                    { Dos open function }
+
+   FUNCTION DosRead(Handle: Word; Var BufferArea;
+     BufferLength: Word; Var BytesRead : Word): Word; FAR;
+     EXTERNAL 'DOSCALLS' Index 137;                   { Dos read procedure }
+
+   FUNCTION DosWrite(Handle: Word; Var BufferArea;
+     BufferLength: Word; Var BytesRead : Word): Word; FAR;
+     EXTERNAL 'DOSCALLS' Index 138;                   { Dos write procedure }
+
+   FUNCTION DosSetFilePtr (Handle: Word; ulOffset: LongInt;
+     MoveType: Word; Var NewPointer: LongInt): LongInt; FAR;
+     EXTERNAL 'DOSCALLS' Index 58;                    { Dos write procedure }
+{$ENDIF}
+
+{$IFDEF OS2}                                          { OS2 CODE }
+CONST
+{ Private Os2 File mode magic numbers }
+   FmInput  = $20;                                    { Open file for input }
+   FmOutput = $31;                                    { Open file for output }
+   FmInout  = $42;                                    { Open file }
+   FmClosed = $0;                                     { Close file }
+{$ENDIF}
+
+{$IFDEF DPMI}                                         { DPMI CODE }
+  {$DEFINE NewExeFormat}                              { New format EXE }
+{$ENDIF}
+
+{$IFDEF ADV_OS}                                       { WINDOWS/OS2 CODE }
+  {$DEFINE NewExeFormat}                              { New format EXE }
+{$ENDIF}
+
+CONST
+{ÞßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßÝ}
+{Þ                     INITIALIZED PRIVATE VARIABLES                       Ý}
+{ÞÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÝ}
+   StreamTypes: Sw_Word = $0;                         { Stream types }
+
+{***************************************************************************}
+{                               OBJECT METHODS                              }
+{***************************************************************************}
+
+{ÞßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßÝ}
+{Þ                          TRect OBJECT METHODS                           Ý}
+{ÞÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÝ}
+
+PROCEDURE CheckEmpty (Var Rect: TRect);
+{ ******************************* REMARK ****************************** }
+{  This is is my desired code but FPK does not like the with statement  }
+{  Can we please get this error fixed!!!!!                              }
+{ ****************************** END REMARK *** Leon de Boer, 10May96 * }
+{   With Rect Do Begin }
+{     If (A.X >= B.X) OR (A.Y >= B.Y) Then Begin    }   { Zero of reversed }
+{       A.X := 0;                                   }   { Clear a.x }
+{       A.Y := 0;                                   }   { Clear a.y }
+{       B.X := 0;                                   }   { Clear b.x }
+{       B.Y := 0;                                   }   { Clear b.y }
+{     End; }
+{   End; }
+BEGIN
+   If (Rect.A.X >= Rect.B.X) OR
+   (Rect.A.Y >= Rect.B.Y) Then Begin                  { Zero of reversed }
+     Rect.A.X := 0;                                   { Clear a.x }
+     Rect.A.Y := 0;                                   { Clear a.y }
+     Rect.B.X := 0;                                   { Clear b.x }
+     Rect.B.Y := 0;                                   { Clear b.y }
+   End;
+END;
+
+{ ******************************* REMARK ****************************** }
+{  This is a bug fix of EMPTY from the original code which was:         }
+{  Empty := (A.X = B.X) AND (A.Y = B.Y)                                 }
+{ ****************************** END REMARK *** Leon de Boer, 10May96 * }
+
+{**TRect********************************************************************}
+{  Empty -> Platforms DOS/DPMI/WIN/OS2 - Checked 10May96 LdB                }
+{***************************************************************************}
+FUNCTION TRect.Empty: Boolean;
+BEGIN
+   Empty := (A.X >= B.X) OR (A.Y >= B.Y);             { Empty result }
+END;
+
+{**TRect********************************************************************}
+{  Equals -> Platforms DOS/DPMI/WIN/OS2 - Checked 10May96 LdB               }
+{***************************************************************************}
+FUNCTION TRect.Equals (R: TRect): Boolean;
+BEGIN
+   Equals := (A.X = R.A.X) AND (A.Y = R.A.Y) AND
+   (B.X = R.B.X) AND (B.Y = R.B.Y);                   { Equals result }
+END;
+
+{ ******************************* REMARK ****************************** }
+{  This is a bug fix of Contains from the original code which was:      }
+{   Contains := (P.X >= A.X) AND (P.X <= B.X) AND                       }
+{     (P.Y >= A.Y) AND (P.Y <= B.Y)                                     }
+{ ****************************** END REMARK *** Leon de Boer, 10May96 * }
+
+{**TRect********************************************************************}
+{  Contains -> Platforms DOS/DPMI/WIN/OS2 - Checked 10May96 LdB             }
+{***************************************************************************}
+FUNCTION TRect.Contains (P: TPoint): Boolean;
+BEGIN
+   Contains := (P.X >= A.X) AND (P.X < B.X) AND
+     (P.Y >= A.Y) AND (P.Y < B.Y);                    { Contains result }
+END;
+
+{**TRect********************************************************************}
+{  Copy -> Platforms DOS/DPMI/WIN/OS2 - Checked 10May96 LdB                 }
+{***************************************************************************}
+PROCEDURE TRect.Copy (R: TRect);
+BEGIN
+   A := R.A;                                          { Copy point a }
+   B := R.B;                                          { Copy point b }
+END;
+
+{**TRect********************************************************************}
+{  Union -> Platforms DOS/DPMI/WIN/OS2 - Checked 10May96 LdB                }
+{***************************************************************************}
+PROCEDURE TRect.Union (R: TRect);
+BEGIN
+   If (R.A.X < A.X) Then A.X := R.A.X;                { Take if smaller }
+   If (R.A.Y < A.Y) Then A.Y := R.A.Y;                { Take if smaller }
+   If (R.B.X > B.X) Then B.X := R.B.X;                { Take if larger }
+   If (R.B.Y > B.Y) Then B.Y := R.B.Y;                { Take if larger }
+END;
+
+{**TRect********************************************************************}
+{  Intersect -> Platforms DOS/DPMI/WIN/OS2 - Checked 10May96 LdB            }
+{***************************************************************************}
+PROCEDURE TRect.Intersect (R: TRect);
+BEGIN
+   If (R.A.X > A.X) Then A.X := R.A.X;                { Take if larger }
+   If (R.A.Y > A.Y) Then A.Y := R.A.Y;                { Take if larger }
+   If (R.B.X < B.X) Then B.X := R.B.X;                { Take if smaller }
+   If (R.B.Y < B.Y) Then B.Y := R.B.Y;                { Take if smaller }
+   CheckEmpty(Self);                                  { Check if empty }
+END;
+
+{**TRect********************************************************************}
+{  Move -> Platforms DOS/DPMI/WIN/OS2 - Checked 10May96 LdB                 }
+{***************************************************************************}
+PROCEDURE TRect.Move (ADX, ADY: Integer);
+BEGIN
+   Inc(A.X, ADX);                                     { Adjust A.X }
+   Inc(A.Y, ADY);                                     { Adjust A.Y }
+   Inc(B.X, ADX);                                     { Adjust B.X }
+   Inc(B.Y, ADY);                                     { Adjust B.Y }
+END;
+
+{**TRect********************************************************************}
+{  Grow -> Platforms DOS/DPMI/WIN/OS2 - Checked 10May96 LdB                 }
+{***************************************************************************}
+PROCEDURE TRect.Grow (ADX, ADY: Integer);
+BEGIN
+   Dec(A.X, ADX);                                     { Adjust A.X }
+   Dec(A.Y, ADY);                                     { Adjust A.Y }
+   Inc(B.X, ADX);                                     { Adjust B.X }
+   Inc(B.Y, ADY);                                     { Adjust B.Y }
+   CheckEmpty(Self);                                  { Check if empty }
+END;
+
+{**TRect********************************************************************}
+{  Assign -> Platforms DOS/DPMI/WIN/OS2 - Checked 10May96 LdB               }
+{***************************************************************************}
+PROCEDURE TRect.Assign (XA, YA, XB, YB: Integer);
+BEGIN
+   A.X := XA;                                         { Hold A.X value }
+   A.Y := YA;                                         { Hold A.Y value }
+   B.X := XB;                                         { Hold B.X value }
+   B.Y := YB;                                         { Hold B.Y value }
+END;
+
+{ÞßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßÝ}
+{Þ                          TObject OBJECT METHODS                         Ý}
+{ÞÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÝ}
+
+TYPE
+   DummyObject = OBJECT (TObject)                     { Internal object }
+     Data: RECORD END;                                { Helps size VMT link }
+   END;
+
+{ ******************************* REMARK ****************************** }
+{ I Prefer this code because it self sizes VMT link rather than using a }
+{ fixed record structure thus it should work on all compilers without a }
+{ specific record to match each compiler.                               }
+{ ****************************** END REMARK *** Leon de Boer, 10May96 * }
+CONSTRUCTOR TObject.Init;
+VAR LinkSize: LongInt; Dummy: DummyObject;
+BEGIN
+   LinkSize := LongInt(@Dummy.Data)-LongInt(@Dummy);  { Calc VMT link size }
+   FillChar(Pointer(LongInt(@Self)+LinkSize)^,
+     SizeOf(Self)-LinkSize, #0);                      { Clear data fields }
+END;
+
+{**TObject******************************************************************}
+{  Free -> Platforms DOS/DPMI/WIN/OS2 - Checked 10May96 LdB                 }
+{***************************************************************************}
+PROCEDURE TObject.Free;
+BEGIN
+   Dispose(PObject(@Self), Done);                     { Dispose of self }
+END;
+
+{**TObject******************************************************************}
+{  Done -> Platforms DOS/DPMI/WIN/OS2 - Checked 10May96 LdB                 }
+{***************************************************************************}
+DESTRUCTOR TObject.Done;
+BEGIN                                                 { Abstract method }
+END;
+
+{ÞßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßÝ}
+{Þ                          TStream OBJECT METHODS                         Ý}
+{ÞÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÝ}
+
+{ ******************************* REMARK ****************************** }
+{  Bug fix of TStream.StrRead from the original code which was:         }
+{  GetMem(P, L+1) can fail and return Nil which should be checked!      }
+{ ****************************** END REMARK *** Leon de Boer, 10May96 * }
+
+{**TStream******************************************************************}
+{  StrRead -> Platforms DOS/DPMI/WIN/OS2 - Checked 10May96 LdB              }
+{***************************************************************************}
+FUNCTION TStream.StrRead: PChar;
+VAR L: Word; P: PChar;
+BEGIN
+   Read(L, SizeOf(L));                                { Read length }
+   If (L=0) Then StrRead := Nil Else Begin            { Check for empty }
+     GetMem(P, L + 1);                                { Allocate memory }
+     If (P<>Nil) Then Begin                           { Check allocate okay }
+       Read(P[0], L);                                 { Read the data }
+       P[L] := #0;                                    { Terminate with #0 }
+     End;
+     StrRead := P;                                    { Return PChar }
+   End;
+END;
+
+{ ******************************* REMARK ****************************** }
+{  Bug fix of TStream.ReadStr from the original code which was:         }
+{  GetMem(P, L+1) can fail and return Nil which should be checked!      }
+{ ****************************** END REMARK *** Leon de Boer, 10May96 * }
+
+{**TStream******************************************************************}
+{  ReadStr -> Platforms DOS/DPMI/WIN/OS2 - Checked 10May96 LdB              }
+{***************************************************************************}
+FUNCTION TStream.ReadStr: PString;
+VAR L: Byte; P: PString;
+BEGIN
+   Read(L, 1);                                        { Read string length }
+   If (L > 0) Then Begin
+     GetMem(P, L + 1);                                { Allocate memory }
+     If (P<>Nil) Then Begin                           { Check allocate okay }
+       P^[0] := Char(L);                              { Hold length }
+       Read(P^[1], L);                                { Read string data }
+     End;
+     ReadStr := P;                                    { Return string ptr }
+   End Else ReadStr := Nil;
+END;
+
+{**TStream******************************************************************}
+{  GetPos -> Platforms DOS/DPMI/WIN/OS2 - Checked 10May96 LdB               }
+{***************************************************************************}
+FUNCTION TStream.GetPos: LongInt;
+BEGIN                                                 { Abstract method }
+   Abstract;                                          { Abstract error }
+END;
+
+{**TStream******************************************************************}
+{  GetSize -> Platforms DOS/DPMI/WIN/OS2 - Checked 10May96 LdB              }
+{***************************************************************************}
+FUNCTION TStream.GetSize: LongInt;
+BEGIN                                                 { Abstract method }
+   Abstract;                                          { Abstract error }
+END;
+
+{**TStream******************************************************************}
+{  Close -> Platforms DOS/DPMI/WIN/OS2 - Checked 10May96 LdB                }
+{***************************************************************************}
+PROCEDURE TStream.Close;
+BEGIN                                                 { Abstract method }
+END;
+
+{**TStream******************************************************************}
+{  Reset -> Platforms DOS/DPMI/WIN/OS2 - Checked 10May96 LdB                }
+{***************************************************************************}
+PROCEDURE TStream.Reset;
+BEGIN
+   Status := 0;                                       { Clear status }
+   ErrorInfo := 0;                                    { Clear error info }
+END;
+
+{**TStream******************************************************************}
+{  Flush -> Platforms DOS/DPMI/WIN/OS2 - Checked 10May96 LdB                }
+{***************************************************************************}
+PROCEDURE TStream.Flush;
+BEGIN                                                 { Abstract method }
+END;
+
+{**TStream******************************************************************}
+{  Truncate -> Platforms DOS/DPMI/WIN/OS2 - Checked 10May96 LdB             }
+{***************************************************************************}
+PROCEDURE TStream.Truncate;
+BEGIN
+   Abstract;                                          { Abstract error }
+END;
+
+{**TStream******************************************************************}
+{  Seek -> Platforms DOS/DPMI/WIN/OS2 - Checked 10May96 LdB                 }
+{***************************************************************************}
+PROCEDURE TStream.Seek (Pos: LongInt);
+BEGIN
+   Abstract;                                          { Abstract error }
+END;
+
+{**TStream******************************************************************}
+{  StrWrite -> Platforms DOS/DPMI/WIN/OS2 - Checked 10May96 LdB             }
+{***************************************************************************}
+PROCEDURE TStream.StrWrite (P: PChar);
+VAR L: Word; Q: PByteArray;
+BEGIN
+   L := 0;                                            { Preset no size }
+   Q := PByteArray(P);                                { Transfer type }
+   If (Q<>Nil) Then While (Q^[L]<>0) Do Inc(L);       { Calc PChar length }
+   Write(L, SizeOf(L));                               { Store PChar length }
+   If (P<>Nil) Then Write(P[0], L);                   { Write data }
+END;
+
+{**TStream******************************************************************}
+{  WriteStr -> Platforms DOS/DPMI/WIN/OS2 - Checked 10May96 LdB             }
+{***************************************************************************}
+PROCEDURE TStream.WriteStr (P: PString);
+CONST Empty: String[1] = '';
+BEGIN
+   If (P<>Nil) Then Write(P^, Length(P^) + 1)         { Write string }
+     Else Write(Empty, 1);                            { Write empty string }
+END;
+
+{**TStream******************************************************************}
+{  Open -> Platforms DOS/DPMI/WIN/OS2 - Checked 10May96 LdB                 }
+{***************************************************************************}
+PROCEDURE TStream.Open (OpenMode: Word);
+BEGIN                                                 { Abstract method }
+END;
+
+{**TStream******************************************************************}
+{  Error -> Platforms DOS/DPMI/WIN/OS2 - Checked 10May96 LdB                }
+{***************************************************************************}
+PROCEDURE TStream.Error (Code, Info: Integer);
+TYPE TErrorProc = Procedure(Var S: TStream);
+BEGIN
+   Status := Code;                                    { Hold error code }
+   ErrorInfo := Info;                                 { Hold error info }
+   If (StreamError<>Nil) Then
+     TErrorProc(StreamError)(Self);                   { Call error ptr }
+END;
+
+{**TStream******************************************************************}
+{  Read -> Platforms DOS/DPMI/WIN/OS2 - Checked 10May96 LdB                 }
+{***************************************************************************}
+PROCEDURE TStream.Read (Var Buf; Count: Sw_Word);
+BEGIN
+   Abstract;                                          { Abstract error }
+END;
+
+{**TStream******************************************************************}
+{  Write -> Platforms DOS/DPMI/WIN/OS2 - Checked 10May96 LdB                }
+{***************************************************************************}
+PROCEDURE TStream.Write (Var Buf; Count: Sw_Word);
+BEGIN
+   Abstract;                                          { Abstract error }
+END;
+
+{**TStream******************************************************************}
+{  CopyFrom -> Platforms DOS/DPMI/WIN/OS2 - Checked 10May96 LdB             }
+{***************************************************************************}
+PROCEDURE TStream.CopyFrom (Var S: TStream; Count: Longint);
+VAR W: Word; Buffer: Array[0..1023] of Byte;
+BEGIN
+   While (Count > 0) Do Begin
+     If (Count > SizeOf(Buffer)) Then                 { To much data }
+       W := SizeOf(Buffer) Else W := Count;           { Size to transfer }
+     S.Read(Buffer, W);                               { Read from stream }
+     Write(Buffer, W);                                { Write to stream }
+     Dec(Count, W);                                   { Dec write count }
+   End;
+END;
+
+{ÞßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßÝ}
+{Þ                        TDosStream OBJECT METHODS                        Ý}
+{ÞÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÝ}
+
+{**TDosStream***************************************************************}
+{  Init -> Platforms DOS/DPMI/WIN/OS2 - Checked 16May96 LdB                 }
+{***************************************************************************}
+CONSTRUCTOR TDosStream.Init (FileName: FNameStr; Mode: Word);
+BEGIN
+   Inherited Init;                                    { Call ancestor }
+   {$IFDEF Windows}
+   AnsiToOem(FileName, FName);                        { Ansi to OEM }
+   {$ELSE}
+   FileName := FileName+#0;                           { Make asciiz }
+   Move(FileName[1], FName, Length(FileName));        { Create asciiz name }
+   {$ENDIF}
+   Handle := DosFileOpen(FName, Mode);                { Open the file }
+   If (Handle=0) Then Begin                           { Open failed }
+     Error(stInitError, DosStreamError);              { Call error }
+     Status := stInitError;                           { Set fail status }
+     Handle := -1;                                    { Set invalid handle }
+   End;
+END;
+
+{**TDosStream***************************************************************}
+{  Done -> Platforms DOS/DPMI/WIN/OS2 - Checked 16May96 LdB                 }
+{***************************************************************************}
+DESTRUCTOR TDosStream.Done;
+BEGIN
+   If (Handle <> -1) Then DosClose(Handle);           { Close the file }
+   Inherited Done;                                    { Call ancestor }
+END;
+
+{**TDosStream***************************************************************}
+{  GetPos -> Platforms DOS/DPMI/WIN/OS2 - Checked 16May96 LdB               }
+{***************************************************************************}
+FUNCTION TDosStream.GetPos: LongInt;
+VAR NewPosition: LongInt;
+BEGIN
+   If (Status=stOk) Then Begin                        { Check status okay }
+     If (Handle = -1) Then DosStreamError := 103      { File not open }
+       Else DosStreamError := DosSetFilePtr(Handle,
+        0, 1, NewPosition);                           { Get file position }
+     If (DosStreamError<>0) Then Begin                { Check for error }
+        Error(stError, DosStreamError);               { Identify error }
+        NewPosition := -1;                            { Invalidate position }
+     End;
+     GetPos := NewPosition;                           { Return file position }
+   End Else GetPos := -1;                             { Stream in error }
+END;
+
+{**TDosStream***************************************************************}
+{  GetSize -> Platforms DOS/DPMI/WIN/OS2 - Checked 16May96 LdB              }
+{***************************************************************************}
+FUNCTION TDosStream.GetSize: LongInt;
+VAR CurrentPos, FileEndPos: LongInt;
+BEGIN
+   If (Status=stOk) Then Begin                        { Check status okay }
+     If (Handle = -1) Then DosStreamError := 103      { File not open }
+       Else DosStreamError := DosSetFilePtr(Handle,
+        0, 1, CurrentPos);                            { Current position }
+     If (DosStreamError=0) Then Begin                 { Check no errors }
+        DosStreamError := DosSetFilePtr(Handle, 0, 2,
+          FileEndPos);                                { Locate end of file }
+        If (DosStreamError=0) Then
+          DosSetFilePtr(Handle, 0, 1, CurrentPos);    { Reset position }
+     End;
+     If (DosStreamError<>0) Then Begin                { Check for error }
+        Error(stError, DosStreamError);               { Identify error }
+        FileEndPos := -1;                             { Invalidate size }
+     End;
+     GetSize := FileEndPos;                           { Return file size }
+   End Else GetSize := -1;                            { Stream in error }
+END;
+
+{**TDosStream***************************************************************}
+{  Close -> Platforms DOS/DPMI/WIN/OS2 - Checked 16May96 LdB                }
+{***************************************************************************}
+PROCEDURE TDosStream.Close;
+BEGIN
+   If (Handle <> -1) Then DosClose(Handle);           { Close the file }
+   Handle := -1;                                      { Handle now invalid }
+END;
+
+{**TDosStream***************************************************************}
+{  Seek -> Platforms DOS/DPMI/WIN/OS2 - Checked 16May96 LdB                 }
+{***************************************************************************}
+PROCEDURE TDosStream.Seek (Pos: LongInt);
+VAR NewPosition: LongInt;
+BEGIN
+   If (Status=stOk) Then Begin                        { Check status okay }
+     If (Pos < 0) Then Pos := 0;                      { Negatives removed }
+     If (Handle = -1) Then DosStreamError := 103      { File not open }
+       Else DosStreamError := DosSetFilePtr(Handle,
+         Pos, 0, NewPosition);                        { Set file position }
+     If ((DosStreamError<>0) OR (NewPosition<>Pos))   { We have an error }
+     Then Begin
+       If (DosStreamError<>0) Then                    { Error was detected }
+         Error(stError, DosStreamError)               { Specific seek error }
+         Else Error(stSeekError, 0);                  { General seek error }
+     End;
+   End;
+END;
+
+{**TDosStream***************************************************************}
+{  Open -> Platforms DOS/DPMI/WIN/OS2 - Checked 16May96 LdB                 }
+{***************************************************************************}
+PROCEDURE TDosStream.Open (OpenMode: Word);
+BEGIN
+   If (Handle = -1) Then Begin                        { File not open }
+     Handle := DosFileOpen(FName, OpenMode);          { Open the file }
+     If (Handle=0) Then Begin                         { File open failed }
+       Error(stOpenError, DosStreamError);            { Call error }
+       Handle := -1;                                  { Set invalid handle }
+     End;
+   End;
+END;
+
+{**TDosStream***************************************************************}
+{  Read -> Platforms DOS/DPMI/WIN/OS2 - Checked 16May96 LdB                 }
+{***************************************************************************}
+PROCEDURE TDosStream.Read (Var Buf; Count: Sw_Word);
+VAR BytesMoved: Sw_Word;
+BEGIN
+   If (Status=stOk) Then Begin                        { Check status }
+     If (Handle = -1) Then BytesMoved := 0 Else       { File not open }
+       DosStreamError := DosRead(Handle, Buf, Count,
+         BytesMoved);                                 { Read from file }
+     If ((DosStreamError<>0) OR (BytesMoved<>Count))  { We have an error }
+     Then Begin
+       If (DosStreamError<>0) Then                    { Error was detected }
+         Error(stError, DosStreamError)               { Specific read error }
+         Else Error(stReadError, 0);                  { General read error }
+     End;
+   End Else FillChar(Buf, Count, #0);                 { Error clear buffer }
+END;
+
+{**TDosStream***************************************************************}
+{  Write -> Platforms DOS/DPMI/WIN/OS2 - Checked 16May96 LdB                }
+{***************************************************************************}
+PROCEDURE TDosStream.Write (Var Buf; Count: Sw_Word);
+VAR BytesMoved: Sw_Word;
+BEGIN
+   If (Status=stOk) Then Begin
+     If (Handle=-1) Then BytesMoved := 0 Else         { File not open }
+       DosStreamError := DosWrite(Handle, Buf, Count,
+         BytesMoved);                                 { Write to file }
+     If ((DosStreamError<>0) OR (BytesMoved<>Count))  { We have an error }
+     Then Begin
+       If (DosStreamError<>0) Then                    { Error was detected }
+         Error(stError, DosStreamError)               { Specific write error }
+         Else Error(stWriteError, 0);                 { General write error }
+     End;
+   End;
+END;
+
+{ÞßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßÝ}
+{Þ                      TCollection OBJECT METHODS                         Ý}
+{ÞÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÝ}
+
+CONSTRUCTOR TCollection.Init (ALimit, ADelta: Sw_Integer);
+BEGIN
+   Inherited Init;                                    { Call ancestor }
+   Delta := ADelta;                                   { Set increment }
+   SetLimit(ALimit);                                  { Set limit }
+END;
+
+CONSTRUCTOR TCollection.Load (Var S: TStream);
+VAR C, I: Sw_Integer;
+BEGIN
+   S.Read(Count, SizeOf(Count));                      { Read count }
+   S.Read(Limit, SizeOf(Limit));                      { Read limit }
+   S.Read(Delta, SizeOf(Delta));                      { Read delta }
+   Items := Nil;                                      { Clear item pointer }
+   C := Count;                                        { Hold count }
+   I := Limit;                                        { Hold limit }
+   Count := 0;                                        { Clear count }
+   Limit := 0;                                        { Clear limit }
+   SetLimit(I);                                       { Set requested limit }
+   Count := C;                                        { Set count }
+   For I := 0 To C-1 Do AtPut(I, GetItem(S));         { Get each item }
+END;
+
+DESTRUCTOR TCollection.Done;
+BEGIN
+   FreeAll;                                           { Free all items }
+   SetLimit(0);                                       { Release all memory }
+END;
+
+FUNCTION TCollection.At (Index: Sw_Integer): Pointer;
+BEGIN
+   If (Index < 0) OR (Index >= Count) Then Begin      { Invalid index }
+     Error(coIndexError, Index);                      { Call error }
+     At := Nil;                                       { Return nil }
+   End Else At := Items^[Index];                      { Return item }
+END;
+
+{ ******************************* REMARK ****************************** }
+{  Bug fix of TCollection.IndexOf from the original code which was:     }
+{  For I := 0 To Count-1 Do  <- What happens if count=0!!!!             }
+{ ****************************** END REMARK *** Leon de Boer, 10May96 * }
+FUNCTION TCollection.IndexOf (Item: Pointer): Sw_Integer;
+VAR I: Sw_Integer;
+BEGIN
+   If (Count>0) Then Begin                            { Count is positive }
+     For I := 0 To Count-1 Do                         { For each item }
+       If (Items^[I]=Item) Then Begin                 { Look for match }
+         IndexOf := I;                                { Return index }
+         Exit;                                        { Now exit }
+       End;
+   End;
+   IndexOf := -1;                                     { Return index }
+END;
+
+FUNCTION TCollection.GetItem (Var S: TStream): Pointer;
+BEGIN
+   GetItem := S.Get;                                  { Item off stream }
+END;
+
+FUNCTION TCollection.LastThat (Test: Pointer): Pointer;
+VAR I: LongInt; P: FuncPtr; {$IFDEF NotFPKPascal} Hold_EBP: Sw_Word; {$ENDIF}
+BEGIN
+   {$IFDEF FPKPascal}                                 { FPK pascal compiler }
+   ASM
+     MOVL (%EBP), %EAX;                               { Load EBP }
+     MOVL %EAX, U_OBJECTS_HOLDEBP;                    { Store to global }
+   END;
+   {$ELSE}                                            { Other compilers }
+   ASM
+     {$IFNDEF CODE_32_BIT}                            { 16 BIT CODE }
+       MOV AX, [BP];                                  { Load AX from BP }
+       {$IFDEF Windows}
+       AND AL, 0FEH;                                  { Windows make even }
+       {$ENDIF}
+       MOV Hold_EBP, AX;                              { Hold value }
+     {$ELSE}                                          { 32 BIT CODE }
+       MOV EAX, [EBP];                                { Load EAX from EBP }
+       MOV Hold_EBP, EAX;                             { Hold value }
+     {$ENDIF}
+   END;
+   {$ENDIF}
+   P := FuncPtr(Test);                                { Set function ptr }
+   For I := Count DownTo 1 Do Begin                   { Down from last item }
+     {$IFDEF FPKPascal}
+       {$$$$$ crahes the compiler
+       If P(Items^[I-1], HoldEBP) Then
+       } Begin          { Test each item }
+     {$ELSE}
+       {$IFDEF VirtualPascal}
+         If P(Items^[I-1]) Then Begin                 { Test each item }
+       {$ELSE}
+         If P(Items^[I-1], Hold_EBP) Then Begin       { Test each item }
+       {$ENDIF}
+     {$ENDIF}
+       LastThat := Items^[I-1];                       { Return item }
+       Exit;                                          { Now exit }
+     End;
+   End;
+   LastThat := Nil;                                   { None passed test }
+END;
+
+FUNCTION TCollection.FirstThat (Test: Pointer): Pointer;
+VAR I: LongInt; P: FuncPtr; {$IFDEF NotFPKPascal} Hold_EBP: Sw_Word; {$ENDIF}
+BEGIN
+   {$IFDEF FPKPascal}                                 { FPK pascal compiler }
+   ASM
+     MOVL (%EBP), %EAX;                               { Load EBP }
+     MOVL %EAX, U_OBJECTS_HOLDEBP;                    { Store to global }
+   END;
+   {$ELSE}                                            { Other compilers }
+   ASM
+     {$IFNDEF CODE_32_BIT}                            { 16 BIT CODE }
+       MOV AX, [BP];                                  { Load AX from BP }
+       {$IFDEF Windows}
+       AND AL, 0FEH;                                  { Windows make even }
+       {$ENDIF}
+       MOV Hold_EBP, AX;                              { Hold value }
+     {$ELSE}                                          { 32 BIT CODE }
+       MOV EAX, [EBP];                                { Load EAX from EBP }
+       MOV Hold_EBP, EAX;                             { Hold value }
+     {$ENDIF}
+   END;
+   {$ENDIF}
+   P := FuncPtr(Test);                                { Set function ptr }
+   For I := 1 To Count Do Begin                       { Up from first item }
+     {$IFDEF FPKPascal}
+       {$$$$$$ crashes the compiler
+       If P(Items^[I-1], HoldEBP) Then }
+       Begin          { Test each item }
+     {$ELSE}
+       {$IFDEF VirtualPascal}
+         If P(Items^[I-1]) Then Begin                 { Test each item }
+       {$ELSE}
+         If P(Items^[I-1], Hold_EBP) Then Begin       { Test each item }
+       {$ENDIF}
+     {$ENDIF}
+       FirstThat := Items^[I-1];                      { Return item }
+       Exit;                                          { Now exit }
+     End;
+   End;
+   FirstThat := Nil;                                  { None passed test }
+END;
+
+{ ******************************* REMARK ****************************** }
+{  Bug fix of TCollection.Pack from the original code which was:        }
+{  While (I<Count) Do  -  Yes but who forget to initialize variable I   }
+{  If count is equal to zero this was going to crash big time and you   }
+{  must re-adjust the count value - Basically it was stuffed!!!         }
+{ ****************************** END REMARK *** Leon de Boer, 10May96 * }
+PROCEDURE TCollection.Pack;
+VAR I, J: Sw_Integer;
+BEGIN
+   If (Count>0) Then Begin                            { Count is positive }
+     I := 0;                                          { Initialize dest }
+     For J := 1 To Count Do Begin                     { For each item }
+       If (Items^[J]<>Nil) Then Begin                 { Entry is non nil }
+         Items^[I] := Items^[J];                      { Transfer item }
+         Inc(I);                                      { Advance dest }
+       End;
+     End;
+     Count := I;                                      { Adjust count }
+   End;
+END;
+
+PROCEDURE TCollection.FreeAll;
+VAR I: Sw_Integer;
+BEGIN
+   For I := 0 To Count-1 Do FreeItem(At(I));          { Release each item }
+   Count := 0;                                        { Clear item count }
+END;
+
+PROCEDURE TCollection.DeleteAll;
+BEGIN
+   Count := 0;                                        { Clear item count }
+END;
+
+PROCEDURE TCollection.Free (Item: Pointer);
+BEGIN
+   Delete(Item);                                      { Delete from list }
+   FreeItem(Item);                                    { Free the item }
+END;
+
+PROCEDURE TCollection.Insert (Item: Pointer);
+BEGIN
+   AtInsert(Count, Item);                             { Insert item }
+END;
+
+PROCEDURE TCollection.Delete (Item: Pointer);
+BEGIN
+   AtDelete(IndexOf(Item));                           { Delete from list }
+END;
+
+PROCEDURE TCollection.AtFree (Index: Sw_Integer);
+VAR Item: Pointer;
+BEGIN
+   Item := At(Index);                                 { Retreive item ptr }
+   AtDelete(Index);                                   { Delete item }
+   FreeItem(Item);                                    { Free the item }
+END;
+
+PROCEDURE TCollection.FreeItem (Item: Pointer);
+VAR P: PObject;
+BEGIN
+   P := PObject(Item);                                { Convert pointer }
+   If (P<>Nil) Then Dispose(P, Done);                 { Dispose of object }
+END;
+
+PROCEDURE TCollection.AtDelete (Index: Sw_Integer);
+BEGIN
+   If (Index >= 0) AND (Index < Count) Then Begin     { Valid index }
+     Dec(Count);                                      { One less item }
+     If (Count>Index) Then Move(Items^[Index+1],
+      Items^[Index], (Count-Index)*Sizeof(Pointer));  { Shuffle items down }
+   End Else Error(coIndexError, Index);               { Index error }
+END;
+
+PROCEDURE TCollection.ForEach (Action: Pointer);
+VAR I: LongInt; P: ProcPtr; {$IFDEF NotFPKPascal} Hold_EBP: Sw_Word; {$ENDIF}
+BEGIN
+   {$IFDEF FPKPascal}                                 { FPK pascal compiler }
+   ASM
+     MOVL (%EBP), %EAX;                               { Load EBP }
+     MOVL %EAX, U_OBJECTS_HOLDEBP;                    { Store to global }
+   END;
+   {$ELSE}                                            { Other compilers }
+   ASM
+     {$IFNDEF CODE_32_BIT}                            { 16 BIT CODE }
+       MOV AX, [BP];
+       {$IFDEF WINDOWS}
+       AND AL, 0FEH;                                  { Windows make even }
+       {$ENDIF}
+       MOV Hold_EBP, AX;                              { Hold value }
+     {$ELSE}                                          { 32 BIT CODE }
+       MOV EAX, [EBP];                                { Load EAX from EBP }
+       MOV Hold_EBP, EAX;                             { Hold value }
+     {$ENDIF}
+   END;
+   {$ENDIF}
+   P := ProcPtr(Action);                              { Set procedure ptr }
+   For I := 1 To Count Do                             { Up from first item }
+     {$IFDEF FPKPascal}
+       P(Items^[I-1], HoldEBP);                       { Call with each item }
+     {$ELSE}
+       {$IFDEF VirtualPascal}
+         P(Items^[I-1]);                              { Call with each item }
+       {$ELSE}
+         P(Items^[I-1], Hold_EBP);                    { Call with each item }
+       {$ENDIF}
+    {$ENDIF}
+END;
+
+{ ******************************* REMARK ****************************** }
+{  Bug fix of TCollection.SetLimit from the original code which was:    }
+{  getmem(p,alimit*sizeof(pointer));  <- This can fail OR ALimit=0      }
+{  move(items^,p^,count*sizeof(Pointer)); <- This would now crash!      }
+{ ****************************** END REMARK *** Leon de Boer, 10May96 * }
+PROCEDURE TCollection.SetLimit (ALimit: Sw_Integer);
+VAR AItems: PItemList;
+BEGIN
+   If (ALimit < Count) Then ALimit := Count;          { Stop underflow }
+   If (ALimit > MaxCollectionSize) Then
+     ALimit := MaxCollectionSize;                     { Stop overflow }
+   If (ALimit <> Limit) Then Begin                    { Limits differ }
+     If (ALimit = 0) Then AItems := Nil Else          { Alimit=0 nil entry }
+       GetMem(AItems, ALimit * SizeOf(Pointer));      { Allocate memory }
+     If (AItems<>Nil) OR (ALimit=0) Then Begin        { Check success }
+       If (AItems <>Nil) AND (Items <> Nil) Then      { Check both valid }
+         Move(Items^, AItems^, Count*SizeOf(Pointer));{ Move existing items }
+       If (Limit <> 0) AND (Items <> Nil) Then        { Check old allocation }
+         FreeMem(Items, Limit * SizeOf(Pointer));     { Release memory }
+       Items := AItems;                               { Update items }
+       Limit := ALimit;                               { Set limits }
+     End;
+   End;
+END;
+
+PROCEDURE TCollection.Error (Code, Info: Integer);
+BEGIN
+   RunError(212 - Code);                              { Run error }
+END;
+
+PROCEDURE TCollection.AtPut (Index: Sw_Integer; Item: Pointer);
+BEGIN
+   If (Index >= 0) AND (Index < Count) Then           { Index valid }
+     Items^[Index] := Item                            { Put item in index }
+     Else Error(coIndexError, Index);                 { Index error }
+END;
+
+{ ******************************* REMARK ****************************** }
+{  Bug fix of TCollection.AtInsert from the original code which was:    }
+{  original remark: copy old items, count is tested by move             }
+{  Move(Items^[Index], Items^[Index+1],(Count-Index)*Sizeof(Pointer));  }
+{  This does not work you must work from the back down!!!!              }
+{ ****************************** END REMARK *** Leon de Boer, 10May96 * }
+PROCEDURE TCollection.AtInsert (Index: Sw_Integer; Item: Pointer);
+VAR I: Sw_Integer;
+BEGIN
+   If (Index >= 0) AND (Index <= Count) Then Begin    { Valid index }
+     If (Count=Limit) Then  SetLimit(Limit+Delta);    { Expand size if able }
+     If (Limit>Count) Then Begin
+       If (Index < Count) Then Begin                  { Not last item }
+         For I := Count DownTo Index Do               { Start from back }
+           Items^[I] := Items^[I-1];                  { Move each item }
+       End;
+       Items^[Index] := Item;                         { Put item in list }
+       Inc(Count);                                    { Inc count }
+     End Else Error(coOverflow, Index);               { Expand failed }
+   End Else Error(coIndexError, Index);               { Index error }
+END;
+
+PROCEDURE TCollection.Store (Var S: TStream);
+
+   PROCEDURE DoPutItem (P: Pointer); FAR;
+   BEGIN
+     PutItem(S, P);                                   { Put item on stream }
+   END;
+
+BEGIN
+   S.Write(Count, SizeOf(Count));                     { Write count }
+   S.Write(Limit, SizeOf(Limit));                     { Write limit }
+   S.Write(Delta, SizeOf(Delta));                     { Write delta }
+   ForEach(@DoPutItem);                               { Each item to stream }
+END;
+
+PROCEDURE TCollection.PutItem (Var S: TStream; Item: Pointer);
+BEGIN
+   S.Put(Item);                                       { Put item on stream }
+END;
+
+{ÞßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßÝ}
+{Þ                      TSortedCollection OBJECT METHODS                   Ý}
+{ÞÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÝ}
+
+CONSTRUCTOR TSortedCollection.Init (ALimit, ADelta: Sw_Integer);
+BEGIN
+   Inherited Init(ALimit, ADelta);                    { Call ancestor }
+   Duplicates := False;                               { Clear flag }
+END;
+
+CONSTRUCTOR TSortedCollection.Load (Var S: TStream);
+BEGIN
+   Inherited Load(S);                                 { Call ancestor }
+   S.Read(Duplicates, SizeOf(Duplicates));            { Read duplicate flag }
+END;
+
+FUNCTION TSortedCollection.KeyOf (Item: Pointer): Pointer;
+BEGIN
+   KeyOf := Item;                                     { Return item }
+END;
+
+FUNCTION TSortedCollection.IndexOf (Item: Pointer): Sw_Integer;
+VAR I: Sw_Integer;
+BEGIN
+   IndexOf := -1;                                     { Preset result }
+   If Search(KeyOf(Item), I) Then Begin               { Search for item }
+     If Duplicates Then                               { Duplicates allowed }
+       While (I < Count) AND (Item <> Items^[I]) Do
+         Inc(I);                                      { Count duplicates }
+     If (I < Count) Then IndexOf := I;                { Return result }
+   End;
+END;
+
+FUNCTION TSortedCollection.Compare (Key1, Key2: Pointer): Sw_Integer;
+BEGIN
+   Abstract;                                          { Abstract method }
+END;
+
+FUNCTION TSortedCollection.Search (Key: Pointer; Var Index: Sw_Integer): Boolean;
+VAR L, H, I, C: Sw_Integer;
+BEGIN
+   Search := False;                                   { Preset failure }
+   L := 0;                                            { Start count }
+   H := Count - 1;                                    { End count }
+   While (L <= H) Do Begin
+     I := (L + H) SHR 1;                              { Mid point }
+     C := Compare(KeyOf(Items^[I]), Key);             { Compare with key }
+     If (C < 0) Then L := I + 1 Else Begin            { Item to left }
+       H := I - 1;                                    { Item to right }
+       If C = 0 Then Begin                            { Item match found }
+         Search := True;                              { Result true }
+         If NOT Duplicates Then L := I;               { Force kick out }
+       End;
+     End;
+   End;
+   Index := L;                                        { Return result }
+END;
+
+PROCEDURE TSortedCollection.Insert (Item: Pointer);
+VAR I: Sw_Integer;
+BEGIN
+   If NOT Search(KeyOf(Item), I) OR Duplicates Then   { Item valid }
+     AtInsert(I, Item);                               { Insert the item }
+END;
+
+PROCEDURE TSortedCollection.Store (Var S: TStream);
+BEGIN
+   TCollection.Store(S);                              { Call ancestor }
+   S.Write(Duplicates, SizeOf(Duplicates));           { Write duplicate flag }
+END;
+
+{ÞßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßÝ}
+{Þ                    TStringCollection OBJECT METHODS                     Ý}
+{ÞÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÝ}
+
+FUNCTION TStringCollection.GetItem (Var S: TStream): Pointer;
+BEGIN
+   GetItem := S.ReadStr;                              { Get new item }
+END;
+
+FUNCTION TStringCollection.Compare (Key1, Key2: Pointer): Sw_Integer;
+VAR I, J: Integer; P1, P2: PString;
+BEGIN
+   P1 := PString(Key1);                               { String 1 pointer }
+   P2 := PString(Key2);                               { String 2 pointer }
+   If (Length(P1^)<Length(P2^)) Then J := Length(P1^)
+     Else J := Length(P2^);                           { Shortest length }
+   I := 1;                                            { First character }
+   While (I<J) AND (P1^[I]=P2^[I]) Do Inc(I);         { Scan till fail }
+   If (P1^[I]=P2^[I]) Then Compare := 0 Else          { Strings matched }
+     If (P1^[I]<P2^[I]) Then Compare := -1 Else       { String1 < String2 }
+        Compare := 1;                                 { String1 > String2 }
+END;
+
+PROCEDURE TStringCollection.FreeItem (Item: Pointer);
+BEGIN
+   DisposeStr(Item);                                  { Dispose item }
+END;
+
+PROCEDURE TStringCollection.PutItem (Var S: TStream; Item: Pointer);
+BEGIN
+   S.WriteStr(Item);                                  { Write string }
+END;
+
+{ÞßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßÝ}
+{Þ                  TUnSortedStrCollection OBJECT METHODS                  Ý}
+{ÞÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÝ}
+PROCEDURE TUnSortedStrCollection.Insert (Item: Pointer);
+BEGIN
+   AtInsert(Count, Item);                             { NO sorting insert }
+END;
+
+
+
+
+FUNCTION TStream.Get: PObject;
+BEGIN
+END;
+
+PROCEDURE TStream.Put (P: PObject);
+BEGIN
+END;
+
+{***************************************************************************}
+{                            INTERFACE ROUTINES                             }
+{***************************************************************************}
+
+{ÞßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßÝ}
+{Þ                   DYNAMIC STRING INTERFACE ROUTINES                     Ý}
+{ÞÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÝ}
+FUNCTION NewStr (Const S: String): PString;
+VAR P: PString;
+BEGIN
+   If (S = '') Then P := Nil Else Begin               { Return nil }
+     GetMem(P, Length(S) + 1);                        { Allocate memory }
+     If (P<>Nil) Then P^ := S;                        { Hold string }
+   End;
+   NewStr := P;                                       { Return result }
+END;
+
+PROCEDURE DisposeStr (P: PString);
+BEGIN
+   If (P <> Nil) Then FreeMem(P, Length(P^) + 1);     { Release memory }
+END;
+
+{ÞßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßÝ}
+{Þ                       STREAM INTERFACE ROUTINES                         Ý}
+{ÞÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÝ}
+
+PROCEDURE Abstract;
+BEGIN
+   RunError(211);                                     { Abstract error }
+END;
+
+PROCEDURE RegisterError;
+BEGIN
+   RunError(212);                                     { Register error }
+END;
+
+{ÞßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßÝ}
+{Þ                     NEW FREE VISION STREAM ROUTINES                     Ý}
+{ÞÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÝ}
+
+FUNCTION CreateStream (Strategy: Word; ReqSize: LongInt): PStream;
+VAR Stream: PStream;
+BEGIN
+   Stream := Nil;                                     { Preset failure }
+   While (Strategy <> 0) AND (Stream = Nil) Do Begin
+     If (Strategy AND sa_XMSFirst <> 0) Then Begin    { ** XMS STREAM ** }
+     End Else
+     If (Strategy AND sa_EMSFirst <> 0) Then Begin    { ** EMS STREAM ** }
+     End Else
+     If (Strategy AND sa_RamFirst <> 0) Then Begin    { ** RAM STREAM ** }
+     End Else
+     If (Strategy AND sa_DiskFirst <> 0) Then Begin   { ** DISK STREAM ** }
+     End;
+     If (Stream<>Nil) AND (Stream^.Status <> stOk)    { Stream in error }
+     Then Begin
+       Dispose(Stream, Done);                         { Dispose stream }
+       Stream := Nil;                                 { Clear pointer }
+     End;
+     Strategy := Strategy SHL 4;                      { Next strategy mask }
+   End;
+   CreateStream := Stream;                            { Return stream result }
+END;
+
+{ÞßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßÝ}
+{Þ                    NEW FREE VISION DOS FILE ROUTINES                    Ý}
+{ÞÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÝ}
+
+{***************************************************************************}
+{  DosFileOpen -> Platforms DOS/DPMI/WIN/OS2 - Checked 16May96 LdB          }
+{***************************************************************************}
+FUNCTION DosFileOpen (Var FileName: AsciiZ; Mode: Word): Word;
+{$IFDEF NotOS2}                                       { DOS/DPMI/WINDOWS }
+   {$IFDEF FPKPascal}                                 { FPK Pascal compiler }
+     {$IFDEF GO32V2}
+var regs : trealregs;
+BEGIN
+         syscopytodos(longint(@FileName),256);
+         regs.realedx:=tb mod 16;
+         regs.realds:=tb div 16;
+         regs.realeax := Mode;
+         regs.realecx:=0;
+         sysrealintr($21,regs);
+         if (regs.realflags and 1) <> 0 then
+           begin
+           InOutRes:=lo(regs.realeax);
+           DosFileOpen:=-1;
+           exit;
+           end else
+           DosFileOpen:=regs.realeax;
+END;
+    {$ELSE not GO32V2}
+BEGIN
+   ASM
+     XOR %AX, %AX;                                    { Clear error }
+     MOVW %AX, U_OBJECTS_DOSSTREAMERROR;
+     MOVL Filename, %EDX;                             { Filename to open }
+     XOR %CX, %CX;
+     MOVW Mode, %AX;                               { Mode to open file }
+     PUSHL %EBP;
+	 INT $0x21;                                         { Open/create the file }
+     POPL %EBP;
+     JNC EXIT1;
+     MOV %AX, U_OBJECTS_DOSSTREAMERROR;               { Hold error }
+     XOR %AX, %AX;                                    { Open failed }
+   EXIT1:
+     MOV %AX, U_OBJECTS_TRANSFERHANDLE;               { Hold opened handle }
+   END;
+   DosFileOpen := TransferHandle;                     { Return handle }
+END;
+     {$ENDIF GO32V2}
+   {$ELSE}                                            { Other compilers }
+ASSEMBLER;
+   ASM
+     XOR AX, AX;                                      { Dos error cleared }
+     MOV DosStreamError, AX;
+	 MOV AX, Mode;                                    { Mode to open file }
+     PUSH DS;
+     LDS DX, FileName;                                { Filename to open }
+	 XOR CX, CX;
+     INT $21;                                         { Open/create file }
+     POP DS;
+     JNC @@Exit1;                                     { Check for error }
+     MOV DosStreamError, AX;
+     XOR AX, AX;                                      { Open fail return 0 }
+   @@Exit1:
+   END;
+   {$ENDIF}
+{$ELSE}                                               { OS2 CODE }
+{$IFNDEF FPK}
+VAR Attr, OpenFlags, OpenMode: Word; Success, Handle, ActionTaken: Sw_Word;
+BEGIN
+   Case Mode Of
+     stCreate: Begin                                  { Create file }
+         Attr := $20;                                 { Archive file }
+         OpenFlags := 18;                             { Open flags }
+         OpenMode := FmInOut;                         { Input/output file }
+       End;
+     stOpenRead: Begin                                { Open file for read }
+         Attr := $0;                                  { Any attributes }
+         OpenFlags := 1;                              { Open flags }
+         OpenMode := FmInput;                         { Input file }
+       End;
+     stOpenWrite: Begin                               { Open file for write }
+         Attr := $0;                                  { Any attributes }
+		 OpenFlags := 1;                              { Open flags }
+         OpenMode := FmOutput;                        { Output file }
+       End;
+     stOpen: Begin                                    { Open file read/write }
+         Attr := $0;                                  { Any attributes }
+         OpenFlags := 1;                              { Open flags }
+         OpenMode := FmInOut;                         { Input/output file }
+       End;
+   End;
+   {$IFDEF Speed}                                     { Speed pascal differs }
+   DosStreamError := DosOpen(CString(FileName), Handle,
+   {$ELSE}                                            { Other OS2 compilers }
+   DosStreamError := DosOpen(@FileName[0], Handle,
+   {$ENDIF}
+	 ActionTaken, 0, Attr, OpenFlags, OpenMode, Nil); { Open the file }
+   If (DosStreamError=0) Then DosFileOpen := Handle   { Successful open }
+	 Else DosFileOpen := 0;                           { Fail so return zero }
+END;
+{$ELSE FPK}
+BEGIN
+   ASM
+	 XOR %AX, %AX;                                    { Clear error }
+	 MOVW %AX, U_OBJECTS_DOSSTREAMERROR;
+	 MOVL Filename, %EDX;                             { Filename to open }
+	 XOR %CX, %CX;
+	 MOVW Mode, %AX;                                  { Mode to open file }
+	 CALL ___syscall;                                 { Open/create the file }
+	 JNC EXIT1;
+	 MOV %AX, U_OBJECTS_DOSSTREAMERROR;               { Hold error }
+	 XOR %AX, %AX;                                    { Open failed }
+   EXIT1:
+	 MOV %AX, U_OBJECTS_TRANSFERHANDLE;               { Hold opened handle }
+   END;
+   DosFileOpen := TransferHandle;                     { Return handle }
+END;
+{$ENDIF FPK}
+{$ENDIF}
+
+{***************************************************************************}
+{  DosRead -> Platforms DOS/DPMI/WIN - Checked 16May96 LdB                  }
+{***************************************************************************}
+FUNCTION DosRead (Handle: Word; Var BufferArea; BufferLength: Sw_Word;
+Var BytesMoved: Sw_Word): Word;
+{$IFDEF FPKPascal}                                    { FPK pascal compiler }
+{$IFDEF GO32V2}
+BEGIN
+BytesMoved:=system.dosread(Handle,longint(@BufferArea),BufferLength);
+DosRead:=InOutRes;
+End;
+{$ELSE not GO32V2}
+{$IFNDEF OS2}
+BEGIN
+   ASM
+	 MOVL BufferArea, %EDX;                             { Buffer for data }
+	 MOVL BufferLength, %CX;                              { Bytes to read }
+	 MOVB $0x3F, %AH;
+	 MOVW Handle, %BX;                              { Load file handle }
+	 PUSHL %EBP;
+	 INT $0x21;                                         { Read from file }
+	 POPL %EBP;
+	 JC EXIT2;                                        { Check for error }
+	 MOVL BytesMoved, %EDI;
+	 MOVZWL %AX, %EAX;
+	 MOVL %EAX, (%EDI);                               { Update bytes moved }
+	 XOR %EAX, %EAX;                                  { Clear register }
+   EXIT2:
+	 MOV %AX, U_OBJECTS_DOSSTREAMERROR;               { DOS error returned }
+   END;
+   DosRead := DosStreamError;                         { Return any error }
+END;
+{$ELSE OS2}
+BEGIN
+   ASM
+	 MOVL BufferArea, %EDX;                             { Buffer for data }
+	 MOVL BufferLength, %CX;                              { Bytes to read }
+	 MOVB $0x3F, %AH;
+	 MOVW Handle, %BX;                                { Load file handle }
+	 CALL ___syscall;                                 { Read from file }
+	 JC EXIT2;                                        { Check for error }
+	 MOVL BytesMoved, %EDI;
+	 MOVZWL %AX, %EAX;
+	 MOVL %EAX, (%EDI);                               { Update bytes moved }
+	 XOR %EAX, %EAX;                                  { Clear register }
+   EXIT2:
+	 MOV %AX, U_OBJECTS_DOSSTREAMERROR;               { DOS error returned }
+   END;
+   DosRead := DosStreamError;                         { Return any error }
+END;
+{$ENDIF OS2}
+{$EndIf GO32V2}
+{$ELSE}                                               { Other compilers }
+ASSEMBLER;
+   ASM
+	 PUSH DS;
+	 LDS DX, BufferArea;                              { Data dest buffer }
+	 MOV CX, BufferLength;
+	 MOV BX, Handle;                                  { Load file handle }
+	 MOV AH, $0x3F;
+	 INT $0x21;                                         { Read from file }
+	 POP DS;
+	 JC @@Exit2;                                      { Check for error }
+	 LES DI, BytesMoved;
+	 MOV ES:[DI], AX;                                 { Update bytes moved }
+	 XOR AX, AX;
+   @@Exit2:
+	 MOV DosStreamError, AX;                          { DOS error returned }
+   END;
+{$ENDIF}
+
+{***************************************************************************}
+{  DosWrite -> Platforms DOS/DPMI/WIN - Checked 16May96 LdB                 }
+{***************************************************************************}
+FUNCTION DosWrite (Handle: Word; Var BufferArea; BufferLength: Sw_Word;
+Var BytesMoved: Sw_Word): Word;
+{$IFDEF FPKPascal}                                    { FPK pascal compiler }
+{$IFDEF GO32V2}
+BEGIN
+system.doswrite(Handle,longint(@BufferArea),BufferLength);
+BytesMoved:=BufferLength;
+DosWrite:=InOutRes;
+End;
+{$ELSE not GO32V2}
+BEGIN
+   ASM
+	 MOVL BufferArea, %EDX;                             { Buffer with data }
+	 MOVL BufferLength, %CX;                              { Bytes to write }
+	 MOVB $0x40, %AH;
+	 MOVW Handle, %BX;                              { Load file handle }
+	 PUSHL %EBP;
+	 INT $0x21;                                         { Write to file }
+	 POPL %EBP;
+	 JC EXIT3;                                        { Check for error }
+	 MOVL BytesMoved, %EDI;
+	 MOVZWL %AX, %EAX;
+	 MOVL %EAX, (%EDI);                               { Update bytes moved }
+	 XOR %EAX, %EAX;
+   EXIT3:
+	 MOV %AX, U_OBJECTS_DOSSTREAMERROR;               { DOS error returned }
+   END;
+   DosWrite := DosStreamError;                        { Return any error }
+END;
+{$ENDIF GO32V2}
+{$ELSE}                                               { Other compilers }
+ASSEMBLER;
+   ASM
+	 PUSH DS;
+	 LDS DX, BufferArea;                              { Data source buffer }
+	 MOV CX, BufferLength;
+	 MOV BX, Handle;                                  { Load file handle }
+	 MOV AH, $40;
+	 INT $21;                                         { Write to file }
+	 POP DS;
+	 JC @@Exit3;                                      { Check for error }
+	 LES DI, BytesMoved;
+     MOV ES:[DI], AX;                                 { Update bytes moved }
+     XOR AX, AX;
+   @@Exit3:
+     MOV DosStreamError, AX;                          { DOS error returned }
+   END;
+{$ENDIF}
+
+{***************************************************************************}
+{  DosSetFilePtr -> Platforms DOS/DPMI/WIN - Checked 16May96 LdB            }
+{***************************************************************************}
+FUNCTION DosSetFilePtr (Handle: Word; Pos: LongInt; MoveType: Word;
+VAR NewPos: LongInt): Word;
+{$IFDEF FPKPascal}                                    { FPK pascal compiler }
+{$IFNDEF OS2}
+BEGIN
+   ASM
+	 MOVW MoveType, %AX;                              { Load move type }
+	 MOVB $0x42, %AH;
+	 MOVW POS, %DX;                              { Load file position }
+	 MOVL POS, %ECX;
+	 SHRL $16,%ECX;
+	 MOVW Handle, %BX;                              { Load file handle }
+	 PUSHL %EBP;
+	 INT $0x21;                                         { Position the file }
+	 POPL %EBP;
+	 JC EXIT4;
+	 MOVL NewPos, %EDI;                              { New position address }
+	 MOVW %AX, %BX;
+	 MOVW %DX, %AX;
+	 SHLL $0x10, %EAX;                                   { Roll to high part }
+	 MOVW %BX, %AX;
+	 MOVL %EAX, (%EDI);                               { Update new position }
+	 XOR %EAX, %EAX;
+   EXIT4:
+	 MOVW %AX, U_OBJECTS_DOSSTREAMERROR;              { DOS error returned }
+   END;
+   DosSetFilePtr := DosStreamError;                   { Return any error }
+END;
+{$ELSE OS2}
+BEGIN
+   ASM
+	 MOVW MoveType, %AX;                              { Load move type }
+	 MOVB $0x42, %AH;
+	 MOVW POS, %DX;                                  { Load file position }
+	 MOVL POS, %ECX;
+	 SHRL $16,%ECX;
+	 MOVW Handle, %BX;                               { Load file handle }
+	 CALL ___syscall;                                { Position the file }
+	 JC EXIT4;
+	 MOVL NewPos, %EDI;                              { New position address }
+	 MOVW %AX, %BX;
+	 MOVW %DX, %AX;
+	 SHLL $0x10, %EAX;                                   { Roll to high part }
+	 MOVW %BX, %AX;
+	 MOVL %EAX, (%EDI);                               { Update new position }
+	 XOR %EAX, %EAX;
+   EXIT4:
+	 MOVW %AX, U_OBJECTS_DOSSTREAMERROR;              { DOS error returned }
+   END;
+   DosSetFilePtr := DosStreamError;                   { Return any error }
+END;
+{$ENDIF OS2}
+{$ELSE}                                               { Other compilers }
+ASSEMBLER;
+   ASM
+	 MOV AX, MoveType;                                { Load move type }
+	 MOV AH, $42;
+	 MOV DX, Pos.Word[0];                             { Load file position }
+	 MOV CX, Pos.Word[2];
+	 MOV BX, Handle;                                  { Load file handle }
+	 INT $21;                                         { Position the file }
+	 JC @@Exit4;
+	 LES DI, NewPos;                                  { New position address }
+	 MOV ES:[DI], AX;
+	 MOV ES:[DI+2], DX;                               { Update new position }
+     XOR AX, AX;
+   @@Exit4:
+     MOV DosStreamError, AX;                          { DOS error returned }
+   END;
+{$ENDIF}
+
+{***************************************************************************}
+{  DosClose -> Platforms DOS/DPMI/WIN - Checked 16May96 LdB                 }
+{***************************************************************************}
+PROCEDURE DosClose (Handle: Word);
+{$IFDEF FPKPascal}                                    { FPK pascal compiler }
+{$IFNDEF OS2}
+BEGIN
+   ASM
+	 XOR %AX, %AX;
+	 MOVW %AX, U_OBJECTS_DOSSTREAMERROR;              { DOS error cleared }
+	 MOVB $0x3E, %AH;
+	 MOVW Handle, %BX;                               { DOS file handle }
+	 PUSHL %EBP;
+	 INT $0x21;                                         { Close the file }
+	 POPL %EBP;
+	 JNC EXIT5;
+	 MOVW %AX, U_OBJECTS_DOSSTREAMERROR;              { DOS error returned }
+   EXIT5:
+   END;
+END;
+{$ELSE OS2}
+BEGIN
+   ASM
+	 XOR %AX, %AX;
+	 MOVW %AX, U_OBJECTS_DOSSTREAMERROR;              { DOS error cleared }
+	 MOVB $0x3E, %AH;
+	 MOVW Handle, %BX;                                { DOS file handle }
+	 CALL ___syscall;                                 { Close the file }
+	 JNC EXIT5;
+	 MOVW %AX, U_OBJECTS_DOSSTREAMERROR;              { DOS error returned }
+   EXIT5:
+   END;
+END;
+{$ENDIF OS2}
+{$ELSE}                                               { Other compilers }
+ASSEMBLER;
+   ASM
+	 XOR AX, AX;                                      { DOS error cleared }
+	 MOV DosStreamError, AX;
+	 MOV BX, Handle;                                  { DOS file handle }
+	 MOV AH, $3E;
+	 INT $21;                                         { Close the file }
+	 JNC @@Exit5;
+	 MOV DosStreamError, AX;                          { DOS error returned }
+   @@Exit5:
+   END;
+{$ENDIF}
+
+
+END.

+ 2 - 2
rtl/os2/os.inc

@@ -20,8 +20,8 @@
 
 
 {
 {
   $Log$
   $Log$
-  Revision 1.1  1998-03-25 11:18:46  root
-  Initial revision
+  Revision 1.2  1998-04-09 08:24:14  daniel
+  * Brings OS/2 directory up to date.
 
 
   Revision 1.3  1998/01/26 12:01:56  michael
   Revision 1.3  1998/01/26 12:01:56  michael
   + Added log at the end
   + Added log at the end

+ 2 - 2
rtl/os2/os2def.pas

@@ -35,7 +35,7 @@ typedef CHAR      * _Seg16 PCHAR16; }
 {       typedef int ( APIENTRY _PFN)  ();
 {       typedef int ( APIENTRY _PFN)  ();
 typedef _PFN    *PFN;
 typedef _PFN    *PFN;
 typedef int ( APIENTRY _NPFN)  ();
 typedef int ( APIENTRY _NPFN)  ();
-typedef _NPFN   *NPFN;	}
+typedef _NPFN   *NPFN;  }
 
 
        PBYTE = ^BYTE;
        PBYTE = ^BYTE;
        NPBYTE = ^BYTE;
        NPBYTE = ^BYTE;
@@ -346,7 +346,7 @@ typedef _NPFN   *NPFN;	}
   
   
       { null. term. Strings sind in den Header Dateien oft als }
       { null. term. Strings sind in den Header Dateien oft als }
       { array[0..0] of byte deklariert, der folgende Typ er-   }
       { array[0..0] of byte deklariert, der folgende Typ er-   }
-      { m”glich eine Typkonvertierung			       }
+      { m”glich eine Typkonvertierung                  }
       CHARARRAY = array[0..0] of char;
       CHARARRAY = array[0..0] of char;
      
      
   implementation
   implementation

+ 10 - 6
rtl/os2/prt0.as → rtl/os2/prt0.so2

@@ -1,6 +1,10 @@
 / prt0.s (emx+fpk) -- Made from crt0.s,
 / prt0.s (emx+fpk) -- Made from crt0.s,
 /                     Copyright (c) 1990-1994 by Eberhard Mattes.
 /                     Copyright (c) 1990-1994 by Eberhard Mattes.
-/                     Portions Copyright (c) 1997 Dani‰l Mantione.
+/                     Changed for FPK-Pascal in 1997 Dani‰l Mantione.
+/					  This code is _not_ under the Library GNU Public
+/					  License, because the original is not. See copying.emx
+/					  for details. You should have received it with this
+/					  product, write the author if you haven't.
 
 
 		.globl  __text
 		.globl  __text
 		.globl  ___syscall
 		.globl  ___syscall
@@ -10,15 +14,15 @@
 		.globl  __heap_end
 		.globl  __heap_end
 		.globl  __init
 		.globl  __init
 
 
-        .text
+		.text
 
 
 __text:
 __text:
-        push    $__data
-        call    __dos_init
-        jmp     __init
+		push    $__data
+		call    __dos_init
+		jmp     __init
 
 
 ___syscall:
 ___syscall:
-        call    __dos_syscall
+		call    __dos_syscall
 		ret
 		ret
 
 
 		.space  6, 0x90
 		.space  6, 0x90

+ 0 - 38
rtl/os2/prt1.as

@@ -1,38 +0,0 @@
-/ prt1.s (emx+fpk) -- Made from crt2.s,
-/					  Copyright (c) 1990-1996 by Eberhard Mattes.
-/					  Portions Copyright (c) 1997 by Dani‰l Mantione
-
-		.globl  __entry1
-		.globl  _environ
-		.globl	_envc
-		.globl	_argv
-		.globl	_argc
-
-		.text
-
-__entry1:
-		popl    %esi
-		xorl    %ebp, %ebp
-		leal    (%esp), %edi
-		movl    %edi,_environ
-		call    L_ptr_tbl
-		mov		%ecx,_envc
-		mov		%edi,_argv
-		call    L_ptr_tbl
-		mov		%ecx,_argc
-		jmp     *%esi
-
-L_ptr_tbl:
-		xorl    %eax, %eax
-		movl    $-1, %ecx
-1:      incl    %ecx
-		scasl
-		jne     1b
-		ret
-
-		.data
-
-		.comm   _environ,	4
-		.comm   _envc,		4
-		.comm   _argv,		4
-		.comm   _argc,		4

+ 60 - 0
rtl/os2/prt1.so2

@@ -0,0 +1,60 @@
+/ prt1.s (emx+fpk) -- Made from crt2.s and dos.s,
+/					  Copyright (c) 1990-1996 by Eberhard Mattes.
+/                     Changed for FPK-Pascal in 1997 Dani‰l Mantione.
+/					  This code is _not_ under the Library GNU Public
+/					  License, because the original is not. See copying.emx
+/					  for details. You should have received it with this
+/					  product, write the author if you haven't.
+
+		.globl  __entry1
+		.globl  _environ
+		.globl	_envc
+		.globl	_argv
+		.globl	_argc
+
+		.text
+
+__entry1:
+		popl    %esi
+		xorl    %ebp, %ebp
+		leal    (%esp), %edi
+		movl    %edi,_environ
+		call    L_ptr_tbl
+		mov		%ecx,_envc
+		mov		%edi,_argv
+		call    L_ptr_tbl
+		mov		%ecx,_argc
+		jmp     *%esi
+
+L_ptr_tbl:
+		xorl    %eax, %eax
+		movl    $-1, %ecx
+1:      incl    %ecx
+		scasl
+		jne     1b
+		ret
+
+/ In executables created with emxbind, the call to _dos_init will
+/ be fixed up at load time to _emx_init of emx.dll.  Under DOS,
+/ this dummy is called instead as there is no fixup.  This module
+/ must be linked statically to avoid having two fixups for the
+/ same location.
+
+		.globl  __dos_init
+		.globl  __dos_syscall
+
+__dos_init:
+		ret     $4
+
+		.align  2, 0x90
+
+__dos_syscall:
+		int     $0x21
+		ret
+
+		.data
+
+		.comm   _environ,	4
+		.comm   _envc,		4
+		.comm   _argv,		4
+		.comm   _argc,		4

+ 574 - 662
rtl/os2/sysos2.pas

@@ -1,9 +1,9 @@
 {****************************************************************************
 {****************************************************************************
 
 
-					 FPK-Pascal -- OS/2 runtime library
+                     FPK-Pascal -- OS/2 runtime library
 
 
-				  Copyright (c) 1993,95 by Florian Kl„mpfl
-				   Copyright (c) 1997 by Dani‰l Mantione
+                  Copyright (c) 1993,95 by Florian Kl„mpfl
+                   Copyright (c) 1997 by Dani‰l Mantione
 
 
  FPK-Pascal is distributed under the GNU Public License v2. So is this unit.
  FPK-Pascal is distributed under the GNU Public License v2. So is this unit.
  The GNU Public License requires you to distribute the source code of this
  The GNU Public License requires you to distribute the source code of this
@@ -16,794 +16,706 @@
 
 
  Send us your modified files, we can work together if you want!
  Send us your modified files, we can work together if you want!
 
 
-****************************************************************************}
+ FPK-Pascal is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ Library GNU General Public License for more details.
 
 
-unit sysos2;
+ You should have received a copy of the Library GNU General Public License
+ along with FPK-Pascal; see the file COPYING.LIB.  If not, write to
+ the Free Software Foundation, 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
 
 
-{$I os.inc}
-
-interface
-
-{ die betriebssystemunabhangigen Deklarationen einfuegen: }
-
-{$I	SYSTEMH.INC}
-{$I	heaph.inc}
-
-type	Tos=(osDOS,osOS2,osDPMI);
-
-var		os_mode:Tos;
-		first_meg:pointer;
-
-type	Psysthreadib=^Tsysthreadib;
-		Pthreadinfoblock=^Tthreadinfoblock;
-		Pprocessinfoblock=^Tprocessinfoblock;
-
-		Tbytearray=array[0..$ffff] of byte;
-		Pbytearray=^Tbytearray;
-
-		Tsysthreadib=record
-			tid,
-			priority,
-			version:longint;
-			MCcount,
-			MCforceflag:word;
-		end;
-
-		Tthreadinfoblock=record
-			pexchain,
-			stack,
-			stacklimit:pointer;
-			tib2:Psysthreadib;
-			version,
-			ordinal:longint;
-		end;
-
-		Tprocessinfoblock=record
-			pid,
-			parentpid,
-			hmte:longint;
-			cmd,
-			env:Pbytearray;
-			flstatus,
-			ttype:longint;
-		end;
-
-procedure _DosGetInfoBlocks(var Atib:Pthreadinfoblock;
-							var Apib:Pprocessinfoblock);
-
-implementation
+****************************************************************************}
 
 
-{ die betriebssystemunabhangigen Implementationen einfuegen: }
+unit sysos2;
 
 
-{$I	SYSTEM.INC}
+{Changelog:
 
 
-procedure _DosGetInfoBlocks(var Atib:Pthreadinfoblock;
-							var Apib:Pprocessinfoblock);[C];
+    People:
 
 
-{****************************************************************************
+        DM - Dani‰l Mantione
 
 
-					Miscelleanious related routines.
+    Date:           Description of change:              Changed by:
 
 
-****************************************************************************}
+     -              First released version 0.1.         DM
 
 
-procedure halt;
+Coding style:
 
 
-begin
-	asm
-		movw $0x4c00,%ax
-		call ___syscall
-	end;
-end;
+    My coding style is a bit unusual for Pascal. Nevertheless I friendly ask
+    you to try to make your changes not look all to different. In general,
+    set your IDE to use tab characters, optimal fill on and a tabsize of 4.}
 
 
-procedure halt(errnum :	byte);
+{$I os.inc}
 
 
-begin
-	asm
-		movb $0x4c,%ah
-		movb errnum,%al
-		call ___syscall
-	end;
-end;
+interface
 
 
-function paramcount	: longint;
+{Link the startup code.}
+{$l prt1.oo2}
+
+{$I SYSTEMH.INC}
+{$I heaph.inc}
+
+type    Tos=(osDOS,osOS2,osDPMI);
+
+var     os_mode:Tos;
+        first_meg:pointer;
+
+type    Psysthreadib=^Tsysthreadib;
+        Pthreadinfoblock=^Tthreadinfoblock;
+        Pprocessinfoblock=^Tprocessinfoblock;
+
+        Tbytearray=array[0..$ffff] of byte;
+        Pbytearray=^Tbytearray;
+
+        Tsysthreadib=record
+            tid,
+            priority,
+            version:longint;
+            MCcount,
+            MCforceflag:word;
+        end;
+
+        Tthreadinfoblock=record
+            pexchain,
+            stack,
+            stacklimit:pointer;
+            tib2:Psysthreadib;
+            version,
+            ordinal:longint;
+        end;
+
+        Tprocessinfoblock=record
+            pid,
+            parentpid,
+            hmte:longint;
+            cmd,
+            env:Pbytearray;
+            flstatus,
+            ttype:longint;
+        end;
+
+const   UnusedHandle=$ffff;
+        StdInputHandle=0;
+        StdOutputHandle=1;
+        StdErrorHandle=2;
 
 
-begin
-	 asm
-		movl _argc,%eax
-		decl %eax
-		leave
-		ret
-	 end ['EAX'];
-end;
+implementation
 
 
-function paramstr(l	: longint):string;
+{ die betriebssystemunabhangigen Implementationen einfuegen: }
 
 
-	function args	: pointer;
+{$I SYSTEM.INC}
 
 
-	begin
-		asm
-			movl _argv,%eax
-			leave
-			ret
-		end ['EAX'];
-	end;
+procedure dosgetinfoblocks(var Atib:Pthreadinfoblock;
+                           var Apib:Pprocessinfoblock);
+                           external 'DOSCALLS' index 312;
 
 
-var	p:^Pchar;
+{***************************************************************************
 
 
-begin
-	 if	(l>=0) and (l<=paramcount) then
-		begin
-			p:=args;
-			paramstr:=strpas(p[l]);
-		end
-	 else paramstr:='';
-end;
+                Runtime error checking related routines.
 
 
-procedure randomize;
+***************************************************************************}
 
 
-var	hl:longint;
+{$S-}
+procedure st1(stack_size:longint);[public,alias: 'STACKCHECK'];
 
 
 begin
 begin
-	asm
-		movb $0x2c,%ah
-		call ___syscall
-		movw %cx,-4(%ebp)
-		movw %dx,-2(%ebp)
-	end;
-	randseed:=hl;
+    { called when trying to get local stack }
+    { if the compiler directive $S is set   }
+    asm
+        movl stack_size,%ebx
+        movl %esp,%eax
+        subl %ebx,%eax
+{$ifdef SYSTEMDEBUG}
+        movl U_SYSOS2_LOWESTSTACK,%ebx
+        cmpl %eax,%ebx
+        jb   _is_not_lowest
+        movl %eax,U_SYSOS2_LOWESTSTACK
+    _is_not_lowest:
+{$endif SYSTEMDEBUG}
+        cmpb $2,U_SYSOS2_OS_MODE
+        jne _running_in_dos
+        movl U_SYSOS2_STACKBOTTOM,%ebx
+        jmp _running_in_os2
+    _running_in_dos:
+        movl __heap_brk,%ebx
+    _running_in_os2:
+        cmpl %eax,%ebx
+        jae  __short_on_stack
+        leave
+        ret  $4
+    __short_on_stack:
+    end ['EAX','EBX'];
+    { this needs a local variable }
+    { so the function called itself !! }
+    { Writeln('low in stack ');}
+    RunError(202);
 end;
 end;
+{no stack check in system }
 
 
 {****************************************************************************
 {****************************************************************************
 
 
-						Text-file I/O related routines.
+                    Miscelleanious related routines.
 
 
 ****************************************************************************}
 ****************************************************************************}
 
 
-
-function open(f:Pchar;flags:longint):longint;
+procedure halt(errnum:byte);
 
 
 begin
 begin
-	asm
-		movb $0x3d,%ah
-		movl 8(%ebp),%edx
-		movb 12(%ebp),%al
-		call ___syscall
-		jnc	LOPEN1
-		movw %ax,U_SYSOS2_INOUTRES;
-		xorl %eax,%eax
-	LOPEN1:
-		; Returnwert ist in	EAX
-		leave
-		ret	$8
-	 end;
+    asm
+        movb $0x4c,%ah
+        movb errnum,%al
+        call ___syscall
+    end;
 end;
 end;
 
 
-function create(f :	pchar):longint;
+function paramcount:longint;
 
 
 begin
 begin
-	 asm
-		movb $0x3c,%ah
-		movl 8(%ebp),%edx
-		xor	%ecx,%ecx
-		call ___syscall
-		jnc	Lcreate1
-		movw %ax,U_SYSOS2_INOUTRES;
-		xorl %eax,%eax
-	 Lcreate1:
-		; Returnwert ist in	EAX
-		leave
-		ret	$8
-	 end;
+     asm
+        movl _argc,%eax
+        decl %eax
+        leave
+        ret
+     end ['EAX'];
 end;
 end;
 
 
-procedure do_close(h:longint);
+function paramstr(l:longint):string;
 
 
-begin
-	 asm
-		movb $0x3e,%ah
-		mov	h,%ebx
-		call ___syscall
-	 end;
-end;
-
-function dosfilepos(handle:longint) :	longint;
-
-begin
-	asm
-		movb $0x42,%ah
-		movb $0x1,%al
-		movl 8(%ebp),%ebx
-		xorl %edx,%edx
-		call ___syscall
-		jnc	LDOSFILEPOS
-		movw %ax,U_SYSOS2_INOUTRES;
-		xorl %eax,%eax
-	LDOSFILEPOS:
-		leave
-		ret	$4
-	 end;
-end;
-
-procedure dosseek(handle:longint;pos:longint);
-
-begin
-	asm
-		movb $0x42,%ah
-		xorb %al,%al
-		movl 8(%ebp),%ebx
-		movl 12(%ebp),%edx
-		call ___syscall
-		jnc	LDOSSEEK1
-		movw %ax,U_SYSOS2_INOUTRES;
-	LDOSSEEK1:
-	end;
-end;
-
-function dosfilesize(handle	: longint):longint;
-
-	function set_at_end(handle:longint)	: longint;
-
-	begin
-		asm
-			movb $0x42,%ah
-			movb $0x2,%al
-			;	Vorsicht Stack:	0 %ebp;	4 retaddr;
-			;	8 nextstackframe; 12 handle
-			movl 12(%ebp),%ebx
-			xorl %edx,%edx
-			call ___syscall
-			jnc Lset_at_end
-			movw %ax,U_SYSOS2_INOUTRES;
-			xorl %eax,%eax
-		Lset_at_end:
-			leave
-			ret $8
-		end;
-	end;
-
-var	tempfilesize,aktfilepos:longint;
-
-begin
-	aktfilepos:=dosfilepos(handle);
-	tempfilesize:=set_at_end(handle);
-	dosseek(handle,aktfilepos);
-	dosfilesize:=tempfilesize;
-end;
-
-procedure fileclosefunc(var	t :	textrec);
-
-begin
-	do_close(t.handle);
-	t.mode:=fmclosed;
-end;
+    function args:pointer;
 
 
-procedure fileopenfunc(var f:textrec);
+    begin
+        asm
+            movl _argv,%eax
+            leave
+            ret
+        end ['EAX'];
+    end;
 
 
-var	b:array[0..255] of char;
-	size:longint;
+var p:^Pchar;
 
 
 begin
 begin
-	move(f.name[1],b,length(f.name));
-	b[length(f.name)]:=#0;
-	f.inoutfunc:=@fileinoutfunc;
-	f.flushfunc:=@fileinoutfunc;
-	f.closefunc:=@fileclosefunc;
-	case f.mode of
-		fminput:
-			f.handle:=open(b,0);
-		fmoutput:
-			f.handle:=create(b);
-		fmappend:
-			begin
-				f.handle:=open(b,1);
-				f.mode:=fmoutput;
-				size:=dosfilesize(f.handle);
-				if size>0 then
-					begin
-						{Set filepointer to eof character if present,
-						 or to end of file if not. Any change to the
-						 file causes the eof character to be overwritten,
-						 so we get a correct text file.}
-						dosseek(f.handle,size-1);
-						dosread(f.handle,longint(@b),1);
-						if b[0]<>#26 then
-							dosseek(f.handle,size);
-					end;
-			end;
-	end;
+     if (l>=0) and (l<=paramcount) then
+        begin
+            p:=args;
+            paramstr:=strpas(p[l]);
+        end
+     else paramstr:='';
 end;
 end;
 
 
+procedure randomize;
 
 
-function eof(var t:text):boolean;[iocheck];
-
-var	zoekpos:byte;
+var hl:longint;
 
 
 begin
 begin
-	{ maybe we	need new data }
-	if	textrec(t).bufpos+3>=textrec(t).bufend then
-		dateifunc(textrec(t).inoutfunc)(textrec(t));
-	eof:=dosfilesize(textrec(t).handle)<=dosfilepos(textrec(t).handle);
-	if	eof	then
-		eof:=textrec(t).bufend<=textrec(t).bufpos;
-		if	not	eof	then
-			begin
-				{If	the	next character is an end-of-file character,
-				 or	if we are at eoln and first	character on next line
-				 is	eof	then we	should also	return true.}
-				zoekpos:=textrec(t).bufpos;
-				while textrec(t).buffer[zoekpos] in	[#13,#10] do
-					inc(zoekpos);
-				if zoekpos>textrec(t).bufpos+2 then
-					eof:=false
-				else
-					eof:=textrec(t).buffer[zoekpos]=#26;
-			end;
+    asm
+        movb $0x2c,%ah
+        call ___syscall
+        movw %cx,-4(%ebp)
+        movw %dx,-2(%ebp)
+    end;
+    randseed:=hl;
 end;
 end;
 
 
 {****************************************************************************
 {****************************************************************************
 
 
-						File I/O related routines.
+                    Heap management releated routines.
 
 
 ****************************************************************************}
 ****************************************************************************}
 
 
 
 
-procedure doserase(p:Pchar);
-
-begin
-	asm
-		movl 8(%ebp),%edx
-		movb $0x41,%ah
-		call ___syscall
-		jnc	LERASE1
-		movw %ax,U_SYSOS2_INOUTRES;
-	LERASE1:
-	end;
-end;
-
-procedure dosrename(p1,p2:Pchar);
-
-begin
-	asm
-		movl 8(%ebp),%edx
-		movl 12(%ebp),%edi
-		movb $0x56,%ah
-		call ___syscall
-		jnc	LRENAME1
-		movw %ax,U_SYSOS2_INOUTRES;
-	LRENAME1:
-	end;
-end;
-
-function dosread(h,addr,len:longint):longint;
-
-begin
-	asm
-		movl 16(%ebp),%ecx
-		movl 12(%ebp),%edx
-		movl 8(%ebp),%ebx
-		movb $0x3f,%ah
-		call ___syscall
-		jnc	LDOSREAD1
-		movw %ax,U_SYSOS2_INOUTRES;
-		xorl %eax,%eax
-	LDOSREAD1:
-		leave
-		ret	$12
-	end;
-end;
-
-function doswrite(h,addr,len:longint) : longint;
-
-begin
-	asm
-		movl 16(%ebp),%ecx
-		movl 12(%ebp),%edx
-		movl 8(%ebp),%ebx
-		movb $0x40,%ah
-		call ___syscall
-		jnc	LDOSWRITE1
-		movw %ax,U_SYSOS2_INOUTRES;
-	LDOSWRITE1:
-       movl %eax,-4(%ebp)
-	end;
-end;
-
-procedure rewrite(var f:file;l:word);
-
-var	b:array[0..255] of char;
-
-begin
-	{According to Turbo Pascal helpfile, a file is automatically closed
-	 if it's open.}
-	if	filerec(f).mode<>fmclosed then
-	close(f);
-	filerec(f).mode:=fmoutput;
-	move(filerec(f).name[1],b,length(filerec(f).name));
-	b[length(filerec(f).name)]:=#0;
-	filerec(f).handle:=create(b);
-	filerec(f).recsize:=l;
-end;
-
-procedure rewrite(var f:file);
-
-begin
-	rewrite(f,128);
-end;
-
-procedure reset(var	f:file;l:word);
-
-var	b:array[0..255] of char;
-
-begin
-	{According to Turbo Pascal helpfile, a file is automatically closed
-				  if it's open.}
-	if filerec(f).mode<>fmclosed then
-	close(f);
-	move(filerec(f).name[1],b,length(filerec(f).name));
-	b[length(filerec(f).name)]:=#0;
-	case filemode of
-		0:
-			begin
-				filerec(f).mode:=fminput;
-				filerec(f).handle:=open(b,0);
-			end;
-		1:
-			begin
-				filerec(f).mode:=fmoutput;
-				filerec(f).handle:=open(b,1);
-			end;
-		2:
-			begin
-				filerec(f).mode:=fminout;
-				filerec(f).handle:=open(b,2);
-			end;
-	end;
-	filerec(f).recsize:=l;
-end;
+{ this function allows to extend the heap by calling
+syscall $7f00 resizes the brk area}
 
 
-procedure reset(var	f:file);
+function sbrk(size:longint):longint;
 
 
 begin
 begin
-	reset(f,128);
+    asm
+        movl size,%edx
+        movl $0x7f00,%ax
+        int  $0x21
+        movl %eax,__RESULT
+    end;
 end;
 end;
 
 
-procedure blockwrite(var f:file;var buf;count:longint);
-
-var p:pointer;
-	size:longint;
+function getheapstart:pointer;
 
 
 begin
 begin
-	p:=@buf;
-	doswrite(filerec(f).handle,longint(p),count*filerec(f).recsize);
+    asm
+        movl __heap_base,%eax
+        leave
+        ret
+    end ['EAX'];
 end;
 end;
 
 
-procedure blockread(var	f:file;var buf;count:longint;var result:longint);
+{$i heap.inc}
 
 
-begin
-	result:=dosread(filerec(f).handle,longint(@buf),
-	 count*filerec(f).recsize) div filerec(f).recsize;
-end;
+{****************************************************************************
 
 
-procedure blockread(var	f:file;var buf;count:longint);
+                          Low Level File Routines
 
 
-var	result:longint;
+****************************************************************************}
 
 
-begin
-	blockread(f,buf,count,result);
-end;
+procedure allowslash(p:Pchar);
 
 
-procedure truncate (var f : file);[iocheck];
+{Allow slash as backslash.}
 
 
-var p : pointer;
+var i:longint;
 
 
 begin
 begin
-   doswrite(filerec(f).handle,longint(p),0);
+    for i:=0 to strlen(p) do
+        if p[i]='/' then p[i]:='\';
 end;
 end;
 
 
-procedure close(var	f:file);
+procedure do_close(h:longint);
 
 
 begin
 begin
-	if (filerec(f).mode<>fmclosed) then
-		begin
-			filerec(f).mode:=fmclosed;
-			do_close(filerec(f).handle);
-		end;
+     asm
+        movb $0x3e,%ah
+        mov h,%ebx
+        call ___syscall
+     end;
 end;
 end;
 
 
-function filepos(var f:file):longint;
-
-var	l:longint;
+procedure do_erase(p:Pchar);
 
 
 begin
 begin
-	filepos:=dosfilepos(filerec(f).handle) div filerec(f).recsize;
+    allowslash(p);
+    asm
+        movl 8(%ebp),%edx
+        movb $0x41,%ah
+        call ___syscall
+        jnc LERASE1
+        movw %ax,U_SYSOS2_INOUTRES;
+    LERASE1:
+    end;
 end;
 end;
 
 
-function filesize(var f:file)	: longint;
+procedure do_rename(p1,p2:Pchar);
 
 
 begin
 begin
-	filesize:=dosfilesize(filerec(f).handle) div filerec(f).recsize;
+    allowslash(p1);
+    allowslash(p2);
+    asm
+        movl 8(%ebp),%edx
+        movl 12(%ebp),%edi
+        movb $0x56,%ah
+        call ___syscall
+        jnc LRENAME1
+        movw %ax,U_SYSOS2_INOUTRES;
+    LRENAME1:
+    end;
 end;
 end;
 
 
-function eof(var f:file):boolean;[iocheck];
+function do_read(h,addr,len:longint):longint;
 
 
 begin
 begin
-	eof:=filesize(f)<=filepos(f);
+    asm
+        movl 16(%ebp),%ecx
+        movl 12(%ebp),%edx
+        movl 8(%ebp),%ebx
+        movb $0x3f,%ah
+        call ___syscall
+        jnc LDOSREAD1
+        movw %ax,U_SYSOS2_INOUTRES;
+        xorl %eax,%eax
+    LDOSREAD1:
+        leave
+        ret $12
+    end;
 end;
 end;
 
 
-procedure seek(var f:file;pos	: longint);
+function do_write(h,addr,len:longint) : longint;
 
 
 begin
 begin
-	dosseek(filerec(f).handle,pos*filerec(f).recsize);
-end;
+    asm
+        movl 16(%ebp),%ecx
+        movl 12(%ebp),%edx
+        movl 8(%ebp),%ebx
+        movb $0x40,%ah
+        call ___syscall
+        jnc LDOSWRITE1
+        movw %ax,U_SYSOS2_INOUTRES;
+    LDOSWRITE1:
+       movl %eax,-4(%ebp)
+    end;
+end;
+
+function do_filepos(handle:longint):longint;
+
+begin
+    asm
+        movb $0x42,%ah
+        movb $0x1,%al
+        movl 8(%ebp),%ebx
+        xorl %edx,%edx
+        call ___syscall
+        jnc LDOSFILEPOS
+        movw %ax,U_SYSOS2_INOUTRES;
+        xorl %eax,%eax
+    LDOSFILEPOS:
+        leave
+        ret $4
+     end;
+end;
+
+procedure do_seek(handle,pos:longint);
+
+begin
+    asm
+        movl $0x4200,%eax
+        movl 8(%ebp),%ebx
+        movl 12(%ebp),%edx
+        movl %edx,%ecx
+        shrl $16,%ecx
+        call ___syscall
+        jnc .LDOSSEEK1
+        movw %ax,U_SYSOS2_INOUTRES;
+    .LDOSSEEK1:
+        leave
+        ret $8
+    end;
+end;
+
+function do_seekend(handle:longint):longint;
+
+begin
+    asm
+        movl $0x4202,%eax
+        movl 8(%ebp),%ebx
+        xorl %ecx,%ecx
+        xorl %edx,%edx
+        call ___syscall
+        jnc .Lset_at_end1
+        movw %ax,U_SYSOS2_INOUTRES;
+        xorl %eax,%eax
+        jmp .Lset_at_end2
+    .Lset_at_end1:
+        shll $16,%edx
+        movzwl %ax,%eax
+        orl %edx,%eax
+    .Lset_at_end2:
+        leave
+        ret $4
+    end;
+end;
+
+function do_filesize(handle:longint):longint;
+
+var aktfilepos:longint;
+
+begin
+    aktfilepos:=do_filepos(handle);
+    do_filesize:=do_seekend(handle);
+    do_seek(handle,aktfilepos);
+end;
+
+procedure do_truncate(handle,pos:longint);
+
+begin
+    asm
+        movl $0x4200,%eax
+        movl 8(%ebp),%ebx
+        movl 12(%ebp),%edx
+        movl %edx,%ecx
+        shrl $16,%ecx
+        call ___syscall
+        jc .LTruncate1
+        movl 8(%ebp),%ebx
+        movl 12(%ebp),%edx
+        movl %ebp,%edx
+        xorl %ecx,%ecx
+        movb $0x40,%ah
+        call ___syscall
+        jnc .LTruncate2
+        .LTruncate1:
+        movw %ax,U_SYSOS2_INOUTRES;
+        .LTruncate2:
+        leave
+        ret $8
+    end;
+end;
+
+procedure do_open(var f;p:pchar;flags:longint);
+
+{
+  filerec and textrec have both handle and mode as the first items so
+  they could use the same routine for opening/creating.
+  when (flags and $10)   the file will be append
+  when (flags and $100)  the file will be truncate/rewritten
+  when (flags and $1000) there is no check for close (needed for textfiles)
+}
+
+var oflags:longint;
+
+begin
+    allowslash(p);
+    { close first if opened }
+    if ((flags and $1000)=0) then
+        begin
+            case filerec(f).mode of
+                fminput,fmoutput,fminout : Do_Close(filerec(f).handle);
+                fmclosed:;
+            else
+                begin
+                    inoutres:=102; {not assigned}
+                    exit;
+                end;
+            end;
+       end;
+    { reset file handle }
+    filerec(f).handle:=high(word);
+    oflags:=$8404;
+    { convert filemode to filerec modes }
+    case (flags and 3) of
+        0 : begin
+            filerec(f).mode:=fminput;
+            oflags:=$8001;
+        end;
+        1 : filerec(f).mode:=fmoutput;
+        2 : filerec(f).mode:=fminout;
+    end;
+    if (flags and $100)<>0 then
+        begin
+            filerec(f).mode:=fmoutput;
+            oflags:=$8302;
+        end
+    else
+        if (flags and $10)<>0 then
+            begin
+                filerec(f).mode:=fmoutput;
+                oflags:=$8404;
+            end;
+    { empty name is special }
+    if p[0]=#0 then
+        begin
+            case filerec(f).mode of
+                fminput:filerec(f).handle:=StdInputHandle;
+                fmappend,fmoutput : begin
+                    filerec(f).handle:=StdOutputHandle;
+                    filerec(f).mode:=fmoutput; {fool fmappend}
+                end;
+            end;
+            exit;
+        end;
+    asm
+        movl $0xff02,%ax
+        movl -4(%ebp),%ecx
+        movl 12(%ebp),%ebx
+        call ___syscall
+        jnc .LOPEN1
+        movw %ax,U_SYSOS2_INOUTRES;
+        movw $0xffff,%ax
+    .LOPEN1:
+        movl 8(%ebp),%edx
+        movw %ax,(%edx)
+    end;
+    if (flags and $10)<>0 then
+        do_seekend(filerec(f).handle);
+end;
+
+{*****************************************************************************
+                           UnTyped File Handling
+*****************************************************************************}
+
+{$i file.inc}
+
+{*****************************************************************************
+                           Typed File Handling
+*****************************************************************************}
+
+{$i typefile.inc}
+
+{*****************************************************************************
+                           Text File Handling
+*****************************************************************************}
+
+{$DEFINE EOF_CTRLZ}
+
+{$i text.inc}
 
 
 {****************************************************************************
 {****************************************************************************
 
 
-						  Directory related routines.
+                          Directory related routines.
 
 
 ****************************************************************************}
 ****************************************************************************}
 
 
-procedure dos_dirs(func:byte;name:Pchar);
-
-begin
-	asm
-		movl 10(%ebp),%edx
-		movb 8(%ebp),%ah
-		call ___syscall
-		jnc	LDOS_DIRS1
-		movw %ax,U_SYSOS2_INOUTRES;
-	LDOS_DIRS1:
-		leave
-		ret	$6
-	end;
-end;
+{*****************************************************************************
+                           Directory Handling
+*****************************************************************************}
 
 
-procedure _dir(func:byte;const s:string);
+procedure dosdir(func:byte;const s:string);
 
 
-var	buffer:array[0..255] of char;
+var buffer:array[0..255] of char;
 
 
 begin
 begin
-	move(s[1],buffer,length(s));
-	buffer[length(s)]:=#0;
-	dos_dirs(func,buffer);
+    move(s[1],buffer,length(s));
+    buffer[length(s)]:=#0;
+    allowslash(Pchar(@buffer));
+    asm
+        leal buffer,%edx
+        movb 8(%ebp),%ah
+        call ___syscall
+        jnc  .LDOS_DIRS1
+        movw %ax,U_SYSOS2_INOUTRES;
+    .LDOS_DIRS1:
+    end;
 end;
 end;
 
 
-procedure mkdir(const s:string);
 
 
-begin
-	_dir($39,s);
-end;
-
-procedure rmdir(const s:string);
+procedure mkdir(const s : string);
 
 
 begin
 begin
-	_dir($3a,s);
+    DosDir($39,s);
 end;
 end;
 
 
-procedure chdir(const s:string);
+
+procedure rmdir(const s : string);
 
 
 begin
 begin
-	_dir($3b,s);
+    DosDir($3a,s);
 end;
 end;
 
 
-{ thanks to	Michael	Van	Canneyt	<[email protected]>, }
-{ who wrote this code												 }
-procedure getdir(drivenr:byte;var dir:string);
-
-var	temp:string;
-	sof:pointer;
-	i:byte;
+procedure chdir(const s : string);
 
 
 begin
 begin
-	sof:=@dir[4];
-
-	{ dir[1..3] will contain '[drivenr]:\', but is	not	}
-	{ supplied by DOS, so we let dos string start at	}
-	{ dir[4]											}
-	asm
-		{ Get dir from drivenr:0=default,	1=A	etc... }
-		movb drivenr,%dl
-
-		{ put (previously saved) offset	in si }
-		movl sof,%esi
-
-		{ call msdos function 47H :	Get	dir	}
-		mov	$0x47,%ah
-
-		{ make the call	}
-		call ___syscall
-
-		{ Rem: if call unsuccesfull, carry is set, and AX has }
-		{ error	code										  }
-
-	end;
-	{ Now Dir should be filled	with directory in ASCIIZ, }
-	{ starting	from dir[4]								  }
-	dir[0]:=#3;
-	dir[2]:=':';
-	dir[3]:='\';
-
-	i:=4;
-	{ conversation	to Pascal string }
-	while (dir[i]<>#0)	do
-		begin
-			{ convert path name to DOS }
-			if dir[i]='/'	then
-				dir[i]:='\';
-			dir[0]:=chr(i);
-			inc(i);
-		end;
-
-	{ upcase the string (FPKPascal	function) }
-	dir:=upcase(dir);
-	if drivenr<>0 then	  {	Drive was supplied.	We know	it }
-		dir[1]:=chr(65+drivenr-1)
-	else
-		begin
-			{ We need to get the current drive from DOS function 19H }
-			{ because the drive was the default, which can be unknown	}
-			asm
-				movb $0x19,%ah
-				call ___syscall
-				addb $65,%al
-				movb %al,i
-			end;
-			dir[1]:=chr(i)
-		end;
+    DosDir($3b,s);
 end;
 end;
 
 
-{****************************************************************************
-
-					Heap management releated routines.
-
-****************************************************************************}
+procedure getdir(drivenr : byte;var dir : string);
 
 
+{Written by Michael Van Canneyt.}
 
 
-{ this function allows to extend the heap by calling
-syscall $7f00 resizes the brk area}
-
-function sbrk(size:longint):longint;
-
-begin
-	asm
-		movl size,%edx
-		movl $0x7f00,%ax
-		int  $0x21
-		movl %eax,__RESULT
-	end;
-end;
-
-function getheapstart:pointer;
+var temp:array[0..255] of char;
+    sof:Pchar;
+    i:byte;
 
 
 begin
 begin
-	asm
-		movl __heap_base,%eax
-		leave
-		ret
-	end ['EAX'];
+    sof:=pchar(@dir[4]);
+    { dir[1..3] will contain '[drivenr]:\', but is not }
+    { supplied by DOS, so we let dos string start at   }
+    { dir[4]                                           }
+    { Get dir from drivenr : 0=default, 1=A etc... }
+    asm
+        movb drivenr,%dl
+        movl sof,%esi
+        mov  $0x47,%ah
+        call ___syscall
+    end;
+    { Now Dir should be filled with directory in ASCIIZ, }
+    { starting from dir[4]                               }
+    dir[0]:=#3;
+    dir[2]:=':';
+    dir[3]:='\';
+    i:=4;
+    {Conversion to Pascal string }
+    while (dir[i]<>#0) do
+        begin
+            { convert path name to DOS }
+            if dir[i]='/' then
+            dir[i]:='\';
+            dir[0]:=char(i);
+            inc(i);
+        end;
+    { upcase the string (FPKPascal function) }
+    dir:=upcase(dir);
+    if drivenr<>0 then   { Drive was supplied. We know it }
+        dir[1]:=char(65+drivenr-1)
+    else
+        begin
+            { We need to get the current drive from DOS function 19H  }
+            { because the drive was the default, which can be unknown }
+            asm
+                movb $0x19,%ah
+                call ___syscall
+                addb $65,%al
+                movb %al,i
+            end;
+            dir[1]:=char(i);
+        end;
 end;
 end;
 
 
-{$i	heap.inc}
-
-{***************************************************************************
 
 
-				Runtime error checking related routines.
-
-***************************************************************************}
-
-{$S-}
-procedure st1(stack_size:longint);[public,alias: 'STACKCHECK'];
-
-begin
-	{ called when trying to get local stack }
-	{ if the compiler directive $S is set   }
-	asm
-		movl stack_size,%ebx
-		movl %esp,%eax
-		subl %ebx,%eax
-{$ifdef SYSTEMDEBUG}
-		movl U_SYSOS2_LOWESTSTACK,%ebx
-		cmpl %eax,%ebx
-		jb   _is_not_lowest
-		movl %eax,U_SYSOS2_LOWESTSTACK
-	_is_not_lowest:
-{$endif SYSTEMDEBUG}
-		cmpb $2,U_SYSOS2_OS_MODE
-		jne _running_in_dos
-		movl U_SYSOS2_STACKBOTTOM,%ebx
-		jmp _running_in_os2
-	_running_in_dos:
-		movl __heap_brk,%ebx
-	_running_in_os2:
-		cmpl %eax,%ebx
-		jae  __short_on_stack
-		leave
-		ret  $4
-	__short_on_stack:
-	end ['EAX','EBX'];
-	{ this needs a local variable }
-	{ so the function called itself !! }
-	{ Writeln('low in stack ');}
-	RunError(202);
-end;
-{no stack check in system }
 
 
 {****************************************************************************
 {****************************************************************************
 
 
-						System unit initialization.
+                        System unit initialization.
 
 
 ****************************************************************************}
 ****************************************************************************}
 
 
-
-var
-	pib:Pprocessinfoblock;
-	tib:Pthreadinfoblock;
-
-begin
-	{Determine the operating system	we are running on.}
-	asm
-		movw $0x7f0a,%ax
-		call ___syscall
-		test $512,%bx		   ; Bit 9 is OS/2 flag.
-		setnzb U_SYSOS2_OS_MODE
-		test $4096,%bx
-		jz _noRSX
-		movb $2,U_SYSOS2_OS_MODE
-	_noRSX:
-	end;
-	{Now request, if we	are	running	under DOS,
-	 read-access to	the	first meg. of memory.}
-	if os_mode in [osDOS,osDPMI] then
-		asm
-			mov	$0x7f13,%ax
-			xor	%ebx,%ebx
-			mov	$0xfff,%ecx
-			xor	%edx,%edx
-			call ___syscall
-			mov	%eax,U_SYSOS2_FIRST_MEG
-		end
-	else
-		first_meg:=nil;
-	{At 0.9.2, case for enumeration does not work.}
-	case os_mode of
-		osDOS:
-			stackbottom:=0;
-		osOS2:
-			begin
-				_DosGetInfoBlocks(tib,pib);
-				stackbottom:=longint(tib^.stack);
-			end;
-		osDPMI:
-			stackbottom:=0;		{Not sure how to get it, but seems to be
-								 always zero.}
-	end;
-	exitproc:=nil;
-
-	{Initialize the heap.}
-	InitHeap;
-	
-   { to test stack depth }
-   loweststack:=maxlongint;
-
-	{Enable the brk area by initializing it with the initial heap size.}
-	asm
-		mov $0x7f01,%ax
-		movl HEAPSIZE,%edx
-		call ___syscall
-	end;
-
-	{ Ein- und Ausgabe initialisieren }
-	assign(input,'');
-	textrec(input).handle:=0;
-	textrec(input).mode:=fminput;
-	textrec(input).inoutfunc:=@fileinoutfunc;
-	textrec(input).flushfunc:=@fileinoutfunc;
-	assign(output,'');
-	textrec(output).handle:=1;
-	textrec(output).mode:=fmoutput;
-	textrec(output).inoutfunc:=@fileinoutfunc;
-	textrec(output).flushfunc:=@fileinoutfunc;
-	textrec(input).mode:=fminput;
-
-	{ kein Ein-	Ausgabefehler }
-	inoutres:=0;
+procedure OpenStdIO(var f:text;mode:word;hdl:longint);
+
+begin
+    Assign(f,'');
+    TextRec(f).Handle:=hdl;
+    TextRec(f).Mode:=mode;
+    TextRec(f).InOutFunc:=@FileInOutFunc;
+    TextRec(f).FlushFunc:=@FileInOutFunc;
+    TextRec(f).Closefunc:=@fileclosefunc;
+end;
+
+var pib:Pprocessinfoblock;
+    tib:Pthreadinfoblock;
+
+begin
+    {Determine the operating system we are running on.}
+    asm
+        movw $0x7f0a,%ax
+        call ___syscall
+        test $512,%bx          {Bit 9 is OS/2 flag.}
+        setnzb U_SYSOS2_OS_MODE
+        test $4096,%bx
+        jz _noRSX
+        movb $2,U_SYSOS2_OS_MODE
+    _noRSX:
+    end;
+
+    {Enable the brk area by initializing it with the initial heap size.}
+    asm
+        mov $0x7f01,%ax
+        movl HEAPSIZE,%edx
+        call ___syscall
+    end;
+
+    {Now request, if we are running under DOS,
+     read-access to the first meg. of memory.}
+    if os_mode in [osDOS,osDPMI] then
+        asm
+            mov $0x7f13,%ax
+            xor %ebx,%ebx
+            mov $0xfff,%ecx
+            xor %edx,%edx
+            call ___syscall
+            mov %eax,U_SYSOS2_FIRST_MEG
+        end
+    else
+        first_meg:=nil;
+    {At 0.9.2, case for enumeration does not work.}
+    case os_mode of
+        osDOS:
+            stackbottom:=0;     {In DOS mode, heap_brk is also the
+                                 stack bottom.}
+        osOS2:
+            begin
+                dosgetinfoblocks(tib,pib);
+                stackbottom:=longint(tib^.stack);
+            end;
+        osDPMI:
+            stackbottom:=0;     {Not sure how to get it, but seems to be
+                                 always zero.}
+    end;
+    exitproc:=nil;
+
+    {Initialize the heap.}
+    initheap;
+
+    { to test stack depth }
+    loweststack:=maxlongint;
+
+    OpenStdIO(Input,fmInput,StdInputHandle);
+    OpenStdIO(Output,fmOutput,StdOutputHandle);
+    OpenStdIO(StdErr,fmOutput,StdErrorHandle);
+
+    { kein Ein- Ausgabefehler }
+    inoutres:=0;
 end.
 end.

+ 36 - 0
rtl/os2/testkbd.pas

@@ -0,0 +1,36 @@
+program TestKBD;
+{$X+}
+
+uses
+{$IFDEF FPK}
+ KbdCalls;
+{$ELSE}
+ Os2Base, Os2Def;
+{$ENDIF}
+
+function ExtKeyPressed: boolean;       (* 'key' is here as well e.g. a shift *)
+var
+ C: char;
+{$IFDEF VIRTUALPASCAL}
+ KI: KbdKeyInfo;
+ K: KbdInfo;
+{$ELSE}
+ KI: TKbdKeyInfo;
+ K: TKbdInfo;
+{$ENDIF}
+ B: boolean;
+begin
+ B := false;
+ K.cb := SizeOf (K);
+ KbdGetStatus (K, 0);
+{ FillChar (KI, SizeOf (KI), 0);
+ KbdCharIn (KI, IO_NOWAIT, 0);}
+ ExtKeyPressed :=
+{ (KI.chScan <> 0) and (KI.chScan and $80 = 0) or }
+                                                    (K.fsState and $FF0F <> 0);
+end;
+
+begin
+ WriteLn ('Press any _shift_ (or Alt, Ctrl etc.) key to continue ...');
+ repeat until ExtKeyPressed;
+end.

Some files were not shown because too many files changed in this diff