home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Multimedia & CD-ROM 3
/
mmcd03-jun1995-cd.iso
/
utils
/
various
/
utils-1
/
findtext.asm
< prev
next >
Wrap
Assembly Source File
|
1991-06-24
|
69KB
|
1,432 lines
;****************************************************************************
; FINDTEXT searches the files in a directory (and optionally its descendant
; directories) for a specified text string. Its syntax is:
;
; FINDTEXT [d:][path][filename] "text" [/S] [/C] [/I] [/A] [/M] [/7]
;
; where
;
; filename Specifies the file or files to search
; "text" Specifies the text to search for
; /S Search descendant directories
; /C Make the search case-sensitive
; /I Run in full-screen interactive mode
; /A Search hidden and system files as well as normal files
; /M Use monochrome video attributes on color adapters
; /7 Do 7-bit comparisons (ignore 8th bit)
;
; If no path name is specified, the search begins in the current directory.
; Similarly, if no file name is specified, all files are searched. If the
; /I switch is not specified, FINDTEXT lists the names of all the files that
; contain the specified text. /I causes FINDTEXT to run in interactive mode,
; displaying the contents of the files as well as their names. The /7 switch
; is useful for searching word processing files that use the high bit of each
; character for non-text purposes. By default, FINDTEXT only searches files
; whose hidden and system attribute bits aren't set. /A has it search those
; files, too. Finally, /M has FINDTEXT use monochrome attributes in inter-
; active mode, useful for laptops that pair color adapters with black-and-
; white LCD or gas plasma screens.
;****************************************************************************
code segment
assume cs:code,ds:code
org 100h
begin: jmp main
helpmsg db "Searches for files that contain a specified "
db "text string.",13,10,13,10
db "FINDTEXT [d:][path][filename] ",22h,"text",22h
db " [/S] [/C] [/I] [/A] [/M] [/7]",13,10,13,10
db " filename Specifies the file or files to "
db "search.",13,10
db " text Specifies the text to search for."
db 13,10
db " /S Search descendant directories."
db 13,10
db " /C Make the search case-sensitive."
db 13,10
db " /I Run in full-screen interactive mode."
db 13,10
db " /A Search hidden and system files also."
db 13,10
db " /M Use monochrome video attributes "
db "(interactive mode only).",13,10
db " /7 Do 7-bit comparisons (ignore 8th bit)."
crlf db 13,10,"$"
errmsg1 db "Syntax: FINDTEXT [d:][path][filename] ",22h,"text"
db 22h," [/S] [/C] [/I] [/A] [/M] [/7]",13,10,"$"
errmsg2 db "Invalid drive specification",13,10,"$"
errmsg3 db "Invalid path specification",13,10,"$"
errmsg4 db "Error opening $"
errmsg5 db "Error reading $"
errmsg6 db "Not enough memory",13,10,"$"
msg1 db " file(s) searched in $"
msg2a db " directory; $"
msg2b db " directories; $"
msg3 db " file(s) found containing ",22h,"$"
msg4 db 22h,13,10,"$"
defspec db "*.*",0 ;Default file spec
filespec dw offset defspec ;Address of file spec
srchtext dw 0 ;Address of search text
textsize dw ? ;Length of search text
endspec dw ? ;Address of end of file spec
rootdir db "\",0 ;Command to go to root
updir db "..",0 ;Command to go up one level
descflag db 0 ;1=Search descendants
caseflag db 0 ;1=Case sensitive
scrnflag db 0 ;1=Full-screen mode
bitflag db 0 ;1=7-bit comparisons
fileattr dw 1 ;File attributes
drive db ? ;Default drive
directory db "\",64 dup (?) ;Current directory
pathstring db "x:\",64 dup (?) ;Current drive and directory
bytesbefore dw ? ;Offset to search text
filessearched dw 0 ;Files searched
dirssearched dw 0 ;Directories searched
filesfound dw 0 ;Files found
foundflag db ? ;1=Match found in this file
bytesread dw ? ;Bytes read from file
breakflag db ? ;Ctrl-Break flag
handle dw ? ;File handle
rows db 24 ;Rows displayed (minus 1)
cursor dw ? ;Cursor mode
pageno db ? ;Active display page
videoseg dw 0B800h ;Video segment address
videobuf dw ? ;Video buffer offset
window_color1 db 1Fh ;Primary window color
window_color2 db 1Ah ;Secondary window color
hilite_color db 4Fh ;Highlighted text color
text_color db 07h ;Normal text color
scrn_color db ? ;Screen color on entry
scrntxt1 db "FINDTEXT",0
scrntxt2 db "Directories searched:",12 dup (20h)
db "Files searched:",12 dup (20h)
db "Files found:",0
scrntxt3 db 6 dup (20h),"Press xxxxx to continue, "
db "xxx to stop, or xxxxx to go to next file"
db 7 dup (20h),0
scrntxt4 db "Searching for:",0
scrntxt5 db "Location:",0
scrntxt6 db "File:",0
scrntxt7 db 22h,0
scrntxt8 db "No more files",0
scrntxt9 db "Enter",0
scrntxt10 db "Esc",0
scrntxt11 db "Space",0
row1 db ? ;Starting row for DRAWBOX
col1 db ? ;Starting column for DRAWBOX
row2 db ? ;Ending row for DRAWBOX
col2 db ? ;Ending column for DRAWBOX
boxwidth db ?,0 ;Box width for DRAWBOX
boxheight db ?,0 ;Box height for DRAWBOX
;****************************************************************************
; Procedure MAIN
;****************************************************************************
main proc near
cld ;Clear direction flag
mov si,81h ;Point SI to command line
call scanhelp ;Scan for "/?" switch
jnc checkmem ;Branch if not found
mov ah,09h ;Display help text and exit
mov dx,offset helpmsg ; with ERRORLEVEL=0
int 21h
mov ax,4C00h
int 21h
checkmem: mov dx,offset errmsg6 ;Make sure there's enough
cmp sp,0F000h ; memory to run the
ja parse ; program
error: mov ah,09h ;Display error message and
int 21h ; exit with ERRORLEVEL=1
mov ax,4C01h
int 21h
error1: mov dx,offset errmsg1
jmp error
;
; Parse the command line.
;
parse: call findchar ;Find next parameter
jnc parse2 ;Continue if found
jmp check ;Branch if not
parse2: lodsb ;Get next character
cmp al,"/" ;Branch if it's a "/"
je switch
cmp al,22h ;Branch if it's a
je readtext ; quotation mark
cmp filespec,offset defspec ;Error if this parameter has
jne error1 ; already been entered
dec si ;Move back one character
mov filespec,si ;Save address
call finddelim ;Find the end of it
mov byte ptr [si],0 ;Convert it to ASCIIZ
mov endspec,si ;Save ending address
jc check ;Branch if end of line
inc si ;Advance to next character
jmp parse ;Return to parsing loop
readtext: cmp srchtext,0 ;Error if this parameter has
jne error1 ; already been entered
mov srchtext,si ;Save address
sub cx,cx ;Initialize count
readloop: lodsb ;Get next character
cmp al,22h ;Done if quotation mark
je readdone
cmp al,0Dh ;Error if end of line
je error1
inc cx ;Increment count
jmp readloop ;Go back for more
readdone: jcxz error1 ;Error if count is 0
mov textsize,cx ;Save count
mov byte ptr [si-1],0 ;Convert to ASCIIZ string
jmp parse ;Go back for more
switch: lodsb ;Get character after switch
cmp al,"7" ;Set bitflag if it's /7
jne switch1
mov bitflag,1
jmp parse
switch1: and al,0DFh ;Capitalize the character
cmp al,"C" ;Set CASEFLAG is it's /C
jne switch2
mov caseflag,1
jmp parse
switch2: cmp al,"I" ;Set SCRNFLAG if it's /I
jne switch3
mov scrnflag,1
jmp parse
switch3: cmp al,"S" ;Set DESCFLAG if it's /S
jne switch4
mov descflag,1
jmp parse
switch4: cmp al,"A" ;Set FILEATTR if it's /A
jne switch5
mov fileattr,07h
jmp parse
switch5: cmp al,"M" ;Replace color attributes
je switch6 ; with monochrome if /M
goto_error: jmp error1 ; was entered
switch6: call setmono
jmp parse
check: cmp srchtext,0 ;Make sure text string was
je goto_error ; entered before going on
;
; If a path name was entered, go to the drive and directory named.
;
mov ah,19h ;Save the default drive
int 21h
mov drive,al
mov ah,47h ;Save the current directory
sub dl,dl
mov si,offset directory+1
int 21h
cmp filespec,offset defspec ;Branch if no path string
je gotosrch ; was entered
mov si,filespec ;Point SI to path
cmp byte ptr [si+1],":" ;Branch if path did not
jne nodrive ; contain a drive code
mov ah,0Eh ;Otherwise set the default
mov dl,[si] ; drive to the one
and dl,0DFh ; specified
sub dl,41h
int 21h
mov ah,19h ;See if it worked by seeing
int 21h ; what is now the default
cmp al,dl ;Error if AL != DL
mov dx,offset errmsg2
je checkpath
error3: jmp error
checkpath: add filespec,2 ;Advance past drive code
cmp byte ptr [si+2],0 ;If there's no path string
jne nodrive ; after the drive code,
mov filespec,offset defspec ; begin search now
gotosrch: jmp short beginsrch
nodrive: mov ah,3Bh ;Try to set the current
mov dx,filespec ; directory using the
int 21h ; path string entered
jc checkend ; on the command line
mov filespec,offset defspec ;If it worked, set FILESPEC
jmp short beginsrch ; equal to *.* and branch
checkend: mov di,endspec ;If it failed, make sure the
cmp byte ptr [di-1],"\" ; path didn't end in "\"
je badpath
mov cx,di ;Get length in CX
sub cx,filespec
dec di
mov al,"\" ;Initialize AL
std ;Set direction flag
repne scasb ;Search for "\"
cld ;Clear direction flag
jne beginsrch ;Begin search if no "\"
mov dx,filespec ;Point DX to path
mov filespec,di ;Point FILESPEC to new
add filespec,2 ; file spec string
mov byte ptr [di+1],0 ;Convert path to ASCIIZ
mov ah,3Bh ;Try to set the current
mov si,dx ; directory again
cmp byte ptr [si],0 ;Reset DX if path pointed
jne chdir ; to the root directory
mov dx,offset rootdir
chdir: int 21h
jnc beginsrch ;Continue if it worked
badpath: mov ah,0Eh ;Restore default drive
mov dl,drive ; and exit if it
int 21h ; failed
mov dx,offset errmsg3
jmp error
;
; Perform initializations and do the search.
;
beginsrch: mov ah,19h ;Initialize path string with
int 21h ; the letter of the current
add al,41h ; drive
mov pathstring,al
mov si,srchtext ;Copy the search string to
mov di,offset text ; buffer at end of program
mov cx,textsize
rep movsb
cmp caseflag,0 ;Convert search string to
jne docase ; uppercase if /C was not
mov si,offset text ; entered
mov cx,textsize
call stripcase
docase: cmp bitflag,0 ;Strip high bits from the
je do8bits ; search string if /7 was
mov si,offset text ; entered
mov cx,textsize
call striphigh
do8bits: mov ax,3300h ;Get the state of Ctrl-
int 21h ; Break checking
mov dl,breakflag
mov ax,3301h ;Turn Ctrl-Break checking
mov dl,1 ; on
int 21h
mov ax,2523h ;Point interrupt 23H to
mov dx,offset exit ; internal Ctrl-Break
cmp scrnflag,0 ; handler
je exit_ok
mov dx,offset abort
exit_ok: int 21h
cmp scrnflag,0 ;Initialize video if full-
je dosearch ; screen mode
call init_video
dosearch: call searchdir ;Do the search
cmp scrnflag,0 ;Branch if not full-screen
je show_results
mov ax,0600h ;Blank the window
mov cx,090Bh
mov dx,0D44h
mov bh,window_color1
int 10h
mov si,offset scrntxt8 ;Display "No more files"
mov dx,0B21h
mov bl,window_color1
call bios_outtext
mov ah,0 ;Wait for a keypress
int 16h
abort: call restore_video ;Clear the screen and exit
jmp short exit
;
; Summarize the results of the search.
;
show_results: mov ah,09h ;Advance cursor to next line
mov dx,offset crlf
int 21h
mov ax,filessearched ;Echo number of files
call dos_outnum ; searched
mov ah,09h
mov dx,offset msg1
int 21h
mov ax,dirssearched ;Echo number of directories
call dos_outnum ; searched
mov ah,09h
mov dx,offset msg2a
cmp dirssearched,1
je singular
mov dx,offset msg2b
singular: int 21h
mov ax,filesfound ;Echo number of files
call dos_outnum ; found containing
mov ah,09h ; the text string
mov dx,offset msg3
int 21h
mov si,srchtext ;Echo the text string
call dos_out
mov ah,09h
mov dx,offset msg4
int 21h
;
; Restore the default drive and directory and exit.
;
exit: mov ax,3301h ;Restore the state of Ctrl-
mov dl,breakflag ; Break checking
int 21h
mov ah,0Eh ;Restore default drive
mov dl,drive
int 21h
mov ah,3Bh ;Restore current directory
mov dx,offset directory
int 21h
mov ax,4C00h ;Exit with ERRORLEVEL=0
int 21h
main endp
;****************************************************************************
; FINDCHAR advances SI to the next non-space or non-comma character.
; On return, carry set indicates EOL was encountered.
;****************************************************************************
findchar proc near
lodsb ;Get the next character
cmp al,20h ;Loop if space
je findchar
cmp al,2Ch ;Loop if comma
je findchar
dec si ;Point SI to the character
cmp al,0Dh ;Exit with carry set if end
je eol ; of line is reached
clc ;Clear carry and exit
ret
eol: stc ;Set carry and exit
ret
findchar endp
;****************************************************************************
; FINDDELIM advances SI to the next space or comma character. On return,
; carry set indicates EOL was encountered.
;****************************************************************************
finddelim proc near
lodsb ;Get the next character
cmp al,20h ;Exit if space
je fd_exit
cmp al,2Ch ;Exit if comma
je fd_exit
cmp al,0Dh ;Loop back for more if end
jne finddelim ; of line isn't reached
dec si ;Set carry and exit
stc
ret
fd_exit: dec si ;Clear carry and exit
clc
ret
finddelim endp
;****************************************************************************
; SCANHELP scans the command line for a /? switch. If found, carry returns
; set and SI contains its offset. If not found, carry returns clear.
;****************************************************************************
scanhelp proc near
push si ;Save SI
scanloop: lodsb ;Get a character
cmp al,0Dh ;Exit if end of line
je scan_exit
cmp al,22h ;Branch if it's a quotation
je skip ; mark
cmp al,"?" ;Loop if not "?"
jne scanloop
cmp byte ptr [si-2],"/" ;Loop if not "/"
jne scanloop
add sp,2 ;Clear the stack
sub si,2 ;Adjust SI
stc ;Set carry and exit
ret
scan_exit: pop si ;Restore SI
clc ;Clear carry and exit
ret
skip: lodsb ;Get a character
cmp al,0Dh ;Exit if end of line
je scan_exit
cmp al,22h ;Reenter the loop if it's
je scanloop ; a quotation mark
jmp skip ;Continue scanning
scanhelp endp
;****************************************************************************
; SEARCHDIR searches files in the current directory for a text string. If
; FINDTEXT was started with a /S switch, SEARCHDIR calls itself recursively
; to search the current directory and all its descendants.
;****************************************************************************
searchdir proc near
push bp ;Save BP
mov ah,2Fh ;Get current DTA address
int 21h
push bx ;Save it
push es
sub sp,2Bh ;Make room on the stack
mov bp,sp ;Establish addressability
mov ah,1Ah ;Set DTA address to a
mov dx,bp ; location in the
int 21h ; stack
inc dirssearched ;Increment directory count
mov ah,47h ;Add the current directory
sub dl,dl ; to the path string for
mov si,offset pathstring+3 ; output
int 21h
cmp scrnflag,0 ;Branch if not full-screen
je findfirstfile
call win_showdir ;Display directory name
mov dh,rows ;Blank the directory count
mov dl,23 ; currently displayed
mov cx,5
mov bl,window_color1
call blankcells
mov ax,dirssearched ;Display the new number of
mov dl,23 ; directories searched
call bios_outnum
;
; Search all the files in the current directory.
;
findfirstfile: mov ah,4Eh ;Find first file matching
mov cx,fileattr ; the search criteria
mov dx,filespec
int 21h
jc findfirstdir ;Branch if no files found
search_another: call searchfile ;Search the file
mov ah,4Fh ;Find next file matching
int 21h ; the search criteria
jnc search_another
;
; Search for a subdirectory to go to if /S was specified.
;
findfirstdir: cmp descflag,0 ;Exit if /S was not entered
je sd_exit
mov ah,4Eh ;Find first file or
mov cx,17h ; subdirectory
mov dx,offset defspec
int 21h
jc sd_exit ;Exit if nothing found
testdir: cmp byte ptr [bp+30],2Eh ;Skip . and .. entries
je findnextdir
test byte ptr [bp+21],10h ;Branch if name returned
jz findnextdir ; is not a subdirectory
mov ah,3Bh ;Change to the subdirectory
mov dx,bp ; whose name was just
add dx,30 ; returned
int 21h
call searchdir ;Search it too
mov ah,3Bh ;Go up a directory level
mov dx,offset updir
int 21h
findnextdir: mov ah,4Fh ;Find next subdirectory
int 21h
jnc testdir ;Loop back if found
;
; Restore BP, the DTA, and the stack, then exit.
;
sd_exit: add sp,2Bh ;Adjust the stack pointer
mov ah,1Ah ;Restore the DTA to where
mov bx,ds ; it was on entry
pop ds
pop dx
int 21h
mov ds,bx
pop bp ;Restore BP
ret ;Return to caller
searchdir endp
;****************************************************************************
; SEARCHFILE searches the file whose name is at [BP+30] for a text string.
;****************************************************************************
searchfile proc near
mov foundflag,0 ;Initialize flag
inc filessearched ;Increment search count
cmp scrnflag,0 ;Branch if not full-screen
je openfile
call win_showfile ;Display file name
mov dh,rows ;Blank the file count
mov dl,50 ; currently displayed
mov cx,5
mov bl,window_color1
call blankcells
mov ax,filessearched ;Display the new number of
mov dl,50 ; files searched
call bios_outnum
;
; Open the file.
;
openfile: mov ax,3D00h ;Open the file for
mov dx,bp ; reading
add dx,30
int 21h
jnc savehandle ;Branch if no error
mov dx,offset errmsg4 ;Exit on error
search_error: cmp scrnflag,0 ;Branch if not full-screen
je serror1
push dx ;Save DX
call restore_video ;Restore video before exit
pop dx ;Restore DX
serror1: mov ah,09h ;Output the error message
int 21h
call dos_outname ;Followed by the file name
mov ah,09h ;Advance cursor to next
mov dx,offset crlf ; line before exit
int 21h
jmp exit ;Terminate the program
savehandle: mov handle,ax ;Save file handle
;
; Read a block of data and search it.
;
readblock: mov ah,3Fh ;Read one 24K block of data
mov bx,handle ; from the file
mov cx,6000h
mov dx,offset buffer1
int 21h
mov dx,offset errmsg5 ;Exit on error
jc search_error
cmp ax,textsize ;Done if bytes read is less
jae search1 ; then search text length
jmp search_done
search1: mov bytesread,ax ;Save bytes read count
cmp bitflag,0 ;Strip the high bits off
je search2 ; characters in the buffer
mov si,offset buffer1 ; if /7 was entered
mov cx,bytesread
call striphigh
search2: cmp caseflag,0 ;Branch if /C was not entered
jne search3
cmp scrnflag,0 ;Also branch if /I was not
je nocopy ; entered
mov si,offset buffer1 ;Copy everything in BUFFER1
mov di,offset buffer2 ; to BUFFER2
mov cx,bytesread
rep movsb
nocopy: mov si,offset buffer1 ;Capitalize everything in
mov cx,bytesread ; BUFFER1
call stripcase
search3: mov cx,bytesread ;Compute number of string
sub cx,textsize ; comparisons to be
inc cx ; performed
mov si,offset buffer1 ;Point SI to buffer
search4: push cx ;Save CX and SI
push si
mov di,offset text ;Point DI to search string
mov cx,textsize ;Initialize CX with length
repe cmpsb ;Compare the strings
je match ;Branch if match found
continue: pop si ;Restore SI and CX
pop cx
inc si ;Increment SI
loop search4 ;Loop back for more
cmp bytesread,6000h ;Search done if end of
jb search_done ; file reached
mov ax,textsize ;Set the file pointer
neg ax ; back to make sure
cwd ; text strings that
mov cx,dx ; straddle buffer
mov dx,ax ; boundaries are
mov bx,handle ; not missed
mov ax,4201h
int 21h
jmp readblock ;Process another block
;
; Process a match.
;
match: cmp scrnflag,0 ;Branch if not full-screen
je match2
cmp foundflag,0 ;Increment files found count
jne alreadyfound ; if this is the first match
mov foundflag,1 ; in this file
inc filesfound
push si ;Save SI
mov dh,rows ;Blank the found count
mov dl,74 ; currently displayed
mov cx,5
mov bl,window_color1
call blankcells
mov ax,filesfound ;Display the new number of
mov dl,74 ; files found
call bios_outnum
pop si ;Restore SI
alreadyfound: call showfile ;Show the file
or ah,ah ;Reenter the search loop
je continue ; if Enter was pressed
add sp,4 ;Clean off the stack
cmp ah,2 ;Search complete if spacebar
je search_done ; was pressed
call restore_video ;Restore video and terminate
jmp exit ; if Esc was pressed
match2: add sp,4 ;Clean off the stack
call dos_outname ;Display the file name
inc filesfound ;Increment files found count
;
; Close the file and exit.
;
search_done: mov ah,3Eh ;Close file with DOS
mov bx,handle ; function 3EH
int 21h
ret
searchfile endp
;****************************************************************************
; SHOWFILE displays the contents of a file surrounding the point where
; a match was found in the search for matching text. On entry, SI points
; to the address just after the text string in BUFFER1 and [BP+30] points
; to the name of the file. On exit, AH=0 if Enter was pressed, AH=1 if
; Esc was pressed, or AH=2 if the spacebar was pressed.
;****************************************************************************
showfile proc near
push si ;Save SI
mov dx,0020h ;Blank "FINDTEXT" at the
mov cx,8 ; top of the screen
mov bl,window_color1
call blankcells
;
; Display the file name at the top of the screen and instructions at bottom.
;
mov di,offset pathstring ;Compute length of path
call strlen ; name string
mov bx,cx ;Save it in BX
mov di,bp ;Compute length of file
add di,30 ; name string
call strlen
add bx,cx ;Add it to BX
mov dx,79 ;Calculate where to write
sub dx,bx ; string such that it is
shr dx,1 ; centered
sub dh,dh
mov bl,window_color1
mov si,offset pathstring ;Output path string
call bios_outtext
cmp byte ptr [bp+3],0 ;Branch if this is the
je show1 ; root directory
mov si,offset rootdir ;Output a "\" to separate
call bios_outtext ; the path and file names
show1: mov si,bp ;Output file name
add si,30
call bios_outtext
mov dh,rows ;Display instructions at the
mov dl,1 ; bottom of the screen
mov bl,window_color2
mov si,offset scrntxt3
call bios_outtext
mov bl,window_color1
mov dl,13
mov si,offset scrntxt9
call bios_outtext
mov dl,32
mov si,offset scrntxt10
call bios_outtext
mov dl,48
mov si,offset scrntxt11
call bios_outtext
mov ax,0600h ;Clear the screen
mov cx,0100h
mov dh,rows
dec dh
mov dl,79
mov bh,text_color
call exec10h
;
; Calculate starting and ending buffer offsets and show the file.
;
pop si ;Retrieve buffer pointer
sub si,textsize ;Point SI to start of text
mov dx,si ;Save it in DX
mov al,80 ;Compute the maximum number
mov bl,rows ; of characters that can be
dec bl ; displayed
mul bl
push ax ;Save it
mov al,80 ;Redo the calculation, this
mov bl,rows ; time making sure that the
shr bl,1 ; number of rows is an even
shl bl,1 ; number
dec bl
mul bl
sub ax,textsize ;Now compute the buffer
shr ax,1 ; offset where display
sub si,ax ; should begin
cmp si,offset buffer1
jnb start_ok
mov si,offset buffer1
start_ok: pop cx ;Retrieve count
sub dx,si ;Calculate offset to text
push si ;Save starting offset
add si,cx ;Compute ending offset
mov di,offset buffer1 ;Compute maximum offset
add di,bytesread
cmp si,di ;Compare the offsets
jbe end_ok ;CX okay if end < maximum
sub si,di ;Otherwise subtract the
sub cx,si ; difference from CX
end_ok: pop si ;Retrieve starting offset
cmp caseflag,0
jne blast_it
add si,6000h ;Adjust if case-sensitive
blast_it: push es ;Save ES
mov es,videoseg ;Point ES:DI to video buffer
mov di,videobuf
add di,160
out_loop1: lodsb ;Get a character
cmp al,32 ;Substitute a period if
jb period ; it's non-displayable
cmp al,126
jbe copy_it
period: mov al,"."
copy_it: stosb ;Copy it to the video buffer
inc di ;Advance to next character
loop out_loop1 ;Loop until done
;
; Highlight the search text.
;
mov di,videobuf ;Point DI to the byte that
add di,160 ; corresponds to the first
shl dx,1 ; attribute of the search
add di,dx ; text
inc di
mov al,hilite_color ;Load attribute in AL
mov cx,textsize ;Load string length in CX
out_loop2: stosb ;Highlight the search text
inc di
loop out_loop2
pop es ;Restore ES
;
; Get a keyboard response from the user.
;
getkey: mov ah,0 ;Read keyboard
int 16h
sub ah,ah ;Set AH to 0
cmp al,0Dh ;Exit if Enter was pressed
je show_exit
inc ah ;Set AH to 1
cmp al,1Bh ;Exit if Esc was pressed
je show_abort
mov ah,2
cmp al,20h ;Exit if spacebar was pressed
jne getkey ;Otherwise loop back for more
;
; Redraw the title bar, status bar, and search window, then exit.
;
show_exit: push ax ;Save return code
mov ax,0600h ;Clear the screen
mov cx,0100h
mov dh,rows
dec dh
mov dl,79
mov bh,text_color
call exec10h
call drawtitle ;Redraw the title bar
call drawstatus ;Redraw the status bar
call drawwindow ;Redraw the window
call win_showdir ;Display directory name
call win_showfile ;Display file name
pop ax ;Retrieve return code
show_abort: ret
showfile endp
;****************************************************************************
; DOS_OUTNUM converts the number in AX to ASCII and displays it.
;****************************************************************************
dos_outnum proc near
mov bx,10 ;Initialize BX with divisor
sub cx,cx ;Initialize digit counter
divide: inc cx ;Increment counter
sub dx,dx ;Zero high word of DX:AX
div bx ;Divide AX by 10
push dx ;Save remainder on stack
or ax,ax ;Loop if AX != 0
jnz divide
output: mov ah,02h ;Use DOS function 02H
pop dx ;Retrieve digit from stack
add dl,30h ;Convert to ASCII
int 21h ;Output it
loop output ;Loop until done
ret
dos_outnum endp
;****************************************************************************
; DOS_OUTNAME displays the ASCIIZ file name addressed by [BP+30] prefixed
; by the ASCIIZ string PATHSTRING.
;****************************************************************************
dos_outname proc near
mov si,offset pathstring ;Output path string
call dos_out
mov ah,02h
mov si,offset pathstring ;Output "\" if this is
cmp byte ptr [si+3],0 ; not the root directory
je notroot
mov ah,02h
mov dl,"\"
int 21h
notroot: mov si,bp ;Output file name
add si,30
call dos_out
mov ah,09h ;Move cursor to next line
mov dx,offset crlf
int 21h
ret
dos_outname endp
;****************************************************************************
; WIN_SHOWDIR displays the name of the directory being searched in
; the search window.
;****************************************************************************
win_showdir proc near
mov dx,0B1Bh ;Blank the directory name
mov cx,42 ; currently displayed
mov bl,window_color1
call blankcells
mov si,offset pathstring ;Point SI to PATHSTRING
mov dx,0B1Bh ;Starting row and column
mov di,si ;Get length of PATHSTRING
call strlen
cmp cx,41 ;Branch if it's greater
ja wsd1 ; than 41
call bios_outtext ;Output PATHSTRING
ret ;Return to caller
wsd1: mov cx,41 ;Output first 41 characters
call bios_out ; of PATHSTRING
ret ;Return to caller
win_showdir endp
;****************************************************************************
; WIN_SHOWFILE displays the name of the file being searched in the
; search window. On entry, [BP+30] points to the file name.
;****************************************************************************
win_showfile proc near
mov dx,0C1Bh ;Blank the file name
mov cx,42 ; currently displayed
mov bl,window_color1
call blankcells
mov si,bp
add si,30
mov dx,0C1Bh ;Display the file name
call bios_outtext
ret
win_showfile endp
;****************************************************************************
; STRIPCASE converts lowercase characters to uppercase in the buffer
; pointed ot by DS:SI. On entry, CX the buffer length.
;****************************************************************************
stripcase proc near
cmp byte ptr [si],"a" ;Skip if less than "a"
jb notlower
cmp byte ptr [si],"z" ;Skip if greater than "z"
ja notlower
and byte ptr [si],0DFh ;Capitalize the character
notlower: inc si ;Advance SI
loop stripcase ;Loop until done
ret
stripcase endp
;****************************************************************************
; STRIPHIGH strips the high bits off the characters in the buffer pointed
; to by DS:SI. On entry, CX holds the buffer length.
;****************************************************************************
striphigh proc near
and byte ptr [si],7Fh ;Zero the high bit
inc si ;Advance SI
loop striphigh ;Loop until done
ret
striphigh endp
;****************************************************************************
; DOS_OUT displays the ASCIIZ text string pointed to by DS:SI using DOS
; function 02H. Text is displayed at the current cursor position.
;***************************************************************************
dos_out proc near
lodsb ;Get a character
or al,al ;Exit if zero
jz dos_exit
mov ah,02h ;Display it using DOS
mov dl,al ; function 02H
int 21h
jmp dos_out ;Loop back for more
dos_exit: ret
dos_out endp
;****************************************************************************
; INIT_VIDEO sets the video environment for full-screen mode.
;****************************************************************************
init_video proc near
push es ;Point ES to the BIOS
mov ax,40h ; Data Area
mov es,ax
mov al,es:[49h] ;Get display mode in AL
cmp al,7 ;Continue if mode 2, 3,
je mode_ok ; or 7
cmp al,2
je mode_ok
cmp al,3
je mode_ok
mov ax,0003h ;Reset video mode
test byte ptr es:[63h],40h
jnz reset
mov ax,0007h
reset: int 10h
mode_ok: test byte ptr es:[63h],40h ;Determine whether video is
jnz is_color ; color or monochrome
call setmono ;Switch to monochrome video
mov videoseg,0B000h
is_color: mov ax,es:[4Eh] ;Get starting page address
mov videobuf,ax
mov al,es:[62h] ;Get active page number
mov pageno,al
mov ax,es:[60h] ;Get cursor type
mov cursor,ax
mov ah,12h ;Find out if there's an
mov bl,10h ; an EGA, VGA, or XGA
int 10h ; installed
cmp bl,10h
je noega
mov al,es:[84h] ;Determine number of rows
mov rows,al ; displayed if there is
noega: pop es ;Restore ES
mov ah,08h ;Get the color of the
mov bh,pageno ; character at the
int 10h ; cursor
mov scrn_color,ah
;
; Paint the screen.
;
mov ah,01h ;Hide the cursor
mov ch,20h
int 10h
mov ax,0600h ;Clear the screen
sub cx,cx
mov dh,rows
mov dl,79
mov bh,text_color
int 10h
call drawtitle ;Display the title bar
call drawstatus ;Display the status bar
call drawwindow ;Display the status window
ret
init_video endp
;****************************************************************************
; RESTORE_VIDEO cleans up the screen before the program terminates.
;****************************************************************************
restore_video proc near
mov ax,0600h ;Clear the screen
sub cx,cx
mov dh,rows
mov dl,79
mov bh,scrn_color
int 10h
mov ah,02h ;Home the cursor
mov bh,pageno
sub dx,dx
int 10h
mov ah,01h ;Redisplay the cursor
mov cx,cursor
int 10h
ret
restore_video endp
;****************************************************************************
; SETMONO replaces color video attributes with monochrome attributes.
;****************************************************************************
setmono proc near
mov window_color1,70h
mov window_color2,70h
mov hilite_color,70h
mov text_color,07h
ret
setmono endp
;****************************************************************************
; DRAWTITLE displays the screen title at the top of the screen.
;****************************************************************************
drawtitle proc near
sub dx,dx ;Blank the line
mov cx,80
mov bl,window_color1
call blankcells
mov dx,0024h ;Display title
mov si,offset scrntxt1
call bios_outtext
ret
drawtitle endp
;****************************************************************************
; DRAWSTATUS displays the status bar at the bottom of the screen.
;****************************************************************************
drawstatus proc near
mov dh,rows ;Blank the line
sub dl,dl
mov cx,80
mov bl,window_color1
call blankcells
mov dl,1 ;Display status bar text
mov si,offset scrntxt2
mov bl,window_color2
call bios_outtext
mov ax,dirssearched ;Display number of
mov bl,window_color1 ; directories searched
mov dl,23
call bios_outnum
mov ax,filessearched ;Display number of files
mov dl,50 ; searched
call bios_outnum
mov ax,filesfound ;Display number of files
mov dl,74 ; found containing the
call bios_outnum ; search string
ret
drawstatus endp
;****************************************************************************
; DRAWWINDOW displays the search window on the screen.
;****************************************************************************
drawwindow proc near
mov ax,0600h ;Blank the area where the
mov cx,080Ah ; window will lie
mov dx,0E45h
mov bh,window_color1
call exec10h
mov cx,080Ah ;Draw a border around the
mov dx,0E45h ; window
mov bh,pageno
mov bl,window_color1
call drawbox
mov dx,0A0Ch ;Display "Searching for:"
mov si,offset scrntxt4
mov bl,window_color2
call bios_outtext
mov dx,0B11h ;Display "Location:"
mov si,offset scrntxt5
call bios_outtext
mov dx,0C15h ;Display "File:"
mov si,offset scrntxt6
call bios_outtext
mov dx,0A1Bh ;Display opening quotation
mov bl,window_color1 ; mark
mov si,offset scrntxt7
call bios_outtext
mov si,srchtext ;Display search text
mov di,si
call strlen
cmp cx,39
ja dw1
call bios_outtext
jmp short dw2
dw1: mov cx,39
call bios_out
dw2: mov si,offset scrntxt7 ;Display closing quotation
call bios_outtext ; mark
ret
drawwindow endp
;****************************************************************************
; EXEC10H executes an INT 10H and preserves BP across the call.
;****************************************************************************
exec10h proc near
push bp ;Save BP
int 10h ;Do the interrupt
pop bp ;Restore BP
ret
exec10h endp
;****************************************************************************
; STRLEN returns the length of the ASCIIZ string pointed to by ES:DI in CX.
;****************************************************************************
strlen proc near
mov cx,0FFFFh ;Initialize count
sub al,al ;Intialize AL
repne scasb ;Search for zero
inc cx ;Calculate number of
mov ax,0FFFFh ; bytes that were
xchg ax,cx ; examined
sub cx,ax
ret
strlen endp
;****************************************************************************
; BIOS_OUT displays an ASCII string. On entry, DS:SI points to the string,
; DH and DL hold the starting row and column, BL holds the attribute to be
; used, and CX holds the character count.
;****************************************************************************
bios_out proc near
mov ah,02h ;Set the cursor position
mov bh,pageno
call exec10h
push cx ;Save count
lodsb ;Get a character
mov ah,09h ;Display it
mov cx,1
call exec10h
inc dl ;Advance column number
pop cx ;Retrieve count
loop bios_out ;Loop until done
ret
bios_out endp
;****************************************************************************
; BIOS_OUTTEXT displays the ASCIIZ text string pointed to by DS:SI using
; BIOS text output functions. On entry, DH and DL hold the row and column
; where output should begin and BL holds the attribute to be used.
;****************************************************************************
bios_outtext proc near
mov ah,02h ;Set the cursor position
mov bh,pageno
call exec10h
lodsb ;Get a character
or al,al ;Exit if zero
jz bios_exit
mov ah,09h ;Display it
mov cx,1
call exec10h
inc dl ;Advance column number
jmp bios_outtext ;Loop back for more
bios_exit: ret
bios_outtext endp
;****************************************************************************
; BIOS_OUTNUM converts the number in AX to ASCII form and displays it using
; BIOS output functions. On entry, AX holds the number, DH and DL hold the
; row and column address, and BL holds the attribute to be used.
;****************************************************************************
bios_outnum proc near
mov si,bx ;Save BX and DX
mov di,dx
mov bx,10 ;Initialize BX with divisor
sub cx,cx ;Initialize digit counter
bnum1: inc cx ;Increment counter
sub dx,dx ;Zero high word of DX:AX
div bx ;Divide AX by 10
push dx ;Save remainder on stack
or ax,ax ;Loop if AX != 0
jnz bnum1
mov bx,si ;Retrieve BX and DX
mov dx,di
mov bh,pageno ;Place page number in BH
bnum2: mov ah,02h ;Position the cursor
call exec10h
pop ax ;Retrieve digit from stack
add al,30h ;Convert to ASCII
mov ah,09h ;Output it using BIOS
push cx ; function 09H
mov cx,1
call exec10h
pop cx
inc dl ;Advance the cursor
loop bnum2 ;Loop until done
ret
bios_outnum endp
;****************************************************************************
; BLANKCELLS blanks a line or part of a line. On entry, DH and DL hold the
; starting row and column, CX holds the number of cells to blank, and BL
; holds the attribute to be used.
;****************************************************************************
blankcells proc near
mov ah,02h ;Position the cursor
mov bh,pageno
call exec10h
mov ax,0920h ;Blank the cells
call exec10h
ret
blankcells endp
;****************************************************************************
; DRAWBOX draws a single line box. On entry, CH and CL hold the row and
; column address of the upper left corner of the box, DH and DL the address
; of the lower right corner, BH the page number, and BL the attribute to be
; used.
;****************************************************************************
drawbox proc near
mov row1,ch ;Save box coordinates and
mov col1,cl ; compute the box height
mov row2,dh ; and box width
mov col2,dl
push cx
sub dh,ch
dec dh
mov boxheight,dh
sub dl,cl
dec dl
mov boxwidth,dl
mov ah,02h ;Position the cursor at the
pop dx ; upper left corner
call exec10h
mov ah,09h ;Draw upper left corner
mov al,218
mov cx,1
call exec10h
mov dh,row1 ;Draw upper horizontal
mov dl,col1
inc dl
mov cx,word ptr boxwidth
call drawhorizontal
mov ah,02h ;Draw upper right corner
mov dl,col2
call exec10h
mov ah,09h
mov al,191
mov cx,1
call exec10h
inc dh ;Draw right vertical
mov cx,word ptr boxheight
call drawvertical
mov ah,02h ;Draw lower right corner
mov dh,row2
call exec10h
mov ah,09h
mov al,217
mov cx,1
call exec10h
mov dl,col1 ;Draw lower horizontal
inc dl
mov cx,word ptr boxwidth
call drawhorizontal
mov ah,02h ;Draw lower left corner
dec dl
call exec10h
mov ah,09h
mov al,192
mov cx,1
call exec10h
mov dh,row1 ;Draw left vertical
inc dh
mov cx,word ptr boxheight
call drawvertical
ret
drawbox endp
;****************************************************************************
; DRAWHORIZONTAL draws a horizontal line at the cursor position passed in
; DH and DL. Length is specified in CX, attribute in BL, and page number in
; BH. The line is drawn left to right.
;****************************************************************************
drawhorizontal proc near
mov ah,02h ;Position the cursor
call exec10h
mov ah,09h ;Draw horizontal
mov al,196
call exec10h
dh_exit: ret
drawhorizontal endp
;****************************************************************************
; DRAWVERTICAL draws a vertical line at the cursor position passed in
; DH and DL. Length is specified in CX, attribute in BL, and page number
; in BH. The line is drawn top to bottom.
;****************************************************************************
drawvertical proc near
mov ah,02h ;Position the cursor
call exec10h
push cx ;Save CX
mov ah,09h ;Draw one character
mov al,179
mov cx,1
call exec10h
inc dh
pop cx ;Retrieve CX
loop drawvertical ;Loop until done
dv_exit: ret
drawvertical endp
text = $ ;Text being searched for
buffer1 = $+80h ;File I/O buffer 1 (24K)
buffer2 = $+6080h ;File I/O buffer 2 (24K)
code ends
end begin