2 Copyright © 2016, 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
;
90 fh
= Open(anchorpath
->ap_Buf
, MODE_OLDFILE
);
93 text
= oldtext
= AllocVec(textlen
, MEMF_ANY
);
96 if (Read(fh
, text
, textlen
) == textlen
)
101 for(i
= 0; i
< searchlen
; i
++)
103 if (ToUpper(text
[i
]) != ToUpper(content
[i
]))
121 // app must be NULL to avoid deadlocks
122 display_doserror(NULL
, IoErr());
128 MUI_Request(NULL
, NULL
, 0, _(MSG_APP_TITLE
), _(MSG_OK
), _(MSG_ERR_NO_MEM
));
135 // app must be NULL to avoid deadlocks
136 display_doserror(NULL
, IoErr());
147 // =======================================================================================
149 AROS_UFH3(APTR
, list_constr_func
,
150 AROS_UFHA(struct Hook
*, h
, A0
),
151 AROS_UFHA(APTR
, pool
, A2
),
152 AROS_UFHA(struct Listentry
*, li
, A1
))
156 struct Listentry
*newentry
= AllocPooled(pool
, sizeof(struct Listentry
));
160 buflen
= strlen(li
->fullname
) + 1;
161 newentry
->fullname
= AllocPooled(pool
, buflen
);
162 if (newentry
->fullname
)
164 newentry
->namebuflen
= buflen
;
165 CopyMem(li
->fullname
, newentry
->fullname
, buflen
);
167 newentry
->fib
= li
->fib
;
174 // =======================================================================================
176 AROS_UFH3(void, list_destr_func
,
177 AROS_UFHA(struct Hook
*, h
, A0
),
178 AROS_UFHA(APTR
, pool
, A2
),
179 AROS_UFHA(struct Listentry
*, li
, A1
))
183 FreePooled(pool
, li
->fullname
, li
->namebuflen
);
184 FreePooled(pool
, li
, sizeof(struct Listentry
));
189 // =======================================================================================
191 AROS_UFH3S(LONG
, list_display_func
,
192 AROS_UFHA(struct Hook
*, h
, A0
),
193 AROS_UFHA(char **, array
, A2
),
194 AROS_UFHA(struct Listentry
*, li
, A1
))
200 static TEXT protbuf
[8], sizebuf
[20];
201 static TEXT datebuf
[20], timebuf
[20];
205 protbuf
[0] = li
->fib
.fib_Protection
& FIBF_SCRIPT
? 's' : '-';
206 protbuf
[1] = li
->fib
.fib_Protection
& FIBF_PURE
? 'p' : '-';
207 protbuf
[2] = li
->fib
.fib_Protection
& FIBF_ARCHIVE
? 'a' : '-';
209 // Not set means action is allowed!
210 protbuf
[3] = li
->fib
.fib_Protection
& FIBF_READ
? '-' : 'r';
211 protbuf
[4] = li
->fib
.fib_Protection
& FIBF_WRITE
? '-' : 'w';
212 protbuf
[5] = li
->fib
.fib_Protection
& FIBF_EXECUTE
? '-' : 'e';
213 protbuf
[6] = li
->fib
.fib_Protection
& FIBF_DELETE
? '-' : 'd';
217 snprintf(sizebuf
, sizeof sizebuf
, "%lu", (long unsigned int)li
->fib
.fib_Size
);
222 dt
.dat_Stamp
= li
->fib
.fib_Date
;
223 dt
.dat_Format
= FORMAT_DEF
;
225 dt
.dat_StrDay
= NULL
;
226 dt
.dat_StrDate
= datebuf
;
227 dt
.dat_StrTime
= timebuf
;
230 *array
++ = li
->fullname
;
235 *array
++ = li
->fib
.fib_Comment
;
239 *array
++ = (STRPTR
)_(MSG_LST_FULLPATH
);
240 *array
++ = (STRPTR
)_(MSG_LST_SIZE
);
241 *array
++ = (STRPTR
)_(MSG_LST_ATTRIBUTES
);
242 *array
++ = (STRPTR
)_(MSG_LST_DATE
);
243 *array
++ = (STRPTR
)_(MSG_LST_TIME
);
244 *array
++ = (STRPTR
)_(MSG_LST_COMMENT
);
252 // =======================================================================================
254 AROS_UFH3(LONG
, list_compare_func
,
255 AROS_UFHA(struct Hook
*, h
, A0
),
256 AROS_UFHA(struct Listentry
*, li1
, A2
),
257 AROS_UFHA(struct Listentry
*, li2
, A1
))
261 return stricmp(li2
->fullname
, li1
->fullname
);
267 // =======================================================================================
269 AROS_UFH3S(void, openwbobj_func
,
270 AROS_UFHA(struct Hook
*, h
, A0
),
271 AROS_UFHA(Object
*, obj
, A2
),
272 AROS_UFHA(APTR
, msg
, A1
))
276 D(bug("[Find::openwbobject_func] called\n"));
278 // struct FindGroup_DATA *data = h->h_Data;
279 struct Listentry
*entry
;
280 BPTR filelock
= (BPTR
)-1;
281 BPTR parentdirlock
= (BPTR
)-1;
282 BPTR olddirlock
= (BPTR
)-1;
284 DoMethod(obj
, MUIM_NList_GetEntry
, MUIV_NList_GetEntry_Active
, &entry
);
287 D(bug("[Find::openwbobj_func] name %s\n", entry
->fullname
));
289 // trying to change directory to file's parent directory
290 filelock
= Lock(entry
->fullname
, SHARED_LOCK
);
293 parentdirlock
= ParentDir(filelock
);
294 olddirlock
= CurrentDir(parentdirlock
);
297 D(bug("[Find::openwbobj_func] file %p parent %p olddir %p\n", filelock
, parentdirlock
, olddirlock
));
299 // execute program even if directory change failed
300 if (OpenWorkbenchObject(entry
->fullname
, TAG_DONE
) == FALSE
)
302 MUI_Request(_app(obj
), _win(obj
), 0, _(MSG_APP_TITLE
), _(MSG_OK
), _(MSG_ERR_NO_FILE
), entry
->fullname
);
305 if (olddirlock
!= (BPTR
)-1)
307 CurrentDir(olddirlock
);
309 if (parentdirlock
!= (BPTR
)-1)
311 UnLock(parentdirlock
);
313 if (filelock
!= (BPTR
)-1)
322 // =======================================================================================
324 AROS_UFH3S(void, view_func
,
325 AROS_UFHA(struct Hook
*, h
, A0
),
326 AROS_UFHA(Object
*, obj
, A2
),
327 AROS_UFHA(APTR
, msg
, A1
))
331 D(bug("[Find::view_func] called\n"));
333 // struct FindGroup_DATA *data = h->h_Data;
334 struct Listentry
*entry
;
335 TEXT command
[PATHNAMESIZE
];
338 DoMethod(obj
, MUIM_NList_GetEntry
, MUIV_NList_GetEntry_Active
, &entry
);
341 D(bug("[Find::view_func] viewing %s\n", entry
->fullname
));
342 con
= Open("CON:////Find Output/CLOSE/AUTO/WAIT", MODE_OLDFILE
);
343 snprintf(command
, sizeof command
, "SYS:Utilities/Multiview \"%s\"", entry
->fullname
);
344 if (SystemTags(command
,
351 display_doserror(_app(obj
), IoErr());
352 Close(con
); // an error occured, we must close con: ourselves
359 // =======================================================================================
361 AROS_UFH3S(void, parent_func
,
362 AROS_UFHA(struct Hook
*, h
, A0
),
363 AROS_UFHA(Object
*, obj
, A2
),
364 AROS_UFHA(APTR
, msg
, A1
))
368 D(bug("[Find::parent_func] called\n"));
370 // struct FindGroup_DATA *data = h->h_Data;
371 struct Listentry
*entry
;
374 TEXT buffer
[PATHNAMESIZE
];
376 DoMethod(obj
, MUIM_NList_GetEntry
, MUIV_NList_GetEntry_Active
, &entry
);
379 D(bug("[Find::parent_func] name %s\n", entry
->fullname
));
381 filelock
= Lock(entry
->fullname
, SHARED_LOCK
);
384 parentdirlock
= ParentDir(filelock
);
385 if (NameFromLock(parentdirlock
, buffer
, PATHNAMESIZE
))
387 D(bug("[Find::parent_func] parent %s\n", buffer
));
389 if (OpenWorkbenchObject(buffer
, TAG_DONE
) == FALSE
)
391 MUI_Request(_app(obj
), _win(obj
), 0, _(MSG_APP_TITLE
), _(MSG_OK
),
392 _(MSG_ERR_NO_DIR
), buffer
);
395 UnLock(parentdirlock
);
403 // =======================================================================================
405 AROS_UFH3S(void, activeentry_func
,
406 AROS_UFHA(struct Hook
*, h
, A0
),
407 AROS_UFHA(Object
*, obj
, A2
),
408 AROS_UFHA(APTR
, msg
, A1
))
412 D(bug("[activeentry_func] called\n"));
414 struct FindGroup_DATA
*data
= h
->h_Data
;
417 entry
= XGET(obj
, MUIA_List_Active
);
418 if (entry
== MUIV_NList_Active_Off
)
420 SET(data
->btn_open
, MUIA_Disabled
, TRUE
);
421 SET(data
->btn_view
, MUIA_Disabled
, TRUE
);
422 SET(data
->btn_parent
, MUIA_Disabled
, TRUE
);
426 SET(data
->btn_open
, MUIA_Disabled
, FALSE
);
427 SET(data
->btn_view
, MUIA_Disabled
, FALSE
);
428 SET(data
->btn_parent
, MUIA_Disabled
, FALSE
);
434 // =======================================================================================
436 Object
*FindGroup__OM_NEW(Class
*CLASS
, Object
*self
, struct opSet
*message
)
438 Object
*str_path
, *str_pattern
, *str_contents
;
439 Object
*btn_start
, *btn_stop
, *btn_open
, *btn_view
, *btn_parent
;
443 STRPTR pattern
= NULL
;
444 STRPTR contents
= NULL
;
446 struct TagItem
*tstate
= message
->ops_AttrList
;
447 struct TagItem
*tag
= NULL
;
449 while ((tag
= NextTagItem(&tstate
)) != NULL
)
453 case MUIA_FindGroup_Path
:
454 path
= (STRPTR
)tag
->ti_Data
;
457 case MUIA_FindGroup_Pattern
:
458 pattern
= (STRPTR
)tag
->ti_Data
;
461 case MUIA_FindGroup_Contents
:
462 contents
= (STRPTR
)tag
->ti_Data
;
467 if (path
== NULL
) path
= "SYS:";
468 if (pattern
== NULL
) pattern
= "";
469 if (contents
== NULL
) contents
= "";
471 list_constr_hook
.h_Entry
= (HOOKFUNC
)list_constr_func
;
472 list_destr_hook
.h_Entry
= (HOOKFUNC
)list_destr_func
;
473 list_display_hook
.h_Entry
= (HOOKFUNC
)list_display_func
;
474 list_compare_hook
.h_Entry
= (HOOKFUNC
)list_compare_func
;
477 self
= (Object
*) DoSuperNewTags
486 Child
, Label(_(MSG_LBL_PATH
)),
488 MUIA_Popasl_Type
, ASL_FileRequest
,
489 ASLFR_TitleText
, _(MSG_LBL_PATH
),
490 MUIA_Popstring_String
, str_path
= StringObject
,
492 MUIA_String_Contents
, path
,
495 MUIA_Popstring_Button
, PopButton(MUII_PopFile
),
497 Child
, Label(_(MSG_LBL_PATTERN
)),
498 Child
, str_pattern
= StringObject
,
500 MUIA_String_Contents
, pattern
,
503 Child
, Label(_(MSG_LBL_CONTENTS
)),
504 Child
, str_contents
= StringObject
,
506 MUIA_String_Contents
, contents
,
513 Child
, btn_start
= SimpleButton(_(MSG_BTN_START
)),
515 Child
, btn_stop
= SimpleButton(_(MSG_BTN_STOP
)),
519 Child
, lst_result
= NListviewObject
,
520 MUIA_NListview_NList
, NListObject
,
521 MUIA_NList_Format
, "BAR,P=\33r BAR,BAR,BAR,BAR,",
522 MUIA_NList_Title
, TRUE
,
523 MUIA_Frame
, MUIV_Frame_InputList
,
524 MUIA_NList_DisplayHook
, &list_display_hook
,
525 MUIA_NList_ConstructHook
, &list_constr_hook
,
526 MUIA_NList_DestructHook
, &list_destr_hook
,
527 MUIA_NList_CompareHook
, &list_compare_hook
,
533 Child
, btn_open
= SimpleButton(_(MSG_BTN_OPEN
)),
535 Child
, btn_view
= SimpleButton(_(MSG_BTN_VIEW
)),
537 Child
, btn_parent
= SimpleButton(_(MSG_BTN_DRAWER
)),
540 Child
, txt_status
= TextObject
,
545 TAG_MORE
, (IPTR
)message
->ops_AttrList
,
551 struct FindGroup_DATA
*data
= INST_DATA(CLASS
, self
);
553 // embed the process object
554 data
->scanproc
= MUI_NewObject(MUIC_Process
,
555 MUIA_Process_SourceClass
, CLASS
,
556 MUIA_Process_SourceObject
, self
,
557 MUIA_Process_Priority
, -1,
558 MUIA_Process_AutoLaunch
, FALSE
,
561 data
->str_path
= str_path
;
562 data
->str_pattern
= str_pattern
;
563 data
->str_contents
= str_contents
;
564 data
->btn_start
= btn_start
;
565 data
->btn_stop
= btn_stop
;
566 data
->btn_open
= btn_open
;
567 data
->btn_view
= btn_view
;
568 data
->btn_parent
= btn_parent
;
569 data
->lst_result
= lst_result
;
570 data
->txt_status
= txt_status
;
572 data
->openwbobj_hook
.h_Entry
= (HOOKFUNC
)openwbobj_func
;
573 data
->openwbobj_hook
.h_Data
= data
;
575 data
->view_hook
.h_Entry
= (HOOKFUNC
)view_func
;
576 data
->view_hook
.h_Data
= data
;
578 data
->parent_hook
.h_Entry
= (HOOKFUNC
)parent_func
;
579 data
->parent_hook
.h_Data
= data
;
581 data
->activeentry_hook
.h_Entry
= (HOOKFUNC
)activeentry_func
;
582 data
->activeentry_hook
.h_Data
= data
;
584 SET(data
->btn_open
, MUIA_Disabled
, TRUE
);
585 SET(data
->btn_view
, MUIA_Disabled
, TRUE
);
586 SET(data
->btn_parent
, MUIA_Disabled
, TRUE
);
590 data
->btn_start
, MUIM_Notify
, MUIA_Pressed
, FALSE
,
591 self
, 1, MUIM_FindGroup_Start
596 data
->btn_stop
, MUIM_Notify
, MUIA_Pressed
, FALSE
,
597 self
, 1, MUIM_FindGroup_Stop
602 data
->btn_open
, MUIM_Notify
, MUIA_Pressed
, FALSE
,
603 self
, 2, MUIM_CallHook
, &data
->openwbobj_hook
608 data
->btn_view
, MUIM_Notify
, MUIA_Pressed
, FALSE
,
609 self
, 2, MUIM_CallHook
, &data
->view_hook
614 data
->btn_parent
, MUIM_Notify
, MUIA_Pressed
, FALSE
,
615 self
, 2, MUIM_CallHook
, &data
->parent_hook
620 data
->lst_result
, MUIM_Notify
, MUIA_NList_DoubleClick
, MUIV_EveryTime
,
621 self
, 2, MUIM_CallHook
, &data
->openwbobj_hook
626 data
->lst_result
, MUIM_Notify
, MUIA_NList_Active
, MUIV_EveryTime
,
627 self
, 2, MUIM_CallHook
, &data
->activeentry_hook
633 // =======================================================================================
635 IPTR
FindGroup__OM_DISPOSE(Class
*CLASS
, Object
*self
, Msg msg
)
637 struct FindGroup_DATA
*data
= INST_DATA(CLASS
, self
);
638 MUI_DisposeObject(data
->scanproc
);
639 return DoSuperMethodA(CLASS
, self
, msg
);
642 // =======================================================================================
644 IPTR
FindGroup__MUIM_Cleanup(Class
*CLASS
, Object
*self
, Msg msg
)
646 struct FindGroup_DATA
*data
= INST_DATA(CLASS
, self
);
648 DoMethod(data
->scanproc
, MUIM_Process_Kill
, 0);
650 return DoSuperMethodA(CLASS
, self
, msg
);
653 // =======================================================================================
655 IPTR
FindGroup__MUIM_Process_Process(Class
*CLASS
, Object
*self
, struct MUIP_Process_Process
*msg
)
657 // this is our sub process
659 D(bug("[Find::search process] called\n"));
661 struct FindGroup_DATA
*data
= INST_DATA(CLASS
, self
);
663 struct AnchorPath
*anchorpath
;
667 ULONG methodid1
= 0, methodid2
= 0;
669 STRPTR path
= (STRPTR
)XGET(data
->str_path
, MUIA_String_Contents
);
670 STRPTR srcpattern
= (STRPTR
)XGET(data
->str_pattern
, MUIA_String_Contents
);
671 STRPTR content
= (STRPTR
)XGET(data
->str_contents
, MUIA_String_Contents
);
673 destlen
= strlen(srcpattern
) * 2 + 2;
674 destpattern
= AllocVec(destlen
, MEMF_ANY
);
677 if (ParsePatternNoCase(srcpattern
, destpattern
, destlen
) < 0) // error
679 // app must be NULL to avoid deadlocks
680 MUI_Request(NULL
, NULL
, 0, _(MSG_APP_TITLE
), _(MSG_OK
), _(MSG_ERR_PATTERN
));
681 FreeVec(destpattern
);
686 // we must use PushMethod because we are in a sub process
687 methodid1
= DoMethod(_app(self
), MUIM_Application_PushMethod
, data
->lst_result
, 1, MUIM_NList_Clear
);
689 if (anchorpath
= AllocMem(sizeof(struct AnchorPath
) + PATHNAMESIZE
, MEMF_CLEAR
))
691 anchorpath
->ap_Strlen
= PATHNAMESIZE
;
692 anchorpath
->ap_Flags
= APF_DODIR
;
694 if ((error
= MatchFirst(path
, anchorpath
)) == 0)
700 // process stopped by user
704 if (anchorpath
->ap_Flags
& APF_DIDDIR
)
706 anchorpath
->ap_Flags
&= ~(APF_DODIR
| APF_DIDDIR
);
710 struct Listentry
*entry
;
711 D(bug("found %s\n", anchorpath
->ap_Buf
));
712 if (checkfile(_app(self
), anchorpath
, destpattern
, content
))
714 entry
= AllocVec(sizeof (struct Listentry
), MEMF_CLEAR
);
717 entry
->fullname
= StrDup(anchorpath
->ap_Buf
);
718 CopyMem(&anchorpath
->ap_Info
, &entry
->fib
, sizeof (entry
->fib
));
720 // we must use PushMethod because we are in a sub process
721 methodid2
= DoMethod(_app(self
), MUIM_Application_PushMethod
,
722 self
, 2, MUIM_FindGroup_AddEntry
, entry
);
725 FreeVec(entry
->fullname
);
730 anchorpath
->ap_Flags
= APF_DODIR
;
732 } while ((error
= MatchNext(anchorpath
)) == 0);
735 MatchEnd(anchorpath
);
737 if (!*msg
->kill
&& error
!= ERROR_NO_MORE_ENTRIES
)
739 // app must be NULL to avoid deadlocks
740 display_doserror(NULL
, error
);
743 FreeMem(anchorpath
, sizeof(struct AnchorPath
) + PATHNAMESIZE
);
746 FreeVec(destpattern
);
748 // prevent method execution after task has been killed
749 DoMethod(_app(self
), MUIM_Application_UnpushMethod
, self
, methodid1
, 0);
750 DoMethod(_app(self
), MUIM_Application_UnpushMethod
, self
, methodid2
, 0);
755 // =======================================================================================
757 IPTR
FindGroup__MUIM_FindGroup_Start(Class
*CLASS
, Object
*self
, Msg msg
)
759 struct FindGroup_DATA
*data
= INST_DATA(CLASS
, self
);
761 DoMethod(data
->scanproc
, MUIM_Process_Launch
);
766 // =======================================================================================
768 IPTR
FindGroup__MUIM_FindGroup_Stop(Class
*CLASS
, Object
*self
, Msg msg
)
770 struct FindGroup_DATA
*data
= INST_DATA(CLASS
, self
);
772 DoMethod(data
->scanproc
, MUIM_Process_Kill
, 4);
777 // =======================================================================================
779 IPTR
FindGroup__MUIM_FindGroup_AddEntry(Class
*CLASS
, Object
*self
, struct MUIP_FindGroup_AddEntry
*msg
)
781 D(bug("[Find::MUIM_FindGroup_AddEntry] started\n"));
782 struct FindGroup_DATA
*data
= INST_DATA(CLASS
, self
);
784 DoMethod(data
->lst_result
, MUIM_List_InsertSingle
, msg
->entry
, MUIV_List_Insert_Sorted
);
786 // we were called with PushMethod. After inserting the entry we can release the data
787 FreeVec(msg
->entry
->fullname
);
793 // =======================================================================================
797 FindGroup
, NULL
, MUIC_Group
, NULL
,
798 OM_NEW
, struct opSet
*,
801 MUIM_Process_Process
, struct MUIP_Process_Process
*,
802 MUIM_FindGroup_Start
, Msg
,
803 MUIM_FindGroup_Stop
, Msg
,
804 MUIM_FindGroup_AddEntry
, struct MUIP_FindGroup_AddEntry
*