Fixed binary search: no more infinite loops when vendor is unknown.
[tangerine.git] / workbench / libs / asl / filereqsupport.c
blob890736a1aa830ec534121c13df82dfddf14df2b9
1 /*
2 Copyright © 1995-2007, The AROS Development Team. All rights reserved.
3 $Id$
4 */
7 #include <proto/exec.h>
8 #include <proto/dos.h>
9 #include <proto/intuition.h>
10 #include <proto/graphics.h>
11 #include <proto/utility.h>
12 #include <exec/memory.h>
13 #include <dos/dos.h>
14 #include <dos/exall.h>
15 #include <dos/dosasl.h>
16 #include <dos/datetime.h>
17 #include <dos/filehandler.h>
18 #include <intuition/gadgetclass.h>
19 #include <stdio.h>
20 #include <string.h>
21 #include <clib/macros.h>
23 #include "asl_intern.h"
24 #include "filereqsupport.h"
25 #include "filereqhooks.h"
26 #include "specialreq.h"
27 #include "layout.h"
29 #define CATCOMP_NUMBERS
30 #include "strings.h"
32 #define SDEBUG 0
33 #define DEBUG 0
34 //#define ADEBUG 0
36 #include <aros/debug.h>
38 /*****************************************************************************************/
40 static WORD FRCompareDirectoryNodes(struct IntFileReq *ifreq, struct ASLLVFileReqNode *node1,
41 struct ASLLVFileReqNode *node2, struct AslBase_intern *AslBase);
44 /*****************************************************************************************/
46 static void fixpath(char *pathstring)
48 char *start;
49 WORD i, len;
51 /* tricky slash stuff:
53 work:pictures/ --> work:pictures
54 work:pictures// --> work:
55 work:pictures/// --> work:/
56 work:pictures//// --> work://
57 /pics/ --> /pics
58 /pics// --> /
59 /pics/// --> //
60 /pics//pics --> /pics
61 /pics//pics/ --> /pics
62 /pics/scans//// --> //
66 start = strrchr(pathstring,':');
67 if (start)
69 start++;
70 } else {
71 start = pathstring;
74 for(; (i = len = strlen(start)); )
76 char *sp = start;
78 /* skip leading slashes */
80 while(i && (*sp == '/'))
82 i--;
83 sp++;
86 if (i)
88 char *sp2;
90 if((sp2 = strstr(sp, "//")))
92 char *sp3 = sp2;
94 while(sp3 > sp)
96 char c = sp3[-1];
98 if (c == '/') break;
99 sp3--;
102 memmove(sp3, sp2 + 2, strlen(sp2 + 2) + 1);
104 continue;
107 } /* if path is something more than just leading slashes */
109 break;
111 } /* for(; (i = len = strlen(start)); ) */
113 /* kill trailing slash */
115 i = strlen(start);
116 if (i >= 2)
118 if ((start[i - 1] == '/') &&
119 (start[i - 2] != '/'))
121 start[--i] = '\0';
126 /*****************************************************************************************/
128 void FRRefreshListview(struct LayoutData *ld, struct AslBase_intern *AslBase)
130 struct FRUserData *udata = (struct FRUserData *)ld->ld_UserData;
131 struct TagItem set_tags[] =
133 {ASLLV_Labels, (IPTR)&udata->ListviewList },
134 {TAG_DONE }
137 SetGadgetAttrsA((struct Gadget *)udata->Listview, ld->ld_Window, NULL, set_tags);
140 /*****************************************************************************************/
142 void FRFreeListviewNode(struct ASLLVFileReqNode *node, struct LayoutData *ld, struct AslBase_intern *AslBase)
144 WORD i;
146 for(i = 0; i < ASLLV_MAXCOLUMNS; i++)
148 if (node->text[i] && !(node->dontfreetext & (1 << i)))
150 FreePooled(ld->ld_IntReq->ir_MemPool, node->text[i], strlen(node->text[i]) + 1);
154 #ifdef __MORPHOS__
155 if (node->type == ASLLV_FRNTYPE_VOLUMES)
156 FreePooled(ld->ld_IntReq->ir_MemPool, node->node.ln_Name, strlen(node->node.ln_Name) + 1);
157 #endif
159 FreePooled(ld->ld_IntReq->ir_MemPool, node, sizeof(struct ASLLVFileReqNode));
162 /*****************************************************************************************/
164 void FRFreeListviewList(struct LayoutData *ld, struct AslBase_intern *AslBase)
166 struct FRUserData *udata = (struct FRUserData *)ld->ld_UserData;
167 struct ASLLVFileReqNode *node, *succ;
168 struct TagItem set_tags [] =
170 {ASLLV_Labels , 0 },
171 {TAG_DONE }
174 if (udata->Listview)
176 SetGadgetAttrsA((struct Gadget *)udata->Listview, ld->ld_Window, NULL, set_tags);
179 ForeachNodeSafe(&udata->ListviewList, node, succ)
181 FRFreeListviewNode(node, ld, AslBase);
184 NEWLIST(&udata->ListviewList);
188 /*****************************************************************************************/
190 void FRReSortListview(struct LayoutData *ld, struct AslBase_intern *AslBase)
192 struct FRUserData *udata = (struct FRUserData *)ld->ld_UserData;
193 struct IntFileReq *ifreq = (struct IntFileReq *)ld->ld_IntReq;
194 struct Node *node, *succ;
195 struct List templist;
196 struct TagItem set_tags [] =
198 {ASLLV_Labels , 0 },
199 {ASLLV_Top , 0 },
200 {TAG_DONE }
202 IPTR old_top;
204 if (udata->Flags & FRFLG_SHOWING_VOLUMES) return;
206 GetAttr(ASLLV_Top, udata->Listview, &old_top);
208 SetGadgetAttrsA((struct Gadget *)udata->Listview, ld->ld_Window, NULL, set_tags);
210 NEWLIST(&templist);
212 ForeachNodeSafe(&udata->ListviewList, node, succ)
214 Remove(node);
215 MARK_UNSELECTED(node);
216 AddTail(&templist, node);
219 ForeachNodeSafe(&templist, node, succ)
221 SortInNode(ifreq, &udata->ListviewList, node, (APTR)FRCompareDirectoryNodes, AslBase);
224 set_tags[0].ti_Data = (IPTR)&udata->ListviewList;
225 set_tags[1].ti_Data = old_top;
227 SetGadgetAttrsA((struct Gadget *)udata->Listview, ld->ld_Window, NULL, set_tags);
230 /*****************************************************************************************/
232 void FRDirectoryScanSymbolState(struct LayoutData *ld, BOOL on, struct AslBase_intern *AslBase)
235 if (ld->ld_Window)
237 struct FRUserData *udata = (struct FRUserData *)ld->ld_UserData;
238 struct TagItem set_tags[] =
240 {GA_Selected , on },
241 {TAG_DONE }
244 SetAttrsA(udata->DirectoryScanSymbol, set_tags);
245 RefreshGList((struct Gadget *)udata->DirectoryScanSymbol, ld->ld_Window, NULL, 1);
249 /*****************************************************************************************/
251 static void FRCalcColumnWidths(struct LayoutData *ld, struct AslBase_intern *AslBase)
253 struct FRUserData *udata = (struct FRUserData *)ld->ld_UserData;
254 struct ASLLVFileReqNode *node;
255 WORD i;
257 for(i = 0; i < ASLLV_MAXCOLUMNS; i++)
259 udata->LVColumnWidth[i] = 0;
262 ForeachNode(&udata->ListviewList, node)
264 for(i = 0; i < ASLLV_MAXCOLUMNS; i++)
266 WORD w;
268 if (node->text[i])
270 w = TextLength(&ld->ld_DummyRP, node->text[i], strlen(node->text[i]));
271 if (w > udata->LVColumnWidth[i]) udata->LVColumnWidth[i] = w;
276 if (udata->LVColumnWidth[0] < FREQ_MIN_FILECOLUMNWIDTH)
278 udata->LVColumnWidth[0] = FREQ_MIN_FILECOLUMNWIDTH;
283 /*****************************************************************************************/
285 static WORD FRCompareDirectoryNodes(struct IntFileReq *ifreq, struct ASLLVFileReqNode *node1,
286 struct ASLLVFileReqNode *node2, struct AslBase_intern *AslBase)
288 WORD pri1 = (node1->subtype > 0) ? 1 : 0;
289 WORD pri2 = (node2->subtype > 0) ? 1 : 0;
290 WORD diff = (pri2 - pri1) * -(ifreq->ifr_SortDrawers - 1);
291 LONG bigdiff;
293 if (!diff)
295 switch(ifreq->ifr_SortBy)
297 case ASLFRSORTBY_Name:
298 diff = Stricmp(node1->node.ln_Name, node2->node.ln_Name);
299 break;
301 case ASLFRSORTBY_Date:
302 bigdiff = CompareDates((const struct DateStamp *)&node2->date, (const struct DateStamp *)&node1->date);
303 if (bigdiff < 0)
305 diff = -1;
306 } else if (bigdiff > 0)
308 diff = 1;
310 break;
312 case ASLFRSORTBY_Size:
313 if (node1->filesize < node2->filesize)
315 diff = -1;
317 else if (node1->filesize > node2->filesize)
319 diff = 1;
321 break;
324 if (ifreq->ifr_SortOrder == ASLFRSORTORDER_Descend) diff = -diff;
327 return diff;
330 BOOL FRGetDirectory(STRPTR path, struct LayoutData *ld, struct AslBase_intern *AslBase)
332 struct FRUserData *udata = (struct FRUserData *)ld->ld_UserData;
333 struct IntFileReq *ifreq = (struct IntFileReq *)ld->ld_IntReq;
334 struct FileRequester *freq = (struct FileRequester *)ld->ld_Req;
335 struct FileInfoBlock *fib;
336 UBYTE parsedpattern[MAX_PATTERN_LEN * 2 + 3];
337 BPTR lock;
338 BOOL dopatternstring = FALSE, success = FALSE;
340 FRDirectoryScanSymbolState(ld, TRUE, AslBase);
342 FRFreeListviewList(ld, AslBase);
343 FRMultiSelectOnOff(ld, (ifreq->ifr_Flags1 & FRF_DOMULTISELECT) ? TRUE : FALSE, AslBase);
345 if (ifreq->ifr_Flags1 & FRF_DOPATTERNS)
347 char *pat;
349 GetAttr(STRINGA_TextVal, udata->PatternGad, (IPTR *)&pat);
350 if (pat[0])
352 if (ParsePatternNoCase(pat, parsedpattern, MAX_PATTERN_LEN * 2 + 3) != -1)
354 dopatternstring = TRUE;
359 lock = Lock(path, ACCESS_READ);
360 if (!lock)
362 D(bug("Could not lock directory \"%s\"\n", path));
364 else
366 fib = AllocDosObject(DOS_FIB, NULL);
367 if (fib)
369 success = Examine(lock, fib);
371 if (success && fib->fib_DirEntryType > 0) for(;;)
373 struct ASLLVFileReqNode *node;
374 BOOL ok, addentry = TRUE;
376 ok = ExNext(lock, fib);
378 if (!ok)
380 if (IoErr() == ERROR_NO_MORE_ENTRIES) break;
381 success = FALSE;
382 continue;
385 /* add to list checks which affect only files */
387 if (fib->fib_DirEntryType < 0)
389 if (ifreq->ifr_Flags2 & FRF_DRAWERSONLY) addentry = FALSE;
391 if (addentry && (ifreq->ifr_Flags2 & FRF_REJECTICONS))
393 WORD len = strlen(fib->fib_FileName);
394 if (len >= 5)
396 if (Stricmp(fib->fib_FileName + len - 5, ".info") == 0) addentry = FALSE;
400 if (addentry && dopatternstring)
402 if (!MatchPatternNoCase(parsedpattern, fib->fib_FileName)) addentry = FALSE;
405 if (addentry && ifreq->ifr_AcceptPattern)
407 if (!MatchPatternNoCase(ifreq->ifr_AcceptPattern, fib->fib_FileName)) addentry = FALSE;
410 if (addentry && ifreq->ifr_RejectPattern)
412 if (MatchPatternNoCase(ifreq->ifr_RejectPattern, fib->fib_FileName)) addentry = FALSE;
415 } /* if (fib->fib_DirEntryType < 0) */
417 /* add to list checks which affect both files and drawers */
419 if (addentry && ifreq->ifr_HookFunc && (ifreq->ifr_Flags1 & FRF_FILTERFUNC))
421 struct AnchorPath ap;
422 STRPTR old_frdrawer;
424 /* FIXME: is ap.ap_Info enough for the hookfunc */
426 memset(&ap, 0, sizeof(ap));
427 ap.ap_Info = *fib;
429 /* Some user filter functions access freq->fr_Drawer :-( */
431 old_frdrawer = freq->fr_Drawer;
432 freq->fr_Drawer = path;
434 D(bug("FRGetDirectory: 1 fr_Drawer 0x%lx <%s>\n",path,path));
436 /* return code 0 means, add to list */
438 #ifdef __MORPHOS__
440 ULONG ret;
441 UWORD *funcptr = ifreq->ifr_HookFunc;
442 ULONG *p = (ULONG *)REG_A7 - 3;
444 p[0] = (ULONG)FRF_FILTERFUNC;
445 p[1] = (ULONG)&ap;
446 p[2] = (ULONG)freq;
447 REG_A7 = (ULONG)p;
449 if (*funcptr >= (UWORD)0xFF00)
450 REG_A7 -= 4;
452 REG_A4 = (ULONG)ifreq->ifr_IntReq.ir_BasePtr; /* Compatability */
454 ret = (ULONG)(*MyEmulHandle->EmulCallDirect68k)(funcptr);
456 if (*funcptr >= (UWORD)0xFF00)
457 REG_A7 += 4;
459 REG_A7 += (3*4);
461 if (ret != 0)
462 addentry = FALSE;
464 #else
465 if (ifreq->ifr_HookFunc(FRF_FILTERFUNC, &ap, freq) != 0)
466 addentry = FALSE;
467 #endif
469 freq->fr_Drawer = old_frdrawer;
472 if (addentry && ifreq->ifr_FilterFunc)
474 struct AnchorPath ap;
475 STRPTR old_frdrawer;
477 /* FIXME: is ap.ap_Info enough for the filterfunc */
479 memset(&ap, 0, sizeof(ap));
480 ap.ap_Info = *fib;
482 /* Some user filter functions access freq->fr_Drawer :-( */
484 old_frdrawer = freq->fr_Drawer;
485 freq->fr_Drawer = path;
487 D(bug("FRGetDirectory: 2 fr_Drawer 0x%lx <%s>\n",path,path));
489 /* return code TRUE (!= 0) means, add to list */
491 #ifdef __MORPHOS__
493 ULONG ret;
495 REG_A4 = (ULONG)ifreq->ifr_IntReq.ir_BasePtr; /* Compatability */
496 REG_A0 = (ULONG)ifreq->ifr_FilterFunc;
497 REG_A2 = (ULONG)freq;
498 REG_A1 = (ULONG)&ap;
499 ret = (*MyEmulHandle->EmulCallDirect68k)(ifreq->ifr_FilterFunc->h_Entry);
501 if (ret == 0)
502 addentry = FALSE;
504 #else
505 if (CallHookPkt(ifreq->ifr_FilterFunc, freq, &ap) == 0)
506 addentry = FALSE;
507 #endif
509 freq->fr_Drawer = old_frdrawer;
511 D(bug("FRGetDirectory: 3 fr_Drawer 0x%lx <%s>\n",old_frdrawer,old_frdrawer));
515 if (addentry)
517 if ((node = AllocPooled(ld->ld_IntReq->ir_MemPool, sizeof(struct ASLLVFileReqNode))))
519 struct DateTime dt;
520 char datebuffer[LEN_DATSTRING];
521 char timebuffer[LEN_DATSTRING];
523 if (fib->fib_FileName[0])
525 node->text[0] = node->node.ln_Name = PooledCloneString(fib->fib_FileName,
526 NULL,
527 ld->ld_IntReq->ir_MemPool,
528 AslBase);
531 if (fib->fib_DirEntryType > 0)
533 node->text[1] = GetString(MSG_FILEREQ_LV_DRAWER, GetIR(ifreq)->ir_Catalog, AslBase);
534 node->dontfreetext |= (1 << 1);
535 } else {
536 node->text[1] = PooledUIntegerToString(fib->fib_Size,
537 ld->ld_IntReq->ir_MemPool,
538 AslBase);
540 MARK_DO_MULTISEL(node);
543 dt.dat_Stamp = fib->fib_Date;
544 dt.dat_Format = FORMAT_DOS;
545 dt.dat_Flags = 0;
546 dt.dat_StrDay = NULL;
547 dt.dat_StrDate = datebuffer;
548 dt.dat_StrTime = timebuffer;
550 if (DateToStr(&dt))
552 //sprintf(datebuffer, "%x8", fib->fib_Date.ds_Days);
553 //sprintf(timebuffer, "%x8", fib->fib_Date.ds_Minute);
555 node->text[2] = PooledCloneString(datebuffer, NULL, ld->ld_IntReq->ir_MemPool, AslBase);
556 node->text[3] = PooledCloneString(timebuffer, NULL, ld->ld_IntReq->ir_MemPool, AslBase);
559 if (fib->fib_Comment[0])
561 node->text[4] = PooledCloneString(fib->fib_Comment, NULL, ld->ld_IntReq->ir_MemPool, AslBase);
564 node->userdata = ld;
565 node->date = fib->fib_Date;
566 node->filesize = fib->fib_Size;
567 node->type = ASLLV_FRNTYPE_DIRECTORY;
568 node->subtype = fib->fib_DirEntryType;
570 SortInNode(ifreq, &udata->ListviewList, &node->node, (APTR)FRCompareDirectoryNodes, AslBase);
573 } /* if (addentry) */
575 } /* foreach file in directory */
577 FreeDosObject(DOS_FIB, fib);
579 } /* if (DosObject allocated) */
581 UnLock(lock);
583 } /* if (directory locked) */
585 udata->LVColumnAlign[0] = ASLLV_ALIGN_LEFT; /* File/Dir name */
586 udata->LVColumnAlign[1] = ASLLV_ALIGN_RIGHT; /* Size/"Drawer" */
587 udata->LVColumnAlign[2] = ASLLV_ALIGN_LEFT; /* Date */
588 udata->LVColumnAlign[3] = ASLLV_ALIGN_LEFT; /* Time */
589 udata->LVColumnAlign[4] = ASLLV_ALIGN_LEFT; /* Comment */
591 FRCalcColumnWidths(ld, AslBase);
592 FRRefreshListview(ld, AslBase);
594 udata->Flags &= ~FRFLG_SHOWING_VOLUMES;
596 FRDirectoryScanSymbolState(ld, FALSE, AslBase);
598 return success;
601 /*****************************************************************************************/
603 static WORD FRCompareVolumeNodes(struct IntFileReq *ifreq, struct ASLLVFileReqNode *node1,
604 struct ASLLVFileReqNode *node2, struct AslBase_intern *AslBase)
606 WORD pri1, pri2, diff;
608 switch(node1->subtype)
610 case DLT_DIRECTORY:
611 case DLT_LATE:
612 case DLT_NONBINDING:
613 pri1 = 0;
614 break;
616 default:
617 pri1 = 1;
618 break;
621 switch(node2->subtype)
623 case DLT_DIRECTORY:
624 case DLT_LATE:
625 case DLT_NONBINDING:
626 pri2 = 0;
627 break;
629 default:
630 pri2 = 1;
631 break;
634 diff = pri2 - pri1;
635 if (!diff) diff = Stricmp(node1->node.ln_Name, node2->node.ln_Name);
637 return diff;
640 /*****************************************************************************************/
642 BOOL FRGetVolumes(struct LayoutData *ld, struct AslBase_intern *AslBase)
644 struct FRUserData *udata = (struct FRUserData *)ld->ld_UserData;
645 struct IntFileReq *ifreq = (struct IntFileReq *)ld->ld_IntReq;
646 struct DosList *dlist;
647 BOOL success = TRUE;
649 FRDirectoryScanSymbolState(ld, TRUE, AslBase);
651 FRFreeListviewList(ld, AslBase);
652 FRMultiSelectOnOff(ld, FALSE, AslBase);
654 dlist = LockDosList(LDF_READ | LDF_VOLUMES | LDF_ASSIGNS);
656 while ((dlist = NextDosEntry(dlist, LDF_VOLUMES | LDF_ASSIGNS)) != NULL)
658 struct ASLLVFileReqNode *node;
660 if ((node = AllocPooled(ld->ld_IntReq->ir_MemPool, sizeof(struct ASLLVFileReqNode))))
662 #ifdef __MORPHOS__
663 char *name = BADDR(dlist->dol_Name);
664 if (name)
666 node->text[0] = PooledCloneStringLen(&name[1], name[0], ":", sizeof(":"), ld->ld_IntReq->ir_MemPool, AslBase);
667 node->node.ln_Name = PooledCloneStringLen(&name[1], name[0], NULL, 0, ld->ld_IntReq->ir_MemPool, AslBase);
669 #else
670 char *name = dlist->dol_Ext.dol_AROS.dol_DevName;
671 if (name)
673 node->text[0] = node->node.ln_Name = PooledCloneString(name, ":", ld->ld_IntReq->ir_MemPool, AslBase);
675 #endif
677 switch(dlist->dol_Type)
679 case DLT_DIRECTORY:
680 case DLT_LATE:
681 case DLT_NONBINDING:
682 node->text[1] = GetString(MSG_FILEREQ_LV_ASSIGN, GetIR(ifreq)->ir_Catalog, AslBase);
683 node->dontfreetext |= (1 << 1);
684 break;
686 #ifdef __MORPHOS__
687 case DLT_VOLUME:
689 struct DosList *dl = LockDosList(LDF_DEVICES | LDF_READ);
691 while ((dl = NextDosEntry(dl, LDF_DEVICES)))
693 /* This works for most filesystems */
694 if (dl->dol_Task == dlist->dol_Task)
696 STRPTR devname = (STRPTR)BADDR(dl->dol_Name);
697 ULONG devlen = *devname++;
699 if (devname[devlen-1] == 0) devlen--;
701 node->text[1] = AllocPooled(ld->ld_IntReq->ir_MemPool, devlen + 3);
702 node->text[1][0] = '(';
703 strncpy(&node->text[1][1], devname, devlen);
704 node->text[1][devlen+1] = ')';
705 node->text[1][devlen+2] = 0;
707 break;
711 UnLockDosList(LDF_DEVICES | LDF_READ);
713 break;
714 #endif
717 node->userdata = ld;
719 node->filesize = 0;
720 node->type = ASLLV_FRNTYPE_VOLUMES;
721 node->subtype = dlist->dol_Type;
723 SortInNode(ifreq, &udata->ListviewList, &node->node, (APTR)FRCompareVolumeNodes, AslBase);
729 UnLockDosList(LDF_READ | LDF_VOLUMES | LDF_ASSIGNS);
731 udata->LVColumnAlign[0] = ASLLV_ALIGN_LEFT;
732 udata->LVColumnAlign[1] = ASLLV_ALIGN_RIGHT;
734 FRCalcColumnWidths(ld, AslBase);
735 FRRefreshListview(ld, AslBase);
737 udata->Flags |= FRFLG_SHOWING_VOLUMES;
739 FRDirectoryScanSymbolState(ld, FALSE, AslBase);
741 return success;
744 /*****************************************************************************************/
746 void FRSetPath(STRPTR path, struct LayoutData *ld, struct AslBase_intern *AslBase)
748 struct FRUserData *udata = (struct FRUserData *)ld->ld_UserData;
749 struct TagItem set_tags[] =
751 {STRINGA_TextVal , path ? (IPTR)path : (IPTR)"" },
752 {TAG_DONE }
755 SetGadgetAttrsA((struct Gadget *)udata->PathGad, ld->ld_Window, NULL, set_tags);
758 /*****************************************************************************************/
760 BOOL FRNewPath(STRPTR path, struct LayoutData *ld, struct AslBase_intern *AslBase)
762 char pathstring[MAX_PATH_LEN];
763 BOOL result = FALSE;
765 strcpy(pathstring, path);
766 fixpath(pathstring);
768 FRSetPath(pathstring, ld, AslBase);
770 result = FRGetDirectory(pathstring, ld, AslBase);
772 return result;
775 /*****************************************************************************************/
777 BOOL FRAddPath(STRPTR path, struct LayoutData *ld, struct AslBase_intern *AslBase)
779 struct FRUserData *udata = (struct FRUserData *)ld->ld_UserData;
780 char pathstring[MAX_PATH_LEN], *gadpath;
781 BOOL result;
783 GetAttr(STRINGA_TextVal, udata->PathGad, (IPTR *)&gadpath);
785 strcpy(pathstring, gadpath);
786 AddPart(pathstring, path, MAX_PATH_LEN);
788 result = FRNewPath(pathstring, ld, AslBase);
790 return result;
794 /*****************************************************************************************/
796 BOOL FRParentPath(struct LayoutData *ld, struct AslBase_intern *AslBase)
798 struct FRUserData *udata = (struct FRUserData *)ld->ld_UserData;
799 char pathstring[MAX_PATH_LEN], *gadpath;
800 WORD len;
801 BOOL result;
803 GetAttr(STRINGA_TextVal, udata->PathGad, (IPTR *)&gadpath);
805 strcpy(pathstring, gadpath);
806 fixpath(pathstring);
808 len = strlen(pathstring);
809 if (len == 0)
811 strcpy(pathstring, "/");
813 else if (len < MAX_PATH_LEN - 3)
815 switch(pathstring[len - 1])
817 case '/':
818 case ':':
819 strcat(pathstring, "/");
820 break;
822 default:
823 strcat(pathstring, "//");
824 fixpath(pathstring);
825 break;
829 result = FRNewPath(pathstring, ld, AslBase);
831 return result;
835 /*****************************************************************************************/
837 void FRSetFile(STRPTR file, struct LayoutData *ld, struct AslBase_intern *AslBase)
839 struct FRUserData *udata = (struct FRUserData *)ld->ld_UserData;
840 struct TagItem set_tags[] =
842 {STRINGA_TextVal , file ? (IPTR)file : (IPTR)"" },
843 {TAG_DONE }
846 SetGadgetAttrsA((struct Gadget *)udata->FileGad, ld->ld_Window, NULL, set_tags);
849 /*****************************************************************************************/
851 void FRChangeActiveLVItem(struct LayoutData *ld, WORD delta, UWORD quali, struct Gadget *gad, struct AslBase_intern *AslBase)
853 struct FRUserData *udata = (struct FRUserData *)ld->ld_UserData;
854 struct IntFileReq *ifreq = (struct IntFileReq *)ld->ld_IntReq;
855 struct ASLLVFileReqNode *node;
856 IPTR active, total, visible;
857 struct Gadget *mainstrgad;
858 struct TagItem set_tags[] =
860 {ASLLV_Active , 0 },
861 {ASLLV_MakeVisible , 0 },
862 {TAG_DONE }
865 GetAttr(ASLLV_Active , udata->Listview, &active );
866 GetAttr(ASLLV_Total , udata->Listview, &total );
867 GetAttr(ASLLV_Visible, udata->Listview, &visible);
869 mainstrgad = (struct Gadget *)((ifreq->ifr_Flags2 & FRF_DRAWERSONLY) ? udata->PathGad : udata->FileGad);
871 if (total < 1) return;
873 if (quali & (IEQUALIFIER_LSHIFT | IEQUALIFIER_RSHIFT))
875 delta *= (visible - 1);
877 else if (quali & (IEQUALIFIER_LALT | IEQUALIFIER_RALT | IEQUALIFIER_CONTROL))
879 delta *= total;
881 else if (gad && (gad == mainstrgad))
883 /* try to jump to first item which matches text in string gadget,
884 but only if text in string gadget mismatches actual active
885 item's text (in this case move normally = one step)) */
887 char buffer[MAX_FILE_LEN];
888 char *val;
889 WORD i, len;
890 BOOL dojump = TRUE;
892 GetAttr(STRINGA_TextVal, (Object *)gad, (IPTR *)&val);
893 strcpy(buffer, val);
895 len = strlen(buffer);
896 if (len > 0) if (buffer[len - 1] == '/') buffer[--len] = '\0';
898 if (len)
900 if (((LONG)active) >= 0)
902 if ((node = (struct ASLLVFileReqNode *)FindListNode(&udata->ListviewList, (WORD)active)))
904 if (stricmp(node->node.ln_Name, buffer) == 0) dojump = FALSE;
908 if (dojump)
910 i = 0;
911 ForeachNode(&udata->ListviewList, node)
913 if (Strnicmp((CONST_STRPTR)node->node.ln_Name, (CONST_STRPTR)buffer, len) == 0)
915 active = i;
916 delta = 0;
917 break;
919 i++;
923 } /* if (dojump) */
925 } /* if (len) */
929 active += delta;
931 if (((LONG)active) < 0) active = 0;
932 if (active >= total) active = total - 1;
934 set_tags[0].ti_Data = set_tags[1].ti_Data = active;
936 SetGadgetAttrsA((struct Gadget *)udata->Listview, ld->ld_Window, NULL, set_tags);
938 if ((node = (struct ASLLVFileReqNode *)FindListNode(&udata->ListviewList, (WORD)active)))
940 if (ifreq->ifr_Flags2 & FRF_DRAWERSONLY)
942 FRSetPath(node->node.ln_Name, ld, AslBase);
943 } else {
944 char pathstring[MAX_FILE_LEN];
946 strcpy(pathstring, node->node.ln_Name);
947 if ((node->subtype > 0) && (!(udata->Flags & FRFLG_SHOWING_VOLUMES)))
949 strcat(pathstring, "/");
952 FRSetFile(pathstring, ld, AslBase);
956 if (gad)
958 ActivateGadget(gad, ld->ld_Window, NULL);
959 } else {
960 FRActivateMainStringGadget(ld, AslBase);
964 /*****************************************************************************************/
966 void FRActivateMainStringGadget(struct LayoutData *ld, struct AslBase_intern *AslBase)
968 struct FRUserData *udata = (struct FRUserData *)ld->ld_UserData;
969 struct IntFileReq *ifreq = (struct IntFileReq *)ld->ld_IntReq;
971 if (ifreq->ifr_Flags2 & FRF_DRAWERSONLY)
973 ActivateGadget((struct Gadget *)udata->PathGad, ld->ld_Window, NULL);
974 } else {
975 ActivateGadget((struct Gadget *)udata->FileGad, ld->ld_Window, NULL);
979 /*****************************************************************************************/
981 void FRMultiSelectOnOff(struct LayoutData *ld, BOOL onoff, struct AslBase_intern *AslBase)
983 struct FRUserData *udata = (struct FRUserData *)ld->ld_UserData;
984 struct TagItem set_tags[] =
986 {ASLLV_DoMultiSelect , onoff },
987 {TAG_DONE }
990 SetGadgetAttrsA((struct Gadget *)udata->Listview, ld->ld_Window, NULL, set_tags);
993 /*****************************************************************************************/
995 void FRSetPattern(STRPTR pattern, struct LayoutData *ld, struct AslBase_intern *AslBase)
997 struct FRUserData *udata = (struct FRUserData *)ld->ld_UserData;
998 struct TagItem set_tags[] =
1000 {STRINGA_TextVal , pattern ? (IPTR)pattern : (IPTR)"" },
1001 {TAG_DONE }
1004 SetGadgetAttrsA((struct Gadget *)udata->PatternGad, ld->ld_Window, NULL, set_tags);
1007 /*****************************************************************************************/
1009 void FRSelectRequester(struct LayoutData *ld, struct AslBase_intern *AslBase)
1011 struct FRUserData *udata = (struct FRUserData *)ld->ld_UserData;
1012 struct IntFileReq *ifreq = (struct IntFileReq *)ld->ld_IntReq;
1013 STRPTR oldpattern = udata->SelectPattern;
1015 udata->SelectPattern = REQ_String(GetString(MSG_FILEREQ_SELECT_TITLE, GetIR(ifreq)->ir_Catalog, AslBase),
1016 oldpattern ? oldpattern : (STRPTR)"#?",
1017 GetString(MSG_FILEREQ_SELECT_OK, GetIR(ifreq)->ir_Catalog, AslBase),
1018 GetString(MSG_FILEREQ_SELECT_CANCEL, GetIR(ifreq)->ir_Catalog, AslBase),
1020 AslBase);
1022 if (oldpattern) MyFreeVecPooled(oldpattern, AslBase);
1024 if (udata->SelectPattern)
1026 LONG patternlen = strlen(udata->SelectPattern);
1028 if (patternlen > 0)
1030 STRPTR parsedpattern;
1032 parsedpattern = MyAllocVecPooled(ld->ld_IntReq->ir_MemPool, patternlen * 2 + 3, AslBase);
1033 if (parsedpattern)
1035 if (ParsePatternNoCase(udata->SelectPattern, parsedpattern, patternlen * 2 + 3) != -1)
1037 struct ASLLVFileReqNode *node;
1039 if (udata->Flags & FRFLG_SHOWING_VOLUMES)
1041 UBYTE *dir;
1043 GetAttr(STRINGA_TextVal, udata->PathGad, (IPTR *)&dir);
1044 FRGetDirectory(dir, ld, AslBase);
1047 SetGadgetAttrs((struct Gadget *)udata->Listview, ld->ld_Window, NULL, ASLLV_Active, -1,
1048 TAG_DONE);
1050 ForeachNode(&udata->ListviewList, node)
1052 if (IS_MULTISEL(node) && node->node.ln_Name)
1054 if (MatchPatternNoCase(parsedpattern, node->node.ln_Name))
1056 MARK_SELECTED(node);
1057 } else {
1058 MARK_UNSELECTED(node);
1063 RefreshGList((struct Gadget *)udata->Listview, ld->ld_Window, NULL, 1);
1066 MyFreeVecPooled(parsedpattern, AslBase);
1068 } /* if (parsedpattern) */
1070 } /* if (udata->SelectPattern[0]) */
1072 } /* if (udata->SelectPattern) */
1074 } /**/
1076 /*****************************************************************************************/
1078 void FRDeleteRequester(struct LayoutData *ld, struct AslBase_intern *AslBase)
1080 struct FRUserData *udata = (struct FRUserData *)ld->ld_UserData;
1081 struct IntFileReq *ifreq = (struct IntFileReq *)ld->ld_IntReq;
1082 STRPTR name = NULL, name2, s;
1084 GetAttr(STRINGA_TextVal, udata->PathGad, (IPTR *)&name);
1086 if (ifreq->ifr_Flags2 & FRF_DRAWERSONLY)
1088 name = name2 = VecPooledCloneString(name, NULL, ld->ld_IntReq->ir_MemPool, AslBase);
1089 } else {
1090 GetAttr(STRINGA_TextVal, udata->FileGad, (IPTR *)&name2);
1092 if ((s = MyAllocVecPooled(ld->ld_IntReq->ir_MemPool, strlen(name) + strlen(name2) + 4, AslBase)))
1094 strcpy(s, name);
1095 AddPart(s, name2, 10000);
1096 name = s;
1100 if (name) if (name[0])
1102 struct EasyStruct es;
1104 es.es_StructSize = sizeof(es);
1105 es.es_Flags = 0;
1106 es.es_Title = GetString(MSG_FILEREQ_DELETE_TITLE , GetIR(ifreq)->ir_Catalog, AslBase);
1107 es.es_TextFormat = GetString(MSG_FILEREQ_DELETE_MSG , GetIR(ifreq)->ir_Catalog, AslBase);
1108 es.es_GadgetFormat = GetString(MSG_FILEREQ_DELETE_OKCANCEL, GetIR(ifreq)->ir_Catalog, AslBase);
1110 if (EasyRequestArgs(ld->ld_Window, &es, NULL, &name) == 1)
1112 if (DeleteFile(name) && !(udata->Flags & FRFLG_SHOWING_VOLUMES))
1114 struct ASLLVFileReqNode *node;
1115 struct TagItem set_tags[] =
1117 {ASLLV_Labels , 0 },
1118 {ASLLV_Top , 0 },
1119 {TAG_DONE }
1121 IPTR top;
1123 GetAttr(ASLLV_Top, udata->Listview, &top);
1124 SetGadgetAttrsA((struct Gadget *)udata->Listview, ld->ld_Window, NULL, set_tags);
1126 ForeachNode(&udata->ListviewList, node)
1128 if (node->node.ln_Name)
1130 if (stricmp(node->node.ln_Name, name2) == 0)
1132 Remove(&node->node);
1133 FRFreeListviewNode(node, ld, AslBase);
1134 break;
1139 set_tags[0].ti_Data = (IPTR)&udata->ListviewList;
1140 set_tags[1].ti_Data = top;
1141 SetGadgetAttrsA((struct Gadget *)udata->Listview, ld->ld_Window, NULL, set_tags);
1144 } /* if (DeleteFile(name) && !(udata->Flags & FRFLG_SHOWING_VOLUMES)) */
1146 } /* if (EasyRequestArgs(ld->ld_Window, &es, NULL, &name) == 1) */
1148 } /* if (name) if (name[0]) */
1150 if (name) MyFreeVecPooled(name, AslBase);
1153 /*****************************************************************************************/
1155 void FRNewDrawerRequester(struct LayoutData *ld, struct AslBase_intern *AslBase)
1157 struct FRUserData *udata = (struct FRUserData *)ld->ld_UserData;
1158 struct IntFileReq *ifreq = (struct IntFileReq *)ld->ld_IntReq;
1159 STRPTR path, dirname;
1160 BPTR lock, lock2, olddir;
1162 GetAttr(STRINGA_TextVal, udata->PathGad, (IPTR *)&path);
1164 lock = Lock(path, SHARED_LOCK);
1165 if (lock)
1167 olddir = CurrentDir(lock);
1169 if ((dirname = REQ_String(GetString(MSG_FILEREQ_CREATEDRAWER_TITLE, GetIR(ifreq)->ir_Catalog, AslBase),
1170 GetString(MSG_FILEREQ_CREATEDRAWER_DEFNAME, GetIR(ifreq)->ir_Catalog, AslBase),
1171 GetString(MSG_FILEREQ_CREATEDRAWER_OK, GetIR(ifreq)->ir_Catalog, AslBase),
1172 GetString(MSG_FILEREQ_CREATEDRAWER_CANCEL, GetIR(ifreq)->ir_Catalog, AslBase),
1174 AslBase)))
1176 if ((lock2 = CreateDir(dirname)))
1178 if (!(udata->Flags & FRFLG_SHOWING_VOLUMES))
1180 struct TagItem set_tags[] =
1182 {ASLLV_Top , 0 },
1183 {TAG_DONE }
1185 IPTR top;
1187 GetAttr(ASLLV_Top, udata->Listview, &top);
1189 FRGetDirectory(path, ld, AslBase);
1191 set_tags[0].ti_Data = top;
1192 SetGadgetAttrsA((struct Gadget *)udata->Listview, ld->ld_Window, NULL, set_tags);
1195 UnLock(lock2);
1197 } /* if ((lock2 = CreateDir(dirname))) */
1199 MyFreeVecPooled(dirname, AslBase);
1201 }; /* if ((dirname = REQ_String(... */
1203 CurrentDir(olddir);
1204 UnLock(lock);
1206 } /* if (lock) */
1210 /*****************************************************************************************/
1212 void FRRenameRequester(struct LayoutData *ld, struct AslBase_intern *AslBase)
1214 struct FRUserData *udata = (struct FRUserData *)ld->ld_UserData;
1215 struct IntFileReq *ifreq = (struct IntFileReq *)ld->ld_IntReq;
1216 STRPTR path, file, newname;
1217 BPTR lock, lock2, olddir;
1219 if (ifreq->ifr_Flags2 & FRF_DRAWERSONLY) return;
1221 GetAttr(STRINGA_TextVal, udata->FileGad, (IPTR *)&file);
1222 if (!file[0]) return;
1224 GetAttr(STRINGA_TextVal, udata->PathGad, (IPTR *)&path);
1226 lock = Lock(path, SHARED_LOCK);
1227 if (lock)
1229 olddir = CurrentDir(lock);
1231 lock2 = Lock(file, SHARED_LOCK);
1232 if (lock2)
1234 UnLock(lock2);
1236 if ((newname = REQ_String(GetString(MSG_FILEREQ_RENAME_TITLE, GetIR(ifreq)->ir_Catalog, AslBase),
1237 file,
1238 GetString(MSG_FILEREQ_RENAME_OK, GetIR(ifreq)->ir_Catalog, AslBase),
1239 GetString(MSG_FILEREQ_RENAME_CANCEL, GetIR(ifreq)->ir_Catalog, AslBase),
1241 AslBase)))
1243 if (Rename(file, newname))
1245 FRSetFile(newname, ld, AslBase);
1247 if (!(udata->Flags & FRFLG_SHOWING_VOLUMES))
1249 struct TagItem set_tags[] =
1251 {ASLLV_Top , 0 },
1252 {TAG_DONE }
1254 IPTR top;
1256 GetAttr(ASLLV_Top, udata->Listview, &top);
1258 FRGetDirectory(path, ld, AslBase);
1260 set_tags[0].ti_Data = top;
1261 SetGadgetAttrsA((struct Gadget *)udata->Listview, ld->ld_Window, NULL, set_tags);
1264 } /* if (Rename(file, newname)) */
1266 MyFreeVecPooled(newname, AslBase);
1268 }; /* if ((newname = REQ_String(... */
1270 } /* if (lock2) */
1272 CurrentDir(olddir);
1273 UnLock(lock);
1275 } /* if (lock) */
1279 /*****************************************************************************************/