2 Copyright © 2016-2018, 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/workbench.h>
12 #include <proto/alib.h>
14 #include <libraries/mui.h>
15 #include <mui/NList_mcc.h>
16 #include <mui/NListview_mcc.h>
19 #include <aros/debug.h>
20 #include <zune/customclasses.h>
24 #include "findgroup_class.h"
27 #define PATHNAMESIZE (1024)
32 Object
*str_path
, *str_pattern
, *str_contents
;
33 Object
*btn_start
, *btn_stop
, *btn_open
, *btn_view
, *btn_parent
;
37 struct Hook openwbobj_hook
;
38 struct Hook view_hook
;
39 struct Hook parent_hook
;
40 struct Hook activeentry_hook
;
48 struct FileInfoBlock fib
;
51 static struct Hook list_display_hook
, list_constr_hook
, list_destr_hook
, list_compare_hook
;
54 // =======================================================================================
56 static void display_doserror(Object
*app
, ULONG error
)
59 Fault(error
, NULL
, buffer
, sizeof buffer
);
60 MUI_Request(app
, NULL
, 0, _(MSG_APP_TITLE
), _(MSG_OK
), _(MSG_ERR_DOS
), buffer
);
63 // =======================================================================================
65 static BOOL
checkfile(Object
*app
, struct AnchorPath
*anchorpath
, STRPTR pattern
, STRPTR content
)
67 D(bug("[Find::checkfile] name %s pattern %s content %s\n", anchorpath
->ap_Info
.fib_FileName
, pattern
, content
));
69 // warning: this function is called from a sub process
73 if (anchorpath
->ap_Info
.fib_DirEntryType
> 0) // ignore directories
78 if ((pattern
[0] == '\0') || MatchPatternNoCase(pattern
, anchorpath
->ap_Info
.fib_FileName
))
80 if (content
&& (content
[0] != '\0'))
82 D(bug("[Find::checkfile] content search\n"));
85 LONG searchlen
= strlen(content
);
86 LONG textlen
= anchorpath
->ap_Info
.fib_Size
;
92 fh
= Open(anchorpath
->ap_Buf
, MODE_OLDFILE
);
95 text
= oldtext
= AllocVec(textlen
, MEMF_ANY
);
98 if (Read(fh
, text
, textlen
) == textlen
)
100 textlen
-= searchlen
;
103 for(i
= 0; i
< searchlen
; i
++)
105 if (ToUpper(text
[i
]) !=
124 // app must be NULL to avoid deadlocks
125 display_doserror(NULL
, IoErr());
131 MUI_Request(NULL
, NULL
, 0, _(MSG_APP_TITLE
),
132 _(MSG_OK
), _(MSG_ERR_NO_MEM
));
139 // app must be NULL to avoid deadlocks
140 display_doserror(NULL
, IoErr());
152 // =======================================================================================
154 AROS_UFH3(APTR
, list_constr_func
,
155 AROS_UFHA(struct Hook
*, h
, A0
),
156 AROS_UFHA(APTR
, pool
, A2
),
157 AROS_UFHA(struct Listentry
*, li
, A1
))
161 struct Listentry
*newentry
= AllocPooled(pool
, sizeof(struct Listentry
));
165 buflen
= strlen(li
->fullname
) + 1;
166 newentry
->fullname
= AllocPooled(pool
, buflen
);
167 if (newentry
->fullname
)
169 newentry
->namebuflen
= buflen
;
170 CopyMem(li
->fullname
, newentry
->fullname
, buflen
);
172 newentry
->fib
= li
->fib
;
179 // =======================================================================================
181 AROS_UFH3(void, list_destr_func
,
182 AROS_UFHA(struct Hook
*, h
, A0
),
183 AROS_UFHA(APTR
, pool
, A2
),
184 AROS_UFHA(struct Listentry
*, li
, A1
))
188 FreePooled(pool
, li
->fullname
, li
->namebuflen
);
189 FreePooled(pool
, li
, sizeof(struct Listentry
));
194 // =======================================================================================
196 AROS_UFH3S(LONG
, list_display_func
,
197 AROS_UFHA(struct Hook
*, h
, A0
),
198 AROS_UFHA(char **, array
, A2
),
199 AROS_UFHA(struct Listentry
*, li
, A1
))
205 static TEXT protbuf
[8], sizebuf
[20];
206 static TEXT datebuf
[20], timebuf
[20];
210 protbuf
[0] = li
->fib
.fib_Protection
& FIBF_SCRIPT
? 's' : '-';
211 protbuf
[1] = li
->fib
.fib_Protection
& FIBF_PURE
? 'p' : '-';
212 protbuf
[2] = li
->fib
.fib_Protection
& FIBF_ARCHIVE
? 'a' : '-';
214 // Not set means action is allowed!
215 protbuf
[3] = li
->fib
.fib_Protection
& FIBF_READ
? '-' : 'r';
216 protbuf
[4] = li
->fib
.fib_Protection
& FIBF_WRITE
? '-' : 'w';
217 protbuf
[5] = li
->fib
.fib_Protection
& FIBF_EXECUTE
? '-' : 'e';
218 protbuf
[6] = li
->fib
.fib_Protection
& FIBF_DELETE
? '-' : 'd';
222 snprintf(sizebuf
, sizeof sizebuf
, "%lu", (long unsigned int)li
->fib
.fib_Size
);
227 dt
.dat_Stamp
= li
->fib
.fib_Date
;
228 dt
.dat_Format
= FORMAT_DEF
;
230 dt
.dat_StrDay
= NULL
;
231 dt
.dat_StrDate
= datebuf
;
232 dt
.dat_StrTime
= timebuf
;
235 *array
++ = li
->fullname
;
240 *array
++ = li
->fib
.fib_Comment
;
244 *array
++ = (STRPTR
)_(MSG_LST_FULLPATH
);
245 *array
++ = (STRPTR
)_(MSG_LST_SIZE
);
246 *array
++ = (STRPTR
)_(MSG_LST_ATTRIBUTES
);
247 *array
++ = (STRPTR
)_(MSG_LST_DATE
);
248 *array
++ = (STRPTR
)_(MSG_LST_TIME
);
249 *array
++ = (STRPTR
)_(MSG_LST_COMMENT
);
257 // =======================================================================================
259 AROS_UFH3(LONG
, list_compare_func
,
260 AROS_UFHA(struct Hook
*, h
, A0
),
261 AROS_UFHA(struct Listentry
*, li1
, A2
),
262 AROS_UFHA(struct Listentry
*, li2
, A1
))
266 return stricmp(li2
->fullname
, li1
->fullname
);
272 // =======================================================================================
274 AROS_UFH3S(void, openwbobj_func
,
275 AROS_UFHA(struct Hook
*, h
, A0
),
276 AROS_UFHA(Object
*, obj
, A2
),
277 AROS_UFHA(APTR
, msg
, A1
))
281 D(bug("[Find::openwbobject_func] called\n"));
283 // struct FindGroup_DATA *data = h->h_Data;
284 struct Listentry
*entry
;
285 BPTR filelock
= (BPTR
)-1;
286 BPTR parentdirlock
= (BPTR
)-1;
287 BPTR olddirlock
= (BPTR
)-1;
289 DoMethod(obj
, MUIM_NList_GetEntry
, MUIV_NList_GetEntry_Active
, &entry
);
292 D(bug("[Find::openwbobj_func] name %s\n", entry
->fullname
));
294 // trying to change directory to file's parent directory
295 filelock
= Lock(entry
->fullname
, SHARED_LOCK
);
298 parentdirlock
= ParentDir(filelock
);
299 olddirlock
= CurrentDir(parentdirlock
);
302 D(bug("[Find::openwbobj_func] file %p parent %p olddir %p\n", filelock
, parentdirlock
, olddirlock
));
304 // execute program even if directory change failed
305 if (OpenWorkbenchObject(entry
->fullname
, TAG_DONE
) == FALSE
)
307 MUI_Request(_app(obj
), _win(obj
), 0, _(MSG_APP_TITLE
), _(MSG_OK
), _(MSG_ERR_NO_FILE
), entry
->fullname
);
310 if (olddirlock
!= (BPTR
)-1)
312 CurrentDir(olddirlock
);
314 if (parentdirlock
!= (BPTR
)-1)
316 UnLock(parentdirlock
);
318 if (filelock
!= (BPTR
)-1)
327 // =======================================================================================
329 AROS_UFH3S(void, view_func
,
330 AROS_UFHA(struct Hook
*, h
, A0
),
331 AROS_UFHA(Object
*, obj
, A2
),
332 AROS_UFHA(APTR
, msg
, A1
))
336 D(bug("[Find::view_func] called\n"));
338 // struct FindGroup_DATA *data = h->h_Data;
339 struct Listentry
*entry
;
340 TEXT command
[PATHNAMESIZE
];
343 DoMethod(obj
, MUIM_NList_GetEntry
, MUIV_NList_GetEntry_Active
, &entry
);
346 D(bug("[Find::view_func] viewing %s\n", entry
->fullname
));
347 con
= Open("CON:////Find Output/CLOSE/AUTO/WAIT", MODE_OLDFILE
);
348 snprintf(command
, sizeof command
, "SYS:Utilities/Multiview \"%s\"", entry
->fullname
);
349 if (SystemTags(command
,
356 display_doserror(_app(obj
), IoErr());
357 Close(con
); // an error occured, we must close con: ourselves
364 // =======================================================================================
366 AROS_UFH3S(void, parent_func
,
367 AROS_UFHA(struct Hook
*, h
, A0
),
368 AROS_UFHA(Object
*, obj
, A2
),
369 AROS_UFHA(APTR
, msg
, A1
))
373 D(bug("[Find::parent_func] called\n"));
375 // struct FindGroup_DATA *data = h->h_Data;
376 struct Listentry
*entry
;
379 TEXT buffer
[PATHNAMESIZE
];
381 DoMethod(obj
, MUIM_NList_GetEntry
, MUIV_NList_GetEntry_Active
, &entry
);
384 D(bug("[Find::parent_func] name %s\n", entry
->fullname
));
386 filelock
= Lock(entry
->fullname
, SHARED_LOCK
);
389 parentdirlock
= ParentDir(filelock
);
390 if (NameFromLock(parentdirlock
, buffer
, PATHNAMESIZE
))
392 D(bug("[Find::parent_func] parent %s\n", buffer
));
394 if (OpenWorkbenchObject(buffer
, TAG_DONE
) == FALSE
)
396 MUI_Request(_app(obj
), _win(obj
), 0, _(MSG_APP_TITLE
), _(MSG_OK
),
397 _(MSG_ERR_NO_DIR
), buffer
);
400 UnLock(parentdirlock
);
408 // =======================================================================================
410 AROS_UFH3S(void, activeentry_func
,
411 AROS_UFHA(struct Hook
*, h
, A0
),
412 AROS_UFHA(Object
*, obj
, A2
),
413 AROS_UFHA(APTR
, msg
, A1
))
417 D(bug("[activeentry_func] called\n"));
419 struct FindGroup_DATA
*data
= h
->h_Data
;
422 entry
= XGET(obj
, MUIA_List_Active
);
423 if (entry
== MUIV_NList_Active_Off
)
425 SET(data
->btn_open
, MUIA_Disabled
, TRUE
);
426 SET(data
->btn_view
, MUIA_Disabled
, TRUE
);
427 SET(data
->btn_parent
, MUIA_Disabled
, TRUE
);
431 SET(data
->btn_open
, MUIA_Disabled
, FALSE
);
432 SET(data
->btn_view
, MUIA_Disabled
, FALSE
);
433 SET(data
->btn_parent
, MUIA_Disabled
, FALSE
);
439 // =======================================================================================
441 Object
*FindGroup__OM_NEW(Class
*CLASS
, Object
*self
, struct opSet
*message
)
443 Object
*str_path
, *str_pattern
, *str_contents
;
444 Object
*btn_start
, *btn_stop
, *btn_open
, *btn_view
, *btn_parent
;
448 STRPTR pattern
= NULL
;
449 STRPTR contents
= NULL
;
451 struct TagItem
*tstate
= message
->ops_AttrList
;
452 struct TagItem
*tag
= NULL
;
454 while ((tag
= NextTagItem(&tstate
)) != NULL
)
458 case MUIA_FindGroup_Path
:
459 path
= (STRPTR
)tag
->ti_Data
;
462 case MUIA_FindGroup_Pattern
:
463 pattern
= (STRPTR
)tag
->ti_Data
;
466 case MUIA_FindGroup_Contents
:
467 contents
= (STRPTR
)tag
->ti_Data
;
472 if (path
== NULL
) path
= "SYS:";
473 if (pattern
== NULL
) pattern
= "";
474 if (contents
== NULL
) contents
= "";
476 list_constr_hook
.h_Entry
= (HOOKFUNC
)list_constr_func
;
477 list_destr_hook
.h_Entry
= (HOOKFUNC
)list_destr_func
;
478 list_display_hook
.h_Entry
= (HOOKFUNC
)list_display_func
;
479 list_compare_hook
.h_Entry
= (HOOKFUNC
)list_compare_func
;
482 self
= (Object
*) DoSuperNewTags
491 Child
, Label(_(MSG_LBL_PATH
)),
493 MUIA_Popasl_Type
, ASL_FileRequest
,
494 ASLFR_TitleText
, _(MSG_LBL_PATH
),
495 MUIA_Popstring_String
, str_path
= StringObject
,
497 MUIA_String_Contents
, path
,
500 MUIA_Popstring_Button
, PopButton(MUII_PopFile
),
502 Child
, Label(_(MSG_LBL_PATTERN
)),
503 Child
, str_pattern
= StringObject
,
505 MUIA_String_Contents
, pattern
,
508 Child
, Label(_(MSG_LBL_CONTENTS
)),
509 Child
, str_contents
= StringObject
,
511 MUIA_String_Contents
, contents
,
518 Child
, btn_start
= SimpleButton(_(MSG_BTN_START
)),
520 Child
, btn_stop
= SimpleButton(_(MSG_BTN_STOP
)),
524 Child
, lst_result
= NListviewObject
,
525 MUIA_NListview_NList
, NListObject
,
526 MUIA_NList_Format
, "BAR,P=\33r BAR,BAR,BAR,BAR,",
527 MUIA_NList_Title
, TRUE
,
528 MUIA_Frame
, MUIV_Frame_InputList
,
529 MUIA_NList_DisplayHook
, &list_display_hook
,
530 MUIA_NList_ConstructHook
, &list_constr_hook
,
531 MUIA_NList_DestructHook
, &list_destr_hook
,
532 MUIA_NList_CompareHook
, &list_compare_hook
,
538 Child
, btn_open
= SimpleButton(_(MSG_BTN_OPEN
)),
540 Child
, btn_view
= SimpleButton(_(MSG_BTN_VIEW
)),
542 Child
, btn_parent
= SimpleButton(_(MSG_BTN_DRAWER
)),
545 Child
, txt_status
= TextObject
,
550 TAG_MORE
, (IPTR
)message
->ops_AttrList
,
556 struct FindGroup_DATA
*data
= INST_DATA(CLASS
, self
);
558 // embed the process object
559 data
->scanproc
= MUI_NewObject(MUIC_Process
,
560 MUIA_Process_SourceClass
, CLASS
,
561 MUIA_Process_SourceObject
, self
,
562 MUIA_Process_Priority
, -1,
563 MUIA_Process_AutoLaunch
, FALSE
,
566 data
->str_path
= str_path
;
567 data
->str_pattern
= str_pattern
;
568 data
->str_contents
= str_contents
;
569 data
->btn_start
= btn_start
;
570 data
->btn_stop
= btn_stop
;
571 data
->btn_open
= btn_open
;
572 data
->btn_view
= btn_view
;
573 data
->btn_parent
= btn_parent
;
574 data
->lst_result
= lst_result
;
575 data
->txt_status
= txt_status
;
577 data
->openwbobj_hook
.h_Entry
= (HOOKFUNC
)openwbobj_func
;
578 data
->openwbobj_hook
.h_Data
= data
;
580 data
->view_hook
.h_Entry
= (HOOKFUNC
)view_func
;
581 data
->view_hook
.h_Data
= data
;
583 data
->parent_hook
.h_Entry
= (HOOKFUNC
)parent_func
;
584 data
->parent_hook
.h_Data
= data
;
586 data
->activeentry_hook
.h_Entry
= (HOOKFUNC
)activeentry_func
;
587 data
->activeentry_hook
.h_Data
= data
;
589 SET(data
->btn_stop
, MUIA_Disabled
, TRUE
);
591 SET(data
->btn_open
, MUIA_Disabled
, TRUE
);
592 SET(data
->btn_view
, MUIA_Disabled
, TRUE
);
593 SET(data
->btn_parent
, MUIA_Disabled
, TRUE
);
597 data
->btn_start
, MUIM_Notify
, MUIA_Pressed
, FALSE
,
598 self
, 1, MUIM_FindGroup_Start
603 data
->btn_stop
, MUIM_Notify
, MUIA_Pressed
, FALSE
,
604 self
, 1, MUIM_FindGroup_Stop
609 data
->btn_open
, MUIM_Notify
, MUIA_Pressed
, FALSE
,
610 self
, 2, MUIM_CallHook
, &data
->openwbobj_hook
615 data
->btn_view
, MUIM_Notify
, MUIA_Pressed
, FALSE
,
616 self
, 2, MUIM_CallHook
, &data
->view_hook
621 data
->btn_parent
, MUIM_Notify
, MUIA_Pressed
, FALSE
,
622 self
, 2, MUIM_CallHook
, &data
->parent_hook
627 data
->lst_result
, MUIM_Notify
, MUIA_NList_DoubleClick
, MUIV_EveryTime
,
628 self
, 2, MUIM_CallHook
, &data
->openwbobj_hook
633 data
->lst_result
, MUIM_Notify
, MUIA_NList_Active
, MUIV_EveryTime
,
634 self
, 2, MUIM_CallHook
, &data
->activeentry_hook
640 // =======================================================================================
642 IPTR
FindGroup__OM_DISPOSE(Class
*CLASS
, Object
*self
, Msg msg
)
644 struct FindGroup_DATA
*data
= INST_DATA(CLASS
, self
);
645 MUI_DisposeObject(data
->scanproc
);
646 return DoSuperMethodA(CLASS
, self
, msg
);
649 // =======================================================================================
651 IPTR
FindGroup__MUIM_Cleanup(Class
*CLASS
, Object
*self
, Msg msg
)
653 struct FindGroup_DATA
*data
= INST_DATA(CLASS
, self
);
655 DoMethod(data
->scanproc
, MUIM_Process_Kill
, 0);
657 return DoSuperMethodA(CLASS
, self
, msg
);
660 // =======================================================================================
662 IPTR
FindGroup__MUIM_Process_Process(Class
*CLASS
, Object
*self
, struct MUIP_Process_Process
*msg
)
664 // this is our sub process
666 D(bug("[Find::search process] called\n"));
668 struct FindGroup_DATA
*data
= INST_DATA(CLASS
, self
);
670 struct AnchorPath
*anchorpath
;
674 ULONG methodid1
= 0, methodid2
= 0;
676 STRPTR path
= (STRPTR
)XGET(data
->str_path
, MUIA_String_Contents
);
677 STRPTR srcpattern
= (STRPTR
)XGET(data
->str_pattern
, MUIA_String_Contents
);
678 STRPTR content
= (STRPTR
)XGET(data
->str_contents
, MUIA_String_Contents
);
680 destlen
= strlen(srcpattern
) * 2 + 2;
681 destpattern
= AllocVec(destlen
, MEMF_ANY
);
684 if (ParsePatternNoCase(srcpattern
, destpattern
, destlen
) < 0) // error
686 // app must be NULL to avoid deadlocks
687 MUI_Request(NULL
, NULL
, 0, _(MSG_APP_TITLE
), _(MSG_OK
), _(MSG_ERR_PATTERN
));
688 FreeVec(destpattern
);
693 // we must use PushMethod because we are in a sub process
694 methodid1
= DoMethod(_app(self
), MUIM_Application_PushMethod
, data
->lst_result
, 1, MUIM_NList_Clear
);
696 if (anchorpath
= AllocMem(sizeof(struct AnchorPath
) + PATHNAMESIZE
, MEMF_CLEAR
))
698 anchorpath
->ap_Strlen
= PATHNAMESIZE
;
699 anchorpath
->ap_Flags
= APF_DODIR
;
701 if ((error
= MatchFirst(path
, anchorpath
)) == 0)
707 // process stopped by user
711 if (anchorpath
->ap_Flags
& APF_DIDDIR
)
713 anchorpath
->ap_Flags
&= ~(APF_DODIR
| APF_DIDDIR
);
717 struct Listentry
*entry
;
718 D(bug("found %s\n", anchorpath
->ap_Buf
));
719 if (checkfile(_app(self
), anchorpath
, destpattern
, content
))
721 entry
= AllocVec(sizeof (struct Listentry
), MEMF_CLEAR
);
724 entry
->fullname
= StrDup(anchorpath
->ap_Buf
);
725 CopyMem(&anchorpath
->ap_Info
, &entry
->fib
, sizeof (entry
->fib
));
727 // we must use PushMethod because we are in a sub process
728 methodid2
= DoMethod(_app(self
), MUIM_Application_PushMethod
,
729 self
, 2, MUIM_FindGroup_AddEntry
, entry
);
732 FreeVec(entry
->fullname
);
737 anchorpath
->ap_Flags
= APF_DODIR
;
739 } while ((error
= MatchNext(anchorpath
)) == 0);
742 MatchEnd(anchorpath
);
744 if (!*msg
->kill
&& error
!= ERROR_NO_MORE_ENTRIES
)
746 // app must be NULL to avoid deadlocks
747 display_doserror(NULL
, error
);
750 FreeMem(anchorpath
, sizeof(struct AnchorPath
) + PATHNAMESIZE
);
753 FreeVec(destpattern
);
755 // prevent method execution after task has been killed
756 DoMethod(_app(self
), MUIM_Application_UnpushMethod
, self
, methodid1
, 0);
757 DoMethod(_app(self
), MUIM_Application_UnpushMethod
, self
, methodid2
, 0);
759 // Allow another start
760 SET(data
->btn_start
, MUIA_Disabled
, FALSE
);
761 SET(data
->btn_stop
, MUIA_Disabled
, TRUE
);
766 // =======================================================================================
768 IPTR
FindGroup__MUIM_FindGroup_Start(Class
*CLASS
, Object
*self
, Msg msg
)
770 struct FindGroup_DATA
*data
= INST_DATA(CLASS
, self
);
772 SET(data
->btn_start
, MUIA_Disabled
, TRUE
);
773 SET(data
->btn_stop
, MUIA_Disabled
, FALSE
);
774 DoMethod(data
->scanproc
, MUIM_Process_Launch
);
779 // =======================================================================================
781 IPTR
FindGroup__MUIM_FindGroup_Stop(Class
*CLASS
, Object
*self
, Msg msg
)
783 struct FindGroup_DATA
*data
= INST_DATA(CLASS
, self
);
785 DoMethod(data
->scanproc
, MUIM_Process_Kill
, 4);
786 SET(data
->btn_start
, MUIA_Disabled
, FALSE
);
787 SET(data
->btn_stop
, MUIA_Disabled
, TRUE
);
792 // =======================================================================================
794 IPTR
FindGroup__MUIM_FindGroup_AddEntry(Class
*CLASS
, Object
*self
, struct MUIP_FindGroup_AddEntry
*msg
)
796 D(bug("[Find::MUIM_FindGroup_AddEntry] started\n"));
797 struct FindGroup_DATA
*data
= INST_DATA(CLASS
, self
);
799 DoMethod(data
->lst_result
, MUIM_List_InsertSingle
, msg
->entry
, MUIV_List_Insert_Sorted
);
801 // we were called with PushMethod. After inserting the entry we can release the data
802 FreeVec(msg
->entry
->fullname
);
808 // =======================================================================================
812 FindGroup
, NULL
, MUIC_Group
, NULL
,
813 OM_NEW
, struct opSet
*,
816 MUIM_Process_Process
, struct MUIP_Process_Process
*,
817 MUIM_FindGroup_Start
, Msg
,
818 MUIM_FindGroup_Stop
, Msg
,
819 MUIM_FindGroup_AddEntry
, struct MUIP_FindGroup_AddEntry
*