objects.pas 162 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809281028112812281328142815281628172818281928202821282228232824282528262827282828292830283128322833283428352836283728382839284028412842284328442845284628472848284928502851285228532854285528562857285828592860286128622863286428652866286728682869287028712872287328742875287628772878287928802881288228832884288528862887288828892890289128922893289428952896289728982899290029012902290329042905290629072908290929102911291229132914291529162917291829192920292129222923292429252926292729282929293029312932293329342935293629372938293929402941294229432944294529462947294829492950295129522953295429552956295729582959296029612962296329642965296629672968296929702971297229732974297529762977297829792980298129822983298429852986298729882989299029912992299329942995299629972998299930003001300230033004300530063007300830093010301130123013301430153016301730183019302030213022302330243025302630273028302930303031303230333034303530363037303830393040304130423043304430453046304730483049305030513052305330543055305630573058305930603061306230633064306530663067306830693070307130723073307430753076307730783079308030813082308330843085308630873088308930903091309230933094309530963097309830993100310131023103310431053106310731083109311031113112311331143115311631173118311931203121312231233124312531263127312831293130313131323133313431353136313731383139314031413142314331443145314631473148314931503151315231533154315531563157315831593160316131623163316431653166316731683169317031713172317331743175317631773178317931803181318231833184318531863187318831893190319131923193319431953196319731983199320032013202320332043205320632073208320932103211321232133214
  1. {**********************************************************}
  2. { }
  3. { System independent clone of OBJECTS.PAS }
  4. { }
  5. { Interface Copyright (c) 1992 Borland International }
  6. { }
  7. { Parts Copyright (c) 1992,96 by Florian Klaempfl }
  8. { [email protected] }
  9. { }
  10. { Parts Copyright (c) 1996 by Frank ZAGO }
  11. { [email protected] }
  12. { }
  13. { Parts Copyright (c) 1995 by MH Spiegel }
  14. { }
  15. { Parts Copyright (c) 1996, 1997, 1998, 1999 }
  16. { [email protected] - primary e-mail address }
  17. { [email protected] - backup e-mail address }
  18. { }
  19. {****************[ THIS CODE IS FREEWARE ]*****************}
  20. { }
  21. { This sourcecode is released for the purpose to }
  22. { promote the pascal language on all platforms. You may }
  23. { redistribute it and/or modify with the following }
  24. { DISCLAIMER. }
  25. { }
  26. { This SOURCE CODE is distributed "AS IS" WITHOUT }
  27. { WARRANTIES AS TO PERFORMANCE OF MERCHANTABILITY OR }
  28. { ANY OTHER WARRANTIES WHETHER EXPRESSED OR IMPLIED. }
  29. { }
  30. {*****************[ SUPPORTED PLATFORMS ]******************}
  31. { 16 and 32 Bit compilers }
  32. { DOS - Turbo Pascal 7.0 + (16 Bit) }
  33. { DPMI - Turbo Pascal 7.0 + (16 Bit) }
  34. { - FPC 0.9912+ (GO32V2) (32 Bit) }
  35. { WINDOWS - Turbo Pascal 7.0 + (16 Bit) }
  36. { - Delphi 1.0+ (16 Bit) }
  37. { WIN95/NT - Delphi 2.0+ (32 Bit) }
  38. { - Virtual Pascal 2.0+ (32 Bit) }
  39. { - Speedsoft Sybil 2.0+ (32 Bit) }
  40. { - FPC 0.9912+ (32 Bit) }
  41. { OS2 - Virtual Pascal 1.0+ (32 Bit) }
  42. { - Speed Pascal 1.0+ (32 Bit) }
  43. { - C'T patch to BP (16 Bit) }
  44. { }
  45. {*****************[ REVISION HISTORY ]*********************}
  46. { Version Date Fix }
  47. { ------- --------- --------------------------------- }
  48. { 1.00 12 Jun 96 First multi platform release }
  49. { 1.01 20 Jun 96 Fixes to TCollection }
  50. { 1.02 07 Aug 96 Fixed TStringCollection.Compare }
  51. { 1.10 18 Jul 97 Windows 95 support added. }
  52. { 1.11 21 Aug 97 FPC pascal 0.92 implemented }
  53. { 1.15 26 Aug 97 TXMSStream compatability added }
  54. { TEMSStream compatability added }
  55. { 1.30 29 Aug 97 Platform.inc sort added. }
  56. { 1.32 02 Sep 97 RegisterTypes completed. }
  57. { 1.37 04 Sep 97 TStream.Get & Put completed. }
  58. { 1.40 04 Sep 97 LongMul & LongDiv added. }
  59. { 1.45 04 Sep 97 Refined and passed all tests. }
  60. { FPC - bugged on register records! }
  61. { 1.50 05 May 98 Fixed DOS Access to files, one }
  62. { version for all intel platforms }
  63. { (CEC) }
  64. { 1.60 22 Oct 97 Delphi3 32 bit code added. }
  65. { 1.70 05 Feb 98 Speed pascal code added. }
  66. { 1.80 05 May 98 Virtual pascal 2.0 compiler added. }
  67. { 1.85 10 Sep 98 Checks run & commenting added. }
  68. { 1.90 03 Nov 98 Fixed for FPC version 0.998 }
  69. { Only Go32v2 supported no Go32v1 }
  70. { 1.95 02 Feb 99 Moved some stuff to common.pas }
  71. { 1.97 28 May 99 Bug fix to TCollection.AtInsert }
  72. { 1.98 07 Jul 99 Speedsoft SYBIL 2.0 code added. }
  73. { 1.99 08 Jul 99 Fixed TCollection FirstThat etc. }
  74. { 2.00 27 Oct 99 All stream read/writes checked. }
  75. { Delphi3+ memory code to COMMON.PAS }
  76. { 2.01 03 Nov 99 FPC windows support added. }
  77. {**********************************************************}
  78. UNIT Objects;
  79. {<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>}
  80. INTERFACE
  81. {<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>}
  82. {====Include file to sort compiler platform out =====================}
  83. {$I Platform.inc}
  84. {====================================================================}
  85. {==== Compiler directives ===========================================}
  86. {$IFNDEF PPC_FPC} { FPC doesn't support these switches }
  87. {$F+} { Force far calls - Used because of the Foreach, FirstThat etc...}
  88. {$A+} { Word Align Data }
  89. {$B-} { Allow short circuit boolean evaluations }
  90. {$O+} { This unit may be overlaid }
  91. {$G+} { 286 Code optimization - if you're on an 8088 get a real computer }
  92. {$E+} { Emulation is on }
  93. {$N-} { No 80x87 code generation }
  94. {$ENDIF}
  95. {$X+} { Extended syntax is ok }
  96. {$R-} { Disable range checking }
  97. {$S-} { Disable Stack Checking }
  98. {$I-} { Disable IO Checking }
  99. {$Q-} { Disable Overflow Checking }
  100. {$V-} { Turn off strict VAR strings }
  101. {====================================================================}
  102. USES
  103. {$IFDEF OS_WINDOWS} { WIN/NT CODE }
  104. {$IFNDEF PPC_SPEED} { NON SPEED COMPILER }
  105. {$IFDEF PPC_FPC} { FPC WINDOWS COMPILER }
  106. Windows, { Standard unit }
  107. {$ELSE} { OTHER COMPILERS }
  108. WinTypes, WinProcs, { Stardard units }
  109. {$ENDIF}
  110. {$ELSE} { SPEEDSOFT COMPILER }
  111. WinBase, WinUser, { Standard unit }
  112. {$ENDIF}
  113. {$ENDIF}
  114. Common, FileIO; { GFV standard units }
  115. {***************************************************************************}
  116. { PUBLIC CONSTANTS }
  117. {***************************************************************************}
  118. {---------------------------------------------------------------------------}
  119. { STREAM ERROR STATE MASKS }
  120. {---------------------------------------------------------------------------}
  121. CONST
  122. stOk = 0; { No stream error }
  123. stError = -1; { Access error }
  124. stInitError = -2; { Initialize error }
  125. stReadError = -3; { Stream read error }
  126. stWriteError = -4; { Stream write error }
  127. stGetError = -5; { Get object error }
  128. stPutError = -6; { Put object error }
  129. stSeekError = -7; { Seek error in stream }
  130. stOpenError = -8; { Error opening stream }
  131. {---------------------------------------------------------------------------}
  132. { STREAM ACCESS MODE CONSTANTS }
  133. {---------------------------------------------------------------------------}
  134. CONST
  135. stCreate = fa_Create; { Create new file }
  136. stOpenRead = fa_OpenRead; { Read access only }
  137. stOpenWrite = fa_OpenWrite; { Write access only }
  138. stOpen = fa_Open; { Read/write access }
  139. {---------------------------------------------------------------------------}
  140. { TCollection ERROR CODES }
  141. {---------------------------------------------------------------------------}
  142. CONST
  143. coIndexError = -1; { Index out of range }
  144. coOverflow = -2; { Overflow }
  145. {---------------------------------------------------------------------------}
  146. { VMT HEADER CONSTANT - HOPEFULLY WE CAN DROP THIS LATER }
  147. {---------------------------------------------------------------------------}
  148. {$IFDEF PPC_Virtual} { Virtual is different }
  149. CONST
  150. vmtHeaderSize = 12; { VMT header size }
  151. {$ELSE}
  152. CONST
  153. vmtHeaderSize = 8; { VMT header size }
  154. {$ENDIF}
  155. {---------------------------------------------------------------------------}
  156. { MAXIUM DATA SIZES }
  157. {---------------------------------------------------------------------------}
  158. CONST
  159. MaxCollectionSize = 65520 DIV SizeOf(Pointer); { Max collection size }
  160. {***************************************************************************}
  161. { PUBLIC TYPE DEFINITIONS }
  162. {***************************************************************************}
  163. {---------------------------------------------------------------------------}
  164. { CHARACTER SET }
  165. {---------------------------------------------------------------------------}
  166. TYPE
  167. TCharSet = SET Of Char; { Character set }
  168. PCharSet = ^TCharSet; { Character set ptr }
  169. {---------------------------------------------------------------------------}
  170. { POINTER TO STRING }
  171. {---------------------------------------------------------------------------}
  172. TYPE
  173. PString = ^String; { String pointer }
  174. {---------------------------------------------------------------------------}
  175. { DOS FILENAME STRING }
  176. {---------------------------------------------------------------------------}
  177. TYPE
  178. {$IFDEF OS_DOS} { DOS/DPMI DEFINE }
  179. FNameStr = String[79]; { DOS filename }
  180. {$ENDIF}
  181. {$IFDEF OS_WINDOWS} { WIN/NT DEFINE }
  182. FNameStr = PChar; { Windows filename }
  183. {$ENDIF}
  184. {$IFDEF OS_OS2} { OS2 DEFINE }
  185. FNameStr = String; { OS2 filename }
  186. {$ENDIF}
  187. {$IFDEF OS_LINUX} { LINUX DEFINE }
  188. FNameStr = String; { Linux filename }
  189. {$ENDIF}
  190. {$IFDEF OS_AMIGA} { AMIGA DEFINE }
  191. FNameStr = String; { Amiga filename }
  192. {$ENDIF}
  193. {$IFDEF OS_ATARI} { ATARI DEFINE }
  194. FNameStr = String[79]; { Atari filename }
  195. {$ENDIF}
  196. {$IFDEF OS_MAC} { MACINTOSH DEFINE }
  197. FNameStr = String; { Mac filename }
  198. {$ENDIF}
  199. {---------------------------------------------------------------------------}
  200. { FILE HANDLE SIZE }
  201. {---------------------------------------------------------------------------}
  202. TYPE
  203. {$IFDEF OS_DOS} { DOS DEFINITION }
  204. THandle = Integer; { Handles are 16 bits }
  205. {$ENDIF}
  206. {$IFDEF OS_ATARI} { ATARI DEFINITION }
  207. THandle = Integer; { Handles are 16 bits }
  208. {$ENDIF}
  209. {$IFDEF OS_LINUX} { LINUX DEFINITIONS }
  210. { values are words, though the OS calls return 32-bit values }
  211. { to check (CEC) }
  212. THandle = LongInt; { Simulated 32 bits }
  213. {$ENDIF}
  214. {$IFDEF OS_AMIGA} { AMIGA DEFINITIONS }
  215. THandle = LongInt; { Handles are 32 bits }
  216. {$ENDIF}
  217. {$IFDEF OS_WINDOWS} { WIN/NT DEFINITIONS }
  218. THandle = sw_Integer; { Can be either }
  219. {$ENDIF}
  220. {$IFDEF OS_OS2} { OS2 DEFINITIONS }
  221. THandle = sw_Integer; { Can be either }
  222. {$ENDIF}
  223. {$IFDEF OS_MAC} { MACINTOSH DEFINITIONS }
  224. THandle = LongInt; { Handles are 32 bits }
  225. {$ENDIF}
  226. {***************************************************************************}
  227. { PUBLIC RECORD DEFINITIONS }
  228. {***************************************************************************}
  229. {---------------------------------------------------------------------------}
  230. { TYPE CONVERSION RECORDS }
  231. {---------------------------------------------------------------------------}
  232. TYPE
  233. WordRec = PACKED RECORD
  234. Lo, Hi: Byte; { Word to bytes }
  235. END;
  236. LongRec = PACKED RECORD
  237. Lo, Hi: Word; { LongInt to words }
  238. END;
  239. PtrRec = PACKED RECORD
  240. Ofs, Seg: Word; { Pointer to words }
  241. END;
  242. {---------------------------------------------------------------------------}
  243. { TStreamRec RECORD - STREAM OBJECT RECORD }
  244. {---------------------------------------------------------------------------}
  245. TYPE
  246. PStreamRec = ^TStreamRec; { Stream record ptr }
  247. TStreamRec = PACKED RECORD
  248. ObjType: Word; { Object type id }
  249. {$IFDEF BP_VmtLink}
  250. VmtLink: Sw_Word; { VMT link like BP }
  251. {$ELSE}
  252. VmtLink: Pointer; { Delphi3/FPC like VMT }
  253. {$ENDIF}
  254. Load : Pointer; { Object load code }
  255. Store: Pointer; { Object store code }
  256. Next : PStreamRec; { Next stream record }
  257. END;
  258. {***************************************************************************}
  259. { PUBLIC OBJECT DEFINITIONS }
  260. {***************************************************************************}
  261. {---------------------------------------------------------------------------}
  262. { TPoint OBJECT - POINT OBJECT }
  263. {---------------------------------------------------------------------------}
  264. TYPE
  265. TPoint = OBJECT
  266. X, Y: Integer;
  267. END;
  268. PPoint = ^TPoint;
  269. {---------------------------------------------------------------------------}
  270. { TRect OBJECT - RECTANGLE OBJECT }
  271. {---------------------------------------------------------------------------}
  272. TRect = OBJECT
  273. A, B: TPoint; { Corner points }
  274. FUNCTION Empty: Boolean;
  275. FUNCTION Equals (R: TRect): Boolean;
  276. FUNCTION Contains (P: TPoint): Boolean;
  277. PROCEDURE Copy (R: TRect);
  278. PROCEDURE Union (R: TRect);
  279. PROCEDURE Intersect (R: TRect);
  280. PROCEDURE Move (ADX, ADY: Integer);
  281. PROCEDURE Grow (ADX, ADY: Integer);
  282. PROCEDURE Assign (XA, YA, XB, YB: Integer);
  283. END;
  284. PRect = ^TRect;
  285. {---------------------------------------------------------------------------}
  286. { TObject OBJECT - BASE ANCESTOR OBJECT }
  287. {---------------------------------------------------------------------------}
  288. TYPE
  289. TObject = OBJECT
  290. CONSTRUCTOR Init;
  291. PROCEDURE Free;
  292. DESTRUCTOR Done; Virtual;
  293. END;
  294. PObject = ^TObject;
  295. { ******************************* REMARK ****************************** }
  296. { Two new virtual methods have been added to the object in the form of }
  297. { Close and Open. The main use here is in the Disk Based Descendants }
  298. { the calls open and close the given file so these objects can be }
  299. { used like standard files. Two new fields have also been added to }
  300. { speed up seeks on descendants. All existing code will compile and }
  301. { work completely normally oblivious to these new methods and fields. }
  302. { ****************************** END REMARK *** Leon de Boer, 15May96 * }
  303. {---------------------------------------------------------------------------}
  304. { TStream OBJECT - STREAM ANCESTOR OBJECT }
  305. {---------------------------------------------------------------------------}
  306. TYPE
  307. TStream = OBJECT (TObject)
  308. Status : Integer; { Stream status }
  309. ErrorInfo : Integer; { Stream error info }
  310. StreamSize: LongInt; { Stream current size }
  311. Position : LongInt; { Current position }
  312. FUNCTION Get: PObject;
  313. FUNCTION StrRead: PChar;
  314. FUNCTION GetPos: LongInt; Virtual;
  315. FUNCTION GetSize: LongInt; Virtual;
  316. FUNCTION ReadStr: PString;
  317. PROCEDURE Open (OpenMode: Word); Virtual;
  318. PROCEDURE Close; Virtual;
  319. PROCEDURE Reset;
  320. PROCEDURE Flush; Virtual;
  321. PROCEDURE Truncate; Virtual;
  322. PROCEDURE Put (P: PObject);
  323. PROCEDURE StrWrite (P: PChar);
  324. PROCEDURE WriteStr (P: PString);
  325. PROCEDURE Seek (Pos: LongInt); Virtual;
  326. PROCEDURE Error (Code, Info: Integer); Virtual;
  327. PROCEDURE Read (Var Buf; Count: Word); Virtual;
  328. PROCEDURE Write (Var Buf; Count: Word); Virtual;
  329. PROCEDURE CopyFrom (Var S: TStream; Count: LongInt);
  330. END;
  331. PStream = ^TStream;
  332. { ******************************* REMARK ****************************** }
  333. { A few minor changes to this object and an extra field added called }
  334. { FName which holds an AsciiZ array of the filename this allows the }
  335. { streams file to be opened and closed like a normal text file. All }
  336. { existing code should work without any changes. }
  337. { ****************************** END REMARK *** Leon de Boer, 19May96 * }
  338. {---------------------------------------------------------------------------}
  339. { TDosStream OBJECT - DOS FILE STREAM OBJECT }
  340. {---------------------------------------------------------------------------}
  341. TYPE
  342. TDosStream = OBJECT (TStream)
  343. Handle: THandle; { DOS file handle }
  344. FName : AsciiZ; { AsciiZ filename }
  345. CONSTRUCTOR Init (FileName: FNameStr; Mode: Word);
  346. DESTRUCTOR Done; Virtual;
  347. PROCEDURE Close; Virtual;
  348. PROCEDURE Truncate; Virtual;
  349. PROCEDURE Seek (Pos: LongInt); Virtual;
  350. PROCEDURE Open (OpenMode: Word); Virtual;
  351. PROCEDURE Read (Var Buf; Count: Word); Virtual;
  352. PROCEDURE Write (Var Buf; Count: Word); Virtual;
  353. END;
  354. PDosStream = ^TDosStream;
  355. { ******************************* REMARK ****************************** }
  356. { A few minor changes to this object and an extra field added called }
  357. { lastmode which holds the read or write condition last using the }
  358. { speed up buffer which helps speed up the flush, position and size }
  359. { functions. All existing code should work without any changes. }
  360. { ****************************** END REMARK *** Leon de Boer, 19May96 * }
  361. {---------------------------------------------------------------------------}
  362. { TBufStream OBJECT - BUFFERED DOS FILE STREAM }
  363. {---------------------------------------------------------------------------}
  364. TYPE
  365. TBufStream = OBJECT (TDosStream)
  366. LastMode: Byte; { Last buffer mode }
  367. BufSize : Word; { Buffer size }
  368. BufPtr : Word; { Buffer start }
  369. BufEnd : Word; { Buffer end }
  370. Buffer : PByteArray; { Buffer allocated }
  371. CONSTRUCTOR Init (FileName: FNameStr; Mode, Size: Word);
  372. DESTRUCTOR Done; Virtual;
  373. PROCEDURE Close; Virtual;
  374. PROCEDURE Flush; Virtual;
  375. PROCEDURE Truncate; Virtual;
  376. PROCEDURE Seek (Pos: LongInt); Virtual;
  377. PROCEDURE Open (OpenMode: Word); Virtual;
  378. PROCEDURE Read (Var Buf; Count: Word); Virtual;
  379. PROCEDURE Write (Var Buf; Count: Word); Virtual;
  380. END;
  381. PBufStream = ^TBufStream;
  382. { ******************************* REMARK ****************************** }
  383. { All the changes here should be completely transparent to existing }
  384. { code. Basically the memory blocks do not have to be base segments }
  385. { but this means our list becomes memory blocks rather than segments. }
  386. { The stream will also expand like the other standard streams!! }
  387. { ****************************** END REMARK *** Leon de Boer, 19May96 * }
  388. {---------------------------------------------------------------------------}
  389. { TMemoryStream OBJECT - MEMORY STREAM OBJECT }
  390. {---------------------------------------------------------------------------}
  391. TYPE
  392. TMemoryStream = OBJECT (TStream)
  393. BlkCount: Word; { Number of segments }
  394. BlkSize : Word; { Memory block size }
  395. MemSize : LongInt; { Memory alloc size }
  396. BlkList : PPointerArray; { Memory block list }
  397. CONSTRUCTOR Init (ALimit: LongInt; ABlockSize: Word);
  398. DESTRUCTOR Done; Virtual;
  399. PROCEDURE Truncate; Virtual;
  400. PROCEDURE Read (Var Buf; Count: Word); Virtual;
  401. PROCEDURE Write (Var Buf; Count: Word); Virtual;
  402. PRIVATE
  403. FUNCTION ChangeListSize (ALimit: Word): Boolean;
  404. END;
  405. PMemoryStream = ^TMemoryStream;
  406. { ******************************* REMARK ****************************** }
  407. { This object under all but real mode DOS is simple a TMemoryStream }
  408. { by another name. Under real mode DOS programs it copies the standard }
  409. { standard EMS stream object as per Borland's original unit. }
  410. { ****************************** END REMARK *** Leon de Boer, 14Aug98 * }
  411. {---------------------------------------------------------------------------}
  412. { TEmsStream OBJECT - EMS STREAM OBJECT }
  413. {---------------------------------------------------------------------------}
  414. TYPE
  415. {$IFDEF PROC_Real} { DOS REAL MODE CODE }
  416. TEmsStream = OBJECT (TStream)
  417. Handle : Word; { EMS handle }
  418. PageCount: Word; { Pages allocated }
  419. MemSize : LongInt; { EMS alloc size }
  420. CONSTRUCTOR Init (MinSize, MaxSize: LongInt);
  421. DESTRUCTOR Done; Virtual;
  422. PROCEDURE Truncate; Virtual;
  423. PROCEDURE Read (Var Buf; Count: Word); Virtual;
  424. PROCEDURE Write (Var Buf; Count: Word); Virtual;
  425. END;
  426. {$ELSE} { DPMI/WIN/OS2 CODE }
  427. TEmsStream = OBJECT (TMemoryStream) { Memory stream object }
  428. CONSTRUCTOR Init (MinSize, MaxSize: LongInt);
  429. END;
  430. {$ENDIF}
  431. PEmsStream = ^TEmsStream; { EMS stream pointer }
  432. { ******************************* REMARK ****************************** }
  433. { This object under all but real mode DOS is simple a TMemoryStream }
  434. { by another name. Under real mode DOS programs it is a copy of the }
  435. { EMS stream object but using XMS, it can replace use of TEMSStream. }
  436. { ****************************** END REMARK *** Leon de Boer, 14Aug98 * }
  437. {---------------------------------------------------------------------------}
  438. { TXmsStream OBJECT - XMS STREAM OBJECT }
  439. {---------------------------------------------------------------------------}
  440. TYPE
  441. {$IFDEF PROC_Real} { DOS REAL MODE CODE }
  442. TXmsStream = OBJECT (TStream)
  443. Handle : Word; { XMS handle number }
  444. BlocksUsed: Word; { XMS blocks in use }
  445. MemSize : LongInt; { XMS alloc size }
  446. CONSTRUCTOR Init (MinSize, MaxSize: LongInt);
  447. DESTRUCTOR Done; Virtual;
  448. PROCEDURE Truncate; Virtual;
  449. PROCEDURE Read (Var Buf; Count: Word); Virtual;
  450. PROCEDURE Write (Var Buf; Count: Word); Virtual;
  451. END;
  452. {$ELSE} { DPMI/WIN/NT/OS2 CODE }
  453. TXmsStream = OBJECT (TMemoryStream) { Memory stream object }
  454. CONSTRUCTOR Init (MinSize, MaxSize: LongInt);
  455. END;
  456. {$ENDIF}
  457. PXmsStream = ^TXmsStream; { XMS stream pointer }
  458. TYPE
  459. TItemList = Array [0..MaxCollectionSize - 1] Of Pointer;
  460. PItemList = ^TItemList;
  461. { ******************************* REMARK ****************************** }
  462. { The changes here look worse than they are. The Sw_Integer simply }
  463. { switches between Integers and LongInts if switched between 16 and 32 }
  464. { bit code. All existing code will compile without any changes. }
  465. { ****************************** END REMARK *** Leon de Boer, 10May96 * }
  466. {---------------------------------------------------------------------------}
  467. { TCollection OBJECT - COLLECTION ANCESTOR OBJECT }
  468. {---------------------------------------------------------------------------}
  469. TCollection = OBJECT (TObject)
  470. Items: PItemList; { Item list pointer }
  471. Count: Integer; { Item count }
  472. Limit: Integer; { Item limit count }
  473. Delta: Integer; { Inc delta size }
  474. CONSTRUCTOR Init (ALimit, ADelta: Integer);
  475. CONSTRUCTOR Load (Var S: TStream);
  476. DESTRUCTOR Done; Virtual;
  477. FUNCTION At (Index: Integer): Pointer;
  478. FUNCTION IndexOf (Item: Pointer): Integer; Virtual;
  479. FUNCTION GetItem (Var S: TStream): Pointer; Virtual;
  480. FUNCTION LastThat (Test: Pointer): Pointer;
  481. FUNCTION FirstThat (Test: Pointer): Pointer;
  482. PROCEDURE Pack;
  483. PROCEDURE FreeAll;
  484. PROCEDURE DeleteAll;
  485. PROCEDURE Free (Item: Pointer);
  486. PROCEDURE Insert (Item: Pointer); Virtual;
  487. PROCEDURE Delete (Item: Pointer);
  488. PROCEDURE AtFree (Index: Integer);
  489. PROCEDURE FreeItem (Item: Pointer); Virtual;
  490. PROCEDURE AtDelete (Index: Integer);
  491. PROCEDURE ForEach (Action: Pointer);
  492. PROCEDURE SetLimit (ALimit: Integer); Virtual;
  493. PROCEDURE Error (Code, Info: Integer); Virtual;
  494. PROCEDURE AtPut (Index: Integer; Item: Pointer);
  495. PROCEDURE AtInsert (Index: Integer; Item: Pointer);
  496. PROCEDURE Store (Var S: TStream);
  497. PROCEDURE PutItem (Var S: TStream; Item: Pointer); Virtual;
  498. END;
  499. PCollection = ^TCollection;
  500. {---------------------------------------------------------------------------}
  501. { TSortedCollection OBJECT - SORTED COLLECTION ANCESTOR }
  502. {---------------------------------------------------------------------------}
  503. TYPE
  504. TSortedCollection = OBJECT (TCollection)
  505. Duplicates: Boolean; { Duplicates flag }
  506. CONSTRUCTOR Init (ALimit, ADelta: Integer);
  507. CONSTRUCTOR Load (Var S: TStream);
  508. FUNCTION KeyOf (Item: Pointer): Pointer; Virtual;
  509. FUNCTION IndexOf (Item: Pointer): Integer; Virtual;
  510. FUNCTION Compare (Key1, Key2: Pointer): Integer; Virtual;
  511. FUNCTION Search (Key: Pointer; Var Index: Integer): Boolean; Virtual;
  512. PROCEDURE Insert (Item: Pointer); Virtual;
  513. PROCEDURE Store (Var S: TStream);
  514. END;
  515. PSortedCollection = ^TSortedCollection;
  516. {---------------------------------------------------------------------------}
  517. { TStringCollection OBJECT - STRING COLLECTION OBJECT }
  518. {---------------------------------------------------------------------------}
  519. TYPE
  520. TStringCollection = OBJECT (TSortedCollection)
  521. FUNCTION GetItem (Var S: TStream): Pointer; Virtual;
  522. FUNCTION Compare (Key1, Key2: Pointer): Integer; Virtual;
  523. PROCEDURE FreeItem (Item: Pointer); Virtual;
  524. PROCEDURE PutItem (Var S: TStream; Item: Pointer); Virtual;
  525. END;
  526. PStringCollection = ^TStringCollection;
  527. {---------------------------------------------------------------------------}
  528. { TStrCollection OBJECT - STRING COLLECTION OBJECT }
  529. {---------------------------------------------------------------------------}
  530. TYPE
  531. TStrCollection = OBJECT (TSortedCollection)
  532. FUNCTION Compare (Key1, Key2: Pointer): Integer; Virtual;
  533. FUNCTION GetItem (Var S: TStream): Pointer; Virtual;
  534. PROCEDURE FreeItem (Item: Pointer); Virtual;
  535. PROCEDURE PutItem (Var S: TStream; Item: Pointer); Virtual;
  536. END;
  537. PStrCollection = ^TStrCollection;
  538. { ******************************* REMARK ****************************** }
  539. { This is a completely >> NEW << object which holds a collection of }
  540. { strings but does not alphabetically sort them. It is a very useful }
  541. { object for insert ordered list boxes! }
  542. { ****************************** END REMARK *** Leon de Boer, 15May96 * }
  543. {---------------------------------------------------------------------------}
  544. { TUnSortedStrCollection - UNSORTED STRING COLLECTION OBJECT }
  545. {---------------------------------------------------------------------------}
  546. TYPE
  547. TUnSortedStrCollection = OBJECT (TStringCollection)
  548. PROCEDURE Insert (Item: Pointer); Virtual;
  549. END;
  550. PUnSortedStrCollection = ^TUnSortedStrCollection;
  551. {---------------------------------------------------------------------------}
  552. { TResourceCollection OBJECT - RESOURCE COLLECTION OBJECT }
  553. {---------------------------------------------------------------------------}
  554. TYPE
  555. TResourceCollection = OBJECT (TStringCollection)
  556. FUNCTION KeyOf (Item: Pointer): Pointer; Virtual;
  557. FUNCTION GetItem (Var S: TStream): Pointer; Virtual;
  558. PROCEDURE FreeItem (Item: Pointer); Virtual;
  559. PROCEDURE PutItem (Var S: TStream; Item: Pointer); Virtual;
  560. END;
  561. PResourceCollection = ^TResourceCollection;
  562. {---------------------------------------------------------------------------}
  563. { TResourceFile OBJECT - RESOURCE FILE OBJECT }
  564. {---------------------------------------------------------------------------}
  565. TYPE
  566. TResourceFile = OBJECT (TObject)
  567. Stream : PStream; { File as a stream }
  568. Modified: Boolean; { Modified flag }
  569. CONSTRUCTOR Init (AStream: PStream);
  570. DESTRUCTOR Done; Virtual;
  571. FUNCTION Count: Integer;
  572. FUNCTION KeyAt (I: Integer): String;
  573. FUNCTION Get (Key: String): PObject;
  574. FUNCTION SwitchTo (AStream: PStream; Pack: Boolean): PStream;
  575. PROCEDURE Flush;
  576. PROCEDURE Delete (Key: String);
  577. PROCEDURE Put (Item: PObject; Key: String);
  578. PRIVATE
  579. BasePos: LongInt; { Base position }
  580. IndexPos: LongInt; { Index position }
  581. Index: TResourceCollection; { Index collection }
  582. END;
  583. PResourceFile = ^TResourceFile;
  584. TYPE
  585. TStrIndexRec = PACKED RECORD Key, Count, Offset: Word; END;
  586. TStrIndex = Array [0..9999] Of TStrIndexRec;
  587. PStrIndex = ^TStrIndex;
  588. {---------------------------------------------------------------------------}
  589. { TStringList OBJECT - STRING LIST OBJECT }
  590. {---------------------------------------------------------------------------}
  591. TStringList = OBJECT (TObject)
  592. CONSTRUCTOR Load (Var S: TStream);
  593. DESTRUCTOR Done; Virtual;
  594. FUNCTION Get (Key: Word): String;
  595. PRIVATE
  596. Stream : PStream;
  597. BasePos : LongInt;
  598. IndexSize: Sw_Word;
  599. Index : PStrIndex;
  600. PROCEDURE ReadStr (Var S: String; Offset, Skip: Word);
  601. END;
  602. PStringList = ^TStringList;
  603. {---------------------------------------------------------------------------}
  604. { TStrListMaker OBJECT - RESOURCE FILE OBJECT }
  605. {---------------------------------------------------------------------------}
  606. TYPE
  607. TStrListMaker = OBJECT (TObject)
  608. CONSTRUCTOR Init (AStrSize, AIndexSize: Word);
  609. DESTRUCTOR Done; Virtual;
  610. PROCEDURE Put (Key: Word; S: String);
  611. PROCEDURE Store (Var S: TStream);
  612. PRIVATE
  613. StrPos : Sw_Word;
  614. StrSize : Sw_Word;
  615. Strings : PByteArray;
  616. IndexPos : Sw_Word;
  617. IndexSize: Sw_Word;
  618. Index : PStrIndex;
  619. Cur : TStrIndexRec;
  620. PROCEDURE CloseCurrent;
  621. END;
  622. PStrListMaker = ^TStrListMaker;
  623. {***************************************************************************}
  624. { INTERFACE ROUTINES }
  625. {***************************************************************************}
  626. {+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++}
  627. { STREAM INTERFACE ROUTINES }
  628. {+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++}
  629. {-Abstract-----------------------------------------------------------
  630. Terminates program with a run-time error 211. When implementing
  631. an abstract object type, call Abstract in those virtual methods that
  632. must be overridden in descendant types. This ensures that any
  633. attempt to use instances of the abstract object type will fail.
  634. 12Jun96 LdB
  635. ---------------------------------------------------------------------}
  636. PROCEDURE Abstract;
  637. {-RegisterObjects----------------------------------------------------
  638. Registers the three standard objects TCollection, TStringCollection
  639. and TStrCollection.
  640. 02Sep97 LdB
  641. ---------------------------------------------------------------------}
  642. PROCEDURE RegisterObjects;
  643. {-RegisterType-------------------------------------------------------
  644. Registers the given object type with Free Vision's streams, creating
  645. a list of known objects. Streams can only store and return these known
  646. object types. Each registered object needs a unique stream registration
  647. record, of type TStreamRec.
  648. 02Sep97 LdB
  649. ---------------------------------------------------------------------}
  650. PROCEDURE RegisterType (Var S: TStreamRec);
  651. {+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++}
  652. { GENERAL FUNCTION INTERFACE ROUTINES }
  653. {+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++}
  654. {-LongMul------------------------------------------------------------
  655. Returns the long integer value of X * Y integer values.
  656. 10Feb98 LdB
  657. ---------------------------------------------------------------------}
  658. FUNCTION LongMul (X, Y: Integer): LongInt;
  659. {-LongDiv------------------------------------------------------------
  660. Returns the integer value of long integer X divided by integer Y.
  661. 10Feb98 LdB
  662. ---------------------------------------------------------------------}
  663. FUNCTION LongDiv (X: LongInt; Y: Integer): Integer;
  664. {+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++}
  665. { DYNAMIC STRING INTERFACE ROUTINES }
  666. {+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++}
  667. {-NewStr-------------------------------------------------------------
  668. Allocates a dynamic string into memory. If S is nil, NewStr returns
  669. a nil pointer, otherwise NewStr allocates Length(S)+1 bytes of memory
  670. containing a copy of S, and returns a pointer to the string.
  671. 12Jun96 LdB
  672. ---------------------------------------------------------------------}
  673. FUNCTION NewStr (S: String): PString;
  674. {-DisposeStr---------------------------------------------------------
  675. Disposes of a PString allocated by the function NewStr.
  676. 12Jun96 LdB
  677. ---------------------------------------------------------------------}
  678. PROCEDURE DisposeStr (P: PString);
  679. {***************************************************************************}
  680. { PUBLIC INITIALIZED VARIABLES }
  681. {***************************************************************************}
  682. {---------------------------------------------------------------------------}
  683. { INITIALIZED DOS/DPMI/WIN/NT/OS2 PUBLIC VARIABLES }
  684. {---------------------------------------------------------------------------}
  685. CONST
  686. StreamError : Pointer = Nil; { Stream error ptr }
  687. {+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++}
  688. { STREAM REGISTRATION RECORDS }
  689. {+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++}
  690. {---------------------------------------------------------------------------}
  691. { TCollection STREAM REGISTRATION }
  692. {---------------------------------------------------------------------------}
  693. CONST
  694. RCollection: TStreamRec = (
  695. ObjType: 50; { Register id = 50 }
  696. {$IFDEF BP_VMTLink}
  697. VmtLink: Ofs(TypeOf(TCollection)^); { BP style VMT link }
  698. {$ELSE}
  699. VmtLink: TypeOf(TCollection); { Alt style VMT link }
  700. {$ENDIF}
  701. Load: @TCollection.Load; { Object load method }
  702. Store: @TCollection.Store); { Object store method }
  703. {---------------------------------------------------------------------------}
  704. { TStringCollection STREAM REGISTRATION }
  705. {---------------------------------------------------------------------------}
  706. CONST
  707. RStringCollection: TStreamRec = (
  708. ObjType: 51; { Register id = 51 }
  709. {$IFDEF BP_VMTLink}
  710. VmtLink: Ofs(TypeOf(TStringCollection)^); { BP style VMT link }
  711. {$ELSE}
  712. VmtLink: TypeOf(TStringCollection); { Alt style VMT link }
  713. {$ENDIF}
  714. Load: @TStringCollection.Load; { Object load method }
  715. Store: @TStringCollection.Store); { Object store method }
  716. {---------------------------------------------------------------------------}
  717. { TStrCollection STREAM REGISTRATION }
  718. {---------------------------------------------------------------------------}
  719. CONST
  720. RStrCollection: TStreamRec = (
  721. ObjType: 69; { Register id = 69 }
  722. {$IFDEF BP_VMTLink}
  723. VmtLink: Ofs(TypeOf(TStrCollection)^); { BP style VMT link }
  724. {$ELSE}
  725. VmtLink: TypeOf(TStrCollection); { Alt style VMT link }
  726. {$ENDIF}
  727. Load: @TStrCollection.Load; { Object load method }
  728. Store: @TStrCollection.Store); { Object store method }
  729. {---------------------------------------------------------------------------}
  730. { TStringList STREAM REGISTRATION }
  731. {---------------------------------------------------------------------------}
  732. CONST
  733. RStringList: TStreamRec = (
  734. ObjType: 52; { Register id = 52 }
  735. {$IFDEF BP_VMTLink}
  736. VmtLink: Ofs(TypeOf(TStringList)^); { BP style VMT link }
  737. {$ELSE}
  738. VmtLink: TypeOf(TStringList); { Alt style VMT link }
  739. {$ENDIF}
  740. Load: @TStringList.Load; { Object load method }
  741. Store: Nil); { No store method }
  742. {---------------------------------------------------------------------------}
  743. { TStrListMaker STREAM REGISTRATION }
  744. {---------------------------------------------------------------------------}
  745. CONST
  746. RStrListMaker: TStreamRec = (
  747. ObjType: 52; { Register id = 52 }
  748. {$IFDEF BP_VMTLink}
  749. VmtLink: Ofs(TypeOf(TStrListMaker)^); { BP style VMT link }
  750. {$ELSE}
  751. VmtLink: TypeOf(TStrListMaker); { Alt style VMT link }
  752. {$ENDIF}
  753. Load: Nil; { No load method }
  754. Store: @TStrListMaker.Store); { Object store method }
  755. {<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>}
  756. IMPLEMENTATION
  757. {<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>}
  758. {$IFDEF PROC_Real} { DOS REAL MODE CODE }
  759. USES XMSUnit, EMSUnit; { Needs these units }
  760. {$ENDIF}
  761. {$IFNDEF PROC_Real} { NOT DOS REAL CODE }
  762. {$DEFINE NewExeFormat} { New format EXE }
  763. {$ENDIF}
  764. {$IFDEF OS_OS2} { OS2 COMPILERS }
  765. {$IFDEF PPC_Virtual} { VIRTUAL PASCAL UNITS }
  766. USES OS2Base; { Standard unit }
  767. {$ENDIF}
  768. {$IFDEF PPC_Speed} { SPEED PASCAL UNITS }
  769. USES BseDos, Os2Def; { Standard units }
  770. {$ENDIF}
  771. {$IFDEF PPC_BPOS2} { C'T PATCH TO BP UNITS }
  772. USES DosTypes, DosProcs; { Standard units }
  773. TYPE FILEFINDBUF = TFILEFINDBUF; { Type correction }
  774. {$ENDIF}
  775. {$ENDIF}
  776. {***************************************************************************}
  777. { PRIVATE TYPE DEFINITIONS }
  778. {***************************************************************************}
  779. {---------------------------------------------------------------------------}
  780. { FRAME POINTER SIZE SWITCH TYPE }
  781. {---------------------------------------------------------------------------}
  782. TYPE
  783. FramePointer = sw_Word; { Frame pointer }
  784. { ******************************* REMARK ****************************** }
  785. { This TYPECAST is serverely COMPILER SPECIFIC if you have a different }
  786. { compiler you will probably have to work this out. }
  787. { ****************************** END REMARK *** Leon de Boer, 08Jul99 * }
  788. {---------------------------------------------------------------------------}
  789. { POINTER LOCAl FUNCTION DEFINITION SWITCH }
  790. {---------------------------------------------------------------------------}
  791. TYPE
  792. {$IFDEF PPC_VIRTUAL} { VIRTUAL PASCAL }
  793. FuncCallPtr = FUNCTION (Param1: Pointer): Boolean;
  794. {$ELSE} { OTHER COMPILERS }
  795. {$IFNDEF PPC_FPC} { NON FPC COMPILERS }
  796. FuncCallPtr = FUNCTION (Param1: Pointer; _EBP: FramePointer): Boolean;
  797. {$ELSE} { FPC COMPILER }
  798. FuncCallPtr = FUNCTION (_EBP: FramePointer; Param1: Pointer): Boolean;
  799. {$ENDIF}
  800. {$ENDIF}
  801. {***************************************************************************}
  802. { PRIVATE INITIALIZED VARIABLES }
  803. {***************************************************************************}
  804. {---------------------------------------------------------------------------}
  805. { INITIALIZED DOS/DPMI/WIN/NT/OS2 PRIVATE VARIABLES }
  806. {---------------------------------------------------------------------------}
  807. CONST
  808. StreamTypes: PStreamRec = Nil; { Stream types reg }
  809. {***************************************************************************}
  810. { PRIVATE INTERNAL ROUTINES }
  811. {***************************************************************************}
  812. {+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++}
  813. { PRIVATE INTERNAL DOS/DPMI/WIN/NT/OS2 ROUTINES }
  814. {+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++}
  815. { ******************************* REMARK ****************************** }
  816. { This routine is serverely COMPILER SPECIFIC if you have a different }
  817. { compiler you will probably have to work this out. }
  818. { ****************************** END REMARK *** Leon de Boer, 08Jul99 * }
  819. {---------------------------------------------------------------------------}
  820. { PrevFramePtr -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 08Jul99 LdB }
  821. {---------------------------------------------------------------------------}
  822. FUNCTION PrevFramePtr: FramePointer; ASSEMBLER;
  823. {$IFNDEF PPC_FPC} { NON FPC COMPILER }
  824. ASM
  825. {$IFDEF BIT_16} { 16 BIT CODE }
  826. MOV AX, [BP]; { Load AX from BP }
  827. {$IFDEF OS_WINDOWS} { WIN 16 BIT CODE }
  828. AND AL, 0FEH; { Windows make even }
  829. {$ENDIF}
  830. {$IFDEF OS_OS2} { OS2 16 BIT CODE }
  831. AND AL, 0FEH; { OS2 make even }
  832. {$ENDIF}
  833. {$ENDIF}
  834. {$IFDEF BIT_32} { 32 BIT CODE }
  835. MOV EAX, [EBP]; { Get previous frame }
  836. {$ENDIF}
  837. END;
  838. {$ELSE} { FPC COMPILER }
  839. ASM
  840. {$IFDEF i386} { 80x PROCESSOR }
  841. MOVL (%EBP), %EAX; { Get previous frame }
  842. {$ENDIF}
  843. {$IFDEF m68k} { 68x PROCESSOR }
  844. MOVE.L A6, D0; { Get previous frame }
  845. {$ENDIF}
  846. END ['EAX'];
  847. {$ENDIF}
  848. { ******************************* REMARK ****************************** }
  849. { This routine is serverely COMPILER SPECIFIC if you have a different }
  850. { compiler you will probably have to work this out. }
  851. { ****************************** END REMARK *** Leon de Boer, 08Jul99 * }
  852. {---------------------------------------------------------------------------}
  853. { CallPointerLocal -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 08Jul99 LdB }
  854. {---------------------------------------------------------------------------}
  855. {$IFDEF PPC_VIRTUAL} { VIRTUAL COMPILER }
  856. FUNCTION CallTestLocal (Func: Pointer; Param1: Pointer): Boolean;
  857. BEGIN
  858. CallTestLocal := FuncCallPtr(Func)(Param1); { Function call to ptr }
  859. END;
  860. {$ELSE} { OTHER COMPILERS }
  861. FUNCTION CallTestLocal (Func: Pointer; Frame: FramePointer;
  862. Param1: Pointer): Boolean;
  863. BEGIN
  864. {$IFNDEF PPC_FPC} { NON FPC COMPILERS }
  865. CallTestLocal := FuncCallPtr(Func)(Param1, Frame); { Function call to ptr }
  866. {$ELSE} { FPC COMPILER }
  867. CallTestLocal := FuncCallPtr(Func)(Frame, Param1); { Function call to ptr }
  868. {$ENDIF}
  869. END;
  870. {$ENDIF}
  871. {---------------------------------------------------------------------------}
  872. { RegisterError -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 12Jun96 LdB }
  873. {---------------------------------------------------------------------------}
  874. PROCEDURE RegisterError;
  875. BEGIN
  876. RunError(212); { Register error }
  877. END;
  878. {***************************************************************************}
  879. { OBJECT METHODS }
  880. {***************************************************************************}
  881. {+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++}
  882. { TRect OBJECT METHODS }
  883. {+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++}
  884. PROCEDURE CheckEmpty (Var Rect: TRect);
  885. BEGIN
  886. With Rect Do Begin
  887. If (A.X >= B.X) OR (A.Y >= B.Y) Then Begin { Zero or reversed }
  888. A.X := 0; { Clear a.x }
  889. A.Y := 0; { Clear a.y }
  890. B.X := 0; { Clear b.x }
  891. B.Y := 0; { Clear b.y }
  892. End;
  893. End;
  894. END;
  895. {--TRect--------------------------------------------------------------------}
  896. { Empty -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 10May96 LdB }
  897. {---------------------------------------------------------------------------}
  898. FUNCTION TRect.Empty: Boolean;
  899. BEGIN
  900. Empty := (A.X >= B.X) OR (A.Y >= B.Y); { Empty result }
  901. END;
  902. {--TRect--------------------------------------------------------------------}
  903. { Equals -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 10May96 LdB }
  904. {---------------------------------------------------------------------------}
  905. FUNCTION TRect.Equals (R: TRect): Boolean;
  906. BEGIN
  907. Equals := (A.X = R.A.X) AND (A.Y = R.A.Y) AND
  908. (B.X = R.B.X) AND (B.Y = R.B.Y); { Equals result }
  909. END;
  910. {--TRect--------------------------------------------------------------------}
  911. { Contains -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 10May96 LdB }
  912. {---------------------------------------------------------------------------}
  913. FUNCTION TRect.Contains (P: TPoint): Boolean;
  914. BEGIN
  915. Contains := (P.X >= A.X) AND (P.X <= B.X) AND
  916. (P.Y >= A.Y) AND (P.Y <= B.Y); { Contains result }
  917. END;
  918. {--TRect--------------------------------------------------------------------}
  919. { Copy -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 10May96 LdB }
  920. {---------------------------------------------------------------------------}
  921. PROCEDURE TRect.Copy (R: TRect);
  922. BEGIN
  923. A := R.A; { Copy point a }
  924. B := R.B; { Copy point b }
  925. END;
  926. {--TRect--------------------------------------------------------------------}
  927. { Union -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 10May96 LdB }
  928. {---------------------------------------------------------------------------}
  929. PROCEDURE TRect.Union (R: TRect);
  930. BEGIN
  931. If (R.A.X < A.X) Then A.X := R.A.X; { Take if smaller }
  932. If (R.A.Y < A.Y) Then A.Y := R.A.Y; { Take if smaller }
  933. If (R.B.X > B.X) Then B.X := R.B.X; { Take if larger }
  934. If (R.B.Y > B.Y) Then B.Y := R.B.Y; { Take if larger }
  935. END;
  936. {--TRect--------------------------------------------------------------------}
  937. { Intersect -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 10May96 LdB }
  938. {---------------------------------------------------------------------------}
  939. PROCEDURE TRect.Intersect (R: TRect);
  940. BEGIN
  941. If (R.A.X > A.X) Then A.X := R.A.X; { Take if larger }
  942. If (R.A.Y > A.Y) Then A.Y := R.A.Y; { Take if larger }
  943. If (R.B.X < B.X) Then B.X := R.B.X; { Take if smaller }
  944. If (R.B.Y < B.Y) Then B.Y := R.B.Y; { Take if smaller }
  945. CheckEmpty(Self); { Check if empty }
  946. END;
  947. {--TRect--------------------------------------------------------------------}
  948. { Move -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 10May96 LdB }
  949. {---------------------------------------------------------------------------}
  950. PROCEDURE TRect.Move (ADX, ADY: Integer);
  951. BEGIN
  952. Inc(A.X, ADX); { Adjust A.X }
  953. Inc(A.Y, ADY); { Adjust A.Y }
  954. Inc(B.X, ADX); { Adjust B.X }
  955. Inc(B.Y, ADY); { Adjust B.Y }
  956. END;
  957. {--TRect--------------------------------------------------------------------}
  958. { Grow -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 10May96 LdB }
  959. {---------------------------------------------------------------------------}
  960. PROCEDURE TRect.Grow (ADX, ADY: Integer);
  961. BEGIN
  962. Dec(A.X, ADX); { Adjust A.X }
  963. Dec(A.Y, ADY); { Adjust A.Y }
  964. Inc(B.X, ADX); { Adjust B.X }
  965. Inc(B.Y, ADY); { Adjust B.Y }
  966. CheckEmpty(Self); { Check if empty }
  967. END;
  968. {--TRect--------------------------------------------------------------------}
  969. { Assign -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 10May96 LdB }
  970. {---------------------------------------------------------------------------}
  971. PROCEDURE TRect.Assign (XA, YA, XB, YB: Integer);
  972. BEGIN
  973. A.X := XA; { Hold A.X value }
  974. A.Y := YA; { Hold A.Y value }
  975. B.X := XB; { Hold B.X value }
  976. B.Y := YB; { Hold B.Y value }
  977. END;
  978. {+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++}
  979. { TObject OBJECT METHODS }
  980. {+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++}
  981. TYPE
  982. DummyObject = OBJECT (TObject) { Internal object }
  983. Data: RECORD END; { Helps size VMT link }
  984. END;
  985. { ******************************* REMARK ****************************** }
  986. { I Prefer this code because it self sizes VMT link rather than using a }
  987. { fixed record structure thus it should work on all compilers without a }
  988. { specific record to match each compiler. }
  989. { ****************************** END REMARK *** Leon de Boer, 10May96 * }
  990. {--TObject------------------------------------------------------------------}
  991. { Init -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 08Jul99 LdB }
  992. {---------------------------------------------------------------------------}
  993. CONSTRUCTOR TObject.Init;
  994. VAR LinkSize: LongInt; Dummy: DummyObject; P: Pointer;
  995. BEGIN
  996. LinkSize := LongInt(@Dummy.Data)-LongInt(@Dummy); { Calc VMT link size }
  997. P := Pointer(LongInt(@Self)+LinkSize); { Pointer to data }
  998. FillChar(P^, SizeOf(Self)-LinkSize, #0); { Clear data fields }
  999. END;
  1000. {--TObject------------------------------------------------------------------}
  1001. { Free -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 10May96 LdB }
  1002. {---------------------------------------------------------------------------}
  1003. PROCEDURE TObject.Free;
  1004. BEGIN
  1005. Dispose(PObject(@Self), Done); { Dispose of self }
  1006. END;
  1007. {--TObject------------------------------------------------------------------}
  1008. { Done -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 10May96 LdB }
  1009. {---------------------------------------------------------------------------}
  1010. DESTRUCTOR TObject.Done;
  1011. BEGIN { Abstract method }
  1012. END;
  1013. {+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++}
  1014. { TStream OBJECT METHODS }
  1015. {+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++}
  1016. {--TStream------------------------------------------------------------------}
  1017. { Get -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 14Aug98 LdB }
  1018. {---------------------------------------------------------------------------}
  1019. FUNCTION TStream.Get: PObject;
  1020. TYPE LoadPtr = FUNCTION (Var S: TStream; Link: Sw_Word; Iv: Pointer): PObject;
  1021. VAR ObjType: Word; P: PStreamRec;
  1022. BEGIN
  1023. ObjType := 0; { Zero the value }
  1024. Read(ObjType, 2); { Read object type }
  1025. If (ObjType <> 0) Then Begin { Object registered }
  1026. P := StreamTypes; { Current reg list }
  1027. While (P <> Nil) AND (P^.ObjType <> ObjType) { Find object type OR }
  1028. Do P := P^.Next; { Find end of chain }
  1029. If (P = Nil) Then Begin { Not registered }
  1030. Error(stGetError, ObjType); { Obj not registered }
  1031. Get := Nil; { Return nil pointer }
  1032. End Else
  1033. {$IFDEF BP_VMTLink} { BP like VMT link }
  1034. Get := LoadPtr(P^.Load)(Self, P^.VMTLink, Nil) { Call constructor }
  1035. {$ELSE} { FPC/DELPHI3 VMT link }
  1036. Get := LoadPtr(P^.Load)(Self,
  1037. Sw_Word(P^.VMTLink^), Nil) { Call constructor }
  1038. {$ENDIF}
  1039. End Else Get := Nil; { Return nil pointer }
  1040. END;
  1041. {--TStream------------------------------------------------------------------}
  1042. { StrRead -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 10May96 LdB }
  1043. {---------------------------------------------------------------------------}
  1044. FUNCTION TStream.StrRead: PChar;
  1045. VAR W: Word; P: PChar;
  1046. BEGIN
  1047. W := 0; { Zero the value }
  1048. Read(W, 2); { Read string length }
  1049. If (W = 0) Then StrRead := Nil Else Begin { Check for empty }
  1050. If (MaxAvail >= (W+1)) Then Begin { Check avail memory }
  1051. GetMem(P, W + 1); { Allocate memory }
  1052. Read(P[0], W); { Read the data }
  1053. P[W] := #0; { Terminate with #0 }
  1054. End Else P := Nil; { Not enough memory }
  1055. StrRead := P; { PChar returned }
  1056. End;
  1057. END;
  1058. {--TStream------------------------------------------------------------------}
  1059. { ReadStr -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 06Aug98 LdB }
  1060. {---------------------------------------------------------------------------}
  1061. FUNCTION TStream.ReadStr: PString;
  1062. VAR B: Byte; P: PString;
  1063. BEGIN
  1064. Read(B, 1); { Read string length }
  1065. If (B > 0) AND (MaxAvail >= (B+1)) Then Begin { Check enough memory }
  1066. GetMem(P, B + 1); { Allocate memory }
  1067. {$IFDEF PPC_DELPHI3} { DELPHI 3+ COMPILER }
  1068. SetLength(P^, B); { Hold new length }
  1069. {$ELSE} { OTHER COMPILERS }
  1070. P^[0] := Chr(B); { Hold new length }
  1071. {$ENDIF}
  1072. Read(P^[1], B); { Read string data }
  1073. ReadStr := P; { Return string ptr }
  1074. End Else ReadStr := Nil;
  1075. END;
  1076. {--TStream------------------------------------------------------------------}
  1077. { GetPos -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 10May96 LdB }
  1078. {---------------------------------------------------------------------------}
  1079. FUNCTION TStream.GetPos: LongInt;
  1080. BEGIN
  1081. If (Status = stOk) Then GetPos := Position { Return position }
  1082. Else GetPos := -1; { Stream in error }
  1083. END;
  1084. {--TStream------------------------------------------------------------------}
  1085. { GetSize -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 10May96 LdB }
  1086. {---------------------------------------------------------------------------}
  1087. FUNCTION TStream.GetSize: LongInt;
  1088. BEGIN
  1089. If (Status = stOk) Then GetSize := StreamSize { Return stream size }
  1090. Else GetSize := -1; { Stream in error }
  1091. END;
  1092. {--TStream------------------------------------------------------------------}
  1093. { Close -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 10May96 LdB }
  1094. {---------------------------------------------------------------------------}
  1095. PROCEDURE TStream.Close;
  1096. BEGIN { Abstract method }
  1097. END;
  1098. {--TStream------------------------------------------------------------------}
  1099. { Reset -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 10May96 LdB }
  1100. {---------------------------------------------------------------------------}
  1101. PROCEDURE TStream.Reset;
  1102. BEGIN
  1103. Status := 0; { Clear status }
  1104. ErrorInfo := 0; { Clear error info }
  1105. END;
  1106. {--TStream------------------------------------------------------------------}
  1107. { Flush -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 10May96 LdB }
  1108. {---------------------------------------------------------------------------}
  1109. PROCEDURE TStream.Flush;
  1110. BEGIN { Abstract method }
  1111. END;
  1112. {--TStream------------------------------------------------------------------}
  1113. { Truncate -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 10May96 LdB }
  1114. {---------------------------------------------------------------------------}
  1115. PROCEDURE TStream.Truncate;
  1116. BEGIN
  1117. Abstract; { Abstract error }
  1118. END;
  1119. {--TStream------------------------------------------------------------------}
  1120. { Get -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 14Aug98 LdB }
  1121. {---------------------------------------------------------------------------}
  1122. PROCEDURE TStream.Put (P: PObject);
  1123. TYPE StorePtr = PROCEDURE (Var S: TStream; AnObject: PObject);
  1124. VAR ObjType: Word; Link: Sw_Word; Q: PStreamRec; VmtPtr: ^Sw_Word;
  1125. BEGIN
  1126. ObjType := 0; { Set objtype to zero }
  1127. If (P <> Nil) Then Begin { Non nil object }
  1128. VmtPtr := Pointer(P); { Xfer object to ptr }
  1129. Link := VmtPtr^; { VMT link }
  1130. If (Link <> 0) Then Begin { We have a VMT link }
  1131. Q := StreamTypes; { Current reg list }
  1132. {$IFDEF BP_VMTLink} { BP like VMT link }
  1133. While (Q <> Nil) AND (Q^.VMTLink <> Link) { Find link match OR }
  1134. {$ELSE} { FPC/DELHI3 VMT link }
  1135. While (Q <> Nil) AND (Sw_Word(Q^.VMTLink^) <>
  1136. Link) { Find link match OR }
  1137. {$ENDIF}
  1138. Do Q := Q^.Next; { Find end of chain }
  1139. If (Q = Nil) Then Begin { End of chain found }
  1140. Error(stPutError, 0); { Not registered error }
  1141. Exit; { Now exit }
  1142. End Else ObjType := Q^.ObjType; { Update object type }
  1143. End;
  1144. End;
  1145. Write(ObjType, 2); { Write object type }
  1146. If (ObjType <> 0) Then { Registered object }
  1147. StorePtr(Q^.Store)(Self, P); { Store object }
  1148. END;
  1149. {--TStream------------------------------------------------------------------}
  1150. { Seek -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 10May96 LdB }
  1151. {---------------------------------------------------------------------------}
  1152. PROCEDURE TStream.Seek (Pos: LongInt);
  1153. BEGIN
  1154. If (Status = stOk) Then Begin { Check status }
  1155. If (Pos < 0) Then Pos := 0; { Remove negatives }
  1156. If (Pos <= StreamSize) Then Position := Pos { If valid set pos }
  1157. Else Error(stSeekError, Pos); { Position error }
  1158. End;
  1159. END;
  1160. {--TStream------------------------------------------------------------------}
  1161. { StrWrite -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 10May96 LdB }
  1162. {---------------------------------------------------------------------------}
  1163. PROCEDURE TStream.StrWrite (P: PChar);
  1164. VAR W: Word; Q: PByteArray;
  1165. BEGIN
  1166. W := 0; { Preset zero size }
  1167. Q := PByteArray(P); { Transfer type }
  1168. If (Q <> Nil) Then While (Q^[W] <> 0) Do Inc(W); { PChar length }
  1169. Write(W, SizeOf(W)); { Store length }
  1170. If (P <> Nil) Then Write(P[0], W); { Write data }
  1171. END;
  1172. {--TStream------------------------------------------------------------------}
  1173. { WriteStr -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 10May96 LdB }
  1174. {---------------------------------------------------------------------------}
  1175. PROCEDURE TStream.WriteStr (P: PString);
  1176. CONST Empty: String[1] = '';
  1177. BEGIN
  1178. If (P <> Nil) Then Write(P^, Length(P^) + 1) { Write string }
  1179. Else Write(Empty, 1); { Write empty string }
  1180. END;
  1181. {--TStream------------------------------------------------------------------}
  1182. { Open -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 10May96 LdB }
  1183. {---------------------------------------------------------------------------}
  1184. PROCEDURE TStream.Open (OpenMode: Word);
  1185. BEGIN { Abstract method }
  1186. END;
  1187. {--TStream------------------------------------------------------------------}
  1188. { Error -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 10May96 LdB }
  1189. {---------------------------------------------------------------------------}
  1190. PROCEDURE TStream.Error (Code, Info: Integer);
  1191. TYPE TErrorProc = Procedure (Var S: TStream);
  1192. BEGIN
  1193. Status := Code; { Hold error code }
  1194. ErrorInfo := Info; { Hold error info }
  1195. If (StreamError <> Nil) Then
  1196. TErrorProc(StreamError)(Self); { Call error ptr }
  1197. END;
  1198. {--TStream------------------------------------------------------------------}
  1199. { Read -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 10May96 LdB }
  1200. {---------------------------------------------------------------------------}
  1201. PROCEDURE TStream.Read (Var Buf; Count: Word);
  1202. BEGIN
  1203. Abstract; { Abstract error }
  1204. END;
  1205. {--TStream------------------------------------------------------------------}
  1206. { Write -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 10May96 LdB }
  1207. {---------------------------------------------------------------------------}
  1208. PROCEDURE TStream.Write (Var Buf; Count: Word);
  1209. BEGIN
  1210. Abstract; { Abstract error }
  1211. END;
  1212. {--TStream------------------------------------------------------------------}
  1213. { CopyFrom -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 10May96 LdB }
  1214. {---------------------------------------------------------------------------}
  1215. PROCEDURE TStream.CopyFrom (Var S: TStream; Count: LongInt);
  1216. VAR W: Word; Buffer: Array[0..1023] of Byte;
  1217. BEGIN
  1218. While (Count > 0) Do Begin
  1219. If (Count > SizeOf(Buffer)) Then { To much data }
  1220. W := SizeOf(Buffer) Else W := Count; { Size to transfer }
  1221. S.Read(Buffer, W); { Read from stream }
  1222. Write(Buffer, W); { Write to stream }
  1223. Dec(Count, W); { Dec write count }
  1224. End;
  1225. END;
  1226. {+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++}
  1227. { TDosStream OBJECT METHODS }
  1228. {+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++}
  1229. {--TDosStream---------------------------------------------------------------}
  1230. { Init -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 08Jul99 LdB }
  1231. {---------------------------------------------------------------------------}
  1232. CONSTRUCTOR TDosStream.Init (FileName: FNameStr; Mode: Word);
  1233. VAR Success: Integer; {$IFDEF OS_OS2} Info: FILEFINDBUF; {$ENDIF}
  1234. BEGIN
  1235. Inherited Init; { Call ancestor }
  1236. {$IFDEF OS_WINDOWS} { WIN/NT CODE }
  1237. {$IFDEF BIT_16} { 16 BIT WINDOWS CODE }
  1238. AnsiToOEM(FileName, FName); { Ansi to OEM }
  1239. {$ENDIF}
  1240. {$IFDEF BIT_32} { 32 BIT WINDOWS CODE }
  1241. {$IFNDEF PPC_SPEED} { NON SPEED COMPILER }
  1242. CharToOEM(FileName, FName); { Ansi to OEM }
  1243. {$ELSE} { SPEEDSOFT SYBIL 2+ }
  1244. CharToOEM(CString(FileName), CString(FName)); { Ansi to OEM }
  1245. {$ENDIF}
  1246. {$ENDIF}
  1247. {$ELSE} { DOS/DPMI/OS2 CODE }
  1248. FileName := FileName+#0; { Make asciiz }
  1249. Move(FileName[1], FName, Length(FileName)); { Create asciiz name }
  1250. {$ENDIF}
  1251. Handle := FileOpen(FName, Mode); { Open the file }
  1252. If (Handle <> 0) Then Begin { Handle valid }
  1253. Success := SetFilePos(Handle, 0, 2, StreamSize); { Locate end of file }
  1254. If (Success = 0) Then
  1255. Success := SetFilePos(Handle, 0, 0, Position); { Reset to file start }
  1256. End Else Success := 103; { Open file failed }
  1257. If (Handle = 0) OR (Success <> 0) Then Begin { Open failed }
  1258. Handle := -1; { Reset invalid handle }
  1259. Error(stInitError, Success); { Call stream error }
  1260. End;
  1261. END;
  1262. {--TDosStream---------------------------------------------------------------}
  1263. { Done -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 16May96 LdB }
  1264. {---------------------------------------------------------------------------}
  1265. DESTRUCTOR TDosStream.Done;
  1266. BEGIN
  1267. If (Handle <> -1) Then FileClose(Handle); { Close the file }
  1268. Inherited Done; { Call ancestor }
  1269. END;
  1270. {--TDosStream---------------------------------------------------------------}
  1271. { Close -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 16May96 LdB }
  1272. {---------------------------------------------------------------------------}
  1273. PROCEDURE TDosStream.Close;
  1274. BEGIN
  1275. If (Handle <> -1) Then FileClose(Handle); { Close the file }
  1276. Position := 0; { Zero the position }
  1277. Handle := -1; { Handle now invalid }
  1278. END;
  1279. {--TDosStream---------------------------------------------------------------}
  1280. { Truncate -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 16May96 LdB }
  1281. {---------------------------------------------------------------------------}
  1282. PROCEDURE TDosStream.Truncate;
  1283. VAR Success: Integer;
  1284. BEGIN
  1285. If (Status = stOk) Then Begin { Check status okay }
  1286. Success := SetFileSize(Handle, Position); { Truncate file }
  1287. If (Success = 0) Then StreamSize := Position { Adjust size }
  1288. Else Error(stError, Success); { Identify error }
  1289. End;
  1290. END;
  1291. {--TDosStream---------------------------------------------------------------}
  1292. { Seek -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 16May96 LdB }
  1293. {---------------------------------------------------------------------------}
  1294. PROCEDURE TDosStream.Seek (Pos: LongInt);
  1295. VAR Success: Integer; Li: LongInt;
  1296. BEGIN
  1297. If (Status = stOk) Then Begin { Check status okay }
  1298. If (Pos < 0) Then Pos := 0; { Negatives removed }
  1299. If (Handle = -1) Then Success := 103 Else { File not open }
  1300. Success := SetFilePos(Handle, Pos, 0, Li); { Set file position }
  1301. If ((Success = -1) OR (Li <> Pos)) Then Begin { We have an error }
  1302. If (Success = -1) Then Error(stSeekError, 0) { General seek error }
  1303. Else Error(stSeekError, Success); { Specific seek error }
  1304. End Else Position := Li; { Adjust position }
  1305. End;
  1306. END;
  1307. {--TDosStream---------------------------------------------------------------}
  1308. { Open -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 16May96 LdB }
  1309. {---------------------------------------------------------------------------}
  1310. PROCEDURE TDosStream.Open (OpenMode: Word);
  1311. BEGIN
  1312. If (Status = stOk) Then Begin { Check status okay }
  1313. If (Handle = -1) Then Begin { File not open }
  1314. Handle := FileOpen(FName, OpenMode); { Open the file }
  1315. Position := 0; { Reset position }
  1316. If (Handle = 0) Then Begin { File open failed }
  1317. Handle := -1; { Reset handle }
  1318. Error(stOpenError, 103); { Call stream error }
  1319. End;
  1320. End Else Error(stOpenError, 104); { File already open }
  1321. End;
  1322. END;
  1323. {--TDosStream---------------------------------------------------------------}
  1324. { Read -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 27Oct99 LdB }
  1325. {---------------------------------------------------------------------------}
  1326. PROCEDURE TDosStream.Read (Var Buf; Count: Word);
  1327. VAR Success: Integer; Ri, W: Word; Moved: Sw_Word; P: PByteArray;
  1328. BEGIN
  1329. If (Position + Count > StreamSize) Then { Insufficient data }
  1330. Error(stReadError, 0); { Read beyond end!!! }
  1331. If (Handle = -1) Then Error(stReadError, 103); { File not open }
  1332. P := @Buf; { Transfer address }
  1333. Ri := 0; { Zero read index }
  1334. While (Count > 0) AND (Status = stOk) Do Begin { Check status & count }
  1335. W := Count; { Transfer read size }
  1336. If (Count > $FFFE) Then W := $FFFE; { Cant read >64K bytes }
  1337. Success := FileRead(Handle, P^[Ri], W, Moved); { Read from file }
  1338. If ((Success <> 0) OR (Moved <> W)) { Error was detected }
  1339. Then Begin
  1340. Moved := 0; { Clear bytes moved }
  1341. If (Success <> 0) Then
  1342. Error(stReadError, Success) { Specific read error }
  1343. Else Error(stReadError, 0); { Non specific error }
  1344. End;
  1345. Inc(Position, Moved); { Adjust position }
  1346. Inc(Ri, Moved); { Adjust read index }
  1347. Dec(Count, Moved); { Adjust count left }
  1348. End;
  1349. If (Count <> 0) Then FillChar(P^[Ri], Count, #0); { Error clear buffer }
  1350. END;
  1351. {--TDosStream---------------------------------------------------------------}
  1352. { Write -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 27Oct99 LdB }
  1353. {---------------------------------------------------------------------------}
  1354. PROCEDURE TDosStream.Write (Var Buf; Count: Word);
  1355. VAR Success: Integer; W, Wi: Word; Moved: Sw_Word; P: PByteArray;
  1356. BEGIN
  1357. If (Handle = -1) Then Error(stWriteError, 103); { File not open }
  1358. P := @Buf; { Transfer address }
  1359. Wi := 0; { Zero write index }
  1360. While (Count > 0) AND (Status = stOk) Do Begin { Check status & count }
  1361. W := Count; { Transfer read size }
  1362. If (Count > $FFFE) Then W := $FFFE; { Cant read >64K bytes }
  1363. Success := FileWrite(Handle, P^[Wi], W, Moved); { Write to file }
  1364. If ((Success <> 0) OR (Moved <> W)) { Error was detected }
  1365. Then Begin
  1366. Moved := 0; { Clear bytes moved }
  1367. If (Success <> 0) Then
  1368. Error(stWriteError, Success) { Specific write error }
  1369. Else Error(stWriteError, 0); { Non specific error }
  1370. End;
  1371. Inc(Position, Moved); { Adjust position }
  1372. Inc(Wi, Moved); { Adjust write index }
  1373. Dec(Count, Moved); { Adjust count left }
  1374. If (Position > StreamSize) Then { File expanded }
  1375. StreamSize := Position; { Adjust stream size }
  1376. End;
  1377. END;
  1378. {+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++}
  1379. { TBufStream OBJECT METHODS }
  1380. {+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++}
  1381. {--TBufStream---------------------------------------------------------------}
  1382. { Init -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 17May96 LdB }
  1383. {---------------------------------------------------------------------------}
  1384. CONSTRUCTOR TBufStream.Init (FileName: FNameStr; Mode, Size: Word);
  1385. BEGIN
  1386. Inherited Init(FileName, Mode); { Call ancestor }
  1387. If (Size <> 0) AND (MaxAvail >= Size) Then Begin
  1388. GetMem(Buffer, Size); { Allocate buffer }
  1389. BufSize := Size; { Hold buffer size }
  1390. End;
  1391. If (Buffer = Nil) Then Error(stInitError, 0); { Buffer allocate fail }
  1392. END;
  1393. {--TBufStream---------------------------------------------------------------}
  1394. { Done -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 17May96 LdB }
  1395. {---------------------------------------------------------------------------}
  1396. DESTRUCTOR TBufStream.Done;
  1397. BEGIN
  1398. Flush; { Flush the file }
  1399. Inherited Done; { Call ancestor }
  1400. If (Buffer <> Nil) Then FreeMem(Buffer, BufSize); { Release buffer }
  1401. END;
  1402. {--TBufStream---------------------------------------------------------------}
  1403. { Close -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 17May96 LdB }
  1404. {---------------------------------------------------------------------------}
  1405. PROCEDURE TBufStream.Close;
  1406. BEGIN
  1407. Flush; { Flush the buffer }
  1408. Inherited Close; { Call ancestor }
  1409. END;
  1410. {--TBufStream---------------------------------------------------------------}
  1411. { Flush -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 17May96 LdB }
  1412. {---------------------------------------------------------------------------}
  1413. PROCEDURE TBufStream.Flush;
  1414. VAR Success: Integer; W: Sw_Word;
  1415. BEGIN
  1416. If (LastMode = 2) AND (BufPtr <> 0) Then Begin { Must update file }
  1417. If (Handle = -1) Then Success := 103 { File is not open }
  1418. Else Success := FileWrite(Handle, Buffer^,
  1419. BufPtr, W); { Write to file }
  1420. If (Success <> 0) OR (W <> BufPtr) Then { We have an error }
  1421. If (Success = 0) Then Error(stWriteError, 0) { Unknown write error }
  1422. Else Error(stError, Success); { Specific write error }
  1423. End;
  1424. BufPtr := 0; { Reset buffer ptr }
  1425. BufEnd := 0; { Reset buffer end }
  1426. END;
  1427. {--TBufStream---------------------------------------------------------------}
  1428. { Truncate -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 17May96 LdB }
  1429. {---------------------------------------------------------------------------}
  1430. PROCEDURE TBufStream.Truncate;
  1431. BEGIN
  1432. Flush; { Flush buffer }
  1433. Inherited Truncate; { Truncate file }
  1434. END;
  1435. {--TBufStream---------------------------------------------------------------}
  1436. { Seek -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 17May96 LdB }
  1437. {---------------------------------------------------------------------------}
  1438. PROCEDURE TBufStream.Seek (Pos: LongInt);
  1439. BEGIN
  1440. If (Status = stOk) Then Begin { Check status okay }
  1441. If (Position <> Pos) Then Begin { Move required }
  1442. Flush; { Flush the buffer }
  1443. Inherited Seek(Pos); { Call ancestor }
  1444. End;
  1445. End;
  1446. END;
  1447. {--TBufStream---------------------------------------------------------------}
  1448. { Open -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 17May96 LdB }
  1449. {---------------------------------------------------------------------------}
  1450. PROCEDURE TBufStream.Open (OpenMode: Word);
  1451. BEGIN
  1452. If (Status = stOk) Then Begin { Check status okay }
  1453. BufPtr := 0; { Clear buffer start }
  1454. BufEnd := 0; { Clear buffer end }
  1455. Inherited Open(OpenMode); { Call ancestor }
  1456. End;
  1457. END;
  1458. {--TBufStream---------------------------------------------------------------}
  1459. { Read -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 27Oct99 LdB }
  1460. {---------------------------------------------------------------------------}
  1461. PROCEDURE TBufStream.Read (Var Buf; Count: Word);
  1462. VAR Success: Integer; W, Bw, Ri: Word; Br: Sw_Word; P: PByteArray;
  1463. BEGIN
  1464. If (Position + Count > StreamSize) Then { Read pas stream end }
  1465. Error(stReadError, 0); { Call stream error }
  1466. If (Handle = -1) Then Error(stReadError, 103); { File not open }
  1467. P := @Buf; { Transfer address }
  1468. Ri := 0; { Zero read index }
  1469. If (LastMode = 2) Then Flush; { Flush write buffer }
  1470. LastMode := 1; { Now set read mode }
  1471. While (Count > 0) AND (Status = stOk) Do Begin { Check status & count }
  1472. If (BufPtr = BufEnd) Then Begin { Buffer is empty }
  1473. If (Position + BufSize > StreamSize) Then
  1474. Bw := StreamSize - Position { Amount of file left }
  1475. Else Bw := BufSize; { Full buffer size }
  1476. Success := FileRead(Handle, Buffer^, Bw, Br); { Read from file }
  1477. If ((Success <> 0) OR (Bw <> Br)) Then Begin { Error was detected }
  1478. If (Success <> 0) Then
  1479. Error(stReadError, Success) { Specific read error }
  1480. Else Error(stReadError, 0); { Non specific error }
  1481. End Else Begin
  1482. BufPtr := 0; { Reset BufPtr }
  1483. BufEnd := Bw; { End of buffer }
  1484. End;
  1485. End;
  1486. If (Status = stOk) Then Begin { Status still okay }
  1487. W := BufEnd - BufPtr; { Space in buffer }
  1488. If (Count < W) Then W := Count; { Set transfer size }
  1489. Move(Buffer^[BufPtr], P^[Ri], W); { Data from buffer }
  1490. Dec(Count, W); { Reduce count }
  1491. Inc(BufPtr, W); { Advance buffer ptr }
  1492. Inc(Ri, W); { Increase read index }
  1493. Inc(Position, W); { Advance position }
  1494. End;
  1495. End;
  1496. If (Status <> stOk) AND (Count > 0) Then
  1497. FillChar(P^[Ri], Count, #0); { Error clear buffer }
  1498. END;
  1499. {--TBufStream---------------------------------------------------------------}
  1500. { Write -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 27Oct99 LdB }
  1501. {---------------------------------------------------------------------------}
  1502. PROCEDURE TBufStream.Write (Var Buf; Count: Word);
  1503. VAR Success: Integer; W, Wi: Word; Bw: Sw_Word; P: PByteArray;
  1504. BEGIN
  1505. If (Handle = -1) Then Error(stWriteError, 103); { File not open }
  1506. If (LastMode = 1) Then Flush; { Flush read buffer }
  1507. LastMode := 2; { Now set write mode }
  1508. P := @Buf; { Transfer address }
  1509. Wi := 0; { Zero write index }
  1510. While (Count > 0) AND (Status = stOk) Do Begin { Check status & count }
  1511. If (BufPtr = BufSize) Then Begin { Buffer is full }
  1512. Success := FileWrite(Handle, Buffer^, BufSize,
  1513. Bw); { Write to file }
  1514. If (Success <> 0) OR (Bw <> BufSize) Then { We have an error }
  1515. If (Success=0) Then Error(stWriteError, 0) { Unknown write error }
  1516. Else Error(stError, Success); { Specific write error }
  1517. BufPtr := 0; { Reset BufPtr }
  1518. End;
  1519. If (Status = stOk) Then Begin { Status still okay }
  1520. W := BufSize - BufPtr; { Space in buffer }
  1521. If (Count < W) Then W := Count; { Transfer size }
  1522. Move(P^[Wi], Buffer^[BufPtr], W); { Data to buffer }
  1523. Dec(Count, W); { Reduce count }
  1524. Inc(BufPtr, W); { Advance buffer ptr }
  1525. Inc(Wi, W); { Advance write index }
  1526. Inc(Position, W); { Advance position }
  1527. If (Position > StreamSize) Then { File has expanded }
  1528. StreamSize := Position; { Update new size }
  1529. End;
  1530. End;
  1531. END;
  1532. {+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++}
  1533. { TMemoryStream OBJECT METHODS }
  1534. {+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++}
  1535. {--TMemoryStream------------------------------------------------------------}
  1536. { Init -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 19May96 LdB }
  1537. {---------------------------------------------------------------------------}
  1538. CONSTRUCTOR TMemoryStream.Init (ALimit: LongInt; ABlockSize: Word);
  1539. VAR W: Word;
  1540. BEGIN
  1541. Inherited Init; { Call ancestor }
  1542. If (ABlockSize = 0) Then BlkSize := 8192 Else { Default blocksize }
  1543. BlkSize := ABlockSize; { Set blocksize }
  1544. If (ALimit = 0) Then W := 1 Else { At least 1 block }
  1545. W := (ALimit + BlkSize - 1) DIV BlkSize; { Blocks needed }
  1546. If NOT ChangeListSize(W) Then { Try allocate blocks }
  1547. Error(stInitError, 0); { Initialize error }
  1548. END;
  1549. {--TMemoryStream------------------------------------------------------------}
  1550. { Done -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 19May96 LdB }
  1551. {---------------------------------------------------------------------------}
  1552. DESTRUCTOR TMemoryStream.Done;
  1553. BEGIN
  1554. ChangeListSize(0); { Release all memory }
  1555. Inherited Done; { Call ancestor }
  1556. END;
  1557. {--TMemoryStream------------------------------------------------------------}
  1558. { Truncate -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 19May96 LdB }
  1559. {---------------------------------------------------------------------------}
  1560. PROCEDURE TMemoryStream.Truncate;
  1561. VAR W: Word;
  1562. BEGIN
  1563. If (Status = stOk) Then Begin { Check status okay }
  1564. If (Position = 0) Then W := 1 Else { At least one block }
  1565. W := (Position + BlkSize - 1) DIV BlkSize; { Blocks needed }
  1566. If ChangeListSize(W) Then StreamSize := Position { Set stream size }
  1567. Else Error(stError, 0); { Error truncating }
  1568. End;
  1569. END;
  1570. {--TMemoryStream------------------------------------------------------------}
  1571. { Read -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 19May96 LdB }
  1572. {---------------------------------------------------------------------------}
  1573. PROCEDURE TMemoryStream.Read (Var Buf; Count: Word);
  1574. VAR W, CurBlock, BlockPos, Op: Word; Li: LongInt; P, Q: PByteArray;
  1575. BEGIN
  1576. If (Position + Count > StreamSize) Then { Insufficient data }
  1577. Error(stReadError, 0); { Read beyond end!!! }
  1578. P := @Buf; { Transfer address }
  1579. Op := 0; { Zero offset position }
  1580. While (Count > 0) AND (Status = stOk) Do Begin { Check status & count }
  1581. CurBlock := Position DIV BlkSize; { Current block }
  1582. { * REMARK * - Do not shorten this, result can be > 64K }
  1583. Li := CurBlock; { Transfer current block }
  1584. Li := Li * BlkSize; { Current position }
  1585. { * REMARK END * - Leon de Boer }
  1586. BlockPos := Position - Li; { Current position }
  1587. W := BlkSize - BlockPos; { Current block space }
  1588. If (W > Count) Then W := Count; { Adjust read size }
  1589. Q := BlkList^[CurBlock]; { Calc pointer }
  1590. Move(Q^[BlockPos], P^[Op], W); { Move data to buffer }
  1591. Inc(Position, W); { Adjust position }
  1592. Inc(Op, W); { Increase offset }
  1593. Dec(Count, W); { Adjust count left }
  1594. End;
  1595. If (Count <> 0) Then FillChar(P^[Op], Count, #0); { Error clear buffer }
  1596. END;
  1597. {--TMemoryStream------------------------------------------------------------}
  1598. { Write -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 19May96 LdB }
  1599. {---------------------------------------------------------------------------}
  1600. PROCEDURE TMemoryStream.Write (Var Buf; Count: Word);
  1601. VAR W, CurBlock, BlockPos, Op: Word; Li: LongInt; P, Q: PByteArray;
  1602. BEGIN
  1603. If (Position + Count > MemSize) Then Begin { Expansion needed }
  1604. If (Position + Count = 0) Then W := 1 Else { At least 1 block }
  1605. W := (Position+Count+BlkSize-1) DIV BlkSize; { Blocks needed }
  1606. If NOT ChangeListSize(W) Then
  1607. Error(stWriteError, 0); { Expansion failed!!! }
  1608. End;
  1609. P := @Buf; { Transfer address }
  1610. Op := 0; { Zero offset position }
  1611. While (Count > 0) AND (Status = stOk) Do Begin { Check status & count }
  1612. CurBlock := Position DIV BlkSize; { Current segment }
  1613. { * REMARK * - Do not shorten this, result can be > 64K }
  1614. Li := CurBlock; { Transfer current block }
  1615. Li := Li * BlkSize; { Current position }
  1616. { * REMARK END * - Leon de Boer }
  1617. BlockPos := Position - Li; { Current position }
  1618. W := BlkSize - BlockPos; { Current block space }
  1619. If (W > Count) Then W := Count; { Adjust write size }
  1620. Q := BlkList^[CurBlock]; { Calc pointer }
  1621. Move(P^[Op], Q^[BlockPos], W); { Transfer data }
  1622. Inc(Position, W); { Adjust position }
  1623. Inc(Op, W); { Increase offset }
  1624. Dec(Count, W); { Adjust count left }
  1625. If (Position > StreamSize) Then { File expanded }
  1626. StreamSize := Position; { Adjust stream size }
  1627. End;
  1628. END;
  1629. {***************************************************************************}
  1630. { TMemoryStream PRIVATE METHODS }
  1631. {***************************************************************************}
  1632. {--TMemoryStream------------------------------------------------------------}
  1633. { ChangeListSize -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 19May96 LdB }
  1634. {---------------------------------------------------------------------------}
  1635. FUNCTION TMemoryStream.ChangeListSize (ALimit: Word): Boolean;
  1636. VAR I, W, Bas: Word; P: PPointerArray;
  1637. BEGIN
  1638. If (ALimit <> BlkCount) Then Begin { Change is needed }
  1639. ChangeListSize := False; { Preset failure }
  1640. If (ALimit > MaxPtrs) Then Exit; { To many blocks req }
  1641. If (ALimit <> 0) Then Begin { Create segment list }
  1642. Bas := ALimit * SizeOf(Pointer); { Block array size }
  1643. If (MaxAvail > Bas) Then Begin
  1644. GetMem(P, Bas); { Allocate memory }
  1645. FillChar(P^, Bas, #0); { Clear the memory }
  1646. End Else Exit; { Insufficient memory }
  1647. If (BlkCount <> 0) AND (BlkList <> Nil) Then { Current list valid }
  1648. If (BlkCount <= ALimit) Then Move(BlkList^,
  1649. P^, BlkCount * SizeOf(Pointer)) Else { Move whole old list }
  1650. Move(BlkList^, P^, Bas); { Move partial list }
  1651. End Else P := Nil; { No new block list }
  1652. If (ALimit < BlkCount) Then { Shrink stream size }
  1653. For W := BlkCount-1 DownTo ALimit Do
  1654. FreeMem(BlkList^[W], BlkSize); { Release memory block }
  1655. If (P <> Nil) AND (ALimit > BlkCount) Then Begin { Expand stream size }
  1656. For W := BlkCount To ALimit-1 Do Begin
  1657. If (MaxAvail < BlkSize) Then Begin { Check enough memory }
  1658. For I := BlkCount To W-1 Do
  1659. FreeMem(P^[I], BlkSize); { Free mem allocated }
  1660. FreeMem(P, Bas); { Release memory }
  1661. Exit; { Now exit }
  1662. End Else GetMem(P^[W], BlkSize); { Allocate memory }
  1663. End;
  1664. End;
  1665. If (BlkCount <> 0) AND (BlkList<>Nil) Then
  1666. FreeMem(BlkList, BlkCount * SizeOf(Pointer)); { Release old list }
  1667. BlkList := P; { Hold new block list }
  1668. BlkCount := ALimit; { Hold new count }
  1669. { * REMARK * - Do not shorten this, result can be > 64K }
  1670. MemSize := BlkCount; { Block count }
  1671. MemSize := MemSize * BlkSize; { Current position }
  1672. { * REMARK END * - Leon de Boer }
  1673. End;
  1674. ChangeListSize := True; { Successful }
  1675. END;
  1676. {+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++}
  1677. { TEmsStream OBJECT METHODS }
  1678. {+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++}
  1679. {--TEmsStream---------------------------------------------------------------}
  1680. { Init -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 28Feb97 LdB }
  1681. {---------------------------------------------------------------------------}
  1682. CONSTRUCTOR TEmsStream.Init (MinSize, MaxSize: LongInt);
  1683. {$IFDEF PROC_Real} { DOS REAL MODE CODE }
  1684. VAR Success: Integer; MinPg, MaxPg: Word;
  1685. BEGIN
  1686. Inherited Init; { Call ancestor }
  1687. If (EMS_MemAvail >= MaxSize) Then Begin { Sufficient memory }
  1688. If (MaxSize = 0) Then MaxPg := 1 Else { At least one page }
  1689. MaxPg := (MaxSize + 16383) DIV 16384; { Max pages needed }
  1690. If (MinSize = 0) Then MinPg := 1 Else { At least one page }
  1691. MinPg := (MinSize + 16383) DIV 16384; { Min pages needed }
  1692. Handle := EMS_GetMem(MaxPg); { Allocate EMS pages }
  1693. If (Handle <> 0) Then Begin
  1694. Success := 0; { Preset success }
  1695. PageCount := MaxPg; { Pages used }
  1696. If (MaxPg <> MinPg) Then { Sizes differ }
  1697. If (EMS_ResizeMem(MinPg, Handle)=0) { Resize to minimum }
  1698. Then PageCount := MinPg; { Hold new page count }
  1699. { * REMARK * - Do not shorten this, result can be > 64K }
  1700. MemSize := PageCount;
  1701. MemSize := MemSize * 16384;
  1702. { * REMARK END * - Leon de Boer }
  1703. End Else Success := 403; { Failed to allocate }
  1704. End Else Success := 400; { Insufficent EMS }
  1705. If (Handle = 0) OR (Success <> 0) Then { EMS failed }
  1706. Error(stInitError, Success); { Call stream error }
  1707. END;
  1708. {$ELSE} { ALL OTHER OS SYSTEMS }
  1709. BEGIN
  1710. Inherited Init(MaxSize, 16384); { For compatability }
  1711. END;
  1712. {$ENDIF}
  1713. {$IFDEF PROC_Real} { DOS REAL MODE CODE }
  1714. {***************************************************************************}
  1715. { TEMSStream DOS REAL MODE ONLY METHODS }
  1716. {***************************************************************************}
  1717. {--TEmsStream---------------------------------------------------------------}
  1718. { Done -> Platforms DOS REAL MODE - Updated 28Feb97 LdB }
  1719. {---------------------------------------------------------------------------}
  1720. DESTRUCTOR TEmsStream.Done;
  1721. BEGIN
  1722. If (Handle <> 0) Then EMS_FreeMem(Handle); { Release EMS blocks }
  1723. Inherited Done; { Call ancestor }
  1724. END;
  1725. {--TEmsStream---------------------------------------------------------------}
  1726. { Truncate -> Platforms DOS REAL MODE - Updated 28Feb97 LdB }
  1727. {---------------------------------------------------------------------------}
  1728. PROCEDURE TEmsStream.Truncate;
  1729. VAR Success: Integer; W: Word;
  1730. BEGIN
  1731. If (Status = stOk) Then Begin { Check status okay }
  1732. If (Position = 0) Then W := 1 Else { At least one page }
  1733. W := (Position + 16383) DIV 16384; { Pages to use }
  1734. Success := 0; { Preset success }
  1735. If (W <> PageCount) Then { Sizes differ }
  1736. If (EMS_ResizeMem(W, Handle)=0) Then { Resize to this }
  1737. PageCount := W Else Success := 401; { Adjust blocks used }
  1738. If (Success = 0) Then StreamSize := Position { Adjust size }
  1739. Else Error(stError, Success); { Identify error }
  1740. End;
  1741. END;
  1742. {--TEmsStream---------------------------------------------------------------}
  1743. { Read -> Platforms DOS REAL MODE - Updated 27Oct99 LdB }
  1744. {---------------------------------------------------------------------------}
  1745. PROCEDURE TEmsStream.Read (Var Buf; Count: Word);
  1746. VAR Success: Integer; W, Ri: Word; P: PByteArray;
  1747. BEGIN
  1748. If (Position + Count > StreamSize) Then { Insufficient data }
  1749. Error(stReadError, 0); { Read beyond end!!! }
  1750. If (Handle = 0) Then Error(stReadError, 403); { EMS not available }
  1751. P := @Buf; { Transfer address }
  1752. Ri := 0; { Zero read index }
  1753. While (Count > 0) AND (Status = stOk) Do Begin { Check status & count }
  1754. W := Count; { Transfer read size }
  1755. If (Count > $FFFE) Then W := $FFFE; { Cant read >64K bytes }
  1756. Success := EMS_MoveMem(LongInt(P^[Ri]), 0,
  1757. Position, Handle, W); { Move the data }
  1758. If (Success <> 0) Then Begin { Error was detected }
  1759. W := 0; { Clear bytes moved }
  1760. Error(stReadError, Success) { Specific read error }
  1761. End;
  1762. Inc(Position, W); { Adjust position }
  1763. Inc(Ri, W); { Adjust read index }
  1764. Dec(Count, W); { Adjust count left }
  1765. End;
  1766. If (Count <> 0) Then FillChar(P^[Ri], Count, #0); { Error clear buffer }
  1767. END;
  1768. {--TEmsStream---------------------------------------------------------------}
  1769. { Write -> Platforms DOS REAL MODE - Updated 27Oct99 LdB }
  1770. {---------------------------------------------------------------------------}
  1771. PROCEDURE TEmsStream.Write (Var Buf; Count: Word);
  1772. VAR Success: Integer; W, Wi: Word; P: PByteArray;
  1773. BEGIN
  1774. If (Position + Count > MemSize) Then Begin { Expansion needed }
  1775. If (Position + Count = 0) Then W := 1 Else { At least one page }
  1776. W := (Position+Count + 16383) DIV 16384; { Pages needed }
  1777. If (EMS_ResizeMem(W, Handle)=0) Then Begin { Resize memory }
  1778. PageCount := W; { Adjust page count }
  1779. { * REMARK * - Do not shorten this, result can be > 64K }
  1780. MemSize := PageCount;
  1781. MemSize := MemSize * 1024; { New memory size }
  1782. { * REMARK END * - Leon de Boer }
  1783. End Else Error(stWriteError, 0); { We have an error }
  1784. End;
  1785. If (Handle = 0) Then Error(stWriteError, 403); { EMS not available }
  1786. P := @Buf; { Transfer address }
  1787. Wi := 0; { Zero write index }
  1788. While (Count > 0) AND (Status = stOk) Do Begin { Check status & count }
  1789. W := Count; { Transfer read size }
  1790. If (Count > $FFFE) Then W := $FFFE; { Cant read >64K bytes }
  1791. Success := EMS_MoveMem(Position, Handle,
  1792. LongInt(P^[Wi]), 0, W); { Move the memory }
  1793. If (Success <> 0) Then Begin { Error was detected }
  1794. W := 0; { Clear bytes moved }
  1795. Error(stWriteError, Success); { Specific write error }
  1796. End;
  1797. Inc(Position, W); { Adjust position }
  1798. Inc(Wi, W); { Adjust write index }
  1799. Dec(Count, W); { Adjust count left }
  1800. If (Position > StreamSize) Then { File expanded }
  1801. StreamSize := Position; { Adjust stream size }
  1802. End;
  1803. END;
  1804. {$ENDIF}
  1805. {+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++}
  1806. { TXmsStream OBJECT ANCESTOR }
  1807. {+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++}
  1808. {--TXmsStream---------------------------------------------------------------}
  1809. { Init -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 28Feb97 LdB }
  1810. {---------------------------------------------------------------------------}
  1811. CONSTRUCTOR TXmsStream.Init (MinSize, MaxSize: LongInt);
  1812. {$IFDEF PROC_Real} { DOS REAL MODE CODE }
  1813. VAR Success: Integer; MinBlk, MaxBlk: Word;
  1814. BEGIN
  1815. Inherited Init; { Call ancestor }
  1816. If (XMS_MemAvail >= MaxSize) Then Begin { Sufficient memory }
  1817. If (MaxSize = 0) Then MaxBlk := 1 Else { At least one block }
  1818. MaxBlk := (MaxSize + 1023) DIV 1024; { Max blocks needed }
  1819. If (MinSize = 0) Then MinBlk := 1 Else { At least one block }
  1820. MinBlk := (MinSize + 1023) DIV 1024; { Min blocks needed }
  1821. Handle := XMS_GetMem(MaxBlk); { Allocate XMS blocks }
  1822. If (Handle <> 0) Then Begin
  1823. Success := 0; { Preset success }
  1824. BlocksUsed := MaxBlk; { Blocks used }
  1825. If (MaxBlk <> MinBlk) Then { Sizes differ }
  1826. If (XMS_ResizeMem(MaxBlk, MinBlk, Handle)=0) { Resize to minimum }
  1827. Then BlocksUsed := MinBlk; { Hold block size }
  1828. { * REMARK * - Do not shorten this, result can be > 64K }
  1829. MemSize := BlocksUsed;
  1830. MemSize := MemSize * 1024;
  1831. { * REMARK END * - Leon de Boer }
  1832. End Else Success := 303; { Failed to allocate }
  1833. End Else Success := 300; { Insufficent XMS }
  1834. If (Handle = 0) OR (Success <> 0) Then { XMS failed }
  1835. Error(stInitError, Success); { Call stream error }
  1836. END;
  1837. {$ELSE} { ALL OTHER OP SYSTEMS }
  1838. BEGIN
  1839. Inherited Init(MaxSize, 16384); { For compatability }
  1840. END;
  1841. {$ENDIF}
  1842. {$IFDEF PROC_Real} { DOS REAL MODE CODE }
  1843. {***************************************************************************}
  1844. { TXMSStream DOS REAL MODE ONLY METHODS }
  1845. {***************************************************************************}
  1846. {--TXmsStream---------------------------------------------------------------}
  1847. { Done -> Platforms DOS REAL MODE - Updated 28Feb97 LdB }
  1848. {---------------------------------------------------------------------------}
  1849. DESTRUCTOR TXmsStream.Done;
  1850. BEGIN
  1851. If (Handle <> 0) Then XMS_FreeMem(Handle); { Release XMS blocks }
  1852. Inherited Done; { Call ancestor }
  1853. END;
  1854. {--TXmsStream---------------------------------------------------------------}
  1855. { Truncate -> Platforms DOS REAL MODE - Updated 28Feb97 LdB }
  1856. {---------------------------------------------------------------------------}
  1857. PROCEDURE TXmsStream.Truncate;
  1858. VAR Success: Integer; W: Word;
  1859. BEGIN
  1860. If (Status = stOk) Then Begin { Check status okay }
  1861. If (Position = 0) Then W := 1 Else { At least 1 block }
  1862. W := (Position + 1023) DIV 1024; { Blocks to use }
  1863. Success := 0; { Preset success }
  1864. If (W <> BlocksUsed) Then { Sizes differ }
  1865. If (XMS_ResizeMem(BlocksUsed, W, Handle)=0) { Resize to this }
  1866. Then Begin
  1867. BlocksUsed := W; { Adjust blocks used }
  1868. { * REMARK * - Do not shorten this, result can be > 64K }
  1869. MemSize := BlocksUsed; { Blocks used }
  1870. MemSize := MemSize * 1024; { Mult by block size }
  1871. { * REMARK END * - Leon de Boer }
  1872. End Else Success := 301; { Resize failed }
  1873. If (Success = 0) Then StreamSize := Position { Adjust size }
  1874. Else Error(stError, Success); { Identify error }
  1875. End;
  1876. END;
  1877. {--TXmsStream---------------------------------------------------------------}
  1878. { Read -> Platforms DOS REAL MODE - Updated 27Oct99 LdB }
  1879. {---------------------------------------------------------------------------}
  1880. PROCEDURE TXmsStream.Read (Var Buf; Count: Word);
  1881. VAR Success: Integer; W, Ri: Word; P: PByteArray;
  1882. BEGIN
  1883. If (Position + Count > StreamSize) Then { Insufficient data }
  1884. Error(stReadError, 0); { Read beyond end!!! }
  1885. If (Handle = 0) Then Error(stReadError, 303); { XMS not available }
  1886. P := @Buf; { Transfer address }
  1887. Ri := 0; { Zero read index }
  1888. While (Count > 0) AND (Status = stOk) Do Begin { Check status & count }
  1889. W := Count; { Transfer read size }
  1890. If (Count > $FFFE) Then W := $FFFE; { Cant read >64K bytes }
  1891. Success := XMS_MoveMem(LongInt(P^[Ri]), 0,
  1892. Position, Handle, W); { Move the data }
  1893. If (Success <> 0) Then Begin { Error was detected }
  1894. W := 0; { Clear bytes moved }
  1895. Error(stReadError, Success) { Specific read error }
  1896. End;
  1897. Inc(Position, W); { Adjust position }
  1898. Inc(Ri, W); { Adjust read index }
  1899. Dec(Count, W); { Adjust count left }
  1900. End;
  1901. If (Count <> 0) Then FillChar(P^[Ri], Count, #0); { Error clear buffer }
  1902. END;
  1903. {--TXmsStream---------------------------------------------------------------}
  1904. { Write -> Platforms DOS REAL MODE - Updated 27Oct99 LdB }
  1905. {---------------------------------------------------------------------------}
  1906. PROCEDURE TXmsStream.Write (Var Buf; Count: Sw_Word);
  1907. VAR Success: Integer; W, Wi: Word; P: PByteArray;
  1908. BEGIN
  1909. { * REMARK * - Because XMS must move even bytes we expand if within }
  1910. { one byte of allocated size so we can read/write the }
  1911. { last byte with an even access using a dummy end byte. }
  1912. { * REMARK * - Leon de Boer }
  1913. If (Position + Count > (MemSize-1)) Then Begin { Expansion needed }
  1914. If (Position + Count = 0) Then W := 1 Else Begin { At least one }
  1915. W := (Position + Count + 1023) DIV 1024; { Blocks needed }
  1916. If ((Position + Count) MOD 1024 = 0) Then
  1917. Inc(W); { Fix for even access }
  1918. End;
  1919. If (XMS_ResizeMem(BlocksUsed, W, Handle)=0) { Resize memory }
  1920. Then Begin
  1921. BlocksUsed := W; { Adjust block count }
  1922. { * REMARK * - Do not shorten this, result can be > 64K }
  1923. MemSize := BlocksUsed;
  1924. MemSize := MemSize * 1024; { New memory size }
  1925. { * REMARK END * - Leon de Boer }
  1926. End Else Error(stWriteError, 0); { We have an error }
  1927. End;
  1928. If (Handle = 0) Then Error(stWriteError, 303); { XMS not available }
  1929. P := @Buf; { Transfer address }
  1930. Wi := 0; { Zero write index }
  1931. While (Count > 0) AND (Status = stOk) Do Begin { Check status & count }
  1932. W := Count; { Transfer read size }
  1933. If (Count > $FFFE) Then W := $FFFE; { Cant read >64K bytes }
  1934. Success := XMS_MoveMem(Position, Handle,
  1935. LongInt(P^[Wi]), 0, W); { Move the memory }
  1936. If (Success <> 0) Then Begin { Error was detected }
  1937. W := 0; { Clear bytes moved }
  1938. Error(stWriteError, Success); { Specific write error }
  1939. End;
  1940. Inc(Position, W); { Adjust position }
  1941. Inc(Wi, W); { Adjust write index }
  1942. Dec(Count, W); { Adjust count left }
  1943. If (Position > StreamSize) Then { File expanded }
  1944. StreamSize := Position; { Adjust stream size }
  1945. End;
  1946. END;
  1947. {$ENDIF}
  1948. {+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++}
  1949. { TCollection OBJECT METHODS }
  1950. {+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++}
  1951. {--TCollection--------------------------------------------------------------}
  1952. { Init -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 22May96 LdB }
  1953. {---------------------------------------------------------------------------}
  1954. CONSTRUCTOR TCollection.Init (ALimit, ADelta: Integer);
  1955. BEGIN
  1956. Inherited Init; { Call ancestor }
  1957. Delta := ADelta; { Set increment }
  1958. SetLimit(ALimit); { Set limit }
  1959. END;
  1960. {--TCollection--------------------------------------------------------------}
  1961. { Load -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 22May96 LdB }
  1962. {---------------------------------------------------------------------------}
  1963. CONSTRUCTOR TCollection.Load (Var S: TStream);
  1964. VAR C, I: Integer;
  1965. BEGIN
  1966. S.Read(Count, 2); { Read count }
  1967. S.Read(Limit, 2); { Read limit }
  1968. S.Read(Delta, 2); { Read delta }
  1969. Items := Nil; { Clear item pointer }
  1970. C := Count; { Hold count }
  1971. I := Limit; { Hold limit }
  1972. Count := 0; { Clear count }
  1973. Limit := 0; { Clear limit }
  1974. SetLimit(I); { Set requested limit }
  1975. Count := C; { Set count }
  1976. For I := 0 To C-1 Do AtPut(I, GetItem(S)); { Get each item }
  1977. END;
  1978. {--TCollection--------------------------------------------------------------}
  1979. { Done -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 22May96 LdB }
  1980. {---------------------------------------------------------------------------}
  1981. DESTRUCTOR TCollection.Done;
  1982. BEGIN
  1983. FreeAll; { Free all items }
  1984. SetLimit(0); { Release all memory }
  1985. END;
  1986. {--TCollection--------------------------------------------------------------}
  1987. { At -> Platforms DOS/DPMI/WIN/NT/OS2 -Updated 22May96 LdB }
  1988. {---------------------------------------------------------------------------}
  1989. FUNCTION TCollection.At (Index: Integer): Pointer;
  1990. BEGIN
  1991. If (Index < 0) OR (Index >= Count) Then Begin { Invalid index }
  1992. Error(coIndexError, Index); { Call error }
  1993. At := Nil; { Return nil }
  1994. End Else At := Items^[Index]; { Return item }
  1995. END;
  1996. {--TCollection--------------------------------------------------------------}
  1997. { IndexOf -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 22May96 LdB }
  1998. {---------------------------------------------------------------------------}
  1999. FUNCTION TCollection.IndexOf (Item: Pointer): Integer;
  2000. VAR I: Integer;
  2001. BEGIN
  2002. If (Count > 0) Then Begin { Count is positive }
  2003. For I := 0 To Count-1 Do { For each item }
  2004. If (Items^[I] = Item) Then Begin { Look for match }
  2005. IndexOf := I; { Return index }
  2006. Exit; { Now exit }
  2007. End;
  2008. End;
  2009. IndexOf := -1; { Return index }
  2010. END;
  2011. {--TCollection--------------------------------------------------------------}
  2012. { GetItem -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 22May96 LdB }
  2013. {---------------------------------------------------------------------------}
  2014. FUNCTION TCollection.GetItem (Var S: TStream): Pointer;
  2015. BEGIN
  2016. GetItem := S.Get; { Item off stream }
  2017. END;
  2018. {--TCollection--------------------------------------------------------------}
  2019. { LastThat -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 08Jul99 LdB }
  2020. {---------------------------------------------------------------------------}
  2021. FUNCTION TCollection.LastThat (Test: Pointer): Pointer;
  2022. VAR I: Integer;
  2023. BEGIN
  2024. For I := Count DownTo 1 Do Begin { Down from last item }
  2025. {$IFDEF PPC_VIRTUAL} { VIRTUAL COMPILER }
  2026. If CallTestLocal(Test, Items^[I-1]) { Test each item }
  2027. {$ELSE} { OTHER COMPILERS }
  2028. If CallTestLocal(Test, PrevFramePtr, Items^[I-1]){ Test each item }
  2029. {$ENDIF}
  2030. Then Begin { Test each item }
  2031. LastThat := Items^[I-1]; { Return successful }
  2032. Exit; { Now exit }
  2033. End;
  2034. End;
  2035. LastThat := Nil; { None passed test }
  2036. END;
  2037. {--TCollection--------------------------------------------------------------}
  2038. { FirstThat -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 08Jul99 LdB }
  2039. {---------------------------------------------------------------------------}
  2040. FUNCTION TCollection.FirstThat (Test: Pointer): Pointer;
  2041. VAR I: Integer;
  2042. BEGIN
  2043. For I := 1 To Count Do Begin { Up from first item }
  2044. {$IFDEF PPC_VIRTUAL} { VIRTUAL COMPILER }
  2045. If CallTestLocal(Test, Items^[I-1]) { Test each item }
  2046. {$ELSE} { OTHER COMPILERS }
  2047. If CallTestLocal(Test, PrevFramePtr, Items^[I-1]){ Test each item }
  2048. {$ENDIF}
  2049. Then Begin { Test each item }
  2050. FirstThat := Items^[I-1]; { Return successful }
  2051. Exit; { Now exit }
  2052. End;
  2053. End;
  2054. FirstThat := Nil; { None passed test }
  2055. END;
  2056. {--TCollection--------------------------------------------------------------}
  2057. { Pack -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 22May96 LdB }
  2058. {---------------------------------------------------------------------------}
  2059. PROCEDURE TCollection.Pack;
  2060. VAR I, J: Integer;
  2061. BEGIN
  2062. I := 0; { Initialize dest }
  2063. J := 0; { Intialize test }
  2064. While (I < Count) AND (J < Limit) Do Begin { Check fully packed }
  2065. If (Items^[J] <> Nil) Then Begin { Found a valid item }
  2066. If (I <> J) Then Begin
  2067. Items^[I] := Items^[J]; { Transfer item }
  2068. Items^[J] := Nil; { Now clear old item }
  2069. End;
  2070. Inc(I); { One item packed }
  2071. End;
  2072. Inc(J); { Next item to test }
  2073. End;
  2074. If (I < Count) Then Count := I; { New packed count }
  2075. END;
  2076. {--TCollection--------------------------------------------------------------}
  2077. { FreeAll -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 22May96 LdB }
  2078. {---------------------------------------------------------------------------}
  2079. PROCEDURE TCollection.FreeAll;
  2080. VAR I: Integer;
  2081. BEGIN
  2082. For I := 0 To Count-1 Do FreeItem(At(I)); { Release each item }
  2083. Count := 0; { Clear item count }
  2084. END;
  2085. {--TCollection--------------------------------------------------------------}
  2086. { DeleteAll -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 22May96 LdB }
  2087. {---------------------------------------------------------------------------}
  2088. PROCEDURE TCollection.DeleteAll;
  2089. BEGIN
  2090. Count := 0; { Clear item count }
  2091. END;
  2092. {--TCollection--------------------------------------------------------------}
  2093. { Free -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 22May96 LdB }
  2094. {---------------------------------------------------------------------------}
  2095. PROCEDURE TCollection.Free (Item: Pointer);
  2096. BEGIN
  2097. Delete(Item); { Delete from list }
  2098. FreeItem(Item); { Free the item }
  2099. END;
  2100. {--TCollection--------------------------------------------------------------}
  2101. { Insert -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 22May96 LdB }
  2102. {---------------------------------------------------------------------------}
  2103. PROCEDURE TCollection.Insert (Item: Pointer);
  2104. BEGIN
  2105. AtInsert(Count, Item); { Insert item }
  2106. END;
  2107. {--TCollection--------------------------------------------------------------}
  2108. { Delete -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 22May96 LdB }
  2109. {---------------------------------------------------------------------------}
  2110. PROCEDURE TCollection.Delete (Item: Pointer);
  2111. BEGIN
  2112. AtDelete(IndexOf(Item)); { Delete from list }
  2113. END;
  2114. {--TCollection--------------------------------------------------------------}
  2115. { AtFree -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 22May96 LdB }
  2116. {---------------------------------------------------------------------------}
  2117. PROCEDURE TCollection.AtFree (Index: Integer);
  2118. VAR Item: Pointer;
  2119. BEGIN
  2120. Item := At(Index); { Retreive item ptr }
  2121. AtDelete(Index); { Delete item }
  2122. FreeItem(Item); { Free the item }
  2123. END;
  2124. {--TCollection--------------------------------------------------------------}
  2125. { FreeItem -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 22May96 LdB }
  2126. {---------------------------------------------------------------------------}
  2127. PROCEDURE TCollection.FreeItem (Item: Pointer);
  2128. VAR P: PObject;
  2129. BEGIN
  2130. P := PObject(Item); { Convert pointer }
  2131. If (P <> Nil) Then Dispose(P, Done); { Dispose of object }
  2132. END;
  2133. {--TCollection--------------------------------------------------------------}
  2134. { AtDelete -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 22May96 LdB }
  2135. {---------------------------------------------------------------------------}
  2136. PROCEDURE TCollection.AtDelete (Index: Integer);
  2137. BEGIN
  2138. If (Index >= 0) AND (Index < Count) Then Begin { Valid index }
  2139. Dec(Count); { One less item }
  2140. If (Count > Index) Then Move(Items^[Index+1],
  2141. Items^[Index], (Count-Index)*Sizeof(Pointer)); { Shuffle items down }
  2142. End Else Error(coIndexError, Index); { Index error }
  2143. END;
  2144. {--TCollection--------------------------------------------------------------}
  2145. { ForEach -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 08Jul99 LdB }
  2146. {---------------------------------------------------------------------------}
  2147. PROCEDURE TCollection.ForEach (Action: Pointer);
  2148. VAR I: Integer;
  2149. BEGIN
  2150. For I := 1 To Count Do { Up from first item }
  2151. {$IFDEF PPC_VIRTUAL} { VIRTUAL COMPILER }
  2152. CallTestLocal(Action, Items^[I-1]); { Call with each item }
  2153. {$ELSE} { OTHER COMPILERS }
  2154. CallTestLocal(Action, PrevFramePtr, Items^[I-1]); { Call with each item }
  2155. {$ENDIF}
  2156. END;
  2157. {--TCollection--------------------------------------------------------------}
  2158. { SetLimit -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 22May96 LdB }
  2159. {---------------------------------------------------------------------------}
  2160. PROCEDURE TCollection.SetLimit (ALimit: Integer);
  2161. VAR AItems: PItemList;
  2162. BEGIN
  2163. If (ALimit < Count) Then ALimit := Count; { Stop underflow }
  2164. If (ALimit > MaxCollectionSize) Then
  2165. ALimit := MaxCollectionSize; { Stop overflow }
  2166. {$IFNDEF PPC_SPEED} { NON SPEED COMPILERS }
  2167. If (MaxAvail < (ALimit*SizeOf(Pointer))) Then { Check enough memory }
  2168. ALimit := Limit; { Insufficient memory }
  2169. {$ENDIF}
  2170. If (ALimit <> Limit) Then Begin { Limits differ }
  2171. If (ALimit = 0) Then AItems := Nil Else Begin { Alimit=0 nil entry }
  2172. GetMem(AItems, ALimit * SizeOf(Pointer)); { Allocate memory }
  2173. If (AItems <> Nil) Then FillChar(AItems^,
  2174. ALimit * SizeOf(Pointer), #0); { Clear the memory }
  2175. End;
  2176. If (AItems <> Nil) OR (ALimit = 0) Then Begin { Check success }
  2177. If (AItems <> Nil) AND (Items <> Nil) Then { Check both valid }
  2178. Move(Items^, AItems^, Count*SizeOf(Pointer));{ Move existing items }
  2179. If (Limit <> 0) AND (Items <> Nil) Then { Check old allocation }
  2180. FreeMem(Items, Limit * SizeOf(Pointer)); { Release memory }
  2181. Items := AItems; { Update items }
  2182. Limit := ALimit; { Set limits }
  2183. End;
  2184. End;
  2185. END;
  2186. {--TCollection--------------------------------------------------------------}
  2187. { Error -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 22May96 LdB }
  2188. {---------------------------------------------------------------------------}
  2189. PROCEDURE TCollection.Error (Code, Info: Integer);
  2190. BEGIN
  2191. RunError(212 - Code); { Run error }
  2192. END;
  2193. {--TCollection--------------------------------------------------------------}
  2194. { AtPut -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 22May96 LdB }
  2195. {---------------------------------------------------------------------------}
  2196. PROCEDURE TCollection.AtPut (Index: Integer; Item: Pointer);
  2197. BEGIN
  2198. If (Index >= 0) AND (Index < Count) Then { Index valid }
  2199. Items^[Index] := Item { Put item in index }
  2200. Else Error(coIndexError, Index); { Index error }
  2201. END;
  2202. {--TCollection--------------------------------------------------------------}
  2203. { AtInsert -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 28May99 LdB }
  2204. {---------------------------------------------------------------------------}
  2205. PROCEDURE TCollection.AtInsert (Index: Integer; Item: Pointer);
  2206. VAR I: Integer;
  2207. BEGIN
  2208. If (Index >= 0) AND (Index <= Count) Then Begin { Valid index }
  2209. If (Count=Limit) Then SetLimit(Limit+Delta); { Expand size if able }
  2210. If (Limit>Count) Then Begin
  2211. If (Index < Count) Then Begin { Not last item }
  2212. For I := Count-1 DownTo Index Do { Start from back }
  2213. Items^[I+1] := Items^[I]; { Move each item }
  2214. End;
  2215. Items^[Index] := Item; { Put item in list }
  2216. Inc(Count); { Inc count }
  2217. End Else Error(coOverflow, Index); { Expand failed }
  2218. End Else Error(coIndexError, Index); { Index error }
  2219. END;
  2220. {--TCollection--------------------------------------------------------------}
  2221. { Store -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 22May96 LdB }
  2222. {---------------------------------------------------------------------------}
  2223. PROCEDURE TCollection.Store (Var S: TStream);
  2224. PROCEDURE DoPutItem (P: Pointer); {$IFNDEF FPC} FAR;{$ENDIF}
  2225. BEGIN
  2226. PutItem(S, P); { Put item on stream }
  2227. END;
  2228. BEGIN
  2229. S.Write(Count, 2); { Write count }
  2230. S.Write(Limit, 2); { Write limit }
  2231. S.Write(Delta, 2); { Write delta }
  2232. ForEach(@DoPutItem); { Each item to stream }
  2233. END;
  2234. {--TCollection--------------------------------------------------------------}
  2235. { PutItem -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 22May96 LdB }
  2236. {---------------------------------------------------------------------------}
  2237. PROCEDURE TCollection.PutItem (Var S: TStream; Item: Pointer);
  2238. BEGIN
  2239. S.Put(Item); { Put item on stream }
  2240. END;
  2241. {+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++}
  2242. { TSortedCollection OBJECT METHODS }
  2243. {+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++}
  2244. {--TSortedCollection--------------------------------------------------------}
  2245. { Init -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 22May96 LdB }
  2246. {---------------------------------------------------------------------------}
  2247. CONSTRUCTOR TSortedCollection.Init (ALimit, ADelta: Integer);
  2248. BEGIN
  2249. Inherited Init(ALimit, ADelta); { Call ancestor }
  2250. Duplicates := False; { Clear flag }
  2251. END;
  2252. {--TSortedCollection--------------------------------------------------------}
  2253. { Load -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 22May96 LdB }
  2254. {---------------------------------------------------------------------------}
  2255. CONSTRUCTOR TSortedCollection.Load (Var S: TStream);
  2256. BEGIN
  2257. Inherited Load(S); { Call ancestor }
  2258. S.Read(Duplicates, 1); { Read duplicate flag }
  2259. END;
  2260. {--TSortedCollection--------------------------------------------------------}
  2261. { KeyOf -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 22May96 LdB }
  2262. {---------------------------------------------------------------------------}
  2263. FUNCTION TSortedCollection.KeyOf (Item: Pointer): Pointer;
  2264. BEGIN
  2265. KeyOf := Item; { Return item as key }
  2266. END;
  2267. {--TSortedCollection--------------------------------------------------------}
  2268. { IndexOf -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 22May96 LdB }
  2269. {---------------------------------------------------------------------------}
  2270. FUNCTION TSortedCollection.IndexOf (Item: Pointer): Integer;
  2271. VAR I, J: Integer;
  2272. BEGIN
  2273. J := -1; { Preset result }
  2274. If Search(KeyOf(Item), I) Then Begin { Search for item }
  2275. If Duplicates Then { Duplicates allowed }
  2276. While (I < Count) AND (Item <> Items^[I]) Do
  2277. Inc(I); { Count duplicates }
  2278. If (I < Count) Then J := I; { Index result }
  2279. End;
  2280. IndexOf := J; { Return result }
  2281. END;
  2282. {--TSortedCollection--------------------------------------------------------}
  2283. { Compare -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 22May96 LdB }
  2284. {---------------------------------------------------------------------------}
  2285. FUNCTION TSortedCollection.Compare (Key1, Key2: Pointer): Integer;
  2286. BEGIN
  2287. Abstract; { Abstract method }
  2288. END;
  2289. {--TSortedCollection--------------------------------------------------------}
  2290. { Search -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 22May96 LdB }
  2291. {---------------------------------------------------------------------------}
  2292. FUNCTION TSortedCollection.Search (Key: Pointer; Var Index: Integer): Boolean;
  2293. VAR L, H, I, C: Integer;
  2294. BEGIN
  2295. Search := False; { Preset failure }
  2296. L := 0; { Start count }
  2297. H := Count - 1; { End count }
  2298. While (L <= H) Do Begin
  2299. I := (L + H) SHR 1; { Mid point }
  2300. C := Compare(KeyOf(Items^[I]), Key); { Compare with key }
  2301. If (C < 0) Then L := I + 1 Else Begin { Item to left }
  2302. H := I - 1; { Item to right }
  2303. If C = 0 Then Begin { Item match found }
  2304. Search := True; { Result true }
  2305. If NOT Duplicates Then L := I; { Force kick out }
  2306. End;
  2307. End;
  2308. End;
  2309. Index := L; { Return result }
  2310. END;
  2311. {--TSortedCollection--------------------------------------------------------}
  2312. { Insert -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 22May96 LdB }
  2313. {---------------------------------------------------------------------------}
  2314. PROCEDURE TSortedCollection.Insert (Item: Pointer);
  2315. VAR I: Integer;
  2316. BEGIN
  2317. If NOT Search(KeyOf(Item), I) OR Duplicates Then { Item valid }
  2318. AtInsert(I, Item); { Insert the item }
  2319. END;
  2320. {--TSortedCollection--------------------------------------------------------}
  2321. { Store -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 22May96 LdB }
  2322. {---------------------------------------------------------------------------}
  2323. PROCEDURE TSortedCollection.Store (Var S: TStream);
  2324. BEGIN
  2325. TCollection.Store(S); { Call ancestor }
  2326. S.Write(Duplicates, 1); { Write duplicate flag }
  2327. END;
  2328. {+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++}
  2329. { TStringCollection OBJECT METHODS }
  2330. {+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++}
  2331. {--TStringCollection--------------------------------------------------------}
  2332. { GetItem -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 22May96 LdB }
  2333. {---------------------------------------------------------------------------}
  2334. FUNCTION TStringCollection.GetItem (Var S: TStream): Pointer;
  2335. BEGIN
  2336. GetItem := S.ReadStr; { Get new item }
  2337. END;
  2338. {--TStringCollection--------------------------------------------------------}
  2339. { Compare -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 21Aug97 LdB }
  2340. {---------------------------------------------------------------------------}
  2341. FUNCTION TStringCollection.Compare (Key1, Key2: Pointer): Integer;
  2342. VAR I, J: Integer; P1, P2: PString;
  2343. BEGIN
  2344. P1 := PString(Key1); { String 1 pointer }
  2345. P2 := PString(Key2); { String 2 pointer }
  2346. If (Length(P1^)<Length(P2^)) Then J := Length(P1^)
  2347. Else J := Length(P2^); { Shortest length }
  2348. I := 1; { First character }
  2349. While (I<J) AND (P1^[I]=P2^[I]) Do Inc(I); { Scan till fail }
  2350. If (I=J) Then Begin { Possible match }
  2351. { * REMARK * - Bug fix 21 August 1997 }
  2352. If (P1^[I]<P2^[I]) Then Compare := -1 Else { String1 < String2 }
  2353. If (P1^[I]>P2^[I]) Then Compare := 1 Else { String1 > String2 }
  2354. If (Length(P1^)>Length(P2^)) Then Compare := 1 { String1 > String2 }
  2355. Else If (Length(P1^)<Length(P2^)) Then { String1 < String2 }
  2356. Compare := -1 Else Compare := 0; { String1 = String2 }
  2357. { * REMARK END * - Leon de Boer }
  2358. End Else If (P1^[I]<P2^[I]) Then Compare := -1 { String1 < String2 }
  2359. Else Compare := 1; { String1 > String2 }
  2360. END;
  2361. {--TStringCollection--------------------------------------------------------}
  2362. { FreeItem -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 22May96 LdB }
  2363. {---------------------------------------------------------------------------}
  2364. PROCEDURE TStringCollection.FreeItem (Item: Pointer);
  2365. BEGIN
  2366. DisposeStr(Item); { Dispose item }
  2367. END;
  2368. {--TStringCollection--------------------------------------------------------}
  2369. { PutItem -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 22May96 LdB }
  2370. {---------------------------------------------------------------------------}
  2371. PROCEDURE TStringCollection.PutItem (Var S: TStream; Item: Pointer);
  2372. BEGIN
  2373. S.WriteStr(Item); { Write string }
  2374. END;
  2375. {+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++}
  2376. { TStrCollection OBJECT METHODS }
  2377. {+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++}
  2378. {--TStrCollection-----------------------------------------------------------}
  2379. { Compare -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 23May96 LdB }
  2380. {---------------------------------------------------------------------------}
  2381. FUNCTION TStrCollection.Compare (Key1, Key2: Pointer): Integer;
  2382. VAR I, J: Integer; P1, P2: PByteArray;
  2383. BEGIN
  2384. P1 := PByteArray(Key1); { PChar 1 pointer }
  2385. P2 := PByteArray(Key2); { PChar 2 pointer }
  2386. I := 0; { Preset no size }
  2387. If (P1 <> Nil) Then While (P1^[I] <> 0) Do Inc(I); { PChar 1 length }
  2388. J := 0; { Preset no size }
  2389. If (P2 <> Nil) Then While (P2^[J] <> 0) Do Inc(J); { PChar 2 length }
  2390. If (I < J) Then J := I; { Shortest length }
  2391. I := 0; { First character }
  2392. While (I < J) AND (P1^[I] = P2^[I]) Do Inc(I); { Scan till fail }
  2393. If (P1^[I] = P2^[I]) Then Compare := 0 Else { Strings matched }
  2394. If (P1^[I] < P2^[I]) Then Compare := -1 Else { String1 < String2 }
  2395. Compare := 1; { String1 > String2 }
  2396. END;
  2397. {--TStrCollection-----------------------------------------------------------}
  2398. { GetItem -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 23May96 LdB }
  2399. {---------------------------------------------------------------------------}
  2400. FUNCTION TStrCollection.GetItem (Var S: TStream): Pointer;
  2401. BEGIN
  2402. GetItem := S.StrRead; { Get string item }
  2403. END;
  2404. {--TStrCollection-----------------------------------------------------------}
  2405. { FreeItem -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 23May96 LdB }
  2406. {---------------------------------------------------------------------------}
  2407. PROCEDURE TStrCollection.FreeItem (Item: Pointer);
  2408. VAR I: Integer; P: PByteArray;
  2409. BEGIN
  2410. If (Item <> Nil) Then Begin { Item is valid }
  2411. P := PByteArray(Item); { Create byte pointer }
  2412. I := 0; { Preset no size }
  2413. While (P^[I] <> 0) Do Inc(I); { Find PChar end }
  2414. FreeMem(Item, I+1); { Release memory }
  2415. End;
  2416. END;
  2417. {--TStrCollection-----------------------------------------------------------}
  2418. { PutItem -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 23May96 LdB }
  2419. {---------------------------------------------------------------------------}
  2420. PROCEDURE TStrCollection.PutItem (Var S: TStream; Item: Pointer);
  2421. BEGIN
  2422. S.StrWrite(Item); { Write the string }
  2423. END;
  2424. {+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++}
  2425. { TUnSortedStrCollection OBJECT METHODS }
  2426. {+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++}
  2427. {--TUnSortedCollection------------------------------------------------------}
  2428. { Insert -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 23May96 LdB }
  2429. {---------------------------------------------------------------------------}
  2430. PROCEDURE TUnSortedStrCollection.Insert (Item: Pointer);
  2431. BEGIN
  2432. AtInsert(Count, Item); { Insert - NO sorting }
  2433. END;
  2434. {+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++}
  2435. { TResourceItem RECORD }
  2436. {+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++}
  2437. TYPE
  2438. TResourceItem = PACKED RECORD
  2439. Posn: LongInt; { Resource position }
  2440. Size: LongInt; { Resource size }
  2441. Key : String; { Resource key }
  2442. End;
  2443. PResourceItem = ^TResourceItem;
  2444. {+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++}
  2445. { TResourceCollection OBJECT METHODS }
  2446. {+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++}
  2447. {--TResourceCollection------------------------------------------------------}
  2448. { KeyOf -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 24May96 LdB }
  2449. {---------------------------------------------------------------------------}
  2450. FUNCTION TResourceCollection.KeyOf (Item: Pointer): Pointer;
  2451. BEGIN
  2452. KeyOf := @PResourceItem(Item)^.Key; { Pointer to key }
  2453. END;
  2454. {--TResourceCollection------------------------------------------------------}
  2455. { GetItem -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 24May96 LdB }
  2456. {---------------------------------------------------------------------------}
  2457. FUNCTION TResourceCollection.GetItem (Var S: TStream): Pointer;
  2458. VAR B: Byte; Pos, Size: LongInt; P: PResourceItem; Ts: String;
  2459. BEGIN
  2460. S.Read(Pos, 4); { Read position }
  2461. S.Read(Size, 4); { Read size }
  2462. S.Read(B, 1); { Read key length }
  2463. If (MaxAvail > (SizeOf(TResourceItem)-SizeOf(Ts)))
  2464. Then Begin
  2465. GetMem(P, B + (SizeOf(TResourceItem) -
  2466. SizeOf(Ts) + 1)); { Allocate min memory }
  2467. P^.Posn := Pos; { Xfer position }
  2468. P^.Size := Size; { Xfer size }
  2469. {$IFDEF PPC_DELPHI3} { DELPHI 3+ COMPILER }
  2470. SetLength(P^.Key, B); { Xfer string length }
  2471. {$ELSE} { OTHER COMPILERS }
  2472. P^.Key[0] := Chr(B); { Xfer string length }
  2473. {$ENDIF}
  2474. S.Read(P^.Key[1], B); { Xfer string data }
  2475. End Else P := Nil; { Insufficient memory }
  2476. GetItem := P; { Return pointer }
  2477. END;
  2478. {--TResourceCollection------------------------------------------------------}
  2479. { FreeItem -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 24May96 LdB }
  2480. {---------------------------------------------------------------------------}
  2481. PROCEDURE TResourceCollection.FreeItem (Item: Pointer);
  2482. VAR S: String;
  2483. BEGIN
  2484. If (Item <> Nil) Then FreeMem(Item,
  2485. SizeOf(TResourceItem) - SizeOf(S) +
  2486. Length(PResourceItem(Item)^.Key) + 1); { Release memory }
  2487. END;
  2488. {--TResourceCollection------------------------------------------------------}
  2489. { PutItem -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 24May96 LdB }
  2490. {---------------------------------------------------------------------------}
  2491. PROCEDURE TResourceCollection.PutItem (Var S: TStream; Item: Pointer);
  2492. VAR Ts: String;
  2493. BEGIN
  2494. If (Item <> Nil) Then S.Write(PResourceItem(Item)^,
  2495. SizeOf(TResourceItem) - SizeOf(Ts) +
  2496. Length(PResourceItem(Item)^.Key) + 1); { Write to stream }
  2497. END;
  2498. {+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++}
  2499. { PRIVATE RESOURCE MANAGER CONSTANTS }
  2500. {+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++}
  2501. CONST
  2502. RStreamMagic: LongInt = $52504246; { 'FBPR' }
  2503. RStreamBackLink: LongInt = $4C424246; { 'FBBL' }
  2504. {+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++}
  2505. { PRIVATE RESOURCE MANAGER TYPES }
  2506. {+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++}
  2507. TYPE
  2508. {$IFDEF NewExeFormat} { New EXE format }
  2509. TExeHeader = PACKED RECORD
  2510. eHdrSize: Word;
  2511. eMinAbove: Word;
  2512. eMaxAbove: Word;
  2513. eInitSS: Word;
  2514. eInitSP: Word;
  2515. eCheckSum: Word;
  2516. eInitPC: Word;
  2517. eInitCS: Word;
  2518. eRelocOfs: Word;
  2519. eOvlyNum: Word;
  2520. eRelocTab: Word;
  2521. eSpace: Array[1..30] of Byte;
  2522. eNewHeader: Word;
  2523. END;
  2524. {$ENDIF}
  2525. THeader = PACKED RECORD
  2526. Signature: Word;
  2527. Case Integer Of
  2528. 0: (
  2529. LastCount: Word;
  2530. PageCount: Word;
  2531. ReloCount: Word);
  2532. 1: (
  2533. InfoType: Word;
  2534. InfoSize: Longint);
  2535. End;
  2536. {+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++}
  2537. { TResourceFile OBJECT METHODS }
  2538. {+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++}
  2539. {--TResourceFile------------------------------------------------------------}
  2540. { Init -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 18Jun96 LdB }
  2541. {---------------------------------------------------------------------------}
  2542. CONSTRUCTOR TResourceFile.Init(AStream: PStream);
  2543. VAR Found, Stop: Boolean; Header: THeader;
  2544. {$IFDEF NewExeFormat} ExeHeader: TExeHeader; {$ENDIF}
  2545. BEGIN
  2546. TObject.Init; { Initialize object }
  2547. Found := False; { Preset false }
  2548. If (AStream <> Nil) Then Begin
  2549. Stream := AStream; { Hold stream }
  2550. BasePos := Stream^.GetPos; { Get position }
  2551. Repeat
  2552. Stop := True; { Preset stop }
  2553. If (BasePos <= Stream^.GetSize-SizeOf(THeader))
  2554. Then Begin { Valid file header }
  2555. Stream^.Seek(BasePos); { Seek to position }
  2556. Stream^.Read(Header, SizeOf(THeader)); { Read header }
  2557. Case Header.Signature Of
  2558. {$IFDEF NewExeFormat} { New format file }
  2559. $5A4D: Begin
  2560. Stream^.Read(ExeHeader, SizeOf(TExeHeader));
  2561. BasePos := ExeHeader.eNewHeader; { Hold position }
  2562. Stop := False; { Clear stop flag }
  2563. End;
  2564. $454E: Begin
  2565. BasePos := Stream^.GetSize - 8; { Hold position }
  2566. Stop := False; { Clear stop flag }
  2567. End;
  2568. $4246: Begin
  2569. Stop := False; { Clear stop flag }
  2570. Case Header.Infotype Of
  2571. $5250: Begin { Found Resource }
  2572. Found := True; { Found flag is true }
  2573. Stop := True; { Set stop flag }
  2574. End;
  2575. $4C42: Dec(BasePos, Header.InfoSize-8);{ Found BackLink }
  2576. $4648: Dec(BasePos, SizeOf(THeader)*2);{ Found HelpFile }
  2577. Else Stop := True; { Set stop flag }
  2578. End;
  2579. End;
  2580. $424E: If Header.InfoType = $3230 { Found Debug Info }
  2581. Then Begin
  2582. Dec(BasePos, Header.InfoSize); { Adjust position }
  2583. Stop := False; { Clear stop flag }
  2584. End;
  2585. {$ELSE} { Old EXE format }
  2586. $5A4D: Begin
  2587. Inc(BasePos, LongInt(Header.PageCount)*512
  2588. - (-Header.LastCount AND 511)); { Calc position }
  2589. Stop := False; { Clear stop flag }
  2590. End;
  2591. $4246: If Header.InfoType = $5250 Then { Header was found }
  2592. Found := True Else Begin
  2593. Inc(BasePos, Header.InfoSize + 8); { Adjust position }
  2594. Stop := False; { Clear stop flag }
  2595. End;
  2596. {$ENDIF}
  2597. End;
  2598. End;
  2599. Until Stop; { Until flag is set }
  2600. End;
  2601. If Found Then Begin { Resource was found }
  2602. Stream^.Seek(BasePos + SizeOf(LongInt) * 2); { Seek to position }
  2603. Stream^.Read(IndexPos, SizeOf(LongInt)); { Read index position }
  2604. Stream^.Seek(BasePos + IndexPos); { Seek to resource }
  2605. Index.Load(Stream^); { Load resource }
  2606. End Else Begin
  2607. IndexPos := SizeOf(LongInt) * 3; { Set index position }
  2608. Index.Init(0, 8); { Set index }
  2609. End;
  2610. END;
  2611. {--TResourceFile------------------------------------------------------------}
  2612. { Done -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 18Jun96 LdB }
  2613. {---------------------------------------------------------------------------}
  2614. DESTRUCTOR TResourceFile.Done;
  2615. BEGIN
  2616. Flush; { Flush the file }
  2617. Index.Done; { Dispose of index }
  2618. If (Stream <> Nil) Then Dispose(Stream, Done); { Dispose of stream }
  2619. END;
  2620. {--TResourceFile------------------------------------------------------------}
  2621. { Count -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 18Jun96 LdB }
  2622. {---------------------------------------------------------------------------}
  2623. FUNCTION TResourceFile.Count: Integer;
  2624. BEGIN
  2625. Count := Index.Count; { Return index count }
  2626. END;
  2627. {--TResourceFile------------------------------------------------------------}
  2628. { KeyAt -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 18Jun96 LdB }
  2629. {---------------------------------------------------------------------------}
  2630. FUNCTION TResourceFile.KeyAt (I: Integer): String;
  2631. BEGIN
  2632. KeyAt := PResourceItem(Index.At(I))^.Key; { Return key }
  2633. END;
  2634. {--TResourceFile------------------------------------------------------------}
  2635. { Get -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 18Jun96 LdB }
  2636. {---------------------------------------------------------------------------}
  2637. FUNCTION TResourceFile.Get (Key: String): PObject;
  2638. VAR I: Integer;
  2639. BEGIN
  2640. If (Stream = Nil) OR (NOT Index.Search(@Key, I)) { No match on key }
  2641. Then Get := Nil Else Begin
  2642. Stream^.Seek(BasePos +
  2643. PResourceItem(Index.At(I))^.Posn); { Seek to position }
  2644. Get := Stream^.Get; { Get item }
  2645. End;
  2646. END;
  2647. {--TResourceFile------------------------------------------------------------}
  2648. { SwitchTo -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 18Jun96 LdB }
  2649. {---------------------------------------------------------------------------}
  2650. FUNCTION TResourceFile.SwitchTo (AStream: PStream; Pack: Boolean): PStream;
  2651. VAR NewBasePos: LongInt;
  2652. PROCEDURE DoCopyResource (Item: PResourceItem); {$IFNDEF FPC} FAR; {$ENDIF}
  2653. BEGIN
  2654. Stream^.Seek(BasePos + Item^.Posn); { Move stream position }
  2655. Item^.Posn := AStream^.GetPos - NewBasePos; { Hold new position }
  2656. AStream^.CopyFrom(Stream^, Item^.Size); { Copy the item }
  2657. END;
  2658. BEGIN
  2659. SwitchTo := Stream; { Preset return }
  2660. If (AStream <> Nil) AND (Stream <> Nil) Then Begin { Both streams valid }
  2661. NewBasePos := AStream^.GetPos; { Get position }
  2662. If Pack Then Begin
  2663. AStream^.Seek(NewBasePos + SizeOf(LongInt)*3); { Seek to position }
  2664. Index.ForEach(@DoCopyResource); { Copy each resource }
  2665. IndexPos := AStream^.GetPos - NewBasePos; { Hold index position }
  2666. End Else Begin
  2667. Stream^.Seek(BasePos); { Seek to position }
  2668. AStream^.CopyFrom(Stream^, IndexPos); { Copy the resource }
  2669. End;
  2670. Stream := AStream; { Hold new stream }
  2671. BasePos := NewBasePos; { New base position }
  2672. Modified := True; { Set modified flag }
  2673. End;
  2674. END;
  2675. {--TResourceFile------------------------------------------------------------}
  2676. { Flush -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 18Jun96 LdB }
  2677. {---------------------------------------------------------------------------}
  2678. PROCEDURE TResourceFile.Flush;
  2679. VAR ResSize: LongInt; LinkSize: LongInt;
  2680. BEGIN
  2681. If (Modified) AND (Stream <> Nil) Then Begin { We have modification }
  2682. Stream^.Seek(BasePos + IndexPos); { Seek to position }
  2683. Index.Store(Stream^); { Store the item }
  2684. ResSize := Stream^.GetPos - BasePos; { Hold position }
  2685. LinkSize := ResSize + SizeOf(LongInt) * 2; { Hold link size }
  2686. Stream^.Write(RStreamBackLink, SizeOf(LongInt)); { Write link back }
  2687. Stream^.Write(LinkSize, SizeOf(LongInt)); { Write link size }
  2688. Stream^.Seek(BasePos); { Move stream position }
  2689. Stream^.Write(RStreamMagic, SizeOf(LongInt)); { Write number }
  2690. Stream^.Write(ResSize, SizeOf(LongInt)); { Write record size }
  2691. Stream^.Write(IndexPos, SizeOf(LongInt)); { Write index position }
  2692. Stream^.Flush; { Flush the stream }
  2693. End;
  2694. Modified := False; { Clear modified flag }
  2695. END;
  2696. {--TResourceFile------------------------------------------------------------}
  2697. { Delete -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 18Jun96 LdB }
  2698. {---------------------------------------------------------------------------}
  2699. PROCEDURE TResourceFile.Delete (Key: String);
  2700. VAR I: Integer;
  2701. BEGIN
  2702. If Index.Search(@Key, I) Then Begin { Search for key }
  2703. Index.Free(Index.At(I)); { Delete from index }
  2704. Modified := True; { Set modified flag }
  2705. End;
  2706. END;
  2707. {--TResourceFile------------------------------------------------------------}
  2708. { Put -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 18Jun96 LdB }
  2709. {---------------------------------------------------------------------------}
  2710. PROCEDURE TResourceFile.Put (Item: PObject; Key: String);
  2711. VAR I: Integer; P: PResourceItem;
  2712. BEGIN
  2713. If (Stream = Nil) Then Exit; { Stream not valid }
  2714. If Index.Search(@Key, I) Then P := Index.At(I) { Search for item }
  2715. Else Begin
  2716. If (MaxAvail > SizeOf(TResourceItem)-SizeOf(Key)){ Check free memory }
  2717. Then Begin
  2718. GetMem(P, Length(Key) + (SizeOf(TResourceItem)
  2719. - SizeOf(Key) + 1)); { Allocate memory }
  2720. P^.Key := Key; { Store key }
  2721. Index.AtInsert(I, P); { Insert item }
  2722. End Else P := Nil; { Insufficient memory }
  2723. End;
  2724. If (P <> Nil) Then Begin { Allocate worked }
  2725. P^.Posn := IndexPos; { Set index position }
  2726. Stream^.Seek(BasePos + IndexPos); { Seek file position }
  2727. Stream^.Put(Item); { Put item on stream }
  2728. IndexPos := Stream^.GetPos - BasePos; { Hold index position }
  2729. P^.Size := IndexPos - P^.Posn; { Calc size }
  2730. Modified := True; { Set modified flag }
  2731. End;
  2732. END;
  2733. {+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++}
  2734. { TStringList OBJECT METHODS }
  2735. {+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++}
  2736. {--TStringList--------------------------------------------------------------}
  2737. { Load -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 30Jun97 LdB }
  2738. {---------------------------------------------------------------------------}
  2739. CONSTRUCTOR TStringList.Load (Var S: TStream);
  2740. VAR Size: Word;
  2741. BEGIN
  2742. Stream := @S; { Hold stream pointer }
  2743. S.Read(Size, SizeOf(Word)); { Read size }
  2744. BasePos := S.GetPos; { Hold position }
  2745. S.Seek(BasePos + Size); { Seek to position }
  2746. S.Read(IndexSize, SizeOf(Integer)); { Read index size }
  2747. If (MaxAvail >= IndexSize * SizeOf(TStrIndexRec)) { Check free memory }
  2748. Then Begin
  2749. GetMem(Index, IndexSize * SizeOf(TStrIndexRec)); { Allocate memory }
  2750. S.Read(Index^, IndexSize * SizeOf(TStrIndexRec));{ Read indexes }
  2751. End Else IndexSize := 0; { Insufficient memory }
  2752. END;
  2753. {--TStringList--------------------------------------------------------------}
  2754. { Done -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 30Jun97 LdB }
  2755. {---------------------------------------------------------------------------}
  2756. DESTRUCTOR TStringList.Done;
  2757. BEGIN
  2758. FreeMem(Index, IndexSize * SizeOf(TStrIndexRec)); { Release memory }
  2759. END;
  2760. {--TStringList--------------------------------------------------------------}
  2761. { Get -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 30Jun97 LdB }
  2762. {---------------------------------------------------------------------------}
  2763. FUNCTION TStringList.Get (Key: Word): String;
  2764. VAR I: Word; S: String;
  2765. BEGIN
  2766. S := ''; { Preset empty string }
  2767. If (IndexSize > 0) Then Begin { We must have strings }
  2768. I := 0; { First entry }
  2769. While (I < IndexSize) AND (S = '') Do Begin
  2770. If ((Key - Index^[I].Key) < Index^[I].Count) { Diff less than count }
  2771. Then ReadStr(S, Index^[I].Offset,
  2772. Key-Index^[I].Key); { Read the string }
  2773. Inc(I); { Next entry }
  2774. End;
  2775. End;
  2776. Get := S; { Return empty string }
  2777. END;
  2778. {***************************************************************************}
  2779. { TStringList PRIVATE METHODS }
  2780. {***************************************************************************}
  2781. {--TStringList--------------------------------------------------------------}
  2782. { ReadStr -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 30Jun97 LdB }
  2783. {---------------------------------------------------------------------------}
  2784. PROCEDURE TStringList.ReadStr (Var S: String; Offset, Skip: Word);
  2785. VAR B: Byte;
  2786. BEGIN
  2787. Stream^.Seek(BasePos + Offset); { Seek to position }
  2788. Inc(Skip); { Adjust skip }
  2789. Repeat
  2790. Stream^.Read(B, 1); { Read string size }
  2791. {$IFDEF PPC_DELPHI3} { DELPHI 3+ COMPILER }
  2792. SetLength(S, B); { Xfer string length }
  2793. {$ELSE} { OTHER COMPILERS }
  2794. S[0] := Chr(B); { Xfer string size }
  2795. {$ENDIF}
  2796. Stream^.Read(S[1], B); { Read string data }
  2797. Dec(Skip); { One string read }
  2798. Until (Skip = 0);
  2799. END;
  2800. {+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++}
  2801. { TStrListMaker OBJECT METHODS }
  2802. {+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++}
  2803. {--TStrListMaker------------------------------------------------------------}
  2804. { Init -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 30Jun97 LdB }
  2805. {---------------------------------------------------------------------------}
  2806. CONSTRUCTOR TStrListMaker.Init (AStrSize, AIndexSize: Word);
  2807. BEGIN
  2808. Inherited Init; { Call ancestor }
  2809. StrSize := AStrSize; { Hold size }
  2810. If (MaxAvail >= AStrSize) Then
  2811. GetMem(Strings, AStrSize); { Allocate memory }
  2812. If (MaxAvail >= AIndexSize * SizeOf(TStrIndexRec)) { Check free memory }
  2813. Then Begin
  2814. IndexSize := AIndexSize; { Hold index size }
  2815. GetMem(Index, AIndexSize * SizeOf(TStrIndexRec));{ Allocate memory }
  2816. End;
  2817. END;
  2818. {--TStrListMaker------------------------------------------------------------}
  2819. { Done -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 30Jun97 LdB }
  2820. {---------------------------------------------------------------------------}
  2821. DESTRUCTOR TStrListMaker.Done;
  2822. BEGIN
  2823. FreeMem(Index, IndexSize * SizeOf(TStrIndexRec)); { Free index memory }
  2824. FreeMem(Strings, StrSize); { Free data memory }
  2825. END;
  2826. {--TStrListMaker------------------------------------------------------------}
  2827. { Put -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 30Jun97 LdB }
  2828. {---------------------------------------------------------------------------}
  2829. PROCEDURE TStrListMaker.Put (Key: Word; S: String);
  2830. BEGIN
  2831. If (Cur.Count = 16) OR (Key <> Cur.Key + Cur.Count)
  2832. Then CloseCurrent; { Close current }
  2833. If (Cur.Count = 0) Then Begin
  2834. Cur.Key := Key; { Set key }
  2835. Cur.Offset := StrPos; { Set offset }
  2836. End;
  2837. Inc(Cur.Count); { Inc count }
  2838. Move(S, Strings^[StrPos], Length(S) + 1); { Move string data }
  2839. Inc(StrPos, Length(S) + 1); { Adjust position }
  2840. END;
  2841. {--TStrListMaker------------------------------------------------------------}
  2842. { Store -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 30Jun97 LdB }
  2843. {---------------------------------------------------------------------------}
  2844. PROCEDURE TStrListMaker.Store (Var S: TStream);
  2845. BEGIN
  2846. CloseCurrent; { Close all current }
  2847. S.Write(StrPos, SizeOf(Word)); { Write position }
  2848. S.Write(Strings^, StrPos); { Write string data }
  2849. S.Write(IndexPos, SizeOf(Word)); { Write index position }
  2850. S.Write(Index^, IndexPos * SizeOf(TStrIndexRec)); { Write indexes }
  2851. END;
  2852. {***************************************************************************}
  2853. { TStrListMaker PRIVATE METHODS }
  2854. {***************************************************************************}
  2855. {--TStrListMaker------------------------------------------------------------}
  2856. { CloseCurrent -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 30Jun97 LdB }
  2857. {---------------------------------------------------------------------------}
  2858. PROCEDURE TStrListMaker.CloseCurrent;
  2859. BEGIN
  2860. If (Cur.Count <> 0) Then Begin
  2861. Index^[IndexPos] := Cur; { Hold index position }
  2862. Inc(IndexPos); { Next index }
  2863. Cur.Count := 0; { Adjust count }
  2864. End;
  2865. END;
  2866. {***************************************************************************}
  2867. { INTERFACE ROUTINES }
  2868. {***************************************************************************}
  2869. {+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++}
  2870. { STREAM INTERFACE ROUTINES }
  2871. {+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++}
  2872. {---------------------------------------------------------------------------}
  2873. { Abstract -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 12Jun96 LdB }
  2874. {---------------------------------------------------------------------------}
  2875. PROCEDURE Abstract;
  2876. BEGIN
  2877. RunError(211); { Abstract error }
  2878. END;
  2879. {---------------------------------------------------------------------------}
  2880. { RegisterObjects -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 02Sep97 LdB }
  2881. {---------------------------------------------------------------------------}
  2882. PROCEDURE RegisterObjects;
  2883. BEGIN
  2884. RegisterType(RCollection); { Register object }
  2885. RegisterType(RStringCollection); { Register object }
  2886. RegisterType(RStrCollection); { Register object }
  2887. END;
  2888. {---------------------------------------------------------------------------}
  2889. { RegisterType -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 02Sep97 LdB }
  2890. {---------------------------------------------------------------------------}
  2891. PROCEDURE RegisterType (Var S: TStreamRec);
  2892. VAR P: PStreamRec;
  2893. BEGIN
  2894. P := StreamTypes; { Current reg list }
  2895. While (P <> Nil) AND (P^.ObjType <> S.ObjType)
  2896. Do P := P^.Next; { Find end of chain }
  2897. If (P = Nil) AND (S.ObjType <> 0) Then Begin { Valid end found }
  2898. S.Next := StreamTypes; { Chain the list }
  2899. StreamTypes := @S; { We are now first }
  2900. End Else RegisterError; { Register the error }
  2901. END;
  2902. {+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++}
  2903. { GENERAL FUNCTION INTERFACE ROUTINES }
  2904. {+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++}
  2905. {---------------------------------------------------------------------------}
  2906. { LongMul -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 10Feb98 LdB }
  2907. {---------------------------------------------------------------------------}
  2908. FUNCTION LongMul (X, Y: Integer): LongInt;
  2909. BEGIN
  2910. LongMul := LongInt(X*Y); { Multiply integers }
  2911. END;
  2912. {---------------------------------------------------------------------------}
  2913. { LongDiv -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 10Feb98 LdB }
  2914. {---------------------------------------------------------------------------}
  2915. FUNCTION LongDiv (X: LongInt; Y: Integer): Integer;
  2916. BEGIN
  2917. LongDiv := Integer(X DIV Y); { Divid longint }
  2918. END;
  2919. {+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++}
  2920. { DYNAMIC STRING INTERFACE ROUTINES }
  2921. {+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++}
  2922. {---------------------------------------------------------------------------}
  2923. { NewStr -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 12Jun96 LdB }
  2924. {---------------------------------------------------------------------------}
  2925. FUNCTION NewStr (S: String): PString;
  2926. VAR P: PString;
  2927. BEGIN
  2928. If (S = '') Then P := Nil Else Begin { Empty returns nil }
  2929. If (MaxAvail > Length(S)) Then Begin { Check free memory }
  2930. GetMem(P, Length(S) + 1); { Allocate memory }
  2931. If (P <> Nil) Then P^ := S; { Transfer string }
  2932. End Else P := Nil; { Insufficient memory }
  2933. End;
  2934. NewStr := P; { Return result }
  2935. END;
  2936. {---------------------------------------------------------------------------}
  2937. { DisposeStr -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 12Jun96 LdB }
  2938. {---------------------------------------------------------------------------}
  2939. PROCEDURE DisposeStr (P: PString);
  2940. BEGIN
  2941. If (P <> Nil) Then FreeMem(P, Length(P^) + 1); { Release memory }
  2942. END;
  2943. END.