home *** CD-ROM | disk | FTP | other *** search
- ;void fill_tree_array(tree_array,work_area,max_entry,drive_num);
- ; char *tree_array,*work_area;
- ; unsigned short max_entry,drive_num;
-
- EXTRN _memory_model:byte
- EXTRN _error_code:byte
- EXTRN _tree_array_size:word
-
- _TEXT SEGMENT BYTE PUBLIC 'CODE'
- ASSUME CS:_TEXT
- PUBLIC _fill_tree_array
- _fill_tree_array proc near
- push bp
- mov bp,sp
- push di
- push si
- cmp _memory_model,0 ;near or far?
- jle begin ;jump if near
- inc bp ;else add 2 to BP
- inc bp ;
- begin: push ds
- jmp G1
- current_element dw 1 ;values are initialized below so that can call
- current_search_dir dw 0 ; the routine more than once
- parent_element dw 0
- parent_offset dw 0
- prior_element dw 0
- errorcode db 0
- treearray dd 0
- workarea dd 0
- copy_name PROC
- les di,cs:dword ptr treearray ;point ES:DI to start of TreeArray
- mov ax,cs:current_element ;get current (free) element
- mov bx,cs:parent_offset ;see if parent subdirectory is root dir
- or bx,bx ;will be 0 if so
- jz B1 ;won't set child field in its parent record
- test es:[bx+15],0ffffh ;will set child field only for first subdir
- jnz A1 ;if child field not still zero, already set
- mov es:[bx+15],ax ;set child pointer
- A1: mov cs:parent_offset,0 ;zero value flags that parent dir is root
- B1: dec ax ;count from zero to set offset
- mov bl,21 ;bytes per record
- mul bl ;calculate offset to current element
- add di,ax ;adjust offset pointer
- lds si,cs:dword ptr workarea ;point DS:SI to subdir name field
- add si,30 ;name offset
- push di ;save TreeArray ptr
- C1: mov al,[si] ;get character
- mov es:[di],al ;copy the character
- inc di ;inc TreeArray pointer
- inc si ;forward WorkArea pointer
- or al,al ;final zero?
- jnz C1 ;loop
- pop di ;pt back to start of TreeArray element
- D1: add di,13 ;forward to Parent field
- mov ax,cs:parent_element ;get ptr to parent
- mov es:[di],ax ;place in linked list
- add di,4 ;forward pointer to Prior field
- mov ax,cs:prior_element ;get number of prior element (0=none)
- or ax,ax ;test
- jz E1 ;jump ahead if first record for the subdir
- mov es:[di],ax ;set Prior field
- mov ax,cs:current_element ;
- mov es:[di-19],ax ;set Next field of prior record
- E1: mov ax,cs:current_element ;
- mov cs:prior_element,ax ;set prior_element for next time through
- ret
- copy_name endp
-
- add_drive_descriptor PROC
- mov ax,[bp+10] ;get drive specifier
- or ax,ax ;0 = default
- jz F1 ;don't write drive specifier if default
- dec si ;pull back pointer
- mov byte ptr [si],':' ;write colon
- add ax,64 ;drive number + 64 = ascii char
- dec si ;pull back pointer
- mov [si],al ;write drive character
- F1: ret
- add_drive_descriptor endp
-
- G1: sub ax,ax ;initialize variables
- mov cs:current_search_dir,ax
- mov cs:prior_element,ax ;
- mov cs:parent_element,ax ;
- mov cs:parent_offset,ax ;
- mov cs:errorcode,al ;
- inc ax ;
- mov cs:current_element,ax ;
- cmp _memory_model,2 ;data near or far?
- jb G2 ;jump if near
- les di,dword ptr[bp+4] ;store TreeArray address
- add di,21 ;start from array element 1
- mov word ptr cs:treearray,di
- mov word ptr cs:treearray+2,es
- les di,dword ptr[bp+8] ;store WorkArea address
- mov word ptr cs:workarea,di
- mov word ptr cs:workarea+2,es
- add bp,4 ;add 4 to BP since 2 dword pointers
- jmp short G3 ;
- G2: mov ax,ds ;ES = DS
- mov es,ax ;
- mov word ptr cs:treearray+2,ax
- mov word ptr cs:workarea+2,ax
- mov ax,[bp+4] ;get TreeArray offset
- add ax,21 ;start from array element 1
- mov word ptr cs:treearray,ax
- mov ax,[bp+6] ;get WorkArea offset
- mov word ptr cs:workarea,ax
- G3: mov ah,2fh ;get current DTA address
- int 21h ;DTA in ES:BX
- lds dx,cs:dword ptr workarea ;get WorkArea pointer
- push bx ;save offset of old DTA
- push es ;save segment of old DTA
- mov ah,1ah ;function to set DTA
- int 21h ;set DTA to WorkArea
- lds si,cs:dword ptr workarea ;now DS:SI pts to WorkArea
- les di,cs:dword ptr treearray ;ES:DI pts to TreeArray
- add di,13 ;offset to first linked list pointer
- mov cx,[bp+8] ;get max elements
- or cx,cx ;test for zero
- jnz H1 ;jump ahead if nonzero
- mov cs:errorcode,2 ;else set error code
- jmp S1 ;quit routine
- H1: sub dx,dx ;will zero out all linked list pointers
- I1: mov es:[di],dx ;zero parent
- mov es:[di+2],dx ;zero child
- mov es:[di+4],dx ;zero prior
- mov es:[di+6],dx ;zero next
- add di,21 ;forward to next element
- ;ASSEMBLE INITIAL ASCIIZ STRING:
- loop I1 ;do whole array
- add si,169 ;string is at high end of work area
- mov ax,002Ah ;asterisk plus null (will write *.*0)
- mov [si],ax ;write it
- mov ax,2E2Ah ;asterisk plus period
- dec si ;pull back pointer
- dec si ;
- mov [si],ax ;write it
- mov al,'\' ;initial search is root directory
- dec si ;pull back ASCIIZ ptr
- mov [si],al ;ready to search root dir
- call add_drive_descriptor ;(to start of ASCIIZ string)
- mov dx,si ;DS:DX must point to ASCIIZ string
- ;SEARCH A SUBDIRECTORY:
- J1: mov word ptr cs:prior_element,0 ;clear Prior element counter
- mov ah,4eh ;function to find FIRST
- K1: mov cx,16 ;file attribute for subdirectory
- int 21h ;get first subdir listed
- jc N1 ;jump if none
- lds si,cs:dword ptr workarea;pt to start of DOS work area
- cmp byte ptr[si+21],16 ;is it a subdirectory?
- jne M1 ;jump ahead if not
- cmp byte ptr[si+30],'.';is it a subdir reference entry?
- je M1 ;skip it if so
- mov ax,[bp+8] ;get MaxElements
- cmp cs:current_element,ax ;filled up?
- jna L1 ;jump if not
- mov cs:errorcode,2 ;else set internal error code
- jmp S1 ;go quit
- L1: call copy_name ;copy subdir name to TreeArray
- inc cs:current_element ;inc ptr to next free element
- M1: mov ah,4fh ;function to find NEXT subdir
- jmp short K1 ;go seek next subdir
- N1: mov ax,cs:current_search_dir
- inc ax ;...to current element. When 1 less...
- cmp cs:current_element,ax ;...the scan is finished
- je S1 ;finished
- mov cs:parent_offset,0 ;keeps offset of parent of current element
- ;ASSEMBLE ASCIIZ STRING FOR NEXT SUBDIR:
- lds si,cs:dword ptr workarea ;point to work area
- add si,165 ;offset to byte before \*.*0
- inc cs:current_search_dir
- les di,cs:dword ptr treearray ;ES:DI to TreeArray
- mov ax,cs:current_search_dir ;get subdir element number
- mov cs:parent_element,ax ;use as value for Parent field
- jmp P1 ;jump over entry point for loop
- O1: dec si ;pull back DOS path pointer
- P1: les di,cs:dword ptr treearray ;ES:DI to TreeArray
- dec ax ;count from 0 to figure offset
- mov dl,21 ;bytes per record
- mul dl ;calculate offset
- add di,ax ;add to pointer
- test cs:parent_offset,0ffffh ;see if parent_offset is zero
- jnz Q1 ;if so, parent dir is root dir
- mov cs:parent_offset,di ;save for marking Parent field
- Q1: sub cx,cx ;counts string length
- Q2: cmp byte ptr es:[di],0 ;need to know string length
- je Q3 ;end of string?
- inc di ;forward ptr
- inc cx ;inc string length counter
- jmp short Q2 ;loop till end
- Q3: dec di ;point DI back to last char
- R1: mov al,es:[di] ;get char from the string
- mov [si],al ;move it
- dec di ;moving in reverse
- dec si ;
- loop R1 ;go do next char
- mov byte ptr[si],'\' ;add initial slash
- add di,14 ;point to Parent field
- mov ax,es:[di] ;get Parent element number
- or ax,ax ;test for no Parent
- jnz O1 ;loop till whole path assembled
- call add_drive_descriptor ;(to start of ASCIIZ string)
- mov dx,si ;DS:DX must point to ASCIIZ string
- jmp J1 ;go search next subdir
- S1: pop ds ;get old DTA
- pop dx ;
- mov ah,1ah ;function to set DTA
- int 21h ;restore former DTA
- pop ds ;restore changed registers
- mov ax,cs:current_element
- dec ax ;
- mov _tree_array_size,ax ;set return value for _tree_array_size
- mov bl,1 ;1 = no tree elements
- or ax,ax ;test for zero elements
- jz T1 ;jump if nonzero
- mov bl,cs:errorcode ;get internal errorcode variable
- T1: mov _error_code,bl ;set Turbo's global _error_code
- pop si
- pop di
- pop bp
- cmp _memory_model,0 ;quit
- jle quit ;
- db 0CBh ;RET far
- quit: ret ;RET near
- _fill_tree_array endp
- _TEXT ENDS
- END