2 This file is part of the Free Pascal run time library.
4 A file in Amiga system run time library.
5 Copyright (c) 1998 by Nils Sjoholm
6 member of the Amiga RTL development team.
8 See the file COPYING.FPC, included in this distribution,
9 for details about the copyright.
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
15 **********************************************************************}
24 pClockData
= ^tClockData
;
38 h_Entry
: Pointer; { assembler entry point }
39 h_SubEntry
: Pointer; { often HLL entry point }
40 h_Data
: Pointer; { owner specific }
44 * Hook calling conventions:
45 * A0 - pointer to hook data structure itself
46 * A1 - pointer to parameter structure ("message") typically
47 * beginning with a longword command code, which makes
48 * sense in the context in which the hook is being used.
49 * A2 - Hook specific address data ("object," e.g, GadgetInfo)
51 * Control will be passed to the routine h_Entry. For many
52 * High-Level Languages (HLL), this will be an assembly language
53 * stub which pushes registers on the stack, does other setup,
54 * and then calls the function at h_SubEntry.
56 * The C standard receiving code is:
57 * CDispatcher( hook, object, message )
62 * NOTE that register natural order differs from this convention
63 * for C parameter order, which is A0,A2,A1.
65 * The assembly language stub for "vanilla" C parameter conventions
69 move.l a1,-(sp) ; push message packet pointer
70 move.l a2,-(sp) ; push object pointer
71 move.l a0,-(sp) ; push hook pointer
72 move.l h_SubEntry(a0),a0 ; fetch C entry point ...
73 jsr (a0) ; ... and call it
74 lea 12(sp),sp ; fix stack
77 * with this function as your interface stub, you can write
78 * a Hook setup function as:
80 SetupHook( hook, c_function, userdata )
82 ULONG (*c_function)();
87 hook->h_Entry = hookEntry;
88 hook->h_SubEntry = c_function;
89 hook->h_Data = userdata;
92 * with Lattice C pragmas, you can put the C function in the
93 * h_Entry field directly if you declare the function:
96 CDispatcher( register __a0 struct Hook *hook,
97 register __a2 VOID *object,
98 register __a1 ULONG *message );
102 { Namespace definitions }
106 { The named object structure }
107 pNamedObject
= ^tNamedObject
;
108 tNamedObject
= record
109 no_Object
: Pointer; { Your pointer, for whatever you want }
113 { Tags for AllocNamedObject() }
114 ANO_NameSpace
= 4000; { Tag to define namespace }
115 ANO_UserSpace
= 4001; { tag to define userspace }
116 ANO_Priority
= 4002; { tag to define priority }
117 ANO_Flags
= 4003; { tag to define flags }
119 { Flags for tag ANO_Flags }
123 NSF_NODUPS
= 1; { Default allow duplicates }
124 NSF_CASE
= 2; { Default to caseless... }
127 { Control attributes for Pack/UnpackStructureTags() }
130 { PackTable definition:
132 * The PackTable is a simple array of LONGWORDS that are evaluated by
133 * PackStructureTags() and UnpackStructureTags().
135 * The table contains compressed information such as the tag offset from
136 * the base tag. The tag offset has a limited range so the base tag is
137 * defined in the first longword.
139 * After the first longword, the fields look as follows:
141 * +--------- 1 = signed, 0 = unsigned (for bits, 1=inverted boolean)
143 * | +------ 00 = Pack/Unpack, 10 = Pack, 01 = Unpack, 11 = special
145 * | | | +-- 00 = Byte, 01 = Integer, 10 = Long, 11 = Bit
147 * | | | | | /----- For bit operations: 1 = TAG_EXISTS is TRUE
149 * | | | | | | /-------------------- Tag offset from base tag value
151 * m n n o o p q q q q q q q q q q r r r s s s s s s s s s s s s s
153 * Bit offset (for bit operations) ----/ | |
155 * Offset into data structure -----------------------------------/
157 * A -1 longword signifies that the next longword will be a new base tag
159 * A 0 longword signifies that it is the end of the pack table.
161 * What this implies is that there are only 13-bits of address offset
162 * and 10 bits for tag offsets from the base tag. For most uses this
163 * should be enough, but when this is not, either multiple pack tables
164 * or a pack table with extra base tags would be able to do the trick.
165 * The goal here was to make the tables small and yet flexible enough to
171 PSTB_UNPACK
=30; { Note that these are active low... }
172 PSTB_PACK
=29; { Note that these are active low... }
173 PSTB_EXISTS
=26; { Tag exists bit true flag hack... }
175 PSTF_SIGNED
= $80000000;
176 PSTF_UNPACK
= $40000000;
177 PSTF_PACK
= $20000000;
179 PSTF_EXISTS
= $4000000;
182 {***************************************************************************}
185 PKCTRL_PACKUNPACK
= $00000000;
186 PKCTRL_PACKONLY
= $40000000;
187 PKCTRL_UNPACKONLY
= $20000000;
189 PKCTRL_BYTE
= $80000000;
190 PKCTRL_WORD
= $88000000;
191 PKCTRL_LONG
= $90000000;
193 PKCTRL_UBYTE
= $00000000;
194 PKCTRL_UWORD
= $08000000;
195 PKCTRL_ULONG
= $10000000;
197 PKCTRL_BIT
= $18000000;
198 PKCTRL_FLIPBIT
= $98000000;
201 {***************************************************************************}
204 { Macros used by the next batch of macros below. Normally, you don't use
205 * this batch directly. Then again, some folks are wierd
210 {***************************************************************************}
213 { Some handy dandy macros to easily create pack tables
215 * Use PACK_STARTTABLE() at the start of a pack table. You pass it the
216 * base tag value that will be handled in the following chunk of the pack
219 * PACK_ENDTABLE() is used to mark the end of a pack table.
221 * PACK_NEWOFFSET() lets you change the base tag value used for subsequent
222 * entries in the table
224 * PACK_ENTRY() lets you define an entry in the pack table. You pass it the
225 * base tag value, the tag of interest, the type of the structure to use,
226 * the field name in the structure to affect and control bits (combinations of
227 * the various PKCTRL_XXX bits)
229 * PACK_BYTEBIT() lets you define a bit-control entry in the pack table. You
230 * pass it the same data as PACK_ENTRY, plus the flag bit pattern this tag
231 * affects. This macro should be used when the field being affected is byte
234 * PACK_WORDBIT() lets you define a bit-control entry in the pack table. You
235 * pass it the same data as PACK_ENTRY, plus the flag bit pattern this tag
236 * affects. This macro should be used when the field being affected is Integer
239 * PACK_LONGBIT() lets you define a bit-control entry in the pack table. You
240 * pass it the same data as PACK_ENTRY, plus the flag bit pattern this tag
241 * affects. This macro should be used when the field being affected is longword
246 * ULONG packTable[] =
248 * PACK_STARTTABLE(GA_Dummy),
249 * PACK_ENTRY(GA_Dummy,GA_Left,Gadget,LeftEdge,PKCTRL_WORD|PKCTRL_PACKUNPACK),
250 * PACK_ENTRY(GA_Dummy,GA_Top,Gadget,TopEdge,PKCTRL_WORD|PKCTRL_PACKUNPACK),
251 * PACK_ENTRY(GA_Dummy,GA_Width,Gadget,Width,PKCTRL_UWORD|PKCTRL_PACKUNPACK),
252 * PACK_ENTRY(GA_Dummy,GA_Height,Gadget,Height,PKCTRL_UWORD|PKCTRL_PACKUNPACK),
253 * PACK_WORDBIT(GA_Dummy,GA_RelVerify,Gadget,Activation,PKCTRL_BIT|PKCTRL_PACKUNPACK,GACT_RELVERIFY)
259 { ======================================================================= }
260 { ==== TagItem ========================================================== }
261 { ======================================================================= }
262 { This data type may propagate through the system for more general use.
263 * In the meantime, it is used as a general mechanism of extensible data
264 * arrays for parameter specification and property inquiry (coming soon
265 * to a display controller near you).
267 * In practice, an array (or chain of arrays) of TagItems is used.
273 pTagItem
= ^tTagItem
;
279 ppTagItem
= ^pTagItem
;
281 { ---- system tag values ----------------------------- }
283 TAG_DONE
= 0; { terminates array of TagItems. ti_Data unused }
285 TAG_IGNORE
= 1; { ignore this item, not END of array }
286 TAG_MORE
= 2; { ti_Data is pointer to another array of TagItems
287 * note that this tag terminates the current array
289 TAG_SKIP
= 3; { skip this AND the next ti_Data items }
291 { differentiates user tags from control tags }
292 TAG_USER
= $80000000; { differentiates user tags from system tags}
294 {* If the TAG_USER bit is set in a tag number, it tells utility.library that
295 * the tag is not a control tag (like TAG_DONE, TAG_IGNORE, TAG_MORE) and is
296 * instead an application tag. "USER" means a client of utility.library in
297 * general, including system code like Intuition or ASL, it has nothing to do
302 { Tag filter logic specifiers for use with FilterTagItems() }
303 TAGFILTER_AND
= 0; { exclude everything but filter hits }
304 TAGFILTER_NOT
= 1; { exclude only filter hits }
306 { Mapping types for use with MapTags() }
307 MAP_REMOVE_NOT_FOUND
= 0; { remove tags that aren't in mapList }
308 MAP_KEEP_NOT_FOUND
= 1; { keep tags that aren't in mapList }
313 tUtilityBase
= record
314 ub_LibNode
: tLibrary
;
319 function AddNamedObject(nameSpace
,
320 obj
: pNamedObject
) : Boolean;
321 function AllocateTagItems(num
: ULONG
) : pTagItem
;
322 function AllocNamedObjectA(name
: STRPTR
;
323 TagList
: pTagItem
) : pNamedObject
;
324 procedure Amiga2Date(amigatime
: ULONG
;
325 resultat
: pClockData
);
326 procedure ApplyTagChanges(TagList
,
327 ChangeList
: pTagItem
);
328 function AttemptRemNamedObject(obj
: pNamedObject
) : LongInt;
329 function CallHookPkt(h
: pHook
;
330 obj
, paramPkt
: APTR
) : ULONG
;
331 function CheckDate(date
: pClockData
) : ULONG
;
332 function CloneTagItems(tagList
: pTagItem
) : pTagItem
;
333 function Date2Amiga(date
: pClockData
) : ULONG
;
334 procedure FilterTagChanges(changelist
, oldvalues
: pTagItem
;
336 function FilterTagItems(taglist
: pTagItem
;
338 logic
: ULONG
) : ULONG
;
339 function FindNamedObject(nameSpace
: pNamedObject
;
341 lastobject
: pNamedObject
) : pNamedObject
;
342 function FindTagItem(TagVal
: Tag
;
343 TagList
: pTagItem
) : pTagItem
;
344 procedure FreeNamedObject(Obj
: pNamedObject
);
345 procedure FreeTagItems(TagList
: pTagItem
);
346 function GetTagData(tagval
: Tag
;
348 TagList
: pTagItem
) : ULONG
;
349 function GetUniqueID
: ULONG
;
350 procedure MapTags(TagList
: pTagItem
;
352 IncludeMiss
: ULONG
);
353 function NamedObjectName(Obj
: pNamedObject
) : STRPTR
;
354 function NextTagItem(Item
: ppTagItem
) : pTagItem
;
355 function PackBoolTags(InitialFlags
: ULONG
;
356 TagList
, boolmap
: pTagItem
) : ULONG
;
357 function PackStructureTags(packk
: APTR
;
359 TagList
: pTagItem
) : ULONG
;
360 procedure RefreshTagItemClones(cloneTagItems
,
361 OriginalTagItems
: pTagItem
);
362 procedure ReleaseNamedObject(Obj
: pNamedObject
);
363 procedure RemNamedObject(Obj
: pNamedObject
;
365 function SDivMod32( dividend
, divisor
: LongInt) : LongInt;
366 function SMult32(Arg1
, Arg2
: LongInt) : LongInt;
367 function SMult64(Arg1
, Arg2
: LongInt) : LongInt;
368 function Stricmp(Str1
, Str2
: STRPTR
) : LongInt;
369 function Strnicmp(Str1
, Str2
: STRPTR
;
370 len
: LongInt) : LongInt;
371 function TagInArray(t
: Tag
;
372 TagArray
: Pointer) : Boolean;
373 function ToLower(c
: ULONG
) : Char;
374 function ToUpper(c
: ULONG
) : Char;
375 function UDivMod32( dividend
, divisor
: ULONG
) : ULONG
;
376 function UMult32(Arg1
, Arg2
: ULONG
) : ULONG
;
377 function UMult64(Arg1
, Arg2
: ULONG
) : ULONG
;
378 function UnpackStructureTags(pac
: APTR
;
380 TagList
: pTagItem
) : ULONG
;
384 function AddNamedObject(nameSpace
,
385 obj
: pNamedObject
) : Boolean;
391 MOVE.L _UtilityBase
,A6
404 function AllocateTagItems(num
: ULONG
) : pTagItem
;
409 MOVE.L _UtilityBase
,A6
416 function AllocNamedObjectA(name
: STRPTR
;
417 TagList
: pTagItem
) : pNamedObject
;
423 MOVE.L _UtilityBase
,A6
430 procedure Amiga2Date(amigatime
: ULONG
;
431 resultat
: pClockData
);
437 MOVE.L _UtilityBase
,A6
443 procedure ApplyTagChanges(TagList
,
444 ChangeList
: pTagItem
);
450 MOVE.L _UtilityBase
,A6
456 function AttemptRemNamedObject(obj
: pNamedObject
) : LongInt;
461 MOVE.L _UtilityBase
,A6
468 function CallHookPkt(h
: pHook
;
469 obj
, paramPkt
: APTR
) : ULONG
;
476 MOVE.L _UtilityBase
,A6
483 function CheckDate(date
: pClockData
) : ULONG
;
488 MOVE.L _UtilityBase
,A6
495 function CloneTagItems(tagList
: pTagItem
) : pTagItem
;
500 MOVE.L _UtilityBase
,A6
507 function Date2Amiga(date
: pClockData
) : ULONG
;
512 MOVE.L _UtilityBase
,A6
519 procedure FilterTagChanges(changelist
, oldvalues
: pTagItem
;
527 MOVE.L _UtilityBase
,A6
533 function FilterTagItems(taglist
: pTagItem
;
535 logic
: ULONG
) : ULONG
;
542 MOVE.L _UtilityBase
,A6
549 function FindNamedObject(nameSpace
: pNamedObject
;
551 lastobject
: pNamedObject
) : pNamedObject
;
558 MOVE.L _UtilityBase
,A6
565 function FindTagItem(TagVal
: Tag
;
566 TagList
: pTagItem
) : pTagItem
;
572 MOVE.L _UtilityBase
,A6
579 procedure FreeNamedObject(Obj
: pNamedObject
);
584 MOVE.L _UtilityBase
,A6
590 procedure FreeTagItems(TagList
: pTagItem
);
595 MOVE.L _UtilityBase
,A6
601 function GetTagData(tagval
: Tag
;
603 TagList
: pTagItem
) : ULONG
;
610 MOVE.L _UtilityBase
,A6
617 function GetUniqueID
: ULONG
;
621 MOVE.L _UtilityBase
,A6
628 procedure MapTags(TagList
: pTagItem
;
630 IncludeMiss
: ULONG
);
636 MOVE.L IncludeMiss
,d0
637 MOVE.L _UtilityBase
,A6
643 function NamedObjectName(Obj
: pNamedObject
) : STRPTR
;
648 MOVE.L _UtilityBase
,A6
655 function NextTagItem(Item
: ppTagItem
) : pTagItem
;
660 MOVE.L _UtilityBase
,A6
667 function PackBoolTags(InitialFlags
: ULONG
;
668 TagList
, boolmap
: pTagItem
) : ULONG
;
672 MOVE.L InitialFlags
,d0
675 MOVE.L _UtilityBase
,A6
682 function PackStructureTags(packk
: APTR
;
684 TagList
: pTagItem
) : ULONG
;
691 MOVE.L _UtilityBase
,A6
698 procedure RefreshTagItemClones(cloneTagItems
,
699 OriginalTagItems
: pTagItem
);
703 MOVE.L cloneTagItems
,a0
704 MOVE.L OriginalTagItems
,a1
705 MOVE.L _UtilityBase
,A6
711 procedure ReleaseNamedObject(Obj
: pNamedObject
);
716 MOVE.L _UtilityBase
,A6
722 procedure RemNamedObject(Obj
: pNamedObject
;
729 MOVE.L _UtilityBase
,A6
735 function SDivMod32( dividend
, divisor
: LongInt) : LongInt;
741 MOVE.L _UtilityBase
,A6
748 function SMult32(Arg1
, Arg2
: LongInt) : LongInt;
754 MOVE.L _UtilityBase
,A6
761 function SMult64(Arg1
, Arg2
: LongInt) : LongInt;
767 MOVE.L _UtilityBase
,A6
774 function Stricmp(Str1
, Str2
: STRPTR
) : LongInt;
780 MOVE.L _UtilityBase
,A6
787 function Strnicmp(Str1
, Str2
: STRPTR
;
788 len
: LongInt) : LongInt;
795 MOVE.L _UtilityBase
,A6
802 function TagInArray(t
: Tag
;
803 TagArray
: Pointer) : Boolean;
809 MOVE.L _UtilityBase
,A6
822 function ToLower(c
: ULONG
) : Char;
827 MOVE.L _UtilityBase
,A6
834 function ToUpper(c
: ULONG
) : Char;
839 MOVE.L _UtilityBase
,A6
846 function UDivMod32( dividend
, divisor
: ULONG
) : ULONG
;
852 MOVE.L _UtilityBase
,A6
859 function UMult32(Arg1
, Arg2
: ULONG
) : ULONG
;
865 MOVE.L _UtilityBase
,A6
872 function UMult64(Arg1
, Arg2
: ULONG
) : ULONG
;
878 MOVE.L _UtilityBase
,A6
885 function UnpackStructureTags(pac
: APTR
;
887 TagList
: pTagItem
) : ULONG
;
894 MOVE.L _UtilityBase
,A6