📄 filesel.asm
字号:
include ..\cwlib.inc
scode
;-------------------------------------------------------------------------
;
;Display a file selector and get a list of file names from the user.
;
;On Entry:
;
;C style stack parameters as follows,
;
;flags - Flags, bit significant if set.
; 0 - Allow multiple selections with SHIFT.
; 1 - Allow typed name.
;titleptr - Title pointer, normal ASCII zero terminated string.
;pathptr - Path pointer, normal ASCII zero terminated string.
;maskptr - Masks pointer, list of normal ASCII zero terminated strings, -1
; to terminate list.
;nameptr - Default name pointer, normal ASCII zero terminated string.
;filestart - Start position of file list.
;maskstart - Start position of mask list.
;masknum - Mask number to use by default.
;drivestart - Start position of drive list.
;
;On Exit:
;
;EAX - Exit code.
; 0 - no problems.
; 1 - CANCEL'd.
; 2 - no files selected.
; 3 - ran out of memory.
;
;EBX - File list start position.
;ECX - Mask list start position.
;EDX - Mask number.
;ESI - Drive list start position.
;EDI - List of file names.
;
;ALL other registers preserved.
;
;Notes:
;
;Expects SYSTEM font to have been loaded.
;
dlgFileSelector:
public dlgFileSelector
_dlgFileSelector_ proc syscall flags:dword, titleptr:dword, pathptr:dword, \
maskptr:dword, nameptr:dword, filestart:dword, maskstart:dword, \
masknum:dword, drivestart:dword
pushad
;
mov eax,filestart
mov _FS_FirstFile,eax
mov _FS_CenterFile,0
;
mov eax,titleptr
mov esi,((size Dlg)*dFILE_TITLE)+(size DlgMain)+offset dFileSelector
mov Dlg_Text[esi],eax
mov esi,((size Dlg)*dFILE_PATH)+(size DlgMain)+offset dFileSelector
mov Dlg_Text[esi],offset _FS_PrintPath
;
mov _FS_PrintPath,0 ;clear path for initial print.
mov _FS_FileList,0 ;clear file list pointer.
mov _FS_FirstTyped,0 ;reset typed name cursor to start.
mov _FS_TypedFocus,0 ;remove typed name focus.
;
;Setup the initial path string.
;
mov esi,pathptr ;supplied path.
mov edi,offset _FS_currentpath ;our path storage.
call CopyString
mov esi,offset _FS_currentpath ;make sure it's upper case.
call UpperString
mov edx,offset _FS_currentpath ;force specified path.
call SetPath
;
;Setup mask stuff.
;
mov _FS_TotalMasks,0 ;clear total masks.
mov esi,maskptr
@@1: lodsb
or al,al ;end of a mask yet?
jnz @@1
inc _FS_TotalMasks ;update number of masks.
cmp b[esi],-1 ;end of the list yet?
jnz @@1
mov eax,maskstart
cmp eax,_FS_TotalMasks
jc @@7
jz @@7
xor eax,eax
@@7: mov _FS_FirstMask,eax ;set list entry.
mov eax,masknum
cmp eax,_FS_TotalMasks
jc @@8
jz @@8
xor eax,eax
@@8: mov _FS_CurrentMask,eax ;set current mask.
;
;Copy typed name.
;
mov edi,offset _FS_typedname ;our name storage.
mov ecx,16/4
xor eax,eax
rep stosd
mov esi,nameptr ;supplied name.
mov edi,offset _FS_typedname ;our name storage.
call CopyString
call LenString ;get name length so we can set
mov _FS_TypedTotal,eax ;the limit.
mov b[_FS_typedname+13],128 ;default to selected.
cmp b[_FS_typedname],0
jz @@NotFocus
or _FS_TypedFocus,-1
;
;Force current extension.
;
mov esi,offset _FS_TypedName
or edi,-1
@@itc0: mov al,[esi]
inc esi
cmp al,"."
jnz @@itc1
mov edi,esi
@@itc1: cmp al,"\"
jnz @@itc2
or edi,-1
@@itc2: or al,al
jnz @@itc0
cmp edi,-1 ;any extension?
jnz @@itc6
mov edi,esi
mov b[edi-1],"."
@@itc6: mov ecx,_FS_CurrentMask ;current top of list.
mov esi,maskptr ;the mask list.
or ecx,ecx
jz @@itc4
@@itc3: mov al,[esi]
inc esi
or al,al ;end of a mask yet?
jnz @@itc3
dec ecx ;got to the entry we want yet?
jnz @@itc3
@@itc4: lodsb
cmp al,"."
jnz @@itc4
cmp b[esi],"*" ;this an ALL job?
jz @@itc5
call CopyString
@@itc5: ;
@@NotFocus: ;
mov edx,offset _FS_drivelist ;our drive list buffer.
call GetDrives ;get a list of valid drives.
mov _FS_TotalDrives,ecx ;store total number of drives.
mov esi,offset _FS_drivelist
@@sd0: add b[esi],"A" ;convert drive numbers to ASCII.
add esi,2
loop @@sd0
call GetDrive ;get current drive.
add al,"A" ;make it ASCII.
xor ecx,ecx
mov esi,offset _FS_drivelist ;our list of drives.
@@5: cmp al,[esi]
jz @@6 ;found current drive yet?
add esi,2
inc ecx ;next drive.
jmp @@5
@@6: mov _FS_CurrentDrive,ecx ;store current drive highlight position.
mov eax,drivestart
cmp eax,_FS_TotalDrives
jc @@9
jz @@9
xor eax,eax
@@9: mov _FS_FirstDrive,eax
;
;Setup main window dimensions and coords, then open it ready for action.
;
mov esi,offset dFileSelector
call DialogGetWidth ;width of main dialog.
mov _FS_mainw,eax
mov ecx,eax
shr ecx,1
call DialogGetDepth ;depth of main dialog.
mov _FS_maind,eax
mov edx,eax
shr edx,1
mov eax,VideoXResolution ;use video x resolution to
shr eax,1 ;center the selector.
sub eax,ecx
mov _FS_mainx,eax
mov eax,VideoYResolution ;use video y resolution to
shr eax,1 ;center the selector.
sub eax,edx
mov _FS_mainy,eax
;
;Open the window.
;
push 0
push _FS_maind
push _FS_mainw
push _FS_mainy
push _FS_mainx
push 200
push 0
call WinOpenWindow
add esp,4*7
mov _FS_window,eax
;
;Do initial draw to make sure everything starts up ok.
;
mov edi,eax
or ecx,-1
mov esi,offset dFileSelector
call DrawDialog
;
mov _FS_drawstate,-1 ;force everything to be updated.
;
;Loop point when a new path/mask/file list is needed.
;
restartloop: mov edx,offset _FS_currentpath ;force current list path.
call SetPath
;
;Extract current extension mask from the list.
;
mov ecx,_FS_CurrentMask ;current top of list.
mov esi,maskptr ;the mask list.
jecxz @@3
@@2: lodsb
or al,al ;end of a mask yet?
jnz @@2
dec ecx ;got to the entry we want yet?
jnz @@2
@@3: mov edi,offset _FS_filemask ;our storage for the mask.
call CopyString
;
;Build a file list based on current file mask and path.
;
cmp _FS_FileList,0 ;old list in memory?
jz @@4
mov esi,_FS_FileList
call Free ;release the old list.
mov _FS_FileList,0
@@4: mov edx,offset _FS_filemask
mov ecx,16
call MakeFileList ;build a new file list.
or eax,eax
jz memexit
mov _FS_FileList,eax
mov esi,eax
call ULFileList ;convert DIR's to upper etc.
call SortFileList ;sort the names.
;
;See if we need to try and center on a previous sub-directory.
;
cmp _FS_CenterFile,0 ;any name to center on?
jz @@11
;
;Try and find the name in the current file list.
;
mov ebx,_FS_FileList
mov ecx,[ebx] ;get list length.
add ebx,4+256 ;skip count and path.
xor edx,edx ;reset entry counter.
@@12: mov edi,ebx ;point to current string.
mov esi,offset _FS_CenterFile ;point to string to center on.
@@13: lodsb
call UpperChar
mov ah,al
mov al,[edi]
inc edi
call UpperChar
or ah,ah ;end of string?
jz @@15
cmp al,ah
jz @@13
@@14: inc edx ;update entry counter.
add ebx,14 ;point to next file.
loop @@12
jmp @@11 ;couldn't find it so use normal method.
@@15: or al,al ;end of file list name as well?
jnz @@14
;
;Seem to have found what we were looking for so try and center the file list
;around it.
;
sub edx,5 ;enough entries to center?
jns @@16
xor edx,edx
@@16: mov eax,_FS_FileList
mov eax,[eax] ;get number of files.
mov ebx,edx
add ebx,10
cmp ebx,eax ;too close to the bottom of the list?
jle @@17
mov edx,eax
sub edx,10
jns @@17
xor edx,edx
@@17: mov _FS_FirstFile,edx
@@11: mov _FS_CenterFile,0
;
;Make sure FirstFile isn't beyond the end of the list.
;
mov esi,_FS_FileList
mov eax,_FS_FirstFile
cmp eax,[esi]
jc @@10
jz @@10
xor eax,eax
@@10: mov _FS_FirstFile,eax
;
;Loop point when a re-draw or new file list is needed.
;
drawloop:
;
;Work out where title needs to go and print it.
;
@@ds_1: test _FS_drawstate,1 ;need to update the title?
jz @@ds_2
mov ecx,dFILE_TITLE ;use title entry details, prints
mov esi,offset dFileSelector ;the text itself.
mov edi,_FS_window
call DrawDialog ;update title button, text will
and _FS_drawstate, not 1 ;be printed as well.
;
;Set and display the current path.
;
@@ds_2: test _FS_drawstate,2 ;need to update path display?
jz @@ds_4
mov ecx,dFILE_PATH ;use path entry details.
mov esi,offset dFileSelector
call DialogGetButtonW ;get path button width.
mov edx,eax
xor ecx,ecx
mov esi,offset _FS_currentpath
mov edi,offset _FS_printpath
@@ds_2_0: lodsb ;end of path string yet?
or al,al
jz @@ds_2_1
movzx eax,al
shl eax,2
add eax,SystemFont
mov eax,[eax] ;get pointer to character.
add ecx,BM_Wide[eax] ;include this in width calculation.
cmp ecx,edx
jge @@ds_2_1 ;reached our limit so stop here.
dec esi
movsb ;copy this character.
jmp @@ds_2_0
@@ds_2_1: xor al,al
stosb ;terminate the string.
mov ecx,dFILE_PATH
mov esi,offset dFileSelector
mov edi,_FS_window
call DrawDialog ;re-draw path button, path string
and _FS_drawstate,not 2 ;will be printed as well.
;
;Display the current file list.
;
@@ds_4: test _FS_drawstate,4 ;need to re-print file list?
jz @@ds_8
mov ecx,dFILE_FILES ;use file list button details.
mov esi,offset dFileSelector
mov edi,_FS_window
call DrawDialog ;clear box ready for new print.
;
call DialogGetButtonW ;get width for selected file
mov edi,eax ;bar filling.
sub edi,4
call DialogGetButtonX ;need X co-ord so we know where
add eax,2 ;to start printing.
push eax
call DialogGetButtonY ;need Y co-ord so we know where
add eax,2 ;to start printing.
mov ebx,eax
pop ecx
;
mov esi,_FS_FileList ;get pointer to current list.
mov eax,[esi] ;get number of files in list
mov _FS_TotalFiles,eax ;and stow it away for easy access.
add esi,256+4 ;move to start of name list.
mov eax,14
mul _FS_FirstFile ;move to current start of list.
add esi,eax
xor edx,edx ;clear count so far.
@@ds_4_0: cmp edx,10
jz @@ds_4_1 ;reached limit so stop printing.
mov eax,edx
add eax,_FS_FirstFile ;check if we reached the end of
cmp eax,_FS_TotalFiles ;the file list.
jge @@ds_4_1
test b[esi+13],128 ;this a selected file?
jz @@ds_4_2
;
push FontDepth
push edi
push ebx
push ecx
mov al,251 ;convert "system" pen number into
call VideoSys2Hard ;real hardware value.
push eax
push 0
push _FS_window
call WinFillRectangle ;fill area behind this name so
add esp,4*7 ;we know it's been selected.
;
@@ds_4_2: push ebx
push ecx
push esi
push SystemFont
mov al,253 ;convert "system" pen number into
call VideoSys2Hard ;real hardware value.
push eax
push 2 ;OR it on.
push _FS_window
call WinPrintWindow ;print current file name.
add esp,4*7
add esi,14
add ebx,FontDepth
inc edx
jmp @@ds_4_0
;
@@ds_4_1: and _FS_drawstate,not 4
;
;Display the file mask list.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -