'===========================================================================
' Subject: VIEW DIRECTORIES/FILES ZIP/LZH Date: 10-25-99 (18:05)
' Author: Randall L. Glass Code: PB
' Origin: rlglass@yahoo.com Packet: PB.ABC
'===========================================================================
'-------------------------------------------------------------------------
'
' Shell BY Randall L Glass
' CopyRight Aug3,1999
'
'---------------------------------------------------------------------------
'
' Email rlglass@yahoo.com
'
'---------------------------------------------------------------------------
'
' This Program is Freeware
' You may do anything with this program AS long AS you give me credit
' somewhere in the documentation.
'
'===========================================================================
'
' Program to view directoryies and files ,Including ZIP and Lzh
'
' Credit to Author: Jamshid Khoshrangi for his BOYER-MOORE INSTR Code: PB
' Thanks to William Yu FOR his ZipView & LzhView progam.
'
'
' You must SET the value of TEMP in your autoexec.bat file.
' Example SET TEMP = D:\TMP
'
' OR Rewrite the code in the program to set TempDir to your tempory directory.
' And Rewrite the code to your editor or file viewer.
'
' This includes an text viewer to view huge files up to 32700 lines
' Possible size 2.6 Gig
'
' List File Viewer is Faster
' You Can always replace my file viewer with an shell to List.com
'
' Look for SUB viewer
'
'----------------------------------------------------------------------------
$DYNAMIC
$HUGE
$STACK 10000
DEFINT A-Z
TYPE ZipType ' Zip File Header
Signature AS DWORD
Version AS WORD
GPBFlag AS WORD ' Not sure
Compress AS WORD ' Compression type
FileTime AS WORD
Filedate AS WORD ' Took a while to figure out
CRC32 AS DWORD
CompressSize AS DWORD
UnCompressSize AS DWORD
FileNameLen AS WORD
ExtraField AS WORD
END TYPE
TYPE LZHHead
HeadSize AS BYTE
CheckSum AS BYTE
Id1 AS STRING * 3
Method AS BYTE
Id2 AS BYTE
CompressSize AS DWORD
UnCompressSize AS DWORD
FileTime AS WORD
FileDate AS WORD
Attrs AS BYTE
HeaderLevel AS BYTE
FileNameLen AS BYTE
FileName AS STRING * 12
END TYPE
DECLARE Function GetKey%() AS INTEGER
DECLARE SUB GetStrLoc()
DECLARE SUB BoxBorder ()
DECLARE SUB Scroll(BYVAL TopRow%,BYVAL TopLeftCol%,BYVAL BottomRow%,BYVAL BottomRightCol%,BYVAL TotalLines%,BYVAL Attr%,BYVAL WhichWay%)
DIM ScreenSegment AS shared WORD
DIM DirStack$(10),ShellDir$(10)
DIM Directory$(1000), DirInfo$(1000)
SHARED Directory$(), DirInfo$()
SHARED Viewer$,TempDir$,StackPos%,DirStack$()
SHARED StartLine$,EndLine$,FileList$,Response$,ExtractCmd$,ExtractReponse$
SHARED DosError??,ShellDir$(),ShellPos%,ExitShell%
SHARED NextHandle%,LineSeg??,LinePtr??
IF(PBVScreenCARD AND 1) = 0 THEN
ScreenSegment?? = 47104 '&HB800 'color monitor
ELSE
ScreenSegment?? = 45056 '&HB000 'mono monitor
END IF
%SIG = &H04034B50 ' Signature
%UpArrow = -72:%DownArrow = -80:%Enter = 13:%Escape = 27
%Home = -71:%PageDown = -81:%PageUp = -73:%EndKey = -79
%Up = 6:%Down = 7:%LeftArrow = -75:%RightArrow = -77
%AltHome = -151
%U = 85
%ReadOnly = 1:%Hidden = 2:%System = 4:%Volume = 8:%SubDir = 16:%Archive = 32
%AllFiles = 33
CLS
'Viewer$ = "listr.com"
LastDir$ = CURDRIVE$ + ":\"
CHDIR LastDir$
IF(PBVScreenCARD AND 1) = 0 THEN
ScreenSegment?? = 47104 '&HB800 'color monitor
ELSE
ScreenSegment?? = 45056 '&HB000 'mono monitor
END IF
EXIT FAR AT BackHome
DO
ShellPos% = 0
DosShell LastDir$
BackHome:
LOOP WHILE ShellPos%
END
SUB DosShell(ShellDirectory$)
Choice% = 1:DisplayPos% = 1:LowFIle% = 1:HiFile% = 18:Ky% = 0
InfoLine$ = " FileName"+" Size"+" Date" + " Time"
PushDir2 ShellDirectory$,ShellDir$(),ShellPos%
DO
TotalFiles% = 0
RealDir$ = AddSlash$(TrueDir2$(ShellDir$(), ShellPos%))
GetDirAndFiles RealDir$ + "*.*", %SubDir , Directory$(), DirInfo$(), FilesInfo$, TotalFiles%
DirNum% = TotalFiles%
IF DirNum% > 1 THEN ARRAY SORT Directory$(1) FOR TotalFiles%,TagArray DirInfo$()
GetDirAndFiles RealDir$ + "*.*", %AllFiles, Directory$(), DirInfo$(), FilesInfo$, TotalFiles%
SortNumber% = TotalFiles - DirNum%
IF SortNumber% > 1 THEN
FileStart% = DirNum% + 1
ARRAY SORT Directory$(FileStart%) FOR SortNumber%,TagArray DirInfo$()
END IF
Pick% = ChooseProgram%( DirInfo$(),Directory$(),FilesInfo$,InfoLine$,Choice%,DisplayPos%,LowFile%,HiFile%,Ky%,DirNum%,"Directory")
SELECT CASE Ky%
CASE %RightArrow,%Enter
IF Attrib(RealDir$ + Directory$(Pick%)) = 16 THEN
DosShell(Directory$(Pick%))
COLOR 7,1
CLS
ELSEIF Attrib(RealDir$ + Directory$(Pick%)) <> 16 THEN
Ext$ = Extension$(Directory$(Pick%))
SELECT CASE Ext$
CASE ".ZIP",".LZH"
ShowZip(RealDir$ + Directory$(Pick%))
CASE ELSE '".TXT",".DOC"
Viewer RealDir$ + Directory$(Pick%)
CLS
DELAY .2
COLOR 7,0
END SELECT
END IF
CASE %LeftArrow,%Escape
DECR ShellPos%
EXIT LOOP
CASE %AltHome
EXIT FAR
END SELECT
LOOP
END SUB
SUB ShowZip(File$)
CLS
LOCATE 1,1,0
Ext$ = Extension$(File$)
File$ = TrueName$(File$)
IF ISFALSE FileExist%(File$) THEN EXIT SUB
TempDir$ = ENVIRON$("TEMP") + "\dosview"
PushDir TempDir$
ViewZip File$
PopDir
SHELL "DELTREE /Y " + Rtrim$(RealDir$,"\") + " >NUL"
COLOR 7,0
CLS
END SUB
SUB ViewZip(File$)
IF ISFALSE FileExist%(File$) THEN
LOCATE 5,15:PRINT File$;" doesn't exist !";
EXIT SUB
END IF
DIM ArchiveFiles$(1000),ArchiveInfo$(1000),ArchiveDir$(1000)
Choice% = 1:DisplayPos% = 1:LowFIle% = 1:HiFile% = 18
Ky% = 0
InfoLine$ = " FileName"+" Size"+" Date" + " Time"
CLS
Ext$ = Extension$(File$)
IF Ext$ = ".ZIP" OR Ext$ = ".LZH" THEN
PresentDir$ = CURDIR$
PresentDrive$ = CURDRIVE$
CHDRIVE Left$(File$,1)
CHDIR GetDirectory$(File$)
SELECT CASE Ext$
CASE ".ZIP"
ZipView GetFileName$(File$), ArchiveFiles$(), ArchiveInfo$(), FilesInfo$, Success%
CASE ".LZH"
LzhView GetFileName$(File$), ArchiveFiles$(), ArchiveInfo$(), FilesInfo$, Success%
END SELECT
CHDRIVE PresentDrive$
CHDIR PresentDir$
IF ISFALSE Success% THEN EXIT SUB
TotalFiles?? = CVWRD(ArchiveFiles$(0))
'ARRAY SORT ArchiveFiles$(1) FOR TotalFiles??,TAGARRAY ArchiveInfo$()
DO
Pick% = ChooseProgram%( ArchiveInfo$(),ArchiveFiles$(),FilesInfo$,InfoLine$,Choice%,DisplayPos%,LowFile%,HiFile%,Ky%,0,"")
Choice% = Pick%
SELECT CASE Ky%
CASE %Escape,%LeftArrow
EXIT SUB
CASE %RightArrow
IF Pick% > 0 THEN
Pick$ = UCASE$(ArchiveFiles$(Pick%))
RealName$ = GetFileName$(Pick$)
PickExt$ = Extension$(Pick$)
IF PickExt$ =".ZIP" OR PickExt$ = ".LZH" THEN
PushDir "TEMP"
RealDir$ = TrueDir$ + "\"
IF ISFALSE FileExist%(RealDir$+Pick$) THEN
CLS
SELECT CASE Ext$
CASE ".ZIP"
SHELL "PKUNZIP -e -o " + File$ + " " + Pick$ + " " + RealDir$ + " >NUL"
'SHELL "UNZIP " + File$ + " " + Pick$ + " " + "-d" + RealDir$ '+ " >NUL"
CASE ".LZH"
SHELL "lha.exe e /pn2 " + File$ + " " + RealDir$ + " "+ Pick$
END SELECT
END IF
fe% = FetchErrorLevel%
IF FetchErrorLevel% > 0 THEN
SHELL "DELTREE /Y " + Rtrim$(RealDir$,"\") + " >NUL"
EXIT SUB
END IF
ViewZip RealDir$ + RealName$
SHELL "DELTREE /Y " + Rtrim$(RealDir$,"\") + " >NUL"
PopDir
CLS
DELAY .2
ITERATE LOOP
ELSE
CLS
RealDir$ = TrueDir$ + "\"
SELECT CASE Ext$
CASE ".ZIP"
SHELL "PKUNZIP -e -o " + File$ + " " + Pick$ + " " + RealDir$ + " >NUL"
'SHELL "UNZIP " + File$ + " " + Pick$ + " " + "-d" + RealDir$ ' + " >NUL"
CASE ".LZH"
SHELL "lha.exe e /pn2 " + File$ + " " + RealDir$ + " "+ Pick$
END SELECT
END IF
'CLS
fe% = FetchErrorLevel%
IF FetchErrorLevel% > 0 THEN
SHELL "DELTREE /Y " + Rtrim$(RealDir$,"\") + " >NUL"
EXIT SUB
END IF
PresentDir$ = CURDIR$
PresentDrive$ = CURDRIVE$
CHDRIVE LEFT$(TrueDir$,1)
CHDIR TrueDir$
Viewer RealName$
CLS
KILL RealName$
CHDRIVE PresentDrive$
CHDIR PresentDir$
DELAY .2
COLOR 7,0
END IF
'CASE %U
END SELECT
LOOP
END IF
END SUB
FUNCTION ChooseProgram%(ArchiveInfo$(),ArchiveFile$(),InfoLine1$,InfoLine2$ ,Choice%, DisplayPos%,LowFile%, HiFile%,Ky%,DirNum%,ChooseType$)
DIM PrintLine AS STRING * 47
DIM DirLine AS STRING * 80
DisplayLine% = 18
TotalFiles% = CVWRD(ArchiveInfo$(0))
IF TotalFiles% < DisplayLine% THEN HiFile% = TotalFiles%
BottomDisplayLine% = DisplayLine%
COLOR 7,1
CLS
COLOR 0,7
LOCATE 1,1:PRINT SPACE$(80);
COLOR 7,1
LOCATE 2,2:PRINT Ltrim$(InfoLine1$)
LOCATE 4,2:PRINT InfoLine2$
DO
COLOR 15, 1
LinePos% = 0
IF TotalFiles% < 15 THEN BottomDisplayLine% = TotalFiles%
IF ScrollIt% = 0 THEN
'POKE$ 0, SaveScreen$ : LOCATE y%, x% 'restore old screen
FOR ArchiveFile% = LowFile% TO HiFile%
INCR LinePos%
LSET PrintLine$ = ArchiveInfo$(ArchiveFile%)
IF LinePos% = DisplayPos% THEN
QPrint 5 + LinePos%,1, PrintLine$ ,71
ELSE
QPRINT 5 + LinePos%,1,PrintLine$,23
END IF
NEXT ArchiveFile%
LSET PrintLine$ = ""
FOR I% = LinePos% + 1 To DisplayLine%
QPRINT 5 + I%,1,PrintLine$,23
NEXT I%
ELSE
LSET PrintLine$ = ArchiveInfo$(Choice%)
QPRINT 5 + DisplayPos%,1,PrintLine$,71
END IF
DirLine$ = SPACE$(80)
MID$(DirLine$,2) = ArchiveFile$(Choice%)
COLOR 0,7:LOCATE 25,1:PRINT DirLine$;
ScrollIt% = 0
ClearBuffer
DO: ky$ = UCASE$(INKEY$): LOOP WHILE ky$ = ""
Ky% = ASC(ky$): IF Ky% = 0 THEN Ky% = -ASC(MID$(ky$, 2))
SELECT CASE Ky%
CASE %Enter,%RightArrow
ChooseProgram% = choice%: EXIT DO
CASE %Escape
ChooseProgram% = 0: EXIT DO
CASE %Home
choice% = 1:LowFile% = 1
HiFile% = BottomDisplayLine%
DisplayPos% = 1
CASE %EndKey
Choice% = TotalFiles%
DisplayPos% = MODTYPE(Choice%, BottomDisplayLine%)
LowFile% = Choice% - DisplayPos% + 1
HiFile% = TotalFiles%
CASE %PageDown
INCR Choice%, DisplayLine%
INCR LowFile%,DisplayLine%
HiFile% = LowFile% + BottomDisplayLine% -1
IF HiFile% > TotalFiles% THEN HiFile% = TotalFiles%
IF choice% > TotalFiles% THEN
Choice% = TotalFiles%
DisplayPos% = ModType(Choice%, BottomDisplayLine%)
LowFile% = Choice% - DisplayPos% + 1
HiFile% = TotalFiles%
END IF
CASE %PageUp
DECR Choice%,DisplayLine%
DECR LowFile%,DisplayLine%
HiFile% = LowFile% + DisplayLine% -1
IF LowFile% < 1 THEN LowFile% = 1:HiFile% = BottomDisplayLine%
IF Choice% <=1 THEN
Choice% = 1
LowFile% = 1
HiFile% = BottomDisplayLine%
DisplayPos% = 1
END IF
CASE %DownArrow
INCR Choice%
IF Choice% <= TotalFiles% THEN
INCR DisplayPos%
ELSE
Choice% = TotalFiles%
END IF
IF DisplayPos% > BottomDisplayLine% THEN
DisplayPos% = BottomDisplayLine%
LowFile% = Choice% -BottomDisplayLine% + 1
IF HiFile% >= TotalFiles% THEN
HiFile% = TotalFiles%
ELSE
HiFile% = LowFile% + BottomDisplayLine% -1
END IF
PrintAtr BottomDisplayLine%+5, 1, 47, 23
Scroll 5,1, BottomDisplayLine%+4,47, 1,23,%Up
ScrollIt% = 1
END IF
CASE %UpArrow
DECR choice%
DECR DisplayPos%
IF choice% <=1 THEN
choice% = 1
LowFile% = 1
HiFile% = BottomDisplayLine%
DisplayPos% = 1
ELSE
IF DisplayPos% < 1 THEN
DisplayPos% = 1
LowFile% = Choice%
HiFile% = Choice% + BottomDisplayLine% -1
IF HiFile% >= TotalFiles% THEN
HiFile% = TotalFiles%
ELSE
HiFile% = LowFile% + BottomDisplayLine% -1
END IF
PrintAtr 6, 1, 47, 23
Scroll 5,1, BottomDisplayLine%+4,47, 1,23,%Down
ScrollIt% = 1
END IF
END IF
CASE 48 TO 57,65 TO 90
IF ChooseType$ = "Directory" THEN
ScanFiles% = TotalFiles% - Choice%
ARRAY SCAN ArchiveInfo$(Choice% + 1) FOR ScanFiles% ,FROM 2 TO 2,=Ky$,To PossibleChoice%
IF PossibleChoice% > 0 THEN
Choice% = Choice% + PossibleChoice%
ELSEIF PossibleChoice% = 0 THEN
ARRAY SCAN ArchiveInfo$(1) FOR Choice% - 1 ,FROM 2 TO 2,=Ky$,To PossibleChoice%
IF PossibleChoice% > 0 THEN Choice% = PossibleChoice%
END IF
IF PossibleChoice% > 0 THEN
LowFile% = Choice% - DisplayPos% + 1
HiFile% = LowFile% + BottomDisplayLine% -1
IF LowFile% < 1 THEN LowFile% = 1:HiFile% = BottomDisplayLine%:DisplayPos% = Choice%
IF HiFile% > TotalFiles% THEN HiFile% = TotalFiles%
END IF
END IF
CASE ELSE
EXIT DO
END SELECT
LOOP
COLOR 7,0
END FUNCTION
SUB Scroll(BYVAL TopRow%,BYVAL TopLeftCol%,BYVAL BottomRow%,BYVAL BottomRightCol%,BYVAL TotalLines%,BYVAL Attr%,BYVAL WhichWay%)
! PUSH DS
! PUSH BP
! MOV AH,WhichWay%
! MOV AL, TotalLines%
! MOV BH, Attr%
! MOV CH, TopRow%
! MOV CL, TopLeftCol%
! MOV DH, BottomRow%
! MOV DL, BottomRightCol%
! INT &H10
! POP BP
! POP DS
END SUB
SUB QPrint(BYVAL Row, BYVAL Col, BYVAL Text$, BYVAL attr) PUBLIC
ScreenSeg?? = ScreenSegment??
! push DS ; save DS for PowerBASIC
! mov ax,Row% ; get the row
! dec al ; convert row to zero base
! mov bl,80 ; get the number of cols
! mul bl ; multiply # of cols * rows
! add ax,Col% ; add the column
! dec al ; convert column to zero base
! mov di,ax ; offset within video page
! shl di,1 ; account for color/attribute
! push WORD PTR Text$ ; push string handle on the stack
! call GetStrLoc ; find the string
! jcxz QPExit ; if it's Null, exit
! mov DS, DX ; put segment in DS
! mov SI, AX ; put offset in SI
! mov ES, ScreenSeg?? ; move to ES
! mov AH, attr ; put attribute in AH
WriteChar:
! lodsb ; get Char from string
! stosw ; write Char and attribute to screen
! loop WriteChar ; do it all CX times
QPExit:
! pop DS ; restore DS for PowerBASIC
END SUB
SUB PrintAtr(byval Row%, byval Col%,ByVal LineWidth%, byval Attr%)
ScreenSeg?? = ScreenSegment??
! push ds ;save the good stuff
! mov ax,Row% ; get the row
! dec al ; convert row to zero base
! mov bl,80 ; get the number of cols
! mul bl ; multiply # of cols * rows
! add ax,Col% ; add the column
! dec al ; convert column to zero base
! mov di,ax ; offset within video page
! shl di,1 ; account for color/attribute
! mov es,ScreenSeg?? ;put video segment into ax
! mov ah,Attr% ;the color attribute will be needed
! mov cx,LineWidth%
forloop:
! inc di ;increment to the next vidram position
! mov es:[di],ah ;poke the attribute into vidram
! inc di
! loop forloop ;loop until cx = 0
! pop ds
END SUB
FUNCTION GetKey%() Public
While ISFALSE INSTAT:Wend
ky$ = Inkey$
IF len(ky$) = 2 then
GetKey% = -ascii(right$(ky$,1))
ELSE
GetKey% = ascii(ky$)
END IF
END FUNCTION
SUB ClearBuffer
DO:LOOP UNTIL INKEY$ = ""
END SUB
SUB GetDirAndFiles(Spec$, Attr%, Directory$(), DirInfo$(), FilesInfo$, TotalFiles%)
IF Attr% <> %SubDir THEN Attr% = 33
DIM FileName AS STRING * 8
DIM Ext AS STRING * 4
DirFile$ = DIR$(Spec$,Attr%)
IF DirFile$ <> "" THEN
GetDirInfo DirDate$,DirTime$,DirSize???,DirAttr?
IF Attr% = 16 AND DirAttr? = 16 THEN
INCR TotalFiles%
Directory$(TotalFiles%) = DirFile$
LSET FileName$ = Extract$(DirFile$,".")
LSET Ext$ = Extension$(DirFile$)
IsDir$ = "
"
DirInfo$(TotalFiles%) = " " + FileName$ + Ext$ + " " + IsDir$ + " " + " "+DirDate$ + " " + DirTime$
ELSEIF Attr% <> 16 AND DirAttr? <> 16 THEN
INCR TotalFiles%
Directory$(TotalFiles%) = DirFile$
LSET FileName$ = Extract$(DirFile$,".")
LSET Ext$ = Extension$(DirFile$)
IsDir$ = " "
DirInfo$(TotalFiles%) = " " + FileName$ + Ext$ + " " + IsDir$ + USING$("########",DirSize???) + " "+DirDate$ + " " + DirTime$
END IF
END IF
DO
DirFile$ = DIR$
IF DirFile$ <> "" THEN
GetDirInfo DirDate$,DirTime$,DirSize???,DirAttr?
IF Attr% = 16 AND DirAttr? = 16 THEN
INCR TotalFiles%
Directory$(TotalFiles%) = DirFile$
LSET FileName$ = Extract$(DirFile$,".")
LSET Ext$ = Extension$(DirFile$)
IsDir$ = ""
DirInfo$(TotalFiles%) = " " + FileName$ + Ext$ + " " + IsDir$ + " " + " "+DirDate$ + " " + DirTime$
ELSEIF Attr% <> 16 AND DirAttr? <> 16 THEN
INCR TotalFiles%
Directory$(TotalFiles%) = DirFile$
LSET FileName$ = Extract$(DirFile$,".")
LSET Ext$ = Extension$(DirFile$)
IsDir$ = " "
DirInfo$(TotalFiles%) = " " + FileName$ + Ext$ + " " + IsDir$ + USING$("########",DirSize???) + " "+DirDate$ + " " + DirTime$
END IF
ELSE
EXIT LOOP
END IF
LOOP
FilesInfo$ = Spec$ + ":" + STR$(TotalFiles%)+" Directories And Files"
DirInfo$(0) = MKWRD$(TotalFiles%)
Directory$(0) = MKWRD$(TotalFiles%)
END SUB
SUB GetRegDir(Spec$,Attr%,Directory$(),TotalFiles%)
DirFile$ = DIR$(Spec$,Attr%)
IF DirFile$ <> "" THEN
INCR FileNum%
Directory$(FileNum%) = DirFile$
ELSE
TotalFiles% = 0
EXIT SUB
END IF
DO
DirFile$ = DIR$
IF DirFile$ <> "" THEN
INCR FileNum%
Directory$(FileNum%) = DirFile$
ELSE
EXIT SUB
END IF
LOOP
END SUB
FUNCTION Extension$(File$)
FOR I% = LEN(File$) TO 1 STEP -1
Period$ = MID$(File$,I%,1)
IF Period$ = "." THEN Extension$ = MID$(File$,I%):EXIT FUNCTION
NEXT I%
END FUNCTION
FUNCTION Trim$(S$)
Trim$ = Ltrim$(Rtrim$(S$))
END FUNCTION
FUNCTION GetFileName$(F$)
FOR I% = LEN(F$) TO 1 STEP -1
Char$ = MID$(F$,I%,1)
IF Char$ = "\" OR CHAR$ = "/" THEN
GetFileName$ = File$
EXIT FUNCTION
ELSE
File$ = Char$ + File$
END IF
NEXT I%
GetFileName$ = File$
END FUNCTION
FUNCTION GetDirectory$(D$)
Ln% = LEN(D$)
FOR I% = Ln% TO 1 STEP -1
Char$ = MID$(D$,I%,1)
IF Char$ = "\" OR CHAR$ = "/" THEN EXIT FOR
NEXT I%
IF I% <> 3 THEN
TheDir$ = LEFT$(D$,I%-1)
ELSE
TheDir$ = LEFT$(D$,I%)
END IF
GetDirectory$ = TheDir$
END FUNCTION
FUNCTION GetLastDir$(D$)
Ln% = LEN(D$)
Slash$ = RIGHT$(D$,1)
IF Slash$ = "\" OR Slash$ = "/" THEN DECR Ln%
FOR I% = Ln% TO 1 STEP -1
Char$ = MID$(TheDir$,I%,1)
IF Char$ = "\" OR CHAR$ = "/" THEN EXIT FOR
NEXT I%
IF I% <> 3 THEN
TheDir$ = INDEX$(D$,I%,Ln%)
ELSE
TheDir$ = LEFT$(D$,I%)
END IF
GetLastDir$ = TheDir$
END FUNCTION
FUNCTION INDEX$(M$,StartPos%,LastPos%)
INDEX$ = MID$(M$,StartPos%,LastPos% - StartPos% + 1)
END FUNCTION
FUNCTION GetDirAndSlash$(D$)
Ln% = LEN(D$)
FOR I% = Ln% TO 1 STEP -1
Char$ = MID$(D$,I%,1)
IF Char$ = "\" OR CHAR$ = "/" THEN EXIT FOR
NEXT I%
IF I% <> 3 THEN
TheDir$ = LEFT$(D$,I%)
ELSE
TheDir$ = LEFT$(D$,I%)
END IF
GetDirAndSlash$ = TheDir$
END FUNCTION
FUNCTION AddSlash$(D$)
TheDir$ = TrueName$(D$)
IF LEN(TheDir$) > 3 AND RIGHT$(TheDir$,1) <> "\" THEN
AddSlash$ = TheDir$ + "\"
ELSE
AddSlash$ = TheDir$
END IF
END FUNCTION
FUNCTION FileDirExist%(d$)
Ln% = LEN(D$)
FOR I% = Ln% TO 1 STEP -1
Char$ = MID$(D$,I%,1)
IF Char$ = "\" OR CHAR$ = "/" THEN EXIT FOR
NEXT I%
FileDirExist% = I%
END FUNCTION
SUB PushDir(Directory$)
IF Directory$ = "" THEN EXIT SUB
INCR StackPos%
DirStack$(StackPos%) = Directory$
IF DirExist%(TrueDir$) = 0 THEN MKDIR TrueDir$
END SUB
SUB PopDir()
DECR StackPos%
END SUB
FUNCTION TrueDir$()
D$ = DirStack$(1)
FOR I% = 2 to StackPos%
IF RIGHT$(DirStack$(I% -1),1) <> "\" THEN
D$ = D$ + "\" + DirStack$(I%)
ELSE
D$ = D$ + DirStack$(I%)
END IF
NEXT I%
TrueDir$ = D$
END FUNCTION
SUB PushDir2(Directory$,Stack$(),StackPos2%) PUBLIC
IF Directory$ = "" THEN EXIT SUB
INCR StackPos2%
Stack$(StackPos2%) = Directory$
END SUB
SUB PopDir2(StackPos2%) PUBLIC
DECR StackPos2%
END SUB
FUNCTION TrueDir2$(Stack$(), StackPos2%) PUBLIC
D$ = Stack$(1)
FOR I% = 2 to StackPos2%
IF RIGHT$(Stack$(I% -1),1) <> "\" THEN
D$ = D$ + "\" + Stack$(I%)
ELSE
D$ = D$ + Stack$(I%)
END IF
NEXT I%
TrueDir2$ = D$
END FUNCTION
FUNCTION DirExist%(Directory$)
DirName$ = DIR$(Directory$,16)
IF DirName$ = "" THEN EXIT FUNCTION
Exists% = ATTRIB(Directory$)
Exists% = BIT(Exists%,4)
IF Exists% THEN DirExist% = 1
END FUNCTION
FUNCTION FileExist%(Directory$)
D$ = DIR$(Directory$)
IF D$ <> "" THEN FileExist% = 1
END FUNCTION
FUNCTION TrueName$(Directory$)
DIM DirName2 AS STRING * 128
DirName$ = Directory$ +CHR$(0)
DirNamePtr??? = STRPTR32(DirName$)
DirNamePtr2??? = VARPTR32(DirName2$)
DosError?? = 0
!PUSH DS
!LDS SI,DirNamePtr???
!LES DI,DirNamePtr2???
!MOV AH,&H60
!INT &H21
!POP DS
!JNC NoError
!MOV DosError??,AX
NoError:
TrueName$ = EXTRACT$(DirName2$,CHR$(0))
END FUNCTION
FUNCTION CURDRIVE$
Curdrive$ = LEFT$(CURDIR$,1)
END FUNCTION
FUNCTION MODTYPE??(Number%,ModNumber%)
M% = Number% MOD ModNumber%
IF M% = 0 THEN
ModType% = ModNumber%
ELSE
ModType% = M%
END IF
END FUNCTION
SUB LzhView(LzhFile$,ArchiveFiles$(),ArchiveInfo$(), FilesInfo$, Success%)
DIM Lzh AS LZHHead
DIM FileName AS STRING * 8
DIM Ext AS STRING * 4
FilePos??? = 0: QUIT% = 0
Handle% = FREEFILE
OPEN LzhFile$ FOR BINARY AS Handle%
RestOfFileSize??? = LOF(Handle%)
IF RestOfFileSize??? = 0 THEN
CLOSE Handle%
PRINT LzhFile$+" has an FileSize of Zero !"
Success% = 0
EXIT SUB
END IF
DO
GET Handle%,FilePos???,Lzh
IF Lzh.Id1 = "-lh" Or Lzh.Id1 = "-lz" Or Lzh.Id1 = "-lZ" THEN
IF Lzh.HeadSize AND (Lzh.HeadSize < RestOfFileSize???) THEN
Get Handle%,FilePos??? + Lzh.HeadSize,DirLen??
SEEK Handle%,FilePos??? + Lzh.HeadSize+3
IF DirLen?? > 0 AND DirLen?? < 256 THEN
GET$ Handle%,DirLen??-3,Directory$
REPLACE CHR$(255) WITH "\" IN Directory$
ELSE
Directory$ = ""
END IF
INCR FilePos???, Lzh.CompressSize + Lzh.HeadSize + 2
DECR RestOfFileSize???, FilePos???
INCR FileNumber??
File$ = LEFT$(Lzh.FileName,Lzh.FileNameLen)
LSET FileName$ = Extract$(File$,".")
LSET Ext$ = Extension$(File$)
GetDateAndTime Lzh.Filedate,Lzh.FileTime,Filedate$,FileTime$
IF DirLen?? THEN
DirSign$ = " + "
ELSE
DirSign$ = " "
END IF
ArchiveFiles$(FileNumber??) = Directory$ + File$
ArchiveInfo$(FileNumber??) = DirSign$ + FileName$ + Ext$ + USING$("########",Lzh.UnCompressSize) + " " + Filedate$ + " "+FileTime$
END IF
ELSE
INCR FilePos???, 2
DECR RestOfFileSize???, FilePos???
END IF
Loop UNTIL Lzh.HeadSize = 0 Or Lzh.HeadSize > RestOfFileSize??? OR FilePos??? = RestOfFileSize???
Close Handle%
FilesInfo$ = LzhFile$ + ":" + STR$(FileNumber??)+" Files"
ArchiveFiles$(0) = MKWRD$(FileNumber??)
ArchiveInfo$(0) = MKWRD$(FileNumber??)
IF FileNumber?? > 1 THEN ARRAY SORT ArchiveFiles$(1) FOR FileNumber??,TAGARRAY ArchiveInfo$()
Success% = 1
END SUB
SUB ZipView(ZipFile$,ArchiveFiles$(),ArchiveInfo$(),FilesInfo$,Success%) ' View the ZIP File
DIM Zip AS ZipType
DIM FileName AS STRING * 8
DIM Ext AS STRING * 4
FileNumber?? = 0
Handle% = FREEFILE
OPEN ZipFile$ FOR BINARY AS Handle%
FileSize??? = LOF(Handle%)
IF FileSize??? = 0 THEN ' Check if files exists
?ZipFile;" has an FileSize of Zeor !" ' if not, exit
CLOSE Handle%
Success% = 0
EXIT SUB
END IF
GET$ Handle%,2,PK$ ' Read File Header
IF PK$ = "PK" THEN
FilePos??? = 0
ELSE
SEEK Handle%,2
GET$ Handle%,2,PK$ ' Read File Header
IF PK$ = "PK" THEN
FilePos??? = 2
ELSE
Success% = 0
EXIT SUB
END IF
END IF
DO
GET Handle%,FilePos???,Zip ' Read File Header
IF (Zip.Signature = %Sig) THEN
INCR FilePos???, Zip.CompressSize + 30 + Zip.FileNameLen + ZIP.ExtraField
INCR FileNumber??
GET$ Handle%,Zip.FileNameLen,File$
TheFile$ = GetFileName$(File$)
IF TheFile$ = "" THEN
DECR FileNumber??
ITERATE DO
END IF
LSET FileName$ = Extract$(TheFile$,".")
LSET Ext$ = Extension$(File$)
GetDateAndTime Zip.Filedate,Zip.FileTime,Filedate$,FileTime$
ArchiveFiles$(FileNumber??) = File$
IF FileDirExist%(File$) THEN
DirSign$ = " + "
ELSE
DirSign$ = " "
END IF
ArchiveInfo$(FileNumber??) = DirSign$ + FileName$ + Ext$ + USING$("########",Zip.UnCompressSize) + " "+Filedate$+" "+FileTime$
END IF
LOOP WHILE Zip.Signature = %Sig
CLOSE Handle%
FilesInfo$ = ZipFile$ + ":" + STR$(FileNumber??)+" Files"
ArchiveInfo$(0) = MKWRD$(FileNumber??) 'Total Number of FIles
ArchiveFiles$(0) = MKWRD$(FileNumber??)
IF FileNumber?? > 1 THEN ARRAY SORT ArchiveFiles$(1) FOR FileNumber??,TAGARRAY ArchiveInfo$()
Success% = 1
END SUB
SUB GetDirInfo(DirDate$,DirTime$,DirSize???,DirAttrib?) PUBLIC
LOCAL DirDate??,DirTime??,DirAttr?,Dsize???
! mov AX, &H2F00 ; function 2Fh, get DTA location
! int &H21 ; call DOS
! MOV AX,ES:[BX + 24]
! MOV DirDate??,AX
! MOV AX,ES:[BX + 22]
! MOV DirTime??,AX
! MOV AX,ES:[BX +26]
! MOV DSize???[0],AX
! MOV AX,ES:[BX +28]
! MOV DSize???[2],AX
! MOV AL,ES:[BX +21]
! MOV DirAttr?,AL
DirSize??? = DSize???
DirAttrib? = DirAttr?
GetDateAndTime DirDate??,DirTime??,DirDate$,DirTime$
END SUB
SUB GetDateAndTime(Filedate??,FileTime??,Filedate$,FileTime$) PUBLIC
Year?? = (Filedate?? AND &B1111111000000000):SHIFT RIGHT Year??,9
INCR Year??,1980
Month?? = Filedate?? AND &B0000000111100000:SHIFT RIGHT Month??,5
Day?? = Filedate?? AND &B0000000000011111
Hours?? = FileTime?? AND &B1111100000000000:SHIFT RIGHT Hours??,11
Minutes?? = FileTime?? AND &B0000011111100000:SHIFT RIGHT Minutes??,5
Seconds?? = (FileTime?? AND &B0000000000011111) * 2
Month$ = LTRIM$(STR$(Month??))
Day$ = LTRIM$(STR$(Day??))
IF LEN(Month$) = 1 THEN Month$="0"+Month$
IF LEN(Day$) = 1 THEN Day$ = "0"+Day$
'IF Hours?? > 12 THEN
' Hours?? = Hours?? -12:AmPm$ = "p & "
'ELSE
' AmPm$ = "a & "
'END IF
Hours$ = LTRIM$(STR$(Hours??))
Minutes$ = LTRIM$(STR$(Minutes??))
Seconds$ = LTRIM$(STR$(Seconds??))
IF LEN(Hours$) = 1 THEN Hours$="0"+Hours$
IF LEN(Minutes$) = 1 THEN Minutes$="0"+Minutes$
IF LEN(Seconds$) = 1 THEN Seconds$="0"+Seconds$
Filedate$ = Month$ + "-" + Day$ + "-" + LTRIM$(STR$(Year??))
FileTime$ = Hours$ + ":" + Minutes$ + ":" + Seconds$
'FileTime$ = Hours$ + ":" + Minutes$ + AmPm$ + Seconds$ +"s"
END SUB
SUB Viewer(ViewFileName$)
DIM LinePt???(32700)
NextHandle% = FREEFILE
OPEN ViewFIleName$ FOR INPUT AS NextHandle%
DO
INCR I???
LinePt???(I???) = SEEK(NextHandle%)
LINE INPUT #NextHandle%,Dummy$
LOOP UNTIL EOF(NextHandle%)
LinePt???(0) = I???
ViewFile LinePt???()
CLOSE NextHandle%
END SUB
SUB ViewFile(FileLines???())
DIM PrintLine AS STRING * 80,Lines AS STRING * 1000
SHARED LineSeg??,LinePtr??
LineSeg?? = VARSEG(Lines$)
LinePtr?? = VARPTR(Lines$)
DisplayLine% = 23
PrintLine$ = SPACE$(80)
LowFile& = 1:HiFile& = 23
TotalLines& = FileLines???(0)
DisPlayPos% = 1
HorzPos% = 1
Choice% = 1
IF TotalLines& < DisplayLine% THEN HiFile& = TotalLines&
BottomDisplayLine% = DisplayLine%
COLOR 7,1
CLS
COLOR 0,7
LOCATE 1,1:PRINT SPACE$(80);
LOCATE 25,1:PRINT SPACE$(80);
COLOR 7,1
DO
COLOR 15, 1
LinePos% = 0
IF TotalLines& < 23 THEN BottomDisplayLine% = TotalLines&
IF ScrollIt% = 0 THEN
WAIT &H3DA,8
FOR ViewLines??? = LowFile& TO HiFile&
INCR LinePos%
SEEK NextHandle%,FileLines???(ViewLines???)
Line Input #NextHandle%, LineInput$
REPLACE CHR$(9) WITH " " IN LineInput$
Lines$ = LineInput$
IF LinePos% = DisplayPos% THEN
QuickPrintLine 1 + LinePos%,HorzPos%,71
IF Find% THEN PrintAtr 1 + LinePos%, Find%-HorzPos% + 1,SearchLen%, 48
ELSE
QuickPrintLine 1 + LinePos%, HorzPos%,23
END IF
NEXT ViewLines???
FOR I% = LinePos% + 1 To DisplayLine%
QPRINT 1 + I%, 1 ,PrintLine$,23
NEXT I%
ELSE
SEEK NextHandle%,FileLines???(Choice&)
Line Input #NextHandle%, LineInput$
REPLACE CHR$(9) WITH " " IN LineInput$
Lines$ = LineInput$
QuickPrintLine 1 + DisplayPos%, HorzPos% ,71
END IF
COLOR 0,7
LOCATE 1,1
PRINT "ViewFile";
LOCATE 1,10
PRINT ;Choice&;
LOCATE 1,18
PRINT ;TotalLines&;
LOCATE 1,27:PRINT HorzPos%;
LOCATE 1,34:PRINT "1000";
COLOR 7,1
ScrollIt% = 0
ClearBuffer
FindLine% = 0:Find% = 0:SearchLen% = 0
DO: ky$ = UCASE$(INKEY$): LOOP WHILE ky$ = ""
Ky% = ASC(Ky$)
IF Ky%= 0 THEN Ky% = -ASC(Right$(ky$,1))
SELECT CASE Ky%
CASE %RightArrow
IF HorzPos% < 1000 THEN INCR HorzPos%
CASE %LeftArrow
IF HorzPos% > 1 THEN DECR HorzPos%
CASE %Escape
EXIT DO
CASE %Home
Choice& = 1:LowFile& = 1
HiFile& = BottomDisplayLine%
DisplayPos% = 1
CASE %EndKey
Choice& = TotalLines&
DisplayPos% = ModType2??(Choice&, BottomDisplayLine%)
LowFile& = Choice& - DisplayPos% + 1
HiFile& = TotalLines&
CASE %PageDown
INCR Choice&, DisplayLine%
INCR LowFile&,DisplayLine%
HiFile& = LowFile& + BottomDisplayLine% -1
IF HiFile& > TotalLines& THEN HiFile& = TotalLines&
IF Choice& > TotalLines& THEN
Choice& = TotalLines&
DisplayPos% = ModType2??(Choice&, BottomDisplayLine%)
LowFile& = Choice& - DisplayPos% + 1
HiFile& = TotalLines&
END IF
CASE %PageUp
DECR Choice&,DisplayLine%
DECR LowFile&,DisplayLine%
HiFile& = LowFile& + DisplayLine% -1
IF LowFile& < 1 THEN LowFile& = 1:HiFile& = BottomDisplayLine%
IF Choice& <=1 THEN
Choice& = 1
LowFile& = 1
HiFile& = BottomDisplayLine%
DisplayPos% = 1
END IF
CASE %DownArrow
INCR Choice&
IF Choice& <= TotalLines& THEN
INCR DisplayPos%
ELSE
Choice& = TotalLines&
END IF
IF DisplayPos% > BottomDisplayLine% THEN
DisplayPos% = BottomDisplayLine%
LowFile& = Choice& -BottomDisplayLine% + 1
IF HiFile& >= TotalLines& THEN
HiFile& = TotalLines&
ELSE
HiFile& = LowFile& + BottomDisplayLine% -1
END IF
PrintAtr BottomDisplayLine%+1, 1, 80, 23
Scroll 1, 0, BottomDisplayLine%, 79, 1, 23, %Up
ScrollIt% = 1
END IF
CASE %UpArrow
DECR Choice&
DECR DisplayPos%
IF Choice& <=1 THEN
Choice& = 1
LowFile& = 1
HiFile& = BottomDisplayLine%
DisplayPos% = 1
ELSE
IF DisplayPos% < 1 THEN
DisplayPos% = 1
LowFile& = Choice&
HiFile& = Choice& + BottomDisplayLine% -1
IF HiFile& >= TotalLines& THEN
HiFile& = TotalLines&
ELSE
HiFile& = LowFile& + BottomDisplayLine% -1
END IF
PrintAtr 2, 1, 80, 23
Scroll 1,0, BottomDisplayLine%,79, 1,23,%Down
ScrollIt% = 1
END IF
END IF
CASE 70 'F
LOCATE 25,1:COLOR 0,7
PRINT Space$(50);
LOCATE 25,1
LINE INPUT; "FIND >";Search$
COLOR 7,1
Search$ = UCASE$(Search$)
FOR I??? = Choice& + 1 TO TotalLines&
SEEK NextHandle%,FileLines???(I???)
Line Input #NextHandle%, LineInput$
REPLACE Chr$(9) WITH " " IN LineInput$
Find% = BINSTR% (1,UCASE$(LineInput$),Search$)
IF Find% THEN EXIT FOR
NEXT I???
IF Find% = 0 THEN
FOR I??? = 1 TO Choice& -1
SEEK NextHandle%,FileLines???(I???)
Line Input #NextHandle%, LineInput$
REPLACE Chr$(9) WITH " " IN LineInput$
Find% = BINSTR% (1,UCASE$(LineInput$),Search$)
IF Find% THEN EXIT FOR
NEXT I???
END IF
IF Find% THEN
GOSUB ResetValues
END IF
EXIT SELECT
CASE 65 'N
FOR I??? = Choice& + 1 TO TotalLines&
SEEK NextHandle%,FileLines???(I???)
Line Input #NextHandle%, LineInput$
REPLACE Chr$(9) WITH " " IN LineInput$
Find% = BINSTR% (1,UCASE$(LineInput$),Search$)
IF Find% THEN EXIT FOR
NEXT I???
IF Find% = 0 THEN
FOR I??? = 1 TO Choice& -1
SEEK NextHandle%,FileLines???(I???)
SEEK NextHandle%,FileLines???(I???)
Line Input #NextHandle%, LineInput$
REPLACE Chr$(9) WITH " " IN LineInput$
Find% = BINSTR% (1,UCASE$(LineInput$),Search$)
IF Find% THEN EXIT FOR
NEXT I???
END IF
IF Find% THEN
GOSUB ResetValues
END IF
EXIT SELECT
CASE ELSE
EXIT DO
END SELECT
LOOP
COLOR 7,0
EXIT SUB
ResetValues:
SearchLen% = LEN(Search$)
Choice& = I???
FindLine% = I???
DisplayPos% = ModType2??(Choice&, BottomDisplayLine%)
LowFile& = Choice& - DisplayPos% + 1
HiFile& = LowFile& + BottomDisplayLine% -1
IF LowFile& < 1 THEN LowFile& = 1:HiFile& = BottomDisplayLine%:DisplayPos% = Choice&
IF HiFile& > TotalLines& THEN HiFile& = TotalLines&
IF HorzPos% > Find% THEN HorzPos% = 1
IF Find% > HorzPos% + 80 -1 THEN HorzPos% = Find% -80 + SearchLen% + 80\SearchLen% -1
RETURN
END SUB
FUNCTION ModType2??(Number&,ModNumber%)
M?? = Number& MOD ModNumber%
IF M?? = 0 THEN
ModType2?? = ModNumber%
ELSE
ModType2?? = M??
END IF
END FUNCTION
SUB QuickPrintLine(BYVAL Row , BYVAL HorzPos%,BYVAL attr) PUBLIC
! push DS ; save DS for PowerBASIC
! mov ax,Row% ; get the row
! dec al ; convert row to zero base
! mov bl,80 ; get the number of cols
! mul bl ; multiply # of cols * rows
! mov di,ax ; offset within video page
! shl di,1 ; account for color/attribute
! mov CX,1000
! mov BX, 80
! sub CX, HorzPos%
! CMP CX, 80
! Jg GoAhead
! SUB BX, CX
! JMP DoIt
GoAhead:
! MOV CX,80
! MOV BX,0
DoIt:
! MOV SI, LinePtr?? ; put segment in DS
! MOV DS, LineSeg??
! add SI, HorzPos%
! DEC SI
! mov ES, ScreenSegment?? ; move to ES
! mov AH, attr ; put attribute in AH
! jcxz RestOfLine ; if it's Null, exit
WriteChar2:
! lodsb ; get Char from string
! stosw ; write Char and attribute to screen
! loop WriteChar2 ; do it all CX times
RestOfLine:
! MOV AH, attr ; put attribute in AH
! MOV AL,32
! MOV CX,BX
! jcxz Quit3 ; if it's Null, Do Rest of Line
! REP stosw
Quit3:
! pop DS ; restore DS for PowerBASIC
END SUB
%SMALLEST.PATTERN = 2
%SMALLEST.BUFFER = 4
FUNCTION BINSTR%(TheStart%, Target$, Rule$) PUBLIC
' ES:DI Target$
' DS:SI Rule$
PatLen% = LEN(Rule$)
BuffLen% = LEN(Target$)
IF BuffLen% < %SMALLEST.BUFFER THEN
FUNCTION = INSTR(TheStart%, Target$, Rule$)
EXIT FUNCTION
ELSE
IF PatLen% < %SMALLEST.PATTERN THEN
FUNCTION = INSTR(TheStart%, Target$, Rule$)
EXIT FUNCTION
END IF
END IF
IF TheStart% > BuffLen% THEN ' we might as well not even bother
EXIT FUNCTION
END IF
StackSeg?? = 0 ' We do this for later inline ASM
PatSeg?? = STRSEG(Rule$)
PatPtr?? = STRPTR(Rule$)
BuffSeg?? = STRSEG(Target$)
BuffPtr?? = STRPTR(Target$) + TheStart%
TrueBuffPtr?? = BuffPtr??
! cld
! push sp
! push si ;preserve caller's register variables
! push di
! push es
! push ds
! sub sp, 256*2 ;allocate space for SkipTable on our
! ; stack
! mov ax,PatLen%
! and ax,ax ;return an instant match if the
! jz InstantMatch ; pattern 0-length
! mov StackSeg??,ss
! mov es,StackSeg??
! mov di,sp ;point to SkipBuffer
! mov cx,256
! rep stosw
! mov es,BuffSeg??
! mov ds,PatSeg??
! dec ax ;from now on, we only need
! mov PatLen%,ax ; PatLen% - 1
' Point to last (rightmost) byte of first potential pattern match
' location in buffer.
! add BuffPtr??, ax
! sub BuffLen%,ax
! jbe NoMatch
! mov si,PatPtr?? ;point to start of pattern
! and ax,ax ;are there any skips to set?
! jz SetSkipDone ;no
! mov di,sp ;point to SkipBuffer
SetSkipLoop:
! sub bx,bx ;prepare for word addressing off byte value
! mov bl,ds:[si] ;get the next pattern byte
! inc si ;advance the pattern pointer
! shl bx,1 ;prepare for word look-up
! mov ss:[di+bx],ax ;set the skip value when this byte value
! ;is the mismatch value in the buffer
! dec ax
! jnz SetSkipLoop
SetSkipDone:
! mov dl,ds:[si] ;DL=rightmost pattern byte from now on
! dec si ;point to next-to-rightmost byte of pattern
! mov PatPtr??,si ; from now on
' Search the buffer.
! std ;for backward REPZ CMPSB
! mov di,BuffPtr?? ;point to the first search location
! mov cx,BuffLen% ;# of match locations to check
SearchLoop:
! mov si,sp ;point SI to SkipTable
' Skip through until there's a match for the rightmost pattern
' byte.
' We jump this way to avoid a FIXUP OVERFLOW under PB...
! jmp QuickSearchLoop
InstantMatch:
! mov ax,BuffPtr??
! jmp short Done
' Compare the pattern and the buffer location, searching from high
' memory toward low (right to left).
FullCompare:
! mov BuffPtr??,di ;save the current state of
! mov BuffLen%,cx ; the search
! mov cx,PatLen% ;# of bytes yet to compare
! jcxz Matched ;done if there was only one character
! mov si,PatPtr?? ;point to next-to-rightmost bytes
! dec di ; of buffer location and pattern
! repz cmpsb ;compare the rest of the pattern
! jz Matched ;that's it; we've found a match
' It's a mismatch; let's see what we can learn from it.
! inc di ;compensate for 1-byte overrun of REPZ CMPSB;
! ; point to mismatch location in buffer
! ; # of bytes that did match.
! mov si,BuffPtr??
! sub si,di
! sub bx,bx ;prepare for word addressing off byte value
! mov bl,es:[di] ;get the value of the mismatch byte in buffer
! add bx,bx ;prepare for word look-up
! add bx,sp ;SP points to SkipTable
! mov cx,ss:[bx] ;get the skip value for this mismatch
! mov ax,1 ;assume we'll just advance to the next
! ; potential match location
! sub cx,si ;is the skip far enough to be worth taking?
! jna MoveAhead ;no, go with the default advance of 1
! mov ax,cx ;yes; this is the distance to skip ahead from
! ; the last potential match location checked
MoveAhead:
' Skip ahead and perform the next comparison, if there's any buffer
' left to check.
! mov di,BuffPtr??
! add di,ax ;BuffPtr?? += Skip
! mov cx,BuffLen%
! sub cx,ax ;BuffLen% -= Skip;
! ja SearchLoop ;continue if any buffer left
' Return a NULL pointer for no match.
NoMatch:
! sub ax,ax
! jmp short Done
' Return start of match in buffer (BuffPtr?? - (PatLen% - 1)).
Matched:
! mov ax, BuffPtr??
! sub ax, TrueBuffPtr??
! sub ax, PatLen%
! les bx, [bp+&HE]
! add ax, es:[bx] ; Parameter: TheStart%
! inc ax
! mov FUNCTION, ax
Done:
! cld
! add sp,256*2 ;deallocate space for SkipTable
! pop ds
! pop es
! pop di ;restore caller's register variables
! pop si
! pop sp
EXIT FUNCTION
QuickSearchLoop:
! mov bl,es:[di] ;rightmost buffer byte at this location
! cmp dl,bl ;does it match the rightmost pattern byte?
! jz FullCompare ;yes, so keep going
! sub bh,bh ;convert to a word
! add bx,bx ;prepare for look-up in SkipTable
! mov ax,ss:[si+bx] ;get skip value from skip table for this
! ; mismatch value
! add di,ax ;BuffPtr?? += Skip;
! sub cx,ax ;BuffLen% -= Skip;
! ja QuickSearchLoop;continue if any buffer left
! jmp short NoMatch
' Return a pointer to the start of the buffer (for 0-length
' pattern).
END FUNCTION