4 ** Copyright (C) 1994,95,96,97 Bernardo Innocenti
6 ** Handle asyncronous file requester
9 #include <exec/memory.h>
10 #include <libraries/asl.h>
11 #include <libraries/reqtools.h>
12 #include <dos/dostags.h>
14 #include <proto/exec.h>
15 #include <proto/dos.h>
16 #include <proto/graphics.h>
17 #include <proto/intuition.h>
18 #include <proto/asl.h>
19 #include <proto/reqtools.h>
22 #include "XModulePriv.h"
27 /* Local function prototypes */
28 static LONG CheckOverwrite (CONST_STRPTR path);
32 /* This structure is used for passing parameters to
33 * the requester process and to get the result back.
37 struct Message ExecMsg;
38 struct XMFileReq *XMFReq; /* XMFileReq structure to use */
40 /* User call back function which does something with the file name.
41 * If the user picked multiple files, the user function will be called
42 * once on each selection. The user function can tell which entry is
43 * being processed examining the <num> and <count> arguments.
45 void (*Func)(STRPTR file, ULONG num, ULONG count);
46 APTR Result; /* Replied by FileRequester process */
47 UBYTE PathName[PATHNAME_MAX]; /* Replied by FileRequester process */
52 XDEF struct XMFileReq FileReqs[FREQ_COUNT] =
54 { NULL, MSG_SELECT_MODULES, FRF_DOMULTISELECT | FRF_DOPATTERNS },
55 { NULL, MSG_SAVE_MODULE, FRF_DOSAVEMODE | FRF_DOPATTERNS },
56 { NULL, MSG_SELECT_INSTRUMENTS, FRF_DOMULTISELECT | FRF_DOPATTERNS },
57 { NULL, MSG_SAVE_INSTRUMENT, FRF_DOSAVEMODE | FRF_DOPATTERNS },
58 { NULL, MSG_SELECT_PATTERN, FRF_DOPATTERNS },
59 { NULL, MSG_SAVE_PATTERN, FRF_DOSAVEMODE | FRF_DOPATTERNS },
60 { NULL, 0, FRF_DOPATTERNS },
61 { NULL, 0, FRF_DOSAVEMODE | FRF_DOPATTERNS },
65 static APTR FontReq = NULL;
66 static struct Process *FileReqTask = NULL;
67 static struct MsgPort *FileReqPort = NULL;
68 XDEF ULONG FileReqSig;
73 /* This function is a process that puts out
74 * an asyncronous ASL FileRequester.
76 HOOKCALL static void AslRequestProc (void)
78 struct MsgPort *prMsgPort = &(((struct Process *)FindTask (NULL))->pr_MsgPort);
79 struct FileReqMsg *frmsg;
80 struct XMFileReq *xmfr;
82 /* Wait startup packet */
84 frmsg = (struct FileReqMsg *)GetMsg (prMsgPort);
88 if (AslRequestTags (xmfr->FReq,
89 ASLFR_Window, ThisTask->pr_WindowPtr,
93 strncpy (frmsg->PathName,
94 ((struct FileRequester *)xmfr->FReq)->fr_Drawer, PATHNAME_MAX);
95 AddPart (frmsg->PathName,
96 ((struct FileRequester *)xmfr->FReq)->fr_File, PATHNAME_MAX);
97 frmsg->Result = frmsg->PathName;
100 /* Signal that we are done.
101 * We forbid here to avoid beeing unloaded until exit.
104 ReplyMsg ((struct Message *)frmsg);
109 /* This function is a process that puts out
110 * an asyncronous ReqTools FileRequester.
112 HOOKCALL static void RtRequestProc (void)
114 struct MsgPort *prMsgPort = &(((struct Process *)FindTask(NULL))->pr_MsgPort);
115 struct FileReqMsg *frmsg;
116 struct XMFileReq *xmfr;
118 UBYTE filename[PATHNAME_MAX];
122 /* Wait startup packet */
123 WaitPort (prMsgPort);
124 frmsg = (struct FileReqMsg *)GetMsg (prMsgPort);
125 xmfr = frmsg->XMFReq;
127 if (xmfr->Flags & FRF_DOSAVEMODE) flags |= FREQF_SAVE;
128 if (xmfr->Flags & FRF_DOPATTERNS) flags |= FREQF_PATGAD;
129 if (xmfr->Flags & FRF_DOMULTISELECT) flags |= FREQF_MULTISELECT;
131 if (!(frmsg->Result = rtFileRequest (xmfr->FReq, filename, STR(xmfr->Title),
132 RT_ShareIDCMP, FALSE,
133 RT_Window, ThisTask->pr_WindowPtr,
138 /* Build file path */
139 strncpy (frmsg->PathName, ((struct rtFileRequester *)xmfr->FReq)->Dir,
141 AddPart (frmsg->PathName, filename, PATHNAME_MAX);
143 if (!(xmfr->Flags & FRF_DOMULTISELECT)) frmsg->Result = frmsg->PathName;
146 /* Signal that we are done.
147 * We forbid here to avoid beeing unloaded until exit.
150 ReplyMsg ((struct Message *)frmsg);
155 GLOBALCALL LONG StartFileRequest (ULONG freq, void (*func)(STRPTR file, ULONG num, ULONG count))
157 /* Spawns a process that opens a FileRequester.
158 * Do not touch freq until the child process returns!
161 * freq - Pointer to an ASL or ReqTools FileRequester
162 * func - Pointer to a function to call when FileRequester returns
166 * err - 0 if OK, IOErr()-style error otherwise.
169 struct FileReqMsg *frmsg;
171 /* Do not spawn more than one file requester process at a time */
178 if (!(frmsg = AllocMem (sizeof (struct FileReqMsg), MEMF_PUBLIC)))
179 return ERROR_NO_FREE_STORE;
181 if (!(FileReqTask = CreateNewProcTags (
182 NP_Entry, (ReqToolsBase ? RtRequestProc : AslRequestProc),
183 NP_Name, PRGNAME " FileRequester",
187 FreeMem (frmsg, sizeof (struct FileReqMsg));
188 return ERROR_NO_FREE_STORE;
191 /* Now setup & send FReqMsg */
192 frmsg->ExecMsg.mn_ReplyPort = FileReqPort;
193 frmsg->XMFReq = &FileReqs[freq];
195 PutMsg (&(FileReqTask->pr_MsgPort), (struct Message *)frmsg);
202 GLOBALCALL void HandleFileRequest (void)
204 struct FileReqMsg *frmsg;
205 struct XMFileReq *xmfr;
207 if (!(frmsg = (struct FileReqMsg *)GetMsg (FileReqPort)))
210 xmfr = frmsg->XMFReq;
212 FileReqTask = NULL; /* The FileRequest Process is now gone. */
216 if (xmfr->Flags & FRF_DOMULTISELECT)
220 struct FileRequester *fr = xmfr->FReq;
221 UBYTE Name[PATHNAME_MAX];
224 for (i = 0; i < fr->fr_NumArgs; i++)
226 if (NameFromLock (fr->fr_ArgList[i].wa_Lock, Name, PATHNAME_MAX))
227 if (AddPart (Name, fr->fr_ArgList[i].wa_Name, PATHNAME_MAX))
228 frmsg->Func (Name, i, fr->fr_NumArgs);
231 else if (ReqToolsBase)
233 struct rtFileList *fl;
234 UBYTE Name[PATHNAME_MAX];
235 ULONG num_entries = 0, i = 0;
237 /* Calculate number of entries in FileList */
238 fl = (struct rtFileList *)frmsg->Result;
245 fl = (struct rtFileList *)frmsg->Result;
248 strncpy (Name, ((struct rtFileRequester *)xmfr->FReq)->Dir, PATHNAME_MAX);
249 AddPart (Name, fl->Name, PATHNAME_MAX);
250 frmsg->Func (Name, i++, num_entries);
254 rtFreeFileList (frmsg->Result); /* Free multiselect buffer */
259 frmsg->Func (frmsg->Result, 0, 1);
262 FreeMem (frmsg, sizeof (struct FileReqMsg)); /* Free FileReqMsg */
267 GLOBALCALL STRPTR FileRequest (ULONG freq, STRPTR file)
269 /* Puts up a simple FileRequester to ask the user for a filename.
270 * If the requester is in save mode, will optionally check for
271 * overwrite and ask the user to confirm.
274 STRPTR retval = NULL;
275 struct XMFileReq *xmfr = &FileReqs[freq];
278 if (!xmfr->FReq) return NULL;
288 if (AslRequestTags (xmfr->FReq,
289 ASLFR_Window, ThisTask->pr_WindowPtr,
290 ASLFR_InitialFile, FilePart (file),
293 /* Build file path */
294 strncpy (file, ((struct FileRequester *)xmfr->FReq)->fr_Drawer,
296 AddPart (file, ((struct FileRequester *)xmfr->FReq)->fr_File,
302 else if (ReqToolsBase)
304 UBYTE filename[PATHNAME_MAX];
308 strncpy (filename, FilePart (file), PATHNAME_MAX);
310 if (xmfr->Flags & FRF_DOSAVEMODE) flags |= FREQF_SAVE;
311 if (xmfr->Flags & FRF_DOPATTERNS) flags |= FREQF_PATGAD;
312 if (xmfr->Flags & FRF_DOMULTISELECT) flags |= FREQF_MULTISELECT;
314 if (rtFileRequest (xmfr->FReq, filename, (xmfr->Title == -1) ? NULL : STR(xmfr->Title),
319 /* Build file path */
320 strncpy (file, ((struct rtFileRequester *)(xmfr->FReq))->Dir, PATHNAME_MAX);
321 AddPart (file, filename, PATHNAME_MAX);
328 if (retval && (xmfr->Flags & FRF_DOSAVEMODE))
330 switch (CheckOverwrite (retval))
335 case 2: /* Choose Another */
354 static LONG CheckOverwrite (CONST_STRPTR path)
356 /* Checks if the given file already exists and
357 * kindly asks the user if he knows what he's doing.
362 * 2 - Open the requester again
365 if (GuiSwitches.AskOverwrite)
369 if (fh = Open (path, MODE_OLDFILE))
373 return ShowRequest (MSG_FILE_EXISTS, MSG_OVERWRITE, FilePart (path));
382 GLOBALCALL LONG ShowRequestStr (CONST_STRPTR text, CONST_STRPTR gtext, APTR args)
384 /* Simple N-way requester function. Passing NULL as <gtext>
385 * will put a single "Ok" button. Will fall to a Printf()
386 * when IntuitionBase is NULL.
392 if (!gtext) gtext = STR(MSG_OK);
394 if (!ShowRequesters) return 1;
400 /* This silly thing gets around a nasty SAS/C 6.56 bug which
401 * causes a CXERR (and generates wrong code) when making a
402 * libcall with a parameter in A4.
404 volatile APTR rtargs = args;
409 RT_ShareIDCMP, FALSE,
413 tags[1] = (LONG)STR(MSG_XMODULE_REQUEST);
415 ret = rtEZRequestA (text, gtext, NULL, rtargs, (struct TagItem *)tags);
417 else if (IntuitionBase)
419 static struct EasyStruct es =
421 sizeof (struct EasyStruct),
428 es.es_Title = STR(MSG_XMODULE_REQUEST);
429 es.es_TextFormat = (STRPTR)text;
430 es.es_GadgetFormat = (STRPTR)gtext;
431 ret = EasyRequestArgs (ThisTask->pr_WindowPtr, &es, NULL, args);
435 VPrintf (text, args);
436 FPutC (StdOut, (LONG)'\n');
447 GLOBALCALL LONG ShowRequestArgs (ULONG msg, ULONG gadgets, APTR args)
449 /* Localized interface to ShowRequestStr(). The <msg> and
450 * <gadgets> arguments are any MSG_#? from Locale.h.
453 return ShowRequestStr (STR(msg), STR(gadgets), args);
458 GLOBALCALL LONG ShowRequest (ULONG msg, ULONG gadgets, ...)
460 /* Localized, Variable arguments stub for ShowRequestStr()
461 * The <msg> and <gadgets> arguments are any MSG_#? from Locale.h.
464 return ShowRequestStr (STR(msg), STR(gadgets), (APTR)(((LONG *)(&gadgets))+1));
469 GLOBALCALL LONG ScrModeRequest (struct ScrInfo *scrinfo)
471 /* Let user choose a new screen mode and store mode attributes in the ScrInfo
474 * Returns: TRUE for success, FALSE for failure.
477 BOOL ChangeScreen = FALSE;
479 if (AslBase && AslBase->lib_Version >= 38) /* ASL */
481 struct ScreenModeRequester *ScrModeReq;
482 struct List customsmlist;
483 struct DisplayMode clonemode;
486 /* Setup custom screen mode for Workbench cloning */
488 memset (&clonemode, 0, sizeof (clonemode));
490 clonemode.dm_Node.ln_Name = STR(MSG_CLONE_WB);
491 clonemode.dm_DimensionInfo.Header.StructID = DTAG_DIMS;
492 clonemode.dm_DimensionInfo.Header.DisplayID = 0xFFFFFFFF;
493 clonemode.dm_DimensionInfo.Header.SkipID = TAG_SKIP;
494 clonemode.dm_DimensionInfo.Header.Length = (sizeof (struct DimensionInfo) - sizeof (struct QueryHeader)) / 2;
495 clonemode.dm_PropertyFlags = DIPF_IS_WB;
497 NEWLIST (&customsmlist);
498 ADDHEAD (&customsmlist, (struct Node *)&clonemode);
501 if (ScrModeReq = AllocAslRequest (ASL_ScreenModeRequest, NULL))
505 if (AslRequestTags (ScrModeReq,
506 ASLSM_Window, ThisTask->pr_WindowPtr,
508 ASLSM_DoHeight, TRUE,
510 ASLSM_DoOverscanType, TRUE,
511 ASLSM_DoAutoScroll, TRUE,
512 ASLSM_InitialDisplayID, GetVPModeID (&Scr->ViewPort),
513 ASLSM_InitialDisplayWidth, Scr->Width,
514 ASLSM_InitialDisplayHeight, Scr->Height,
515 ASLSM_InitialDisplayDepth, DrawInfo->dri_Depth,
516 ASLSM_InitialAutoScroll, Scr->Flags & AUTOSCROLL,
517 ASLSM_InitialOverscanType, scrinfo->OverscanType,
519 ASLSM_MinHeight, 200,
520 ASLSM_CustomSMList, &customsmlist,
523 if (ScrModeReq->sm_DisplayID == 0xFFFFFFFF)
524 scrinfo->DisplayID = 0; /* Picked special clone WB mode */
527 scrinfo->DisplayID = ScrModeReq->sm_DisplayID;
528 scrinfo->Width = ScrModeReq->sm_DisplayWidth;
529 scrinfo->Height = ScrModeReq->sm_DisplayHeight;
530 scrinfo->Depth = ScrModeReq->sm_DisplayDepth;
531 scrinfo->OverscanType = ScrModeReq->sm_OverscanType;
532 scrinfo->AutoScroll = ScrModeReq->sm_AutoScroll;
537 FreeAslRequest (ScrModeReq);
543 struct rtScreenModeRequester *ScrModeReq;
544 BOOL CloseReqTools = FALSE;
548 if (!(ReqToolsBase = (struct ReqToolsBase *)
549 OpenLibrary ("reqtools.library", 38)))
551 CantOpenLib ("reqtools.library", 38);
554 CloseReqTools = TRUE;
557 if (ScrModeReq = rtAllocRequestA (RT_SCREENMODEREQ, NULL))
561 if (rtScreenModeRequest (ScrModeReq, NULL,
562 RTSC_Flags, SCREQF_OVERSCANGAD | SCREQF_AUTOSCROLLGAD |
563 SCREQF_SIZEGADS | SCREQF_DEPTHGAD | SCREQF_GUIMODES,
567 scrinfo->DisplayID = ScrModeReq->DisplayID;
568 scrinfo->Width = ScrModeReq->DisplayWidth;
569 scrinfo->Height = ScrModeReq->DisplayHeight;
570 scrinfo->Depth = ScrModeReq->DisplayDepth;
571 scrinfo->OverscanType = ScrModeReq->OverscanType;
572 scrinfo->AutoScroll = ScrModeReq->AutoScroll;
576 rtFreeRequest (ScrModeReq);
582 CloseLibrary ((struct Library *)ReqToolsBase);
592 GLOBALCALL LONG FontRequest (struct TextAttr *ta, ULONG flags)
594 /* Requests a font to the user and copies the selected font to the
595 * passed TextAttr structure. The ta_Name field is allocated with
596 * AllocVec() and the font name is copied to it.
598 * Returns: FALSE for failure, anything else for success.
601 struct TextAttr *result = NULL;
607 if (AslRequestTags (FontReq,
608 ASLFO_Window, ThisTask->pr_WindowPtr,
609 ASLFO_Flags, FOF_DOSTYLE | flags,
611 result = &((struct FontRequester *)FontReq)->fo_Attr;
613 else if (ReqToolsBase)
615 if (rtFontRequest (FontReq, NULL,
617 RTFO_Flags, FREQF_SCALE | FREQF_STYLE | ((flags & FOF_FIXEDWIDTHONLY) ? FREQF_FIXEDWIDTH : 0),
619 result = &((struct rtFontRequester *)FontReq)->Attr;
623 if (result) CopyTextAttrPooled (Pool, result, ta);
627 return result != NULL;
632 GLOBALCALL void FreeFReq (void)
636 /* Terminate async requester */
639 while (!(SetSignal (0L, FileReqSig) & FileReqSig))
640 ShowRequest (MSG_CLOSE_FILEREQUESTER, MSG_CONTINUE, NULL);
647 struct FileReqMsg *frmsg = (struct FileReqMsg *) GetMsg (FileReqPort);
651 if ((frmsg->XMFReq->Flags & FRF_DOMULTISELECT) && ReqToolsBase)
652 rtFreeFileList (frmsg->Result);
653 FreeMem (frmsg, sizeof (struct FileReqMsg));
656 DeleteMsgPort (FileReqPort); FileReqPort = NULL;
657 Signals &= ~FileReqSig;
662 for (i = 0; i < FREQ_COUNT; i++)
664 FreeAslRequest (FileReqs[i].FReq);
665 FileReqs[i].FReq = NULL;
668 FreeAslRequest (FontReq); FontReq = NULL;
669 CloseLibrary (AslBase); AslBase = NULL;
674 for (i = 0; i < FREQ_COUNT; i++)
676 rtFreeRequest (FileReqs[i].FReq);
677 FileReqs[i].FReq = NULL;
680 rtFreeRequest (FontReq); FontReq = NULL;
681 CloseLibrary ((struct Library *)ReqToolsBase); ReqToolsBase = NULL;
687 GLOBALCALL LONG SetupAsl (void)
690 struct XMFileReq *xmfr;
694 if (!(AslBase = OpenLibrary ("asl.library", 37)))
696 CantOpenLib ("asl.library", 37);
701 for (i = 0; i < FREQ_COUNT; i++)
705 if (!(xmfr->FReq = AllocAslRequestTags (ASL_FileRequest,
706 (xmfr->Title == -1) ? TAG_IGNORE : ASLFR_TitleText, (xmfr->Title == -1) ? NULL : STR(xmfr->Title),
707 ASLFR_Flags1, xmfr->Flags | FRF_PRIVATEIDCMP,
708 ASLFR_Flags2, FRF_REJECTICONS,
714 if (!(FontReq = AllocAslRequestTags (ASL_FontRequest,
723 GLOBALCALL LONG SetupReqTools (void)
727 if (!(ReqToolsBase = (struct ReqToolsBase *)OpenLibrary ("reqtools.library", 38)))
729 CantOpenLib ("reqtools.library", 38);
733 for (i = 0; i < FREQ_COUNT; i++)
734 if (!(FileReqs[i].FReq = rtAllocRequestA (RT_FILEREQ, NULL)))
737 if (!(FontReq = rtAllocRequestA (RT_FONTREQ, NULL)))
745 GLOBALCALL LONG SetupRequesters (void)
749 if (!FileReqPort) /* Create FileRequester reply port */
751 if (!(FileReqPort = CreateMsgPort ())) return ERROR_NO_FREE_STORE;
752 FileReqSig = 1 << FileReqPort->mp_SigBit;
753 Signals |= FileReqSig;
756 if (GuiSwitches.UseReqTools)
760 GuiSwitches.UseReqTools = FALSE;
766 GuiSwitches.UseReqTools = TRUE;
767 return SetupReqTools();