6 #include <exec/types.h>
7 #include <scalos/preferences.h>
8 #include <scalos/scalos.h>
9 #include <intuition/intuition.h>
10 #include <devices/inputevent.h>
11 #include <libraries/iffparse.h>
12 #include <libraries/mui.h>
13 #include <libraries/asl.h>
14 #include <libraries/mcpgfx.h>
15 #include <libraries/ttengine.h>
16 #include <graphics/view.h>
17 #include <prefs/prefhdr.h>
18 #include <prefs/font.h>
19 #include <prefs/workbench.h>
20 #include <mui/NListview_mcc.h>
24 #include <proto/dos.h>
25 #include <proto/exec.h>
26 #include <proto/intuition.h>
27 #include <proto/dos.h>
28 #include <proto/iffparse.h>
29 #include <proto/scalos.h>
30 #include <proto/utility.h>
32 #define NO_INLINE_STDARG
33 #include <proto/muimaster.h>
35 #include <clib/alib_protos.h>
46 #include "HiddenDevices.h"
47 #include "ScalosPrefs.h"
49 //-----------------------------------------------------------------
54 char hd_Name
[1]; // variable length
57 struct UnknownPrefsChunk
63 UBYTE upc_Data
[1]; // variable length
66 //-----------------------------------------------------------------
68 static void HandleWBHD(const UBYTE
*data
, size_t length
);
69 static LONG
CollectUnknownPrefsChunks(struct List
*ChunksList
, CONST_STRPTR Filename
);
70 static LONG
AddUnknownChunk(struct List
*ChunksList
, struct IFFHandle
*iff
, const struct ContextNode
*cn
);
71 static void CleanupUnknownChunks(struct List
*ChunksList
);
72 static void AddHiddenDeviceFromDosList(struct SCAModule
*app
, struct DosList
*dl
, struct InfoData
*id
, BOOL Hidden
);
73 static void BtoCString(BPTR bstring
, STRPTR Buffer
, size_t Length
);
74 static BOOL
FindHiddenDevice(CONST_STRPTR Name
);
75 static void StripTrailingColon(STRPTR Line
);
77 //-----------------------------------------------------------------
79 static struct List HiddenDevicesList
;
81 //-----------------------------------------------------------------
83 BOOL
HiddenDevicesInit(void)
85 NewList(&HiddenDevicesList
);
90 //-----------------------------------------------------------------
92 void HiddenDevicesCleanup(void)
94 struct HiddenDevice
*hd
;
96 while ((hd
= (struct HiddenDevice
*) RemHead(&HiddenDevicesList
)))
102 //-----------------------------------------------------------------
104 // Read workbench.prefs and build list of hidden devices
105 BOOL
ReadWorkbenchPrefs(CONST_STRPTR filename
)
107 struct IFFHandle
*iff
;
109 BOOL IffOpened
= FALSE
;
110 static const ULONG pairs
[] = {ID_PREF
, ID_PREF
, ID_WBHD
};
112 HiddenDevicesCleanup();
114 d1(KPrintF(__FILE__
"/%s/%ld: filename=<%s>\n", __FUNC__
, __LINE__
, filename
));
121 iff
->iff_Stream
= (ULONG
) Open((STRPTR
) filename
, MODE_OLDFILE
);
122 d1(KPrintF(__FILE__
"/%s/%ld: iff_Stream=%08lx\n", __FUNC__
, __LINE__
, iff
->iff_Stream
));
123 if (0 == iff
->iff_Stream
)
128 error
= OpenIFF( iff
, IFFF_READ
);
129 if (RETURN_OK
!= error
)
134 error
= CollectionChunks( iff
, (LONG
*) pairs
, Sizeof(pairs
) / 2);
135 if (RETURN_OK
!= error
)
138 StopOnExit( iff
, ID_PREF
, ID_FORM
);
142 if( ( error
= ParseIFF( iff
, IFFPARSE_SCAN
) ) == IFFERR_EOC
)
144 struct CollectionItem
*ci
;
146 ci
= FindCollection( iff
, ID_PREF
, ID_WBHD
);
149 HandleWBHD(ci
->ci_Data
, ci
->ci_Size
);
164 Close( (BPTR
)iff
->iff_Stream
);
171 //-----------------------------------------------------------------
173 static void HandleWBHD(const UBYTE
*data
, size_t length
)
175 d1(KPrintF(__FILE__
"/%s/%ld: data=<%s> length=%lu\n", __FUNC__
, __LINE__
, data
, length
));
177 if (!FindHiddenDevice((STRPTR
)data
)) // make sure we get no cuplicate entries
178 AddHiddenDevice((STRPTR
)data
);
181 //-----------------------------------------------------------------
183 // save workbench.prefs, including WBHD entries for each hidden device
184 LONG
WriteWorkbenchPrefs(CONST_STRPTR Filename
)
186 struct IFFHandle
*iff
= NULL
;
188 BOOL IffOpen
= FALSE
;
189 struct List ChunksList
;
191 NewList(&ChunksList
);
194 static const struct PrefHeader prefHeader
= { 0, 0, 0L };
195 struct HiddenDevice
*hd
;
196 struct UnknownPrefsChunk
*upc
;
198 d1(KPrintF(__FILE__
"/%s/%ld: Filename=<%s>\n", __FUNC__
, __LINE__
, Filename
));
200 Result
= CollectUnknownPrefsChunks(&ChunksList
, Filename
);
201 d1(KPrintF(__FILE__
"/%s/%ld: Result=%ld\n", __FUNC__
, __LINE__
, Result
));
202 if (RETURN_OK
!= Result
)
214 iff
->iff_Stream
= (IPTR
)Open(Filename
, MODE_NEWFILE
);
215 if (0 == iff
->iff_Stream
)
217 // ... try to create missing directories here
221 d1(KPrintF(__FILE__
"/%s/%ld: Result=%ld\n", __FUNC__
, __LINE__
, Result
));
223 FilenameCopy
= AllocVec(1 + strlen(Filename
), MEMF_PUBLIC
);
229 strcpy(FilenameCopy
, Filename
);
231 lp
= PathPart(FilenameCopy
);
237 dirLock
= CreateDir(FilenameCopy
);
242 iff
->iff_Stream
= (IPTR
)Open(Filename
, MODE_NEWFILE
);
243 if (0 == iff
->iff_Stream
)
249 FreeVec(FilenameCopy
);
252 d1(KPrintF(__FILE__
"/%s/%ld: Result=%ld\n", __FUNC__
, __LINE__
, Result
));
253 if (RETURN_OK
!= Result
)
257 d1(KPrintF(__FILE__
"/%s/%ld: Result=%ld\n", __FUNC__
, __LINE__
, Result
));
259 Result
= OpenIFF(iff
, IFFF_WRITE
);
260 if (RETURN_OK
!= Result
)
264 d1(KPrintF(__FILE__
"/%s/%ld: Result=%ld\n", __FUNC__
, __LINE__
, Result
));
266 Result
= PushChunk(iff
, ID_PREF
, ID_FORM
, IFFSIZE_UNKNOWN
);
267 if (RETURN_OK
!= Result
)
270 Result
= PushChunk(iff
, 0, ID_PRHD
, IFFSIZE_UNKNOWN
);
271 if (RETURN_OK
!= Result
)
274 if (WriteChunkBytes(iff
, (APTR
) &prefHeader
, sizeof(prefHeader
)) < 0)
280 Result
= PopChunk(iff
); // PRHD
281 if (RETURN_OK
!= Result
)
284 d1(KPrintF(__FILE__
"/%s/%ld: Result=%ld\n", __FUNC__
, __LINE__
, Result
));
286 for (hd
= (struct HiddenDevice
*) HiddenDevicesList
.lh_Head
;
287 hd
!= (struct HiddenDevice
*) &HiddenDevicesList
.lh_Tail
;
288 hd
= (struct HiddenDevice
*) hd
->hd_Node
.ln_Succ
)
290 size_t wbhdLength
= 1 + strlen(hd
->hd_Name
);
292 d1(KPrintF(__FILE__
"/%s/%ld: hd_Name=<%s>\n", __FUNC__
, __LINE__
, hd
->hd_Name
));
294 Result
= PushChunk(iff
, 0, ID_WBHD
, IFFSIZE_UNKNOWN
);
295 if (RETURN_OK
!= Result
)
298 if (wbhdLength
!= WriteChunkBytes(iff
, (APTR
) hd
->hd_Name
, wbhdLength
))
303 if (wbhdLength
& 0x01)
305 // write dummy byte to get even chunk length
308 if (1 != WriteChunkBytes(iff
, (APTR
) &Dummy
, 1))
315 Result
= PopChunk(iff
); // WBHD
316 if (RETURN_OK
!= Result
)
320 d1(KPrintF(__FILE__
"/%s/%ld: Result=%ld\n", __FUNC__
, __LINE__
, Result
));
322 if (RETURN_OK
!= Result
)
325 for (upc
= (struct UnknownPrefsChunk
*) ChunksList
.lh_Head
;
326 upc
!= (struct UnknownPrefsChunk
*) &ChunksList
.lh_Tail
;
327 upc
= (struct UnknownPrefsChunk
*) upc
->upc_Node
.ln_Succ
)
329 d1(KPrintF("%s/%s/%ld: Write Chunk Type=%08lx, ID=%08lx Length=%lu\n", __FILE__
, __FUNC__
, __LINE__
, \
330 upc
->upc_Type
, upc
->upc_ID
, upc
->upc_Size
));
332 Result
= PushChunk(iff
, 0, upc
->upc_ID
, IFFSIZE_UNKNOWN
);
333 if (RETURN_OK
!= Result
)
336 if (upc
->upc_Size
!= WriteChunkBytes(iff
, (APTR
) upc
->upc_Data
, upc
->upc_Size
))
342 Result
= PopChunk(iff
); // upc->upc_ID
343 if (RETURN_OK
!= Result
)
347 Result
= PopChunk(iff
); // FORM
348 if (RETURN_OK
!= Result
)
353 CleanupUnknownChunks(&ChunksList
);
362 Close((BPTR
)iff
->iff_Stream
);
369 d1(KPrintF(__FILE__
"/%s/%ld: Result=%ld\n", __FUNC__
, __LINE__
, Result
));
371 if (RETURN_OK
== Result
&& fCreateIcons
)
377 //-----------------------------------------------------------------
379 static LONG
CollectUnknownPrefsChunks(struct List
*ChunksList
, CONST_STRPTR Filename
)
382 struct IFFHandle
*iff
;
383 BOOL iffOpened
= FALSE
;
385 d1(KPrintF(__FILE__
"/%s/%ld: Filename=<%s>\n", __FUNC__
, __LINE__
, Filename
));
397 iff
->iff_Stream
= (IPTR
)Open(Filename
, MODE_OLDFILE
);
398 if (0 == iff
->iff_Stream
)
404 Result
= OpenIFF(iff
, IFFF_READ
);
405 if (RETURN_OK
!= Result
)
410 while (RETURN_OK
== Result
)
412 struct ContextNode
*cn
;
414 Result
= ParseIFF(iff
, IFFPARSE_RAWSTEP
);
415 d1(KPrintF(__FILE__
"/%s/%ld: Result=%ld\n", __FUNC__
, __LINE__
, Result
));
416 if (IFFERR_EOC
== Result
)
421 if (IFFERR_EOF
== Result
)
426 if (RETURN_OK
!= Result
)
429 cn
= CurrentChunk(iff
);
436 d1(KPrintF(__FILE__
"/%s/%ld: ID_FORM Size=%ld\n", __FUNC__
, __LINE__
, cn
->cn_Size
));
439 d1(KPrintF(__FILE__
"/%s/%ld: ID_PREF Size=%ld\n", __FUNC__
, __LINE__
, cn
->cn_Size
));
442 d1(KPrintF(__FILE__
"/%s/%ld: ID_PRHD Size=%ld\n", __FUNC__
, __LINE__
, cn
->cn_Size
));
445 d1(KPrintF("%s/%s/%ld: Found Chunk Type=%08lx, ID=%08lx Length=%lu\n", __FILE__
, __FUNC__
, __LINE__
, \
446 cn
->cn_Type
, cn
->cn_ID
, cn
->cn_Size
));
447 Result
= AddUnknownChunk(ChunksList
, iff
, cn
);
459 Close((BPTR
)iff
->iff_Stream
);
467 //-----------------------------------------------------------------
469 static LONG
AddUnknownChunk(struct List
*ChunksList
, struct IFFHandle
*iff
, const struct ContextNode
*cn
)
471 struct UnknownPrefsChunk
*upc
;
472 LONG Result
= RETURN_OK
;
477 upc
= malloc(sizeof(struct UnknownPrefsChunk
) + cn
->cn_Size
);
480 Result
= ERROR_NO_FREE_STORE
;
484 upc
->upc_ID
= cn
->cn_ID
;
485 upc
->upc_Type
= cn
->cn_Type
;
486 upc
->upc_Size
= cn
->cn_Size
;
488 Length
= ReadChunkBytes(iff
, upc
->upc_Data
, upc
->upc_Size
);
489 if (Length
!= upc
->upc_Size
)
495 AddTail(ChunksList
, &upc
->upc_Node
);
504 d1(KPrintF(__FILE__
"/%s/%ld: Result=%ld\n", __FUNC__
, __LINE__
, Result
));
509 //-----------------------------------------------------------------
511 static void CleanupUnknownChunks(struct List
*ChunksList
)
513 struct UnknownPrefsChunk
*upc
;
515 while ((upc
= (struct UnknownPrefsChunk
*) RemTail(ChunksList
)))
521 //-----------------------------------------------------------------
523 // Traverse DosList for all devices, and build list of hideable devices
524 void FillHiddenDevicesList(struct SCAModule
*app
)
526 ULONG LockDosListFlags
= LDF_DEVICES
| LDF_READ
;
527 struct HiddenDevice
*hd
;
531 set(app
->Obj
[NLIST_HIDDENDEVICES
], MUIA_NList_Quiet
, TRUE
);
532 DoMethod(app
->Obj
[NLIST_HIDDENDEVICES
], MUIM_NList_Clear
);
533 DoMethod(app
->Obj
[NLIST_HIDDENDEVICES
], MUIM_NList_UseImage
,
534 NULL
, MUIV_NList_UseImage_All
, 0);
536 id
= malloc(sizeof(struct InfoData
));
539 dl
= LockDosList(LockDosListFlags
);
541 while (dl
= NextDosEntry(dl
, LockDosListFlags
))
543 AddHiddenDeviceFromDosList(app
, dl
, id
, FALSE
);
546 UnLockDosList(LockDosListFlags
);
550 // Now walk through the list of devices marked as hidden,
551 // and add all entries.
553 dl
= LockDosList(LockDosListFlags
);
555 for (hd
= (struct HiddenDevice
*) HiddenDevicesList
.lh_Head
;
556 hd
!= (struct HiddenDevice
*) &HiddenDevicesList
.lh_Tail
;
557 hd
= (struct HiddenDevice
*) hd
->hd_Node
.ln_Succ
)
559 char HiddenDevName
[128];
560 struct DosList
*dlFound
;
562 // Name must not have trailing ":" to use with FindDosEntry()
563 stccpy(HiddenDevName
, hd
->hd_Name
, sizeof(HiddenDevName
));
564 StripTrailingColon(HiddenDevName
);
565 d1(KPrintF(__FILE__
"/%s/%ld: HiddenDevName=<%s>\n", __FUNC__
, __LINE__
, HiddenDevName
));
567 dlFound
= FindDosEntry(dl
, HiddenDevName
, LockDosListFlags
);
568 d1(KPrintF(__FILE__
"/%s/%ld: dl=%08lx\n", __FUNC__
, __LINE__
, dlFound
));
571 AddHiddenDeviceFromDosList(app
, dlFound
, id
, TRUE
);
575 struct NewHiddenDevice nhd
;
577 nhd
.nhd_DeviceName
= hd
->hd_Name
;
578 nhd
.nhd_VolumeName
= "";
579 nhd
.nhd_Hidden
= TRUE
;
581 d1(KPrintF(__FILE__
"/%s/%ld: DevName=<%s> VolName=<%s>\n", \
582 __FUNC__
, __LINE__
, nhd
.nhd_DeviceName
, nhd
.nhd_VolumeName
));
584 DoMethod(app
->Obj
[NLIST_HIDDENDEVICES
],
585 MUIM_NList_InsertSingle
,
587 MUIV_NList_Insert_Sorted
);
591 UnLockDosList(LockDosListFlags
);
593 set(app
->Obj
[NLIST_HIDDENDEVICES
], MUIA_NList_Quiet
, FALSE
);
596 //-----------------------------------------------------------------
598 static void AddHiddenDeviceFromDosList(struct SCAModule
*app
, struct DosList
*dl
, struct InfoData
*id
, BOOL Hidden
)
602 struct DosList
*VolumeNode
;
603 BOOL InfoDataValid
= FALSE
;
606 BtoCString(dl
->dol_Name
, DevName
, sizeof(DevName
));
608 d1(KPrintF(__FILE__
"/%s/%ld: START DevName=<%s>\n", __FUNC__
, __LINE__
, DevName
));
610 #if defined(__amigaos4__)
611 if (0 != Stricmp(DevName
, "ENV"))
612 #endif //!defined(__amigaos4__)
614 d1(KPrintF(__FILE__
"/%s/%ld: \n", __FUNC__
, __LINE__
));
616 DoPkt(dl
->dol_Task
, ACTION_DISK_INFO
,
620 InfoDataValid
= TRUE
;
622 d1(KPrintF(__FILE__
"/%s/%ld: InfoDataValid=%ld\n", __FUNC__
, __LINE__
, InfoDataValid
));
625 if (!Hidden
&& !InfoDataValid
)
630 switch (id
->id_DiskState
)
632 case ID_WRITE_PROTECTED
:
635 VolumeNode
= BADDR(id
->id_VolumeNode
);
638 BtoCString(VolumeNode
->dol_Name
, VolName
, sizeof(VolName
));
639 StripTrailingColon(VolName
);
640 strcat(VolName
, ":");
648 StripTrailingColon(DevName
);
649 strcat(DevName
, ":");
651 // add only visible devices here
652 if (Hidden
|| !FindHiddenDevice(DevName
))
654 struct NewHiddenDevice nhd
;
656 nhd
.nhd_DeviceName
= DevName
;
657 nhd
.nhd_VolumeName
= VolName
;
658 nhd
.nhd_Hidden
= Hidden
;
660 d1(KPrintF(__FILE__
"/%s/%ld: DevName=<%s> VolName=<%s>\n", \
661 __FUNC__
, __LINE__
, nhd
.nhd_DeviceName
, nhd
.nhd_VolumeName
));
663 DoMethod(app
->Obj
[NLIST_HIDDENDEVICES
],
664 MUIM_NList_InsertSingle
,
666 MUIV_NList_Insert_Sorted
);
670 //-----------------------------------------------------------------
672 static void BtoCString(BPTR bstring
, STRPTR Buffer
, size_t Length
)
675 // AROS needs special handling because it uses NULL-terminated
676 // strings on some platforms.
677 size_t Len
= AROS_BSTR_strlen(bstring
);
680 strncpy(Buffer
, AROS_BSTR_ADDR(bstring
), Len
);
683 CONST_STRPTR Src
= BADDR(bstring
);
686 // get BSTRING length (1st octet)
689 while (bLength
-- && (Length
-- > 1))
696 //-----------------------------------------------------------------
698 // Add entry to hidden devices list
699 BOOL
AddHiddenDevice(CONST_STRPTR Name
)
701 struct HiddenDevice
*hd
;
702 BOOL Success
= FALSE
;
704 hd
= malloc(sizeof(struct HiddenDevice
) + 1 + strlen(Name
));
707 strcpy(hd
->hd_Name
, Name
);
709 // make sure device name is terminated with exactly one ":"
710 StripTrailingColon(hd
->hd_Name
);
711 strcat(hd
->hd_Name
, ":");
713 AddHead(&HiddenDevicesList
, &hd
->hd_Node
);
717 d1(KPrintF(__FILE__
"/%s/%ld: Name=<%s> hd=%08lx\n", __FUNC__
, __LINE__
, Name
, hd
));
722 //-----------------------------------------------------------------
724 // Remove entry from hidden devices list
725 BOOL
RemoveHiddenDevice(CONST_STRPTR Name
)
727 struct HiddenDevice
*hd
;
730 d1(KPrintF(__FILE__
"/%s/%ld: Name=<%s>", __FUNC__
, __LINE__
, Name
));
732 for (hd
= (struct HiddenDevice
*) HiddenDevicesList
.lh_Head
;
733 hd
!= (struct HiddenDevice
*) &HiddenDevicesList
.lh_Tail
;
734 hd
= (struct HiddenDevice
*) hd
->hd_Node
.ln_Succ
)
736 if (0 == Stricmp(Name
, hd
->hd_Name
))
739 Remove(&hd
->hd_Node
);
748 //-----------------------------------------------------------------
750 // search for entry in hidden devices list
751 static BOOL
FindHiddenDevice(CONST_STRPTR Name
)
753 const struct HiddenDevice
*hd
;
756 d1(KPrintF(__FILE__
"/%s/%ld: Name=<%s>", __FUNC__
, __LINE__
, Name
));
758 for (hd
= (struct HiddenDevice
*) HiddenDevicesList
.lh_Head
;
759 hd
!= (struct HiddenDevice
*) &HiddenDevicesList
.lh_Tail
;
760 hd
= (struct HiddenDevice
*) hd
->hd_Node
.ln_Succ
)
762 if (0 == Stricmp(Name
, hd
->hd_Name
))
772 //-----------------------------------------------------------------
774 static void StripTrailingColon(STRPTR Line
)
776 size_t Len
= strlen(Line
);
784 //-----------------------------------------------------------------