Updated from original SVN.
[cake.git] / workbench / classes / gadgets / texteditor / includes / mccheader.c
blobb7c88c38fdbe3ec21cc8c512ec0c7880977c2418
1 /*****************************************************************************
3 This code serves as a basis for writing a library-based MUI custom class
4 (xyz.mcc) and its preferences editor (xyz.mcp).
6 You need to define a few things in your main source file, then include
7 this file and then continue with your classes methods. The order is
8 important, mccheader.c must be the first code-generating module.
10 Things to be defined before mccheader.c is included:
12 (1) UserLibID - version string for your class. must follow normal $VER: string conventions.
13 (2) VERSION - version number of the class. must match the one given in the $VER: string.
14 (3) REVISION - revision number of the class. must match the one given in the $VER: string.
15 (4) CLASS - Name of your class, ".mcc" or ".mcp" must always be appended.
17 (5) SUPERCLASS - superclass of your class.
18 (6) struct Data - instance data structure.
19 (7) _Dispatcher - your dispatcher function.
21 (8) SUPERCLASSP - Superclass of the preferences class, must be MUIC_Mccprefs or a subclass.
22 (9) struct DataP - instance data structure of preferences class.
23 (10) _DispatcherP - dispatcher for the preferences class.
25 (11) USEDCLASSES - Other custom classes required by this class (NULL terminated string array)
26 (12) USEDCLASSESP - Preferences classes (.mcp) required by this class (NULL terminated string array)
27 (13) SHORTHELP - .mcp help text for prefs program's listview.
29 Items (1) to (4) must always be defined. If you create a stand-alone
30 custom class (*.mcc) without preferences editor, also define (5), (6)
31 and (7). Name your class and the resulting ouptut file "Myclass.mcc".
33 If you create a preferences class (*.mcp) for a custom class, define
34 (8), (9) and (10) instead of (5), (6) and (7). Name your class and the
35 resulting output file "Myclass.mcp".
37 If you create a custom class with included preferences editor, define
38 all the above. Note that in this case, the name of your class and the
39 resulting output file is always "Myclass.mcc". MUI will automatically
40 recognize that there's also a "Myclass.mcp" included. Having a builtin
41 preferences class reduces the need for a second file but increases the
42 size and memory consuption of the class.
44 (11) If your class requires other mcc custom classes, list them in the
45 static array USEDCLASSES like this:
46 #define USEDCLASSES used_classes
47 const STRPTR used_classes[] = { "Busy.mcc", "Listtree.mcc", NULL };
49 (12) If your class has one (or more) preferences classes, list them in
50 the array USEDCLASSESP like this:
51 #define USEDCLASSESP used_classesP
52 const STRPTR used_classesP[] = { "Myclass.mcp", "Popxxx.mcp", NULL };
54 (13) If you want MUI to display additional help text (besides name,
55 version and copyright) when the mouse pointer is over your mcp entry
56 in the prefs listview:
57 #define SHORTHELP "ANSI display for terminal programs."
59 If your class needs custom initialization (e.g. opening other
60 libraries), you can define
61 ClassInit
62 ClassExit
63 to point to custom functions. These functions need to have the prototypes
64 BOOL ClassInitFunc(struct Library *base);
65 VOID ClassExitFunc(struct Library *base);
66 and will be called right after the class has been created and right
67 before the class is being deleted. If your init func returns FALSE,
68 the custom class will be unloaded immediately.
70 Define the minimum version of muimaster.libray in MASTERVERSION. If you
71 don't define MASTERVERSION, it will default to MUIMASTER_VMIN from the
72 mui.h include file.
74 ---
75 Items (1) to (4) must always be defined. If you create a stand-alone
76 custom class (*.mcc) without preferences editor, also define (5), (6)
77 and (7). Name your class and the resulting ouptut file "Myclass.mcc".
79 If you create a preferences class (*.mcp) for a custom class, define
80 (8), (9) and (10) instead of (5), (6) and (7). Name your class and the
81 resulting output file "Myclass.mcp".
83 If you create a custom class with included preferences editor, define
84 all the above. Note that in this case, the name of your class and the
85 resulting output file is always "Myclass.mcc". MUI will automatically
86 recognize that there's also a "Myclass.mcp" included. Having a builtin
87 preferences class reduces the need for a second file but increases the
88 size and memory consuption of the class.
90 If your class needs custom initialization (e.g. opening other
91 libraries), you can define
92 PreClassInit
93 PostClassExit
94 ClassInit
95 ClassExit
96 to point to custom functions. These functions need to have the prototypes
97 BOOL ClassInitFunc(struct Library *base);
98 VOID ClassExitFunc(struct Library *base);
99 and will be called right after the class has been created and right
100 before the class is being deleted. If your init func returns FALSE,
101 the custom class will be unloaded immediately.
103 BOOL PreClassInitFunc(void);
104 VOID PostClassExitFunc(void);
106 These functions will be called BEFORE the class is created and AFTER the
107 class is deleted, if something depends on it for example. MUIMasterBase
108 is open then.
110 Define the minimum version of muimaster.libray in MASTERVERSION. If you
111 don't define MASTERVERSION, it will default to MUIMASTER_VMIN from the
112 mui.h include file.
114 This code automatically defines and initializes the following variables:
115 struct Library *MUIMasterBase;
116 struct Library *SysBase;
117 struct Library *UtilityBase;
118 struct DosLibrary *DOSBase;
119 struct GfxBase *GfxBase;
120 struct IntuitionBase *IntuitionBase;
121 struct Library *MUIClassBase; // your classes library base
122 struct MUI_CustomClass *ThisClass; // your custom class
123 struct MUI_CustomClass *ThisClassP; // your preferences class
125 Example: Myclass.c
126 #define CLASS MUIC_Myclass // name of class, e.g. "Myclass.mcc"
127 #define SUPERCLASS MUIC_Area // name of superclass
128 struct Data
130 LONG MyData;
131 struct Foobar MyData2;
132 // ...
134 #define UserLibID "$VER: Myclass.mcc 17.53 (11.11.96)"
135 #define VERSION 17
136 #define REVISION 53
137 #include "mccheader.c"
138 ULONG ASM SAVEDS _Dispatcher(REG(a0) struct IClass *cl GNUCREG(a0),
139 REG(a2) Object *obj GNUCREG(a2),
140 REG(a1) Msg msg GNUCREG(a1) )
142 // ...
145 Compiling and linking with SAS-C can look like this:
146 Myclass.mcc: Myclass.c
147 sc $(CFLAGS) $*.c OBJNAME $*.o
148 slink to $@ from $*.o lib $(LINKERLIBS) $(LINKERFLAGS)
150 Note well that we don't use SAS library creation feature here, it simply
151 sucks too much. It's not much more complicated to do the library
152 initialziation ourselves and we have better control over everything.
154 Make sure to read the whole source to get some interesting comments
155 and some understanding on how libraries are created!
157 *****************************************************************************/
159 /******************************************************************************/
160 /* Includes */
161 /******************************************************************************/
163 /* MorphOS relevant includes... */
164 #ifdef __MORPHOS__
165 #include <emul/emulinterface.h>
166 #include <emul/emulregs.h>
167 #endif
169 /* a few other includes... */
171 #include <exec/types.h>
172 #include <exec/memory.h>
173 #include <exec/libraries.h>
174 #include <exec/semaphores.h>
175 #include <exec/resident.h>
176 #include <exec/execbase.h>
177 #include <dos/dos.h>
179 #include <proto/exec.h>
180 #include <proto/muimaster.h>
181 #include <proto/utility.h>
182 #include <proto/dos.h>
183 #include <proto/graphics.h>
184 #include <proto/intuition.h>
186 /* The name of the class will also become the name of the library. */
187 /* We need a pointer to this string in our ROMTag (see below). */
189 static const char UserLibName[] = CLASS;
191 /* Here's our global data, described above. */
193 #if defined(__amigaos4__)
194 struct Library *MUIMasterBase = NULL;
195 struct Library *SysBase = NULL;
196 struct Library *UtilityBase = NULL;
197 struct Library *DOSBase = NULL;
198 struct Library *GfxBase = NULL;
199 struct Library *IntuitionBase = NULL;
200 struct MUIMasterIFace *IMUIMaster = NULL;
201 struct ExecIFace *IExec = NULL;
202 struct UtilityIFace *IUtility = NULL;
203 struct DOSIFace *IDOS = NULL;
204 struct GraphicsIFace *IGraphics = NULL;
205 struct IntuitionIFace *IIntuition = NULL;
206 #else
207 struct Library *MUIMasterBase = NULL;
208 struct ExecBase *SysBase = NULL;
209 struct Library *UtilityBase = NULL;
210 struct DosLibrary *DOSBase = NULL;
211 struct GfxBase *GfxBase = NULL;
212 struct IntuitionBase *IntuitionBase = NULL;
213 #endif
215 #ifdef SUPERCLASS
216 static struct MUI_CustomClass *ThisClass = NULL;
217 #endif
219 #ifdef SUPERCLASSP
220 static struct MUI_CustomClass *ThisClassP = NULL;
221 #endif
223 #ifdef __GNUC__
224 #ifdef USE_UTILITYBASE
225 struct Library *__UtilityBase = NULL; // required by libnix & clib2
226 #endif
227 #ifdef __libnix__
228 /* these one are needed copies for libnix.a */
229 #ifdef USE_MATHIEEEDOUBBASBASE
230 struct Library *__MathIeeeDoubBasBase = NULL;
231 #endif
232 #ifdef USE_MATHIEEEDOUBTRANSBASE
233 struct Library *__MathIeeeDoubTransBase = NULL;
234 #endif
235 #endif
236 #endif /* __GNUC__ */
238 /* Our library structure, consisting of a struct Library, a segment pointer */
239 /* and a semaphore. We need the semaphore to protect init/exit stuff in our */
240 /* open/close functions */
242 struct LibraryHeader
244 struct Library lh_Library;
245 UWORD lh_Pad1;
246 BPTR lh_Segment;
247 struct SignalSemaphore lh_Semaphore;
248 UWORD lh_Pad2;
249 struct StackSwapStruct *lh_Stack;
252 /******************************************************************************/
253 /* External references */
254 /******************************************************************************/
256 //static BOOL LIBFUNC UserLibInit (struct Library *base);
257 //static BOOL LIBFUNC UserLibExpunge(struct Library *base);
258 static BOOL LIBFUNC UserLibOpen (struct Library *base);
259 static BOOL LIBFUNC UserLibClose (struct Library *base);
261 /******************************************************************************/
262 /* Local Structures & Prototypes */
263 /******************************************************************************/
265 #if defined(__amigaos4__)
267 struct LibraryHeader * LIBFUNC LibInit (struct LibraryHeader *base, BPTR librarySegment, struct ExecIFace *pIExec);
268 BPTR LIBFUNC LibExpunge(struct LibraryManagerInterface *Self);
269 struct LibraryHeader * LIBFUNC LibOpen (struct LibraryManagerInterface *Self, ULONG version);
270 BPTR LIBFUNC LibClose (struct LibraryManagerInterface *Self);
271 LONG LIBFUNC LibNull (void);
272 ULONG LIBFUNC MCC_Query (UNUSED struct Interface *self, REG(d0, LONG which));
274 #elif defined(__MORPHOS__)
276 struct LibraryHeader * LIBFUNC LibInit (struct LibraryHeader *base, BPTR Segment, struct ExecBase *SysBase);
277 BPTR LIBFUNC LibExpunge(void);
278 struct LibraryHeader * LIBFUNC LibOpen (void);
279 BPTR LIBFUNC LibClose (void);
280 LONG LIBFUNC LibNull (void);
281 ULONG LIBFUNC MCC_Query (void);
283 #else
285 struct LibraryHeader * LIBFUNC LibInit (REG(a0, BPTR Segment), REG(a6, struct ExecBase *SysBase));
286 BPTR LIBFUNC LibExpunge(REG(a6, struct LibraryHeader *base));
287 struct LibraryHeader * LIBFUNC LibOpen (REG(a6, struct LibraryHeader *base));
288 BPTR LIBFUNC LibClose (REG(a6, struct LibraryHeader *base));
289 LONG LIBFUNC LibNull (void);
290 ULONG LIBFUNC MCC_Query (REG(d0, LONG which));
292 #endif
294 /******************************************************************************/
295 /* Dummy entry point and LibNull() function all in one */
296 /******************************************************************************/
298 int _start(void)
300 return RETURN_FAIL;
303 LONG LIBFUNC LibNull(VOID)
305 return(0);
308 /******************************************************************************/
309 /* Local data structures */
310 /******************************************************************************/
312 #if defined(__amigaos4__)
313 /* ------------------- OS4 Manager Interface ------------------------ */
314 STATIC ULONG LibObtain(struct LibraryManagerInterface *Self)
316 return(Self->Data.RefCount++);
319 STATIC ULONG LibRelease(struct LibraryManagerInterface *Self)
321 return(Self->Data.RefCount--);
324 STATIC CONST APTR LibManagerVectors[] =
326 (APTR)LibObtain,
327 (APTR)LibRelease,
328 (APTR)NULL,
329 (APTR)NULL,
330 (APTR)LibOpen,
331 (APTR)LibClose,
332 (APTR)LibExpunge,
333 (APTR)NULL,
334 (APTR)-1
337 STATIC CONST struct TagItem LibManagerTags[] =
339 {MIT_Name, (ULONG)"__library"},
340 {MIT_VectorTable, (ULONG)LibManagerVectors},
341 {MIT_Version, 1},
342 {TAG_DONE, 0}
345 /* ------------------- Library Interface(s) ------------------------ */
347 STATIC CONST APTR LibVectors[] =
349 (APTR)LibObtain,
350 (APTR)LibRelease,
351 (APTR)NULL,
352 (APTR)NULL,
353 (APTR)MCC_Query,
354 (APTR)-1
357 STATIC CONST struct TagItem MainTags[] =
359 {MIT_Name, (ULONG)"main"},
360 {MIT_VectorTable, (ULONG)LibVectors},
361 {MIT_Version, 1},
362 {TAG_DONE, 0}
365 STATIC CONST ULONG LibInterfaces[] =
367 (ULONG)LibManagerTags,
368 (ULONG)MainTags,
369 (ULONG)0
372 // Out libraries always have to carry a 68k jump table with it, so
373 // lets define it here as extern, as we are going to link it to
374 // our binary here.
375 #ifndef NO_VECTABLE68K
376 extern const APTR VecTable68K[];
377 #endif
379 STATIC CONST struct TagItem LibCreateTags[] =
381 {CLT_DataSize, (ULONG)(sizeof(struct LibraryHeader))},
382 {CLT_InitFunc, (ULONG)LibInit},
383 {CLT_Interfaces, (ULONG)LibInterfaces},
384 #ifndef NO_VECTABLE68K
385 {CLT_Vector68K, (ULONG)VecTable68K},
386 #endif
387 {TAG_DONE, 0}
390 #else
392 static const APTR LibVectors[] =
394 #ifdef __MORPHOS__
395 (APTR)FUNCARRAY_32BIT_NATIVE,
396 #endif
397 (APTR)LibOpen,
398 (APTR)LibClose,
399 (APTR)LibExpunge,
400 (APTR)LibNull,
401 (APTR)MCC_Query,
402 (APTR)-1
405 #endif
407 /* ------------------- ROM Tag ------------------------ */
408 static const USED_VAR struct Resident ROMTag =
410 RTC_MATCHWORD,
411 (struct Resident *)&ROMTag,
412 (struct Resident *)&ROMTag + 1,
413 #if defined(__amigaos4__)
414 RTF_AUTOINIT|RTF_NATIVE, // The Library should be set up according to the given table.
415 #elif defined(__MORPHOS__)
416 RTF_PPC,
417 #else
419 #endif
420 VERSION,
421 NT_LIBRARY,
423 (char *)UserLibName,
424 (char *)UserLibID+6,
425 #if defined(__amigaos4__)
426 (APTR)LibCreateTags, // This table is for initializing the Library.
427 #else
428 (APTR)LibInit,
429 #endif
430 #if defined(__MORPHOS__)
431 REVISION,
433 #endif
436 #if defined(__MORPHOS__)
438 * To tell the loader that this is a new emulppc elf and not
439 * one for the ppc.library.
440 * ** IMPORTANT **
442 const USED_VAR ULONG __amigappc__ = 1;
443 const USED_VAR ULONG __abox__ = 1;
445 #undef USE_SEMAPHORE
447 #else
449 #ifndef USE_SEMAPHORE
450 #define USE_SEMAPHORE
451 #endif
453 #endif /* __MORPHOS */
455 #ifndef __amigaos4__
456 #define DeleteLibrary(LIB) \
457 FreeMem((STRPTR)(LIB)-(LIB)->lib_NegSize, (ULONG)((LIB)->lib_NegSize+(LIB)->lib_PosSize))
458 #endif
460 /******************************************************************************/
461 /* Standard Library Functions, all of them are called in Forbid() state. */
462 /******************************************************************************/
464 #if defined(__amigaos4__)
465 struct LibraryHeader * ASM SAVEDS LibInit(struct LibraryHeader *base, BPTR librarySegment, struct ExecIFace *pIExec)
467 struct ExecBase *sb = (struct ExecBase *)pIExec->Data.LibBase;
468 IExec = pIExec;
469 SysBase = (struct Library *)sb;
471 D(DBF_STARTUP, "start... (segment=%08lx)", librarySegment);
473 base->lh_Library.lib_Node.ln_Type = NT_LIBRARY;
474 base->lh_Library.lib_Node.ln_Pri = 0;
475 base->lh_Library.lib_Node.ln_Name = (char *)UserLibName;
476 base->lh_Library.lib_Flags = LIBF_CHANGED | LIBF_SUMUSED;
477 base->lh_Library.lib_Version = VERSION;
478 base->lh_Library.lib_Revision = REVISION;
479 base->lh_Library.lib_IdString = (char *)UserLibID;
481 base->lh_Segment = librarySegment;
483 InitSemaphore(&base->lh_Semaphore);
486 if(!UserLibInit((struct Library *)base))
488 DeleteLibrary((struct Library *)base);
489 return(NULL);
493 return(base);
496 #else
498 #ifdef __MORPHOS__
499 #undef CLASS_STACKSWAP
500 struct LibraryHeader *LibInit(struct LibraryHeader *base, BPTR Segment, struct ExecBase *sb)
502 #else
503 struct LibraryHeader * ASM SAVEDS LibInit(REG(a0, BPTR Segment), REG(a6, struct ExecBase *sb))
505 #endif
507 #if defined(CLASS_STACKSWAP)
508 static struct StackSwapStruct *stack;
509 #endif
510 #if !defined(__MORPHOS__)
511 struct LibraryHeader *base;
512 #endif
514 SysBase = sb;
516 D(DBF_STARTUP, "Start..." );
518 // make sure that this is really a 68020+ machine if optimized for 020+
519 #if _M68060 || _M68040 || _M68030 || _M68020 || __mc68020 || __mc68030 || __mc68040 || __mc68060
520 if(!(SysBase->AttnFlags & AFF_68020))
521 return(NULL);
522 #endif
524 #if defined(CLASS_STACKSWAP)
525 if ( !( stack = AllocMem( sizeof( struct StackSwapStruct ) + 8192, MEMF_PUBLIC | MEMF_CLEAR ) ) )
526 return( NULL );
528 stack->stk_Lower = (APTR)( (ULONG)stack + sizeof( struct StackSwapStruct ) );
529 stack->stk_Upper = (ULONG)( (ULONG)stack->stk_Lower + 8192 );
530 stack->stk_Pointer = (APTR)stack->stk_Upper;
532 D(DBF_STARTUP, "Before StackSwap()");
533 StackSwap( stack );
534 #endif
536 if((base = (struct LibraryHeader *)MakeLibrary((APTR)LibVectors,NULL,NULL,sizeof(struct LibraryHeader),NULL)))
538 D(DBF_STARTUP, "After MakeLibrary()");
540 base->lh_Library.lib_Node.ln_Type = NT_LIBRARY;
541 base->lh_Library.lib_Node.ln_Name = (char *)UserLibName;
542 base->lh_Library.lib_Flags = LIBF_CHANGED | LIBF_SUMUSED;
543 base->lh_Library.lib_Version = VERSION;
544 base->lh_Library.lib_Revision = REVISION;
545 base->lh_Library.lib_IdString = (char *)UserLibID;
547 base->lh_Segment = Segment;
549 #if defined(USE_SEMAPHORE)
550 InitSemaphore(&base->lh_Semaphore);
551 #endif
553 #if defined(CLASS_STACKSWAP)
554 base->lh_Stack = stack;
555 #endif
557 //if(UserLibInit((struct Library *)base))
559 D(DBF_STARTUP, "AddLibrary()");
560 AddLibrary((struct Library *)base);
562 /*else
564 DeleteLibrary(&base->lh_Library)
565 base = NULL;
569 else
571 D(DBF_STARTUP, "\7MakeLibrary() failed");
574 #if defined(CLASS_STACKSWAP)
575 StackSwap(base->lh_Stack);
576 FreeMem(base->lh_Stack, sizeof(struct StackSwapStruct) + 8192);
577 D(DBF_STARTUP, "After second StackSwap()");
578 #endif
580 return(base);
582 #endif
584 /*****************************************************************************************************/
585 /*****************************************************************************************************/
587 #ifdef __amigaos4__
588 BPTR LibExpunge(struct LibraryManagerInterface *Self)
590 struct LibraryHeader *base = (struct LibraryHeader *)Self->Data.LibBase;
591 #elif __MORPHOS__
592 BPTR LibExpunge(void)
594 struct LibraryHeader *base = (void *)REG_A6;
595 #else
596 BPTR ASM SAVEDS LibExpunge(REG(a6, struct LibraryHeader *base))
598 #endif
599 BPTR rc;
601 D(DBF_STARTUP, "OpenCount = %ld", base->lh_Library.lib_OpenCnt);
603 if(base->lh_Library.lib_OpenCnt > 0)
605 base->lh_Library.lib_Flags |= LIBF_DELEXP;
606 D(DBF_STARTUP, "Setting LIBF_DELEXP");
607 return(0);
611 if(!UserLibExpunge(&base->lh_Library))
613 D(DBF_STARTUP, "UserLibExpunge() failed, setting LIBF_DELEXP");
614 base->lh_Library.lib_Flags |= LIBF_DELEXP;
615 return(0);
619 Remove((struct Node *)base);
620 rc = base->lh_Segment;
622 DeleteLibrary(&base->lh_Library);
624 return(rc);
627 /*****************************************************************************************************/
628 /*****************************************************************************************************/
630 #ifdef __amigaos4__
631 struct LibraryHeader *LibOpen(struct LibraryManagerInterface *Self, UNUSED ULONG version)
633 struct LibraryHeader *base = (struct LibraryHeader *)Self->Data.LibBase;
634 #elif __MORPHOS__
635 struct LibraryHeader *LibOpen( void )
637 struct LibraryHeader *base = (void *)REG_A6;
638 #else
639 struct LibraryHeader * ASM SAVEDS LibOpen(REG(a6, struct LibraryHeader *base))
641 #endif
642 struct LibraryHeader *rc;
644 /* Kill the Delayed Expunge flag since we are opened again */
645 base->lh_Library.lib_Flags &= ~LIBF_DELEXP;
647 #ifdef USE_SEMAPHORE
648 ObtainSemaphore(&base->lh_Semaphore);
649 #endif
651 base->lh_Library.lib_OpenCnt++;
653 D(DBF_STARTUP, "OpenCount = %ld", base->lh_Library.lib_OpenCnt);
655 if(UserLibOpen(&base->lh_Library))
657 #ifdef CLASS_VERSIONFAKE
658 base->lh_Library.lib_Version = MUIMasterBase->lib_Version;
659 base->lh_Library.lib_Revision = MUIMasterBase->lib_Revision;
660 #endif
662 rc = base;
664 else
666 rc = NULL;
667 base->lh_Library.lib_OpenCnt--;
668 D(DBF_STARTUP, "\7UserLibOpen() failed");
671 #ifdef USE_SEMAPHORE
672 ReleaseSemaphore(&base->lh_Semaphore);
673 #endif
675 return(rc);
678 /*****************************************************************************************************/
679 /*****************************************************************************************************/
681 #ifdef __amigaos4__
682 BPTR LibClose(struct LibraryManagerInterface *Self)
684 struct LibraryHeader *base = (struct LibraryHeader *)Self->Data.LibBase;
685 #elif __MORPHOS__
686 BPTR LibClose(void)
688 struct LibraryHeader *base = (struct LibraryHeader *)REG_A6;
689 #else
690 BPTR ASM SAVEDS LibClose(REG(a6, struct LibraryHeader *base))
692 #endif
693 BPTR rc = 0;
695 #ifdef USE_SEMAPHORE
696 ObtainSemaphore(&base->lh_Semaphore);
697 #endif
699 D(DBF_STARTUP, "OpenCount = %ld %s", base->lh_Library.lib_OpenCnt, base->lh_Library.lib_OpenCnt == 0 ? "\7ERROR" : "");
701 UserLibClose((struct Library *)base);
703 base->lh_Library.lib_OpenCnt--;
705 #ifdef USE_SEMAPHORE
706 ReleaseSemaphore(&base->lh_Semaphore);
707 #endif
709 if(base->lh_Library.lib_OpenCnt == 0 &&
710 base->lh_Library.lib_Flags & LIBF_DELEXP)
712 #ifdef __amigaos4__
713 rc = LibExpunge(Self);
714 #elif __MORPHOS__
715 rc = LibExpunge();
716 #else
717 rc = LibExpunge(base);
718 #endif
721 return(rc);
724 /*****************************************************************************************************/
725 /*****************************************************************************************************/
727 #ifdef SUPERCLASS
728 DISPATCHERPROTO(_Dispatcher);
729 #endif
731 #ifdef SUPERCLASSP
732 DISPATCHERPROTO(_DispatcherP);
733 #endif
735 BOOL UserLibOpen(struct Library *base)
737 BOOL PreClassInitFunc(void);
738 BOOL ClassInitFunc(struct Library *base);
740 D(DBF_STARTUP, "OpenCount = %ld", base->lib_OpenCnt);
742 if (base->lib_OpenCnt!=1)
743 return(TRUE);
745 #ifndef MASTERVERSION
746 #define MASTERVERSION MUIMASTER_VMIN
747 #endif
749 if((MUIMasterBase = OpenLibrary(MUIMASTER_NAME, MASTERVERSION)) &&
750 GETINTERFACE(IMUIMaster, MUIMasterBase))
752 #ifdef PreClassInit
753 if (!PreClassInitFunc())
755 return FALSE;
757 #endif
760 #ifdef SUPERCLASS
761 ThisClass = MUI_CreateCustomClass(base, SUPERCLASS, NULL, sizeof(struct INSTDATA), ENTRY(_Dispatcher));
762 if(ThisClass)
763 #endif
765 #ifdef SUPERCLASSP
766 if((ThisClassP = MUI_CreateCustomClass(base, SUPERCLASSP, NULL, sizeof(struct INSTDATAP), ENTRY(_DispatcherP))))
767 #endif
769 #ifdef SUPERCLASS
770 #define THISCLASS ThisClass
771 #else
772 #define THISCLASS ThisClassP
773 #endif
775 UtilityBase = (APTR)THISCLASS->mcc_UtilityBase;
776 DOSBase = (APTR)THISCLASS->mcc_DOSBase;
777 GfxBase = (APTR)THISCLASS->mcc_GfxBase;
778 IntuitionBase = (APTR)THISCLASS->mcc_IntuitionBase;
780 #ifdef USE_UTILITYBASE
781 __UtilityBase = (APTR)UtilityBase;
782 #endif
784 if(UtilityBase && DOSBase && GfxBase && IntuitionBase &&
785 GETINTERFACE(IUtility, UtilityBase) &&
786 GETINTERFACE(IDOS, DOSBase) &&
787 GETINTERFACE(IGraphics, GfxBase) &&
788 GETINTERFACE(IIntuition, IntuitionBase))
790 #if defined(DEBUG)
791 SetupDebug();
792 #endif
794 #ifndef ClassInit
795 return(TRUE);
796 #else
797 if(ClassInitFunc(base))
799 return(TRUE);
802 #ifdef SUPERCLASSP
803 MUI_DeleteCustomClass(ThisClassP);
804 ThisClassP = NULL;
805 #endif
806 #endif
809 DROPINTERFACE(IIntuition);
810 DROPINTERFACE(IGraphics);
811 DROPINTERFACE(IDOS);
812 DROPINTERFACE(IUtility);
815 #if defined(SUPERCLASSP) && defined(SUPERCLASS)
816 MUI_DeleteCustomClass(ThisClass);
817 ThisClass = NULL;
818 #endif
821 DROPINTERFACE(IMUIMaster);
822 CloseLibrary(MUIMasterBase);
823 MUIMasterBase = NULL;
826 D(DBF_STARTUP, "fail.: %08lx %s",base,base->lib_Node.ln_Name);
828 return(FALSE);
831 /*****************************************************************************************************/
832 /*****************************************************************************************************/
834 BOOL UserLibClose(struct Library *base)
836 VOID PostClassExitFunc(void);
837 VOID ClassExitFunc(struct Library *base);
839 D(DBF_STARTUP, "OpenCount = %ld", base->lib_OpenCnt);
841 if (base->lib_OpenCnt==1)
843 #ifdef ClassExit
844 ClassExitFunc(base);
845 #endif
847 #ifdef SUPERCLASSP
848 if (ThisClassP)
850 MUI_DeleteCustomClass(ThisClassP);
851 ThisClassP = NULL;
853 #endif
855 #ifdef SUPERCLASS
856 if (ThisClass)
858 MUI_DeleteCustomClass(ThisClass);
859 ThisClass = NULL;
861 #endif
863 #ifdef PostClassExit
864 PostClassExitFunc();
865 #endif
867 DROPINTERFACE(IIntuition);
868 DROPINTERFACE(IGraphics);
869 DROPINTERFACE(IDOS);
870 DROPINTERFACE(IUtility);
872 if (MUIMasterBase)
874 DROPINTERFACE(IMUIMaster);
875 CloseLibrary(MUIMasterBase);
876 MUIMasterBase = NULL;
880 return(TRUE);
883 /*****************************************************************************************************/
884 /*****************************************************************************************************/
886 #if defined(__amigaos4__)
887 ULONG LIBFUNC MCC_Query(UNUSED struct Interface *self, REG(d0, LONG which))
889 #elif defined(__MORPHOS__)
890 ULONG MCC_Query(void)
892 LONG which = (LONG)REG_D0;
893 #else
894 ULONG LIBFUNC MCC_Query(REG(d0, LONG which))
896 #endif
898 switch (which)
900 #ifdef SUPERCLASS
901 case 0: return((ULONG)ThisClass);
902 #endif
904 #ifdef SUPERCLASSP
905 case 1: return((ULONG)ThisClassP);
906 #endif
908 #ifdef PREFSIMAGEOBJECT
909 case 2:
911 Object *obj = PREFSIMAGEOBJECT;
912 return((ULONG)obj);
914 #endif
916 #ifdef ONLYGLOBAL
917 case 3:
919 return(TRUE);
921 #endif
923 #ifdef INFOCLASS
924 case 4:
926 return(TRUE);
928 #endif
930 #ifdef USEDCLASSES
931 case 5:
933 return((ULONG)USEDCLASSES);
935 #endif
937 #ifdef USEDCLASSESP
938 case 6:
940 return((ULONG)USEDCLASSESP);
942 #endif
944 #ifdef SHORTHELP
945 case 7:
947 return((ULONG)SHORTHELP);
949 #endif
952 return(0);