2 Copyright © 2012-2017, The AROS Development Team. All rights reserved.
7 #include <proto/muimaster.h>
8 #include <proto/intuition.h>
10 #include <proto/utility.h>
11 #include <proto/xadmaster.h>
12 #include <proto/alib.h>
15 #include <aros/debug.h>
17 #include <libraries/mui.h>
18 #include <mui/NList_mcc.h>
19 #include <mui/NListview_mcc.h>
20 #include <zune/customclasses.h>
24 #include "unarcgroup_class.h"
27 #define PATHNAMESIZE (1024)
30 struct UnarcGroup_DATA
32 Object
*btn_all
, *btn_none
, *btn_invert
, *btn_start
, *btn_cancel
;
33 Object
*str_file
, *str_targetdir
, *lst_content
, *ga_progress
;
34 Object
*txt_status_total
, *txt_status_select
;
35 struct Hook start_hook
, change_selection_hook
, read_file_hook
, expand_dest_hook
;
36 struct xadArchiveInfo
*ai
;
37 ULONG total_entry_cnt
;
39 ULONG select_entry_cnt
;
41 STRPTR targetpathname
;
48 struct xadFileInfo
*fi
;
51 static struct Hook list_display_hook
, list_constr_hook
, list_destr_hook
;
62 static STRPTR
alloc_name_from_lock(CONST_STRPTR filename
)
65 STRPTR buffer
= AllocVec(PATHNAMESIZE
, MEMF_ANY
);
68 BPTR lock
= Lock(filename
, ACCESS_READ
);
71 if (NameFromLock(lock
, buffer
, PATHNAMESIZE
))
82 static BOOL
is_file(CONST_STRPTR filename
)
91 BPTR lock
= Lock(filename
, ACCESS_READ
);
94 struct FileInfoBlock
*fib
= AllocDosObject(DOS_FIB
, NULL
);
97 BOOL ex
= Examine(lock
, fib
);
100 D(bug("[is_file] file %s direntry_type %d\n", filename
, fib
->fib_DirEntryType
));
101 if (fib
->fib_DirEntryType
< 0) // File
106 FreeDosObject(DOS_FIB
, fib
);
114 AROS_UFH3(APTR
, list_constr_func
,
115 AROS_UFHA(struct Hook
*, h
, A0
),
116 AROS_UFHA(APTR
, pool
, A2
),
117 AROS_UFHA(struct Listentry
*, li
, A1
))
121 struct Listentry
*newentry
= AllocPooled(pool
, sizeof(struct Listentry
));
132 AROS_UFH3(void, list_destr_func
,
133 AROS_UFHA(struct Hook
*, h
, A0
),
134 AROS_UFHA(APTR
, pool
, A2
),
135 AROS_UFHA(struct Listentry
*, li
, A1
))
139 FreePooled(pool
, li
, sizeof(struct Listentry
));
145 AROS_UFH3S(LONG
, list_display_func
,
146 AROS_UFHA(struct Hook
*, h
, A0
),
147 AROS_UFHA(char **, array
, A2
),
148 AROS_UFHA(struct Listentry
*, li
, A1
))
154 static TEXT protbuf
[8], sizebuf
[20], crsizebuf
[20], percentbuf
[8];
155 static TEXT datebuf
[20], timebuf
[20];
159 protbuf
[0] = li
->fi
->xfi_Protection
& FIBF_SCRIPT
? 's' : '-';
160 protbuf
[1] = li
->fi
->xfi_Protection
& FIBF_PURE
? 'p' : '-';
161 protbuf
[2] = li
->fi
->xfi_Protection
& FIBF_ARCHIVE
? 'a' : '-';
163 // The following bits are high-active!
164 protbuf
[3] = li
->fi
->xfi_Protection
& FIBF_READ
? '-' : 'r';
165 protbuf
[4] = li
->fi
->xfi_Protection
& FIBF_WRITE
? '-' : 'w';
166 protbuf
[5] = li
->fi
->xfi_Protection
& FIBF_EXECUTE
? '-' : 'e';
167 protbuf
[6] = li
->fi
->xfi_Protection
& FIBF_DELETE
? '-' : 'd';
171 snprintf(sizebuf
, sizeof sizebuf
, "%lu", (long unsigned int)li
->fi
->xfi_Size
);
172 snprintf(crsizebuf
, sizeof crsizebuf
, "%lu", (long unsigned int)li
->fi
->xfi_CrunchSize
);
173 if (li
->fi
->xfi_Size
)
175 snprintf(percentbuf
, sizeof percentbuf
, "%u %%", (unsigned int)(100 - li
->fi
->xfi_CrunchSize
* 100 / li
->fi
->xfi_Size
));
179 strlcpy(percentbuf
, "100 %", sizeof percentbuf
);
185 dt
.dat_Format
= FORMAT_DEF
;
187 dt
.dat_StrDay
= NULL
;
188 dt
.dat_StrDate
= datebuf
;
189 dt
.dat_StrTime
= timebuf
;
190 if (xadConvertDates(XAD_DATEXADDATE
, &li
->fi
->xfi_Date
, XAD_GETDATEDATESTAMP
, &dt
, TAG_DONE
) == 0)
197 *array
++ = "\033I[5:PROGDIR:Images/selected]";
201 *array
++ = "\033I[5:PROGDIR:Images/unselected]";
203 *array
++ = li
->fi
->xfi_FileName
;
206 *array
++ = crsizebuf
;
207 *array
++ = percentbuf
;
214 *array
++ = (STRPTR
)_(MSG_LBL_NAME
);
215 *array
++ = (STRPTR
)_(MSG_LBL_PROTECTION
);
216 *array
++ = (STRPTR
)_(MSG_LBL_SIZE
);
217 *array
++ = (STRPTR
)_(MSG_LBL_PACKSIZE
);
218 *array
++ = (STRPTR
)_(MSG_LBL_RATE
);
219 *array
++ = (STRPTR
)_(MSG_LBL_DATE
);
220 *array
++ = (STRPTR
)_(MSG_LBL_TIME
);
229 AROS_UFH3S(void, change_selection_func
,
230 AROS_UFHA(struct Hook
*, h
, A0
),
231 AROS_UFHA(Object
*, obj
, A2
),
232 AROS_UFHA(APTR
, msg
, A1
))
236 struct UnarcGroup_DATA
*data
= h
->h_Data
;
237 ULONG status
= *(ULONG
*)msg
;
238 struct Listentry
*oldentry
, newentry
;
242 D(bug("[change_selection_func] status %u\n", status
));
244 SET(data
->lst_content
, MUIA_List_Quiet
, TRUE
);
249 data
->select_size
= data
->total_size
;
250 data
->select_entry_cnt
= data
->total_entry_cnt
;
253 DoMethod(data
->lst_content
, MUIM_NList_GetEntry
, i
, &oldentry
);
256 if (!oldentry
->selected
)
258 newentry
.selected
= TRUE
;
259 newentry
.fi
= oldentry
->fi
;
260 DoMethod(data
->lst_content
, MUIM_NList_Remove
, i
);
261 DoMethod(data
->lst_content
, MUIM_NList_InsertSingle
, &newentry
, i
);
267 data
->select_size
= 0;
268 data
->select_entry_cnt
= 0;
271 DoMethod(data
->lst_content
, MUIM_NList_GetEntry
, i
, &oldentry
);
274 if (oldentry
->selected
)
276 newentry
.selected
= FALSE
;
277 newentry
.fi
= oldentry
->fi
;
278 DoMethod(data
->lst_content
, MUIM_NList_Remove
, i
);
279 DoMethod(data
->lst_content
, MUIM_NList_InsertSingle
, &newentry
, i
);
285 data
->select_size
= 0;
286 data
->select_entry_cnt
= 0;
289 DoMethod(data
->lst_content
, MUIM_NList_GetEntry
, i
, &oldentry
);
292 newentry
.selected
= oldentry
->selected
? FALSE
: TRUE
;
293 newentry
.fi
= oldentry
->fi
;
294 DoMethod(data
->lst_content
, MUIM_NList_Remove
, i
);
295 DoMethod(data
->lst_content
, MUIM_NList_InsertSingle
, &newentry
, i
);
296 if (newentry
.selected
)
298 data
->select_size
+= newentry
.fi
->xfi_Size
;
299 data
->select_entry_cnt
++;
305 i
= XGET(data
->lst_content
, MUIA_NList_EntryClick
);
308 DoMethod(data
->lst_content
, MUIM_NList_GetEntry
, i
, &oldentry
);
309 newentry
.selected
= oldentry
->selected
? FALSE
: TRUE
;
310 newentry
.fi
= oldentry
->fi
;
311 DoMethod(data
->lst_content
, MUIM_NList_Remove
, i
);
312 DoMethod(data
->lst_content
, MUIM_NList_InsertSingle
, &newentry
, i
);
313 if (newentry
.selected
)
315 data
->select_size
+= newentry
.fi
->xfi_Size
;
316 data
->select_entry_cnt
++;
320 data
->select_size
-= newentry
.fi
->xfi_Size
;
321 data
->select_entry_cnt
--;
327 SET(data
->lst_content
, MUIA_List_Quiet
, FALSE
);
328 snprintf(buffer
, sizeof buffer
, _(MSG_TXT_STATUS_SEL
), data
->select_size
, data
->select_entry_cnt
);
329 SET(data
->txt_status_select
, MUIA_Text_Contents
, buffer
);
335 AROS_UFH3S(void, start_func
,
336 AROS_UFHA(struct Hook
*, h
, A0
),
337 AROS_UFHA(Object
*, obj
, A2
),
338 AROS_UFHA(APTR
, msg
, A1
))
342 D(bug("[start_func] called\n"));
344 struct UnarcGroup_DATA
*data
= h
->h_Data
;
345 struct Listentry
*entry
;
348 STRPTR destination
= (STRPTR
)XGET(data
->str_targetdir
, MUIA_String_Contents
);
349 if (destination
[0] == '\0')
351 // FIXME: what if user selects "" as destination when starting from CLI?
354 _app(obj
), _win(obj
), 0, _(MSG_ERR
),
355 _(MSG_OK
), _(MSG_ERR_NODEST
)
362 DoMethod(obj
, MUIM_NList_GetEntry
, i
, &entry
);
367 strlcpy(data
->targetpathname
, destination
, PATHNAMESIZE
);
368 result
= AddPart(data
->targetpathname
, entry
->fi
->xfi_FileName
, PATHNAMESIZE
);
373 _app(obj
), _win(obj
), 0, _(MSG_ERR
),
374 _(MSG_OK
), _(MSG_ERR_ADDPART
), data
->targetpathname
, result
378 D(bug("[start_func] filename %s\n", data
->targetpathname
));
379 if (entry
->fi
->xfi_Flags
& XADFIF_DIRECTORY
)
381 // FIXME: create directory (needed if empty)
385 result
= xadFileUnArc
388 XAD_ENTRYNUMBER
, i
+ 1,
389 XAD_OUTFILENAME
, data
->targetpathname
,
390 XAD_MAKEDIRECTORY
, TRUE
,
394 D(bug("[start_func] xadFileUnArc result %d\n", result
));
395 if (result
!=0 && result
!= XADERR_BADPARAMS
) // FIXME: why do I have to catch that error?
401 _app(obj
), _win(obj
), 0, _(MSG_ERR
),
402 _(MSG_SKIP_CANCEL
), _(MSG_ERR_CANT_UNPACK
),
403 data
->targetpathname
, xadGetErrorText(result
)
412 SET(data
->ga_progress
, MUIA_Gauge_Current
, i
);
419 AROS_UFH3S(void, read_file_func
,
420 AROS_UFHA(struct Hook
*, h
, A0
),
421 AROS_UFHA(Object
*, obj
, A2
),
422 AROS_UFHA(APTR
, msg
, A1
))
426 D(bug("[read_file_func] called\n"));
428 struct UnarcGroup_DATA
*data
= h
->h_Data
;
432 STRPTR filename
= (STRPTR
)XGET(data
->str_file
, MUIA_String_Contents
);
433 STRPTR newfilename
= alloc_name_from_lock(filename
); // expand to full path
436 NNSET(data
->str_file
, MUIA_String_Contents
, newfilename
);
437 filename
= (STRPTR
)XGET(data
->str_file
, MUIA_String_Contents
);
438 FreeVec(newfilename
);
441 DoMethod(data
->lst_content
, MUIM_NList_Clear
);
443 xadFreeInfo(data
->ai
);
444 data
->total_entry_cnt
= 0;
445 data
->total_size
= 0;
446 SET(data
->ga_progress
, MUIA_Gauge_Current
, 0);
447 SET(data
->btn_all
, MUIA_Disabled
, TRUE
);
448 SET(data
->btn_none
, MUIA_Disabled
, TRUE
);
449 SET(data
->btn_invert
, MUIA_Disabled
, TRUE
);
450 SET(data
->btn_start
, MUIA_Disabled
, TRUE
);
452 result
= xadGetInfo(data
->ai
, XAD_INFILENAME
, filename
, TAG_DONE
);
455 struct xadFileInfo
*fi
= data
->ai
->xai_FileInfo
;
458 struct Listentry newentry
;
459 newentry
.selected
= TRUE
;
461 DoMethod(data
->lst_content
, MUIM_NList_InsertSingle
, &newentry
, MUIV_List_Insert_Bottom
);
462 data
->total_entry_cnt
++;
463 data
->total_size
+= fi
->xfi_Size
;
466 SET(data
->ga_progress
, MUIA_Gauge_Max
, data
->total_entry_cnt
- 1);
467 SET(data
->btn_all
, MUIA_Disabled
, FALSE
);
468 SET(data
->btn_none
, MUIA_Disabled
, FALSE
);
469 SET(data
->btn_invert
, MUIA_Disabled
, FALSE
);
470 SET(data
->btn_start
, MUIA_Disabled
, FALSE
);
476 NULL
, NULL
, 0, _(MSG_ERR
),
477 _(MSG_OK
), _(MSG_ERR_NO_ARC
), NULL
480 snprintf(buffer
, sizeof buffer
, _(MSG_TXT_STATUS_ALL
), data
->total_size
, data
->total_entry_cnt
);
481 SET(data
->txt_status_total
, MUIA_Text_Contents
, buffer
);
483 data
->select_entry_cnt
= data
->total_entry_cnt
;
484 data
->select_size
= data
->total_size
;
485 snprintf(buffer
, sizeof buffer
, _(MSG_TXT_STATUS_SEL
), data
->select_size
, data
->select_entry_cnt
);
486 SET(data
->txt_status_select
, MUIA_Text_Contents
, buffer
);
492 AROS_UFH3S(void, expand_dest_func
,
493 AROS_UFHA(struct Hook
*, h
, A0
),
494 AROS_UFHA(Object
*, obj
, A2
),
495 AROS_UFHA(APTR
, msg
, A1
))
499 D(bug("[expand_dest_func] called\n"));
501 struct UnarcGroup_DATA
*data
= h
->h_Data
;
503 STRPTR targetdir
= (STRPTR
)XGET(data
->str_targetdir
, MUIA_String_Contents
);
504 STRPTR newtargetdir
= alloc_name_from_lock(targetdir
); // expand to full path
507 NNSET(data
->str_targetdir
, MUIA_String_Contents
, newtargetdir
);
508 FreeVec(newtargetdir
);
515 Object
*UnarcGroup__OM_NEW(Class
*CLASS
, Object
*self
, struct opSet
*message
)
517 Object
*btn_all
, *btn_none
, *btn_invert
, *btn_start
, *btn_cancel
;
518 Object
*str_file
, *str_targetdir
, *lst_content
, *ga_progress
;
519 Object
*txt_status_total
, *txt_status_select
;
520 STRPTR archive
= NULL
, destination
= NULL
;
522 struct xadArchiveInfo
*ai
= xadAllocObjectA(XADOBJ_ARCHIVEINFO
, 0);
523 STRPTR targetpathname
= AllocVec(PATHNAMESIZE
, MEMF_ANY
);
525 if (ai
== NULL
|| targetpathname
== NULL
)
527 // FIXME: I get memory corruption alert if I leave function here
530 NULL
, NULL
, 0, _(MSG_ERR
),
531 _(MSG_OK
), _(MSG_ERR_NO_MEM
), NULL
536 struct TagItem
*tstate
= message
->ops_AttrList
;
537 struct TagItem
*tag
= NULL
;
539 while ((tag
= NextTagItem(&tstate
)) != NULL
)
543 case MUIA_UnarcGroup_Archive
:
544 archive
= (STRPTR
)tag
->ti_Data
;
547 case MUIA_UnarcGroup_Destination
:
548 destination
= (STRPTR
)tag
->ti_Data
;
553 if (archive
== NULL
) archive
= "SYS:";
554 if (destination
== NULL
) destination
= "RAM:";
556 list_constr_hook
.h_Entry
= (HOOKFUNC
)list_constr_func
;
557 list_destr_hook
.h_Entry
= (HOOKFUNC
)list_destr_func
;
558 list_display_hook
.h_Entry
= (HOOKFUNC
)list_display_func
;
560 self
= (Object
*) DoSuperNewTags
564 Child
, Label(_(MSG_LA_ARCHIVE
)),
566 MUIA_Popasl_Type
, ASL_FileRequest
,
567 ASLFR_TitleText
, _(MSG_FREQ_ARCHIVE_TITLE
),
568 ASLFR_RejectIcons
, TRUE
,
569 MUIA_Popstring_String
, str_file
= StringObject
,
571 MUIA_String_Contents
, archive
,
573 MUIA_Popstring_Button
, PopButton(MUII_PopFile
),
575 Child
, Label(_(MSG_LA_DESTINATION
)),
577 MUIA_Popasl_Type
, ASL_FileRequest
,
578 ASLFR_TitleText
, _(MSG_FREQ_DESTINATION_TITLE
),
579 ASLFR_DrawersOnly
, TRUE
,
580 MUIA_Popstring_String
, str_targetdir
= StringObject
,
582 MUIA_String_Contents
, destination
,
584 MUIA_Popstring_Button
, PopButton(MUII_PopDrawer
),
587 Child
, ga_progress
= GaugeObject
,
590 MUIA_Gauge_Horiz
, TRUE
,
593 Child
, NListviewObject
,
594 MUIA_NListview_NList
, lst_content
= NListObject
,
595 MUIA_Frame
, MUIV_Frame_InputList
,
596 MUIA_NList_Input
, FALSE
,
597 MUIA_NList_Format
, "BAR,BAR,P=\33r BAR,P=\33r BAR,P=\33r BAR,P=\33r BAR,BAR,",
598 MUIA_NList_Title
, TRUE
,
599 MUIA_NList_DisplayHook
, &list_display_hook
,
600 MUIA_NList_ConstructHook
, &list_constr_hook
,
601 MUIA_NList_DestructHook
, &list_destr_hook
,
605 Child
, txt_status_total
= TextObject
,
608 Child
, txt_status_select
= TextObject
,
613 Child
, btn_all
= SimpleButton(_(MSG_BT_ALL
)),
614 Child
, btn_none
= SimpleButton(_(MSG_BT_NONE
)),
615 Child
, btn_invert
= SimpleButton(_(MSG_BT_INVERT
)),
617 Child
, (IPTR
) RectangleObject
,
618 MUIA_Rectangle_HBar
, TRUE
,
622 Child
, btn_start
= SimpleButton(_(MSG_BT_START
)),
624 Child
, btn_cancel
= SimpleButton(_(MSG_BT_CANCEL
)),
626 TAG_MORE
, (IPTR
)message
->ops_AttrList
,
632 struct UnarcGroup_DATA
*data
= INST_DATA(CLASS
, self
);
634 data
->btn_all
= btn_all
;
635 data
->btn_none
= btn_none
;
636 data
->btn_invert
= btn_invert
;
637 data
->btn_start
= btn_start
;
638 data
->btn_cancel
= btn_cancel
;
639 data
->str_file
= str_file
;
640 data
->str_targetdir
= str_targetdir
;
641 data
->lst_content
= lst_content
;
642 data
->ga_progress
= ga_progress
;
643 data
->txt_status_total
= txt_status_total
;
644 data
->txt_status_select
= txt_status_select
;
647 data
->start_hook
.h_Entry
= (HOOKFUNC
)start_func
;
648 data
->start_hook
.h_Data
= data
;
649 data
->read_file_hook
.h_Entry
= (HOOKFUNC
)read_file_func
;
650 data
->read_file_hook
.h_Data
= data
;
651 data
->change_selection_hook
.h_Entry
= (HOOKFUNC
)change_selection_func
;
652 data
->change_selection_hook
.h_Data
= data
;
653 data
->expand_dest_hook
.h_Entry
= (HOOKFUNC
)expand_dest_func
;
654 data
->expand_dest_hook
.h_Data
= data
;
656 data
->targetpathname
= targetpathname
;
658 SET(data
->btn_all
, MUIA_Disabled
, TRUE
);
659 SET(data
->btn_none
, MUIA_Disabled
, TRUE
);
660 SET(data
->btn_invert
, MUIA_Disabled
, TRUE
);
661 SET(data
->btn_start
, MUIA_Disabled
, TRUE
);
665 data
->btn_cancel
, MUIM_Notify
, MUIA_Pressed
, FALSE
,
666 MUIV_Notify_Application
, 2, MUIM_Application_ReturnID
, MUIV_Application_ReturnID_Quit
671 data
->btn_all
, MUIM_Notify
, MUIA_Pressed
, FALSE
,
672 data
->lst_content
, 3, MUIM_CallHook
, &data
->change_selection_hook
, SETALL
677 data
->btn_none
, MUIM_Notify
, MUIA_Pressed
, FALSE
,
678 data
->lst_content
, 3, MUIM_CallHook
, &data
->change_selection_hook
, CLEARALL
683 data
->btn_invert
, MUIM_Notify
, MUIA_Pressed
, FALSE
,
684 data
->lst_content
, 3, MUIM_CallHook
, &data
->change_selection_hook
, INVERTALL
689 data
->lst_content
, MUIM_Notify
, MUIA_NList_EntryClick
, MUIV_EveryTime
,
690 data
->lst_content
, 3, MUIM_CallHook
, &data
->change_selection_hook
, INVERTSINGLE
695 data
->btn_start
, MUIM_Notify
, MUIA_Pressed
, FALSE
,
696 data
->lst_content
, 2, MUIM_CallHook
, &data
->start_hook
701 data
->str_file
, MUIM_Notify
, MUIA_String_Acknowledge
, MUIV_EveryTime
,
702 data
->lst_content
, 2, MUIM_CallHook
, &data
->read_file_hook
707 data
->str_targetdir
, MUIM_Notify
, MUIA_String_Acknowledge
, MUIV_EveryTime
,
708 data
->str_targetdir
, 2, MUIM_CallHook
, &data
->expand_dest_hook
711 if (is_file(archive
))
713 // fill the list if we have an existing file
716 data
->lst_content
, MUIM_CallHook
, &data
->read_file_hook
724 IPTR
UnarcGroup__OM_DISPOSE(Class
*CLASS
, Object
*self
, Msg message
)
726 struct UnarcGroup_DATA
*data
= INST_DATA(CLASS
, self
);
730 xadFreeInfo(data
->ai
);
731 xadFreeObjectA(data
->ai
, 0);
733 FreeVec(data
->targetpathname
);
735 return DoSuperMethodA(CLASS
, self
, message
);
741 UnarcGroup
, NULL
, MUIC_Group
, NULL
,
742 OM_NEW
, struct opSet
*,