;----------------------------------------------------------- ; ; Api92/Api89 Source Code ; ; (c) NeXO Software, Benoit SCHERRER ; e-mail : p.c.scherrer@wanadoo.fr ; ; ; File> nfolders.xas ; Utility> Nested folders management ;----------------------------------------------------------- ; Folder Src | Nested Folder | Folder Src | Nested Folder ;----------------------------------------------------- ; Check if all nested folders are valid ;----------------------------------------------------- apilib@001C: CheckNestedFolders: nf_CheckIfValid: _nf_CheckIfValid: movem.l d0-d5/a0-a2,-(a7) ;first pass : look for invalid folders \lp bsr _nf_GetBufferAddr ;get buffer addr in a1 move.w d0,d5 ;save handle beq.s \exit lea 2(a1),a2 move.w (a2)+,d4 ;nb beq.s \exit subq.w #1,d4 ;for dbra clr.w d3 ;index to delete \loop move.w (a2),d1 ;check parent folder cmp.w 2(a2),d1 beq.s \error API92_FOLDHDL d0 bsr _vat_FindHdl tst.w d2 beq.s \error move.w 2(a2),d1 ;check nested folder bsr _vat_FindHdl tst.w d2 bne.s \noerror \error move.w d5,d0 ;list handle moveq.w #4,d1 ;size of items moveq.w #2,d2 ;offset bsr _array_fDeleteItem ;d3 is the item index bra.s \lp \noerror addq.l #4,a2 ;next items addq.l #1,d3 ;increment item index dbra.s d4,\loop \exit movem.l (a7)+,d0-d5/a0-a2 rts ;---------------------------------------------- ; nf_GetBufferAddr ; ; > Look for the buffer that describes nested ; folders. ; ;Input> Nothing ;Out> d0.w : 0 if buffer not found ; else handle of the buffer ; a1.l : Address of the buffer ;---------------------------------------------- apilib@001D: _nf_GetBufferAddr: movem.l d1-d2/a0/a2,-(a7) ;---------------------------------- ; find 'nested' var ;---------------------------------- \find lea nf_VarName(PC),a0 API92_MAINHDL d0 ;Handle of 'Main' folder bsr _vat_Find ;find 'nested' file tst.w d2 beq.s \notfound ; ;---------------------------------- ; if found but archived, unarchive var ;---------------------------------- btst.b #1,VAT_ENTRYFLAG-1(a1) ;if var beq.s \noarch ;was archived subq.w #1,d2 bsr _vat_UnarchiveVar tst.w d1 bne.s \error bra.s \find \noarch move.w d1,d0 ;if found set d0=hdl bra.s \found ;---------------------------------- ; if not found or invalid create var ;---------------------------------- \notfound API92_MAINHDL d0 ;if not found, create it moveq.w #0,d1 ;flag moveq.w #14,d2 ;size lea nf_VarName(PC),a0 bsr _vat_CreateVar tst.w d1 bne.s \error bsr DEREFd0a0 ;get addr lea 16(a0),a1 ;put file extension move.b #$F8,-(a1) clr.b -(a1) move.b #'G',-(a1) move.b #'F',-(a1) move.b #'C',-(a1) clr.b -(a1) ;create array moveq.w #4,d1 ;size of each item moveq.w #2,d2 ;offset bsr _array_fCreate tst.w d0 beq.s \error ;---------------------------------- ; Check if valid 'nested' var ;---------------------------------- \found bsr DEREFd0a0 lea 2(a0),a1 clr.l d1 ; move.w (a0),d1 ;file size lea 2(a0,d1.l),a2 ;get end of file cmp.b #$F8,-(a2) ;Check extension bne.s \delfile ;if not valid, delete file tst.b -(a2) bne.s \delfile cmp.b #'G',-(a2) bne.s \delfile cmp.b #'F',-(a2) bne.s \delfile cmp.b #'C',-(a2) bne.s \delfile \exit movem.l (a7)+,d1-d2/a0/a2 rts \error clr.w d0 bra.s \exit ;---------------------------------- ; Delete var if invalid ;---------------------------------- \delfile lea nf_VarName(PC),a0 ;delete invalid previous file API92_MAINHDL d0 ;Handle of 'Main' folder bsr _vat_Find ;find d0/d2 tst.w d2 beq.s \error subq.w #1,d2 bsr _vat_Delete ;and delete bra \notfound nf_VarName dc.b "nested",0,0 ;------------------------------------------------------ ; nf_AddFolder ; ; > Make a folder a nested folder, or make it ; a normal folder ; ;Input> d1.w : Handle of parent folder ; d2.w : Handle of folder to make nested ;Out> d1.w : Error code ; No other register modified ;------------------------------------------------------ apilib@001E: _nf_AddFolder: AddNestedFolder: movem.l d0/d2-d3/a0-a2,-(a7) bsr _nf_GetBufferAddr ;test if buffer created tst.w d0 beq.s \nobuf lea Nested_Buf(PC),a0 ;addr of a 4 bytes buffer move.l a0,a2 move.w d1,(a0)+ ;put info move.w d2,(a0)+ ;Check if folder already nested move.w d2,d0 ;nested in d0 move.w d1,d3 ;save parent in d2 moveq.w #1,d1 ;2nd word bsr nf_Search tst.w d0 beq.s \notfound API92_CMPFOLDHDL d3 ;dest=root ? bne.s \destnoroot move.w d0,d3 ;d0=index from nf_Search subq.w #1,d3 ;0-based index bsr _nf_GetBufferAddr ;get d0=hdl of buffer moveq.w #4,d1 ;size of items moveq.w #2,d2 ;offset bsr _array_fDeleteItem bra.s \exit \destnoroot move.w d3,-2(a0) clr.w d1 ;no error bra.s \exit \notfound clr.w d1 ;default error value API92_CMPFOLDHDL d3 ;if not found and dest=root beq.s \exit bsr _nf_GetBufferAddr ;get d0=hdl of buffer move.l a2,a0 ;addr of item moveq.w #4,d1 ;size of item moveq.w #2,d2 ;offset bsr _array_fAddItem ;a0 already adr of item \exit movem.l (a7)+,d0/d2-d3/a0-a2 rts \nobuf moveq.w #EC_HDLNOTFOUND,d1 bra.s \exit Nested_Buf dc.l 0 ;-------------------------------------------------------------------- ; nf_IsFolderNested ; ; > Check if a folder is nested or not ; ;Input> d1.w : Handle of folder ;Out> d0.w : 0 = Folder not nested ; else d0.w=Handle of parent folder ;-------------------------------------------------------------------- apilib@0020: _nf_IsFolderNested: IsFolderNested: movem.l d1-d3/a0-a1,-(a7) move.w d1,d0 moveq.w #1,d1 ;mode=2nd word bsr nf_Search tst.w d0 beq.s \exit move.w -2(a0),d0 \exit movem.l (a7)+,d1-d3/a0-a1 rts ;--------------------------------------------- ; nf_IsParentOf ; ; > Check if a folder is the parent of an ; other. ; ;Input> d0.w : Handle of parent folder ; d1.w : Handle of a folder ;Out> d0.w : 0 if no ; 1 if yes ;--------------------------------------------- apilib@0030: nf_IsParentOf: movem.l d1-d3/a0-a1,-(a7) move.w d0,d2 ;save hdl \loop bsr _nf_GetBufferAddr tst.w d0 beq.s \error addq.l #2,a1 move.w (a1)+,d3 ;nb of info beq.s \error subq.w #1,d3 \lp2 cmp.w 2(a1),d1 ;nested found ? bne.s \next_folder cmp.w (a1),d2 beq.s \found move.w (a1),d1 bra.s \loop \next_folder addq.l #4,a1 dbra.s d3,\lp2 \error clr.w d0 \exit movem.l (a7)+,d1-d3/a0-a1 rts \found moveq.w #1,d0 bra.s \exit ;------------------- ;Input> d0.l or d0.w = data ; d1=mode : 0 = first word ; 1 = second word ; 2 = long word ;Out> d0=0 : error ; else 1-based index of item ; a0.l : addr ;------------------- apilib@001F: nf_Search: movem.l d1-d3/a1,-(a7) move.l d0,d2 bsr _nf_GetBufferAddr ;get buffer addr tst.w d0 ;if error exit beq.s \exit clr.w d0 ;return value addq.l #2,a1 ;skip first word move.w (a1)+,d3 beq.s \exit subq.w #1,d3 ;for dbra cmp.w #1,d1 bne.s \skip addq.l #2,a1 \skip \search addq.l #1,d0 cmp.w #2,d1 beq.s \lg cmp.w (a1),d2 beq.s \found bra.s \skip2 \lg cmp.l (a1),d2 beq.s \found \skip2 addq.l #4,a1 dbra.s d3,\search clr.w d0 \found move.l a1,a0 \exit movem.l (a7)+,d1-d3/a1 rts ;-------------------------------------------------------- ; nf_GetNestedCount ; ; > Get the number of nested folder in a folder ; ;Input> d0.w : Handle of a folder ;Out> d2.w : Number of nested folders ;-------------------------------------------------------- apilib@0021: _nf_GetNestedCount: GetNstedCount: movem.l d0-d1/d3/a0-a1,-(a7) move.w d0,d1 ;handle clr.l d2 bsr _nf_GetBufferAddr tst.w d0 beq.s \exit addq.l #2,a1 move.w (a1)+,d3 ;nb nested beq.s \exit subq.w #1,d3 \search cmp.w (a1),d1 bne.s \skip addq.w #1,d2 \skip addq.l #4,a1 dbra.s d3,\search \exit movem.l (a7)+,d0-d1/d3/a0-a1 rts ;--------------------------------------------------- ; nf_GetVatName ; ; > Get complete name of a var ; ;Input> d0.w : Handle of source folder ; d1.w : Length of buffer (minimum:10 bytes) ; d2.w : 0-based index of file ; a0.l : Address of the buffer ;out> d1.w : Error code ; a0.l : address of the beginning output string ;--------------------------------------------------- _nf_GetVatName: apilib@0051: movem.l d0/d2-d5/a1-a3,-(a7) move.w d0,d3 move.w d1,d4 move.l a0,a2 bsr _vat_IndexToAddr tst.w d1 bne.s \exit move.l a0,a1 bsr _FileNameSize move.w d0,d5 ;save string size sub.w d0,d4 subq.w #1,d4 move.w d3,d0 move.w d4,d1 move.l a2,a0 bsr _nf_GetFolderName tst.w d1 beq.s \skip2 addq.l #1,a0 ;skip the '\' char \skip2 move.l a0,a3 ;save a0 move.l a2,a0 ; adda.w d4,a0 move.b #'\',-1(a0) tst.w d5 beq.s \skip subq.w #1,d5 \copy move.b (a1)+,(a0)+ dbra.s d5,\copy \skip clr.b (a0)+ ;null terminated clr.l d1 move.l a3,a0 \exit movem.l (a7)+,d0/d2-d5/a1-a3 rts _FileNameSize: movem.l d1/a1,-(a7) moveq.w #7,d1 ;8 laps at max clr.w d0 ;length of str \nb tst.b (a1)+ beq.s \out addq.w #1,d0 dbra.s d1,\nb \out movem.l (a7)+,d1/a1 rts ;------------------------------------------------------ ; nf_GetFolderName ; ; > Get the complete name of a folder, including ; nested folders ; ;Input> d0.w : Folder Handle ; d1.w : length of buffer ; a0.l : address of buffer ;Out> d1.w : error code ; a0.l : Address of the string begining ;------------------------------------------------------ apilib@0050: _nf_GetFolderName: movem.l d0/d2-d5/a1-a2,-(a7) move.w d1,d4 ;max length subq.w #1,d4 ;-1 because 0 terminated adda.w d1,a0 clr.b -(a0) ;zero terminated string move.l a0,a2 ;Save buffer addr move.w d0,d5 ;save folder hdl bra.s \skip1 \loop move.b #'\',-(a2) subq.w #1,d4 beq.s \toolong \skip1 move.w d5,d1 ;Folder to search API92_FOLDHDL d0 ;Handle of VAT bsr _vat_FindHdl ;Find Handle tst.w d2 ;found ? beq.s \notfound ;if not, exit ! move.w VATENTRY_HDL(a1),d5 ;new folder bsr _FileNameSize adda.w d0,a1 ;Add string length tst.w d0 ;if null, skip beq.s \skip ; subq.w #1,d0 ;else copy string \copy move.b -(a1),-(a2) ; subq.w #1,d4 ;MaxLength-1 beq.s \toolong ;check length dbra.s d0,\copy \skip move.w d5,d1 bsr _nf_IsFolderNested move.w d0,d5 bne.s \loop \sucess clr.w d1 \exit move.l a2,a0 movem.l (a7)+,d0/d2-d5/a1-a2 rts \toolong move.b #'.',(a2) move.b #'.',1(a2) bra.s \sucess \notfound moveq.w #EC_HDLNOTFOUND,d1 bra.s \exit ;--------------------------------------------------- ;Input> d0.w : Handle ;Out> d1.w : Error Code ;--------------------------------------------------- apilib@006F: _nf_DeleteFolder: ;#ifdef TIPLUS movem.l d0-d2/a0-a1,-(a7) bsr _nf_GetBufferAddr ;Get nested addr move.w d0,-(a7) beq.s \skip TIOS_CALL HeapLock \skip addq.l #2,a7 movem.l (a7)+,d0-d2/a0-a1 ;#endif bsr _nf_DF ;#ifdef TIPLUS movem.l d0-d2/a0-a1,-(a7) bsr _nf_GetBufferAddr ;Get nested addr move.w d0,-(a7) beq.s \skip2 TIOS_CALL HeapUnlock \skip2 addq.l #2,a7 movem.l (a7)+,d0-d2/a0-a1 ;#endif bsr _nf_CheckIfValid rts _nf_DF: movem.l d0/d2-d4/a0-a1,-(a7) move.w d0,-(a7) ;Lock handle ;#ifdef TIPLUS TIOS_CALL HeapLock ;#endif bsr _nf_GetBufferAddr ;Get nested addr tst.w d0 ;if error next beq.s \delfiles addq.l #2,a1 move.w (a1)+,d4 ;Nb nested info beq.s \delfiles ;if =0 exit subq.w #1,d4 \loop move.w (a7),d0 ; cmp.w (a1),d0 ;is that folder parent of ? bne.s \skip ;if not skip move.w 2(a1),d0 ;else recursiv call bsr _nf_DF tst.w d1 ;if an error bne.s \exit ;exit \skip addq.l #4,a1 dbra.s d4,\loop ;now delete files \delfiles move.w (a7),d0 bsr DEREFd0a0 addq.l #2,a0 ;skip first word move.w (a0)+,d4 beq.s \skip2 subq.w #1,d4 ;for dbra \loop2 clr.w d2 ;first item bsr _vat_Delete tst.w d1 bne.s \exit ;error dbra.s d4,\loop2 \skip2 move.w (a7),d0 bsr _vat_DeleteFolder ;return d1 \exit ;#ifdef TIPLUS move.l d1,d4 ;save return value TIOS_CALL HeapUnlock move.l d4,d1 ;#endif addq.l #2,a7 movem.l (a7)+,d0/d2-d4/a0-a1 rts ;--------------------------------------------------- ; Recursive Function called to calculate the ; size of a folder ;Input> d0.w : folder handle ; d1.w : 0=recursive call ; else only that folder ;Out> d2.l : Size of the folder ;--------------------------------------------------- apilib@006E: _nf_GetFolderSize: movem.l d0-d1/d3,-(a7) clr.l d2 ;first size move.l d1,d3 ;flag bsr nf_CalcSize movem.l (a7)+,d0-d1/d3 rts ;--------------------------------------------------- ;Input> d0.w : folder handle ; d2.l : for the first call, you must put d2.l=0 ; d3.w : 0 if allow recursiv call ;Out> d2.l : Size of the folder ;--------------------------------------------------- nf_CalcSize: movem.l d0-d1/d4/a0-a1,-(a7) move.w d0,d4 ;save hdl bsr DEREFd0a0 ;get folder addr addq.l #2,a0 move.w (a0)+,d1 ;get number of file beq.s \empty1 ;if empty skip subq.w #1,d1 ;for dbra \calc move.l a0,a1 ;save a1 move.w VATENTRY_HDL(a0),d0 ;get handle beq.s \golp ;if null, go loop bsr DEREFd0a0 ;get addr of file clr.l d0 move.w (a0),d0 add.l d0,d2 ;add file size to d2 addq.l #2,d2 ; +2 \golp lea VATENTRY_SIZE(a1),a0 ;Next VAT entry dbra.s d1,\calc \empty1 tst.w d3 bne.s \empty2 ;no recursive call ;now check nested folders bsr _nf_GetBufferAddr ;return a1=addr of buffer tst.w d0 ;if error beq.s \empty2 ;exit addq.w #2,a1 move.w (a1)+,d1 ;nb of nested beq.s \empty2 subq.w #1,d1 \loop2 cmp.w (a1),d4 ;is parent of ? bne.s \skip move.w 2(a1),d0 ;folder handle bsr nf_CalcSize \skip addq.l #4,a1 dbra.s d1,\loop2 \empty2 movem.l (a7)+,d0-d1/d4/a0-a1 rts ;------------------------------------------------------ ;Search a folder giving its handle, return its ;name ; ;in> d1.w : hdl ;out> d0.w : 0 if not found ; 1 if found ; a2.l : addr of VAT entry ;------------------------------------------------------ apilib@0025: ;vat_FolderHdlToVat: SearchFolder: move.l a0,-(a7) API92_FOLDHDL d0 ;Folder list hdl bsr DEREFd0a0 lea 2(a0),a2 ;skip first word move.w (a2)+,d0 ;nb of folder beq.s \exit subq.w #1,d0 ;for dbra \loop cmp.w ENTRY_HDL(a2),d1 beq.s \found lea VATENTRY_SIZE(a2),a2 dbra.s d0,\loop clr.w d0 bra.s \exit \found moveq.w #1,d0 \exit move.l (a7)+,a0 rts