You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809281028112812281328142815281628172818281928202821282228232824282528262827282828292830283128322833283428352836283728382839284028412842284328442845284628472848284928502851285228532854285528562857285828592860286128622863286428652866286728682869287028712872287328742875287628772878287928802881288228832884288528862887288828892890289128922893289428952896289728982899290029012902290329042905290629072908290929102911291229132914291529162917291829192920292129222923292429252926292729282929293029312932293329342935293629372938293929402941294229432944294529462947294829492950295129522953295429552956295729582959296029612962296329642965296629672968296929702971297229732974297529762977297829792980298129822983298429852986298729882989299029912992299329942995299629972998299930003001300230033004300530063007300830093010301130123013301430153016301730183019302030213022302330243025302630273028302930303031303230333034303530363037303830393040304130423043304430453046304730483049305030513052305330543055305630573058305930603061306230633064306530663067306830693070307130723073307430753076307730783079308030813082308330843085308630873088308930903091309230933094309530963097309830993100310131023103310431053106310731083109311031113112311331143115311631173118311931203121312231233124312531263127312831293130313131323133313431353136313731383139314031413142314331443145314631473148314931503151315231533154315531563157315831593160316131623163316431653166316731683169317031713172317331743175317631773178317931803181318231833184318531863187318831893190319131923193319431953196319731983199320032013202320332043205320632073208320932103211321232133214321532163217321832193220322132223223322432253226322732283229323032313232323332343235323632373238323932403241324232433244324532463247324832493250325132523253325432553256325732583259326032613262326332643265326632673268326932703271327232733274327532763277327832793280328132823283328432853286328732883289329032913292329332943295329632973298329933003301330233033304330533063307330833093310331133123313331433153316331733183319332033213322332333243325332633273328332933303331333233333334333533363337333833393340334133423343334433453346334733483349335033513352335333543355335633573358335933603361336233633364336533663367336833693370337133723373337433753376337733783379338033813382338333843385338633873388338933903391339233933394339533963397339833993400340134023403340434053406340734083409341034113412341334143415341634173418341934203421342234233424342534263427342834293430343134323433343434353436343734383439344034413442344334443445344634473448344934503451345234533454345534563457345834593460346134623463346434653466346734683469347034713472347334743475347634773478347934803481348234833484348534863487348834893490349134923493349434953496349734983499350035013502350335043505350635073508350935103511351235133514351535163517351835193520352135223523352435253526352735283529353035313532353335343535353635373538353935403541354235433544354535463547354835493550355135523553355435553556355735583559356035613562356335643565356635673568356935703571357235733574357535763577357835793580358135823583358435853586358735883589359035913592359335943595359635973598359936003601360236033604360536063607360836093610361136123613361436153616361736183619
  1. //[START OF KOL.pas]
  2. {****************************************************************
  3. d d
  4. KKKKK KKKKK OOOOOOOOO LLLLL d d
  5. KKKKK KKKKK OOOOOOOOOOOOO LLLLL d d
  6. KKKKK KKKKK OOOOO OOOOO LLLLL aaaa d d
  7. KKKKK KKKKK OOOOO OOOOO LLLLL a d d
  8. KKKKKKKKKK OOOOO OOOOO LLLLL a d d
  9. KKKKK KKKKK OOOOO OOOOO LLLLL aaaaa dddddd dddddd
  10. KKKKK KKKKK OOOOO OOOOO LLLLL a a d d d d
  11. KKKKK KKKKK OOOOOOOOOOOOO LLLLLLLLLLLLL a a d d d d
  12. KKKKK KKKKK OOOOOOOOO LLLLLLLLLLLLL aaaaa aa dddddd dddddd
  13. Key Objects Library (C) 2000 by Kladov Vladimir.
  14. //[VERSION]
  15. ****************************************************************
  16. * VERSION 2.75
  17. ****************************************************************
  18. //[END OF VERSION]
  19. The only reason why this part of KOL separated into another unit is that
  20. Delphi has a restriction to DCU size exceeding which it is failed to debug
  21. it normally and in attempt to execute code step by step an internal error
  22. is occur which stops Delphi from working at all.
  23. Version indicated above is a version of KOL, having place when KOLadd.pas was
  24. modified last time, this is not a version of KOLadd itself.
  25. }
  26. {$ifdef FPC} {$mode delphi} {$endif FPC}
  27. unit KOLadd;
  28. {*
  29. Define symbol TREE_NONAME to disallow using Name in TTree object.
  30. Define symbol TREE_WIDE to use WideString for Name in TTree object.
  31. }
  32. {$IFDEF EXTERNAL_DEFINES}
  33. {$INCLUDE EXTERNAL_DEFINES.INC}
  34. {$ENDIF EXTERNAL_DEFINES}
  35. interface
  36. {$I KOLDEF.INC}
  37. uses Windows, Messages, KOL {$IFDEF USE_GRUSH}, ToGrush {$ENDIF};
  38. {------------------------------------------------------------------------------)
  39. | |
  40. | T L i s t E x |
  41. | |
  42. (------------------------------------------------------------------------------}
  43. type
  44. //[TListEx DEFINITION]
  45. {++}(*TListEx = class;*){--}
  46. PListEx = {-}^{+}TListEx;
  47. TListEx = object( TObj )
  48. {* Extended list, with Objects[ ] property. Created calling NewListEx function. }
  49. protected
  50. fList: PList;
  51. fObjects: PList;
  52. function GetEx(Idx: Integer): Pointer;
  53. procedure PutEx(Idx: Integer; const Value: Pointer);
  54. function GetCount: Integer;
  55. function GetAddBy: Integer;
  56. procedure Set_AddBy(const Value: Integer);
  57. public
  58. destructor Destroy; {-}virtual;{+}{++}(*override;*){--}
  59. {* }
  60. property AddBy: Integer read GetAddBy write Set_AddBy;
  61. {* }
  62. property Items[ Idx: Integer ]: Pointer read GetEx write PutEx;
  63. {* }
  64. property Count: Integer read GetCount;
  65. {* }
  66. procedure Clear;
  67. {* }
  68. procedure Add( Value: Pointer );
  69. {* }
  70. procedure AddObj( Value, Obj: Pointer );
  71. {* }
  72. procedure Insert( Idx: Integer; Value: Pointer );
  73. {* }
  74. procedure InsertObj( Idx: Integer; Value, Obj: Pointer );
  75. {* }
  76. procedure Delete( Idx: Integer );
  77. {* }
  78. procedure DeleteRange( Idx, Len: Integer );
  79. {* }
  80. function IndexOf( Value: Pointer ): Integer;
  81. {* }
  82. function IndexOfObj( Obj: Pointer ): Integer;
  83. {* }
  84. procedure Swap( Idx1, Idx2: Integer );
  85. {* }
  86. procedure MoveItem( OldIdx, NewIdx: Integer );
  87. {* }
  88. property ItemsList: PList read fList;
  89. {* }
  90. property ObjList: PList read fObjects;
  91. {* }
  92. function Last: Pointer;
  93. {* }
  94. function LastObj: Pointer;
  95. {* }
  96. end;
  97. //[END OF TListEx DEFINITION]
  98. //[NewListEx DECLARATION]
  99. function NewListEx: PListEx;
  100. {* Creates extended list. }
  101. {------------------------------------------------------------------------------)
  102. | |
  103. | T B i t s |
  104. | |
  105. (------------------------------------------------------------------------------}
  106. type
  107. //[TBits DEFINITION]
  108. {++}(*TBits = class;*){--}
  109. PBits = {-}^{+}TBits;
  110. TBits = object( TObj )
  111. {* Variable-length bits array object. Created using function NewBits. See also
  112. |<a href="kol_pas.htm#Small bit arrays (max 32 bits in array)">
  113. Small bit arrays (max 32 bits in array)
  114. |</a>. }
  115. protected
  116. fList: PList;
  117. fCount: Integer;
  118. function GetBit(Idx: Integer): Boolean;
  119. procedure SetBit(Idx: Integer; const Value: Boolean);
  120. function GetCapacity: Integer;
  121. function GetSize: Integer;
  122. procedure SetCapacity(const Value: Integer);
  123. public
  124. destructor Destroy; {-}virtual;{+}{++}(*override;*){--}
  125. {* }
  126. property Bits[ Idx: Integer ]: Boolean read GetBit write SetBit;
  127. {* }
  128. property Size: Integer read GetSize;
  129. {* Size in bytes of the array. To get know number of bits, use property Count. }
  130. property Count: Integer read fCount;
  131. {* Number of bits an the array. }
  132. property Capacity: Integer read GetCapacity write SetCapacity;
  133. {* Number of bytes allocated. Can be set before assigning bit values
  134. to improve performance (minimizing amount of memory allocation
  135. operations). }
  136. function Copy( From, BitsCount: Integer ): PBits;
  137. {* Use this property to get a sub-range of bits starting from given bit
  138. and of BitsCount bits count. }
  139. function IndexOf( Value: Boolean ): Integer;
  140. {* Returns index of first bit with given value (True or False). }
  141. function OpenBit: Integer;
  142. {* Returns index of the first bit not set to true. }
  143. procedure Clear;
  144. {* Clears bits array. Count, Size and Capacity become 0. }
  145. function LoadFromStream( strm: PStream ): Integer;
  146. {* Loads bits from the stream. Data should be stored in the stream
  147. earlier using SaveToStream method. While loading, previous bits
  148. data are discarded and replaced with new one totally. In part,
  149. Count of bits also is changed. Count of bytes read from the stream
  150. while loading data is returned. }
  151. function SaveToStream( strm: PStream ): Integer;
  152. {* Saves entire array of bits to the stream. First, Count of bits
  153. in the array is saved, then all bytes containing bits data. }
  154. function Range( Idx, N: Integer ): PBits;
  155. {* Creates and returns new TBits object instance containing N bits
  156. starting from index Idx. If you call this method, you are responsible
  157. for destroying returned object when it become not neccessary. }
  158. procedure AssignBits( ToIdx: Integer; FromBits: PBits; FromIdx, N: Integer );
  159. {* Assigns bits from another bits array object. N bits are assigned
  160. starting at index ToIdx. }
  161. procedure InstallBits( FromIdx, N: Integer; Value: Boolean );
  162. {* Sets new Value for all bits in range [ FromIdx, FromIdx+Count-1 ]. }
  163. end;
  164. //[END OF TBits DEFINITION]
  165. //[NewBits DECLARATION]
  166. function NewBits: PBits;
  167. {* Creates variable-length bits array object. }
  168. {------------------------------------------------------------------------------)
  169. | |
  170. | T F a s t S t r L i s t |
  171. | |
  172. (------------------------------------------------------------------------------}
  173. type
  174. PFastStrListEx = ^TFastStrListEx;
  175. TFastStrListEx = object( TObj )
  176. private
  177. function GetItemLen(Idx: Integer): Integer;
  178. function GetObject(Idx: Integer): DWORD;
  179. procedure SetObject(Idx: Integer; const Value: DWORD);
  180. function GetValues(AName: PChar): PChar;
  181. protected
  182. procedure Init; virtual;
  183. protected
  184. fList: PList;
  185. fCount: Integer;
  186. fCaseSensitiveSort: Boolean;
  187. fTextBuf: PChar;
  188. fTextSiz: DWORD;
  189. fUsedSiz: DWORD;
  190. protected
  191. procedure ProvideSpace( AddSize: DWORD );
  192. function Get(Idx: integer): string;
  193. function GetTextStr: string;
  194. procedure Put(Idx: integer; const Value: string);
  195. procedure SetTextStr(const Value: string);
  196. function GetPChars( Idx: Integer ): PChar;
  197. {++}(*public*){--}
  198. destructor Destroy; {-}virtual;{+}{++}(*override;*){--}
  199. public
  200. function AddAnsi( const S: String ): Integer;
  201. {* Adds Ansi String to a list. }
  202. function AddAnsiObject( const S: String; Obj: DWORD ): Integer;
  203. {* Adds Ansi String and correspondent object to a list. }
  204. function Add(S: PChar): integer;
  205. {* Adds a string to list. }
  206. function AddLen(S: PChar; Len: Integer): integer;
  207. {* Adds a string to list. The string can contain #0 characters. }
  208. public
  209. FastClear: Boolean;
  210. {* }
  211. procedure Clear;
  212. {* Makes string list empty. }
  213. procedure Delete(Idx: integer);
  214. {* Deletes string with given index (it *must* exist). }
  215. function IndexOf(const S: string): integer;
  216. {* Returns index of first string, equal to given one. }
  217. function IndexOf_NoCase(const S: string): integer;
  218. {* Returns index of first string, equal to given one (while comparing it
  219. without case sensitivity). }
  220. function IndexOfStrL_NoCase( Str: PChar; L: Integer ): integer;
  221. {* Returns index of first string, equal to given one (while comparing it
  222. without case sensitivity). }
  223. function Find(const S: String; var Index: Integer): Boolean;
  224. {* Returns Index of the first string, equal or greater to given pattern, but
  225. works only for sorted TFastStrListEx object. Returns TRUE if exact string found,
  226. otherwise nearest (greater then a pattern) string index is returned,
  227. and the result is FALSE. }
  228. procedure InsertAnsi(Idx: integer; const S: String);
  229. {* Inserts ANSI string before one with given index. }
  230. procedure InsertAnsiObject(Idx: integer; const S: String; Obj: DWORD);
  231. {* Inserts ANSI string before one with given index. }
  232. procedure Insert(Idx: integer; S: PChar);
  233. {* Inserts string before one with given index. }
  234. procedure InsertLen( Idx: Integer; S: PChar; Len: Integer );
  235. {* Inserts string from given PChar. It can contain #0 characters. }
  236. function LoadFromFile(const FileName: string): Boolean;
  237. {* Loads string list from a file. (If file does not exist, nothing
  238. happens). Very fast even for huge text files. }
  239. procedure LoadFromStream(Stream: PStream; Append2List: boolean);
  240. {* Loads string list from a stream (from current position to the end of
  241. a stream). Very fast even for huge text. }
  242. procedure MergeFromFile(const FileName: string);
  243. {* Merges string list with strings in a file. Fast. }
  244. procedure Move(CurIndex, NewIndex: integer);
  245. {* Moves string to another location. }
  246. procedure SetText(const S: string; Append2List: boolean);
  247. {* Allows to set strings of string list from given string (in which
  248. strings are separated by $0D,$0A or $0D characters). Text can
  249. contain #0 characters. Works very fast. This method is used in
  250. all others, working with text arrays (LoadFromFile, MergeFromFile,
  251. Assign, AddStrings). }
  252. function SaveToFile(const FileName: string): Boolean;
  253. {* Stores string list to a file. }
  254. procedure SaveToStream(Stream: PStream);
  255. {* Saves string list to a stream (from current position). }
  256. function AppendToFile(const FileName: string): Boolean;
  257. {* Appends strings of string list to the end of a file. }
  258. property Count: integer read fCount;
  259. {* Number of strings in a string list. }
  260. property Items[Idx: integer]: string read Get write Put; default;
  261. {* Strings array items. If item does not exist, empty string is returned.
  262. But for assign to property, string with given index *must* exist. }
  263. property ItemPtrs[ Idx: Integer ]: PChar read GetPChars;
  264. {* Fast access to item strings as PChars. }
  265. property ItemLen[ Idx: Integer ]: Integer read GetItemLen;
  266. {* Length of string item. }
  267. function Last: String;
  268. {* Last item (or '', if string list is empty). }
  269. property Text: string read GetTextStr write SetTextStr;
  270. {* Content of string list as a single string (where strings are separated
  271. by characters $0D,$0A). }
  272. procedure Swap( Idx1, Idx2 : Integer );
  273. {* Swaps to strings with given indeces. }
  274. procedure Sort( CaseSensitive: Boolean );
  275. {* Call it to sort string list. }
  276. public
  277. function AddObject( S: PChar; Obj: DWORD ): Integer;
  278. {* Adds string S (null-terminated) with associated object Obj. }
  279. function AddObjectLen( S: PChar; Len: Integer; Obj: DWORD ): Integer;
  280. {* Adds string S of length Len with associated object Obj. }
  281. procedure InsertObject( Idx: Integer; S: PChar; Obj: DWORD );
  282. {* Inserts string S (null-terminated) at position Idx in the list,
  283. associating it with object Obj. }
  284. procedure InsertObjectLen( Idx: Integer; S: PChar; Len: Integer; Obj: DWORD );
  285. {* Inserts string S of length Len at position Idx in the list,
  286. associating it with object Obj. }
  287. property Objects[ Idx: Integer ]: DWORD read GetObject write SetObject;
  288. {* Access to objects associated with strings in the list. }
  289. public
  290. procedure Append( S: PChar );
  291. {* Appends S (null-terminated) to the last string in FastStrListEx object, very fast. }
  292. procedure AppendLen( S: PChar; Len: Integer );
  293. {* Appends S of length Len to the last string in FastStrListEx object, very fast. }
  294. procedure AppendInt2Hex( N: DWORD; MinDigits: Integer );
  295. {* Converts N to hexadecimal and appends resulting string to the last
  296. string, very fast. }
  297. public
  298. property Values[ Name: PChar ]: PChar read GetValues;
  299. {* Returns a value correspondent to the Name an ini-file-like string list
  300. (having Name1=Value1 Name2=Value2 etc. in each string). }
  301. function IndexOfName( AName: PChar ): Integer;
  302. {* Searches string starting from 'AName=' in string list like ini-file. }
  303. end;
  304. function NewFastStrListEx: PFastStrListEx;
  305. {* Creates FastStrListEx object. }
  306. var Upper: array[ Char ] of Char;
  307. {* An table to convert char to uppercase very fast. First call InitUpper. }
  308. Upper_Initialized: Boolean;
  309. procedure InitUpper;
  310. {* Call this fuction ones to fill Upper[ ] table before using it. }
  311. //[CABINET FILES OBJECT]
  312. type
  313. {++}(*TCabFile = class;*){--}
  314. PCABFile = {-}^{+}TCABFile;
  315. TOnNextCAB = function( Sender: PCABFile ): KOLString of object;
  316. TOnCABFile = function( Sender: PCABFile; var FileName: KOLString ): Boolean of object;
  317. { ----------------------------------------------------------------------
  318. TCabFile - windows cabinet files
  319. ----------------------------------------------------------------------- }
  320. //[TCabFile DEFINITION]
  321. TCABFile = object( TObj )
  322. {* An object to simplify extracting files from a cabinet (.CAB) files.
  323. The only what need to use this object, setupapi.dll. It is provided
  324. with all latest versions of Windows. }
  325. protected
  326. FPaths: {$IFDEF UNICODE_CTRLS} PWStrList {$ELSE} PStrList {$ENDIF};
  327. FNames: {$IFDEF UNICODE_CTRLS} PWStrList {$ELSE} PStrList {$ENDIF};
  328. FOnNextCAB: TOnNextCAB;
  329. FOnFile: TOnCABFile;
  330. FTargetPath: KOLString;
  331. FSetupapi: THandle;
  332. function GetNames(Idx: Integer): KOLString;
  333. function GetCount: Integer;
  334. function GetPaths(Idx: Integer): KOLString;
  335. function GetTargetPath: KOLString;
  336. protected
  337. FGettingNames: Boolean;
  338. FCurCAB: Integer;
  339. public
  340. destructor Destroy; {-}virtual;{+}{++}(*override;*){--}
  341. {* }
  342. property Paths[ Idx: Integer ]: KOLString read GetPaths;
  343. {* A list of CAB-files. It is stored, when constructing function
  344. OpenCABFile called. }
  345. property Names[ Idx: Integer ]: KOLString read GetNames;
  346. {* A list of file names, stored in a sequence of CAB files. To get know,
  347. how many files are there, check Count property. }
  348. property Count: Integer read GetCount;
  349. {* Number of files stored in a sequence of CAB files. }
  350. function Execute: Boolean;
  351. {* Call this method to extract or enumerate files in CAB. For every
  352. file, found during executing, event OnFile is alled (if assigned).
  353. If the event handler (if any) does not provide full target path for
  354. a file to extract to, property TargetPath is applyed (also if it
  355. is assigned), or file is extracted to the default directory (usually
  356. the same directory there CAB file is located, or current directory
  357. - by a decision of the system).
  358. |<br>
  359. If a sequence of CAB files is used, and not all names for CAB files
  360. are provided (absent or represented by a string '?' ), an event
  361. OnNextCAB is called to obtain the name of the next CAB file.}
  362. property CurCAB: Integer read FCurCAB;
  363. {* Index of current CAB file in a sequence of CAB files. When OnNextCAB
  364. event is called (if any), CurCAB property is already set to the
  365. index of path, what should be provided. }
  366. property OnNextCAB: TOnNextCAB read FOnNextCAB write FOnNextCAB;
  367. {* This event is called, when a series of CAB files is needed and not
  368. all CAB file names are provided (absent or represented by '?' string).
  369. If this event is not assigned, the user is prompted to browse file. }
  370. property OnFile: TOnCABFile read FOnFile write FOnFile;
  371. {* This event is called for every file found during Execute method.
  372. In an event handler (if any assigned), it is possible to return
  373. False to skip file, or to provide another full target path for
  374. file to extract it to, then default. If the event is not assigned,
  375. all files are extracted either to default directory, or to the
  376. directory TargetPath, if it is provided. }
  377. property TargetPath: KOLString read GetTargetPath write FTargetPath;
  378. {* Optional target directory to place there extracted files. }
  379. end;
  380. //[END OF TCABFile DEFINITION]
  381. //[OpenCABFile DECLARATION]
  382. function OpenCABFile( const APaths: array of String ): PCABFile;
  383. {* This function creates TCABFile object, passing a sequence of CAB file names
  384. (fully qualified). It is possible not to provide all names here, or pass '?'
  385. string in place of some of those. For such files, either an event OnNextCAB
  386. will be called, or (and) user will be prompted to browse file during
  387. executing (i.e. Extracting). }
  388. //[DIRCHANGE]
  389. type
  390. {++}(*TDirChange = class;*){--}
  391. PDirChange = {-}^{+}TDirChange;
  392. {* }
  393. TOnDirChange = procedure (Sender: PDirChange; const Path: KOLString) of object;
  394. {* Event type to define OnChange event for folder monitoring objects. }
  395. TFileChangeFilters = (fncFileName, fncDirName, fncAttributes, fncSize,
  396. fncLastWrite, fncLastAccess, fncCreation, fncSecurity);
  397. {* Possible change monitor filters. }
  398. TFileChangeFilter = set of TFileChangeFilters;
  399. {* Set of filters to pass to a constructor of TDirChange object. }
  400. { ----------------------------------------------------------------------
  401. TDirChange object
  402. ----------------------------------------------------------------------- }
  403. //[TDirChange DEFINITION]
  404. TDirChange = object(TObj)
  405. {* Object type to monitor changes in certain folder. }
  406. protected
  407. FOnChange: TOnDirChange;
  408. FHandle, FinEvent: THandle;
  409. FPath: KOLString;
  410. FMonitor: PThread;
  411. function Execute( Sender: PThread ): Integer;
  412. procedure Changed;
  413. protected
  414. {++}(*public*){--}
  415. destructor Destroy; {-}virtual;{+}{++}(*override;*){--}
  416. {*}
  417. public
  418. property Handle: THandle read FHandle;
  419. {* Handle of file change notification object. *}
  420. property Path: KOLString read FPath; //write SetPath;
  421. {* Path to monitored folder (to a root, if tree of folders
  422. is under monitoring). }
  423. property OnChange: TOnDirChange read FOnChange write FOnChange;
  424. end;
  425. //[END OF TDirChange DEFINITION]
  426. //[NewDirChangeNotifier DECLARATION]
  427. function NewDirChangeNotifier( const Path: KOLString; Filter: TFileChangeFilter;
  428. WatchSubtree: Boolean; ChangeProc: TOnDirChange ): PDirChange;
  429. {* Creates notification object TDirChange. If something wrong (e.g.,
  430. passed directory does not exist), nil is returned as a result. When change
  431. is notified, ChangeProc is called always in main thread context.
  432. (Please note, that ChangeProc can not be nil).
  433. If empty filter is passed, default filter is used:
  434. [fncFileName..fncLastWrite]. }
  435. {$ifdef win32}
  436. //[METAFILES]
  437. type
  438. {++}(*TMetafile = class;*){--}
  439. PMetafile = {-}^{+}TMetafile;
  440. { ----------------------------------------------------------------------
  441. TMetafile - Windows metafile and Enchanced Metafile image
  442. ----------------------------------------------------------------------- }
  443. //[TMetafile DEFINITION]
  444. TMetafile = object( TObj )
  445. {* Object type to incapsulate metafile image. }
  446. protected
  447. function GetHeight: Integer;
  448. function GetWidth: Integer;
  449. procedure SetHandle(const Value: THandle);
  450. protected
  451. fHandle: THandle;
  452. fHeader: PEnhMetaHeader;
  453. procedure RetrieveHeader;
  454. public
  455. destructor Destroy; {-}virtual;{+}{++}(*override;*){--}
  456. {* }
  457. procedure Clear;
  458. {* }
  459. function Empty: Boolean;
  460. {* Returns TRUE if empty}
  461. property Handle: THandle read fHandle write SetHandle;
  462. {* Returns handle of enchanced metafile. }
  463. function LoadFromStream( Strm: PStream ): Boolean;
  464. {* Loads emf or wmf file format from stream. }
  465. function LoadFromFile( const Filename: String ): Boolean;
  466. {* Loads emf or wmf from stream. }
  467. procedure Draw( DC: HDC; X, Y: Integer );
  468. {* Draws enchanced metafile on DC. }
  469. procedure StretchDraw( DC: HDC; const R: TRect );
  470. {* Draws enchanced metafile stretched. }
  471. property Width: Integer read GetWidth;
  472. {* Native width of the metafile. }
  473. property Height: Integer read GetHeight;
  474. {* Native height of the metafile. }
  475. end;
  476. //[END OF TMetafile DEFINITION]
  477. //[NewMetafile DECLARATION]
  478. function NewMetafile: PMetafile;
  479. {* Creates metafile object. }
  480. //[Metafile CONSTANTS, STRUCTURES, ETC.]
  481. const
  482. WMFKey = Integer($9AC6CDD7);
  483. WMFWord = $CDD7;
  484. type
  485. TMetafileHeader = packed record
  486. Key: Longint;
  487. Handle: SmallInt;
  488. Box: TSmallRect;
  489. Inch: Word;
  490. Reserved: Longint;
  491. CheckSum: Word;
  492. end;
  493. function ComputeAldusChecksum(var WMF: TMetafileHeader): Word;
  494. {++}(*
  495. function SetEnhMetaFileBits(p1: UINT; p2: PChar): HENHMETAFILE; stdcall;
  496. function PlayEnhMetaFile(DC: HDC; p2: HENHMETAFILE; const p3: TRect): BOOL; stdcall;
  497. *){--}
  498. {$endif win32}
  499. // NewActionList, TAction - by Yury Sidorov
  500. //[ACTIONS OBJECT]
  501. { ----------------------------------------------------------------------
  502. TAction and TActionList
  503. ----------------------------------------------------------------------- }
  504. type
  505. PControlRec = ^TControlRec;
  506. TOnUpdateCtrlEvent = procedure(Sender: PControlRec) of object;
  507. TCtrlKind = (ckControl, ckMenu, ckToolbar);
  508. TControlRec = record
  509. Ctrl: PObj;
  510. CtrlKind: TCtrlKind;
  511. ItemID: integer;
  512. UpdateProc: TOnUpdateCtrlEvent;
  513. end;
  514. TUpdateProperty = (upCaption, upHint, upChecked, upEnabled, upVisible, upHelpContext, upAccelerator);
  515. TUpdateProperties = set of TUpdateProperty;
  516. {++}(* TAction = class;*){--}
  517. PAction = {-}^{+}TAction;
  518. {++}(* TActionList = class;*){--}
  519. PActionList = {-}^{+}TActionList;
  520. //[TAction DEFINITION]
  521. TAction = {-} object( TObj ) {+}{++}(*class*){--}
  522. {*! Use action objects, in conjunction with action lists, to centralize the response
  523. to user commands (actions).
  524. Use AddControl, AddMenuItem, AddToolbarButton methods to link controls to an action.
  525. See also TActionList.
  526. }
  527. protected
  528. FControls: PList;
  529. FCaption: KOLString;
  530. FChecked: boolean;
  531. FVisible: boolean;
  532. FEnabled: boolean;
  533. FHelpContext: integer;
  534. FHint: KOLString;
  535. FOnExecute: TOnEvent;
  536. FAccelerator: TMenuAccelerator;
  537. {$ifndef wince}
  538. FShortCut: KOLString;
  539. {$endif wince}
  540. FUpdateMask: TUpdateProperties;
  541. procedure DoOnMenuItem(Sender: PMenu; Item: Integer);
  542. procedure DoOnToolbarButtonClick(Sender: PControl; BtnID: Integer);
  543. procedure DoOnControlClick(Sender: PObj);
  544. procedure SetCaption(const Value: KOLString);
  545. procedure SetChecked(const Value: boolean);
  546. procedure SetEnabled(const Value: boolean);
  547. procedure SetHelpContext(const Value: integer);
  548. procedure SetHint(const Value: KOLString);
  549. procedure SetVisible(const Value: boolean);
  550. procedure SetAccelerator(const Value: TMenuAccelerator);
  551. procedure UpdateControls;
  552. procedure LinkCtrl(ACtrl: PObj; ACtrlKind: TCtrlKind; AItemID: integer; AUpdateProc: TOnUpdateCtrlEvent);
  553. procedure SetOnExecute(const Value: TOnEvent);
  554. procedure UpdateCtrl(Sender: PControlRec);
  555. procedure UpdateMenu(Sender: PControlRec);
  556. procedure UpdateToolbar(Sender: PControlRec);
  557. public
  558. destructor Destroy; {-}virtual;{+}{++}(*override;*){--}
  559. procedure LinkControl(Ctrl: PControl);
  560. {* Add a link to a TControl or descendant control. }
  561. procedure LinkMenuItem(Menu: PMenu; MenuItemIdx: integer);
  562. {* Add a link to a menu item. }
  563. procedure LinkToolbarButton(Toolbar: PControl; ButtonIdx: integer);
  564. {* Add a link to a toolbar button. }
  565. procedure Execute;
  566. {* Executes a OnExecute event handler. }
  567. property Caption: KOLString read FCaption write SetCaption;
  568. {* Text caption. }
  569. property Hint: KOLString read FHint write SetHint;
  570. {* Hint (tooltip). Currently used for toolbar buttons only. }
  571. property Checked: boolean read FChecked write SetChecked;
  572. {* Checked state. }
  573. property Enabled: boolean read FEnabled write SetEnabled;
  574. {* Enabled state. }
  575. property Visible: boolean read FVisible write SetVisible;
  576. {* Visible state. }
  577. property HelpContext: integer read FHelpContext write SetHelpContext;
  578. {* Help context. }
  579. property Accelerator: TMenuAccelerator read FAccelerator write SetAccelerator;
  580. {* Accelerator for menu items. }
  581. property OnExecute: TOnEvent read FOnExecute write SetOnExecute;
  582. {* This event is executed when user clicks on a linked object or Execute method was called. }
  583. end;
  584. //[END OF TAction DEFINITION]
  585. //[TActionList DEFINITION]
  586. TActionList = {-} object( TObj ) {+}{++}(*class*){--}
  587. {*! TActionList maintains a list of actions used with components and controls,
  588. such as menu items and buttons.
  589. Action lists are used, in conjunction with actions, to centralize the response
  590. to user commands (actions).
  591. Write an OnUpdateActions handler to update actions state.
  592. Created using function NewActionList.
  593. See also TAction.
  594. }
  595. protected
  596. FOwner: PControl;
  597. FActions: PList;
  598. FOnUpdateActions: TOnEvent;
  599. function GetActions(Idx: integer): PAction;
  600. function GetCount: integer;
  601. protected
  602. procedure DoUpdateActions(Sender: PObj);
  603. public
  604. destructor Destroy; {-}virtual;{+}{++}(*override;*){--}
  605. function Add(const ACaption, AHint: KOLString; OnExecute: TOnEvent): PAction;
  606. {* Add a new action to the list. Returns pointer to action object. }
  607. procedure Delete(Idx: integer);
  608. {* Delete action by index from list. }
  609. procedure Clear;
  610. {* Clear all actions in the list. }
  611. property Actions[Idx: integer]: PAction read GetActions;
  612. {* Access to actions in the list. }
  613. property Count: integer read GetCount;
  614. {* Number of actions in the list.. }
  615. property OnUpdateActions: TOnEvent read FOnUpdateActions write FOnUpdateActions;
  616. {* Event handler to update actions state. This event is called each time when application
  617. goes in the idle state (no messages in the queue). }
  618. end;
  619. //[END OF TActionList DEFINITION]
  620. //[NewActionList DECLARATION]
  621. function NewActionList(AOwner: PControl): PActionList;
  622. {* Action list constructor. AOwner - owner form. }
  623. { -- tree (non-visual) -- }
  624. type
  625. //[TTree DEFINITION]
  626. {++}(*TTree = class;*){--}
  627. PTree = {-}^{+}TTree;
  628. TTree = object( TObj )
  629. {* Object to store tree-like data in memory (non-visual). }
  630. protected
  631. fParent: PTree;
  632. fChildren: PList;
  633. fPrev: PTree;
  634. fNext: PTree;
  635. {$IFDEF TREE_NONAME}
  636. {$ELSE}
  637. {$IFDEF TREE_WIDE}
  638. fNodeName: WideString;
  639. {$ELSE}
  640. fNodeName: String;
  641. {$ENDIF}
  642. {$ENDIF}
  643. fData: Pointer;
  644. function GetCount: Integer;
  645. function GetItems(Idx: Integer): PTree;
  646. procedure Unlink;
  647. function GetRoot: PTree;
  648. function GetLevel: Integer;
  649. function GetTotal: Integer;
  650. function GetIndexAmongSiblings: Integer;
  651. protected
  652. {$IFDEF USE_CONSTRUCTORS}
  653. constructor CreateTree( AParent: PTree; const AName: String );
  654. {* }
  655. {$ENDIF}
  656. {++}(*public*){--}
  657. destructor Destroy; {-}virtual;{+}{++}(*override;*){--}
  658. {* }
  659. {++}(*protected*){--}
  660. procedure Init; {-}virtual;{+}{++}(*override;*){--}
  661. public
  662. procedure Clear;
  663. {* Destoyes all child nodes. }
  664. {$IFDEF TREE_NONAME}
  665. {$ELSE}
  666. {$IFDEF TREE_WIDE}
  667. property Name: WideString read fNodeName write fNodeName;
  668. {$ELSE}
  669. property Name: String read fNodeName write fNodeName;
  670. {$ENDIF}
  671. {$ENDIF}
  672. {* Optional node name. }
  673. property Data: Pointer read fData write fData;
  674. {* Optional user-defined pointer. }
  675. property Count: Integer read GetCount;
  676. {* Number of child nodes of given node. }
  677. property Items[ Idx: Integer ]: PTree read GetItems;
  678. {* Child nodes list items. }
  679. procedure Add( Node: PTree );
  680. {* Adds another node as a child of given tree node. This operation
  681. as well as Insert can be used to move node together with its children
  682. to another location of the same tree or even from another tree.
  683. Anyway, added Node first correctly removed from old place (if it is
  684. defined for it). But for simplest task, such as filling of tree with
  685. nodes, code should looking as follows:
  686. ! Node := NewTree( nil, 'test of creating node without parent' );
  687. ! RootOfMyTree.Add( Node );
  688. Though, this code gives the same result as:
  689. ! Node := NewTree( RootOfMyTree, 'test of creatign node as a child' ); }
  690. procedure Insert( Before, Node: PTree );
  691. {* Inserts earlier created 'Node' just before given child node 'Before'
  692. as a child of given tree node. See also Add method. }
  693. property Parent: PTree read fParent;
  694. {* Returns parent node (or nil, if there is no parent). }
  695. property Index: Integer read GetIndexAmongSiblings;
  696. {* Returns an index of the node in a list of nodes of the same parent
  697. (or -1, if Parent is not defined). }
  698. property PrevSibling: PTree read fPrev;
  699. {* Returns previous node in a list of children of the Parent. Nil is
  700. returned, if given node is the first child of the Parent or has
  701. no Parent. }
  702. property NextSibling: PTree read fNext;
  703. {* Returns next node in a list of children of the Parent. Nil is returned,
  704. if given node is the last child of the Parent or has no Parent at all. }
  705. property Root: PTree read GetRoot;
  706. {* Returns root node (i.e. the last Parent, enumerating parents recursively). }
  707. property Level: Integer read GetLevel;
  708. {* Returns level of the node, i.e. integer value, equal to 0 for root
  709. of a tree, 1 for its children, etc. }
  710. property Total: Integer read GetTotal;
  711. {* Returns total number of children of the node and all its children
  712. counting its recursively (but node itself is not considered, i.e.
  713. Total for node without children is equal to 0). }
  714. procedure SortByName;
  715. {* Sorts children of the node in ascending order. Sorting is not
  716. recursive, i.e. only immediate children are sorted. }
  717. procedure SwapNodes( i1, i2: Integer );
  718. {* Swaps two child nodes. }
  719. function IsParentOfNode( Node: PTree ): Boolean;
  720. {* Returns true, if Node is the tree itself or is a parent of the given node
  721. on any level. }
  722. function IndexOf( Node: PTree ): Integer;
  723. {* Total index of the child node (on any level under this node). }
  724. end;
  725. //[END OF TTree DEFINITION]
  726. //[NewTree DECLARATION]
  727. {$IFDEF TREE_NONAME}
  728. function NewTree( AParent: PTree ): PTree;
  729. {* Nameless version (for case when TREE_NONAME symbol is defined).
  730. Constructs tree node, adding it to the end of children list of
  731. the AParent. If AParent is nil, new root tree node is created. }
  732. {$ELSE}
  733. {$IFDEF TREE_WIDE}
  734. function NewTree( AParent: PTree; const AName: WideString ): PTree;
  735. {* WideString version (for case when TREE_WIDE symbol is defined).
  736. Constructs tree node, adding it to the end of children list of
  737. the AParent. If AParent is nil, new root tree node is created. }
  738. {$ELSE}
  739. function NewTree( AParent: PTree; const AName: String ): PTree;
  740. {* Constructs tree node, adding it to the end of children list of
  741. the AParent. If AParent is nil, new root tree node is created. }
  742. {$ENDIF}
  743. {$ENDIF}
  744. {-------------------------------------------------------------------------------
  745. ADDITIONAL UTILITIES
  746. }
  747. function MapFileRead( const Filename: String; var hFile, hMap: THandle ): Pointer;
  748. {* Opens file for read only (with share deny none attribute) and maps its
  749. entire content using memory mapped files technique. The address of the
  750. first byte of file mapped into the application address space is returned.
  751. When mapping no more needed, it must be closed calling UnmapFile (see below).
  752. Maximum file size which can be mapped at a time is 1/4 Gigabytes. If file size
  753. exceeding this value only 1/4 Gigabytes starting from the beginning of the
  754. file is mapped therefore. }
  755. function MapFile( const Filename: String; var hFile, hMap: THandle ): Pointer;
  756. {* Opens file for read/write (in exlusive mode) and maps its
  757. entire content using memory mapped files technique. The address of the
  758. first byte of file mapped into the application address space is returned.
  759. When mapping no more needed, it must be closed calling UnmapFile (see below). }
  760. procedure UnmapFile( BasePtr: Pointer; hFile, hMap: THandle );
  761. {* Closes mapping opened via MapFile or MapFileRead call. }
  762. //------------------------ for MCK projects:
  763. type
  764. TKOLAction = PAction;
  765. TKOLActionList = PActionList;
  766. function ShowQuestion( const S: String; Answers: String ): Integer;
  767. {* Modal dialog like ShowMsgModal. It is based on KOL form, so it can
  768. be called also out of message loop, e.g. after finishing the
  769. application. Also, this function *must* be used in MDI applications
  770. in place of any dialog functions, based on MessageBox.
  771. |<br>
  772. The second parameter should be empty string or several possible
  773. answers separated by '/', e.g.: 'Yes/No/Cancel'. Result is
  774. a number answered, starting from 1. For example, if 'Cancel'
  775. was pressed, 3 will be returned.
  776. |<br>
  777. User can also press ESCAPE key, or close modal dialog. In such case
  778. -1 is returned. }
  779. function ShowQuestionEx( S: KOLString; Answers: KOLString; CallBack: TOnEvent ): Integer;
  780. {* Like ShowQuestion, but with CallBack function, called just before showing
  781. the dialog. }
  782. procedure ShowMsgModal( const S: String );
  783. {* This message function can be used out of a message loop (e.g., after
  784. finishing the application). It is always modal.
  785. Actually, a form with word-wrap label (decorated as borderless edit
  786. box with btnFace color) and with OK button is created and shown modal.
  787. When a dialog is called from outside message loop, caption 'Information'
  788. is always displayed.
  789. Dialog form is automatically resized vertically to fit message text
  790. (but until screen height is achieved) and shown always centered on
  791. screen. The width is fixed (400 pixels).
  792. |<br>
  793. Do not use this function outside the message loop for case, when the
  794. Applet variable is not used in an application. }
  795. implementation
  796. type
  797. PCrackList = ^TCrackList;
  798. TCrackList = object( TList )
  799. end;
  800. {------------------------------------------------------------------------------)
  801. | |
  802. | T L i s t E x |
  803. | |
  804. (------------------------------------------------------------------------------}
  805. { TListEx }
  806. //[function NewListEx]
  807. function NewListEx: PListEx;
  808. begin
  809. {-}
  810. new( Result, Create );
  811. {+}{++}(*Result := PListEx.Create;*){--}
  812. Result.fList := NewList;
  813. Result.fObjects := NewList;
  814. end;
  815. //[END NewListEx]
  816. //[procedure TListEx.Add]
  817. procedure TListEx.Add(Value: Pointer);
  818. begin
  819. AddObj( Value, nil );
  820. end;
  821. //[procedure TListEx.AddObj]
  822. procedure TListEx.AddObj(Value, Obj: Pointer);
  823. var C: Integer;
  824. begin
  825. C := Count;
  826. fList.Add( Value );
  827. fObjects.Insert( C, Obj );
  828. end;
  829. //[procedure TListEx.Clear]
  830. procedure TListEx.Clear;
  831. begin
  832. fList.Clear;
  833. fObjects.Clear;
  834. end;
  835. //[procedure TListEx.Delete]
  836. procedure TListEx.Delete(Idx: Integer);
  837. begin
  838. DeleteRange( Idx, 1 );
  839. end;
  840. //[procedure TListEx.DeleteRange]
  841. procedure TListEx.DeleteRange(Idx, Len: Integer);
  842. begin
  843. fList.DeleteRange( Idx, Len );
  844. fObjects.DeleteRange( Idx, Len );
  845. end;
  846. //[destructor TListEx.Destroy]
  847. destructor TListEx.Destroy;
  848. begin
  849. fList.Free;
  850. fObjects.Free;
  851. inherited;
  852. end;
  853. //[function TListEx.GetAddBy]
  854. function TListEx.GetAddBy: Integer;
  855. begin
  856. Result := fList.AddBy;
  857. end;
  858. //[function TListEx.GetCount]
  859. function TListEx.GetCount: Integer;
  860. begin
  861. Result := fList.Count;
  862. end;
  863. //[function TListEx.GetEx]
  864. function TListEx.GetEx(Idx: Integer): Pointer;
  865. begin
  866. Result := fList.Items[ Idx ];
  867. end;
  868. //[function TListEx.IndexOf]
  869. function TListEx.IndexOf(Value: Pointer): Integer;
  870. begin
  871. Result := fList.IndexOf( Value );
  872. end;
  873. //[function TListEx.IndexOfObj]
  874. function TListEx.IndexOfObj(Obj: Pointer): Integer;
  875. begin
  876. Result := fObjects.IndexOf( Obj );
  877. end;
  878. //[procedure TListEx.Insert]
  879. procedure TListEx.Insert(Idx: Integer; Value: Pointer);
  880. begin
  881. InsertObj( Idx, Value, nil );
  882. end;
  883. //[procedure TListEx.InsertObj]
  884. procedure TListEx.InsertObj(Idx: Integer; Value, Obj: Pointer);
  885. begin
  886. fList.Insert( Idx, Value );
  887. fObjects.Insert( Idx, Obj );
  888. end;
  889. //[function TListEx.Last]
  890. function TListEx.Last: Pointer;
  891. begin
  892. Result := fList.Last;
  893. end;
  894. //[function TListEx.LastObj]
  895. function TListEx.LastObj: Pointer;
  896. begin
  897. Result := fObjects.Last;
  898. end;
  899. //[procedure TListEx.MoveItem]
  900. procedure TListEx.MoveItem(OldIdx, NewIdx: Integer);
  901. begin
  902. fList.MoveItem( OldIdx, NewIdx );
  903. fObjects.MoveItem( OldIdx, NewIdx );
  904. end;
  905. //[procedure TListEx.PutEx]
  906. procedure TListEx.PutEx(Idx: Integer; const Value: Pointer);
  907. begin
  908. fList.Items[ Idx ] := Value;
  909. end;
  910. //[procedure TListEx.Set_AddBy]
  911. procedure TListEx.Set_AddBy(const Value: Integer);
  912. begin
  913. fList.AddBy := Value;
  914. fObjects.AddBy := Value;
  915. end;
  916. //[procedure TListEx.Swap]
  917. procedure TListEx.Swap(Idx1, Idx2: Integer);
  918. begin
  919. fList.Swap( Idx1, Idx2 );
  920. fObjects.Swap( Idx1, Idx2 );
  921. end;
  922. {------------------------------------------------------------------------------)
  923. | |
  924. | T B i t s |
  925. | |
  926. (------------------------------------------------------------------------------}
  927. { TBits }
  928. //[function NewBits]
  929. function NewBits: PBits;
  930. begin
  931. {-}
  932. new( Result, Create );
  933. {+}{++}(*Result := PBits.Create;*){--}
  934. Result.fList := NewList;
  935. //Result.fList.fAddBy := 1;
  936. end;
  937. //[procedure TBits.AssignBits]
  938. procedure TBits.AssignBits(ToIdx: Integer; FromBits: PBits; FromIdx,
  939. N: Integer);
  940. var i: Integer;
  941. NewCount: Integer;
  942. begin
  943. if FromIdx >= FromBits.Count then Exit;
  944. if FromIdx + N > FromBits.Count then
  945. N := FromBits.Count - FromIdx;
  946. Capacity := (ToIdx + N + 8) div 8;
  947. NewCount := Max( Count, ToIdx + N - 1 );
  948. fCount := Max( NewCount, fCount );
  949. PCrackList( fList ).fCount := (Capacity + 3) div 4;
  950. while ToIdx and $1F <> 0 do
  951. begin
  952. Bits[ ToIdx ] := FromBits.Bits[ FromIdx ];
  953. Inc( ToIdx );
  954. Inc( FromIdx );
  955. Dec( N );
  956. if N = 0 then Exit;
  957. end;
  958. Move( PByte( cardinal( PCrackList( FromBits.fList ).fItems ) + cardinal((FromIdx + 31) div 32) )^,
  959. PByte( cardinal( PCrackList( fList ).fItems ) + cardinal(ToIdx div 32) )^, (N + 31) div 32 );
  960. FromIdx := FromIdx and $1F;
  961. if FromIdx <> 0 then
  962. begin // shift data by (Idx and $1F) bits right
  963. for i := ToIdx div 32 to fList.Count-2 do
  964. fList.Items[ i ] := Pointer(
  965. (DWORD( fList.Items[ i ] ) shr FromIdx) or
  966. (DWORD( fList.Items[ i+1 ] ) shl (32 - FromIdx))
  967. );
  968. fList.Items[ fList.Count-1 ] := Pointer(
  969. DWORD( fList.Items[ fList.Count-1 ] ) shr FromIdx
  970. );
  971. end;
  972. end;
  973. //[function TBits.Copy]
  974. procedure TBits.Clear;
  975. begin
  976. fCount := 0;
  977. fList.Clear;
  978. end;
  979. function TBits.Copy(From, BitsCount: Integer): PBits;
  980. var Shift, N: Integer;
  981. FirstItemPtr: Pointer;
  982. begin
  983. Result := NewBits;
  984. if BitsCount = 0 then Exit;
  985. Result.Capacity := BitsCount + 32;
  986. Result.fCount := BitsCount;
  987. Move( PCrackList( fList ).fItems[ From shr 5 ],
  988. PCrackList( Result.fList ).fItems[ 0 ], (Count + 31) div 32 );
  989. Shift := From and $1F;
  990. if Shift <> 1 then
  991. begin
  992. N := (BitsCount + 31) div 32;
  993. FirstItemPtr := @ PCrackList( Result.fList ).fItems[ N - 1 ];
  994. {$ifdef cpu86}
  995. asm
  996. PUSH ESI
  997. PUSH EDI
  998. MOV ESI, FirstItemPtr
  999. MOV EDI, ESI
  1000. STD
  1001. MOV ECX, N
  1002. XOR EAX, EAX
  1003. CDQ
  1004. @@1:
  1005. PUSH ECX
  1006. LODSD
  1007. MOV ECX, Shift
  1008. SHRD EAX, EDX, CL
  1009. STOSD
  1010. SUB ECX, 32
  1011. NEG ECX
  1012. SHR EDX, CL
  1013. POP ECX
  1014. LOOP @@1
  1015. CLD
  1016. POP EDI
  1017. POP ESI
  1018. end {$IFDEF F_P} ['EAX','EDX','ECX'] {$ENDIF};
  1019. {$else}
  1020. // FIXME
  1021. MsgOK('TBits.Copy should be fixed.');
  1022. Halt(7);
  1023. {$endif cpu86}
  1024. end;
  1025. end;
  1026. //[destructor TBits.Destroy]
  1027. destructor TBits.Destroy;
  1028. begin
  1029. fList.Free;
  1030. inherited;
  1031. end;
  1032. //[function TBits.GetBit]
  1033. {$IFDEF ASM_VERSION}
  1034. function TBits.GetBit(Idx: Integer): Boolean;
  1035. asm
  1036. CMP EDX, [EAX].FCount
  1037. JL @@1
  1038. XOR EAX, EAX
  1039. RET
  1040. @@1:
  1041. MOV EAX, [EAX].fList
  1042. {TEST EAX, EAX
  1043. JZ @@exit}
  1044. MOV EAX, [EAX].TList.fItems
  1045. BT [EAX], EDX
  1046. SETC AL
  1047. @@exit:
  1048. end;
  1049. {$ELSE}
  1050. function TBits.GetBit(Idx: Integer): Boolean;
  1051. begin
  1052. if (Idx >= Count) {or (PCrackList( fList ).fItems = nil)} then Result := FALSE else
  1053. Result := ( ( DWORD( PCrackList( fList ).fItems[ Idx shr 5 ] ) shr (Idx and $1F)) and 1 ) <> 0;
  1054. end;
  1055. {$ENDIF}
  1056. //[function TBits.GetCapacity]
  1057. function TBits.GetCapacity: Integer;
  1058. begin
  1059. Result := fList.Capacity * 32;
  1060. end;
  1061. //[function TBits.GetSize]
  1062. function TBits.GetSize: Integer;
  1063. begin
  1064. Result := ( PCrackList( fList ).fCount + 3) div 4;
  1065. end;
  1066. {$IFDEF ASM_noVERSION}
  1067. //[function TBits.IndexOf]
  1068. function TBits.IndexOf(Value: Boolean): Integer;
  1069. asm //cmd //opd
  1070. PUSH EDI
  1071. MOV EDI, [EAX].fList
  1072. MOV ECX, [EDI].TList.fCount
  1073. @@ret_1:
  1074. OR EAX, -1
  1075. JECXZ @@ret_EAX
  1076. MOV EDI, [EDI].TList.fItems
  1077. TEST DL, DL
  1078. MOV EDX, EDI
  1079. JE @@of_false
  1080. INC EAX
  1081. REPZ SCASD
  1082. JE @@ret_1
  1083. MOV EAX, [EDI-4]
  1084. NOT EAX
  1085. JMP @@calc_offset
  1086. BSF EAX, EAX
  1087. SUB EDI, EDX
  1088. SHR EDI, 2
  1089. ADD EAX, EDI
  1090. JMP @@ret_EAX
  1091. @@of_false:
  1092. REPE SCASD
  1093. JE @@ret_1
  1094. MOV EAX, [EDI-4]
  1095. @@calc_offset:
  1096. BSF EAX, EAX
  1097. DEC EAX
  1098. SUB EDI, 4
  1099. SUB EDI, EDX
  1100. SHL EDI, 3
  1101. ADD EAX, EDI
  1102. @@ret_EAX:
  1103. POP EDI
  1104. end;
  1105. {$ELSE ASM_VERSION} //Pascal
  1106. function TBits.IndexOf(Value: Boolean): Integer;
  1107. var I: Integer;
  1108. D: DWORD;
  1109. begin
  1110. Result := -1;
  1111. if Value then
  1112. begin
  1113. for I := 0 to fList.Count-1 do
  1114. begin
  1115. D := DWORD( PCrackList( fList ).fItems[ I ] );
  1116. if D <> 0 then
  1117. begin
  1118. {$ifdef cpu86}
  1119. asm
  1120. MOV EAX, D
  1121. BSF EAX, EAX
  1122. MOV D, EAX
  1123. end {$IFDEF F_P} [ 'EAX' ] {$ENDIF};
  1124. {$else}
  1125. // FIXME
  1126. MsgOK('TBits.IndexOf should be fixed.');
  1127. Halt(7);
  1128. {$endif cpu86}
  1129. Result := I * 32 + Integer( D );
  1130. break;
  1131. end;
  1132. end;
  1133. end
  1134. else
  1135. begin
  1136. for I := 0 to PCrackList( fList ).fCount-1 do
  1137. begin
  1138. D := DWORD( PCrackList( fList ).fItems[ I ] );
  1139. if D <> $FFFFFFFF then
  1140. begin
  1141. {$ifdef cpu86}
  1142. asm
  1143. MOV EAX, D
  1144. NOT EAX
  1145. BSF EAX, EAX
  1146. MOV D, EAX
  1147. end {$IFDEF F_P} [ 'EAX' ] {$ENDIF};
  1148. {$else}
  1149. // FIXME
  1150. MsgOK('TBits.IndexOf should be fixed.');
  1151. Halt(7);
  1152. {$endif cpu86}
  1153. Result := I * 32 + Integer( D );
  1154. break;
  1155. end;
  1156. end;
  1157. end;
  1158. end;
  1159. {$ENDIF ASM_VERSION}
  1160. //[function TBits.LoadFromStream]
  1161. procedure TBits.InstallBits(FromIdx, N: Integer; Value: Boolean);
  1162. var NewCount: Integer;
  1163. begin
  1164. if FromIdx + N > fCount then
  1165. begin
  1166. Capacity := (FromIdx + N + 8) div 8;
  1167. fCount := FromIdx + N - 1;
  1168. end;
  1169. NewCount := Max( Count, FromIdx + N - 1 );
  1170. fCount := Max( NewCount, fCount );
  1171. PCrackList( fList ).fCount := (Capacity + 3) div 4;
  1172. while FromIdx and $1F <> 0 do
  1173. begin
  1174. Bits[ FromIdx ] := Value;
  1175. Inc( FromIdx );
  1176. Dec( N );
  1177. if N = 0 then Exit;
  1178. end;
  1179. FillChar( PByte( cardinal( PCrackList( fList ).fItems ) + cardinal(FromIdx div 32) )^,
  1180. (N + 7) div 8, -Integer( Value ) );
  1181. end;
  1182. function TBits.LoadFromStream(strm: PStream): Integer;
  1183. var
  1184. i: Integer;
  1185. begin
  1186. Result := strm.Read( i, 4 );
  1187. if Result < 4 then Exit;
  1188. bits[ i]:= false; //by miek
  1189. fcount:= i;
  1190. i := (i + 7) div 8;
  1191. Inc( Result, strm.Read( PCrackList( fList ).fItems^, i ) );
  1192. end;
  1193. //[function TBits.OpenBit]
  1194. function TBits.OpenBit: Integer;
  1195. begin
  1196. Result := IndexOf( FALSE );
  1197. if Result < 0 then Result := Count;
  1198. end;
  1199. //[function TBits.Range]
  1200. function TBits.Range(Idx, N: Integer): PBits;
  1201. begin
  1202. Result := NewBits;
  1203. Result.AssignBits( 0, @ Self, Idx, N );
  1204. end;
  1205. //[function TBits.SaveToStream]
  1206. function TBits.SaveToStream(strm: PStream): Integer;
  1207. begin
  1208. Result := strm.Write( fCount, 4 );
  1209. if fCount = 0 then Exit;
  1210. Inc( Result, strm.Write( PCrackList( fList ).fItems^, (fCount + 7) div 8 ) );
  1211. end;
  1212. //[procedure TBits.SetBit]
  1213. {$IFDEF ASM_VERSION}
  1214. procedure TBits.SetBit(Idx: Integer; const Value: Boolean);
  1215. asm
  1216. PUSH ECX
  1217. MOV ECX, [EAX].fList
  1218. MOV ECX, [ECX].TList.fCapacity
  1219. SHL ECX, 5
  1220. CMP EDX, ECX
  1221. JLE @@1
  1222. PUSH EDX
  1223. INC EDX
  1224. PUSH EAX
  1225. CALL SetCapacity
  1226. POP EAX
  1227. POP EDX
  1228. @@1:
  1229. CMP EDX, [EAX].FCount
  1230. JL @@2
  1231. INC EDX
  1232. MOV [EAX].fCount, EDX
  1233. DEC EDX
  1234. @@2:
  1235. POP ECX
  1236. MOV EAX, [EAX].fList
  1237. MOV EAX, [EAX].TList.fItems
  1238. SHR ECX, 1
  1239. JC @@2set
  1240. BTR [EAX], EDX
  1241. JMP @@exit
  1242. @@2set:
  1243. BTS [EAX], EDX
  1244. @@exit:
  1245. end;
  1246. {$ELSE}
  1247. procedure TBits.SetBit(Idx: Integer; const Value: Boolean);
  1248. var Msk: DWORD;
  1249. begin
  1250. if Idx >= Capacity then
  1251. Capacity := Idx + 1;
  1252. Msk := 1 shl (Idx and $1F);
  1253. if Value then
  1254. PCrackList( fList ).fItems[ Idx shr 5 ] := Pointer(
  1255. DWORD(PCrackList( fList ).fItems[ Idx shr 5 ]) or Msk)
  1256. else
  1257. PCrackList( fList ).fItems[ Idx shr 5 ] := Pointer(
  1258. DWORD(PCrackList( fList ).fItems[ Idx shr 5 ]) and not Msk);
  1259. if Idx >= fCount then
  1260. fCount := Idx + 1;
  1261. end;
  1262. {$ENDIF}
  1263. //[procedure TBits.SetCapacity]
  1264. procedure TBits.SetCapacity(const Value: Integer);
  1265. var OldCap: Integer;
  1266. begin
  1267. OldCap := fList.Capacity;
  1268. fList.Capacity := (Value + 31) div 32;
  1269. if OldCap < fList.Capacity then
  1270. FillChar( PChar( cardinal( PCrackList( fList ).fItems ) + cardinal(OldCap * Sizeof( Pointer )) )^,
  1271. (fList.Capacity - OldCap) * sizeof( Pointer ), 0 );
  1272. end;
  1273. {------------------------------------------------------------------------------)
  1274. | |
  1275. | T F a s t S t r L i s t |
  1276. | |
  1277. (------------------------------------------------------------------------------}
  1278. function NewFastStrListEx: PFastStrListEx;
  1279. begin
  1280. new( Result, Create );
  1281. end;
  1282. procedure InitUpper;
  1283. var c: Char;
  1284. begin
  1285. for c := #0 to #255 do
  1286. Upper[ c ] := AnsiUpperCase( c + #0 )[ 1 ];
  1287. Upper_Initialized := TRUE;
  1288. end;
  1289. { TFastStrListEx }
  1290. function TFastStrListEx.AddAnsi(const S: String): Integer;
  1291. begin
  1292. Result := AddObjectLen( PChar( S ), Length( S ), 0 );
  1293. end;
  1294. function TFastStrListEx.AddAnsiObject(const S: String; Obj: DWORD): Integer;
  1295. begin
  1296. Result := AddObjectLen( PChar( S ), Length( S ), Obj );
  1297. end;
  1298. function TFastStrListEx.Add(S: PChar): integer;
  1299. begin
  1300. Result := AddObjectLen( S, StrLen( S ), 0 )
  1301. end;
  1302. function TFastStrListEx.AddLen(S: PChar; Len: Integer): integer;
  1303. begin
  1304. Result := AddObjectLen( S, Len, 0 )
  1305. end;
  1306. function TFastStrListEx.AddObject(S: PChar; Obj: DWORD): Integer;
  1307. begin
  1308. Result := AddObjectLen( S, StrLen( S ), Obj )
  1309. end;
  1310. function TFastStrListEx.AddObjectLen(S: PChar; Len: Integer; Obj: DWORD): Integer;
  1311. var Dest: PChar;
  1312. begin
  1313. ProvideSpace( Len + 9 );
  1314. Dest := PChar( DWORD( fTextBuf ) + fUsedSiz );
  1315. Result := fCount;
  1316. Inc( fCount );
  1317. fList.Add( Pointer( DWORD(Dest)-DWORD(fTextBuf) ) );
  1318. PDWORD( Dest )^ := Obj;
  1319. Inc( Dest, 4 );
  1320. PDWORD( Dest )^ := Len;
  1321. Inc( Dest, 4 );
  1322. if S <> nil then
  1323. System.Move( S^, Dest^, Len );
  1324. Inc( Dest, Len );
  1325. Dest^ := #0;
  1326. Inc( fUsedSiz, Len+9 );
  1327. end;
  1328. function TFastStrListEx.AppendToFile(const FileName: string): Boolean;
  1329. var F: HFile;
  1330. Txt: String;
  1331. begin
  1332. Txt := Text;
  1333. F := FileCreate( FileName, ofOpenAlways or ofOpenReadWrite or ofShareDenyWrite );
  1334. if F = INVALID_HANDLE_VALUE then Result := FALSE
  1335. else begin
  1336. FileSeek( F, 0, spEnd );
  1337. Result := FileWrite( F, PChar( Txt )^, Length( Txt ) ) = DWORD( Length( Txt ) );
  1338. FileClose( F );
  1339. end;
  1340. end;
  1341. procedure TFastStrListEx.Clear;
  1342. begin
  1343. if FastClear then
  1344. begin
  1345. if fList.Count > 0 then
  1346. PCrackList(fList).FCount := 0;
  1347. end
  1348. else
  1349. begin
  1350. fList.Clear;
  1351. if fTextBuf <> nil then
  1352. FreeMem( fTextBuf );
  1353. fTextBuf := nil;
  1354. end;
  1355. fTextSiz := 0;
  1356. fUsedSiz := 0;
  1357. fCount := 0;
  1358. end;
  1359. procedure TFastStrListEx.Delete(Idx: integer);
  1360. begin
  1361. if (Idx < 0) or (Idx >= Count) then Exit;
  1362. if Idx = Count-1 then
  1363. Dec( fUsedSiz, ItemLen[ Idx ]+9 );
  1364. fList.Delete( Idx );
  1365. Dec( fCount );
  1366. end;
  1367. destructor TFastStrListEx.Destroy;
  1368. begin
  1369. FastClear := FALSE;
  1370. Clear;
  1371. fList.Free;
  1372. inherited;
  1373. end;
  1374. function TFastStrListEx.Find(const S: String; var Index: Integer): Boolean;
  1375. var i: Integer;
  1376. begin
  1377. for i := 0 to Count-1 do
  1378. if (ItemLen[ i ] = Length( S )) and
  1379. ((S = '') or CompareMem( ItemPtrs[ i ], @ S[ 1 ], Length( S ) )) then
  1380. begin
  1381. Index := i;
  1382. Result := TRUE;
  1383. Exit;
  1384. end;
  1385. Result := FALSE;
  1386. end;
  1387. function TFastStrListEx.Get(Idx: integer): string;
  1388. begin
  1389. if (Idx >= 0) and (Idx <= Count) then
  1390. SetString( Result, PChar( DWORD( fTextBuf ) + DWORD( fList.Items[ Idx ] ) + 8 ),
  1391. ItemLen[ Idx ] )
  1392. else
  1393. Result := '';
  1394. end;
  1395. function TFastStrListEx.GetItemLen(Idx: Integer): Integer;
  1396. var Src: PDWORD;
  1397. begin
  1398. if (Idx >= 0) and (Idx <= Count) then
  1399. begin
  1400. Src := PDWORD( DWORD( fTextBuf ) + DWORD( fList.Items[ Idx ] ) + 4 );
  1401. Result := Src^
  1402. end
  1403. else Result := 0;
  1404. end;
  1405. function TFastStrListEx.GetObject(Idx: Integer): DWORD;
  1406. var Src: PDWORD;
  1407. begin
  1408. if (Idx >= 0) and (Idx <= Count) then
  1409. begin
  1410. Src := PDWORD( DWORD( fTextBuf ) + DWORD( fList.Items[ Idx ] ) );
  1411. Result := Src^
  1412. end
  1413. else Result := 0;
  1414. end;
  1415. function TFastStrListEx.GetPChars(Idx: Integer): PChar;
  1416. begin
  1417. if (Idx >= 0) and (Idx <= Count) then
  1418. Result := PChar( DWORD( fTextBuf ) + DWORD( fList.Items[ Idx ] ) + 8 )
  1419. else Result := nil;
  1420. end;
  1421. function TFastStrListEx.GetTextStr: string;
  1422. var L, i: Integer;
  1423. p: PChar;
  1424. begin
  1425. L := 0;
  1426. for i := 0 to Count-1 do
  1427. Inc( L, ItemLen[ i ] + 2 );
  1428. SetLength( Result, L );
  1429. p := PChar( Result );
  1430. for i := 0 to Count-1 do
  1431. begin
  1432. L := ItemLen[ i ];
  1433. if L > 0 then
  1434. begin
  1435. System.Move( ItemPtrs[ i ]^, p^, L );
  1436. Inc( p, L );
  1437. end;
  1438. p^ := #13; Inc( p );
  1439. p^ := #10; Inc( p );
  1440. end;
  1441. end;
  1442. function TFastStrListEx.IndexOf(const S: string): integer;
  1443. begin
  1444. if not Find( S, Result ) then Result := -1;
  1445. end;
  1446. function TFastStrListEx.IndexOf_NoCase(const S: string): integer;
  1447. begin
  1448. Result := IndexOfStrL_NoCase( PChar( S ), Length( S ) );
  1449. end;
  1450. function TFastStrListEx.IndexOfStrL_NoCase(Str: PChar;
  1451. L: Integer): integer;
  1452. var i: Integer;
  1453. begin
  1454. for i := 0 to Count-1 do
  1455. if (ItemLen[ i ] = L) and
  1456. ((L = 0) or (StrLComp_NoCase( ItemPtrs[ i ], Str, L ) = 0)) then
  1457. begin
  1458. Result := i;
  1459. Exit;
  1460. end;
  1461. Result := -1;
  1462. end;
  1463. procedure TFastStrListEx.Init;
  1464. begin
  1465. fList := NewList;
  1466. FastClear := TRUE;
  1467. end;
  1468. procedure TFastStrListEx.InsertAnsi(Idx: integer; const S: String);
  1469. begin
  1470. InsertObjectLen( Idx, PChar( S ), Length( S ), 0 );
  1471. end;
  1472. procedure TFastStrListEx.InsertAnsiObject(Idx: integer; const S: String;
  1473. Obj: DWORD);
  1474. begin
  1475. InsertObjectLen( Idx, PChar( S ), Length( S ), Obj );
  1476. end;
  1477. procedure TFastStrListEx.Insert(Idx: integer; S: PChar);
  1478. begin
  1479. InsertObjectLen( Idx, S, StrLen( S ), 0 )
  1480. end;
  1481. procedure TFastStrListEx.InsertLen(Idx: Integer; S: PChar; Len: Integer);
  1482. begin
  1483. InsertObjectLen( Idx, S, Len, 0 )
  1484. end;
  1485. procedure TFastStrListEx.InsertObject(Idx: Integer; S: PChar; Obj: DWORD);
  1486. begin
  1487. InsertObjectLen( Idx, S, StrLen( S ), Obj );
  1488. end;
  1489. procedure TFastStrListEx.InsertObjectLen(Idx: Integer; S: PChar;
  1490. Len: Integer; Obj: DWORD);
  1491. var Dest: PChar;
  1492. begin
  1493. ProvideSpace( Len+9 );
  1494. Dest := PChar( DWORD( fTextBuf ) + fUsedSiz );
  1495. fList.Insert( Idx, Pointer( DWORD(Dest)-DWORD(fTextBuf) ) );
  1496. PDWORD( Dest )^ := Obj;
  1497. Inc( Dest, 4 );
  1498. PDWORD( Dest )^ := Len;
  1499. Inc( Dest, 4 );
  1500. if S <> nil then
  1501. System.Move( S^, Dest^, Len );
  1502. Inc( Dest, Len );
  1503. Dest^ := #0;
  1504. Inc( fUsedSiz, Len+9 );
  1505. Inc( fCount );
  1506. end;
  1507. function TFastStrListEx.Last: String;
  1508. begin
  1509. if Count > 0 then
  1510. Result := Items[ Count-1 ]
  1511. else
  1512. Result := '';
  1513. end;
  1514. function TFastStrListEx.LoadFromFile(const FileName: string): Boolean;
  1515. var Strm: PStream;
  1516. begin
  1517. Strm := NewReadFileStream( FileName );
  1518. TRY
  1519. Result := Strm.Handle <> INVALID_HANDLE_VALUE;
  1520. if Result then
  1521. LoadFromStream( Strm, FALSE )
  1522. else
  1523. Clear;
  1524. FINALLY
  1525. Strm.Free;
  1526. END;
  1527. end;
  1528. procedure TFastStrListEx.LoadFromStream(Stream: PStream;
  1529. Append2List: boolean);
  1530. var Txt: String;
  1531. begin
  1532. SetLength( Txt, Stream.Size - Stream.Position );
  1533. Stream.Read( Txt[ 1 ], Stream.Size - Stream.Position );
  1534. SetText( Txt, Append2List );
  1535. end;
  1536. procedure TFastStrListEx.MergeFromFile(const FileName: string);
  1537. var Strm: PStream;
  1538. begin
  1539. Strm := NewReadFileStream( FileName );
  1540. TRY
  1541. LoadFromStream( Strm, TRUE );
  1542. FINALLY
  1543. Strm.Free;
  1544. END;
  1545. end;
  1546. procedure TFastStrListEx.Move(CurIndex, NewIndex: integer);
  1547. begin
  1548. Assert( (CurIndex >= 0) and (CurIndex < Count) and (NewIndex >= 0) and
  1549. (NewIndex < Count), 'Item indexes violates TFastStrListEx range' );
  1550. fList.MoveItem( CurIndex, NewIndex );
  1551. end;
  1552. procedure TFastStrListEx.ProvideSpace(AddSize: DWORD);
  1553. var OldTextBuf: PChar;
  1554. begin
  1555. Inc( AddSize, 9 );
  1556. if AddSize > fTextSiz - fUsedSiz then
  1557. begin // óâåëè÷åíèå ðàçìåðà áóôåðà
  1558. fTextSiz := Max( 1024, (fUsedSiz + AddSize) * 2 );
  1559. OldTextBuf := fTextBuf;
  1560. GetMem( fTextBuf, fTextSiz );
  1561. if OldTextBuf <> nil then
  1562. begin
  1563. System.Move( OldTextBuf^, fTextBuf^, fUsedSiz );
  1564. FreeMem( OldTextBuf );
  1565. end;
  1566. end;
  1567. if fList.Count >= fList.Capacity then
  1568. fList.Capacity := Max( 100, fList.Count * 2 );
  1569. end;
  1570. procedure TFastStrListEx.Put(Idx: integer; const Value: string);
  1571. var Dest: PChar;
  1572. OldLen: Integer;
  1573. OldObj: DWORD;
  1574. begin
  1575. OldLen := ItemLen[ Idx ];
  1576. if Length( Value ) <= OldLen then
  1577. begin
  1578. Dest := PChar( DWORD( fTextBuf ) + DWORD( fList.Items[ Idx ] ) + 4 );
  1579. PDWORD( Dest )^ := Length( Value );
  1580. Inc( Dest, 4 );
  1581. if Value <> '' then
  1582. System.Move( Value[ 1 ], Dest^, Length( Value ) );
  1583. Inc( Dest, Length( Value ) );
  1584. Dest^ := #0;
  1585. if Idx = Count-1 then
  1586. Dec( fUsedSiz, OldLen - Length( Value ) );
  1587. end
  1588. else
  1589. begin
  1590. OldObj := 0;
  1591. while Idx > Count do
  1592. AddObjectLen( nil, 0, 0 );
  1593. if Idx = Count-1 then
  1594. begin
  1595. OldObj := Objects[ Idx ];
  1596. Delete( Idx );
  1597. end;
  1598. if Idx = Count then
  1599. AddObjectLen( PChar( Value ), Length( Value ), OldObj )
  1600. else
  1601. begin
  1602. ProvideSpace( Length( Value ) + 9 );
  1603. Dest := PChar( DWORD( fTextBuf ) + fUsedSiz );
  1604. fList.Items[ Idx ] := Pointer( DWORD(Dest)-DWORD(fTextBuf) );
  1605. Inc( Dest, 4 );
  1606. PDWORD( Dest )^ := Length( Value );
  1607. Inc( Dest, 4 );
  1608. if Value <> '' then
  1609. System.Move( Value[ 1 ], Dest^, Length( Value ) );
  1610. Inc( Dest, Length( Value ) );
  1611. Dest^ := #0;
  1612. Inc( fUsedSiz, Length( Value )+9 );
  1613. end;
  1614. end;
  1615. end;
  1616. function TFastStrListEx.SaveToFile(const FileName: string): Boolean;
  1617. var Strm: PStream;
  1618. begin
  1619. Strm := NewWriteFileStream( FileName );
  1620. TRY
  1621. if Strm.Handle <> INVALID_HANDLE_VALUE then
  1622. SaveToStream( Strm );
  1623. Result := TRUE;
  1624. FINALLY
  1625. Strm.Free;
  1626. END;
  1627. end;
  1628. procedure TFastStrListEx.SaveToStream(Stream: PStream);
  1629. var Txt: String;
  1630. begin
  1631. Txt := Text;
  1632. Stream.Write( PChar( Txt )^, Length( Txt ) );
  1633. end;
  1634. procedure TFastStrListEx.SetObject(Idx: Integer; const Value: DWORD);
  1635. var Dest: PDWORD;
  1636. begin
  1637. if Idx < 0 then Exit;
  1638. while Idx >= Count do
  1639. AddObjectLen( nil, 0, 0 );
  1640. Dest := PDWORD( DWORD( fTextBuf ) + DWORD( fList.Items[ Idx ] ) );
  1641. Dest^ := Value;
  1642. end;
  1643. procedure TFastStrListEx.SetText(const S: string; Append2List: boolean);
  1644. var Len2Add, NLines, L: Integer;
  1645. p0, p: PChar;
  1646. begin
  1647. if not Append2List then Clear;
  1648. // ïîäñ÷åò òðåáóåìîãî ïðîñòðàíñòâà
  1649. Len2Add := 0;
  1650. NLines := 0;
  1651. p := Pchar( S );
  1652. p0 := p;
  1653. L := Length( S );
  1654. while L > 0 do
  1655. begin
  1656. if p^ = #13 then
  1657. begin
  1658. Inc( NLines );
  1659. Inc( Len2Add, 9 + DWORD(p)-DWORD(p0) );
  1660. REPEAT Inc( p ); Dec( L );
  1661. UNTIL (p^ <> #10) or (L = 0);
  1662. p0 := p;
  1663. end
  1664. else
  1665. begin
  1666. Inc( p ); Dec( L );
  1667. end;
  1668. end;
  1669. if DWORD(p) > DWORD(p0) then
  1670. begin
  1671. Inc( NLines );
  1672. Inc( Len2Add, 9 + DWORD(p)-DWORD(p0) );
  1673. end;
  1674. if Len2Add = 0 then Exit;
  1675. // äîáàâëåíèå
  1676. ProvideSpace( Len2Add - 9 );
  1677. if fList.Capacity <= fList.Count + NLines then
  1678. fList.Capacity := Max( (fList.Count + NLines) * 2, 100 );
  1679. p := PChar( S );
  1680. p0 := p;
  1681. L := Length( S );
  1682. while L > 0 do
  1683. begin
  1684. if p^ = #13 then
  1685. begin
  1686. AddObjectLen( p0, DWORD(p)-DWORD(p0), 0 );
  1687. REPEAT Inc( p ); Dec( L );
  1688. UNTIL (p^ <> #10) or (L = 0);
  1689. p0 := p;
  1690. end
  1691. else
  1692. begin
  1693. Inc( p ); Dec( L );
  1694. end;
  1695. end;
  1696. if DWORD(p) > DWORD(p0) then
  1697. AddObjectLen( p0, DWORD(p)-DWORD(p0), 0 );
  1698. end;
  1699. procedure TFastStrListEx.SetTextStr(const Value: string);
  1700. begin
  1701. SetText( Value, FALSE );
  1702. end;
  1703. function CompareFast(const Data: Pointer; const e1,e2 : Dword) : Integer;
  1704. var FSL: PFastStrListEx;
  1705. L1, L2: Integer;
  1706. S1, S2: PChar;
  1707. begin
  1708. FSL := Data;
  1709. S1 := FSL.ItemPtrs[ e1 ];
  1710. S2 := FSL.ItemPtrs[ e2 ];
  1711. L1 := FSL.ItemLen[ e1 ];
  1712. L2 := FSL.ItemLen[ e2 ];
  1713. if FSL.fCaseSensitiveSort then
  1714. Result := StrLComp( S1, S2, Min( L1, L2 ) )
  1715. else
  1716. Result := StrLComp_NoCase( S1, S2, Min( L1, L2 ) );
  1717. if Result = 0 then
  1718. Result := L1 - L2;
  1719. if Result = 0 then
  1720. Result := e1 - e2;
  1721. end;
  1722. procedure SwapFast(const Data : Pointer; const e1,e2 : Dword);
  1723. var FSL: PFastStrListEx;
  1724. begin
  1725. FSL := Data;
  1726. FSL.Swap( e1, e2 );
  1727. end;
  1728. procedure TFastStrListEx.Sort(CaseSensitive: Boolean);
  1729. begin
  1730. fCaseSensitiveSort := CaseSensitive;
  1731. SortData( @ Self, Count, CompareFast, SwapFast );
  1732. end;
  1733. procedure TFastStrListEx.Swap(Idx1, Idx2: Integer);
  1734. begin
  1735. Assert( (Idx1 >= 0) and (Idx1 <= Count-1) and (Idx2 >= 0) and (Idx2 <= Count-1),
  1736. 'Item indexes violates TFastStrListEx range' );
  1737. fList.Swap( Idx1, Idx2 );
  1738. end;
  1739. function TFastStrListEx.GetValues(AName: PChar): PChar;
  1740. var i: Integer;
  1741. s, n: PChar;
  1742. begin
  1743. if not Upper_Initialized then
  1744. InitUpper;
  1745. for i := 0 to Count-1 do
  1746. begin
  1747. s := ItemPtrs[ i ];
  1748. n := AName;
  1749. while (Upper[ s^ ] = Upper[ n^ ]) and (s^ <> '=') and (s^ <> #0) and (n^ <> #0) do
  1750. begin
  1751. Inc( s );
  1752. Inc( n );
  1753. end;
  1754. if (s^ = '=') and (n^ = #0) then
  1755. begin
  1756. Result := s;
  1757. Inc( Result );
  1758. Exit;
  1759. end;
  1760. end;
  1761. Result := nil;
  1762. end;
  1763. function TFastStrListEx.IndexOfName(AName: PChar): Integer;
  1764. var i: Integer;
  1765. s, n: PChar;
  1766. begin
  1767. if not Upper_Initialized then
  1768. InitUpper;
  1769. for i := 0 to Count-1 do
  1770. begin
  1771. s := ItemPtrs[ i ];
  1772. n := AName;
  1773. while (Upper[ s^ ] = Upper[ n^ ]) and (s^ <> '=') and (s^ <> #0) and (n^ <> #0) do
  1774. begin
  1775. Inc( s );
  1776. Inc( n );
  1777. end;
  1778. if (s^ = '=') and (n^ = #0) then
  1779. begin
  1780. Result := i;
  1781. Exit;
  1782. end;
  1783. end;
  1784. Result := -1;
  1785. end;
  1786. procedure TFastStrListEx.Append(S: PChar);
  1787. begin
  1788. AppendLen( S, StrLen( S ) );
  1789. end;
  1790. procedure TFastStrListEx.AppendInt2Hex(N: DWORD; MinDigits: Integer);
  1791. var Buffer: array[ 0..9 ] of Char;
  1792. Mask: DWORD;
  1793. i, Len: Integer;
  1794. B: Byte;
  1795. begin
  1796. if MinDigits > 8 then
  1797. MinDigits := 8;
  1798. if MinDigits <= 0 then
  1799. MinDigits := 1;
  1800. Mask := $F0000000;
  1801. for i := 8 downto MinDigits do
  1802. begin
  1803. if Mask and N <> 0 then
  1804. begin
  1805. MinDigits := i;
  1806. break;
  1807. end;
  1808. Mask := Mask shr 4;
  1809. end;
  1810. i := 0;
  1811. Len := MinDigits;
  1812. Mask := $F shl ((Len - 1)*4);
  1813. while MinDigits > 0 do
  1814. begin
  1815. Dec( MinDigits );
  1816. B := (N and Mask) shr (MinDigits * 4);
  1817. Mask := Mask shr 4;
  1818. if B <= 9 then
  1819. Buffer[ i ] := Char( B + Ord( '0' ) )
  1820. else
  1821. Buffer[ i ] := Char( B + Ord( 'A' ) - 10 );
  1822. Inc( i );
  1823. end;
  1824. Buffer[ i ] := #0;
  1825. AppendLen( @ Buffer[ 0 ], Len );
  1826. end;
  1827. procedure TFastStrListEx.AppendLen(S: PChar; Len: Integer);
  1828. var Dest: PChar;
  1829. begin
  1830. if Count = 0 then
  1831. AddLen( S, Len )
  1832. else
  1833. begin
  1834. ProvideSpace( Len );
  1835. Dest := PChar( DWORD( fTextBuf ) + fUsedSiz - 1 );
  1836. System.Move( S^, Dest^, Len );
  1837. Inc( Dest, Len );
  1838. Dest^ := #0;
  1839. Inc( fUsedSiz, Len );
  1840. Dest := PChar( DWORD( fTextBuf ) + DWORD( fList.Items[ Count-1 ] ) );
  1841. Inc( Dest, 4 );
  1842. PDWORD( Dest )^ := PDWORD( Dest )^ + DWORD( Len );
  1843. end;
  1844. end;
  1845. { TCABFile }
  1846. //[function OpenCABFile]
  1847. function OpenCABFile( const APaths: array of String ): PCABFile;
  1848. var I: Integer;
  1849. begin
  1850. {-}
  1851. New( Result, Create );
  1852. {+}{++}(*Result := PCABFile.Create;*){--}
  1853. Result.FSetupapi := LoadLibrary( 'setupapi.dll' );
  1854. Result.FNames := {$IFDEF UNICODE_CTRLS} NewWStrList {$ELSE} NewStrList {$ENDIF};
  1855. Result.FPaths := {$IFDEF UNICODE_CTRLS} NewWStrList {$ELSE} NewStrList {$ENDIF};
  1856. for I := 0 to High( APaths ) do
  1857. Result.FPaths.Add( APaths[ I ] );
  1858. end;
  1859. //[destructor TCABFile.Destroy]
  1860. destructor TCABFile.Destroy;
  1861. begin
  1862. FNames.Free;
  1863. FPaths.Free;
  1864. FTargetPath := '';
  1865. if FSetupapi <> 0 then
  1866. FreeLibrary( FSetupapi );
  1867. inherited;
  1868. end;
  1869. const
  1870. SPFILENOTIFY_FILEINCABINET = $11;
  1871. SPFILENOTIFY_NEEDNEWCABINET = $12;
  1872. type
  1873. PSP_FILE_CALLBACK = function( Context: Pointer; Notification, Param1, Param2: DWORD ): DWORD;
  1874. stdcall;
  1875. TSetupIterateCabinet = function ( CabinetFile: PKOLChar; Reserved: DWORD;
  1876. MsgHandler: PSP_FILE_CALLBACK; Context: Pointer ): Boolean; stdcall;
  1877. //external 'setupapi.dll' name 'SetupIterateCabinetA';
  1878. TSetupPromptDisk = function (
  1879. hwndParent: HWND; // parent window of the dialog box
  1880. DialogTitle: PKOLChar; // optional, title of the dialog box
  1881. DiskName: PKOLChar; // optional, name of disk to insert
  1882. PathToSource: PKOLChar;// optional, expected source path
  1883. FileSought: PKOLChar; // name of file needed
  1884. TagFile: PKOLChar; // optional, source media tag file
  1885. DiskPromptStyle: DWORD; // specifies dialog box behavior
  1886. PathBuffer: PKOLChar; // receives the source location
  1887. PathBufferSize: DWORD; // size of the supplied buffer
  1888. PathRequiredSize: PDWORD // optional, buffer size needed
  1889. ): DWORD; stdcall;
  1890. //external 'setupapi.dll' name 'SetupPromptForDiskA';
  1891. type
  1892. TCabinetInfo = packed record
  1893. CabinetPath: PKOLChar;
  1894. CabinetFile: PKOLChar;
  1895. DiskName: PKOLChar;
  1896. SetId: WORD;
  1897. CabinetNumber: WORD;
  1898. end;
  1899. PCabinetInfo = ^TCabinetInfo;
  1900. TFileInCabinetInfo = packed record
  1901. NameInCabinet: PKOLChar;
  1902. FileSize: DWORD;
  1903. Win32Error: DWORD;
  1904. DosDate: WORD;
  1905. DosTime: WORD;
  1906. DosAttribs: WORD;
  1907. FullTargetName: array[0..MAX_PATH-1] of KOLChar;
  1908. end;
  1909. PFileInCabinetInfo = ^TFileInCabinetInfo;
  1910. //[function CABCallback]
  1911. function CABCallback( Context: Pointer; Notification, Param1, Param2: DWORD ): DWORD;
  1912. stdcall;
  1913. var CAB: PCABFile;
  1914. CABPath, OldPath: KOLString;
  1915. CABInfo: PCabinetInfo;
  1916. CABFileInfo: PFileInCabinetInfo;
  1917. hr: Integer;
  1918. SetupPromptProc: TSetupPromptDisk;
  1919. begin
  1920. Result := 0;
  1921. CAB := Context;
  1922. case Notification of
  1923. SPFILENOTIFY_NEEDNEWCABINET:
  1924. begin
  1925. OldPath := CAB.FPaths.Items[ CAB.FCurCAB ];
  1926. Inc( CAB.FCurCAB );
  1927. if CAB.FCurCAB = CAB.FPaths.Count then
  1928. CAB.FPaths.Add( '?' );
  1929. CABPath := CAB.FPaths.Items[ CAB.FCurCAB ];
  1930. if CABPath = '?' then
  1931. begin
  1932. if Assigned( CAB.FOnNextCAB ) then
  1933. CAB.FPaths.Items[CAB.FCurCAB ] := CAB.FOnNextCAB( CAB );
  1934. CABPath := CAB.FPaths.Items[ CAB.FCurCAB ];
  1935. if CABPath = '?' then
  1936. begin
  1937. SetLength( CABPath, MAX_PATH );
  1938. CABInfo := Pointer( Param1 );
  1939. if CAB.FSetupapi <> 0 then
  1940. SetupPromptProc := GetProcAddress( CAB.FSetupapi, 'SetupPromptForDiskA' )
  1941. else
  1942. SetupPromptProc := nil;
  1943. if Assigned( SetupPromptProc ) then
  1944. begin
  1945. hr := SetupPromptProc( 0, nil, nil, PKOLChar( ExtractFilePath( OldPath ) ),
  1946. CABInfo.CabinetFile, nil, 2 {IDF_NOSKIP}, @CabPath[ 1 ], MAX_PATH, nil );
  1947. case hr of
  1948. 0: // success
  1949. begin
  1950. {$IFDEF UNICODE_CTRLS} WStrCopy {$ELSE} StrCopy {$ENDIF}
  1951. ( PKOLChar( Param2 ), PKOLChar( CABPath ) );
  1952. Result := 0;
  1953. end;
  1954. 2: // skip file
  1955. Result := 0;
  1956. else // cancel
  1957. Result := ERROR_FILE_NOT_FOUND;
  1958. end;
  1959. end;
  1960. end
  1961. else
  1962. begin
  1963. {$IFDEF UNICODE_CTRLS} WStrCopy {$ELSE} StrCopy {$ENDIF}
  1964. ( PKOLChar( Param2 ), PKOLChar( CABPath ) );
  1965. Result := 0;
  1966. end;
  1967. end;
  1968. end;
  1969. SPFILENOTIFY_FILEINCABINET:
  1970. begin
  1971. CABFileInfo := Pointer( Param1 );
  1972. if CAB.FGettingNames then
  1973. begin
  1974. CAB.FNames.Add( CABFileInfo.NameInCabinet );
  1975. Result := 2; // FILEOP_SKIP
  1976. end
  1977. else
  1978. begin
  1979. CABPath := CABFileInfo.NameInCabinet;
  1980. if Assigned( CAB.FOnFile ) then
  1981. begin
  1982. if CAB.FOnFile( CAB, CABPath ) then
  1983. begin
  1984. if ExtractFilePath( CABPath ) = '' then
  1985. if CAB.FTargetPath <> '' then
  1986. CABPath := CAB.TargetPath + CABPath;
  1987. {$IFDEF UNICODE_CTRLS} WStrCopy {$ELSE} StrCopy {$ENDIF}
  1988. ( @CABFileInfo.FullTargetName[ 0 ], PKOLChar( CABPath ) );
  1989. Result := 1; // FILEOP_DOIT
  1990. end
  1991. else
  1992. Result := 2
  1993. end
  1994. else
  1995. begin
  1996. if CAB.FTargetPath <> '' then
  1997. {$IFDEF UNICODE_CTRLS} WStrCopy {$ELSE} StrCopy {$ENDIF}
  1998. ( @CABFileInfo.FullTargetName[ 0 ],
  1999. PKOLChar( CAB.TargetPath + CABPath ) );
  2000. Result := 1;
  2001. end;
  2002. end;
  2003. end;
  2004. end;
  2005. end;
  2006. //[function TCABFile.Execute]
  2007. function TCABFile.Execute: Boolean;
  2008. var SetupIterateProc: TSetupIterateCabinet;
  2009. begin
  2010. FCurCAB := 0;
  2011. Result := FALSE;
  2012. if FSetupapi = 0 then Exit;
  2013. SetupIterateProc := GetProcAddress( FSetupapi, 'SetupIterateCabinetA' );
  2014. if not Assigned( SetupIterateProc ) then Exit;
  2015. Result := SetupIterateProc( PKOLChar( KOLString( FPaths.Items[ 0 ] ) ),
  2016. 0, CABCallback, @Self );
  2017. end;
  2018. //[function TCABFile.GetCount]
  2019. function TCABFile.GetCount: Integer;
  2020. begin
  2021. GetNames( 0 );
  2022. Result := FNames.Count;
  2023. end;
  2024. //[function TCABFile.GetNames]
  2025. function TCABFile.GetNames(Idx: Integer): KOLString;
  2026. begin
  2027. if FNames.Count = 0 then
  2028. begin
  2029. FGettingNames := TRUE;
  2030. Execute;
  2031. FGettingNames := FALSE;
  2032. end;
  2033. Result := '';
  2034. if Idx < FNames.Count then
  2035. Result := FNames.Items[ Idx ];
  2036. end;
  2037. //[function TCABFile.GetPaths]
  2038. function TCABFile.GetPaths(Idx: Integer): KOLString;
  2039. begin
  2040. Result := FPaths.Items[ Idx ];
  2041. end;
  2042. //[function TCABFile.GetTargetPath]
  2043. function TCABFile.GetTargetPath: KOLString;
  2044. begin
  2045. Result := FTargetPath;
  2046. if Result <> '' then
  2047. if Result[ Length( Result ) ] <> '\' then
  2048. Result := Result + '\';
  2049. end;
  2050. { -- TDirChange -- }
  2051. const FilterFlags: array[ TFileChangeFilters ] of Integer = (
  2052. FILE_NOTIFY_CHANGE_FILE_NAME, FILE_NOTIFY_CHANGE_DIR_NAME,
  2053. FILE_NOTIFY_CHANGE_ATTRIBUTES, FILE_NOTIFY_CHANGE_SIZE,
  2054. FILE_NOTIFY_CHANGE_LAST_WRITE, $20 {FILE_NOTIFY_CHANGE_LAST_ACCESS},
  2055. $40 {FILE_NOTIFY_CHANGE_CREATION}, FILE_NOTIFY_CHANGE_SECURITY );
  2056. //[FUNCTION _NewDirChgNotifier]
  2057. {$IFDEF ASM_VERSION}
  2058. function _NewDirChgNotifier: PDirChange;
  2059. begin
  2060. New( Result, Create );
  2061. end;
  2062. //[function NewDirChangeNotifier]
  2063. function NewDirChangeNotifier( const Path: String; Filter: TFileChangeFilter;
  2064. WatchSubtree: Boolean; ChangeProc: TOnDirChange )
  2065. : PDirChange;
  2066. const Dflt_Flags = FILE_NOTIFY_CHANGE_FILE_NAME or FILE_NOTIFY_CHANGE_DIR_NAME or
  2067. FILE_NOTIFY_CHANGE_ATTRIBUTES or FILE_NOTIFY_CHANGE_SIZE or
  2068. FILE_NOTIFY_CHANGE_LAST_WRITE;
  2069. asm
  2070. PUSH EBX
  2071. PUSH ECX // [EBP-8] = WatchSubtree
  2072. PUSH EDX // [EBP-12] = Filter
  2073. PUSH EAX // [EBP-16] = Path
  2074. CALL _NewDirChgNotifier
  2075. XCHG EBX, EAX
  2076. LEA EAX, [EBX].TDirChange.FPath
  2077. POP EDX
  2078. CALL System.@LStrAsg
  2079. MOV EAX, [ChangeProc].TMethod.Code
  2080. MOV [EBX].TDirChange.FOnChange.TMethod.Code, EAX
  2081. MOV EAX, [ChangeProc].TMethod.Data
  2082. MOV [EBX].TDirChange.FOnChange.TMethod.Data, EAX
  2083. POP ECX
  2084. MOV EAX, Dflt_Flags
  2085. MOVZX ECX, CL
  2086. JECXZ @@flags_ready
  2087. PUSH ECX
  2088. MOV EAX, ESP
  2089. MOV EDX, offset[FilterFlags]
  2090. XOR ECX, ECX
  2091. MOV CL, 7
  2092. CALL MakeFlags
  2093. POP ECX
  2094. @@flags_ready: // EAX = Flags
  2095. POP EDX
  2096. MOVZX EDX, DL // EDX = WatchSubtree
  2097. PUSH EAX
  2098. PUSH EDX
  2099. PUSH [EBX].TDirChange.FPath
  2100. CALL FindFirstChangeNotification
  2101. MOV [EBX].TDirChange.FHandle, EAX
  2102. INC EAX
  2103. JZ @@fault
  2104. PUSH EBX
  2105. PUSH offset[TDirChange.Execute]
  2106. CALL NewThreadEx
  2107. MOV [EBX].TDirChange.FMonitor, EAX
  2108. JMP @@exit
  2109. @@fault:
  2110. XCHG EAX, EBX
  2111. CALL TObj.Free
  2112. @@exit:
  2113. XCHG EAX, EBX
  2114. POP EBX
  2115. end;
  2116. {$ELSE ASM_VERSION} //Pascal
  2117. function NewDirChangeNotifier( const Path: KOLString; Filter: TFileChangeFilter;
  2118. WatchSubtree: Boolean; ChangeProc: TOnDirChange )
  2119. : PDirChange;
  2120. var Flags: DWORD;
  2121. begin
  2122. {-}
  2123. New( Result, Create );
  2124. {+}{++}(*Result := PDirChange.Create;*){--}
  2125. Result.FPath := Path;
  2126. Result.FOnChange := ChangeProc;
  2127. if Filter = [ ] then
  2128. Flags := FILE_NOTIFY_CHANGE_FILE_NAME or FILE_NOTIFY_CHANGE_DIR_NAME or
  2129. FILE_NOTIFY_CHANGE_ATTRIBUTES or FILE_NOTIFY_CHANGE_SIZE or
  2130. FILE_NOTIFY_CHANGE_LAST_WRITE
  2131. else
  2132. Flags := MakeFlags( @Filter, FilterFlags );
  2133. Result.FinEvent := CreateEvent( nil, TRUE, FALSE, nil );
  2134. Result.FHandle := FindFirstChangeNotification(PKOLChar(Result.FPath),
  2135. Bool( Integer( WatchSubtree ) ), Flags);
  2136. if Result.FHandle <> INVALID_HANDLE_VALUE then
  2137. Result.FMonitor := NewThreadAutoFree( Result.Execute )
  2138. else //MsgOK( 'Can not monitor ' + Result.FPath + #13'Error ' + Int2Str( GetLastError ) );
  2139. begin
  2140. Result.Free;
  2141. Result := nil;
  2142. end;
  2143. end;
  2144. {$ENDIF ASM_VERSION}
  2145. //[END _NewDirChgNotifier]
  2146. { TDirChange }
  2147. {$IFDEF ASM_VERSION}
  2148. //[procedure TDirChange.Changed]
  2149. procedure TDirChange.Changed;
  2150. asm
  2151. MOV ECX, [EAX].FOnChange.TMethod.Code
  2152. JECXZ @@exit
  2153. MOV ECX, [EAX].FPath
  2154. XCHG EDX, EAX
  2155. MOV EAX, [EDX].FOnChange.TMethod.Data
  2156. CALL [EDX].FOnChange.TMethod.Code
  2157. @@exit:
  2158. end;
  2159. {$ELSE ASM_VERSION} //Pascal
  2160. procedure TDirChange.Changed;
  2161. begin
  2162. if Assigned( FOnChange ) then
  2163. FOnChange(@Self, FPath);
  2164. end;
  2165. {$ENDIF ASM_VERSION}
  2166. {$IFDEF ASM_VERSION}
  2167. //[destructor TDirChange.Destroy]
  2168. destructor TDirChange.Destroy;
  2169. asm
  2170. PUSH EBX
  2171. XCHG EBX, EAX
  2172. MOV ECX, [EBX].FMonitor
  2173. JECXZ @@no_monitor
  2174. XCHG EAX, ECX
  2175. CALL TObj.Free
  2176. @@no_monitor:
  2177. MOV ECX, [EBX].FHandle
  2178. JECXZ @@exit
  2179. PUSH ECX
  2180. CALL FindCloseChangeNotification
  2181. @@exit:
  2182. LEA EAX, [EBX].FPath
  2183. CALL System.@LStrClr
  2184. XCHG EAX, EBX
  2185. CALL TObj.Destroy
  2186. POP EBX
  2187. end;
  2188. {$ELSE ASM_VERSION} //Pascal
  2189. destructor TDirChange.Destroy;
  2190. begin
  2191. if FHandle > 0 then // FHandle <> INVALID_HANDLE_VALUE AND FHandle <> 0
  2192. begin
  2193. OnChange := nil;
  2194. SetEvent( FinEvent );
  2195. end;
  2196. //if FMonitor <> nil then
  2197. // FMonitor.Free;
  2198. FPath := '';
  2199. inherited;
  2200. end;
  2201. {$ENDIF ASM_VERSION}
  2202. {$IFDEF ASM_noVERSION}
  2203. //[function TDirChange.Execute]
  2204. function TDirChange.Execute(Sender: PThread): Integer;
  2205. asm
  2206. PUSH EBX
  2207. PUSH ESI
  2208. XCHG EBX, EAX
  2209. MOV ESI, EDX
  2210. @@loo:
  2211. MOVZX ECX, [ESI].TThread.FTerminated
  2212. INC ECX
  2213. LOOP @@e_loop
  2214. MOV ECX, [EBX].FHandle
  2215. INC ECX
  2216. JZ @@e_loop
  2217. PUSH INFINITE
  2218. PUSH ECX
  2219. CALL WaitForSingleObject
  2220. OR EAX, EAX
  2221. JNZ @@loo
  2222. PUSH [EBX].FHandle
  2223. MOV EAX, [EBX].FMonitor
  2224. PUSH EBX
  2225. PUSH offset[TDirChange.Changed]
  2226. CALL TThread.Synchronize
  2227. CALL FindNextChangeNotification
  2228. JMP @@loo
  2229. @@e_loop:
  2230. POP ESI
  2231. POP EBX
  2232. XOR EAX, EAX
  2233. end;
  2234. {$ELSE ASM_VERSION} //Pascal
  2235. function TDirChange.Execute(Sender: PThread): Integer;
  2236. var Handles: array[ 0..1 ] of THandle;
  2237. //i: Integer;
  2238. begin
  2239. Handles[ 0 ] := FHandle;
  2240. Handles[ 1 ] := FinEvent;
  2241. while TRUE do
  2242. case WaitForMultipleObjects(2, @ Handles[ 0 ], FALSE, INFINITE) of
  2243. WAIT_OBJECT_0:
  2244. begin
  2245. if AppletTerminated then break;
  2246. Applet.GetWindowHandle;
  2247. Sender.Synchronize( Changed );
  2248. FindNextChangeNotification(Handles[ 0 ]);
  2249. {for i := 1 to 10 do
  2250. begin
  2251. Sleep( 10 );
  2252. if AppletTerminated then break;
  2253. end;}
  2254. end;
  2255. else break;
  2256. end;
  2257. {$IFDEF SAFE_CODE}
  2258. TRY
  2259. {$ENDIF}
  2260. FindCloseChangeNotification( Handles[ 0 ] );
  2261. CloseHandle( Handles[ 1 ] );
  2262. {$IFDEF SAFE_CODE}
  2263. EXCEPT
  2264. END;
  2265. {$ENDIF}
  2266. Result := 0;
  2267. end;
  2268. {$ENDIF ASM_VERSION}
  2269. {$ifdef win32}
  2270. ////////////////////////////////////////////////////////////////////////
  2271. //
  2272. //
  2273. // M E T A F I L E
  2274. //
  2275. //
  2276. ////////////////////////////////////////////////////////////////////////
  2277. {++}(*
  2278. //[API SetEnhMetaFileBits]
  2279. function SetEnhMetaFileBits; external gdi32 name 'SetEnhMetaFileBits';
  2280. function PlayEnhMetaFile; external gdi32 name 'PlayEnhMetaFile';
  2281. *){--}
  2282. //[function NewMetafile]
  2283. function NewMetafile: PMetafile;
  2284. begin
  2285. {-}
  2286. new( Result, Create );
  2287. {+}{++}(*Result := PMetafile.Create;*){--}
  2288. end;
  2289. //[END NewMetafile]
  2290. { TMetafile }
  2291. //[procedure TMetafile.Clear]
  2292. procedure TMetafile.Clear;
  2293. begin
  2294. if fHandle <> 0 then
  2295. DeleteEnhMetaFile( fHandle );
  2296. fHandle := 0;
  2297. end;
  2298. //[destructor TMetafile.Destroy]
  2299. destructor TMetafile.Destroy;
  2300. begin
  2301. if fHeader <> nil then
  2302. FreeMem( fHeader );
  2303. Clear;
  2304. inherited;
  2305. end;
  2306. //[procedure TMetafile.Draw]
  2307. procedure TMetafile.Draw(DC: HDC; X, Y: Integer);
  2308. begin
  2309. StretchDraw( DC, MakeRect( X, Y, X + Width, Y + Height ) );
  2310. end;
  2311. //[function TMetafile.Empty]
  2312. function TMetafile.Empty: Boolean;
  2313. begin
  2314. Result := fHandle = 0;
  2315. end;
  2316. //[function TMetafile.GetHeight]
  2317. function TMetafile.GetHeight: Integer;
  2318. begin
  2319. Result := 0;
  2320. if Empty then Exit;
  2321. RetrieveHeader;
  2322. Result := fHeader.rclBounds.Bottom - fHeader.rclBounds.Top;
  2323. //Result := fHeader.rclFrame.Bottom - fHeader.rclFrame.Top;
  2324. end;
  2325. //[function TMetafile.GetWidth]
  2326. function TMetafile.GetWidth: Integer;
  2327. begin
  2328. Result := 0;
  2329. if Empty then Exit;
  2330. RetrieveHeader;
  2331. Result := fHeader.rclBounds.Right - fHeader.rclBounds.Left;
  2332. //Result := fHeader.rclFrame.Right - fHeader.rclFrame.Left;
  2333. end;
  2334. //[function TMetafile.LoadFromFile]
  2335. function TMetafile.LoadFromFile(const Filename: String): Boolean;
  2336. var Strm: PStream;
  2337. begin
  2338. Strm := NewReadFileStream( FileName );
  2339. Result := LoadFromStream( Strm );
  2340. Strm.Free;
  2341. end;
  2342. //[function ComputeAldusChecksum]
  2343. function ComputeAldusChecksum(var WMF: TMetafileHeader): Word;
  2344. type
  2345. PWord = ^Word;
  2346. var
  2347. pW: PWord;
  2348. pEnd: PWord;
  2349. begin
  2350. Result := 0;
  2351. pW := @WMF;
  2352. pEnd := @WMF.CheckSum;
  2353. while cardinal(pW) < cardinal(pEnd) do
  2354. begin
  2355. Result := Result xor pW^;
  2356. Inc(Longint(pW), SizeOf(Word));
  2357. end;
  2358. end;
  2359. //[function TMetafile.LoadFromStream]
  2360. function TMetafile.LoadFromStream(Strm: PStream): Boolean;
  2361. var WMF: TMetaFileHeader;
  2362. WmfHdr: TMetaHeader;
  2363. EnhHdr: TEnhMetaHeader;
  2364. Pos, Pos1: Integer;
  2365. Sz: Integer;
  2366. MemStrm: PStream;
  2367. MFP: TMetafilePict;
  2368. begin
  2369. Result := FALSE;
  2370. Pos := Strm.Position;
  2371. if Strm.Read( WMF, Sizeof( WMF ) ) <> Sizeof( WMF ) then
  2372. begin
  2373. Strm.Position := Pos;
  2374. Exit;
  2375. end;
  2376. MemStrm := NewMemoryStream;
  2377. if WMF.Key = WMFKey then
  2378. begin // Windows metafile
  2379. if WMF.CheckSum <> ComputeAldusChecksum( WMF ) then
  2380. begin
  2381. Strm.Position := Pos;
  2382. Exit;
  2383. end;
  2384. Pos1 := Strm.Position;
  2385. if Strm.Read( WmfHdr, Sizeof( WmfHdr ) ) <> Sizeof( WmfHdr ) then
  2386. begin
  2387. Strm.Position := Pos;
  2388. Exit;
  2389. end;
  2390. Strm.Position := Pos1;
  2391. Sz := WMFHdr.mtSize * 2;
  2392. Stream2Stream( MemStrm, Strm, Sz );
  2393. FillChar( MFP, Sizeof( MFP ), 0 );
  2394. MFP.mm := MM_ANISOTROPIC;
  2395. fHandle := SetWinMetafileBits( Sz, MemStrm.Memory, 0, MFP );
  2396. end
  2397. else
  2398. begin // may be enchanced?
  2399. Strm.Position := Pos;
  2400. if Strm.Read( EnhHdr, Sizeof( EnhHdr ) ) < 8 then
  2401. begin
  2402. Strm.Position := Pos;
  2403. Exit;
  2404. end;
  2405. // yes, enchanced
  2406. Strm.Position := Pos;
  2407. Sz := EnhHdr.nBytes;
  2408. Stream2Stream( MemStrm, Strm, Sz );
  2409. fHandle := SetEnhMetaFileBits( Sz, MemStrm.Memory );
  2410. end;
  2411. MemStrm.Free;
  2412. Result := fHandle <> 0;
  2413. if not Result then
  2414. Strm.Position := Pos;
  2415. end;
  2416. //[procedure TMetafile.RetrieveHeader]
  2417. procedure TMetafile.RetrieveHeader;
  2418. var SzHdr: Integer;
  2419. begin
  2420. if fHeader = nil then
  2421. begin
  2422. SzHdr := GetEnhMetaFileHeader( fHandle, 0, nil );
  2423. fHeader := AllocMem( { SzHeader } Sizeof( fHeader^ ) );
  2424. fHeader.iType := EMR_HEADER;
  2425. fHeader.nSize := Sizeof( fHeader^ ) { SzHdr };
  2426. GetEnhMetaFileHeader( fHandle, SzHdr, fHeader );
  2427. end;
  2428. end;
  2429. //[procedure TMetafile.SetHandle]
  2430. procedure TMetafile.SetHandle(const Value: THandle);
  2431. begin
  2432. Clear;
  2433. fHandle := Value;
  2434. end;
  2435. //[procedure TMetafile.StretchDraw]
  2436. procedure TMetafile.StretchDraw(DC: HDC; const R: TRect);
  2437. begin
  2438. if Empty then Exit;
  2439. PlayEnhMetaFile( DC, fHandle, R );
  2440. {if not PlayEnhMetaFile( DC, fHandle, R ) then
  2441. begin
  2442. ShowMessage( SysErrorMessage( GetLastError ) );
  2443. end;}
  2444. end;
  2445. {$endif win32}
  2446. { ----------------------------------------------------------------------
  2447. TAction and TActionList
  2448. ----------------------------------------------------------------------- }
  2449. //[function NewActionList]
  2450. function NewActionList(AOwner: PControl): PActionList;
  2451. begin
  2452. {-}
  2453. New( Result, Create );
  2454. {+} {++}(* Result := PActionList.Create; *){--}
  2455. with Result{-}^{+} do begin
  2456. FActions:=NewList;
  2457. FOwner:=AOwner;
  2458. {$ifdef USE_OnIdle}
  2459. RegisterIdleHandler(DoUpdateActions);
  2460. {$endif USE_OnIdle}
  2461. end;
  2462. end;
  2463. //[END NewActionList]
  2464. //[function NewAction]
  2465. function NewAction(const ACaption, AHint: string; AOnExecute: TOnEvent): PAction;
  2466. begin
  2467. {-}
  2468. New( Result, Create );
  2469. {+} {++}(* Result := PAction.Create; *){--}
  2470. with Result{-}^{+} do begin
  2471. FControls:=NewList;
  2472. Enabled:=True;
  2473. Visible:=True;
  2474. Caption:=ACaption;
  2475. Hint:=AHint;
  2476. OnExecute:=AOnExecute;
  2477. end;
  2478. end;
  2479. //[END NewAction]
  2480. { TAction }
  2481. //[procedure TAction.LinkCtrl]
  2482. procedure TAction.LinkCtrl(ACtrl: PObj; ACtrlKind: TCtrlKind; AItemID: integer; AUpdateProc: TOnUpdateCtrlEvent);
  2483. var
  2484. cr: PControlRec;
  2485. begin
  2486. New(cr);
  2487. with cr^ do begin
  2488. Ctrl:=ACtrl;
  2489. CtrlKind:=ACtrlKind;
  2490. ItemID:=AItemID;
  2491. UpdateProc:=AUpdateProc;
  2492. end;
  2493. FControls.Add(cr);
  2494. FUpdateMask:=[upCaption, upHint, upChecked, upEnabled, upVisible, upHelpContext, upAccelerator];
  2495. AUpdateProc(cr);
  2496. FUpdateMask:=[];
  2497. end;
  2498. //[procedure TAction.LinkControl]
  2499. procedure TAction.LinkControl(Ctrl: PControl);
  2500. begin
  2501. LinkCtrl(Ctrl, ckControl, 0, UpdateCtrl);
  2502. Ctrl.OnClick:=DoOnControlClick;
  2503. end;
  2504. //[procedure TAction.LinkMenuItem]
  2505. procedure TAction.LinkMenuItem(Menu: PMenu; MenuItemIdx: integer);
  2506. {$IFDEF _FPC}
  2507. var
  2508. arr1_DoOnMenuItem: array[ 0..0 ] of TOnMenuItem;
  2509. {$ENDIF _FPC}
  2510. begin
  2511. LinkCtrl(Menu, ckMenu, MenuItemIdx, UpdateMenu);
  2512. {$IFDEF _FPC}
  2513. arr1_DoOnMenuItem[ 0 ] := DoOnMenuItem;
  2514. Menu.AssignEvents(MenuItemIdx, arr1_DoOnMenuItem);
  2515. {$ELSE}
  2516. Menu.AssignEvents(MenuItemIdx, [ DoOnMenuItem ]);
  2517. {$ENDIF}
  2518. end;
  2519. //[procedure TAction.LinkToolbarButton]
  2520. procedure TAction.LinkToolbarButton(Toolbar: PControl; ButtonIdx: integer);
  2521. {$IFDEF _FPC}
  2522. var
  2523. arr1_DoOnToolbarButtonClick: array[ 0..0 ] of TOnToolbarButtonClick;
  2524. {$ENDIF _FPC}
  2525. begin
  2526. LinkCtrl(Toolbar, ckToolbar, ButtonIdx, UpdateToolbar);
  2527. {$IFDEF _FPC}
  2528. arr1_DoOnToolbarButtonClick[ 0 ] := DoOnToolbarButtonClick;
  2529. Toolbar.TBAssignEvents(ButtonIdx, arr1_DoOnToolbarButtonClick);
  2530. {$ELSE}
  2531. Toolbar.TBAssignEvents(ButtonIdx, [DoOnToolbarButtonClick]);
  2532. {$ENDIF}
  2533. end;
  2534. //[destructor TAction.Destroy]
  2535. destructor TAction.Destroy;
  2536. begin
  2537. FControls.Release;
  2538. FCaption:='';
  2539. {$ifndef wince}
  2540. FShortCut:='';
  2541. {$endif wince}
  2542. FHint:='';
  2543. inherited;
  2544. end;
  2545. //[procedure TAction.DoOnControlClick]
  2546. procedure TAction.DoOnControlClick(Sender: PObj);
  2547. begin
  2548. Execute;
  2549. end;
  2550. //[procedure TAction.DoOnMenuItem]
  2551. procedure TAction.DoOnMenuItem(Sender: PMenu; Item: Integer);
  2552. begin
  2553. Execute;
  2554. end;
  2555. //[procedure TAction.DoOnToolbarButtonClick]
  2556. procedure TAction.DoOnToolbarButtonClick(Sender: PControl; BtnID: Integer);
  2557. begin
  2558. Execute;
  2559. end;
  2560. //[procedure TAction.Execute]
  2561. procedure TAction.Execute;
  2562. begin
  2563. if Assigned(FOnExecute) and FEnabled then
  2564. FOnExecute(PObj( @Self ));
  2565. end;
  2566. //[procedure TAction.SetCaption]
  2567. procedure TAction.SetCaption(const Value: KOLstring);
  2568. begin
  2569. if Caption = Value then exit;
  2570. FCaption:=Value;
  2571. Include(FUpdateMask, upCaption);
  2572. UpdateControls;
  2573. end;
  2574. //[procedure TAction.SetChecked]
  2575. procedure TAction.SetChecked(const Value: boolean);
  2576. begin
  2577. if FChecked = Value then exit;
  2578. FChecked := Value;
  2579. Include(FUpdateMask, upChecked);
  2580. UpdateControls;
  2581. end;
  2582. //[procedure TAction.SetEnabled]
  2583. procedure TAction.SetEnabled(const Value: boolean);
  2584. begin
  2585. if FEnabled = Value then exit;
  2586. FEnabled := Value;
  2587. Include(FUpdateMask, upEnabled);
  2588. UpdateControls;
  2589. end;
  2590. //[procedure TAction.SetHelpContext]
  2591. procedure TAction.SetHelpContext(const Value: integer);
  2592. begin
  2593. if FHelpContext = Value then exit;
  2594. FHelpContext := Value;
  2595. Include(FUpdateMask, upHelpContext);
  2596. UpdateControls;
  2597. end;
  2598. //[procedure TAction.SetHint]
  2599. procedure TAction.SetHint(const Value: KOLString);
  2600. begin
  2601. if FHint = Value then exit;
  2602. FHint := Value;
  2603. Include(FUpdateMask, upHint);
  2604. UpdateControls;
  2605. end;
  2606. //[procedure TAction.SetOnExecute]
  2607. procedure TAction.SetOnExecute(const Value: TOnEvent);
  2608. begin
  2609. if @FOnExecute = @Value then exit;
  2610. FOnExecute:=Value;
  2611. UpdateControls;
  2612. end;
  2613. //[procedure TAction.SetVisible]
  2614. procedure TAction.SetVisible(const Value: boolean);
  2615. begin
  2616. if FVisible = Value then exit;
  2617. FVisible := Value;
  2618. Include(FUpdateMask, upVisible);
  2619. UpdateControls;
  2620. end;
  2621. //[procedure TAction.UpdateControls]
  2622. procedure TAction.UpdateControls;
  2623. var
  2624. i: integer;
  2625. begin
  2626. if FUpdateMask = [] then exit;
  2627. with FControls{-}^{+} do
  2628. for i:=0 to Count - 1 do
  2629. PControlRec(Items[i]).UpdateProc(Items[i]);
  2630. FUpdateMask:=[];
  2631. end;
  2632. //[procedure TAction.UpdateCtrl]
  2633. procedure TAction.UpdateCtrl(Sender: PControlRec);
  2634. begin
  2635. with Sender^, PControl(Ctrl){-}^{+} do begin
  2636. if upCaption in FUpdateMask then
  2637. Caption:=Self.FCaption;
  2638. if upEnabled in FUpdateMask then
  2639. Enabled:=Self.FEnabled;
  2640. if upChecked in FUpdateMask then
  2641. Checked:=Self.FChecked;
  2642. if upVisible in FUpdateMask then
  2643. Visible:=Self.FVisible;
  2644. end;
  2645. end;
  2646. //[procedure TAction.UpdateMenu]
  2647. procedure TAction.UpdateMenu(Sender: PControlRec);
  2648. var
  2649. s: KOLstring;
  2650. begin
  2651. with Sender^, PMenu(Ctrl).Items[ItemID]{-}^{+} do begin
  2652. s:=Self.FCaption;
  2653. {$ifndef wince}
  2654. if Self.FShortCut <> '' then
  2655. s:=s + #9 + Self.FShortCut;
  2656. {$endif wince}
  2657. if upCaption in FUpdateMask then
  2658. Caption:=s;
  2659. if upEnabled in FUpdateMask then
  2660. Enabled:=Self.FEnabled;
  2661. if upChecked in FUpdateMask then
  2662. Checked:=Self.FChecked;
  2663. if upVisible in FUpdateMask then
  2664. Visible:=Self.FVisible;
  2665. if upHelpContext in FUpdateMask then
  2666. HelpContext:=Self.FHelpContext;
  2667. if (upAccelerator in FUpdateMask) and (Self.FAccelerator.Key <> 0) then {YS} // Äîáàâèòü
  2668. Accelerator:=Self.FAccelerator;
  2669. end;
  2670. end;
  2671. //[procedure TAction.UpdateToolbar]
  2672. procedure TAction.UpdateToolbar(Sender: PControlRec);
  2673. var
  2674. i: integer;
  2675. s: KOLString;
  2676. begin
  2677. with Sender^, PControl(Ctrl){-}^{+} do begin
  2678. i:=TBIndex2Item(ItemID);
  2679. s:=TBButtonText[i];
  2680. if (s <> '') and (upCaption in FUpdateMask) then
  2681. TBButtonText[i]:=Self.FCaption;
  2682. if upHint in FUpdateMask then
  2683. TBSetTooltips(i, [PKOLChar(Self.FHint)]);
  2684. if upEnabled in FUpdateMask then
  2685. TBButtonEnabled[ItemID]:=Self.FEnabled;
  2686. if upVisible in FUpdateMask then
  2687. TBButtonVisible[ItemID]:=Self.FVisible;
  2688. if upChecked in FUpdateMask then
  2689. TBButtonChecked[ItemID]:=Self.FChecked;
  2690. end;
  2691. end;
  2692. //[procedure TAction.SetAccelerator]
  2693. procedure TAction.SetAccelerator(const Value: TMenuAccelerator);
  2694. begin
  2695. if (FAccelerator.fVirt = Value.fVirt) and (FAccelerator.Key = Value.Key) then exit;
  2696. FAccelerator := Value;
  2697. {$ifndef wince}
  2698. Include(FUpdateMask, upAccelerator);
  2699. FShortCut:=GetAcceleratorText(FAccelerator); // {YS}
  2700. UpdateControls;
  2701. {$endif wince}
  2702. end;
  2703. { TActionList }
  2704. //[function TActionList.Add]
  2705. function TActionList.Add(const ACaption, AHint: KOLstring; OnExecute: TOnEvent): PAction;
  2706. begin
  2707. Result:=NewAction(ACaption, AHint, OnExecute);
  2708. FActions.Add(Result);
  2709. end;
  2710. //[procedure TActionList.Clear]
  2711. procedure TActionList.Clear;
  2712. begin
  2713. while FActions.Count > 0 do
  2714. Delete(0);
  2715. FActions.Clear;
  2716. end;
  2717. //[procedure TActionList.Delete]
  2718. procedure TActionList.Delete(Idx: integer);
  2719. begin
  2720. Actions[Idx].Free;
  2721. FActions.Delete(Idx);
  2722. end;
  2723. //[destructor TActionList.Destroy]
  2724. destructor TActionList.Destroy;
  2725. begin
  2726. {$ifdef USE_OnIdle}
  2727. UnRegisterIdleHandler(DoUpdateActions);
  2728. {$endif USE_OnIdle}
  2729. Clear;
  2730. FActions.Free;
  2731. inherited;
  2732. end;
  2733. //[procedure TActionList.DoUpdateActions]
  2734. procedure TActionList.DoUpdateActions(Sender: PObj);
  2735. begin
  2736. if Assigned(FOnUpdateActions) and (GetActiveWindow = FOwner.Handle) then
  2737. FOnUpdateActions(PObj( @Self ));
  2738. end;
  2739. //[function TActionList.GetActions]
  2740. function TActionList.GetActions(Idx: integer): PAction;
  2741. begin
  2742. Result:=FActions.Items[Idx];
  2743. end;
  2744. //[function TActionList.GetCount]
  2745. function TActionList.GetCount: integer;
  2746. begin
  2747. Result:=FActions.Count;
  2748. end;
  2749. { -- TTree -- }
  2750. {$IFDEF USE_CONSTRUCTORS}
  2751. //[function NewTree]
  2752. function NewTree( AParent: PTree; const AName: String ): PTree;
  2753. begin
  2754. New( Result, CreateTree( AParent, AName ) );
  2755. end;
  2756. //[END NewTree]
  2757. {$ELSE not_USE_CONSTRUCTORS}
  2758. //[function NewTree]
  2759. {$IFDEF TREE_NONAME}
  2760. function NewTree( AParent: PTree ): PTree;
  2761. begin
  2762. {-}
  2763. New( Result, Create );
  2764. {+}{++}(*Result := PTree.Create;*){--}
  2765. if AParent <> nil then
  2766. AParent.Add( Result );
  2767. Result.fParent := AParent;
  2768. end;
  2769. {$ELSE}
  2770. {$IFDEF TREE_WIDE}
  2771. function NewTree( AParent: PTree; const AName: WideString ): PTree;
  2772. begin
  2773. {-}
  2774. New( Result, Create );
  2775. {+}{++}(*Result := PTree.Create;*){--}
  2776. if AParent <> nil then
  2777. AParent.Add( Result );
  2778. Result.fParent := AParent;
  2779. Result.fNodeName := AName;
  2780. end;
  2781. {$ELSE}
  2782. function NewTree( AParent: PTree; const AName: String ): PTree;
  2783. begin
  2784. {-}
  2785. New( Result, Create );
  2786. {+}{++}(*Result := PTree.Create;*){--}
  2787. if AParent <> nil then
  2788. AParent.Add( Result );
  2789. Result.fParent := AParent;
  2790. Result.fNodeName := AName;
  2791. end;
  2792. {$ENDIF}
  2793. {$ENDIF}
  2794. //[END NewTree]
  2795. {$ENDIF USE_CONSTRUCTORS}
  2796. { TTree }
  2797. //[procedure TTree.Add]
  2798. procedure TTree.Add(Node: PTree);
  2799. var Previous: PTree;
  2800. begin
  2801. Node.Unlink;
  2802. if fChildren = nil then
  2803. fChildren := NewList;
  2804. Previous := nil;
  2805. if PCrackList( fChildren ).fCount > 0 then
  2806. Previous := PCrackList( fChildren ).fItems[ PCrackList( fChildren ).fCount - 1 ];
  2807. if Previous <> nil then
  2808. begin
  2809. Previous.fNext := Node;
  2810. Node.fPrev := Previous;
  2811. end;
  2812. fChildren.Add( Node );
  2813. Node.fParent := @Self;
  2814. end;
  2815. //[procedure TTree.Clear]
  2816. procedure TTree.Clear;
  2817. var I: Integer;
  2818. begin
  2819. if fChildren = nil then Exit;
  2820. for I := PCrackList( fChildren ).fCount - 1 downto 0 do
  2821. PTree( PCrackList( fChildren ).fItems[ I ] ).Free;
  2822. end;
  2823. {$IFDEF USE_CONSTRUCTORS}
  2824. //[constructor TTree.CreateTree]
  2825. constructor TTree.CreateTree(AParent: PTree; const AName: String);
  2826. begin
  2827. inherited Create;
  2828. if AParent <> nil then
  2829. AParent.Add( @Self );
  2830. fParent := AParent;
  2831. fName := AName;
  2832. end;
  2833. {$ENDIF}
  2834. //[destructor TTree.Destroy]
  2835. destructor TTree.Destroy;
  2836. begin
  2837. Unlink;
  2838. Clear;
  2839. {$IFDEF TREE_NONAME}
  2840. {$ELSE}
  2841. fNodeName := '';
  2842. {$ENDIF}
  2843. inherited;
  2844. end;
  2845. //[function TTree.GetCount]
  2846. function TTree.GetCount: Integer;
  2847. begin
  2848. Result := 0;
  2849. if fChildren = nil then Exit;
  2850. Result := PCrackList( fChildren ).fCount;
  2851. end;
  2852. //[function TTree.GetIndexAmongSiblings]
  2853. function TTree.GetIndexAmongSiblings: Integer;
  2854. begin
  2855. Result := -1;
  2856. if fParent = nil then Exit;
  2857. Result := fParent.fChildren.IndexOf( @Self );
  2858. end;
  2859. //[function TTree.GetItems]
  2860. function TTree.GetItems(Idx: Integer): PTree;
  2861. begin
  2862. Result := nil;
  2863. if fChildren = nil then Exit;
  2864. Result := fChildren.Items[ Idx ];
  2865. end;
  2866. //[function TTree.GetLevel]
  2867. function TTree.GetLevel: Integer;
  2868. var Node: PTree;
  2869. begin
  2870. Result := 0;
  2871. Node := fParent;
  2872. while Node <> nil do
  2873. begin
  2874. Inc( Result );
  2875. Node := Node.fParent;
  2876. end;
  2877. end;
  2878. //[function TTree.GetRoot]
  2879. function TTree.GetRoot: PTree;
  2880. begin
  2881. Result := @Self;
  2882. while Result.fParent <> nil do
  2883. Result := Result.fParent;
  2884. end;
  2885. //[function TTree.GetTotal]
  2886. function TTree.GetTotal: Integer;
  2887. var I: Integer;
  2888. begin
  2889. Result := Count;
  2890. if Result <> 0 then
  2891. begin
  2892. for I := 0 to Count - 1 do
  2893. Result := Result + Items[ I ].Total;
  2894. end;
  2895. end;
  2896. //[procedure TTree.Init]
  2897. procedure TTree.Init;
  2898. begin
  2899. if FParent <> nil then
  2900. FParent.Add( @Self );
  2901. end;
  2902. //[procedure TTree.Insert]
  2903. procedure TTree.Insert(Before, Node: PTree);
  2904. var Previous: PTree;
  2905. begin
  2906. Node.Unlink;
  2907. if fChildren = nil then
  2908. fChildren := NewList;
  2909. Previous := nil;
  2910. if Before <> nil then
  2911. Previous := Before.fPrev;
  2912. if Previous <> nil then
  2913. begin
  2914. Previous.fNext := Node;
  2915. Node.fPrev := Previous;
  2916. end;
  2917. if Before <> nil then
  2918. begin
  2919. Node.fNext := Before;
  2920. Before.fPrev := Node;
  2921. fChildren.Insert( fChildren.IndexOf( Before ), Node );
  2922. end
  2923. else
  2924. fChildren.Add( Node );
  2925. Node.fParent := @Self;
  2926. end;
  2927. //[function CompareTreeNodes]
  2928. function CompareTreeNodes( const Data: Pointer; const e1, e2: DWORD ): Integer;
  2929. var List: PList;
  2930. begin
  2931. List := Data;
  2932. {$IFDEF TREE_NONAME}
  2933. Result := DWORD( PTree( PCrackList( List ).fItems[ e1 ] ).fData ) -
  2934. DWORD( PTree( PCrackList( List ).fItems[ e2 ] ).fData );
  2935. {$ELSE}
  2936. Result := AnsiCompareStr( PTree( PCrackList( List ).fItems[ e1 ] ).fNodeName,
  2937. PTree( PCrackList( List ).fItems[ e2 ] ).fNodeName );
  2938. {$ENDIF}
  2939. end;
  2940. //[procedure SwapTreeNodes]
  2941. procedure SwapTreeNodes( const Data: Pointer; const e1, e2: DWORD );
  2942. var List: PList;
  2943. begin
  2944. List := Data;
  2945. List.Swap( e1, e2 );
  2946. end;
  2947. //[procedure TTree.SwapNodes]
  2948. procedure TTree.SwapNodes( i1, i2: Integer );
  2949. begin
  2950. fChildren.Swap( i1, i2 );
  2951. end;
  2952. //[procedure TTree.SortByName]
  2953. procedure TTree.SortByName;
  2954. begin
  2955. if Count <= 1 then Exit;
  2956. SortData( fChildren, PCrackList( fChildren ).fCount, CompareTreeNodes, SwapTreeNodes );
  2957. end;
  2958. //[procedure TTree.Unlink]
  2959. procedure TTree.Unlink;
  2960. var I: Integer;
  2961. begin
  2962. if fPrev <> nil then
  2963. fPrev.fNext := fNext;
  2964. if fNext <> nil then
  2965. fNext.fPrev := fPrev;
  2966. if (fParent <> nil) then
  2967. begin
  2968. I := fParent.fChildren.IndexOf( @Self );
  2969. fParent.fChildren.Delete( I );
  2970. if PCrackList( fParent.fChildren ).fCount = 0 then
  2971. begin
  2972. fParent.fChildren.Free;
  2973. fParent.fChildren := nil;
  2974. end;
  2975. end;
  2976. fPrev := nil;
  2977. fNext := nil;
  2978. fParent := nil;
  2979. end;
  2980. //[function TTree.IsParentOfNode]
  2981. function TTree.IsParentOfNode(Node: PTree): Boolean;
  2982. begin
  2983. Result := TRUE;
  2984. while Node <> nil do
  2985. begin
  2986. if Node = @ Self then Exit;
  2987. Node := Node.Parent;
  2988. end;
  2989. Result := FALSE;
  2990. end;
  2991. //[function TTree.IndexOf]
  2992. function TTree.IndexOf(Node: PTree): Integer;
  2993. begin
  2994. Result := -1;
  2995. if not IsParentOfNode( Node ) then Exit;
  2996. while Node <> @ Self do
  2997. begin
  2998. Inc( Result );
  2999. while Node.PrevSibling <> nil do
  3000. begin
  3001. Node := Node.PrevSibling;
  3002. Inc( Result, 1 + Node.Total );
  3003. end;
  3004. Node := Node.Parent;
  3005. end;
  3006. end;
  3007. {-------------------------------------------------------------------------------
  3008. ADDITIONAL UTILITIES
  3009. }
  3010. function MapFileRead( const Filename: String; var hFile, hMap: THandle ): Pointer;
  3011. var Sz, Hi: DWORD;
  3012. begin
  3013. Result := nil;
  3014. hFile := FileCreate( Filename, ofOpenRead or ofOpenExisting or ofShareDenyNone );
  3015. hMap := 0;
  3016. if hFile = INVALID_HANDLE_VALUE then Exit;
  3017. Sz := GetFileSize( hFile, @ Hi );
  3018. hMap := CreateFileMapping( hFile, nil, PAGE_READONLY, Hi, Sz, nil );
  3019. if hMap = 0 then Exit;
  3020. if (Hi <> 0) or (Sz > $0FFFFFFF) then Sz := $0FFFFFFF;
  3021. Result := MapViewOfFile( hMap, FILE_MAP_READ, 0, 0, Sz );
  3022. end;
  3023. function MapFile( const Filename: String; var hFile, hMap: THandle ): Pointer;
  3024. var Sz, Hi: DWORD;
  3025. begin
  3026. Result := nil;
  3027. hFile := FileCreate( Filename, ofOpenRead or ofOpenWrite or ofOpenExisting
  3028. or ofShareExclusive );
  3029. hMap := 0;
  3030. if hFile = INVALID_HANDLE_VALUE then Exit;
  3031. Sz := GetFileSize( hFile, @ Hi );
  3032. hMap := CreateFileMapping( hFile, nil, PAGE_READWRITE, Hi, Sz, nil );
  3033. if hMap = 0 then Exit;
  3034. if (Hi <> 0) or (Sz > $0FFFFFFF) then Sz := $0FFFFFFF;
  3035. Result := MapViewOfFile( hMap, FILE_MAP_READ, 0, 0, Sz );
  3036. end;
  3037. procedure UnmapFile( BasePtr: Pointer; hFile, hMap: THandle );
  3038. begin
  3039. if BasePtr <> nil then
  3040. UnmapViewOfFile( BasePtr );
  3041. if hMap <> 0 then
  3042. CloseHandle( hMap );
  3043. if hFile <> INVALID_HANDLE_VALUE then
  3044. CloseHandle( hFile );
  3045. end;
  3046. //[procedure CloseMsg]
  3047. procedure CloseMsg( Dummy, Dialog: PControl; var Accept: Boolean );
  3048. begin
  3049. Accept := FALSE;
  3050. Dialog.ModalResult := -1;
  3051. end;
  3052. //[END CloseMsg]
  3053. //[procedure OKClick]
  3054. procedure OKClick( Dialog, Btn: PControl );
  3055. var Rslt: Integer;
  3056. begin
  3057. Rslt := -1;
  3058. if Btn <> nil then
  3059. Rslt := Btn.Tag;
  3060. Dialog.ModalResult := Rslt;
  3061. Dialog.Close;
  3062. end;
  3063. //[END OKClick]
  3064. //[procedure KeyClick]
  3065. procedure KeyClick( Dialog, Btn: PControl; var Key: Longint; Shift: DWORD );
  3066. begin
  3067. if (Key = VK_RETURN) or (Key = VK_ESCAPE) then
  3068. begin
  3069. if Key = VK_ESCAPE then
  3070. Btn := nil;
  3071. OKClick( Dialog, Btn );
  3072. end;
  3073. end;
  3074. //[END KeyClick]
  3075. //[function ShowQuestionEx]
  3076. function ShowQuestionEx( S: KOLString; Answers: KOLString; CallBack: TOnEvent ): Integer;
  3077. {$IFDEF F_P105ORBELOW}
  3078. type POnEvent = ^TOnEvent;
  3079. PONKey = ^TOnKey;
  3080. var M: TMethod;
  3081. {$ENDIF F_P105ORBELOW}
  3082. var Dialog: PControl;
  3083. DlgPrnt: PControl;
  3084. Buttons: PList;
  3085. Btn: PControl;
  3086. AppTermFlag: Boolean;
  3087. Lab: PControl;
  3088. {$IFNDEF USE_GRUSH} Y, {$ELSE} {$IFDEF TOGRUSH_OPTIONAL} Y, {$ENDIF} {$ENDIF} W, X, I: Integer;
  3089. Title: String;
  3090. DlgWnd: HWnd;
  3091. AppCtl: PControl;
  3092. {$IFDEF USE_GRUSH}
  3093. Sz: TSize;
  3094. H: Integer;
  3095. Bmp: PBitmap;
  3096. {$ENDIF}
  3097. {$IFNDEF NO_CHECK_STAYONTOP}
  3098. CurForm: PControl;
  3099. DoStayOnTop: Boolean;
  3100. {$ENDIF}
  3101. begin
  3102. AppTermFlag := AppletTerminated;
  3103. AppCtl := Applet;
  3104. AppletTerminated := FALSE;
  3105. Title := 'Information';
  3106. if pos( '/', Answers ) > 0 then
  3107. Title := 'Question';
  3108. {$IFNDEF NO_CHECK_STAYONTOP}
  3109. DoStayOnTop := FALSE;
  3110. {$ENDIF NO_CHECK_STAYONTOP}
  3111. if Applet <> nil then
  3112. begin
  3113. Title := Applet.Caption;
  3114. {$IFNDEF NO_CHECK_STAYONTOP}
  3115. CurForm := Applet.ActiveControl;
  3116. DoStayOnTop := CurForm.StayOnTop;
  3117. {$ENDIF NO_CHECK_STAYONTOP}
  3118. end;
  3119. {$IFNDEF NOT_ALLOW_EXTRACT_TITLE}
  3120. if (Length( S ) > 2) and (S[ 1 ] = '!') then
  3121. begin
  3122. Delete( S, 1, 1 );
  3123. if S[ 1 ] = '!' then Delete( S, 1, 1 )
  3124. else Title := Parse( S, '!' );
  3125. end;
  3126. {$ENDIF}
  3127. Dialog := NewForm( Applet, Title ).SetSize( 300, 40 );
  3128. {$IFNDEF NO_CHECK_STAYONTOP}
  3129. if DoStayOnTop then
  3130. Dialog.StayOnTop := TRUE;
  3131. {$ENDIF NO_CHECK_STAYONTOP}
  3132. Dialog.Style := Dialog.Style and not (WS_MINIMIZEBOX or WS_MAXIMIZEBOX);
  3133. Dialog.OnClose := TOnEventAccept( MakeMethod( Dialog, @CloseMsg ) );
  3134. {$IFDEF USE_GRUSH}
  3135. Bmp := NewBitmap( 1, 1 );
  3136. {$IFDEF TOGRUSH_OPTIONAL}
  3137. if not NoGrush then
  3138. {$ENDIF TOGRUSH_OPTIONAL}
  3139. begin
  3140. Dialog.Color := clGRushLight;
  3141. Dialog.Font.FontName := 'Arial';
  3142. Dialog.Font.FontHeight := 16;
  3143. DlgPrnt := NewPanel( Dialog, esNone ); //.SetAlign( caClient );
  3144. end
  3145. {$IFDEF TOGRUSH_OPTIONAL}
  3146. else
  3147. DlgPrnt := Dialog;
  3148. {$ENDIF TOGRUSH_OPTIONAL}
  3149. ;
  3150. {$ELSE}
  3151. DlgPrnt := Dialog;
  3152. {$ENDIF USE_GRUSH}
  3153. DlgPrnt.Margin := 8;
  3154. {$IFDEF USE_GRUSH}
  3155. {$IFDEF TOGRUSH_OPTIONAL}
  3156. if not NoGrush then
  3157. {$ENDIF TOGRUSH_OPTIONAL}
  3158. begin
  3159. Lab := NewWordWrapLabel( DlgPrnt, S ).SetSize( 278, 20 );
  3160. Lab.AutoSize( TRUE );
  3161. Lab.Transparent := TRUE;
  3162. end
  3163. {$IFDEF TOGRUSH_OPTIONAL}
  3164. else
  3165. begin
  3166. Lab := NewEditbox( DlgPrnt, [ eoMultiline, eoReadonly, eoNoHScroll, eoNoVScroll ] ).SetSize( 278, 20 );
  3167. Lab.HasBorder := FALSE;
  3168. Lab.Color := clBtnFace;
  3169. Lab.Caption := S;
  3170. Lab.Style := Lab.Style and not WS_TABSTOP;
  3171. Lab.TabStop := FALSE;
  3172. while TRUE do
  3173. begin
  3174. Y := HiWord( Lab.Perform( EM_POSFROMCHAR, Length( S ) - 1, 0 ) );
  3175. if Y < Lab.Height - 20 then break;
  3176. Lab.Height := Lab.Height + 4;
  3177. if Lab.Height + 40 > GetSystemMetrics( SM_CYSCREEN ) then break;
  3178. end;
  3179. end
  3180. {$ENDIF TOGRUSH_OPTIONAL}
  3181. ;
  3182. {$ELSE}
  3183. Lab := NewEditbox( DlgPrnt, [ eoMultiline, eoReadonly, eoNoHScroll, eoNoVScroll ] ).SetSize( 278, 20 );
  3184. Lab.HasBorder := FALSE;
  3185. Lab.Color := clBtnFace;
  3186. Lab.Caption := S;
  3187. Lab.Style := Lab.Style and not WS_TABSTOP;
  3188. Lab.TabStop := FALSE;
  3189. //Lab.CreateWindow; //virtual!!! -- not needed, window created in Perform
  3190. while TRUE do
  3191. begin
  3192. Y := HiWord( Lab.Perform( EM_POSFROMCHAR, Length( S ) - 1, 0 ) );
  3193. if Y < Lab.Height - 20 then break;
  3194. Lab.Height := Lab.Height + 4;
  3195. if Lab.Height + 40 > GetSystemMetrics( SM_CYSCREEN ) then break;
  3196. end;
  3197. //Lab.LikeSpeedButton;
  3198. {$ENDIF USE_GRUSH}
  3199. Buttons := NewList;
  3200. W := 0;
  3201. {$IFDEF USE_GRUSH}
  3202. H := 0;
  3203. {$ENDIF}
  3204. if Answers = '' then
  3205. begin
  3206. Btn := NewButton( DlgPrnt, ' OK ' ).PlaceUnder;
  3207. {$IFDEF USE_GRUSH}
  3208. {$IFDEF TOGRUSH_OPTIONAL}
  3209. if not NoGrush then
  3210. {$ENDIF TOGRUSH_OPTIONAL}
  3211. begin
  3212. Sz := Bmp.Canvas.TextExtent( Btn.Caption );
  3213. if H = 0 then H := Sz.cy + 8;
  3214. Btn.SetSize( Sz.cx + 16, H );
  3215. end;
  3216. {$ENDIF}
  3217. W := Btn.BoundsRect.Right;
  3218. Buttons.Add( Btn );
  3219. end
  3220. else
  3221. while Answers <> '' do
  3222. begin
  3223. Btn := NewButton( DlgPrnt, ' ' + Parse( Answers, '/' ) + ' ' );
  3224. Buttons.Add( Btn );
  3225. if W = 0 then
  3226. Btn.PlaceUnder
  3227. else
  3228. Btn.PlaceRight;
  3229. {$IFDEF USE_GRUSH}
  3230. {$IFDEF TOGRUSH_OPTIONAL}
  3231. if not NoGrush then
  3232. {$ENDIF TOGRUSH_OPTIONAL}
  3233. begin
  3234. Sz := Bmp.Canvas.TextExtent( Btn.Caption );
  3235. if H = 0 then H := Sz.cy + 8;
  3236. Btn.SetSize( Sz.cx + 16, H );
  3237. end
  3238. {$IFDEF TOGRUSH_OPTIONAL}
  3239. else Btn.AutoSize( TRUE )
  3240. {$ENDIF TOGRUSH_OPTIONAL}
  3241. ;
  3242. {$ELSE}
  3243. Btn.AutoSize( TRUE );
  3244. {$ENDIF USE_GRUSH}
  3245. if W > 0 then
  3246. begin
  3247. //Inc( W, 6 );
  3248. Btn.Left := Btn.Left + 6;
  3249. end;
  3250. W := Btn.BoundsRect.Right;
  3251. end;
  3252. DlgPrnt.Width := Max( Max( DlgPrnt.Width, Lab.Left + Lab.Width + 4 ), W + 8 );
  3253. X := (DlgPrnt.ClientWidth - W) div 2;
  3254. for I := 0 to Buttons.Count-1 do
  3255. begin
  3256. Btn := Buttons.Items[ I ];
  3257. Btn.Tag := I + 1;
  3258. {$IFDEF F_P105ORBELOW}
  3259. M := MakeMethod( Dialog, @OKClick );
  3260. Btn.OnClick := POnEvent( @ M )^;
  3261. M := MakeMethod( Dialog, @KeyClick );
  3262. Btn.OnKeyDown := POnKey( @ M )^;
  3263. {$ELSE}
  3264. Btn.OnClick := TOnEvent( MakeMethod( Dialog, @OKClick ) );
  3265. Btn.OnKeyDown := TOnKey( MakeMethod( Dialog, @KeyClick ) );
  3266. {$ENDIF}
  3267. Btn.Left := Btn.Left + X;
  3268. if I = 0 then
  3269. begin
  3270. Btn.ResizeParentBottom;
  3271. Dialog.ActiveControl := Btn;
  3272. end;
  3273. end;
  3274. {$IFDEF USE_GRUSH}
  3275. {$IFDEF TOGRUSH_OPTIONAL}
  3276. if not NoGrush then
  3277. {$ENDIF TOGRUSH_OPTIONAL}
  3278. begin
  3279. DlgPrnt.ResizeParent;
  3280. end;
  3281. Bmp.Free;
  3282. {$ENDIF USE_GRUSH}
  3283. Dialog.CenterOnParent.Tabulate.CanResize := FALSE;
  3284. Buttons.Free;
  3285. if Assigned( CallBack ) then
  3286. CallBack( Dialog );
  3287. Dialog.CreateWindow; // virtual!!!
  3288. if (Applet <> nil) and Applet.IsApplet then
  3289. begin
  3290. Dialog.ShowModal;
  3291. Result := Dialog.ModalResult;
  3292. Dialog.Free;
  3293. end
  3294. else
  3295. begin
  3296. DlgWnd := Dialog.Handle;
  3297. while IsWindow( DlgWnd ) and (Dialog.ModalResult = 0) do
  3298. Dialog.ProcessMessage;
  3299. Result := Dialog.ModalResult;
  3300. Dialog.Free;
  3301. CreatingWindow := nil;
  3302. Applet := AppCtl;
  3303. end;
  3304. AppletTerminated := AppTermFlag;
  3305. end;
  3306. //[END ShowQuestionEx]
  3307. //[function ShowQuestion]
  3308. function ShowQuestion( const S: String; Answers: String ): Integer;
  3309. begin
  3310. Result := ShowQuestionEx( S, Answers, nil );
  3311. end;
  3312. //[END ShowQuestion]
  3313. //[procedure ShowMsgModal]
  3314. procedure ShowMsgModal( const S: String );
  3315. begin
  3316. ShowQuestion( S, '' );
  3317. end;
  3318. //[END ShowMsgModal]
  3319. end.