;***************************************************************************;
;                                                                           ;
;                                  FILMAP                                   ;
;                             Directory Command                             ;
;                                                                           ;
;***************************************************************************;
;Copyright (C) 1986 by UltraSoft.  All Rights Reserved.
;
;Written by: David Pallmann
;
;What it does:
;
;       FILMAP is (yet another) directory command.  You can use ^R and ^T to
;       scan back and forth through the directory.  This utility was written
;       for the AMUS M68-SIG as an example of how to use our wildcard scanner,
;       WLDSCN.
;
;How to assemble FILMAP:
;
;       1. Make sure you have (1) FILMAP.M68 (2) WLDSCN.M68 (3) WLDSYM.M68
;       2. Assemble WLDSCN.M68 to create WLDSCN.OBJ (uses WLDSYM.M68)
;       3. Assemble FILMAP with the command .M68 FILMAP
;       4. Link FILMAP with the command .LNKLIT FILMAP,WLDSCN
;
;How to use it:
;
;       It's just like DIR - enter a filespec, or even a blank line.  Examples:
;               .FILMAP         .FILMAP ALL:*.BAS[]     .FILMAP *.CMD
;
;Edit History:
;1.0    17-Jul-86 created. /DFP
;1.0A   19-Jul-86 force octal mode. /DFP
;1.1    02-Aug-86 remove dependence on UltraSoft universals. /DFP

       VMAJOR=1
       VMINOR=1

       SEARCH  SYS
       SEARCH  SYSSYM
       SEARCH  TRM

;dedicated registers

       MEM=A5                          ; impure index
       WILD=A4                         ; wildscan DDB index
       BASE=A3                         ; base of file specs in memory
       INDEX=A1                        ; current filespec pointer
       COUNT=D5                        ; number of files in memory
       CURR=D4                         ; current file number

;impure area used by FILMAP

       .OFINI
       .OFDEF  BUFFER,30.
       .OFDEF  LSTDEV,2                ; last device displayed
       .OFDEF  LSTDRV,2                ; last drive displayed
       .OFDEF  LSTPPN,2                ; last PPN displayed
       .OFSIZ  MEMSIZ

;the following structure is used to remember the directory information in
;memory

       .OFINI
       .OFDEF  F.DEV,2                 ; device code
       .OFDEF  F.DRV,2                 ; drive number
       .OFDEF  F.PPN,2                 ; PPN
       .OFDEF  F.FIL,4                 ; filename
       .OFDEF  F.EXT,2                 ; extension
       .OFDEF  F.BLK,2                 ; size in blocks
       .OFSIZ  F.SIZ

;macro definitions
;
;       CURSOR {row},{col} is the same as PRINT TAB(row,col); in BASIC
;       TCALL {code} is the same as PRINT TAB(-1,code) in BASIC
;       CLS clears the screen (-1,0);
;       CLREOL clears to end of line (-1,9);
;       LOW sets low intensity (-1,11);
;       HIGH sets high intensity (-1,12);
;       GRAFIX turns on graphics mode (-1,23);
;       TEXT turn off graphics mode (-1,24);
;       REVERS turns on reverse video (-1,32);
;       NORMAL turns off reverse video (-1,33);
;       HLINE outputs a horizontal graphics line (-1,46);

DEFINE  CURSOR  ROW,COL
       MOVB    ROW,D1
       ROLW    D1,#8.
       MOVB    COL,D1
       TCRT
       ENDM

DEFINE  TCALL   CODE
       MOVW    #-1_8.+CODE,D1
       TCRT
       ENDM

DEFINE CLS=TCALL 0
DEFINE CLREOL=TCALL 9.
DEFINE LOW=TCALL 11.
DEFINE HIGH=TCALL 12.
DEFINE GRAFIX=TCALL 23.
DEFINE TEXT=TCALL 24.
DEFINE REVERS=TCALL 32.
DEFINE NORMAL=TCALL 33.
DEFINE HLINE=TCALL 46.

;These macros are used to call WLDSCN, the wildcard directory scanner
;These are defined in WLDSCN.UNV as well

DEFINE  WINIT
       IF      NDF,W.INIT,EXTERN W.INIT
       CALL    W.INIT
       ENDM

DEFINE  WSPEC   EXT
       IF      NDF,W.SPEC,EXTERN W.SPEC
       CALL    W.SPEC
       IF      B,EXT,ASCII /???/
       IF      NB,EXT,ASCII /'EXT/
       BYTE    0
       ENDM

DEFINE  WSCAN
       IF      NDF,W.SCAN,EXTERN W.SCAN
       CALL    W.SCAN
       ENDM

;start of code

START:  PHDR    -1,PV$RPD!PV$RSM,PH$REE!PH$REU  ; program header

INIT:   GETIMP  MEMSIZ,MEM              ; allocate local memory
       WINIT                           ; initialize WLDSCN (sets up A4)
       USRFRE  BASE                    ; point to free memory to file table
       MOV     BASE,INDEX              ; set index to table base
       CLR     COUNT                   ; clear file count

SETOCT: JOBIDX  A6                      ; index user's JCB              [1.0A]
       ANDW    #^C<J.HEX>,JOBTYP(A6)   ; force OCTAL radix             [1.0A]

CMDLIN: BYP                             ; bypass leading cmd line spaces
       WSPEC                           ; process wildcard file specification
       JNE     EXIT                    ; branch on invalid spec
       USREND  A2                      ; index end of free memory
       SUB     #10,A2                  ; subtract 8 bytes for good measure

LOAD:   CTRLC   EXIT                    ; branch on ^C
       WSCAN                           ; get next file that matches spec
       JNE     CKZERO                  ;  no more - branch
       MOVW    D.DEV(WILD),F.DEV(INDEX); copy spec
       MOVW    D.DRV(WILD),F.DRV(INDEX);  from wildscan
       MOVW    D.PPN(WILD),F.PPN(INDEX);   DDB @A4 to
       MOV     D.FIL(WILD),F.FIL(INDEX);    our internal
       MOVW    D.EXT(WILD),F.EXT(INDEX);     table
       INC     COUNT                   ; add one to file count
       JOBIDX  A0                      ; index user's JCB again
       TSTW    F.DEV(INDEX)            ; defaulted device code?
       BNE     10$                     ;  no
       MOVW    JOBDEV(A0),F.DEV(INDEX) ;  yes - use log device code
10$:    TSTW    F.DRV(INDEX)            ; defaulted drive number?
       BPL     20$                     ;  no
       MOVW    JOBDRV(A0),F.DRV(INDEX) ; yes - use log device code
20$:    TSTW    F.PPN(INDEX)            ; defaulted PPN?
       BNE     30$                     ;  no
       MOVW    JOBUSR(A0),F.PPN(INDEX) ;  yes - use log account number
30$:    ADD     #F.SIZ,INDEX            ; point index to next table entry
       CMP     INDEX,A2                ; are we out of memory?
       JLT     LOAD                    ;  no
       TYPECR  %Couldn't fit entire directory in memory ; yes - say so

CKZERO: TST     COUNT                   ; any files selected?
       BNE     SETTRM                  ;  yeah
       TYPECR  %No such files          ;  nope
       EXIT                            ; exit

SETTRM: JOBIDX  A6                      ; index JCB
       MOV     JOBTRM(A6),A6           ; get TCB address
       ORW     #T$IMI!T$ECS,T.STS(A6)  ; force image mode, disable echo

;home display to beginning of directory(ies) in memory

HOME:   MOV     BASE,INDEX              ; set index to table base
       CLR     CURR                    ; clear current file index

;display current page

DISPLY: CLRW    LSTDEV(MEM)             ; forget about
       CLRW    LSTDRV(MEM)             ;  previously displayed
       CLRW    LSTPPN(MEM)             ;   data
       CLS                             ; clear screen
       HIGH                            ; high intensity
       MOV     INDEX,A0                ; copy table index
       MOV     CURR,D0                 ; copy file index
       MOV     #1,D2                   ; set row
10$:    MOV     #1,D3                   ; set column
20$:    JOBIDX  A6                      ; index JCB
       MOV     JOBTRM(A6),A6           ; get TCB address
       TST     T.ICC(A6)               ; any characters entered?
       JNE     GETCHR                  ;  yes - abort screen display
       CMP     D2,#24.                 ; at row 24?
       BGE     30$                     ;  yes - done w/display
       CTRLC   EXIT                    ; branch on ^C
       CURSOR  D2,D3                   ; address cursor
       CALL    DISFIL                  ; display file
       CMP     D2,#23.                 ; at end of screen?
       JGT     30$                     ;  yes
       INC     D0                      ; inc temp file count
       CMP     D0,COUNT                ; past end of table?
       BGE     30$                     ;  yes
       ADD     #F.SIZ,A0               ; advance to next entry
       ADD     #13.,D3                 ; advance column
       CMP     D3,#68.                 ; past end of line?
       BLT     20$                     ;  no
       INC     D2                      ; advance row
       BR      10$                     ; branch
30$:    TST     CURR                    ; are we at start of table?
       BNE     SELECT                  ;  yes - branch
       CMP     D0,COUNT                ; are we at end of table?
       JGE     FINISH                  ;  yes - branch

SELECT: CURSOR  #24.,#1
       HIGH
       TYPE    B
       LOW
       TYPE    <ack, >
       HIGH
       TYPE    F
       LOW
       TYPE    <orward, >
       HIGH
       TYPE    Q
       LOW
       TYPE    <uit: >

GETCHR: KBD     FINISH
       UCS
       LEA     A0,CMDTBL
       MOV     #-2,D0
10$:    TSTB    @A0
       JEQ     DISPLY
       ADD     #2,D0
       CMMB    (A0)+,D1
       BNE     10$
       MOVW    JMPTBL[~D0],D0
       JMP     JMPTBL[~D0]

JMPTBL: WORD    BACK-JMPTBL
       WORD    END-JMPTBL
       WORD    FORWRD-JMPTBL
       WORD    TOHOME-JMPTBL
       WORD    FINISH-JMPTBL
       WORD    BACK-JMPTBL
       WORD    END-JMPTBL
       WORD    FORWRD-JMPTBL
       WORD    TOHOME-JMPTBL
       WORD    FINISH-JMPTBL

CMDTBL: BYTE    'B
       BYTE    'E
       BYTE    'F
       BYTE    'H
       BYTE    'Q
       BYTE    'R-'@
       BYTE    'E-'@
       BYTE    'T-'@
       BYTE    '^-'@
       BYTE    '[-'@
       BYTE    0
       EVEN

FINISH: CURSOR  #24.,#1
       CLREOL

EXIT:   HIGH
       EXIT

TOHOME: JMP     HOME

END:    MOV     BASE,INDEX
       MOV     COUNT,D0
       MUL     D0,#F.SIZ
       ADD     D0,INDEX
       SUB     #20.*5*F.SIZ,INDEX
       MOV     COUNT,CURR
       SUB     #20.*5,CURR
       CMP     CURR,#1
       JGE     DISPLY
       JMP     HOME

BACK:   SUB     #20.*5,CURR
       SUB     #20.*5*F.SIZ,INDEX
       CMP     CURR,#1
       JGE     DISPLY
       JMP     HOME

FORWRD: MOV     INDEX,A6
       MOV     CURR,D6
       ADD     #20.*5*F.SIZ,A6
       ADD     #20.*5,D6
       CMP     D6,COUNT
       JGE     SELECT
       MOV     A6,INDEX
       MOV     D6,CURR
       JMP     DISPLY

DISFIL: PUSH    A1
       CMMW    F.DEV(A0),LSTDEV(MEM)
       BNE     10$
       CMMW    F.DRV(A0),LSTDRV(MEM)
       BNE     10$
       CMMW    F.PPN(A0),LSTPPN(MEM)
       BEQ     20$
10$:    CALL    POS
       CMP     D2,#23.
       JGT     30$
       MOVW    F.DEV(A0),LSTDEV(MEM)
       MOVW    F.DRV(A0),LSTDRV(MEM)
       MOVW    F.PPN(A0),LSTPPN(MEM)
20$:    LEA     A2,BUFFER(MEM)
       LEA     A1,F.FIL(A0)
       UNPACK
       UNPACK
       MOVB    #'.,(A2)+
       UNPACK
       CLRB    @A2
       TTYL    BUFFER(MEM)
30$:    POP     A1
       RTN

POS:    SAVE    D0
       CMPB    D3,#1
       BEQ     10$
       INC     D2
       MOV     #1,D3
10$:    INC     D2
       CMP     D2,#23.
       JGT     POSRTN
       CURSOR  D2,D3
       GRAFIX
       MOV     #31.,D0
20$:    HLINE
       SOB     D0,20$
       TEXT
       TYPE    <  >
       CALL    DISPPN
       TYPE    < >
       NORMAL
       MOV     #31.,D0
       GRAFIX
30$:    HLINE
       SOB     D0,30$
       TEXT
       CURSOR  D2,#32.
       REVERS
       INC     D2
       MOV     #1,D3
       CURSOR  D2,D3
POSRTN: REST    D0
       RTN

DISPPN: LEA     A2,BUFFER(MEM)
       LEA     A1,F.DEV(A0)
       UNPACK
       CLR     D1
       MOVW    F.DRV(A0),D1
       DCVT    0,OT$MEM
       MOVB    #':,(A2)+
       MOVB    #'[,(A2)+
       CLR     D1
       MOVB    F.PPN+1(A0),D1
       OCVT    0,OT$MEM
       MOVB    #<',>,(A2)+
       MOVB    F.PPN(A0),D1
       OCVT    0,OT$MEM
       MOVB    #'],(A2)+
       CLRB    @A2
       TTYL    BUFFER(MEM)
       RTN

TRIM:   CMMB    -(A2),#40
       BEQ     TRIM
       INC     A2
       RTN

       END