Initial commit.
[amiga/xmodule.git] / Main.c
1 /*
2 **      $VER: XModule 3.9 (16.8.97) Copyright (C) 1993,94,95,96 Bernardo Innocenti
3 **
4 **      This source code is provided "AS-IS", without warranties of any kind and
5 **      it is subject to change without notice.  All usage is at your own risk.
6 **      No liability or responsibility is assumed by the author.
7 **
8 **      Use 4 chars wide TABs to read this file
9 */
10
11 #include <exec/execbase.h>
12 #include <exec/lists.h>
13 #include <exec/memory.h>
14 #include <dos/dos.h>
15 #include <dos/dostags.h>
16 #include <libraries/gadtools.h>
17 #include <utility/utility.h>
18 #include <workbench/startup.h>
19
20 #include <proto/exec.h>
21 #include <proto/dos.h>
22 #include <proto/intuition.h>
23 #include <proto/icon.h>
24 #include <proto/utility.h>
25 #include <proto/xmodule.h>
26
27
28 #include "XModulePriv.h"
29 #include "Gui.h"
30
31
32
33 /* Local functions prototypes */
34
35 static LONG GetShellArgs (void);
36 static LONG GetWBArgs (void);
37 static void DisposeArgs (void);
38 static void HandleFrom (void);
39 static void SetupHooks (void);
40 static void Cleanup (LONG err);
41 static LONG Setup (void);
42
43
44
45 /* Memory pool for use by main program only */
46 XDEF void *Pool = NULL;
47
48
49
50 /* Version tag */
51 XDEF const UBYTE Version[] = "$VER: " VSTR " " BUILDMODE " " XMODULECOPY;
52 XDEF const UBYTE BaseName[] = BASENAME;
53 XDEF const UBYTE PrgName[] = PRGNAME;
54
55
56
57 /* Library bases */
58 XDEF struct IntuitionBase       *IntuitionBase  = NULL;
59 XDEF struct GfxBase                     *GfxBase                = NULL;
60 XDEF struct Library                     *LayersBase             = NULL;
61 XDEF struct UtilityBase         *UtilityBase    = NULL;
62 XDEF struct Library                     *GadToolsBase   = NULL;
63 XDEF struct Library                     *DiskfontBase   = NULL;
64 XDEF struct Library                     *AslBase                = NULL;
65 XDEF struct Library                     *IFFParseBase   = NULL;
66 XDEF struct Library                     *WorkbenchBase  = NULL;
67 XDEF struct Library                     *IconBase               = NULL;
68 XDEF struct ReqToolsBase        *ReqToolsBase   = NULL;
69 XDEF struct Library                     *CxBase                 = NULL;
70 XDEF struct Library                     *KeymapBase             = NULL;
71 XDEF struct XModuleBase         *XModuleBase    = NULL;
72
73
74
75 /* This structure holds data to open required libraries automatically. */
76
77 struct OpenLibs
78 {
79         struct Library **Base;
80         UBYTE *Name;
81         LONG Version;
82 };
83
84
85 #ifdef OS30_ONLY
86  #define OSLIBVER 39
87 #else
88  #define OSLIBVER 37
89 #endif /* !OS30_ONLY */
90
91 static const struct OpenLibs openlibs[] =
92 {
93         { (struct Library **)&IntuitionBase,    "intuition.library",    OSLIBVER },
94         { (struct Library **)&GfxBase,                  "graphics.library",             OSLIBVER },
95         { (struct Library **)&LayersBase,               "layers.library",               OSLIBVER },
96         { (struct Library **)&UtilityBase,              "utility.library",              OSLIBVER },
97         { (struct Library **)&GadToolsBase,             "gadtools.library",             OSLIBVER },
98         { (struct Library **)&KeymapBase,               "keymap.library",               37 },
99         { (struct Library **)&IFFParseBase,             "iffparse.library",             37 },
100         { (struct Library **)&WorkbenchBase,    "workbench.library",    37 },
101         { (struct Library **)&IconBase,                 "icon.library",                 37 },
102         { (struct Library **)&DiskfontBase,             "diskfont.library",             0 },
103
104         { NULL }
105 };
106
107
108
109 /* Used for argument parsing.
110  * NOTE: All fields must be 4 bytes long.
111  */
112 static struct
113 {
114         STRPTR  *From,
115                          PubScreen,
116                          PortName,
117                          Settings;
118         LONG     CxPopup;               /* Set to TRUE by default. */
119         STRPTR   CxPopKey;
120         LONG    *CxPriority,
121                         *IconX,
122                         *IconY;
123         STRPTR   IconName;
124 } XMArgs; /* egcs doesn't like this: = { 0 }; */
125
126 static struct RDArgs *RDArgs = NULL;
127
128 #define ARGS_TEMPLATE   "FROM/M,PUBSCREEN/K,PORTNAME/K,SETTINGS/K,CX_POPUP/T,CX_POPKEY/K,CX_PRIORITY/K/N,ICONXPOS/K/N,ICONYPOS/K/N,ICONNAME/K"
129
130
131
132 extern LONG STDARGS __main (void)
133
134 /* XModule main entry point.  Get arguments from CLI/Workbench,
135  * setup environment, open required files and call main event
136  * handling loop.
137  */
138 {
139         LONG err;
140
141         DB(kprintf ("\n"));
142         DB(kprintf ((STRPTR)(Version + 6)));
143         DB(kprintf ("\n*** Starting debug session -- Good luck!\n\n"));
144
145
146         if (!(err = Setup())) /* Setup environment */
147                 err = HandleGui();
148
149         Cleanup (err);
150
151         return err;
152 }       /* End main() */
153
154
155
156 static LONG GetShellArgs (void)
157
158 /* Parse command line arguments */
159 {
160         if (!(RDArgs = ReadArgs (ARGS_TEMPLATE, (LONG *)&XMArgs, NULL)))
161                 return IoErr();
162
163         return RETURN_OK;
164
165 } /* End GetShellArgs() */
166
167
168
169 static LONG GetWBArgs (void)
170
171 /* Parse Workbench arguments */
172 {
173         struct DiskObject *dobj;
174         STRPTR val;
175         UWORD i;
176
177
178         /* Get Multiselect args.
179          * Create a NULL-terminated array of STRPTRs
180          * in the same way ReadArgs() would have done.
181          */
182         if (WBenchMsg->sm_NumArgs > 1)
183                 if (!(XMArgs.From = AllocVec (WBenchMsg->sm_NumArgs * sizeof (STRPTR), MEMF_CLEAR)))
184                         return RETURN_FAIL;
185
186         for (i = 1; i < WBenchMsg->sm_NumArgs; i++)
187         {
188                 UBYTE buf[PATHNAME_MAX];
189
190                 if (NameFromLock (WBenchMsg->sm_ArgList[i].wa_Lock, buf, PATHNAME_MAX))
191                         if (AddPart (buf, WBenchMsg->sm_ArgList[i].wa_Name, PATHNAME_MAX))
192                         {
193                                 if (XMArgs.From[i-1] = AllocVec (strlen (buf), MEMF_ANY))
194                                         strcpy (XMArgs.From[i-1], buf);
195                                 else
196                                         break;
197                         }
198         }
199
200
201         /* Get ToolTypes */
202
203         if (!(dobj = GetProgramIcon()))
204                 return RETURN_FAIL;
205
206         if (val = FindToolType (dobj->do_ToolTypes, "PUBSCREEN"))
207                 if (XMArgs.PubScreen = AllocVec (strlen (val), MEMF_ANY))
208                         strcpy (XMArgs.PubScreen, val);
209
210         if (val = FindToolType (dobj->do_ToolTypes, "PORTNAME"))
211                 if (XMArgs.PortName = AllocVec (strlen (val), MEMF_ANY))
212                         strcpy (XMArgs.PortName, val);
213
214         if (val = FindToolType (dobj->do_ToolTypes, "SETTINGS"))
215                 if (XMArgs.Settings = AllocVec (strlen (val), MEMF_ANY))
216                         strcpy (XMArgs.Settings, val);
217
218         if (val = FindToolType (dobj->do_ToolTypes, "CX_POPUP"))
219                 XMArgs.CxPopup = MatchToolValue (val, "YES");
220
221         if (val = FindToolType (dobj->do_ToolTypes, "CX_POPKEY"))
222                 if (XMArgs.CxPopKey = AllocVec (strlen (val), MEMF_ANY))
223                         strcpy (XMArgs.CxPopKey, val);
224
225         if (val = FindToolType (dobj->do_ToolTypes, "CX_PRIORITY"))
226                 if (XMArgs.CxPriority = AllocVec (sizeof (LONG), MEMF_ANY))
227                         StrToLong (val, XMArgs.CxPriority);
228
229         if (val = FindToolType (dobj->do_ToolTypes, "ICONXPOS"))
230                 if (XMArgs.IconX = AllocVec (sizeof (LONG), MEMF_ANY))
231                         StrToLong (val, XMArgs.IconX);
232
233         if (val = FindToolType (dobj->do_ToolTypes, "ICONYPOS"))
234                 if (XMArgs.IconY = AllocVec (sizeof (LONG), MEMF_ANY))
235                         StrToLong (val, XMArgs.IconY);
236
237         if (val = FindToolType (dobj->do_ToolTypes, "ICONNAME"))
238                 if (XMArgs.IconName = AllocVec (strlen (val), MEMF_ANY))
239                         strcpy (XMArgs.IconName, val);
240
241         FreeDiskObject (dobj);
242
243         return RETURN_OK;
244 } /* End GetWBArgs() */
245
246
247
248 static void DisposeArgs (void)
249 {
250         if (RDArgs)
251         {
252                 FreeArgs (RDArgs);
253                 RDArgs = NULL;
254         }
255         else    /* Workbench */
256         {
257                 /* NULL is a valid parameter for FreeVec() */
258                 FreeVec (XMArgs.IconName);
259                 FreeVec (XMArgs.IconY);
260                 FreeVec (XMArgs.IconX);
261                 FreeVec (XMArgs.CxPriority);
262                 FreeVec (XMArgs.CxPopKey);
263                 FreeVec (XMArgs.Settings);
264                 FreeVec (XMArgs.PortName);
265                 FreeVec (XMArgs.PubScreen);
266
267                 if (XMArgs.From)
268                 {
269                         STRPTR *tmp = XMArgs.From;
270
271                         while (*tmp)
272                         {
273                                 FreeVec (*tmp);
274                                 tmp++;
275                         }
276
277                         FreeVec (XMArgs.From);
278                 }
279         }
280
281         memset (&XMArgs, 0, sizeof (XMArgs));
282 }
283
284
285
286 static void HandleFrom (void)
287 {
288         if (XMArgs.From)
289         {
290                 STRPTR                          *name = XMArgs.From;
291                 struct AnchorPath       *ap;
292                 LONG err;
293
294                 if (ap = AllocMem (sizeof (struct AnchorPath) + PATHNAME_MAX, MEMF_CLEAR))
295                 {
296                         OpenProgressWindow ();
297
298                         ap->ap_BreakBits = SIGBREAKF_CTRL_C;
299                         ap->ap_Strlen = PATHNAME_MAX;
300
301                         while (*name)
302                         {
303                                 err = MatchFirst (*name, ap);
304
305                                 while (!err)
306                                 {
307                                         xmLoadModule (ap->ap_Buf,
308                                                 XMSNG_AddToList, TRUE,
309                                                 TAG_DONE);
310
311                                         err = MatchNext (ap);
312                                 }
313
314                                 if (err != ERROR_NO_MORE_ENTRIES)
315                                 {
316                                         UBYTE buf[FAULT_MAX];
317
318                                         Fault (err, NULL, buf, FAULT_MAX);
319                                         ShowMessage (MSG_ERR_LOAD, *name, buf);
320                                 }
321
322                                 MatchEnd (ap);
323                                 name++;
324                         }
325
326                         CloseProgressWindow();
327
328                         FreeMem (ap, sizeof (struct AnchorPath) + PATHNAME_MAX);
329                 }
330                 else LastErr = ERROR_NO_FREE_STORE;
331         }
332 }
333
334
335
336 static void SetupHooks (void)
337 {
338         struct Library                  *XMHookBase;
339         struct FileInfoBlock    *fib;
340         BPTR                                     lock;
341         UBYTE                                    libpath[PATHNAME_MAX];
342
343         /* Built-in hooks */
344         AddXModuleHooks ();
345         AddTrackerHooks ();
346
347
348         if (fib = (struct FileInfoBlock *)AllocDosObject (DOS_FIB, NULL))
349         {
350                 if (lock = Lock (DEF_HOOKSDIR, ACCESS_READ))
351                         if (Examine (lock, fib))
352                                 while (ExNext (lock, fib))
353                                 {
354                                         strcpy (libpath, DEF_HOOKSDIR);
355                                         AddPart (libpath, fib->fib_FileName, PATHNAME_MAX);
356
357                                         if (XMHookBase = OpenLibrary (libpath, 0))
358                                         {
359                                                 #if defined(__SASC)
360                                                         #pragma libcall XMHookBase SetupXMHook 24 801
361                                                         void SetupXMHook (struct XModuleBase *);
362                                                 #elif defined(__GNUC__)
363                                                         #define SetupXMHook(xmbase) \
364                                                                 LP1NR(0x24, SetupXMHook, struct XModuleBase *, xmbase, a0, \
365                                                                 , XMHookBase)
366                                                 #else
367                                                         #error Define SetupXMHook() library call for your compiler
368                                                 #endif
369
370                                                 SetupXMHook (XModuleBase);
371                                                 CloseLibrary (XMHookBase);
372                                         }
373                                 }
374
375                 FreeDosObject (DOS_FIB, fib);
376         }
377
378
379         /* Set default saver */
380
381         if (!IsListEmpty ((struct List *)&XModuleBase->xm_Savers))
382                 XModuleBase->xm_DefaultSaver = (struct XMHook *)XModuleBase->xm_Savers.mlh_Head;
383 }
384
385
386
387 static LONG Setup (void)
388 {
389         LONG err;
390         ULONG i;
391
392         SetProgramName (PrgName);
393
394         /* Initialize view lists */
395         NEWLIST (&WindowList);
396         NEWLIST (&LogList);
397         NEWLIST (&PatternsList);
398         NEWLIST (&SequenceList);
399         NEWLIST (&InstrList);
400
401         /* Install graphics function replacements */
402         /*      InstallGfxFunctions();  */      /* These are currently never used */
403
404         /* Initialize ScrInfo structure */
405         strcpy (ScrInfo.PubScreenName, BaseName);
406
407         /* Initialize PubPort name */
408         strcpy (PubPortName, BaseName);
409
410         /* Initialize PubPort name */
411         strcpy (IconName, PrgName);
412
413
414         /* Open required libraries */
415         for (i = 0 ; openlibs[i].Base ; i++)
416                 if (!(*(openlibs[i].Base) = MyOpenLibrary (openlibs[i].Name, openlibs[i].Version)))
417                         if (openlibs[i].Version) return RETURN_FAIL;
418
419 #ifndef OS30_ONLY
420         if (UtilityBase->lib_Version >= 39)
421 #endif  /* !OS30_ONLY */
422                 UniqueID = GetUniqueID();       /* Get ID for HelpGroup and other jobs */
423
424         /* Get startup arguments */
425         XMArgs.CxPopup = TRUE;
426
427         if (WBenchMsg)
428                 err = GetWBArgs();
429         else
430                 err = GetShellArgs();
431
432         if (err) return err;
433
434         SetupLocale();
435
436         /* Create XModule library */
437         if (err = MakeXModuleLibrary ())
438                 return err;
439
440         Pool = XModuleBase->xm_Pool;
441
442
443         /* Try to load XModule preferences */
444         if (XMArgs.Settings)
445         {
446                 if (LoadPrefs (XMArgs.Settings))
447                 {
448                         UBYTE buf[FAULT_MAX];
449
450                         Fault (IoErr(), NULL, buf, FAULT_MAX);
451                         ShowMessage (MSG_ERR_LOAD, XMArgs.Settings, buf);
452                 }
453         }
454         else
455         {
456                 if (LoadPrefs ("PROGDIR:" PRGNAME ".prefs"))
457                         LoadPrefs ("ENV:" PRGNAME ".prefs");
458         }
459
460
461         /* Use startup Arguments */
462
463         if (XMArgs.PubScreen)
464                 strncpy (ScrInfo.PubScreenName, XMArgs.PubScreen, 31);
465
466         if (XMArgs.PortName)
467                 strncpy (PubPortName, XMArgs.PortName, 15);
468
469         CxPopup = XMArgs.CxPopup;
470
471         if (XMArgs.CxPopKey)
472                 strncpy (CxPopKey, XMArgs.CxPopKey, 31);
473
474         if (XMArgs.CxPriority)
475                 CxPri = *XMArgs.CxPriority;
476
477         if (XMArgs.IconX)
478                 IconX = *XMArgs.IconX;
479
480         if (XMArgs.IconY)
481                 IconY = *XMArgs.IconY;
482
483         if (XMArgs.IconName)
484                 strncpy (IconName, XMArgs.IconName, 15);
485
486         /* Setup FileRequesters if LoadPrefs() hasn't already done it */
487         if (!AslBase && !ReqToolsBase)
488                 if (err = SetupRequesters())
489                         return err;
490
491         /* Setup App Message Port */
492         SetupApp();
493
494         /* Setup Rexx Host */
495         CreateRexxPort();
496
497         /* Setup Commodity object */
498         SetupCx();
499
500         /* Add internal hooks and load external ones */
501         SetupHooks();
502
503         /* Allocate a new SongInfo structure */
504         if (!XModuleBase->xm_CurrentSong)
505         {
506                 struct SongInfo *si;
507
508                 if (si = xmCreateSong (
509                         SNGA_ReadyToUse,        TRUE,
510                         XMSNG_AddToList,        -1,
511                         XMSNG_Active,           TRUE,
512                         TAG_DONE))
513                         ReleaseSemaphore (&si->Lock);
514                 else
515                         return ERROR_NO_FREE_STORE;
516         }
517
518         /* Open screen and ToolBox window */
519         if (CxPopup)
520                 if (err = SetupScreen())
521                         return err;
522
523
524         /* Load modules requested with Shell/Workbench startup arguments */
525
526         HandleFrom();
527
528         DisposeArgs();
529
530         return 0;
531 }
532
533
534
535 static void Cleanup (LONG err)
536
537 /* Cleanup routine.  Display error message, free all resources & exit */
538 {
539         ULONG i;
540
541         if (err > 100)
542                 PrintFault (err, PrgName);
543
544         /* Free all allocated resources */
545
546         CleanupAudio();
547
548         DisposeArgs();  /* Just to be sure */
549
550         FreeFReq();
551         CloseDownScreen();
552
553         if (Pool)
554         {
555                 FreeVecPooled (Pool, ScreenAttr.ta_Name);
556                 FreeVecPooled (Pool, WindowAttr.ta_Name);
557                 FreeVecPooled (Pool, ListAttr.ta_Name);
558                 FreeVecPooled (Pool, EditorAttr.ta_Name);
559         }
560
561         /* Dispose XModule library */
562         DisposeXModuleLibrary ();
563
564         /* Remove AppIcons/AppWindows Port */
565         CleanupApp();
566
567         /* Remove Commodity Broker */
568         CleanupCx();
569
570         /* Remove ARexx port */
571         DeleteRexxPort();
572
573         CleanupLocale();
574
575         /* Close all libraries */
576         for (i = 0 ; openlibs[i].Base ; i++)
577                 /* starting with V36, NULL is a valid parameter for CloseLibrary(). */
578                 CloseLibrary (*(openlibs[i].Base));
579 }
580
581
582
583 /*!*/
584 /* Emergency patch: */
585
586 LONG SampleWinTags[1] = { 0 };
587 void UpdateSampleMenu   (void) {}