home *** CD-ROM | disk | FTP | other *** search
- * ------------------------------------------------------------------------- *
- * FS2.ASM -- Assembly support routines for PathMaster(tm) File Selector
- * Copyright © 1987-1989 by Justin V. McCormick. All Rights Reserved.
- * ------------------------------------------------------------------------- *
-
- ;BENCHMARK EQU 1
-
- include "exec/types.i"
- include "exec/nodes.i"
- include "exec/lists.i"
-
- SYS MACRO *
- IFGT NARG-2
- FAIL !!!
- ENDC
- IFEQ NARG-2
- MOVE.L \2,a6
- ENDC
- JSR _LVO\1(a6)
- ENDM
-
- XLVO MACRO *
- XREF _LVO\1
- ENDM
-
-
- * These three equate control the size of the path, file, and pattern string limits
- PATHSTRSIZE EQU 300
- FILESTRSIZE EQU 32
- MATCHSTRSIZE EQU 32
-
- AUTOKNOB EQU $1
- FREEVERT EQU $4
- PROPBORDERLESS EQU $8
- MEMF_CLEAR EQU $10000
- WINDOWSIZING EQU $1
- WINDOWDRAG EQU $2
- WINDOWDEPTH EQU $4
- WINDOWCLOSE EQU $8
- WINDOWTGADS EQU WINDOWDRAG!WINDOWDEPTH!WINDOWCLOSE
- FPEN EQU 1
- DPEN EQU 3
-
- fib_DirEntryType EQU $4
- fib_FileName EQU $8
- fib_Size EQU $7C
- fib_DateStamp EQU $84
- fib_SIZEOF EQU $104
-
- gg_Flags EQU $C
- id_SIZEOF EQU $24
- it_FrontPen EQU $0
- it_IText EQU $C
- rp_AreaPtrn EQU $8
- rp_AreaPtSz EQU $1D
- wd_Flags EQU $18
- wd_RPort EQU $32
-
- STRUCTURE FSRequest,0
- STRUCT fs_dirname,PATHSTRSIZE
- STRUCT fs_filename,FILESTRSIZE
- STRUCT fs_matchpattern,MATCHSTRSIZE
- WORD fs_leftedge
- WORD fs_topedge
- WORD fs_sorttype
- UWORD fs_flags
- ULONG fs_windowflags
- APTR fs_fullname
- APTR fs_ignorepattern
- APTR fs_pathgadstr
- APTR fs_filegadstr
- APTR fs_titlestr
- APTR fs_readingstr
- APTR fs_sortingstr
- APTR fs_emptydirstr
- APTR fs_nomatchstr
- APTR fs_selectfilestr
- APTR fs_selectstr
- APTR fs_cancelstr
- APTR fs_specgadstr
- APTR fs_userscreen
- APTR fs_userport
- APTR fs_specgadfunc
- APTR fs_dirfunc
- APTR fs_filefunc
- APTR fs_userfunc
- APTR fs_initfunc
- APTR fs_matchfunc
- LABEL fs_SIZEOF
-
- STRUCTURE node_data,0
- STRUCT nd_alphadata,58
- WORD nd_filetype
- WORD nd_showit
- WORD nd_textcolor
- WORD nd_namelength
- ULONG nd_filesize
- ULONG nd_days
- ULONG nd_minutes
- ULONG nd_ticks
- LABEL nd_SIZEOF
-
- STRUCTURE file_node,0
- STRUCT fn_Node,MLN_SIZE
- APTR fn_info
- WORD fn_idnum
- LABEL fn_SIZEOF
-
- STRUCTURE dev_node,0
- STRUCT dn_Node,MLN_SIZE
- STRUCT dn_name,32
- LABEL dn_SIZEOF
-
- XREF _AlphaGad
- XREF _ColonStr
- XREF _CurDevNames
- XREF _DevGads
- XREF _devList
- XREF _DevTxts
- XREF _DOSBase
- XREF _EmptyPattern
- XREF _FileUndoBuffer
- XREF _FileUndoName
- XREF _fnList
- XREF _fsbaddatestr
- XREF _FSCountDown
- XREF _fscurmicros
- XREF _fscursecs
- XREF _fsdatefmtstr
- XREF _fsdayspermonth
- XREF _FSDirFmtStr
- XREF _fsdirlocked
- XREF _FSDone
- XREF _FSDownGad
- XREF _fserrmsgs
- XREF _FSFib
- XREF _FSFileGad
- XREF _FSFileInfo
- XREF _FSFileNodes
- XREF _fsflags
- XREF _FSIgnorePat
- XREF _FSInfo
- XREF _FSLock
- XREF _fsneedshow
- XREF _FSNextDevs
- XREF _fsnumentries
- XREF _fsoldmicros
- XREF _fsoldsecs
- XREF _FSPathBuf
- XREF _FSPathGad
- XREF _FSPathInfo
- XREF _FSPatternGad
- XREF _FSPatternInfo
- XREF _FSPatternUndoBuffer
- XREF _FSPrevDevs
- XREF _fsprevgadid
- XREF _FSReq
- XREF _FSRPort
- XREF _FSSizeFmtStr
- XREF _FSSlideGad
- XREF _FSSlideProp
- XREF _fsstartedstr
- XREF _fstempdate
- XREF _fstitlelength
- XREF _fstitstatus
- XREF _FSUndoGad
- XREF _FSUpGad
- XREF _FSUserGad
- XREF _fsvheight
- XREF _fsvirgindir
- XREF _fsvposition
- XREF _FSWin
- XREF _FSWinTitleStr
- XREF _FSwstr
- XREF _GfxBase
- XREF _IntuitionBase
- XREF _lastdev
- XREF _NIL2Gad
- XREF _OldFSPathBuf
- XREF _RamDirNameStr
- XREF _SizeGad
- XREF _SlashStr
- XREF _TimeGad
- XREF _topfin
-
- XREF _sprintf
- XREF _FSVBDelay
-
- IFD BENCHMARK
- XREF _StartTime
- XREF _StopTime
- XREF _timermsg1
- ENDC
-
- XLVO ActivateGadget
- XLVO AddHead
- XLVO AddTail
- XLVO AllocMem
- XLVO ClipBlit
- XLVO DisplayBeep
- XLVO DoubleClick
- XLVO Examine
- XLVO ExNext
- XLVO FreeMem
- XLVO GetMsg
- XLVO Insert
- XLVO IoErr
- XLVO Move
- XLVO NewModifyProp
- XLVO ParentDir
- XLVO RectFill
- XLVO RefreshGList
- XLVO RemHead
- XLVO ReplyMsg
- XLVO SetAPen
- XLVO SetDrMd
- XLVO SetWindowTitles
- XLVO Text
- XLVO UnLock
-
- SECTION CODE
- * ------------------------------------------------------------------------
- ; LONG MyActivateGad(gadget, window)
- ; struct Gadget *gadget;
- ; struct Window *window;
- ;
- ; Activate a gadget, wait till it is ready. Try up to 3 times. Returns
- ; TRUE (1) if it succeeded, FALSE (0) if it failed to activate.
- * ------------------------------------------------------------------------
- XDEF _MyActivateGad
- _MyActivateGad:
- movem.l d2/a2/a6,-(sp)
- moveq #2,d2 ;Try 3 times to activate gadget
-
- 1$ movem.l 16(sp),a0/a1 ;Grab gadget pointer, window pointer
- suba.l a2,a2 ;No requester pointer
- movea.l _IntuitionBase,a6
- jsr _LVOActivateGadget(a6) ;Activate!
- tst.l d0 ;Did it catch?
- bne.s 2$ ;Yep, move on
-
- pea 5
- jsr _FSVBDelay
- addq.w #4,sp
- dbf d2,1$
- 2$
- movem.l (sp)+,d2/a2/a6
- rts
-
- * --------------------------------------------------------------------- *
- * LONG FSCheckFlagChange(VOID);
- * --------------------------------------------------------------------- *
- XDEF _FSCheckFlagChange
- _FSCheckFlagChange:
-
- movea.l _FSReq,a0
- move.w fs_flags(a0),d0
- move.w _fsflags,d1
- andi.w #%00011000,d0
- andi.w #%00011000,d1
- cmp.w d0,d1 ;FS_SHOW_FILES_FIRST or FS_SHOW_DIRS_FIRST changed?
- beq.s 1$ ;Nope
- move.w #1,_fsvirgindir ;Else we need to re-read the directory
- 1$
- move.w fs_flags(a0),d0
- move.w _fsflags,d1
- andi.w #%01100000,d0
- andi.w #%01100000,d1
- cmp.w d0,d1 ;FS_SHOW_FILES_ONLY or FS_SHOW_DIRS_ONLY changed?
- beq.s 2$ ;Nope
- moveq #1,d0 ;Else flag that we need to FSMatchPattern()
- bra.s 3$
- 2$
- moveq #0,d0
- 3$
- move.w fs_flags(a0),_fsflags ;Reset flags to match FSReq now
- rts
-
- * ------------------------------------------------------------------------
- ; Assign device name texts to intuitexts in the 4 Device Gadgets
- * ------------------------------------------------------------------------
- XDEF _SetDevGads
- _SetDevGads:
- movem.l d3-d4/a2-a3/a5,-(sp)
-
- ;for (i = 0, tnode = lastdev; i < 4;)
- moveq #0,d4 ;d4 = i = 0
- movea.l _lastdev,a2 ;a2 = tnode = lastdev
- move.l a2,d3 ;Copy for comparison
- lea _CurDevNames,a3 ;a3 = &CurDevNames[0]
- lea _DevTxts,a5 ;a5 = &DevTxts[0]
-
- 1$
- lea dn_name(a2),a1
- move.l a1,0(a3,d4.w) ;CurDevNames[i] = tnode->name
-
- moveq #4,d0
- move.l 0(a5,d4.w),a0
- movea.l it_IText(a0),a0
- jsr astrncpy ;astrncpy (DevTxts[i]->IText, tnode->name, 4)
-
- addq.w #4,d4 ;i++
-
- movea.l dn_Node+MLN_SUCC(a2),a2 ;tnode = tnode->dn_Node.mln_Succ
- tst.l dn_Node+MLN_SUCC(a2) ;if (tnode->dn_Node.mln_Succ == 0)
- bne.s 2$ ;Nope
- movea.l _devList,a2
- movea.l MLH_HEAD(a2),a2 ;Else start the listing over at the start
- 2$
- cmpa.l d3,a2 ;Have we already shown this node?
- beq.s 3$ ;Yep, disable the rest
-
- cmpi.w #16,d4 ;Set all 4 Device gadgets yet?
- bcs 1$ ;Nope, do next
-
- 3$
- * Disable any leftover gadgets
- ;for (; i < 4; i++)
- lea _DevGads,a0
- bra.s 5$
-
- 4$ movea.l 0(a0,d4.w),a1
- bset.b #0,gg_Flags(a1) ;DevGads[i]->Flags |= GADGDISABLED
- addq.w #4,d4
-
- 5$ cmpi.w #16,d4
- bcs 4$
-
- movem.l (sp)+,d3-d4/a2-a3/a5
- rts
-
- * ------------------------------------------------------------------------
- ; FSScrollDevGads(direction)
- ; WORD direction;
- * ------------------------------------------------------------------------
- XDEF _FSScrollDevGads
- _FSScrollDevGads:
- movem.l a2/a6,-(sp)
-
- movea.l _lastdev,a0
- tst.w 12+2(sp) ;Grab scroll direction
- beq.s 1$ ;If zero, scroll to next
-
- * Bump list pointer one direction or the other
- move.l dn_Node+MLN_SUCC(a0),a0 ;Get successor
- tst.l dn_Node+MLN_SUCC(a0) ;EndoList?
- bne.s 2$ ;Nope
- movea.l _devList,a0
- movea.l MLH_HEAD(a0),a0 ;Else lastdev = devList->lh_Head
- bra.s 2$
- 1$
- movea.l dn_Node+MLN_PRED(a0),a0 ;Else, lastdev = lastdev->next
- tst.l dn_Node+MLN_PRED(a0) ;Endolist?
- bne.s 2$
- movea.l _devList,a0
- movea.l MLH_TAILPRED(a0),a0 ;Else lastdev = devList->lh_TailPred
- 2$
- move.l a0,_lastdev
- jsr _SetDevGads ;Set the gadget text fields
-
- * Refresh gadget texts
- ;RefreshGList(&NIL2Gad, FSWin, 0L, 4L);
- moveq #4,d0
- suba.l a2,a2
- movea.l _FSWin,a1
- lea _NIL2Gad,a0
- SYS RefreshGList,_IntuitionBase
-
- movem.l (sp)+,a2/a6
- rts
-
- * ------------------------------------------------------------------------
- ; CheckFSArrows()
- ; See if the Up or Down arrow gadgets are currently activated, scroll
- ; the file display area or device gadget list if so.
- * ------------------------------------------------------------------------
- XDEF _CheckFSArrows
- _CheckFSArrows:
- subq.w #1,_FSCountDown
- bge.s 12$
-
- btst.b #7,_FSUpGad+gg_Flags+1 ;FSUpGad.Flags & SELECTED?
- beq.s 2$ ;Nope, maybe FSDownGad
- pea 1 ;Otherwise scroll filegadgets up
- bra.s 3$
-
- 2$ btst.b #7,_FSDownGad+gg_Flags+1 ;FSDownGad.Flags & SELECTED?
- beq.s 4$ ;Nope, maybe slide gadget is selected
- pea 0 ;Otherwise scroll filegadgets down
-
- 3$ jsr _FSScrollFileGads
- addq.w #4,sp
- move.w #0,_FSCountDown ;Set timer to wake up in .02 secs.
- bra.s 12$
-
- 4$ btst.b #7,_FSSlideGad+gg_Flags+1 ;FSSlideGad.Flags & SELECTED?
- beq.s 5$ ;Nope, maybe UpDev
- jsr _FSDoSlideGadget ;Process slide gadget motion
- move.w #0,_FSCountDown ;Set timer to wake up in .02 secs.
- bra.s 12$
-
- 5$ btst.b #7,_FSPrevDevs+gg_Flags+1 ;FSPrevDevs.Flags & SELECTED?
- beq.s 7$ ;Nope, maybe DownDev
- pea 1 ;Otherwise FSScrollDevGads(1);
- 6$ jsr _FSScrollDevGads
- addq.w #4,sp
- move.w #1,_FSCountDown ;Set timer to wake up in .16 secs.
- bra.s 12$
-
- 7$ btst.b #7,_FSNextDevs+gg_Flags+1 ;FSNextDevs.Flags & SELECTED?
- beq.s 10$ ;Nope, nothing of interest, slow down
- pea 0 ;Else FSScrollDevGads(0);
- bra 6$
-
- 10$
- move.w #4,_FSCountDown
- 12$
- rts
-
- * ------------------------------------------------------------------------
- ; BYTE *FibFileDate(fib_date)
- ; struct DateStamp *fib_date;
- ;
- ; Calculate date based on DateStamp structure and return a pointer
- ; to the formatted date text.
- * ------------------------------------------------------------------------
- XDEF _FibFileDate
- _FibFileDate:
- link a5,#0
- movem.l d3-d7,-(sp)
-
- movea.l 8(a5),a1 ;Grab datestamp pointer
- moveq #78,d7 ;Initial year = 1978
-
- move.l (a1),d5 ;days = fib_date->ds_Days
- blt ffdbaddate ;Hey! you can't be negative! Invalid date...
-
- * Determine what year it is
- divu #1461,d5
- move.l d5,d0 ;Stash it
- ext.l d5
- lsl.l #2,d5
- add.l d5,d7 ;year += (days / 1461) * 4
-
- * Count how many months into that year
- ffdgetmo:
- swap d0
- moveq #0,d5
- move.w d0,d5 ;days %= 1461
-
- 1$ tst.w d5 ;Out of days yet?
- beq.s 3$ ;Yep, done here
-
- move.w #365,d6 ;Else month_days = 365
- move.w d7,d0 ;Grab year
- andi.w #3,d0 ;if (year & 3) == 0 Leap year?
- bne.s 2$ ;Nope
- addq.w #1,d6 ;Otherwise bump month_days
-
- 2$ cmp.w d6,d5 ;is day < month_days?
- bcs.s 3$ ;yep, done here
- sub.w d6,d5 ;otherwise day -= month_days
-
- addq.l #1,d7 ; year++
- bra 1$
- 3$
-
- * Count how many days into that month of that year
- ffdgetday:
- ;for (i = 0, day++; i < 12; i++)
- moveq #0,d4 ;current month = 0
- moveq #0,d6 ;Zap hinybs
- addq.w #1,d5
- lea _fsdayspermonth,a0
-
- 1$ move.b 0(a0,d4.w),d6 ;month_days = _fsdayspermonth[i]
-
- cmpi.w #1,d4 ;if (i == 1 && (year & 3) == 0)
- bne.s 2$
- move.w d7,d0
- andi.w #3,d0
- bne.s 2$
- addq.w #1,d6 ;month_days++
-
- 2$ cmp.w d6,d5 ;if (day <= month_days)
- ble.s 4$ ;Break out, found the right month
-
- sub.w d6,d5 ;Else, day -= month_days
-
- addq.w #1,d4 ;i++
- 3$ cmpi.w #12,d4 ;Done all months yet?
- bcs 1$ ;Nope
-
- 4$
- ffdprint:
- 1$ cmpi.l #99,d7 ;while (year >= 100)
- ble.s 2$
- subi.l #100,d7 ;year -= 100
- bra 1$
- 2$
- ;sprintf(_fstempdate, "%02ld-%02ld-%02ld %02ld:%02ld:%02ld", year, i + 1, day, hour, min, sec)
- move.l 8(a1),d0 ;sec = fib_date->ds_Tick / 50;
- divu.w #50,d0
- ext.l d0
- move.l d0,-(sp) ;Push secs
-
- moveq #0,d0 ;Zap reg
- move.w 6(a1),d0 ;min = fib_date->ds_Minute
- move.w d0,d1 ;Clone it
- divu #60,d0
- move.w d0,d3 ;hour = min / 60
- ext.l d3
- mulu #60,d0
- sub.w d0,d1 ;min -= hour * 60
- ext.l d1
- move.l d1,-(sp) ;Push mins
-
- move.l d3,-(sp) ;Push hours
- move.l d5,-(sp) ;Push day of month
- addq.w #1,d4 ;Push month (offset by 1!)
- move.l d4,-(sp)
- move.l d7,-(sp) ;Push year
- pea _fsdatefmtstr ;Push the format pattern
- pea _fstempdate ;Push destination buffer
- jsr _sprintf
- lea 32(sp),sp
- lea _fstempdate,a0
- move.l a0,d0 ;return((BYTE *)&_fstempdate[0])
-
- ffddone:
- movem.l (sp)+,d3-d7
- unlk a5
- rts
-
- ffdbaddate:
- lea _fsbaddatestr,a0
- move.l a0,d0 ;return (" <Invalid Date> ")
- bra ffddone
-
- * --------------------------------------------------------------------- *
- XDEF _FSSetKnobHeight
- _FSSetKnobHeight:
- ;vheight = (ULONG)( 655350L / (long)fsnumentries );
- move.w _fsnumentries,d1
- cmpi.w #10,d1
- bhi.s 1$
- move.w #$ffff,_fsvheight
- rts
- 1$
- move.l #655350,d0
- divu d1,d0
- move.w d0,_fsvheight
- 3$
- rts
-
- * --------------------------------------------------------------------- *
- XDEF _FSSetKnobPos
- _FSSetKnobPos:
- movea.l _topfin,a0
- moveq #0,d0
- move.w fn_idnum(a0),d0
- swap d0
- move.w _fsnumentries,d1
- subi.w #10,d1
- bhi.s 1$
- moveq #0,d0
- bra.s 2$
- 1$
- divu d1,d0
- bvc.s 2$
- move.w #$ffff,d0
- 2$
- move.w d0,_fsvposition
- rts
-
- * --------------------------------------------------------------------- *
- XDEF _FSResetKnob
- _FSResetKnob:
- jsr _FSSetKnobHeight
- jsr _FSSetKnob
- rts
-
- * ------------------------------------------------------------------------
- ; FSSetKnob()
- ; Call ModifyProp() to actually update slide image in window.
- * ------------------------------------------------------------------------
- XDEF _FSSetKnob
- _FSSetKnob:
- movem.l d2-d5/a2/a6,-(sp)
-
- ;NewModifyProp(&FSSlideGad, FSWin, 0L, AUTOKNOB|FREEVERT|PROPB, 0L, vposition, 0xffffL, vheight, 1L)
- lea _FSSlideGad,a0
- movea.l _FSWin,a1
- suba.l a2,a2
- moveq #AUTOKNOB!FREEVERT!PROPBORDERLESS,d0
- moveq #0,d1
- moveq #0,d2
- move.w _fsvposition,d2
- move.l #$ffff,d3
- moveq #0,d4
- move.w _fsvheight,d4
- moveq #1,d5
- SYS NewModifyProp,_IntuitionBase
-
- movem.l (sp)+,d2-d5/a2/a6
- rts
-
- * ------------------------------------------------------------------------
- ; FSEnableFGad(gadg_num)
- ; LONG gadg_num;
- ;
- ; Given a file gadget number, refresh the text for that entry.
- * ------------------------------------------------------------------------
- XDEF _FSEnableFGad
- _FSEnableFGad:
- movem.l a2-a3/a6,-(sp)
-
- movea.l _FSRPort,a2
-
- move.w 4+4*3+2(sp),d0 ;Grab gadget number
- move.w d0,d1 ;Copy
- lsl.w #2,d0 ;Conver to long offset
- lea _FSFileNodes,a0
- movea.l 0(a0,d0.w),a0 ;tnode = FSFileNodes[gadg_num]
- movea.l fn_info(a0),a3 ;a3 = tnode->info
-
- * Move to the right slot text position
- mulu #11,d1
- addi.w #19,d1
- moveq #9,d0
- movea.l a2,a1
- SYS Move,_GfxBase ;Move(FSRPort, 9, gadnum*11+19)
-
- * Set the pen color according to the node
- move.w nd_textcolor(a3),d0
- movea.l a2,a1
- SYS SetAPen ;SetAPen(FSRPort, tinfo->textcolor)
-
- * Blast out the text
- moveq #56,d0
- lea nd_alphadata(a3),a0
- movea.l a2,a1
- SYS Text ;Text(FSRPort, tinfo->alphadata, 56)
-
- movem.l (sp)+,a2-a3/a6
- rts
-
- * ------------------------------------------------------------------------
- ; FSDisableFGad(gadg_num)
- ; LONG gadg_num;
- ;
- ; Given a file gadget number, fill that slot with the EmptyPattern
- ; and clear the FileNode[] slot for that gadget.
- * ------------------------------------------------------------------------
- XDEF _FSDisableFGad
- _FSDisableFGad:
- movem.l d2-d4/a2/a6,-(sp)
-
- move.w 4*5+4+2(sp),d4 ;Grab gadget number
-
- movea.l _FSRPort,a2
-
- lea _EmptyPattern,a0
- move.l a0,rp_AreaPtrn(a2) ;rp->AreaPtrn = EmptyPattern
- move.b #1,rp_AreaPtSz(a2) ;rp->AreaPtSz = (BYTE)1
-
- movea.l a2,a1
- moveq #2,d0
- SYS SetAPen,_GfxBase ;SetAPen(rp, 2)
-
- move.w d4,d1
- mulu #11,d1
- addi.w #13,d1 ;miny = 13L + (gadg_num * 11)
-
- move.l d1,d3
- addq.w #7,d3 ;maxy = miny + 7L
-
- movea.l a2,a1 ;FSWin->RPort
- moveq #9,d0 ;minx
- move.l #456,d2 ;maxx
- SYS RectFill ;RectFill(rp, minx, miny, maxx, maxy)
-
- clr.l rp_AreaPtrn(a2) ;rp->AreaPtrn = 0L
- clr.b rp_AreaPtSz(a2) ;rp->AreaPtSz = (BYTE)0
-
- move.w d4,d0
- lsl.w #2,d0
- lea _FSFileNodes,a0
- clr.l 0(a0,d0.w) ;FSFileNodes[gadg_num] = 0L
-
- movem.l (sp)+,d2-d4/a2/a6
- rts
-
- * --------------------------------------------------------------------- *
- XDEF _FSDisableAllFGads
- _FSDisableAllFGads:
- move.l d2,-(sp)
-
- moveq #0,d2
- move.w _fsnumentries,d2
- bra.s 2$
- 1$ move.l d2,-(sp)
- jsr _FSDisableFGad ;FSDisableFGad(i)
- addq.w #4,sp
- addq.w #1,d2 ;i++
- 2$ cmpi.w #10,d2 ;Hit 10 entries?
- bcs 1$ ;Nope, disable one
- move.l (sp)+,d2
- rts
-
- * ------------------------------------------------------------------------
- ;struct file_node *AllocFileNode()
- ;
- ; Allocate a file_node structure and it's info block, return pointer
- ; to the file_node or NULL if allocation failed.
- * ------------------------------------------------------------------------
- XDEF _AllocFileNode
- _AllocFileNode:
- move.l a6,-(sp)
-
- moveq #fn_SIZEOF+nd_SIZEOF,d0 ;sizeof(struct file_node)+sizeof(struct node_data)
- move.l #MEMF_CLEAR,d1 ;MEMF_CLEAR
- SYS AllocMem,4 ;Allocate file node structure
- move.l d0,d1
- beq.s 1$
- movea.l d0,a0
- addi.l #fn_SIZEOF,d1
- move.l d1,fn_info(a0) ;Set pointer to tnode->info area
- 1$
- movea.l (sp)+,a6
- rts
-
- * ------------------------------------------------------------------------
- ; FreeFileNode(tnode)
- ; struct file_node *tnode;
- ;
- ; Given a pointer to a file_node, Free the memory allocated for that node.
- * ------------------------------------------------------------------------
- XDEF _FreeFileNode
- _FreeFileNode:
- move.l a6,-(sp)
-
- move.l 4+4(sp),d0 ;Grab tnode
- beq.s 2$ ;Nope, get outta here
- movea.l d0,a1
- moveq #fn_SIZEOF+nd_SIZEOF,d0
- SYS FreeMem,4 ;FreeMem(tnode, sizeof(struct file_node)+sizeof(struct node_data))
-
- 2$ movea.l (sp)+,a6
- rts
-
-
- * ------------------------------------------------------------------------
- ; FreeAllFNodes()
- ;
- ; Call FreeFileNode for each node in the linked list of file_nodes,
- ;then deallocate the head of the list (fnList)
- * ------------------------------------------------------------------------
- XDEF _FreeAllFNodes
- _FreeAllFNodes:
- movem.l a2/a6,-(sp)
-
- move.l _fnList,d0 ;Is there a list?
- beq.s 2$ ;Nope, get outta here
-
- movea.l d0,a2 ;Grab head
- movea.l 4,a6 ;Set for ExecBase
- 1$
- movea.l a2,a0
- SYS RemHead ;d0 = RemHead(fnList)
- tst.l d0 ;Hit end?
- beq.s 2$ ;yep
-
- move.l d0,-(sp)
- jsr _FreeFileNode ;Free the node
- addq.w #4,sp
- bra 1$ ;Remove next node
-
- 2$
- * Reset other globals
- clr.w _fsvposition ;Set slider position to top of area
- move.w #$ffff,_fsvheight ;Max height
- clr.w _fsnumentries ;Zero entries
-
- movem.l (sp)+,a2/a6
- rts
-
- * ------------------------------------------------------------------------
- ;struct dev_node *AllocDevNode()
- ;
- ; Allocate a dev_node, return pointer to same
- * ------------------------------------------------------------------------
- XDEF _AllocDevNode
- _AllocDevNode:
- move.l a6,-(sp)
-
- moveq #dn_SIZEOF,d0
- move.l #MEMF_CLEAR,d1
- SYS AllocMem,4 ;AllocMem(sizeof(struct dev_node), MEMF_CLEAR)
-
- movea.l (sp)+,a6
- rts
-
- * ------------------------------------------------------------------------
- ;FreeDevNode(tnode)
- ; struct dev_node *tnode;
- ;
- ; Given a pointer to a dev_node, free memory allocated for that node.
- * ------------------------------------------------------------------------
- XDEF _FreeDevNode
- _FreeDevNode:
- move.l a6,-(sp)
-
- move.l 4+4(sp),d0 ;Grab dev_node to free
- beq.s 1$ ;Oops, nothing here
-
- movea.l d0,a1
- moveq #dn_SIZEOF,d0
- SYS FreeMem,4 ;FreeMem(tnode, (long)sizeof(struct dev_node))
-
- 1$
- movea.l (sp)+,a6
- rts
-
-
- * ------------------------------------------------------------------------
- ;FreeAllDNodes()
- ;
- ; Call FreeDevNode() for each dev_node in the linked list, then free the
- ; head of the list, devList.
- * ------------------------------------------------------------------------
- XDEF _FreeAllDNodes
- _FreeAllDNodes:
- movem.l a2/a6,-(sp)
-
- move.l _devList,d0 ;Is there a head node?
- beq.s 3$ ;Nope, don't deallocate
-
- movea.l d0,a2 ;Grab head of device list
- movea.l 4,a6 ;Set for execbase
-
- 1$ movea.l a2,a0
- SYS RemHead ;d0 = RemHead(devList)
- tst.l d0 ;Got one?
- beq.s 2$ ;Nope, list is empty
-
- move.l d0,-(sp)
- jsr _FreeDevNode ;Free this device node
- addq.w #4,sp
- bra 1$
-
- 2$ movea.l a2,a1
- moveq #MLH_SIZE,d0
- SYS FreeMem ;FreeMem(devList, sizeof(MinList))
- clr.l _devList
-
- 3$ movem.l (sp)+,a2/a6
- rts
-
- * ------------------------------------------------------------------------
- ; FreeFileSelect()
- ; Deallocate filenames and fileinfoblocks, unlock any locks
- * ------------------------------------------------------------------------
- XDEF _FreeFileSelect
- _FreeFileSelect:
- move.l a6,-(sp)
- move.w #1,_fsvirgindir ;virgindir = 1
- jsr _FreeAllFNodes ;Free all allocated filenames
- jsr _FSClearLock ;Unlock any locks
-
- * Free the head node itself
- move.l _fnList,d0
- beq.s 1$
- movea.l d0,a1
- moveq #MLH_SIZE,d0
- SYS FreeMem,4 ;FreeMem(fnList, sizeof(MinList))
- clr.l _fnList ;And clear the pointer
- 1$
- * Free the global FileInfoBlock and InfoData struct
- move.l _FSFib,d0 ;Do we have a FileInfoBlock allocated?
- beq.s 2$ ;Nope
- movea.l d0,a1
- move.l #fib_SIZEOF+id_SIZEOF,d0
- SYS FreeMem,4 ;FreeMem(FSFib, 300L)
- clr.l _FSFib ;Set to NULL so we don't re-free it
- clr.l _FSInfo
- 2$
- movea.l (sp)+,a6
- rts
-
- * --------------------------------------------------------------------- *
- * Cleanup function for fileselect
- * --------------------------------------------------------------------- *
- XDEF _ReleaseFileSelect
- _ReleaseFileSelect:
- jsr _FreeFileSelect
- jsr _FreeAllDNodes
- rts
-
- * ------------------------------------------------------------------------
- ; LONG FSGetNextFib(VOID)
- ;
- ; Call ExNext() to fill in next FileInfoBlock, set titlebar to reflect
- ; status of the request.
- * ------------------------------------------------------------------------
- XDEF _FSGetNextFib
- _FSGetNextFib:
- movem.l d2/a6,-(sp)
-
- * Try to get next fileinfoblock from dos
- move.l _FSLock,d1
- move.l _FSFib,d2
- SYS ExNext,_DOSBase
- tst.l d0 ;Did we get an entry?
- bne.s gnfgot1 ;Yep, got it
-
- * Didn't get one, find out why
- ;if ( (error = IoErr()) != ERROR_NO_MORE_ENTRIES)
- SYS IoErr ;Get error number
- cmpi.l #232,d0 ;No more entries?
- beq.s gnfnme ;Yep
-
- move.l d0,-(sp)
- jsr _ioerrnum ;Otherwise set window title to error number
- addq.w #4,sp
- move.w d0,_fstitstatus
- moveq #-1,d2 ;Return bad get status
- bra.s gnfsetwintit
-
- gnfnme:
- moveq #0,d2 ;Return DONE!
- tst.w _fsnumentries ;Got any valid pattern matches?
- bne.s gnfselect ;Yep, select a file time
-
- movea.l _fnList,a6
- movea.l MLH_HEAD(a6),a6
- tst.l fn_Node+MLN_SUCC(a6) ;Do we have any files?
- beq.s gnfnoentry ;Nope, no entries
-
- move.w #24,_fstitstatus ;Otherwise no match
- bra.s gnfsetwintit
-
- gnfnoentry:
- move.w #22,_fstitstatus ;No Entries...
- bra.s gnfsetwintit
-
- gnfselect:
- move.w #29,_fstitstatus ;Select a file...
-
- gnfsetwintit:
- bra.s gnfdone
-
- gnfgot1:
- moveq #1,d2
-
- gnfdone:
- move.l d2,d0
- movem.l (sp)+,d2/a6
- rts
-
- * ------------------------------------------------------------------------
- ;AllocFSFib()
- ;Allocate a fileinfoblock, return status
- * ------------------------------------------------------------------------
- XDEF _AllocFSFib
- _AllocFSFib:
- move.l a6,-(sp)
- tst.l _FSFib ;Do we already have a fib?
- bne.s 1$ ;Yep, get out of here
-
- ;FSFib = AllocMem(sizeof(*FSFib) + sizeof(*FSInfo), MEMF_CLEAR);
- move.l #fib_SIZEOF+id_SIZEOF,d0
- move.l #MEMF_CLEAR,d1
- SYS AllocMem,4
- move.l d0,_FSFib
- beq.s 2$ ;Oops, allocation failed, return 0
-
- addi.l #fib_SIZEOF,d0
- move.l d0,_FSInfo ;Set pointer to InfoData struct too
-
- 1$ moveq #1,d0 ;Return good status
-
- 2$ movea.l (sp)+,a6
- rts
-
- * ------------------------------------------------------------------------
- ;LONG ioerrnum(num)
- ; LONG num;
- ;
- ; Given an IoErr number, convert to error text table offset, return
- ; converted index number.
- * ------------------------------------------------------------------------
- XDEF _ioerrnum
- _ioerrnum:
- move.l 4(sp),d0
-
- cmpi.w #202,d0 ;if (num < 202L || num > 231L)
- bcs.s ioetl
- cmpi.w #231,d0
- bls.s ioe3l
- ioetl:
- moveq #27,d0 ;return(27)
- rts
- ioe3l:
- cmpi.w #209,d0 ;if (num < 209L)
- bcc.s ioe4l
- subi.w #202,d0 ;num -= 202L
- rts
- ioe4l:
- subi.w #205,d0 ;else num -= 205L
- rts
-
- * ------------------------------------------------------------------------
- ; BYTE *ioerrmsg(num)
- ; long num;
- ;
- ; Given a IoErr number, return pointer to error message text that
- ; describes that error.
- * ------------------------------------------------------------------------
- XDEF _ioerrmsg
- _ioerrmsg:
- move.l 4(sp),-(sp) ;Push error number
- jsr _ioerrnum
- addq.w #4,sp
- lsl.w #2,d0 ;Convert return to text table offset
- lea _fserrmsgs,a0
- move.l 0(a0,d0.w),d0 ;Return pointer to fserrmsgs[num]
- rts
-
- * ------------------------------------------------------------------------
- ; VOID FSPutPath(VOID)
- ; Refresh the FSPathGadget imagery.
- * ------------------------------------------------------------------------
- XDEF _FSPutPath
- _FSPutPath:
- movem.l a2/a6,-(sp)
-
- ;RefreshGList(&FSPathGad, FSWin, 0L, 1L);
- lea _FSPathGad,a0
- movea.l _FSWin,a1
- suba.l a2,a2
- moveq #1,d0
- SYS RefreshGList,_IntuitionBase
-
- movem.l (sp)+,a2/a6
- rts
-
- * ------------------------------------------------------------------------
- ; VOID FSClearLock(VOID)
- ;
- ; If we have a Lock on the current directory, unlock it.
- * ------------------------------------------------------------------------
- XDEF _FSClearLock
- _FSClearLock:
- move.l a6,-(sp)
- tst.w _fsdirlocked ;Is it locked?
- beq.s 2$ ;Nope, don't dare unlock
-
- move.l _FSLock,d1
- beq.s 1$
- SYS UnLock,_DOSBase ;UnLock(FSLock)
- clr.l _FSLock ;FSLock = 0L;
- 1$ clr.w _fsdirlocked ;dirlocked = 0
-
- 2$ movea.l (sp)+,a6
- rts
-
- * ------------------------------------------------------------------------
- ; FSWinTitle()
- ; Refresh current window title using contents of windowtitle[].
- * ------------------------------------------------------------------------
- XDEF _FSWinTitle
- _FSWinTitle:
- movem.l a2/a6,-(sp)
-
- move.w _fstitlelength,d0
- lea _FSWinTitleStr,a0
- clr.b 0(a0,d0.w) ;windowtitle[fstitlelength] = '\x0'
-
- move.w _fstitstatus,d1
- lsl.w #2,d1
- lea _fserrmsgs,a1
- movea.l 0(a1,d1.w),a1
- adda.w d0,a0
- jsr astrcpy ;astrcpy(&windowtitle[fstitlelength], fserrmsgs[fstitstatus])
-
- movea.l _FSWin,a1
- move.l wd_Flags(a1),d0 ;d0 = FSWin->Flags
- andi.l #WINDOWTGADS,d0 ;Do we have titlebar gadgets?
- bne.s 3$ ;Yep, refresh is automatic
-
- lea _FSWinTitleStr+79,a1
- clr.b (a1) ;FSWinTitleStr[79] = 0
- move.b #' ',d0 ;for (;ptr != &FSWinTitle[79];ptr++)
- 2$ cmpa.l a0,a1
- beq.s 4$
- move.b d0,(a0)+ ;*ptr = ' '
- bra 2$
- 3$
- move.b #' ',(a0)+ ;Concat a space and a null onto the end
- clr.b (a0)
- 4$
- ;SetWindowTitles(FSWin, windowtitle, -1L)
- movea.l _FSWin,a0
- lea _FSWinTitleStr,a1
- movea.l #-1,a2
- SYS SetWindowTitles,_IntuitionBase
-
- movem.l (sp)+,a2/a6
- rts
-
- * ------------------------------------------------------------------------
- ; VOID FSEndString(VOID)
- ;
- ; If user started a string gadget entry then clicked in another gadget,
- ;ignore any changes to the string and restore the previous string.
- * ------------------------------------------------------------------------
- XDEF _FSEndString
- _FSEndString:
- movem.l a2/a6,-(sp)
-
- move.w _fsstartedstr,d0 ;Grab starttext flag
- cmpi.w #1,d0 ;Did user start at file entry?
- bne.s fstnotfile ;Nope
-
- movea.l _FSFileInfo,a0 ;Grab filename buffer
- lea _FileUndoName,a1
- lea _FSFileGad,a2 ;Grab filetext gadget
- bra.s fstrefresh ;Refresh it
-
- fstnotfile:
- cmpi.w #2,d0 ;Did user start a path entry?
- bne.s fstnotpath ;Nope, maybe pattern
-
- movea.l _FSPathInfo,a0 ;Grab pathtext buffer
- lea _FileUndoBuffer,a1
- lea _FSPathGad,a2 ;Pointer to path gadget
- bra.s fstrefresh ;Refresh text
-
- fstnotpath:
- cmpi.w #3,d0 ;Started a pattern entry?
- bne.s fstdone ;Nope, don't have to do anything
-
- movea.l _FSPatternInfo,a0 ;Else grab the pattern buffer
- lea _FSPatternUndoBuffer,a1
- lea _FSPatternGad,a2 ;Pointer to pattern gadget
-
- fstrefresh:
- jsr astrcpy ;astrcpy(tstr, FSwstr)
-
- movea.l a2,a0
- movea.l _FSWin,a1
- suba.l a2,a2
- moveq #1,d0
- SYS RefreshGList,_IntuitionBase ;RefreshGList(tgad, FSWin, 0L, 1L)
-
- clr.w _fsstartedstr ;fsstartedstr = 0
-
- fstdone:
- movem.l (sp)+,a2/a6
- rts
-
-
- * ------------------------------------------------------------------------
- ; FSDoGadget(gadgid)
- ; ULONG gadgid;
- ;
- ; Given a gadget id number, perform action associated with that gadget.
- * ------------------------------------------------------------------------
- XDEF _FSDoGadget
- _FSDoGadget:
- movem.l d4/a2,-(sp)
-
- move.w 14(sp),d4 ;Grab gadget id number
- bne.s dgnotusergad ;Not zero, not Undo gadget
-
- * FSUserGad
- jsr _ConcatPathString ;Concat final output text, return
- clr.w _FSDone
-
- movea.l _FSReq,a1
- movea.l fs_specgadfunc(a1),a0
- pea _FSUserGad
- move.l _FSWin,-(sp)
- move.l a1,-(sp)
- jsr (a0)
- lea 12(sp),sp
- tst.l d0
- bne dgnewdir
- bra dogaddone
-
- dgnotusergad:
- * FSSelectGad
- cmpi.w #1,d4 ;Is the the FSSelect gadget?
- bne.s dgnotselect ;Nope
- jsr _ConcatPathString ;Concat final output text, return
- bra dogaddone
-
- dgnotselect:
- * FSCancelGad
- cmpi.w #2,d4 ;Is it the FSCancel Gadget?
- bne.s dgnotcancel ;Nope
- move.w #1,_FSDone ;Global signal that we're done
- movea.l _FSReq,a0 ;a0 = fsreq
- movea.l fs_fullname(a0),a0 ;a0 = fsreq->fullname
- clr.b (a0) ;Return filename == ""
- bra dogaddone
-
- dgnotcancel:
- * UndoGad
- cmpi.w #3,d4 ;Undo?
- bne.s dgnotundo
- movea.l _FSPathInfo,a0 ;Copy OldFSPathBuf to FSPathInfo.Buffer
- movea.l _OldFSPathBuf,a1
- jsr astrcpy ;astrcpy(FSPathInfo.Buffer, OldFSPathBuf)
- bra dgnewdir ;Process new directory
-
- dgnotundo:
- * Dev1Gad
- cmpi.w #20,d4 ;Is it the first Device Gadget?
- bne.s dgnotram ;Nope
- movea.l _CurDevNames+12,a1 ;Push the name text
- dgdevs:
- movea.l _FSPathInfo,a0 ;Destination text
- jsr astrcpy ;Copy new path
- bra dgnewdir ;Now set new directory
-
- dgnotram:
- cmpi.w #21,d4 ;Is it the second Device Gadget?
- bne.s dgnotdf0 ;Nope
- movea.l _CurDevNames+8,a1 ;Push the name text
- bra dgdevs ;Change path
-
- dgnotdf0:
- cmpi.w #22,d4 ;Is it the third Device Gadget?
- bne.s dgnotnil1 ;Nope
- movea.l _CurDevNames+4,a1 ;Push the name text
- bra dgdevs ;Set the path
-
- dgnotnil1:
- cmpi.w #23,d4 ;Is it the fourth Device Gadget?
- bne.s dgnotnil2 ;Nope
- movea.l _CurDevNames,a1 ;Push the name text
- bra dgdevs ;And set the new path
-
- dgnotnil2:
- * RootGad
- cmpi.w #24,d4 ;Is it the ROOT gadget?
- bne.s dgnotroot ;Nope
- jsr _SetRootDir ;Set root directory!
- bra dogaddone ;Done
-
- dgnotroot:
- * ParentGad
- cmpi.w #25,d4 ;Is it the Parent gadget?
- bne.s dgnotpar ;Nope
- jsr _SetParentDir ;Change to parent directory
- bra dogaddone ;Done!
-
- dgnotpar:
- * FSPatternGad
- cmpi.w #30,d4 ;Maybe its the pattern text gadget?
- bne.s dgnotpattern
- jsr _FSMatchPattern ;Otherwise attempt to match new pattern
- bra dogaddone ;We're done!
-
- dgnotpattern:
- * FSFileGad
- cmpi.w #31,d4 ;Is it the file text gadget?
- bne.s dgnotfileg ;Nope
- jsr _FSFileFunc
- jsr _ConcatPathString ;Form final path text
- btst.b #1,_fsflags+1 ;FS_NO_STRING_EXIT?
- beq dogaddone
- clr.w _FSDone
- bra dogaddone
- 1$
- movea.l _FSFileInfo,a0
- tst.b (a0) ;Really a filename here?
- bne.s 2$ ;yep
- btst.b #2,_fsflags+1 ;FS_NO_STRING_OKAY?
- beq.s 2$ ;Nope
- bra dogaddone ;let user exit with no filename
- 2$
- clr.w _FSDone ;Else we ain't done yet!
- bra dogaddone
-
- dgnotfileg:
- * FSPathGad
- cmpi.w #32,d4 ;Is it the path text gadget?
- bne.s dgnotpath ;Nope
- movea.l _FSPathInfo,a2 ;Grab pointer to path text
- movea.l a2,a0
- jsr astrlen ;Determine length
- subq.w #1,d0 ;Move back to last BYTE
- blt.s dgnotdamnsla ;Oops, null text!
-
- cmpi.b #'/',0(a2,d0.w) ;Is the last char a slash?
- bne.s dgnotdamnsla ;Nope, don't have to tromp it
-
- 1$ cmpi.b #'/',0(a2,d0.w) ;Check for a trailing slash
- bne.s 2$ ;Didn't find another
- clr.b 0(a2,d0.w) ;Clobber this slash
- subq.w #1,d0 ;Dec character pointer
- bne.s 1$ ;till we run out of slashes or chars
-
- 2$ jsr _FSPutPath ;Refresh path text
- dgnotdamnsla:
- jsr _FSDirFunc ;Do fsreq->dirfunc, if there is one
- tst.w d0 ;Ignore new dir?
- beq.s 1$ ;Nope
- jsr _SetParentDir ;Else chop off the new path
- jsr _FSPutPath ;Update string gad
- clr.w _fsvirgindir ;Virgin again
- bra.s dogaddone ;All done
- 1$
- move.l _FSWin,-(sp)
- pea _FSFileGad
- jsr _MyActivateGad ;Activate file text gadget
- addq.w #8,sp
- bra.s dgnewdir ;Set new path, read new dir
-
- dgnotpath:
- * Slide Gadget
- cmpi.w #33,d4 ;Is it the SlideGadget?
- bne.s dgnotslide ;nope
- jsr _FSDoSlideGadget ;Else it's been released, update position
- bra.s dgresetarrows ;Done here, reset timer
-
- dgnotslide:
- * Arrow gadgets
- cmpi.w #40,d4 ;Is it one of the four arrows gadgets?
- blt.s dogaddone
- cmpi.w #43,d4
- bgt.s dogaddone
- dgresetarrows:
- clr.w _FSCountDown ;Kill any timer requests in progress
- bra.s dogaddone
-
- dgnewdir:
- move.w #1,_fsvirgindir ;Set flag to read new directory!
-
- dogaddone:
- movem.l (sp)+,d4/a2
- rts
-
- * --------------------------------------------------------------------- *
- * VOID FillFileNode(tnode)
- * struct file_node *tnode;
- * --------------------------------------------------------------------- *
- ffnnode EQU 4+4*4
-
- XDEF _FillFileNode
- _FillFileNode:
- movem.l d2/a2-a3/a6,-(sp)
-
- movea.l ffnnode(sp),a0 ;a0 = tnode passed
- movea.l fn_info(a0),a2 ;a2 = tinfo = tnode->info
- movea.l _FSFib,a3 ;a3 = FSFib
-
- move.l fib_Size(a3),nd_filesize(a2) ;tinfo->filesize = FSFib->fib_Size
- move.l fib_DateStamp+0(a3),nd_days(a2) ;tinfo->day = FSFib->fib_DateStamp.ds_Days
- move.l fib_DateStamp+4(a3),nd_minutes(a2)
- move.l fib_DateStamp+8(a3),nd_ticks(a2)
-
- pea fib_DateStamp(a3)
- jsr _FibFileDate
- addq.w #4,sp
-
- movea.l d0,a1
- lea nd_alphadata(a2),a0 ;a0 = tinfo->alphadata
- jsr astrcpy ;a0 = astrcpy(&tinfo->alphadata[0], FibFileDate(&FSFib->DateStamp))
-
- tst.l fib_DirEntryType(a3) ;If < 0 it is a file
- bge.s ffnisdir ;>= 0, it is a dir
-
- ffnisfile:
- move.w #1,nd_filetype(a2) ;tinfo->filetype = 1
- move.w #FPEN,nd_textcolor(a2) ;tinfo->textcolor = FPEN
-
- move.l a0,-(sp)
- move.l fib_Size(a3),-(sp)
- pea _FSSizeFmtStr
- move.l a0,-(sp)
- jsr _sprintf ;sprintf(a0, "%8ld ", FSFib->fib_Size)
- lea 12(sp),sp
- movea.l (sp)+,a0
- adda.w #9,a0 ;Skip filesize part of message
- bra.s ffnsetname
-
- ffnisdir:
- move.w #2,nd_filetype(a2) ;tinfo->filetype = 2
- move.w #DPEN,nd_textcolor(a2) ;tinfo->textcolor = DPEN
-
- lea _FSDirFmtStr,a1
- jsr astrcpy ;astrcpy(dest, FSDirFmtStr)
-
- ffnsetname:
- moveq #0,d0
- lea fib_FileName(a3),a1 ;a1 = FSFib->fib_FileName
- 1$ move.b (a1)+,d1
- beq.s 2$ ;Hit null, see if we need to pad
- move.b d1,(a0)+ ;copy a char, till null
- addq.w #1,d0 ;i++
- cmpi.w #30,d0 ;Max chars yet?
- bcs 1$
-
- 2$ move.w d0,nd_namelength(a2) ;tinfo->namelength = i
- move.b #' ',d1
- bra.s 4$ ;Append spaces till 30 chars
- 3$ move.b d1,(a0)+
- addq.w #1,d0
- 4$ cmpi.w #30,d0
- bcs 3$
-
- clr.b (a0) ;Null terminate at 31st char
-
- ffnsetshow:
- movea.l ffnnode(sp),a2
- moveq #1,d0
- movea.l a2,a0 ;a0 = tnode
- jsr _FSValidateEntry ;FSValidateEntry(tnode, 1)
-
- * Now insert the node into list according to sort type
- ffninsert:
- movea.l _fnList,a3
- movea.l MLH_HEAD(a3),a3 ;a3 = fnList->lh_Head
-
- movea.l _FSReq,a0
- move.w fs_sorttype(a0),d2 ;d0 = FSReq->sorttype
-
- 1$
- tst.l fn_Node+MLN_SUCC(a3) ;Is this the end of the list?
- beq.s 2$ ;Nope, insert it here
-
- move.l fn_info(a3),a1 ;Push existing node->info
- move.l fn_info(a2),a0 ;Push tnode->info
- move.w d2,d0 ;Push sort type
- jsr _CompareNodes ;Compare info's according to sort type
- tst.w d0 ;Is a0 > a1?
- beq.s 2$ ;nope, found insertion point
- movea.l fn_Node+MLN_SUCC(a3),a3 ;oldnode = oldnode->next
- bra 1$ ;Nope, keep looking
-
- 2$
- movea.l _fnList,a0
- movea.l a2,a1
- move.l fn_Node+MLN_PRED(a3),a2
- SYS Insert,4
-
- ffndone:
- movem.l (sp)+,d2/a2-a3/a6
- rts
-
- * --------------------------------------------------------------------- *
- * VOID FSValidateEntry(tnode, mode)
- * a0 d0
- * --------------------------------------------------------------------- *
- XDEF _FSValidateEntry
- _FSValidateEntry:
- movem.l d2-d3/a2,-(sp)
-
- * See if the Acceptor likes this node name
- move.l d0,d3 ;d3 = mode
- movea.l a0,a2 ;a2 = tnode
- move.l a2,-(sp)
- jsr _FSAcceptEntry ;if (FSAcceptEntry(tnode) == 0)
- addq.w #4,sp
- tst.w d0
- bne.s 1$
-
- * Don't display this node
- movea.l fn_info(a2),a0
- clr.w nd_showit(a0) ;tnode->info->showit = 0;
- move.w #-1,fn_idnum(a2) ;tnode->idnum = -1
- bra.s 4$ ;And return
-
- * Accept this node for display
- 1$ movea.l fn_info(a2),a0
- move.w #1,nd_showit(a0) ;else tnode->info->showit = 1;
-
- moveq #0,d2
- move.w _fsnumentries,d2 ;Grab entry number for this node
- bne.s 2$ ;Not first entry
- move.l a2,_topfin ;topnode = tnode, first visible node
- 2$
- move.w d2,fn_idnum(a2) ;tnode->idnum = fsnumentries
- addq.w #1,_fsnumentries ;fsnumentries++, one more visible entry
- clr.w _fsneedshow ;fsneedshow = 0, needs sorting
-
- * If we haven't filled display area, show this entry
- cmpi.w #10,d2 ;> 10 entries already?
- bcc.s 3$ ;Yep, just set the knob
-
- lea _FSFileNodes,a0
- move.w d2,d0 ;Grab entry number
- lsl.w #2,d0 ;Convert to long table offset
- move.l a2,0(a0,d0.w) ;FSFileNodes[fsnumentries] = tnode
-
- move.l d2,-(sp)
- jsr _FSEnableFGad ;FSEnableFGad(fsnumentries)
- addq.w #4,sp
- bra.s 4$ ;Skip setting knob, it is still full size
-
- 3$
- tst.w d3 ;Want slide update?
- beq.s 4$ ;Nope
-
- ; btst.b #7,_FSSlideGad+gg_Flags+1 ;User has slide gadget in use?
- ; bne.s 4$ ;Yes, don't refresh it while in use
-
- * Calc new knob size and refresh
- btst.l #0,d2 ;(idnum % 2) == 0?
- beq.s 4$ ;Yep, don't reset on even values
- jsr _FSResetKnob
-
- 4$
- movem.l (sp)+,d2-d3/a2
- rts
-
- * --------------------------------------------------------------------- *
- * Update FileTexts list, redisplay
- * Renumber list, find new topfin
- * --------------------------------------------------------------------- *
- XDEF _FSUpdateSort
- _FSUpdateSort:
- move.w _fsneedshow,d0
- blt.s 3$
- move.w _fsnumentries,d1
- beq.s 2$
- subi.w #10,d1 ;Less max number of visible files
- move.w _FSSlideProp+4,d0 ;Grab current vpot
- mulu d1,d0 ;Times position percentage
- addi.l #32768,d0
- clr.w d0
- swap d0
- jsr _FSResetNumEntries
- jsr _FSSetFileGads
- 2$
- move.w #-1,_fsneedshow
- moveq #0,d0
-
- 3$ tst.w d0
- rts
-
- * --------------------------------------------------------------------- *
- * VOID FSResetNumEntrys(idnum)
- * d0:16
- * --------------------------------------------------------------------- *
- XDEF _FSResetNumEntries
- _FSResetNumEntries:
- move.l a2,-(sp)
-
- movea.l _fnList,a2 ;Grab List
- movea.l MLH_HEAD(a2),a2 ;Head of list
-
-
- moveq #0,d1 ;i = 0
-
- 1$ tst.l fn_Node+MLN_SUCC(a2) ;End of list?
- beq.s 5$
- movea.l fn_info(a2),a0 ;a0 = tnode->info
- tst.w nd_showit(a0) ;Visible?
- bne.s 2$ ;Yep
- move.w #-1,fn_idnum(a2) ;Else tnode->idnum = -1
- bra.s 4$ ;Next node
- 2$ move.w d1,fn_idnum(a2) ;tnode->idnum = i
- cmp.w d1,d0 ;if (idnum == oldidnum)
- bne.s 3$
- move.l a2,_topfin ; topfin = tnode;
- 3$
- addq.w #1,d1 ;i++
- 4$
- movea.l fn_Node+MLN_SUCC(a2),a2 ;tnode = tnode->fn_Node.mln_Succ
- bra 1$ ; Check next node
-
- 5$
- move.w d1,_fsnumentries ;Update number of entries
-
- movea.l (sp)+,a2
- rts
-
- * --------------------------------------------------------------------- *
- * LONG FSAcceptEntry(struct file_node *tnode);
- * Decide whether given tnode is displayable.
- * Return 0L for ignore this node, 1L for valid node.
- * --------------------------------------------------------------------- *
- aftnode EQU 8
- aftname EQU -48
-
- XDEF _FSAcceptEntry
- _FSAcceptEntry:
- link a5,#aftname
- movem.l a2-a3,-(sp)
-
- movea.l aftnode(a5),a2 ;Grab tnode
- movea.l fn_info(a2),a3 ;Grab tnode->info
-
- * Copy tnode->info->alphadata name section to stack, null terminate
- move.w nd_namelength(a3),d0 ;Push tinfo->namelength
- lea nd_alphadata+26(a3),a1 ;Push tinfo->alphadata + 26
- lea aftname(a5),a0 ;Push destination
- jsr astrncpy ;Copy and null terminate
-
- * If there is a special match function defined, use that...
- movea.l _FSReq,a0
- tst.l fs_matchfunc(a0) ;If FSReq->matchfunc != 0
- beq.s 1$
- move.l aftnode(a5),-(sp)
- pea aftname(a5)
- move.l _FSReq,-(sp)
- move.l fs_matchfunc(a0),a0
- jsr (a0) ;return((FSReq->matchfunc)(FSReq, name, tnode)
- lea 12(sp),sp
- bra.s aftdone
-
- * Otherwise use built-in acceptor routine
- 1$ cmpi.w #2,nd_filetype(a3) ;Is tinfo->filetype == 2? (a directory)
- beq.s aftisdir ;Yep, we need it in list
-
- * Check file name against patterns
- btst.b #6,_fsflags+1 ;Want dirs only?
- bne.s aftwrongpat ;Yep, ignore all files
-
- pea _FSIgnorePat ;See if it matches the ignore text
- pea aftname(a5)
- jsr _wildmatch
- addq.w #8,sp
- tst.w d0 ;Did it match the ignore text?
- bne.s aftwrongpat ;Yep, ignore this file
-
- move.l _FSPatternInfo,-(sp) ;See if it matches desired pattern
- pea aftname(a5)
- jsr _wildmatch
- addq.w #8,sp
- tst.w d0 ;Did it match?
- beq.s aftwrongpat ;Nope, skip it
- bra.s aftgoodpat ;Else accept this file
-
- aftisdir:
- btst.b #5,_fsflags+1 ;This is a dir, want files only?
- bne.s aftwrongpat ;Yep, ignore this dir
-
- aftgoodpat:
- moveq #1,d0 ;Accept this entry
- bra.s aftdone
-
- aftwrongpat:
- moveq #0,d0 ;Ignore this entry
-
- aftdone:
- movem.l (sp)+,a2-a3
- unlk a5
- rts
-
- * --------------------------------------------------------------------- *
- * VOID FSMatchPattern(VOID);
- * Called when path or pattern has changed - rematch all entries
- * against the new pattern, display entries that match.
- * --------------------------------------------------------------------- *
- XDEF _FSMatchPattern
- _FSMatchPattern:
- movem.l d4/a2-a3/a6,-(sp)
-
- * Pattern match list against new pattern, flag unwanted names
- movea.l _FSPatternInfo,a0 ;Grab pattern
- tst.b (a0) ;Null pattern text?
- bne.s mnpnotnop ;Nope, process it
-
- move.b #'*',(a0)+ ;Otherwise put back wildstar
- clr.b (a0) ;Null terminate
- lea _FSPatternInfo,a0 ;Grab stringinfo
- move.w #1,8(a0) ;FSPatternInfo.BufferPos = 1;
-
- lea _FSPatternGad,a0
- movea.l _FSWin,a1
- suba.l a2,a2
- moveq #1,d0
- SYS RefreshGList,_IntuitionBase ;Refresh pattern text gadget
-
- move.l _FSWin,-(sp)
- pea _FSPatternGad
- jsr _MyActivateGad ;MyActivateGad(&FSPatternGad, FSWin)
- addq.w #8,sp
- bra.s mnpdone ;Make the user type something else in
-
- mnpnotnop:
- movea.l _fnList,a0
- move.l MLH_HEAD(a0),a0
- tst.l fn_Node+MLN_SUCC(a0) ;Do we have any files to match?
- beq.s mnpdone ;Nope, nothing to do
-
- * Reset knob to full height, zero position
- clr.w _fsnumentries ;Clear fsnumentries count
- clr.w _fsvposition
- move.w #$ffff,_fsvheight
- jsr _FSSetKnob ;Show new knob
-
- * Disable all file "gadgets"
- jsr _FSDisableAllFGads
-
- * Scan list, enable/flag entries that match new pattern
- movea.l _fnList,a2 ;tnode = fnList
- movea.l MLH_HEAD(a2),a2 ;tnode = head node
- clr.l _topfin ;Clear out top/bot display pointers
- 1$
- tst.l fn_Node+MLN_SUCC(a2) ;End of list?
- beq.s 2$
-
- moveq #0,d0
- movea.l a2,a0
- jsr _FSValidateEntry ;FSValidateEntry(tnode, 0)
- movea.l fn_Node+MLN_SUCC(a2),a2 ;tnode = tnode->fn_Node.mln_Succ
- bra 1$ ;Nope, process this one too
- 2$
- move.w #-1,_fsneedshow ;Clear reshow/sort flag, list valid
- cmpi.w #10,_fsnumentries ;Found some entries?
- bls.s mnpsettitle ;Yep, skip setting knob again
- jsr _FSResetKnob ;Show new knob size
-
- mnpsettitle:
- tst.w _fsnumentries ;Got any matches to pattern?
- bne.s mnpmatchedsome ;Yep
-
- move.w #24,_fstitstatus ;"Nothing matched PATTERN"
- bra.s mnpnewtit
-
- mnpmatchedsome:
- move.w #29,_fstitstatus ;"Select a file..."
-
- mnpnewtit:
- jsr _FSWinTitle ;Show final title status
-
- mnpdone:
- movem.l (sp)+,d4/a2-a3/a6
- rts
-
- * ----------------------------------------------------------------------
- ; VOID ConcatPathString(VOID)
- ;
- ; If the file text is non-NULL, concat path text and file text,
- ; set global exit flag to show user selected a filename.
- * ----------------------------------------------------------------------
- XDEF _ConcatPathString
- _ConcatPathString:
- * Try to add path prefix
- move.l _FSFileInfo,-(sp)
- move.l _FSPathInfo,-(sp)
- movea.l _FSReq,a0 ;Grab final pathtext
- movea.l fs_fullname(a0),a0
- move.l a0,-(sp)
- jsr _ConcatDirFile ;ConcatDirFile(FSReq->fullname, FSPathInfo->Buffer, FSFileInfo->Buffer)
- lea 12(sp),sp
-
- * Did the user select a filename yet?
- movea.l _FSFileInfo,a0
- tst.b (a0) ;First byte of name null?
- bne.s 1$ ;Nope, must be okay
- btst.b #2,_fsflags+1 ;(FSFlags & FS_NO_STRING_OKAY) == 0?
- beq.s 2$ ;Yep, user can't exit till something is entered
- 1$
- * Flag main loop to exit
- move.w #1,_FSDone
- 2$
- rts
-
- * --------------------------------------------------------------------- *
- * VOID __stdargs ConcatDirFile(BYTE *, BYTE *, BYTE *)
- * --------------------------------------------------------------------- *
- XDEF _ConcatDirFile
- _ConcatDirFile:
- movem.l 4(sp),a0-a1 ;grab dest, dirname
- tst.b (a1) ;Is there a dirname here?
- beq.s 1$ ;Nope
- jsr astrcpy ;astrcpy(dest, dirname)
- movea.l 12(sp),a1 ;grab filename
- tst.b (a1) ;Is there a filename?
- beq.s 2$ ;Nope, don't concat a slash
- move.b -1(a0),d0 ;d0 = dest[strlen(dest - 1)]
- cmpi.b #':',d0 ;Already has a colon?
- beq.s 1$ ;Yep
- cmpi.b #'/',d0 ;Already has a slash?
- beq.s 1$ ;Yep
- move.b #'/',(a0)+ ;Append a slash
- clr.b (a0) ;Terminate
- 1$
- movea.l 12(sp),a1
- jsr astrcpy ;astrcpy(dest, name)
- 2$
- rts
-
- * ------------------------------------------------------------------------
- * VOID FSDoSlideGadget(VOID)
- *
- * Process the current slide gadget position, scroll file entries
- * to match current position.
- * ------------------------------------------------------------------------
- XDEF _FSDoSlideGadget
- _FSDoSlideGadget:
- movem.l d4-d5,-(sp)
-
- jsr _FSUpdateSort
- beq dsgdone
-
- cmpi.w #10,_fsnumentries ;Do we have less than 10 entries?
- blt dsgdone ;Yep, can't move anyhow
-
- moveq #0,d0
- move.w _FSSlideProp+4,d0 ;Grab new vpot
- cmp.w _fsvposition,d0 ;Has it moved?
- beq dsgdone ;Nope
-
- move.w d0,_fsvposition ;Otherwise update position
-
- move.w _fsnumentries,d4 ;Grab number of entries
- subi.w #10,d4 ;Less max number of visible files
- mulu d0,d4 ;Times position percentage
- addi.l #32768,d4
- clr.w d4
- swap d4
-
- movea.l _topfin,a0 ;Grab top node
- cmp.w fn_idnum(a0),d4 ;Is node->idnum the same as newpos?
- beq.s dsgdone ;Yep, don't have to move it
- bcc.s dsgscrup ;newpos is lower, scroll up
-
- **************
- * Scroll Down
- **************
- move.w fn_idnum(a0),d0 ;Grab topfin->idnum
- sub.w d4,d0 ;i = idnum - newpos
- cmpi.w #8,d0 ;Need to scroll more than 8?
- ble.s dsgssdwn ;Nope, use slow scroll
-
- dsgdwn1:
- cmp.w fn_idnum(a0),d4 ;Is topfin->idnum == newpos yet?
- beq.s dsgredo ;Yep, we are done
-
- dsgpretop:
- movea.l fn_Node+MLN_PRED(a0),a0 ;topfin = topfin->fn_Node.mln_Pred
- tst.w fn_idnum(a0) ;Is this idnum >= 0?
- blt.s dsgpretop ;Nope, keep looking
- bra.s dsgdwn1 ;Check this new position
-
- dsgssdwn:
- move.l d0,-(sp)
- jsr _FSScrollDownGads ;Scroll entries down d5 times
- addq.w #4,sp
- bra.s dsgdone
-
- ************
- * Scroll Up
- ************
- dsgscrup:
- move.w d4,d5 ;Grab newpos
- sub.w fn_idnum(a0),d5 ;i = newpos - node->idnum
- cmpi.w #8,d5 ;i > 8?
- ble.s dsgssup ;Nope, use slow scroll
-
- dsgmvup1:
- cmp.w fn_idnum(a0),d4 ;Is topfin->idnum == newpos yet?
- beq.s dsgredo ;Yep, we are done
-
- dsgnxttop:
- movea.l fn_Node+MLN_SUCC(a0),a0 ;topfin = topfin->fn_Node.mln_Succ
- tst.w fn_idnum(a0) ;Is this a valid entry?
- blt.s dsgnxttop ;Nope, move on
- bra.s dsgmvup1
-
- dsgredo:
- move.l a0,_topfin ;Set new top and bottom
- jsr _FSSetFileGads ;Redraw all the file entries
- bra.s dsgdone ;We're done
-
- dsgssup:
- move.l d5,-(sp)
- jsr _FSScrollUpGads ;Scroll the entries up d5 times
- addq.w #4,sp
-
- dsgdone:
- movem.l (sp)+,d4-d5
- rts
-
- * --------------------------------------------------------------------
- * VOID FSStartScrollGad(gadcode)
- * ULONG gadcode;
- * Given Gadget ID code, respond to first user click on a arrow gadget.
- * Reset the timer.device so that .25 seconds delay occurs before
- * the autorepeat kicks in.
- * --------------------------------------------------------------------
- XDEF _FSStartScrollGad
- _FSStartScrollGad:
- move.w 6(sp),d0 ;Grab gadget code
- subi.w #33,d0 ;Slide gad
- bne.s 1$
- jsr _FSDoSlideGadget
- clr.w _FSCountDown
- rts
-
- 1$
- subi.w #7,d0 ;33+7=40, UpGad
- bne.s 2$
- pea 1
- 11$ jsr _FSScrollFileGads
- addq.w #4,sp
- bra.s ssgdone
- 2$
- subq.w #1,d0 ;33+7+1=41, DownGad
- bne.s 3$
- pea 0
- bra 11$
- 3$
- subq.w #1,d0 ;33+7+2=42, UpDev
- bne.s 4$
- pea 1
- 33$ jsr _FSScrollDevGads
- addq.w #4,sp
- bra.s ssgdone
- 4$
- subq.w #1,d0 ;33+7+3=43, DownDev
- bne.s ssgrts
- pea 0
- bra 33$
-
- ssgdone:
- move.w #4,_FSCountDown
- ssgrts:
- rts
-
- * -----------------------------------------------------------------------
- * FSScrollFileGads(direction)
- * BOOL direction;
- *
- * Scroll the file entries up or down by 1
- * if (direction == 0)
- * scrollup;
- * else
- * scrolldown;
- * -----------------------------------------------------------------------
- XDEF _FSScrollFileGads
- _FSScrollFileGads:
-
- ;if (fsnumentries > 10)
- cmpi.w #10,_fsnumentries ;Less than 10 entries?
- ble.s sfgdone ;Yep, can't scroll anyhow
-
- ;if (direction)
- ; FSScrollDownGads(1);
- tst.w 6(sp) ;ScrollDown?
- beq.s sfgup ;Nope, scroll up
- pea 1
- jsr _FSScrollDownGads
- addq.w #4,sp
- bra.s sfgpos
-
- sfgup:
- ;FSScrollUpGads(1)
- pea 1
- jsr _FSScrollUpGads
- addq.w #4,sp
-
- sfgpos:
- * Reset the slide knob position the display movement
- jsr _FSSetKnobPos
- jsr _FSSetKnob ;Set new knob position
-
- sfgdone:
- rts
-
- * -------------------------------------------------------------------------
- ; FSScrollUpGads(count)
- ; LONG count;
- ;
- ; Single-step scroll the file entries up count times.
- * -------------------------------------------------------------------------
- XDEF _FSScrollUpGads
- _FSScrollUpGads:
- link a5,#0
- movem.l d2-d7/a2/a6,-(sp)
-
- jsr _FSUpdateSort
- beq.s sugdone
-
- movea.l _FSRPort,a2
-
- ;for (i = 0; i < count; i++)
- moveq #0,d7
- bra.s sugchk1
-
- sugloop1:
- * If the bottom entry is not the last entry, scroll it up
- movea.l _topfin,a0 ;Grab top visible node
- move.w fn_idnum(a0),d0 ;Grab id number
- addi.w #11,d0 ;Plus 11
- cmp.w _fsnumentries,d0 ;Compare to last known entry
- bgt.s sugdone ;Yep, can't scroll up any more
-
- * Bump the top pointer down the list to the next visible entry
- movea.l _topfin,a0
- 1$ move.l fn_Node+MLN_SUCC(a0),a0 ;topfin = topfin->fn_Node.mln_Succ
- tst.w fn_idnum(a0) ;while (topfin->idnum < 0)
- blt 1$ ;Not a valid entry
- move.l a0,_topfin ;Here's our new top entry node
-
- * Now reassign the visible file gadget array to the new node list
- jsr _FSAssignNodes
-
- * Display new file entries and redraw borders
- ;ClipBlit(rp, 9L, 24L, rp, 9L, 13L, 447L, 96L, 0xc0L);
- movea.l a2,a0
- moveq #9,d0
- moveq #24,d1
- movea.l a2,a1
- moveq #9,d2
- moveq #13,d3
- move.l #447,d4
- moveq #96,d5
- move.l #$0c0,d6
- SYS ClipBlit,_GfxBase
-
- ;FSEnableFGad(9);
- move.l #9,-(sp)
- jsr _FSEnableFGad ;Now draw the new gadget at bottom
- addq.w #4,sp
-
- addq.w #1,d7 ;Bump scroll count
-
- sugchk1:
- cmp.w 10(a5),d7 ;Have we scrolled enough?
- blt sugloop1 ;Nope, do again
-
- sugdone:
- movem.l (sp)+,d2-d7/a2/a6
- unlk a5
- rts
-
- * -------------------------------------------------------------------------
- ; FSScrollDownGads(count)
- ; LONG count;
- ;
- ; Single-step scroll the file entries down count times.
- * -------------------------------------------------------------------------
- XDEF _FSScrollDownGads
- _FSScrollDownGads:
- link a5,#0
- movem.l d2-d7/a2/a6,-(sp)
-
- jsr _FSUpdateSort
- beq.s sdgdone
-
- movea.l _FSRPort,a2
-
- ;for (i = 0; i < count; i++)
- moveq #0,d7
- bra.s sdgchk1
-
- sdgloop1:
- ;If the top entry is not the first entry, scroll it down
- movea.l _topfin,a0 ;Grab top node
- tst.w fn_idnum(a0) ;idnum == 0?
- beq.s sdgdone ;Yep, can't scroll down any more
-
- * Bump the top and bottom entry pointers down the list
- 1$ movea.l fn_Node+MLN_PRED(a0),a0 ;topfin = topfin->fn_Node.mln_Pred
- tst.w fn_idnum(a0) ;while (topfin->idnum < 0)
- blt 1$
- move.l a0,_topfin ;New topfin
-
- * Now reassign the visible file gadget array to the new node list
- jsr _FSAssignNodes
-
- * Display new file entries and redraw borders
- ;ClipBlit(rp, 9L, 13L, rp, 9L, 24L, 447L, 96L, 0xc0L)
- movea.l a2,a0
- moveq #9,d0
- moveq #13,d1
- movea.l a2,a1
- moveq #9,d2
- moveq #24,d3
- move.l #447,d4
- moveq #96,d5
- move.l #$0c0,d6
- SYS ClipBlit,_GfxBase
-
- ;FSEnableFGad(0);
- pea 0
- jsr _FSEnableFGad ;Display the only new "gadget"
- addq.w #4,sp
-
- addq.w #1,d7 ;Bump scroll count
-
- sdgchk1:
- cmp.w 10(a5),d7 ;Have we scrolled enough?
- blt sdgloop1 ;Nope, do again
-
- sdgdone:
- movem.l (sp)+,d2-d7/a2/a6
- unlk a5
- rts
-
- * -------------------------------------------------------------------
- * VOID FSAssignNodes(VOID)
- * -------------------------------------------------------------------
- XDEF _FSAssignNodes
- _FSAssignNodes:
- movem.l a2-a3,-(sp)
-
- ;for (tnode = topfin, i = 0; ;tnode = tnode->next)
- lea _FSFileNodes,a3 ;Grab base address of array of filegadgets
- movea.l _topfin,a2 ;Grab our top visible filenode
- moveq #10,d0 ;Fill 10 gadgets max
- ran1:
- tst.l fn_Node+MLN_SUCC(a2) ;Succ == 0?
- beq.s ragdone ;Ran out of list entries
-
- ;if (tnode->idnum >= 0)
- tst.w fn_idnum(a2) ;Is this name "visible"?
- blt.s ragchkbot ;Nope, skip it
- move.l a2,(a3)+ ;FSFileNodes[i] = tnode
- subq.w #1,d0 ;One less slot available
- beq.s ragdone ;Filled all the slots, exit loop
-
- ragchkbot:
- movea.l fn_Node+MLN_SUCC(a2),a2
- bra ran1 ;check next node
-
- ragdone:
- movem.l (sp)+,a2-a3
- rts
-
- * -----------------------------------------------------------------------
- ; VOID __stdargs FSDoFileGad(Ypos)
- ; LONG Ypos;
- ;
- ; Based on the mouse's Ypos passed, select file entry that user clicked.
- * -----------------------------------------------------------------------
- XDEF _FSDoFileGad
- _FSDoFileGad:
- link a5,#0
- movem.l d2-d4/a2-a3/a6,-(sp)
-
- moveq #0,d4
- move.w 10(a5),d4 ;Grab gadget y position
- subi.w #12,d4 ;Less 12 (top edge of first entry)
- divu #11,d4 ; divided by 11 (height of each entry)
- ext.l d4 ;Blow remainder, this is our entry number
-
- move.w d4,d0
- lsl.w #2,d0 ;Convert to long offset
- lea _FSFileNodes,a2 ;Grab base address of visible node_datas
- movea.l 0(a2,d0.w),a3 ;Grab FSFileNodes[gadg_num]
- cmpa.l #0,a3
- beq dfgdone ;If zero, not a active "gadget" slot
-
- ;strncpy(FSwstr, tinfo->alphadata + 26L, tinfo->namelength)
- movea.l fn_info(a3),a3 ;tinfo = tnode->info
- lea _FSwstr,a2 ;Grab address of worktext
- move.w nd_namelength(a3),d0 ;Push tinfo->namelength
- lea nd_alphadata+26(a3),a1 ;Push tinfo->alphadata + 26
- movea.l a2,a0 ;Push dest text
- jsr astrncpy ;strncpy(FSwstr, filename, namelength)
-
- ;if (tinfo->filetype == 1)
- cmpi.w #1,nd_filetype(a3) ;Did user click on a filename?
- bne.s dfgnotfile ;Nope, must be a dir
-
- ;if ( strcmp(FSFileInfo.Buffer, FSwstr) )
- movea.l a2,a1 ;Push FSwstr
- movea.l _FSFileInfo,a0 ;Push address of filebuffer
- jsr astrcmp
- tst.w d0 ;Is this the same as what we already have?
- beq.s dfgnsname ;Yep, see if it was double-clicked
-
- ;strcpy(FSFileInfo.Buffer, FSwstr)
- movea.l a2,a1
- movea.l _FSFileInfo,a0
- jsr astrcpy ;Otherwise copy new filename to filebuffer
-
- lea _FSFileGad,a0 ;And refresh filename text gadget
- movea.l _FSWin,a1
- suba.l a2,a2
- moveq #1,d0
- SYS RefreshGList,_IntuitionBase
- bra dfgfiledone
-
- dfgnsname:
- ;if ( DoubleClick(fsoldsecs, fsoldmicros, fscursecs, fscurmicros &&
- ; (gadg_num == fsprevgadid) )
- ; ConcatPathString();
- btst.b #0,_fsflags+1 ;FS_NO_DCLICK_EXIT?
- bne dfgfiledone ;Yep, programmer doesn't allow that
-
- cmp.w _fsprevgadid,d4 ;Is it the same gadget?
- bne dfgfiledone ;Nope, can't be a double click
-
- move.l _fsoldsecs,d0
- move.l _fsoldmicros,d1
- move.l _fscursecs,d2
- move.l _fscurmicros,d3
- SYS DoubleClick,_IntuitionBase
- tst.w d0 ;Is it within click speed parameters?
- beq.s dfgfiledone ;Nope
-
- jsr _ConcatPathString ;Construct full path text
- bra.s dfgdone
-
- ;Clicked on a DIR
- dfgnotfile:
- cmpi.w #1,_fsvirgindir ;if (virgindir != 1)
- beq.s dfgdone ;Don't concat if we haven't locked dir yet
-
- ;i = strlen(FSPathInfo.Buffer);
- move.l _FSPathInfo,a0
- jsr astrlen
- move.w d0,d2 ;Length of stuff already in path text
-
- ;if ( (strlen(FSwstr) + i) < PATHSTRSIZE)
- movea.l a2,a0
- jsr astrlen
- add.w d2,d0
- cmpi.w #PATHSTRSIZE-1,d0
- bge.s dfgtoodeep ;Don't append path if no room!
-
- move.l a2,-(sp)
- move.l _FSPathInfo,-(sp)
- move.l _FSPathInfo,-(sp)
- jsr _ConcatDirFile ;ConcatDirFile(FSPathInfo->Buffer, FSPathInfo->Buffer, FSwstr)
- lea 12(sp),sp
-
- jsr _FSDirFunc ;Do FSReq->dirfunc, if there is one
- tst.w d0 ;Avoid reading this dir?
- beq.s 1$ ;Nope, process it
- move.l _FSPathInfo,a0
- clr.b 0(a0,d2.w) ;Else FSPathInfo->Buffer[oldstrlen] = 0
- bra.s dfgdone
- 1$
- move.w #1,_fsvirgindir ;virgindir = 1, read the new directory
- bra.s dfgdone
-
- dfgtoodeep:
- move.w #12,_fstitstatus ;fstitstatus = 12
- jsr _FSWinTitle
- suba.l a0,a0
- SYS DisplayBeep,_IntuitionBase
- bra.s dfgdone
-
- dfgfiledone:
- jsr _FSFileFunc ;Call FSReq->filefunc, if there is one
-
- dfgdone:
- move.w d4,_fsprevgadid ;fsprevgadid = gadg_num
- movem.l (sp)+,d2-d4/a2-a3/a6
- unlk a5
- rts
-
- * --------------------------------------------------------------------- *
- * LONG FSDirFunc(VOID);
- * If there is a fsrequest->dirfunc, this routine handles the interface.
- * --------------------------------------------------------------------- *
- XDEF _FSDirFunc
- _FSDirFunc:
- move.l d2,-(sp)
-
- moveq #0,d0
- movea.l _FSReq,a0 ;Grab our FSRequest struct
- move.l fs_dirfunc(a0),d2 ;Is there a user dir function to call?
- beq.s 1$ ;Nope, that's all we have to do this click!
-
- jsr _ConcatPathString ;Combine dir/file as fullname for return
- clr.w _FSDone ;Not done though, undo return status
-
- move.l _FSWin,-(sp)
- move.l _FSReq,-(sp)
- movea.l d2,a0
- jsr (a0) ;d0 = (FSReq->dirfunc)(FSReq, FSWin)
- addq.w #8,sp
- 1$
- move.l (sp)+,d2
- rts
-
- * --------------------------------------------------------------------- *
- * VOID FSFileFunc(VOID);
- * If there is a fsrequest->filefunc, this routine handles the interface.
- * --------------------------------------------------------------------- *
- XDEF _FSFileFunc
- _FSFileFunc:
- move.l d2,-(sp)
-
- movea.l _FSReq,a0 ;Grab our FSRequest struct
- move.l fs_filefunc(a0),d2 ;Is there a user file function to call?
- beq.s 1$ ;Nope, that's all we have to do this click!
-
- jsr _ConcatPathString ;Combine dir/file as fullname for return
- clr.w _FSDone ;Not done though, undo return status
-
- move.l _FSWin,-(sp)
- move.l _FSReq,-(sp)
- movea.l d2,a0
- jsr (a0) ;d0 = (FSReq->filefunc)(FSReq, FSWin)
- addq.w #8,sp
- tst.l d0 ;Return 0?
- beq.s 1$ ;Yep
- move.w #1,_fsvirgindir ;Else re-read directory
- 1$
- move.l (sp)+,d2
- rts
-
- * -----------------------------------------------------------------------
- * VOID FSSetFileGads(VOID)
- * Assign and render currently active file texts, disable remainder
- * -----------------------------------------------------------------------
- XDEF _FSSetFileGads
- _FSSetFileGads:
- movem.l d4-d5,-(sp)
-
- move.w _fsnumentries,d5 ;Grab number of entries
- beq.s 3$ ;No entries, nothing to set!
-
- * Update visible list based on topfin point in linked list
- jsr _FSAssignNodes
-
- * Show all used gadgets
- moveq #0,d4 ;i = 0
- bra.s 2$
- 1$
- move.l d4,-(sp)
- jsr _FSEnableFGad
- addq.w #4,sp
- addq.w #1,d4 ;Bump gadget count
- 2$
- cmpi.w #10,d4 ;Hit highest gadget?
- bcc.s 3$ ;Yep, done
- cmp.w d5,d4 ;Else, Hit last gadget?
- bcs 1$ ;Nope enable another
- 3$
- movem.l (sp)+,d4-d5
- rts
-
- * ------------------------------------------------------------------------
- * SetRootDir()
- * Chop off all subdirectory names contained in FSPathInfo, moving up to
- * root name if possible. Flag to read new directory in any case.
- * ------------------------------------------------------------------------
- XDEF _SetRootDir
- _SetRootDir:
- ;if ( (tstr = strchr(FSPathInfo.Buffer, ':')) != 0L)
- moveq #':',d0
- movea.l _FSPathInfo,a0
- jsr aindex
- tst.l d0
- beq.s 1$ ;Nope
-
- clr.b 1(a0) ;Otherwise clobber the char after ':'
- move.w #1,_fsvirgindir ;virgindir = 1, read directory
-
- 1$ rts
-
- * ------------------------------------------------------------------------
- ; SetParentDir()
- ; Chop off last directory name contained in FSPathInfo, moving up one level
- ; if possible.
- * ------------------------------------------------------------------------
- XDEF _SetParentDir
- _SetParentDir:
- movem.l a2-a3,-(sp)
-
- ;if (FSPathInfo.Buffer[0])
- movea.l _FSPathInfo,a3 ;Grab pointer to path text
- tst.b (a3) ;Is it of zero length?
- beq.s spddone ;Yep, at root already
-
- ;tstr = rindex(FSPathInfo.Buffer, '/')
- moveq #'/',d0
- movea.l a3,a0
- jsr arindex
- tst.l d0 ;Grab index to last occurance of slash
- bne.s spdnotsub ;If we got one that is
-
- ; if ( tstr = rindex(FSPathInfo.Buffer, ':') )
- ; tstr++;
- moveq #':',d0
- movea.l a3,a0
- jsr arindex ;Grab index to last occurance of colon
- tst.l d0
- beq.s spdnotroot ;Oops, no colon either, at top of path?
- addq.w #1,a0 ;Move past the ':'
- bra.s spdnotsub ;Terminate the text
- ;else
- spdnotroot:
- movea.l a3,a0 ;tstr = (BYTE *)FSPathInfo.Buffer
-
- spdnotsub:
- clr.b (a0) ;*tstr = '\x0'
- move.w #1,_fsvirgindir ;virgindir = 1, read the new directory
-
- spddone:
- movem.l (sp)+,a2-a3
- rts
-
- * -----------------------------------------------------------------
- ;HCompGad(rp, g2)
- ; struct RastPort *rp;
- ; struct Gadget *g2;
- ;
- ; Given a rastport and a gadget pointer, highlight or de-highlight
- ; a gadget using RectFill in COMPLEMENT mode.
- * -----------------------------------------------------------------
- hrp EQU 16
- hgad EQU 20
- XDEF _HCompGad
- _HCompGad:
- movem.l d2-d3/a6,-(sp)
-
- movea.l hrp(sp),a1
- moveq #2,d0
- SYS SetDrMd,_GfxBase ;SetDrMd(rp, COMPLEMENT)
-
- movea.l hgad(sp),a0 ;Grab gadget pointer
- moveq #0,d0
- move.w 4(a0),d0 ;x0 = (ULONG)g2->LeftEdge
-
- move.l d0,d2
- add.w 8(a0),d2
- subq.w #1,d2 ;x1 = x0 + g2->Width - 1L
-
- moveq #0,d1
- move.w 6(a0),d1 ;y0 = (ULONG)g2->TopEdge
-
- move.l d1,d3
- add.w 10(a0),d3
- subq.w #1,d3 ;y1 = y0 + g2->Height - 1L
-
- movea.l hrp(sp),a1
- SYS RectFill ;RectFill(rp, x0, y0, x1, y1)
-
- movea.l hrp(sp),a1
- moveq #1,d0
- SYS SetDrMd ;SetDrMd(rp, JAM2)
-
- movem.l (sp)+,d2-d3/a6
- rts
-
- * -----------------------------------------------------------------
- ;HCompEntry(num)
- ; LONG num;
- ;
- ; Highlight or de-highlight a slot in the filename area, given its
- ; entry number
- * -----------------------------------------------------------------
- XDEF _HCompEntry
- _HCompEntry:
- movem.l d2-d3/a2/a6,-(sp)
-
- movea.l _FSRPort,a2 ;Grab window
-
- movea.l a2,a1
- moveq #2,d0
- SYS SetDrMd,_GfxBase ;SetDrMd(rp, COMPLEMENT)
-
- moveq #5,d0 ;x0 = (ULONG)g2->LeftEdge
- move.l #460,d2 ;x1 = x0 + g2->Width - 1L
-
- move.w 16+4+2(sp),d1
- mulu #11,d1
- add.w #12,d1 ;y0 = (ULONG)g2->TopEdge
-
- move.l d1,d3
- add.w #9,d3 ;y1 = y0 + g2->Height - 1L
-
- movea.l a2,a1
- SYS RectFill ;RectFill(rp, x0, y0, x1, y1)
-
- movea.l a2,a1
- moveq #1,d0
- SYS SetDrMd ;SetDrMd(rp, JAM2)
-
- movem.l (sp)+,d2-d3/a2/a6
- rts
-
- * --------------------------------------------------------------------- *
- * VOID FSDoSortGadget(type)
- * LONG type;
- * --------------------------------------------------------------------- *
- dosgtype EQU 4+4*3
-
- XDEF _FSDoSortGadget
- _FSDoSortGadget:
- movem.l d2/a2/a6,-(sp)
-
- movea.l _FSReq,a0
- moveq #0,d0
- move.w fs_sorttype(a0),d0
- cmp.w dosgtype+2(sp),d0
- beq dosgsame
-
- * Unhighlight previous setting
- tst.w d0 ;Alphabetize?
- bne.s 1$
- lea _AlphaGad,a0
- bra.s 3$
- 1$
- subq.w #1,d0 ;FileSize?
- bne.s 2$
- lea _SizeGad,a0
- bra.s 3$
- 2$
- subq.w #1,d0 ;Time?
- bne.s 4$ ;Nope, nosort previously
- lea _TimeGad,a0
- 3$
- bclr.b #7,gg_Flags+1(a0) ;gad->Flags &= ~SELECTED
-
- movea.l _FSWin,a1
- suba.l a2,a2
- moveq #1,d0
- SYS RefreshGList,_IntuitionBase ;RefreshGList(gad, FSWin, 0L, 1)
- 4$
- * Set new sort type
- movea.l _FSReq,a0
- move.l dosgtype(sp),d1
- move.w d1,fs_sorttype(a0)
-
- movea.l _fnList,a0
- movea.l MLH_HEAD(a0),a0
- tst.l fn_Node+MLN_SUCC(a0)
- beq.s dosgdone ;No list, don't bother sorting
- tst.l _topfin ;Grab current topfin
- beq.s 5$ ;No currently visible files
- clr.w _fsneedshow ;fsneedshow = 0, needs sorting
- bra.s 6$
- 5$
- move.w #-1,_fsneedshow ;No topfin, fsneedshow = -1
- 6$
- dossort:
- * Sort the list using the new sort type
- move.l d1,-(sp)
- jsr _SortNodes ;SortNodes(type)
- addq.w #4,sp
-
- jsr _FSUpdateSort
-
- jsr _FSWinTitle ;Reset title to previous
- bra.s dosgdone
-
- dosgsame:
- move.w #-1,fs_sorttype(a0)
-
- dosgdone:
- movem.l (sp)+,d2/a2/a6
- rts
-
- * -----------------------------------------------------------------------
- ; SortNodes(key)
- ; LONG key;
- ; Selection sort list of filenames using one of three key types
- * -----------------------------------------------------------------------
- XDEF _SortNodes
- _SortNodes:
- movem.l d4/a2-a3/a6,-(sp)
-
- IFD BENCHMARK
- jsr _StartTime
- ENDC
-
- move.l 4+4*4(sp),d4 ;Grab our key type
- blt snsortdone ;No sort wanted
- cmpi.w #1,_fsnumentries ;More than one entry?
- ble snsortdone ;Nope, don't bother sorting
-
- move.w _fstitstatus,-(sp) ;Save old titstatus
- move.w #28,_fstitstatus
- jsr _FSWinTitle ;FSWinTitle("Sorting...")
- move.w (sp)+,_fstitstatus ;Restore previous titlemsg
-
- * Convert Exec list to a simple head->next->NULL type
- movea.l _fnList,a3 ;Grab old list
- movea.l MLH_TAILPRED(a3),a1 ;a0 = last entry in list
- movea.l MLH_HEAD(a3),a0
- clr.l fn_Node+MLN_SUCC(a1) ;Zap last nodes next field
-
- NEWLIST a3 ;New the old list
-
- move.l d4,d0 ;d0 = sorttype, a0 = headnode
- jsr _FSListSort ;list_sort(headnode, key) (a0/d0)
- movea.l d0,a1 ;Grab new head of sorted list
-
- * Now add the new nodes back into the list
- movea.l 4,a6 ;Execbase calls
-
- 1$ cmpa.l #0,a1 ;Grab next node in new list
- beq.s 2$ ;End of list
- movea.l fn_Node+MLN_SUCC(a1),a2 ;node = node->fn_Node.mln_Succ
-
- movea.l a3,a0
- SYS AddTail ;AddTail(fnList, newnode)
-
- movea.l a2,a1 ;a2 = next node
- bra 1$ ;Add the next node
- 2$
- snsortdone:
- IFD BENCHMARK
- pea _timermsg1
- jsr _StopTime
- addq.w #4,sp
- ENDC
-
- movem.l (sp)+,d4/a2-a3/a6
- rts
-
- * --------------------------------------------------------------------
- * struct file_node *FSListSort (list, type)
- * struct file_node *list;
- * long type;
- *
- * Assumes a list of structures, with a pointer to "next" as the first
- * field. It reorders the list into ascending order, and returns the
- * new first node's address. It is order N log(N).
- *
- * The compare routine should return 0 if the items are in order, and 1
- * if they are not. If the compare routine returns 0 in case of
- * equality, the sort will be stable.
- *
- * This routine depends upon compiler-dependant struct layout, but this
- * assumption is likely to be fairly commonly valid.
- *
- * The basic notion of this sort is to make sorted sublists longer and
- * longer by merging. On the Nth pass through the list, sorted
- * sublists of length 2^(N-1) are produced. Eventually, the entire
- * list is sorted, in log2(N)+1 passes through the list. There is
- * extra bookkeeping overhead, but minimal extra storage space needed.
- * Counts and clever pointer management substitute for extra "glue"
- * nodes.
- *
- * while more than one list
- * while not at end of composite lists
- * for each merge_length(m) block
- * merge first items in lists onto current output list
- * toggle current output list
- *
- * Register parameters:
- * struct file_node *FSListSort __ARGS((struct file_node *, LONG));
- * d0 a0 d0
- * --------------------------------------------------------------------- *
- flsold1 equ -4
- flsold0 equ -8
- flsnew1 equ -12
- flsnew0 equ -16
- flscnt1 equ -20
- flscnt0 equ -24
- flsffn1 equ flscnt0-16
- flsffn0 equ flsffn1-16
- flssend equ flsffn0-4
-
- * --------------------------------------------------------------------- *
- XDEF _FSListSort
- _FSListSort:
- link a5,#flssend
- movem.l d2-d7/a2-a3,-(sp)
-
- move.l d0,d3 ;d3 = sorttype
- clr.l flsffn0+LN_SUCC(a5) ;front[0].next = 0
- move.l a0,flsffn1+LN_SUCC(a5) ;front[0].next = list
-
- moveq #1,d7 ;m = 1
- moveq #0,d6 ;hm = 0
-
- flsLoop1:
- tst.l flsffn1+LN_SUCC(a5) ;while (front[1].next)
- beq flsdone
-
- lea flsffn0(a5),a0
- move.l a0,flsnew0(a5) ;new[0] = &front[0]
- lea flsffn1(a5),a0
- move.l a0,flsnew1(a5) ;new[1] = &front[1]
- move.l flsffn0+LN_SUCC(a5),flsold0(a5) ;old[0] = front[0].next
- move.l flsffn1+LN_SUCC(a5),flsold1(a5) ;old[1] = front[1].next
- clr.l flscnt0(a5) ;count[0] = 0
- clr.l flscnt1(a5) ;count[1] = 0
- moveq #0,d4 ;n = 0
-
- moveq #0,d5 ;items_merged = 0
- flsLoop2:
- tst.l flsold0(a5) ;old[0]?
- bne.s 1$ ;Yep, get an item from this list
- tst.l flsold1(a5) ;old[1]?
- beq flsNext2 ;Nope, both lists exhausted
-
- 1$ cmp.l d7,d5 ;if (items_merged >= m)
- bcs.s 2$ ;Nope, m > items_merged
- moveq #0,d5 ;items_merged = 0
- bchg.l #0,d4 ;n = 1 - n
- clr.l flscnt0(a5) ;count[0] = 0
- clr.l flscnt1(a5) ;count[1] = 0
-
- 2$ tst.l flsold0(a5) ;old[0]?
- beq.s 3$
- tst.l flsold1(a5) ;old[1]?
- beq.s 3$
- cmp.l flscnt0(a5),d6 ;count[0] < hm?
- bls.s 3$ ;Nope, hm >= count[0]
- cmp.l flscnt1(a5),d6 ;count[1] < hm?
- bls.s 3$ ;Nope
-
- movea.l flsold1(a5),a1
- movea.l fn_info(a1),a1
- movea.l flsold0(a5),a0
- movea.l fn_info(a0),a0
- move.l d3,d0
- jsr _CompareNodes ;CompareNodes(type, old[0]->info, old[1]->info)
- lsl.w #2,d0 ;d0 = result of compare (0 or 1)
-
- move.w d4,d1
- lsl.w #2,d1 ;d1 = n<<2
- movea.l flsnew0(a5,d1.w),a1 ;a1 = new[n]
- movea.l flsold0(a5,d0.w),a0 ;a0 = old[o]
- move.l a0,LN_SUCC(a1) ;new[n]->next = old[o]
- move.l LN_SUCC(a0),flsold0(a5,d0.w) ;old[o] = old[o]->next
- addq.l #1,flscnt0(a5,d0.w) ;count[o]++
- bra.s flsNext1
- 3$
- flselse1:
- tst.l flsold0(a5) ;old[0]?
- beq.s 2$ ;Nope, use old[1]
- cmp.l flscnt0(a5),d6 ;count[0] < hm?
- bls.s 2$ ;Nope, count[0] >= hm, use old[1]
- 1$ lea flsold0(a5),a0 ;else a0 = &old[0]
- bra.s 3$
- 2$ lea flsold1(a5),a0 ;a0 = &old[1]
- 3$
- move.w d4,d1
- lsl.w #2,d1
- movea.l flsnew0(a5,d1.w),a1 ;a1 = new[n]
- move.l (a0),LN_SUCC(a1) ;new[n]->next = old[o]
- movea.l (a0),a1
- move.l LN_SUCC(a1),(a0) ;old[o] = old[o]->next
-
- flsNext1:
- move.w d4,d0
- lsl.w #2,d0
- movea.l flsnew0(a5,d0.w),a0 ;a0 = new[n]
- move.l LN_SUCC(a0),flsnew0(a5,d0.w) ;new[n] = new[n]->next
- addq.l #1,d5 ;items_merged++
- bra flsLoop2
-
- flsNext2:
- movea.l flsnew0(a5),a0
- clr.l LN_SUCC(a0) ;new[0]->next = 0
- movea.l flsnew1(a5),a0
- clr.l LN_SUCC(a0) ;new[1]->next = 0
- move.l d7,d6 ;hm = m
- lsl.l #1,d7 ;m *= 2
- bra flsLoop1
-
- flsdone:
- move.l flsffn0+LN_SUCC(a5),d0 ;return(front[0].next)
-
- movem.l (sp)+,d2-d7/a2-a3
- unlk a5
- rts
-
- * -------------------------------------------------------------------------
- ; d0 = WORD CompareNodes(d0, a0, a1)
- ; WORD key = d0;
- ; struct node_data *a = a0, *b = a1;
- ;
- ; Compare data in two nodes, based upon key type. Return boolean result
- ; of the comparison in d0. Note that this is a register based function.
- * -------------------------------------------------------------------------
- XDEF _CompareNodes
- _CompareNodes:
- move.w nd_filetype(a0),d1
- cmp.w nd_filetype(a1),d1 ;Comparing same type of entries?
- beq.s 3$ ;Yep, use sort for compare
-
- btst.b #3,_fsflags+1 ;Want files first?
- bne.s 2$ ;Yep
- btst.b #4,_fsflags+1 ;Want dirs first?
- beq.s 3$ ;Don't care, see if there is a sort
-
- cmp.w nd_filetype(a1),d1 ;Recompare
- bcs.s cnmatch ;a0->filetype = 2, a1->filetype = 1
- bra.s cnnomatch ;a0->filetype = 1, a1->filetype = 2
- 2$
- cmp.w nd_filetype(a1),d1 ;Recompare
- bhi.s cnmatch ;a0->filetype = 2, a1->filetype = 1
- bra.s cnnomatch ;a0->filetype = 1, a1->filetype = 2
- 3$
- tst.w d0
- blt.s cnmatch ;No sort, append to end
- bne.s cnnotalpha ;Not zero, not alphabetize
-
- cnnalpha:
- pea nd_alphadata+26(a1)
- pea nd_alphadata+26(a0)
- jsr _lstrcmp ;return(lstrcmp(a->alphadata + 26L, b->alphadata + 26L) > 0)
- addq.w #8,sp
- tst.w d0
- ble.s cnnomatch
- bra.s cnmatch
-
- cnnotalpha:
- cmpi.w #1,d0 ;Sort by size?
- bne.s cnnotsize ;Nope, must be by date
-
- move.l nd_filesize(a0),d0
- cmp.l nd_filesize(a1),d0 ;return(a->filesize > b->filesize)
- beq cnnalpha ;Same size, sort alpha
- bcs.s cnnomatch ;a1 > a0
- bra.s cnmatch
-
- cnnotsize:
- move.l nd_days(a0),d0
- cmp.l nd_days(a1),d0 ;if (a->days > b->days)
- beq.s cntstmins ;Nope, a->days == b->days, check minutes
- bls.s cnnomatch ;Nope, a->days < b->days
- bra.s cnmatch
-
- cntstmins:
- ;t1 = (a->minutes - b->minutes) * 3000L + (a->ticks - b->ticks)
- move.l nd_minutes(a0),d0
- sub.l nd_minutes(a1),d0
- muls #3000,d0
-
- move.l nd_ticks(a0),d1
- sub.l nd_ticks(a1),d1
- add.l d1,d0
-
- tst.l d0 ;return(t1 > 0L);
- beq cnnalpha ;Same date, sort alpha
- bgt.s cnmatch
-
- cnnomatch:
- moveq #0,d0
- bra.s cndone
-
- cnmatch:
- moveq #1,d0
- cndone:
- rts
-
- * ---------------------------- lstrcmp -------------------------------
- * LONG lstrcmp(astr, bstr)
- * BYTE *astr, *bstr;
- *
- * Compare two texts for lexigraphic order, ignoring case differences
- *---------------------------------------------------------------------
- XDEF _lstrcmp
- _lstrcmp:
- movem.l 4(sp),a0/a1 ;Grab astr, bstr
-
- ;for(;*a && tolower(*a) == tolower(*b); a++, b++)
- lccstart:
- move.b (a0)+,d0 ;Grab a char from astr
- cmpi.b #$40,d0 ;less than @ character?
- bls.s 1$ ;Yep
- cmpi.b #$5a,d0 ;Greater than Z?
- bhi.s 1$ ;Yep
- addi.b #$20,d0
- 1$
- move.b (a1)+,d1 ;Grab a char from bstr
- cmpi.b #$40,d1 ;less than @ character?
- bls.s 2$ ;Yep
- cmpi.b #$5a,d1 ;Greater than Z?
- bhi.s 2$ ;Yep
- addi.b #$20,d1
- 2$
- tst.b d0 ;End of astr?
- beq.s 3$
- cmp.b d1,d0 ;Are they the same character?
- beq lccstart ;Yep, compare next pair of chars
- 3$
- sub.b d1,d0 ;return(tolower(*astr) - tolower(*bstr))
- ext.w d0
- ext.l d0
- rts
-
- *----------------------------------------------------------------------
- * Search a text for wild characters, return 1 if found
- *----------------------------------------------------------------------
- XDEF _iswild
- _iswild:
- movea.l 4(sp),a0 ;Grab text pointer
- moveq #0,d0 ;Clear out our character register
- ischk1:
- move.b (a0)+,d0 ;Grab a char
- beq.s iswdone ;Might be end of text?
- cmpi.b #'*',d0 ;Is it *?
- beq.s iswdone ;yep, is wild
- cmpi.b #'?',d0 ;Is it a qmark
- bne ischk1 ;Nope, check next character
- rts ;Otherwise it is wild
-
- iswdone:
- rts
-
-
- * ------------------------------------------------------------------------
- ; Compare a wild card name with a normal name
- ; WORD wildmatch (name, wild)
- ; BYTE *name, *wild;
- * ------------------------------------------------------------------------
- XDEF _wildmatch
- _wildmatch:
- link a5,#-64
- movem.l d3/a2-a3,-(sp)
-
- movem.l 8(a5),a2-a3 ;Grab name/pattern
- lea -64(a5),a0 ;back[0][0]
- lea -60(a5),a1 ;back[0][1]
-
- moveq #0,d3 ;bi = 0
-
- wmloop1:
- tst.b (a2) ;End of name?
- bne.s wmnoteon
- tst.b (a3) ;End of pattern?
- beq wmmatched ;Yep, we matched
-
- wmnoteon:
- cmpi.b #'*',(a3) ;Is it a splat?
- bne.s wmnotstar ;Nope, maybe '?'
-
- cmpi.w #64,d3 ;Have we hit max expression depth?
- beq wmnomatch ;Yep, ran out of room in recursion table
-
- ;back[bi][0] = w
- move.l a3,0(a0,d3.w) ;Stash pointer to this '*' in table
-
- ;back[bi][1] = n
- move.l a2,0(a1,d3.w)
-
- addq.w #8,d3 ;++bi
- addq.w #1,a3 ;++w
- bra wmloop1 ;Check next
-
- wmgoback:
- subq.w #8,d3 ;--bi
- move.l a0,d0
- wmback1:
- tst.w d3 ;while (bi >= 0 && *back[bi][1] == '\x0')
- blt.s wmbacked
- movea.l 0(a1,d3.l),a0
- tst.b (a0)
- bne.s wmbacked
-
- subq.w #8,d3 ;--bi
- bra wmback1
-
- wmbacked:
- tst.w d3 ;if (bi < 0)
- blt.s wmnomatch ;return (0)
-
- movea.l d0,a0
- movea.l 0(a0,d3.w),a3 ;w = back[bi][0] + 1
- addq.w #1,a3
-
- addq.l #1,0(a1,d3.w)
- movea.l 0(a1,d3.l),a2 ;n = ++back[bi][1]
-
- addq.w #8,d3 ;++bi
- bra wmloop1
-
- wmnotstar:
- cmpi.b #'?',(a3) ;Is it '?'
- bne.s wmnotqmark
-
- tst.b (a2) ;Reached end of text?
- bne.s wmincpoint ;Nope, move on to next char
-
- tst.w d3 ;Are we at top level of expression?
- beq.s wmnomatch ;Yep, expression didn't match
- bra wmgoback ;Otherwise pop a level and try to match
-
- wmnotqmark:
- move.b (a2),d0 ;Grab a char from bstr
- cmpi.b #$40,d0 ;less than @ character?
- bls.s 1$ ;Yep
- cmpi.b #$5a,d0 ;Greater than Z?
- bhi.s 1$ ;Yep
- addi.b #$20,d0
- 1$
- move.b (a3),d1 ;Grab a char from bstr
- cmpi.b #$40,d1 ;less than @ character?
- bls.s 2$ ;Yep
- cmpi.b #$5a,d1 ;Greater than Z?
- bhi.s 2$ ;Yep
- addi.b #$20,d1
- 2$
- cmp.b d0,d1 ;*n = *w?
- beq.s wmincpoint ;Yep, move on past
-
- tst.w d3 ;Are we at top expression level?
- beq.s wmnomatch ;Yep, they didn't match
- bra wmgoback ;Nope, process next part
-
- wmincpoint:
- tst.b (a2) ;Done with name?
- beq.s wmnamend ;Yep
- addq.w #1,a2 ;Otherwise increment name pointer
-
- wmnamend:
- tst.b (a3) ;End of pattern?
- beq.s wmmatched ;Yep, we matched
- addq.w #1,a3 ;Otherwise inc wild pointer, match next char
- bra wmloop1
-
- wmmatched:
- moveq #1,d0
- bra.s wmdone
-
- wmnomatch:
- moveq #0,d0
-
- wmdone:
- movem.l (sp)+,d3/a2-a3
- unlk a5
- rts
-
-
- * --------------------------------------------------------------------- *
- * LONG MakePathString(lock, dest)
- * a0 a1
- * struct FileLock *lock;
- * BYTE *dest;
- *
- * DESCRIPTION:
- * Given text and a filelock, construct entire pathname and
- * return in dest.
- * --------------------------------------------------------------------- *
- XDEF _MakePathString
- _MakePathString:
- link a5,#0
- movem.l d2-d5/d7/a2-a3/a6,-(sp)
-
- * Grab pointer to lock and dest text to fill
- move.l 8(a5),d3 ;d3 = lock
- movea.l 12(a5),a2 ;a2 = dest
- clr.b (a2) ;NULL terminate dest
- moveq #0,d5 ;LockFlag = 0
-
- * Allocate a FileInfoBlock for local use
- moveq #0,d1
- move.l #fib_SIZEOF,d0
- SYS AllocMem,4 ;AllocMem(sizeof(fib), 0L)
- move.l d0,d7 ;d7 = *fib
- beq mpsfailed ;Whoops no mem? return!
-
- movea.l _DOSBase(a4),a6 ;DOSBase calls from here on
-
- * while (lock != 0)
- 1$
- tst.l d3 ;Got a lock?
- beq.s mpsokay ;Nope, must be at root
-
- * Examine the current lock
- move.l d3,d1
- move.l d7,d2
- SYS Examine ;Examine(lock, fib)
- tst.l d0 ;Okay?
- beq.s mpsfailed ;Nope, some sort of dos failure?
-
- movea.l d7,a1
- cmpi.b #' ',fib_FileName(a1) ;if (fib->fib_FileName[0] >= ' ')
- bcs.s 3$ ;Nope, don't bother inserting?
-
- tst.b (a2) ;if (dest[0] != 0)
- beq.s 2$
- lea _SlashStr(a4),a1
- movea.l a2,a0
- jsr _InsertPathString ;InsertPathString(dest, "/");
- 2$
- movea.l d7,a1
- lea fib_FileName(a1),a1
- movea.l a2,a0
- jsr _InsertPathString ;InsertPathString(dest, fib->fib_FileName)
- 3$
- * Okay, move up one directory
- move.l d3,d4 ;oldlock = lock
-
- move.l d3,d1
- SYS ParentDir
- move.l d0,d3 ;lock = ParentDir(lock)
-
- tst.w d5 ;LockFlag set?
- bne.s 4$ ;Yep, unlock
- moveq #1,d5 ;Else LockFlag = 1, unlock next time
- bra 1$ ;Next directory up
- 4$
- move.l d4,d1
- SYS UnLock ;UnLock(oldlock)
- bra 1$ ;Examine
-
- mpsokay:
- * See if root was RAM:, special case
- movea.l d7,a1 ;a1 = fib
- cmpi.b #' ',fib_FileName(a1) ;if (fib->fib_FileName[0] >= ' ')
- bcc.s 1$ ;Yep, not 1.1/1.2 RAM:
- lea _RamDirNameStr(a4),a1 ;Else...
- movea.l a2,a0
- jsr _InsertPathString ;InsertPathString(dest, "RAM:")
- bra.s mpsdone
- 1$
- * Find last slash we tacked on, change to a colon, or, add a colon
- moveq #'/',d0
- movea.l a2,a0
- jsr aindex ;d0 = strchr(dest, '/')
- tst.l d0 ;Do we have a slash?
- beq.s 2$ ;Nope, at root....
- movea.l d0,a0
- move.b #':',(a0) ;Else change first '/' to a ':'
- bra.s mpsdone
-
- * No slash, must be locked at the root. Append a colon to the dest.
- 2$
- lea _ColonStr(a4),a1
- movea.l a2,a0
- jsr astrcat ;strcat (dest, ":")
- bra.s mpsdone
-
- * Come here if an error occured, return empty text to caller
- mpsfailed:
- clr.b (a2) ;dest[0] = (BYTE)0
- moveq #0,d3 ;return (0L)
- bra.s mpsdeall
-
- * Come here if everything is okay, deallocate FileInfoBlock
- mpsdone:
- moveq #1,d3 ;return (1L)
-
- mpsdeall:
- tst.l d7 ;Did we allocate a fib?
- beq.s mpsfinis ;nope
- movea.l d7,a1 ;Else free the memory
- move.l #fib_SIZEOF,d0
- SYS FreeMem ;FreeMem(fib, sizeof(fib))
-
- mpsfinis:
- move.l d3,d0 ;Put return value in d0
- movem.l (sp)+,d2-d5/d7/a2-a3/a6
- unlk a5
- rts
-
- * --------------------------------------------------------------------- *
- * VOID InsertPathString(dest, source)
- * a0 a1
- * BYTE *dest, *source;
- *
- * DESCRIPTION:
- * Insert source text into dest text.
- * Special case for source length == 0, source must be RAM.
- * --------------------------------------------------------------------- *
- XDEF _InsertPathString
- _InsertPathString:
- movem.l d7/a2-a3,-(sp)
-
- movea.l a1,a3 ;a3 = source
- move.l a0,a2 ;a2 = dest
-
- movea.l a3,a0
- jsr astrlen
- move.l d0,d7 ;d7 = strlen(source)
-
- 1$ movea.l a2,a0
- jsr astrlen ;d0 = strlen(dest)
-
- addq.w #1,d0 ;Bump the length to include zero byte at end
- movea.l a2,a1
- adda.w d7,a1 ;Push dest + slen
- movea.l a2,a0 ;Push dest
- jsr amovmem ;amovmem(dest, dest + slen, strlen(dest) + 1)
-
- move.w d7,d0
- movea.l a2,a1
- movea.l a3,a0
- jsr amovmem ;amovmem(source, dest, slen)
-
- movem.l (sp)+,d7/a2-a3
- rts
-
- * --------------------------------------------------------------------- *
- * BYTE *myrindex(text, searchchar)
- * BYTE *text;
- * LONG searchchar;
- *
- * C stack version of arindex.
- * --------------------------------------------------------------------- *
- XDEF _myrindex
- _myrindex:
- movea.l 4(sp),a0
- move.l 8(sp),d0
-
- * --------------------------------------------------------------------- *
- * BYTE *aindex(BYTE *, BYTE);
- * --------------------------------------------------------------------- *
- XDEF aindex
- aindex:
- 1$ cmp.b (a0),d0
- beq.s aifound
- tst.b (a0)+
- beq.s ainomatch
- bra 1$
-
- ainomatch:
- moveq #0,d0
- rts
-
- aifound:
- move.l a0,d0
- rts
-
- * --------------------------------------------------------------------- *
- * BYTE *arindex(BYTE *, BYTE);
- * --------------------------------------------------------------------- *
- XDEF arindex
- arindex:
- move.l a0,d1 ;Copy start of string for compares
-
- 1$ tst.b (a0)+ ;Find end of text
- bne 1$
-
- 2$ cmp.b -(a0),d0 ;Now work backward comparing along the way
- beq.s rifound ;..Until we find a match
- cmpa.l d1,a0 ;...or hit the beginning of the text
- bgt 2$
-
- rinomatch:
- moveq #0,d0
- rts
-
- rifound:
- move.l a0,d0
- rts
-
- * ------------------------------------------------------------------------- *
- * d0 a0
- * LONG astrlen(text)
- * BYTE *text;
- *
- * Synopsis: Calculate length of null-byte terminated text.
- * a0 returns pointing to null char at end of text
- * d0 returns number of bytes in the text
- * ------------------------------------------------------------------------- *
- XDEF astrlen
- astrlen:
- move.l a0,d0 ;Save initial address
- 1$ tst.b (a0)+ ;Test a byte for zero-ness
- bne 1$
-
- suba.l d0,a0 ;Minus initial address
- subq.w #1,a0 ;Less one for overshoot
- exg d0,a0 ;swap em
- rts
-
- * ------------------------------------------------------------------------- *
- * astrcat()
- * Takes text in a0, appends text in a1
- * a0 returns pointing to null at end of final text
- * ------------------------------------------------------------------------- *
- XDEF astrcat
- astrcat:
- * Find end of first text
- 1$ tst.b (a0)+
- bne 1$
- subq.w #1,a0 ;Back up to null char
-
- * Append second text
- 2$ move.b (a1)+,(a0)+
- bne 2$
- subq.w #1,a0 ;a0 = the null at end of final text
- rts
-
- * ------------------------------------------------------------------------- *
- * astrcpy()
- * Takes text in a0, copies text in a1
- * a0 returns pointing to null at end of final text
- * ------------------------------------------------------------------------- *
- XDEF astrcpy
- astrcpy:
- * Copy second text
- 1$ move.b (a1)+,(a0)+
- bne 1$
- subq.w #1,a0 ;Back up to null
- rts
-
- * ------------------------------------------------------------------------- *
- * astrcmp()
- * Takes text in a0, compares to text in a1
- * a0 returns pointing to first difference, d0 contains the difference
- * or zero if the two texts are identical
- * ------------------------------------------------------------------------- *
- XDEF astrcmp
- astrcmp:
- 1$ move.b (a0)+,d0 ;Grab a char from A
- move.b (a1)+,d1 ;Grab a char from B
- tst.b d0 ;Hit end of A?
- beq.s 2$ ;Yep, diff em
- cmp.b d1,d0 ;Else the same char?
- beq 1$ ;Compare next pair
- 2$ sub.b d1,d0 ;A - B
- ext.w d0
- ext.l d0
- rts
-
- * -----------------------------------------------------------------------
- * safestrcpy(dest, source, length)
- * Copies at most length chars of source to dest, if source < length
- * don't pad with nulls like strncpy. Always null terminates dest.
- * -----------------------------------------------------------------------
- XDEF _safestrcpy
- _safestrcpy:
- movem.l 4(sp),a0/a1 ;Grab dest and source pointers
- move.w 14(sp),d0 ;Grab count
-
- * ------------------------------------------------------------------------- *
- * astrncpy()
- * Takes text in a1, copies d0 bytes to text in a0.
- * a0 returns pointing to null at end of final text.
- * Dest text is always null terminated.
- * ------------------------------------------------------------------------- *
- XDEF astrncpy
- astrncpy:
- 1$ move.b (a1)+,(a0)+
- 2$ dbeq d0,1$
- subq.w #1,a0
- clr.b (a0) ;Null terminate dest
- move.l a0,d0
- rts
-
- * ------------------------------------------------------------------------- *
- * amovmem()
- * Takes text in a0, copies d0 bytes to text in a1. Correctly handles
- * overlapping memory.
- * ------------------------------------------------------------------------- *
- XDEF amovmem
- amovmem:
- cmpa.l a0,a1 ;Low to high or high to low?
- bcs.s 2$ ;High to low, copy forward
- adda.w d0,a0 ;Else start at end, copy backward
- adda.w d0,a1
-
- 1$ move.b -(a0),-(a1)
- subq.w #1,d0
- bgt 1$
- bra.s amdone
-
- 2$ move.b (a0)+,(a1)+
- subq.w #1,d0
- bgt 2$
- amdone:
- rts
-
- * --------------------------------------------------------------------- *
- * END OF SOURCE
- * --------------------------------------------------------------------- *
- END
-