Initial commit.
[amiga/xmodule.git] / Prefs.c
1 /*
2 **      Prefs.c
3 **
4 **      Copyright (C) 1994,95,96,97 Bernardo Innocenti
5 **
6 **      Save and load preferences.
7 */
8
9
10 #include <exec/memory.h>
11 #include <prefs/prefhdr.h>
12 #include <libraries/iffparse.h>
13 #include <libraries/asl.h>
14 #include <libraries/reqtools.h>
15 #include <libraries/xmodule.h>
16
17 #include <proto/exec.h>
18 #include <proto/dos.h>
19 #include <proto/iffparse.h>
20 #include <proto/intuition.h>
21 #include <proto/asl.h>
22 #include <proto/reqtools.h>
23 #include <proto/xmodule.h>
24
25 #include "XModulePriv.h"
26 #include "Gui.h"
27
28
29
30 #define PRHD_VERS 6     /* Current version of XModule's Preferences file */
31
32 #define ID_XMPR MAKE_ID('X','M','P','R')        /* XModule PRefs                        */
33 #define ID_XMFN MAKE_ID('X','M','F','N')        /* XModule FoNts                        */
34 #define ID_XMSC MAKE_ID('X','M','S','C')        /* XModule SCreen                       */
35 #define ID_XMWN MAKE_ID('X','M','W','N')        /* XModule WiNdow                       */
36 #define ID_XMFR MAKE_ID('X','M','F','R')        /* XModule File Requester       */
37
38 /*
39  *      XModule Preferences format:
40  *
41  *      FORM PREF       Standard preferences file format
42  *      PRHD            Standard preferences chunk
43  *      XMPR            XModulePRefs
44  *      XMFN            XModuleFoNts
45  *      XMSC            XModuleSCreen
46  *      XMWN            XModuleWiNdow (appears several times, once per window)
47  *      XMFR            XModuleFileRequester (appears several times, once per requester)
48  *      EOF
49  */
50
51 struct XMPrefs
52 {
53         struct GuiSwitches              GuiSwitches;
54         struct SaveSwitches             SaveSwitches;
55         struct ClearSwitches    ClearSwitches;
56         struct OptSwitches              OptSwitches;
57         struct PattSwitches             PattSwitches;
58         UBYTE                                   SaverName[32];
59 };
60
61
62 struct XMWindow
63 {
64         LONG            WindowID;
65         BOOL            WindowOpen,
66                                 WindowZoomed;
67         struct IBox     WindowSize,
68                                 WindowZoom;
69 };
70
71 struct XMFonts
72 {
73         /* The TextAttr->ta_Name field does not point
74          * to the font name!
75          */
76         struct TextAttr ScreenAttr,
77                                         WindowAttr,
78                                         ListAttr,
79                                         EditorAttr;
80         UBYTE                   ScreenFontName[32],
81                                         WindowFontName[32],
82                                         ListFontName[32],
83                                         EditorFontName[32];
84 };
85
86
87
88 struct XMFRPrefs
89 {
90         struct IBox     FReqSize;
91         UBYTE           Dir[PATHNAME_MAX],
92                                 Pattern[PATHNAME_MAX];
93 };
94
95
96
97 /* Local function prototypes */
98
99 static LONG SaveXMWN (struct IFFHandle *iff, struct WinUserData *wud);
100 static LONG LoadXMWN (struct IFFHandle *iff);
101 static LONG SaveXMFR (struct IFFHandle *iff, struct XMFileReq *xmfr);
102 static LONG LoadXMFR (struct IFFHandle *iff, struct XMFileReq *xmfr);
103
104
105
106 GLOBALCALL LONG LoadPrefs (CONST_STRPTR filename)
107 {
108         struct IFFHandle        *iff;
109         struct ContextNode      *cn;
110         LONG                             err;
111         UWORD                            frcount = 0;
112         BOOL                             update_screen = FALSE;
113
114         static LONG stopchunks[] =
115         {
116                 ID_PREF, ID_PRHD,
117                 ID_PREF, ID_XMPR,
118                 ID_PREF, ID_XMFN,
119                 ID_PREF, ID_XMSC,
120                 ID_PREF, ID_XMWN,
121                 ID_PREF, ID_XMFR
122         };
123
124
125         if (!(iff = AllocIFF()))
126                 return ERROR_NO_FREE_STORE;
127
128         if (!(iff->iff_Stream = (ULONG) Open (filename, MODE_OLDFILE)))
129         {
130                 err = IoErr();
131                 goto error1;
132         }
133
134         InitIFFasDOS (iff);
135
136         if (err = OpenIFF (iff, IFFF_READ))
137                 goto error2;
138
139         if (err = StopChunks (iff, stopchunks, 6))
140                 goto error3;
141
142         while (1)
143         {
144                 if (err = ParseIFF (iff, IFFPARSE_SCAN))
145                 {
146                         if (err == IFFERR_EOC) continue;
147                         else
148                         {
149                                 if (err == IFFERR_EOF) err = 0;
150                                 break; /* Free resources & exit */
151                         }
152                 }
153
154                 if ((cn = CurrentChunk (iff)) && (cn->cn_Type == ID_PREF))
155                 {
156                         switch (cn->cn_ID)
157                         {
158                                 case ID_PRHD:
159                                 {
160                                         struct PrefHeader prhd;
161
162                                         if ((err = ReadChunkBytes (iff, &prhd, sizeof (prhd))) !=
163                                                 sizeof (prhd)) goto error3;
164
165                                         if (prhd.ph_Version != PRHD_VERS)
166                                         {
167                                                 ShowRequestArgs (MSG_BAD_PREFS_VERSION, 0, NULL);
168                                                 goto error3;
169                                         }
170
171                                         break;
172                                 }
173
174                                 case ID_XMPR:
175                                 {
176                                         struct XMPrefs xmpr;
177
178                                         if ((err = ReadChunkBytes (iff, &xmpr, sizeof (xmpr))) !=
179                                                 sizeof (xmpr)) goto error3;
180
181                                         memcpy (&GuiSwitches, &xmpr.GuiSwitches, sizeof (GuiSwitches));
182                                         memcpy (&SaveSwitches, &xmpr.SaveSwitches, sizeof (SaveSwitches));
183                                         memcpy (&ClearSwitches, &xmpr.ClearSwitches, sizeof (ClearSwitches));
184                                         memcpy (&OptSwitches, &xmpr.OptSwitches, sizeof (OptSwitches));
185                                         memcpy (&PattSwitches, &xmpr.PattSwitches, sizeof (PattSwitches));
186
187                                         {
188                                                 struct XMHook *saver;
189
190                                                 /* FIXME: move this code in a private library
191                                                  * function such as SetDefaultSaver()
192                                                  */
193                                                 ObtainSemaphore (&XModuleBase->xm_BaseLock);
194                                                 if (saver = (struct XMHook *)FindName (
195                                                         (struct List *)&XModuleBase->xm_Savers, xmpr.SaverName))
196                                                         XModuleBase->xm_DefaultSaver = saver;
197                                                 ReleaseSemaphore (&XModuleBase->xm_BaseLock);
198                                         }
199
200                                         UpdateGuiSwitches ();
201                                         UpdateInstrSwitches ();
202                                         UpdateSaveSwitches ();
203                                         UpdateClearSwitches ();
204                                         UpdateOptSwitches ();
205                                         UpdateSampleMenu ();
206                                         UpdatePattPrefs ();
207
208                                         break;
209                                 }
210
211                                 case ID_XMFN:
212                                 {
213                                         struct XMFonts xmfn;
214
215                                         if ((err = ReadChunkBytes (iff, &xmfn, sizeof (xmfn))) !=
216                                                 sizeof (xmfn)) goto error3;
217
218                                         xmfn.ScreenAttr.ta_Name = xmfn.ScreenFontName;
219                                         xmfn.WindowAttr.ta_Name = xmfn.WindowFontName;
220                                         xmfn.ListAttr.ta_Name   = xmfn.ListFontName;
221                                         xmfn.EditorAttr.ta_Name = xmfn.EditorFontName;
222
223                                         if (CmpTextAttr (&xmfn.ScreenAttr, &ScreenAttr) ||
224                                                 CmpTextAttr (&xmfn.WindowAttr, &WindowAttr) ||
225                                                 CmpTextAttr (&xmfn.ListAttr,   &ListAttr)   ||
226                                                 CmpTextAttr (&xmfn.EditorAttr, &EditorAttr))
227                                         {
228                                                 CopyTextAttrPooled (Pool, &xmfn.ScreenAttr, &ScreenAttr);
229                                                 CopyTextAttrPooled (Pool, &xmfn.WindowAttr, &WindowAttr);
230                                                 CopyTextAttrPooled (Pool, &xmfn.ListAttr,   &ListAttr);
231                                                 CopyTextAttrPooled (Pool, &xmfn.EditorAttr, &EditorAttr);
232                                                 update_screen = TRUE;
233                                         }
234
235                                         break;
236                                 }
237
238                                 case ID_XMSC:
239                                 {
240                                         struct ScrInfo newscrinfo;
241
242                                         if ((err = ReadChunkBytes (iff, &newscrinfo, sizeof (newscrinfo))) !=
243                                                 sizeof (newscrinfo)) goto error3;
244
245                                         if (memcmp (&ScrInfo, &newscrinfo, sizeof (ScrInfo)))
246                                         {
247                                                 if (Scr)
248                                                 {
249                                                         CloseDownScreen();
250                                                         update_screen = TRUE;
251                                                 }
252
253                                                 memcpy (&ScrInfo, &newscrinfo, sizeof (ScrInfo));
254                                         }
255
256                                         break;
257                                 }
258
259                                 case ID_XMWN:
260                                         if (err = LoadXMWN (iff))
261                                                 goto error3;
262                                         break;
263
264                                 case ID_XMFR:
265                                         if (frcount < FREQ_COUNT)
266                                         {
267                                                 if (err = LoadXMFR (iff, &FileReqs[frcount]))
268                                                         goto error3;
269                                                 frcount++;
270                                         }
271                                         break;
272
273                                 default:
274                                         break;
275                         }
276                 }
277         }
278
279 error3:
280         CloseIFF (iff);
281 error2:
282         Close (iff->iff_Stream);
283 error1:
284         FreeIFF (iff);
285
286         if (Scr)
287         {
288                 if (update_screen)
289                         err = SetupScreen();
290                 else ReopenWindows();
291         }
292
293         return err;
294 }
295
296
297
298 GLOBALCALL LONG SavePrefs (CONST_STRPTR filename)
299 {
300         struct IFFHandle *iff;
301         LONG err;
302
303         if (!(iff = AllocIFF()))
304                 return ERROR_NO_FREE_STORE;
305
306         if (!(iff->iff_Stream = (ULONG) Open (filename, MODE_NEWFILE)))
307         {
308                 err = IoErr();
309                 goto error1;
310         }
311
312         InitIFFasDOS (iff);
313
314         if (err = OpenIFF (iff, IFFF_WRITE))
315                 goto error2;
316
317
318         /* Write PREF */
319
320         if (err = PushChunk (iff, ID_PREF, ID_FORM, IFFSIZE_UNKNOWN))
321                 goto error3;
322
323         /* Store PRHD chunk */
324         {
325                 struct PrefHeader prhd = {PRHD_VERS, 0, 0};
326
327                 if (err = PushChunk (iff, 0, ID_PRHD, sizeof (struct PrefHeader)))
328                         goto error3;
329
330                 if ((err = WriteChunkBytes (iff, &prhd, sizeof (struct PrefHeader))) !=
331                         sizeof (struct PrefHeader))
332                         goto error3;
333
334                 if (err = PopChunk (iff))
335                         goto error3;
336         }
337
338         /* Store XMPR Chunk */
339         {
340                 struct XMPrefs xmpr;
341
342                 memcpy (&xmpr.GuiSwitches, &GuiSwitches, sizeof (GuiSwitches));
343                 memcpy (&xmpr.SaveSwitches, &SaveSwitches, sizeof (SaveSwitches));
344                 memcpy (&xmpr.ClearSwitches, &ClearSwitches, sizeof (ClearSwitches));
345                 memcpy (&xmpr.OptSwitches, &OptSwitches, sizeof (OptSwitches));
346                 memcpy (&xmpr.PattSwitches, &PattSwitches, sizeof (PattSwitches));
347
348                 ObtainSemaphoreShared (&XModuleBase->xm_BaseLock);
349                 if (XModuleBase->xm_DefaultSaver)
350                         strncpy (xmpr.SaverName, XModuleBase->xm_DefaultSaver->xmh_Link.ln_Name, 32);
351                 else
352                         xmpr.SaverName[0] = '\0';
353                 ReleaseSemaphore (&XModuleBase->xm_BaseLock);
354
355
356                 if (err = PushChunk (iff, 0, ID_XMPR, sizeof (xmpr)))
357                         goto error3;
358
359                 if ((err = WriteChunkBytes (iff, &xmpr, sizeof (xmpr))) !=
360                         sizeof (xmpr))
361                         goto error3;
362
363                 if (err = PopChunk (iff))
364                         goto error3;
365         }
366
367
368         /* Store XMFN chunk */
369         {
370                 struct XMFonts xmfn;
371
372                 if (err = PushChunk (iff, 0, ID_XMFN, sizeof (xmfn)))
373                         goto error3;
374
375                 xmfn.ScreenAttr = ScreenAttr;
376                 xmfn.WindowAttr = WindowAttr;
377                 xmfn.ListAttr   = ListAttr;
378                 xmfn.EditorAttr = EditorAttr;
379
380                 if (ScreenAttr.ta_Name)
381                         strncpy (xmfn.ScreenFontName,   ScreenAttr.ta_Name,     32);
382                 if (WindowAttr.ta_Name)
383                         strncpy (xmfn.WindowFontName,   WindowAttr.ta_Name,     32);
384                 if (ListAttr.ta_Name)
385                         strncpy (xmfn.ListFontName,             ListAttr.ta_Name,       32);
386                 if (EditorAttr.ta_Name)
387                         strncpy (xmfn.EditorFontName,   EditorAttr.ta_Name,     32);
388
389                 if ((err = WriteChunkBytes (iff, &xmfn, sizeof (xmfn))) !=
390                         sizeof (xmfn))
391                         goto error3;
392
393                 if (err = PopChunk (iff))
394                         goto error3;
395         }
396
397         /* Store XMSC Chunk */
398         {
399                 if (err = PushChunk (iff, 0, ID_XMSC, sizeof (ScrInfo)))
400                         goto error3;
401
402                 if ((err = WriteChunkBytes (iff, &ScrInfo, sizeof (ScrInfo))) !=
403                         sizeof (ScrInfo))
404                         goto error3;
405
406                 if (err = PopChunk (iff))
407                         goto error3;
408         }
409
410
411         /* Store XMWN Chunks */
412         {
413                 struct WinUserData *wud;
414
415                 for (wud = (struct WinUserData *) WindowList.lh_Head;
416                         wud->Link.mln_Succ;
417                         wud = (struct WinUserData *)wud->Link.mln_Succ)
418                 {
419                         if (err = SaveXMWN (iff, wud))
420                                 goto error3;
421                 }
422         }
423
424
425         /* Store XMFR Chunks */
426         {
427                 ULONG i;
428
429                 for (i = 0; i < FREQ_COUNT; i++)
430                         SaveXMFR (iff, &FileReqs[i]);
431         }
432
433         err = PopChunk (iff);   /* Pop PREF */
434
435 error3:
436         CloseIFF (iff);
437
438 error2:
439         Close (iff->iff_Stream);
440
441 error1:
442         FreeIFF (iff);
443
444         return err;
445 }
446
447
448
449 static LONG LoadXMWN (struct IFFHandle *iff)
450 {
451         LONG err;
452         struct XMWindow xmwn;
453         struct WinUserData *wud;
454         struct Window *win;
455
456         if ((err = ReadChunkBytes (iff, &xmwn, sizeof (xmwn))) != sizeof (xmwn))
457                 return err;
458
459         if (xmwn.WindowID >= WID_COUNT) return RETURN_OK;
460
461         if (!(wud = WDescr[xmwn.WindowID].Wud))
462                 if (!(wud = CreateWUD (xmwn.WindowID)))
463                         return ERROR_NO_FREE_STORE;
464
465         win = wud->Win;
466
467         if (!win)
468                 wud->WUDFlags |= xmwn.WindowOpen ? WUDF_REOPENME : 0;   /* Open this window later */
469         else if (!xmwn.WindowOpen)
470                 MyCloseWindow (wud);            /* Close this window now */
471
472
473         memcpy (&wud->WindowSize, &xmwn.WindowSize, sizeof (struct IBox));
474         memcpy (&wud->WindowZoom, &xmwn.WindowZoom, sizeof (struct IBox));
475
476 //      wud->WindowSize.Left    = xmwn.WindowSize.Left;
477 //      wud->WindowSize.Top             = xmwn.WindowSize.Top;
478 //      wud->WindowZoom.Left    = xmwn.WindowSize.Left;
479 //      wud->WindowZoom.Top             = xmwn.WindowZoom.Top;
480
481 //      if (wud->Flags & WFLG_SIZEGADGET)
482 //      {
483 //              wud->WindowSize.Width   = xmwn.WindowSize.Width;
484 //              wud->WindowSize.Height  = xmwn.WindowSize.Height;
485 //              wud->WindowZoom.Left    = xmwn.WindowSize.Width;
486 //              wud->WindowZoom.Height  = xmwn.WindowZoom.Height;
487 //      }
488
489         if (win)
490         {
491                 if (xmwn.WindowZoomed)
492                 {
493                         if (!(win->Flags & WFLG_ZOOMED)) ZipWindow (win);
494                         ChangeWindowBox (win, wud->WindowZoom.Left, wud->WindowZoom.Top,
495                                 win->Width, win->Height);
496                 }
497                 else
498                 {
499                         if (win->Flags & WFLG_ZOOMED) ZipWindow (win);
500                         ChangeWindowBox (win, wud->WindowSize.Left, wud->WindowSize.Top,
501                                 win->Width, win->Height);
502                 }
503         }
504
505         return RETURN_OK;
506 }
507
508
509
510 static LONG SaveXMWN (struct IFFHandle *iff, struct WinUserData *wud)
511 {
512         LONG err;
513         struct XMWindow xmwn;
514         struct Window *win = wud->Win;
515
516         if (err = PushChunk (iff, 0, ID_XMWN, sizeof (xmwn)))
517                 return err;
518
519         xmwn.WindowID = wud->WindowID;
520
521         memcpy (&xmwn.WindowSize, &wud->WindowSize, sizeof (struct IBox));
522         memcpy (&xmwn.WindowZoom, &wud->WindowZoom, sizeof (struct IBox));
523
524         if (win)
525         {
526                 if (win->Flags == WFLG_ZOOMED)
527                 {
528                         memcpy (&xmwn.WindowZoom, &win->LeftEdge, sizeof (struct IBox));
529                         xmwn.WindowZoom.Width   -= win->BorderLeft + win->BorderRight;
530                         xmwn.WindowZoom.Height  -= win->BorderTop + win->BorderBottom;
531                 }
532                 else
533                 {
534                         memcpy (&xmwn.WindowSize, &win->LeftEdge, sizeof (struct IBox));
535                         xmwn.WindowSize.Width -= win->BorderLeft + win->BorderRight;
536                         xmwn.WindowSize.Height -= win->BorderTop + win->BorderBottom;
537                 }
538         }
539
540         xmwn.WindowOpen = win ? TRUE : FALSE;
541         xmwn.WindowZoomed = win ? (win->Flags & WFLG_ZOOMED) : FALSE;
542
543         if ((err = WriteChunkBytes (iff, &xmwn, sizeof (xmwn))) != sizeof (xmwn))
544                 return err;
545
546         if (err = PopChunk (iff))
547                 return err;
548
549         return RETURN_OK;
550 }
551
552
553
554 static LONG LoadXMFR (struct IFFHandle *iff, struct XMFileReq *xmfr)
555 {
556         LONG err;
557         struct XMFRPrefs xmfrp;
558
559         if (!ReqToolsBase && !AslBase)
560                 SetupRequesters();
561
562         if (!xmfr->FReq) return RETURN_FAIL;
563
564         if ((err = ReadChunkBytes (iff, &xmfrp, sizeof (xmfrp))) != sizeof (xmfrp))
565                 return err;
566
567         if (ReqToolsBase)
568         {
569                 rtChangeReqAttr (xmfr->FReq,
570                         RT_TopOffset,   xmfrp.FReqSize.Top,
571                         RT_LeftOffset,  xmfrp.FReqSize.Left,
572                         RTFI_Height,    xmfrp.FReqSize.Height,
573                         /* Width not available in ReqTools */
574                         RTFI_Dir,               xmfrp.Dir,
575                         RTFI_MatchPat,  xmfrp.Pattern,
576                         TAG_DONE);
577         }
578         else if (AslBase)
579         {
580                 struct FileRequester *fr;
581
582                 if (!(fr = AllocAslRequestTags (ASL_FileRequest,
583                         (xmfr->Title == -1) ? TAG_IGNORE : ASLFR_TitleText, (xmfr->Title == -1) ? NULL : STR(xmfr->Title),
584                         ASLFR_Flags1,                   xmfr->Flags | FRF_PRIVATEIDCMP,
585                         ASLFR_Flags2,                   FRF_REJECTICONS,
586                         ASLFR_InitialLeftEdge,  xmfrp.FReqSize.Left,
587                         ASLFR_InitialTopEdge,   xmfrp.FReqSize.Top,
588                         ASLFR_InitialWidth,             xmfrp.FReqSize.Width,
589                         ASLFR_InitialHeight,    xmfrp.FReqSize.Height,
590                         ASLFR_InitialDrawer,    xmfrp.Dir,
591                         ASLFR_InitialPattern,   xmfrp.Pattern,
592                         TAG_DONE)))
593                         return RETURN_FAIL;
594
595                 FreeAslRequest (xmfr->FReq);
596                 xmfr->FReq = fr;
597         }
598
599         return RETURN_OK;
600 }
601
602
603
604 static LONG SaveXMFR (struct IFFHandle *iff, struct XMFileReq *xmfr)
605 {
606         LONG err;
607         struct XMFRPrefs xmfrp = { 0 };
608
609         if (err = PushChunk (iff, 0, ID_XMFR, sizeof (xmfrp)))
610                 return err;
611
612         if (xmfr->FReq)
613         {
614                 if (AslBase)
615                 {
616                         struct FileRequester *fr = (struct FileRequester *)xmfr->FReq;
617
618                         xmfrp.FReqSize.Left             = fr->fr_LeftEdge;
619                         xmfrp.FReqSize.Top              = fr->fr_TopEdge;
620                         xmfrp.FReqSize.Width    = fr->fr_Width;
621                         xmfrp.FReqSize.Height   = fr->fr_Height;
622                         strncpy (xmfrp.Dir, fr->fr_Drawer, PATHNAME_MAX);
623                         strncpy (xmfrp.Pattern, fr->fr_Pattern, PATHNAME_MAX);
624                 }
625                 else if (ReqToolsBase)
626                 {
627                         struct rtFileRequester *fr = (struct rtFileRequester *)xmfr->FReq;
628
629                         xmfrp.FReqSize.Left             = fr->LeftOffset;
630                         xmfrp.FReqSize.Top              = fr->TopOffset;
631                         xmfrp.FReqSize.Width    = 0;    /* Width not available in ReqTools */
632                         xmfrp.FReqSize.Height   = fr->ReqHeight;
633                         strncpy (xmfrp.Dir, fr->Dir, PATHNAME_MAX);
634                         strncpy (xmfrp.Pattern, fr->MatchPat, PATHNAME_MAX);
635                 }
636         }
637
638         if ((err = WriteChunkBytes (iff, &xmfrp, sizeof (xmfrp))) != sizeof (xmfrp))
639                 return err;
640
641         if (err = PopChunk (iff)) /* Pop XMFR */
642                 return err;
643
644         return RETURN_OK;
645 }