Jelajahi Sumber

* Brings OS/2 directory up to date.

daniel 27 tahun lalu
induk
melakukan
12fb25a920

+ 11 - 11
rtl/os2/atx.pas

@@ -1,15 +1,15 @@
 program atx;
 
-var	f:text;
-	s:string;
+var f:text;
+    s:string;
 
 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.}
 
-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
-	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 ditekan karena terlalu besar
+ 492 - 467
rtl/os2/crt.pas


+ 8 - 8
rtl/os2/crtdemo.pas

@@ -63,19 +63,19 @@ procedure Initialize;
 { generator. Paint the help line. }
 begin
   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 }
   LastRow:=Hi(WindMax)+1;
   GoToXY(1,LastRow);                   { put message line on screen }
   TextBackground(Black);
   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 }
 end; { Init }
 

File diff ditekan karena terlalu besar
+ 1038 - 1037
rtl/os2/dos.pas


File diff ditekan karena terlalu besar
+ 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:
-	2 June 1997 : Creation.
+    2 June 1997 : Creation.
 
 This unit is copyright (c) 1997 by Dani‰l Mantione.
 FPK Pascal is copyright (c) -1997 by Florian Klaempfl.
@@ -22,9 +22,9 @@ Modifying this unit is allowed, under the following conditions:
 
 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.}
 procedure __emxinit;

+ 3 - 3
rtl/os2/extest.pas

@@ -3,6 +3,6 @@ program extest;
 uses dos;
 
 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
      frameflags : longint = FCF_TITLEBAR+
                             FCF_SYSMENU+
-     			    FCF_SIZEBORDER+
+                    FCF_SIZEBORDER+
                             FCF_MINBUTTON+
                             FCF_MAXBUTTON+
                             FCF_SHELLPOSITION+

+ 11 - 11
rtl/os2/heapsize.pas

@@ -1,25 +1,25 @@
 program heapsize;
 
-var	a:longint;
+var a:longint;
 
 procedure writeheapsize;
 
 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;
 
 begin
     writeheapsize;
     asm
-		movl $0x7f00,%ax
-		movl $327680,%edx
-		call ___syscall
+        movl $0x7f00,%ax
+        movl $327680,%edx
+        call ___syscall
     end;
     writeheapsize;
 end.

+ 19 - 16
rtl/os2/helloos2.pas

@@ -1,21 +1,24 @@
 program helloos2;
 
-var	a,b:^word;
+var a,b:^word;
 
 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.

+ 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;
 
-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 _VioSetMode (var Amodeinfo:viomodeinfo;viohandle:word):word;[C];
 
-var	mode:viomodeinfo;
+var mode:viomodeinfo;
 
 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.

+ 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$
-  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
   + Added log at the end

+ 2 - 2
rtl/os2/os2def.pas

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

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

@@ -1,6 +1,10 @@
 / prt0.s (emx+fpk) -- Made from crt0.s,
 /                     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  ___syscall
@@ -10,15 +14,15 @@
 		.globl  __heap_end
 		.globl  __init
 
-        .text
+		.text
 
 __text:
-        push    $__data
-        call    __dos_init
-        jmp     __init
+		push    $__data
+		call    __dos_init
+		jmp     __init
 
 ___syscall:
-        call    __dos_syscall
+		call    __dos_syscall
 		ret
 
 		.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.
  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!
 
-****************************************************************************}
+ 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
-	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;
+{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
-	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;
 
-function create(f :	pchar):longint;
+function paramcount:longint;
 
 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;
 
-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
-	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;
 
+procedure randomize;
 
-function eof(var t:text):boolean;[iocheck];
-
-var	zoekpos:byte;
+var hl:longint;
 
 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;
 
 {****************************************************************************
 
-						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
-	reset(f,128);
+    asm
+        movl size,%edx
+        movl $0x7f00,%ax
+        int  $0x21
+        movl %eax,__RESULT
+    end;
 end;
 
-procedure blockwrite(var f:file;var buf;count:longint);
-
-var p:pointer;
-	size:longint;
+function getheapstart:pointer;
 
 begin
-	p:=@buf;
-	doswrite(filerec(f).handle,longint(p),count*filerec(f).recsize);
+    asm
+        movl __heap_base,%eax
+        leave
+        ret
+    end ['EAX'];
 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
-   doswrite(filerec(f).handle,longint(p),0);
+    for i:=0 to strlen(p) do
+        if p[i]='/' then p[i]:='\';
 end;
 
-procedure close(var	f:file);
+procedure do_close(h:longint);
 
 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;
 
-function filepos(var f:file):longint;
-
-var	l:longint;
+procedure do_erase(p:Pchar);
 
 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;
 
-function filesize(var f:file)	: longint;
+procedure do_rename(p1,p2:Pchar);
 
 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;
 
-function eof(var f:file):boolean;[iocheck];
+function do_read(h,addr,len:longint):longint;
 
 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;
 
-procedure seek(var f:file;pos	: longint);
+function do_write(h,addr,len:longint) : longint;
 
 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
-	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;
 
-procedure mkdir(const s:string);
 
-begin
-	_dir($39,s);
-end;
-
-procedure rmdir(const s:string);
+procedure mkdir(const s : string);
 
 begin
-	_dir($3a,s);
+    DosDir($39,s);
 end;
 
-procedure chdir(const s:string);
+
+procedure rmdir(const s : string);
 
 begin
-	_dir($3b,s);
+    DosDir($3a,s);
 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
-	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;
 
-{****************************************************************************
-
-					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
-	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;
 
-{$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.

+ 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.

Beberapa file tidak ditampilkan karena terlalu banyak file yang berubah dalam diff ini