2 Copyright © 2012, 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 result
= xadFileUnArc
382 XAD_ENTRYNUMBER
, i
+ 1,
383 XAD_OUTFILENAME
, data
->targetpathname
,
384 XAD_MAKEDIRECTORY
, TRUE
,
388 D(bug("[start_func] xadFileUnArc result %d\n", result
));
389 if (result
!=0 && result
!= XADERR_BADPARAMS
) // FIXME: why do I have to catch that error?
395 _app(obj
), _win(obj
), 0, _(MSG_ERR
),
396 _(MSG_SKIP_CANCEL
), _(MSG_ERR_CANT_UNPACK
), data
->targetpathname
, xadGetErrorText(result
)
404 SET(data
->ga_progress
, MUIA_Gauge_Current
, i
);
411 AROS_UFH3S(void, read_file_func
,
412 AROS_UFHA(struct Hook
*, h
, A0
),
413 AROS_UFHA(Object
*, obj
, A2
),
414 AROS_UFHA(APTR
, msg
, A1
))
418 D(bug("[read_file_func] called\n"));
420 struct UnarcGroup_DATA
*data
= h
->h_Data
;
424 STRPTR filename
= (STRPTR
)XGET(data
->str_file
, MUIA_String_Contents
);
425 STRPTR newfilename
= alloc_name_from_lock(filename
); // expand to full path
428 NNSET(data
->str_file
, MUIA_String_Contents
, newfilename
);
429 filename
= (STRPTR
)XGET(data
->str_file
, MUIA_String_Contents
);
430 FreeVec(newfilename
);
433 DoMethod(data
->lst_content
, MUIM_NList_Clear
);
435 xadFreeInfo(data
->ai
);
436 data
->total_entry_cnt
= 0;
437 data
->total_size
= 0;
438 SET(data
->ga_progress
, MUIA_Gauge_Current
, 0);
439 SET(data
->btn_all
, MUIA_Disabled
, TRUE
);
440 SET(data
->btn_none
, MUIA_Disabled
, TRUE
);
441 SET(data
->btn_invert
, MUIA_Disabled
, TRUE
);
442 SET(data
->btn_start
, MUIA_Disabled
, TRUE
);
444 result
= xadGetInfo(data
->ai
, XAD_INFILENAME
, filename
, TAG_DONE
);
447 struct xadFileInfo
*fi
= data
->ai
->xai_FileInfo
;
450 struct Listentry newentry
;
451 newentry
.selected
= TRUE
;
453 DoMethod(data
->lst_content
, MUIM_NList_InsertSingle
, &newentry
, MUIV_List_Insert_Bottom
);
454 data
->total_entry_cnt
++;
455 data
->total_size
+= fi
->xfi_Size
;
458 SET(data
->ga_progress
, MUIA_Gauge_Max
, data
->total_entry_cnt
- 1);
459 SET(data
->btn_all
, MUIA_Disabled
, FALSE
);
460 SET(data
->btn_none
, MUIA_Disabled
, FALSE
);
461 SET(data
->btn_invert
, MUIA_Disabled
, FALSE
);
462 SET(data
->btn_start
, MUIA_Disabled
, FALSE
);
468 NULL
, NULL
, 0, _(MSG_ERR
),
469 _(MSG_OK
), _(MSG_ERR_NO_ARC
), NULL
472 snprintf(buffer
, sizeof buffer
, _(MSG_TXT_STATUS_ALL
), data
->total_size
, data
->total_entry_cnt
);
473 SET(data
->txt_status_total
, MUIA_Text_Contents
, buffer
);
475 data
->select_entry_cnt
= data
->total_entry_cnt
;
476 data
->select_size
= data
->total_size
;
477 snprintf(buffer
, sizeof buffer
, _(MSG_TXT_STATUS_SEL
), data
->select_size
, data
->select_entry_cnt
);
478 SET(data
->txt_status_select
, MUIA_Text_Contents
, buffer
);
484 AROS_UFH3S(void, expand_dest_func
,
485 AROS_UFHA(struct Hook
*, h
, A0
),
486 AROS_UFHA(Object
*, obj
, A2
),
487 AROS_UFHA(APTR
, msg
, A1
))
491 D(bug("[expand_dest_func] called\n"));
493 struct UnarcGroup_DATA
*data
= h
->h_Data
;
495 STRPTR targetdir
= (STRPTR
)XGET(data
->str_targetdir
, MUIA_String_Contents
);
496 STRPTR newtargetdir
= alloc_name_from_lock(targetdir
); // expand to full path
499 NNSET(data
->str_targetdir
, MUIA_String_Contents
, newtargetdir
);
500 FreeVec(newtargetdir
);
507 Object
*UnarcGroup__OM_NEW(Class
*CLASS
, Object
*self
, struct opSet
*message
)
509 Object
*btn_all
, *btn_none
, *btn_invert
, *btn_start
, *btn_cancel
;
510 Object
*str_file
, *str_targetdir
, *lst_content
, *ga_progress
;
511 Object
*txt_status_total
, *txt_status_select
;
512 STRPTR archive
= NULL
, destination
= NULL
;
514 struct xadArchiveInfo
*ai
= xadAllocObjectA(XADOBJ_ARCHIVEINFO
, 0);
515 STRPTR targetpathname
= AllocVec(PATHNAMESIZE
, MEMF_ANY
);
517 if (ai
== NULL
|| targetpathname
== NULL
)
519 // FIXME: I get memory corruption alert if I leave function here
522 NULL
, NULL
, 0, _(MSG_ERR
),
523 _(MSG_OK
), _(MSG_ERR_NO_MEM
), NULL
528 struct TagItem
*tstate
= message
->ops_AttrList
;
529 struct TagItem
*tag
= NULL
;
531 while ((tag
= NextTagItem(&tstate
)) != NULL
)
535 case MUIA_UnarcGroup_Archive
:
536 archive
= (STRPTR
)tag
->ti_Data
;
539 case MUIA_UnarcGroup_Destination
:
540 destination
= (STRPTR
)tag
->ti_Data
;
545 if (archive
== NULL
) archive
= "SYS:";
546 if (destination
== NULL
) destination
= "RAM:";
548 list_constr_hook
.h_Entry
= (HOOKFUNC
)list_constr_func
;
549 list_destr_hook
.h_Entry
= (HOOKFUNC
)list_destr_func
;
550 list_display_hook
.h_Entry
= (HOOKFUNC
)list_display_func
;
552 self
= (Object
*) DoSuperNewTags
556 Child
, Label(_(MSG_LA_ARCHIVE
)),
558 MUIA_Popasl_Type
, ASL_FileRequest
,
559 ASLFR_TitleText
, _(MSG_FREQ_ARCHIVE_TITLE
),
560 ASLFR_RejectIcons
, TRUE
,
561 MUIA_Popstring_String
, str_file
= StringObject
,
563 MUIA_String_Contents
, archive
,
565 MUIA_Popstring_Button
, PopButton(MUII_PopFile
),
567 Child
, Label(_(MSG_LA_DESTINATION
)),
569 MUIA_Popasl_Type
, ASL_FileRequest
,
570 ASLFR_TitleText
, _(MSG_FREQ_DESTINATION_TITLE
),
571 ASLFR_DrawersOnly
, TRUE
,
572 MUIA_Popstring_String
, str_targetdir
= StringObject
,
574 MUIA_String_Contents
, destination
,
576 MUIA_Popstring_Button
, PopButton(MUII_PopDrawer
),
579 Child
, ga_progress
= GaugeObject
,
582 MUIA_Gauge_Horiz
, TRUE
,
585 Child
, NListviewObject
,
586 MUIA_NListview_NList
, lst_content
= NListObject
,
587 MUIA_Frame
, MUIV_Frame_InputList
,
588 MUIA_NList_Input
, FALSE
,
589 MUIA_NList_Format
, "BAR,BAR,P=\33r BAR,P=\33r BAR,P=\33r BAR,P=\33r BAR,BAR,",
590 MUIA_NList_Title
, TRUE
,
591 MUIA_NList_DisplayHook
, &list_display_hook
,
592 MUIA_NList_ConstructHook
, &list_constr_hook
,
593 MUIA_NList_DestructHook
, &list_destr_hook
,
597 Child
, txt_status_total
= TextObject
,
600 Child
, txt_status_select
= TextObject
,
605 Child
, btn_all
= SimpleButton(_(MSG_BT_ALL
)),
606 Child
, btn_none
= SimpleButton(_(MSG_BT_NONE
)),
607 Child
, btn_invert
= SimpleButton(_(MSG_BT_INVERT
)),
609 Child
, (IPTR
) RectangleObject
,
610 MUIA_Rectangle_HBar
, TRUE
,
614 Child
, btn_start
= SimpleButton(_(MSG_BT_START
)),
616 Child
, btn_cancel
= SimpleButton(_(MSG_BT_CANCEL
)),
618 TAG_MORE
, (IPTR
)message
->ops_AttrList
,
624 struct UnarcGroup_DATA
*data
= INST_DATA(CLASS
, self
);
626 data
->btn_all
= btn_all
;
627 data
->btn_none
= btn_none
;
628 data
->btn_invert
= btn_invert
;
629 data
->btn_start
= btn_start
;
630 data
->btn_cancel
= btn_cancel
;
631 data
->str_file
= str_file
;
632 data
->str_targetdir
= str_targetdir
;
633 data
->lst_content
= lst_content
;
634 data
->ga_progress
= ga_progress
;
635 data
->txt_status_total
= txt_status_total
;
636 data
->txt_status_select
= txt_status_select
;
639 data
->start_hook
.h_Entry
= (HOOKFUNC
)start_func
;
640 data
->start_hook
.h_Data
= data
;
641 data
->read_file_hook
.h_Entry
= (HOOKFUNC
)read_file_func
;
642 data
->read_file_hook
.h_Data
= data
;
643 data
->change_selection_hook
.h_Entry
= (HOOKFUNC
)change_selection_func
;
644 data
->change_selection_hook
.h_Data
= data
;
645 data
->expand_dest_hook
.h_Entry
= (HOOKFUNC
)expand_dest_func
;
646 data
->expand_dest_hook
.h_Data
= data
;
648 data
->targetpathname
= targetpathname
;
650 SET(data
->btn_all
, MUIA_Disabled
, TRUE
);
651 SET(data
->btn_none
, MUIA_Disabled
, TRUE
);
652 SET(data
->btn_invert
, MUIA_Disabled
, TRUE
);
653 SET(data
->btn_start
, MUIA_Disabled
, TRUE
);
657 data
->btn_cancel
, MUIM_Notify
, MUIA_Pressed
, FALSE
,
658 MUIV_Notify_Application
, 2, MUIM_Application_ReturnID
, MUIV_Application_ReturnID_Quit
663 data
->btn_all
, MUIM_Notify
, MUIA_Pressed
, FALSE
,
664 data
->lst_content
, 3, MUIM_CallHook
, &data
->change_selection_hook
, SETALL
669 data
->btn_none
, MUIM_Notify
, MUIA_Pressed
, FALSE
,
670 data
->lst_content
, 3, MUIM_CallHook
, &data
->change_selection_hook
, CLEARALL
675 data
->btn_invert
, MUIM_Notify
, MUIA_Pressed
, FALSE
,
676 data
->lst_content
, 3, MUIM_CallHook
, &data
->change_selection_hook
, INVERTALL
681 data
->lst_content
, MUIM_Notify
, MUIA_NList_EntryClick
, MUIV_EveryTime
,
682 data
->lst_content
, 3, MUIM_CallHook
, &data
->change_selection_hook
, INVERTSINGLE
687 data
->btn_start
, MUIM_Notify
, MUIA_Pressed
, FALSE
,
688 data
->lst_content
, 2, MUIM_CallHook
, &data
->start_hook
693 data
->str_file
, MUIM_Notify
, MUIA_String_Acknowledge
, MUIV_EveryTime
,
694 data
->lst_content
, 2, MUIM_CallHook
, &data
->read_file_hook
699 data
->str_targetdir
, MUIM_Notify
, MUIA_String_Acknowledge
, MUIV_EveryTime
,
700 data
->str_targetdir
, 2, MUIM_CallHook
, &data
->expand_dest_hook
703 if (is_file(archive
))
705 // fill the list if we have an existing file
708 data
->lst_content
, MUIM_CallHook
, &data
->read_file_hook
716 IPTR
UnarcGroup__OM_DISPOSE(Class
*CLASS
, Object
*self
, Msg message
)
718 struct UnarcGroup_DATA
*data
= INST_DATA(CLASS
, self
);
722 xadFreeInfo(data
->ai
);
723 xadFreeObjectA(data
->ai
, 0);
725 FreeVec(data
->targetpathname
);
727 return DoSuperMethodA(CLASS
, self
, message
);
733 UnarcGroup
, NULL
, MUIC_Group
, NULL
,
734 OM_NEW
, struct opSet
*,