From 77889c54ce88ae81378baaca95128d9420b10b8f Mon Sep 17 00:00:00 2001 From: "Evgeny Grechnikov (Diamond)" Date: Tue, 20 Jan 2009 15:03:05 +0000 Subject: [PATCH] KFar 0.6: search capabilities git-svn-id: svn://kolibrios.org@997 a494cfbc-eb01-0410-851d-a64ba20cac60 --- programs/fs/kfar/trunk/dialogs.inc | 399 +++++++++- programs/fs/kfar/trunk/editor.inc | 234 +++++- programs/fs/kfar/trunk/filetool.inc | 1053 ++++++++++++++++++++++++++- programs/fs/kfar/trunk/kfar.asm | 467 +++++++++++- programs/fs/kfar/trunk/kfar.txt | 9 + programs/fs/kfar/trunk/search.inc | 203 ++++++ programs/fs/kfar/trunk/viewer.inc | 269 ++++++- 7 files changed, 2545 insertions(+), 89 deletions(-) create mode 100644 programs/fs/kfar/trunk/search.inc diff --git a/programs/fs/kfar/trunk/dialogs.inc b/programs/fs/kfar/trunk/dialogs.inc index a821adf22c..12118837dd 100644 --- a/programs/fs/kfar/trunk/dialogs.inc +++ b/programs/fs/kfar/trunk/dialogs.inc @@ -40,6 +40,7 @@ GenericBox: pushad ; message loop .event: +; call get_event push 10 pop eax int 40h @@ -264,6 +265,16 @@ ShowGenericBox: ; draw shadow test byte [ebx+dlgtemplate.flags], 4 jnz .noshadow + call draw_dialog_shadow +.noshadow: + popad + push dword [esp+8] + push dword [esp+8] + call DrawGenericBox + xor eax, eax + ret 8 + +draw_dialog_shadow: mov eax, [ebx+dlgtemplate.x] sub eax, [ebx+dlgtemplate.border_size_x] ja @f @@ -316,13 +327,7 @@ ShowGenericBox: add edi, [cur_width] dec edx jnz .shadow_loop -.noshadow: - popad - push dword [esp+8] - push dword [esp+8] - call DrawGenericBox - xor eax, eax - ret 8 + ret ; void __stdcall DrawGenericBox(DLGDATA* dlg, void* DlgProc) DrawGenericBox: @@ -648,9 +653,9 @@ menu_centered_in: xor ecx, ecx mov esi, [esp+20h+20] mov [ebx+40], esi - and dword [ebx+56], 0 + mov dword [ebx+56], eax @@: - cmp dword [esi+4], 0 + cmp dword [esi+4], eax jz .find_width mov esi, [esi+4] inc dword [ebx+56] @@ -1103,6 +1108,9 @@ dlgitemtemplate: ; 1 = статический текст ; 2 = кнопка ; 3 = поле редактирования +; 4 = горизонтальный разделитель +; 5 = флажок +; 6 = список .type dd ? .x1 dd ? .y1 dd ? @@ -1110,9 +1118,14 @@ dlgitemtemplate: .y2 dd ? ; Данные: ; для текста: const char* data - ASCIIZ-строка -; для кнопки: const char* data - заголовок +; для кнопки и флажка: const char* data - заголовок ; для редактора: struct {unsigned maxlength; unsigned pos; unsigned start; ; char data[maxlength+1];}* data; +; для списка: struct {listitem* curitemptr; unsigned numitems; +; listitem *head; unsigned curitem;}* data; +; head = указатель на первый отображаемый элемент, +; curitemptr = указатель на выделенный элемент, curitem = его индекс в списке (от 0) +; (где struct listitem {listitem* next; listitem* prev; char text[];};) .data dd ? .flags dd ? ; Флаги: @@ -1123,6 +1136,7 @@ dlgitemtemplate: ; 8 = элемент может иметь фокус ввода ; 10h: для кнопки = кнопка по умолчанию (Enter на не-кнопке) ; для поля ввода = данные были модифицированы +; для флажка = флажок установлен ; 20h: для поля ввода = не отображать вводимые данные (показывать '*') .size = $ end virtual @@ -1191,10 +1205,17 @@ ManagerDlgProc: jz .up cmp al, 0x50 jz .down - jecxz @f + jecxz .nobtns2 cmp [ebx+dlgitemtemplate.type], 3 jz .key_edit + cmp [ebx+dlgitemtemplate.type], 5 + jnz @f + cmp al, 0x39 + jnz @f + xor [ebx+dlgitemtemplate.flags], 10h + jmp .ret_draw @@: +.nobtns2: cmp al, 0x4B jz .left cmp al, 0x4D @@ -1386,19 +1407,9 @@ ManagerDlgProc: .draw_loop: push ecx mov eax, [ebx+dlgitemtemplate.type] - dec eax - jz .draw_text - dec eax - jz .draw_button - dec eax - jnz .draw_loop_continue - call draw_editbox - jmp .draw_loop_continue -.draw_button: - call draw_button - jmp .draw_loop_continue -.draw_text: - call draw_static_text + cmp eax, draw_functions_num + jae .draw_loop_continue + call [draw_functions + eax*4] .draw_loop_continue: pop ecx add ebx, dlgitemtemplate.size @@ -1406,6 +1417,19 @@ ManagerDlgProc: .done_draw: ret +iglobal +align 4 +label draw_functions dword + dd ManagerDlgProc.done_draw + dd draw_static_text + dd draw_button + dd draw_editbox + dd draw_h_separator + dd draw_checkbox + dd draw_listbox +draw_functions_num = ($ - draw_functions) / 4 +endg + draw_static_text: ; рисуем статический текст mov ah, [dialog_main_color] @@ -1417,7 +1441,8 @@ draw_text: mov esi, [ebx+dlgitemtemplate.data] draw_text_esi: test esi, esi - jz .ret + jz .ret2 + push eax push -1 pop ecx @@: @@ -1425,7 +1450,6 @@ draw_text_esi: cmp byte [ecx+esi], 0 jnz @b ; в ecx длина строки - push eax xor eax, eax mov edx, [ebx+dlgitemtemplate.x2] sub edx, [ebx+dlgitemtemplate.x1] @@ -1451,12 +1475,8 @@ draw_text_esi: .text_draw: push ecx push eax - mov eax, [ebx+dlgitemtemplate.x1] - add eax, [ebp+dlgtemplate.x] push edx - mov edx, [ebx+dlgitemtemplate.y1] - add edx, [ebp+dlgtemplate.y] - call get_console_ptr + call dlgitem_get_console_ptr pop edx pop ecx mov ah, [esp+5] @@ -1508,6 +1528,7 @@ draw_text_esi: pop eax mov al, ' ' rep stosw +.ret2: ret draw_button: @@ -1551,6 +1572,310 @@ draw_editbox: add esi, 12 jmp draw_text_esi +dlgitem_get_console_ptr: + mov eax, [ebx+dlgitemtemplate.x1] + mov edx, [ebx+dlgitemtemplate.y1] + mov ecx, eax + add eax, [ebp+dlgtemplate.x] + add edx, [ebp+dlgtemplate.y] + jmp get_console_ptr + +draw_h_separator: +; рисуем горизонтальный разделитель + call dlgitem_get_console_ptr +.scan: + mov al, 0xC7 + test ecx, ecx + js @f + mov al, 0xB6 + cmp ecx, [ebp+dlgtemplate.width] + jz @f + mov al, 0xC4 +@@: + stosb + jz .done + inc ecx + inc edi + cmp ecx, [ebx+dlgitemtemplate.x2] + jb .scan +.done: + ret + +draw_checkbox: +; рисуем флажок + call dlgitem_get_console_ptr + test byte [ebx+dlgitemtemplate.flags], 4 + jz @f + inc eax + mov [cursor_x], eax + mov [cursor_y], edx +@@: + mov ah, [dialog_main_color] + test byte [ebp+dlgtemplate.flags], 2 + jz @f + mov ah, [warning_main_color] +@@: + mov al, '[' + stosw + mov al, 'x' + test byte [ebx+dlgitemtemplate.flags], 10h + jnz @f + mov al, ' ' +@@: + stosw + mov al, ']' + stosw + mov al, ' ' + stosw + mov ecx, [ebx+dlgitemtemplate.x2] + sub ecx, [ebx+dlgitemtemplate.x1] + jb .ret + sub ecx, 3 + jbe .ret + mov esi, [ebx+dlgitemtemplate.data] +@@: + lodsb + test al, al + jz .ret + stosw + loop @b +.ret: + ret + +draw_listbox: +; рисуем список + call dlgitem_get_console_ptr + mov edx, [ebx+dlgitemtemplate.data] + mov esi, [edx+8] + mov eax, [ebx+dlgitemtemplate.y2] + sub eax, [ebx+dlgitemtemplate.y1] + push eax + push eax +.0: + test esi, esi + jz .listdone + push esi edi + push edx + or edx, -1 + mov ecx, [ebx+dlgitemtemplate.x2] + sub ecx, [ebx+dlgitemtemplate.x1] + inc ecx + xor eax, eax +@@: + inc edx + cmp byte [esi+8+edx], al + jnz @b +@@: + cmp ecx, edx + jae .text_draw + mov al, byte [ebx+dlgitemtemplate.flags] + and al, 3 + jz .text_align_left + cmp al, 1 + jz .text_align_center +; текст выровнен вправо + mov eax, edx + sub eax, ecx + jmp .text_draw +.text_align_center: + mov eax, edx + sub eax, ecx + shr eax, 1 + jmp .text_draw +.text_align_left: +; xor eax, eax +.text_draw: + pop edx + cmp esi, [edx] + lea esi, [esi+8+eax] + mov ah, [dialog_selected_list_color] + jz @f + mov ah, [dialog_list_color] +@@: + jecxz .next +@@: + lodsb + test al, al + jz @f + stosw + loop @b +@@: + mov al, ' ' + rep stosw +.next: + pop edi esi + add edi, [cur_width] + add edi, [cur_width] + mov esi, [esi] + dec dword [esp] + jns .0 +.listdone: + pop eax +; Линейка прокрутки + pop ecx + inc ecx + mov esi, [edx+4] + cmp ecx, esi + jae .noscrollbar + sub ecx, 2 + jbe .noscrollbar + mov eax, [edx+12] + mul ecx + div esi + push eax + mov eax, [ebx+dlgitemtemplate.x2] + add eax, [ebp+dlgtemplate.x] + mov edx, [ebx+dlgitemtemplate.y1] + add edx, [ebp+dlgtemplate.y] + call get_console_ptr + pop edx + inc edx + mov al, 0x1E + mov ah, [dialog_scroll_list_color] + mov [edi], ax + add edi, [cur_width] + add edi, [cur_width] +.2: + mov al, 0xB1 + dec edx + jz @f + mov al, 0xB0 +@@: + mov [edi], ax + add edi, [cur_width] + add edi, [cur_width] + loop .2 + mov al, 0x1F + stosw +.noscrollbar: + ret + +listbox_key: + mov edx, [ebx+dlgitemtemplate.data] + cmp al, 0x48 + jz .prev + cmp al, 0x50 + jz .next + cmp al, 0x47 + jz .home + cmp al, 0x4F + jz .end + cmp al, 0x51 + jz .pgdn + cmp al, 0x49 + jz .pgup + ret +.next: + call .calc_last_line + mov eax, [edx] + cmp dword [eax], 0 + jz @f + call .line_next +@@: + mov [edx], eax + ret +.pgdn: + call .calc_last_line + mov eax, [edx] + mov ecx, [ebx+dlgitemtemplate.y2] + sub ecx, [ebx+dlgitemtemplate.y1] +.pgdnl: + cmp dword [eax], 0 + jz @f + call .line_next + loop .pgdnl +@@: + mov [edx], eax + ret +.prev: + mov eax, [edx] + cmp dword [eax+4], 0 + jz @f + call .line_prev +@@: + mov [edx], eax + ret +.pgup: + mov eax, [edx] + mov ecx, [ebx+dlgitemtemplate.y2] + sub ecx, [ebx+dlgitemtemplate.y1] +; inc ecx +.pgupl: + cmp dword [eax+4], 0 + jz @f + call .line_prev + loop .pgupl +@@: + mov [edx], eax + ret +.home: + mov eax, [edx] +@@: + cmp dword [eax+4], 0 + jz @f + mov eax, [eax+4] + jmp @b +@@: + mov [edx], eax + mov [edx+8], eax + and dword [edx+12], 0 + ret +.end: + mov eax, [edx] +@@: + cmp dword [eax], 0 + jz @f + mov eax, [eax] + jmp @b +@@: + mov [edx], eax + mov ecx, [ebx+dlgitemtemplate.y2] + sub ecx, [ebx+dlgitemtemplate.y1] + jz .e1 +.e2: + mov eax, [eax+4] + loop .e2 +.e1: + mov [edx+8], eax + mov eax, [edx+4] + dec eax + mov [edx+12], eax + ret + +.line_prev: + cmp eax, [edx+8] + mov eax, [eax+4] + jnz @f + mov [edx+8], eax +@@: + dec dword [edx+12] + ret +.calc_last_line: + mov esi, [edx+8] + mov ecx, [ebx+dlgitemtemplate.y2] + sub ecx, [ebx+dlgitemtemplate.y1] + jz .clldone +@@: + mov esi, [esi] + test esi, esi + jz @f + loop @b +.clldone: + ret +.line_next: + cmp eax, esi + mov eax, [eax] + jnz @f + push eax + mov eax, [edx+8] + mov eax, [eax] + mov [edx+8], eax + pop eax + mov esi, eax +@@: + inc dword [edx+12] + ret + ; void __stdcall SayNoMem(void); SayNoMem: or dword [nomem_dlgdata+4], -1 @@ -1559,6 +1884,18 @@ SayNoMem: call DialogBox ret +; int __stdcall ConfirmCancel(void); +; return value: 0 = the user is sure, nonzero = the user wants to continue +ConfirmCancel: + push YesOrNoBtn + push 2 + push ConfirmCancelMsg + push 1 + push aCancelled + call SayErrTitle + test eax, eax + ret + ; int __stdcall SayErr(int num_strings, const char* strings[], ; int num_buttons, const char* buttons[]); SayErr: diff --git a/programs/fs/kfar/trunk/editor.inc b/programs/fs/kfar/trunk/editor.inc index b132b12587..1dd08d7183 100644 --- a/programs/fs/kfar/trunk/editor.inc +++ b/programs/fs/kfar/trunk/editor.inc @@ -123,7 +123,7 @@ edit_file: mov [ebp + editor_data.memsize], ebx mov al, [EditEOLStyle] mov [ebp + editor_data.eol], al - mov eax, [esi + panel1_hPlugin - panel1_data] + mov eax, dword [esi + panel1_hPlugin - panel1_dir] mov [ebp + editor_data.hPlugin], eax test eax, eax jz .nocopyhostname @@ -196,6 +196,7 @@ edit_file: push dword [ebx+21] push [ebp + editor_data.hFile] call [edx + PluginInfo.open] + mov [esp+1Ch], eax popad test eax, eax jz ..openerr_in_screen @@ -210,6 +211,7 @@ edit_file: push [readinfo.data] push ebx call [edx + PluginInfo.read] + mov [esp+1Ch], eax popad cmp eax, -1 jnz .readok @@ -259,7 +261,7 @@ edit_file: jnz .readdone @@: push eax ebx - mov ebx, [ebx+16] + mov ebx, [readinfo.data] .loadloop: mov ecx, [EditBlockSize] cmp eax, ecx @@ -1977,7 +1979,7 @@ editor_OnKey: .left: call editor_cursor_left - jc .redraw_status + jnc .redraw_status jmp editor_draw_text .ret3: ret @@ -2156,6 +2158,204 @@ editor_OnKey: .del1: jmp editor_draw_text +.f7: + call find_in_file_dlg + jz .shift_f7 +.f7.ret: + ret +.shift_f7: +; search string SearchString in file starting from current cursor position + mov ebx, SearchString + xor eax, eax + cmp byte [ebx], al + jz .f7.ret + mov esi, tolower_table + test [find_in_file_dlgdata.flags_case], 10h + jz @f + mov esi, identical_table +@@: + test [find_in_file_dlgdata.flags_whole], 10h + setnz al + push eax + push dword [ebp+editor_data.encoding]; always cp866 for now + ; needs to be revisited after Unicode support in editor + call search_string_pre + mov esi, [ebp + editor_data.cur_block] + add esi, ebp + mov ebx, [ebp + editor_data.cur_offs] + call editor_normalize_offs + jnc .f7.notfound + xor edi, edi + push ebx esi + push edi + push edi + test [find_in_file_dlgdata.flags_whole], 10h + jnz @f + movzx eax, byte [esi+ebx] + jmp .search_loop_next +@@: + mov edi, edx +.search_loop: +; edx -> FSM, ecx = last state, esi:ebx -> current data, +; edi = current state +; [esp] = row, [esp+4] = delta in lines +; get current symbol + movzx eax, byte [esi+ebx] +; calculate next state + movzx edi, byte [edi+eax] +; done? + cmp edi, ecx + jz .f7.found +.search_loop_next: +; no; proceed to next symbol + add ebx, 1 + shl edi, 8 + add dword [esp], 1 + add edi, edx + cmp ebx, [esi + edit_block_header.limit] + jae .f7.nextblock +.f7.nonextblock: + cmp al, 10 + jz .f7.newline + cmp al, 13 + jnz .search_loop + cmp byte [esi+ebx], 10 + jnz .f7.newline + call editor_step_forward + jnc .f7.notfound_pop +.f7.newline: + mov dword [esp], 0 + add dword [esp+4], 1 + mov dword [esp+8], esi + mov dword [esp+12], ebx + jmp .search_loop +.f7.nextblock: + call editor_normalize_offs + jc .f7.nonextblock +.f7.notfound_pop: +; last chance - if we are looking for a whole word, EOF is ok for last symbol + test [find_in_file_dlgdata.flags_whole], 10h + jz @f + mov esi, [ebp + editor_data.last_block] + add esi, ebp + mov ebx, [esi + edit_block_header.limit] + movzx edi, byte [edi+' '] + cmp edi, ecx + jz .f7.found +@@: + add esp, 10h +.f7.notfound: + jmp search_failed +.f7.found: + or [ebp + editor_data.cur_delta], -1 + sub ebx, ecx + inc ebx + test [find_in_file_dlgdata.flags_whole], 10h + jz @f + inc ebx +@@: + cmp ebx, [EditBlockStart] + jge @f + sub ebx, [EditBlockStart] + mov esi, [esi + edit_block_header.prev] + add esi, ebp + add ebx, [esi + edit_block_header.limit] + jmp @b +@@: + sub esi, ebp + mov [ebp + editor_data.cur_block], esi + add esi, ebp + mov [ebp + editor_data.cur_offs], ebx + push ecx + mov ecx, edx + call pgfree + pop ecx + pop eax + pop edi +; esi:ebx -> last symbol of match, eax = row, edi = delta in lines + pop esi ebx + test [find_in_file_dlgdata.flags_whole], 10h + jz @f + dec ecx +@@: + push ebx esi + sub eax, ecx + lea edx, [eax+1] + mov eax, [ebp + editor_data.curcol] + add eax, [ebp + editor_data.cursor_x] + test edi, edi + jz @f + xor eax, eax +@@: + test edx, edx + jz .f7.foundpos1 +.f7.findpos1: + cmp byte [ebx+esi], 9 + jz .f7.findpos1.tab + inc eax + call editor_step_forward + dec edx + jnz .f7.findpos1 + jmp .f7.foundpos1 +.f7.findpos1.tab: + push edx eax + xor edx, edx + div [editor_tabsize] + pop eax + sub edx, [editor_tabsize] + sub eax, edx + call editor_step_forward + pop edx + dec edx + jnz .f7.findpos1 +.f7.foundpos1: + pop esi ebx + push eax + cmp eax, [ebp + editor_data.curcol] + jb .f7.scrollleft + sub eax, [ebp + editor_data.curcol] + sub eax, [cur_width] + jb .f7.xset + inc eax + inc edx + add [ebp + editor_data.curcol], eax + jmp .f7.xset +.f7.scrollleft: + inc edx + mov [ebp + editor_data.curcol], eax +.f7.xset: + pop eax + push edx + sub eax, [ebp + editor_data.curcol] + mov [ebp + editor_data.cursor_x], eax + mov [cursor_x], eax + add edi, [ebp + editor_data.cursor_y] + push edi + inc edi + cmp edi, [cur_height] + pop edi + jae .f7.newview + mov [ebp + editor_data.cursor_y], edi + mov [cursor_y], edi + jmp .f7.yset +.f7.newview: + dec edi + mov [ebp + editor_data.linedata_start + editor_line.block], esi + mov [ebp + editor_data.linedata_start + editor_line.offs], bx + add [ebp + editor_data.curline], edi + xor eax, eax + inc eax + mov [ebp + editor_data.cursor_y], eax + mov [cursor_y], eax + call editor_init_lines + call editor_test_cursor_y + inc dword [esp] +.f7.yset: + pop eax + test eax, eax + jz .redraw_status + jmp editor_draw_text + editor_cursor_left: cmp [ebp + editor_data.cur_delta], -1 jz .in_text @@ -2292,3 +2492,31 @@ editor_OnExit: call close_handle_if_unused @@: ret + +find_in_file_dlg: + mov ebx, find_in_file_dlgdata + mov eax, [cur_width] + sub eax, 12 + mov [ebx + dlgtemplate.width], eax + dec eax + dec eax + mov [ebx - find_in_file_dlgdata + find_in_file_dlgdata.width2], eax + shr eax, 1 + dec eax + dec eax + mov [ebx - find_in_file_dlgdata + find_in_file_dlgdata.search_x2], eax + sub eax, aSearchBLength-1 + mov [ebx - find_in_file_dlgdata + find_in_file_dlgdata.search_x1], eax + add eax, aSearchBLength+3 + mov [ebx - find_in_file_dlgdata + find_in_file_dlgdata.cnl_x1], eax + add eax, aCancelBLength - 1 + mov [ebx - find_in_file_dlgdata + find_in_file_dlgdata.cnl_x2], eax + mov byte [ebx - find_in_file_dlgdata + find_in_file_dlgdata.flags0], 0xC + and byte [ebx - find_in_file_dlgdata + find_in_file_dlgdata.flags1], not 4 + and byte [ebx - find_in_file_dlgdata + find_in_file_dlgdata.flags2], not 4 + and byte [ebx - find_in_file_dlgdata + find_in_file_dlgdata.flags_case], not 4 + and byte [ebx - find_in_file_dlgdata + find_in_file_dlgdata.flags_whole], not 4 + push ebx + call DialogBox + cmp eax, find_in_file_dlgdata.search_btn + ret diff --git a/programs/fs/kfar/trunk/filetool.inc b/programs/fs/kfar/trunk/filetool.inc index 286b827c92..0ac2ef4c78 100644 --- a/programs/fs/kfar/trunk/filetool.inc +++ b/programs/fs/kfar/trunk/filetool.inc @@ -683,18 +683,8 @@ copy_file: ; read error cmp [copy_bSkipAll], 0 jnz .skip1 - push execdata - push aCannotReadFolder - call get_error_msg - push eax - mov eax, esp - push DeleteErrorBtn - push 4 - push eax - push 3 - call SayErr - add esp, 3*4 - test al, al + mov edx, execdata + call recursive_read_folder_err jz .read_retry cmp al, 2 jnz @f @@ -884,6 +874,36 @@ delete_last_name: mov byte [esi+1], 0 ret +recursive_read_folder_err: + push edx + push aCannotReadFolder + call get_error_msg + push eax + mov eax, esp + push DeleteErrorBtn + push 4 + push eax + push 3 + call SayErr + add esp, 3*4 + test al, al + ret + +recursive_read_file_err: + push edx + push aCannotReadFile + call get_error_msg + push eax + mov eax, esp + push DeleteErrorBtn + push 4 + push eax + push 3 + call SayErr + add esp, 3*4 + test al, al + ret + copy_AddDir: push 1 pop eax ; for "return true" @@ -931,6 +951,1015 @@ copy_AddFile: setna al ret 12 +search_dir_query_size = 32 +search_filebuf_size = 32768 + +virtual at 0 +filesearch_data: +.prev_screen_vtable dd ? ; previous in window stack +.prev_screen_data dd ? +.tid dd ? ; -1 for query stage, secondary thread id for search stage +.slot dd ? ; 0 if secondary thread is not running, it's slot otherwise +.result_blocks dd ? ; head of heap blocks for resulting data +.cur_result_ptr dd ? ; offset of free data in the current heap block for result +.stop db ? ; set to 1 when secondary thread need to be stopped +.skip_errors_mask db ? +.skip_read_folder = 1 +.skip_set_folder = 2 +.skip_open_file = 4 +.skip_read_file = 8 +.skip_bigname = 10h +.updating db ? +.datachanged db ? +.list.curitemptr dd ? +.list.numitems dd ? +.list.head dd ? +.list.curitem dd ? +.list.end dd ? +.query_dlgdata rb filesearch_query_template.size +.search_dlgdata rb filesearch_search_template.size +.mask.maxlen dd ? +.mask.pos dd ? +.mask.start dd ? +.mask rb 512 +.string.maxlen dd ? +.string.pos dd ? +.string.start dd ? +.string rb 256 +.caption rb 268 +.statusstr rb 80 +.stack rb 8192 +.stacktop = $ +.fs.func dd ? +.fs.pos_low dd ? +.fs.pos_high dd ? +.fs.size dd ? +.fs.ptr dd ? +.curfile rb 1024 +.curdir rb 1024 +.lowername rb 264 +.dir_area rb 32 + 304*search_dir_query_size +.filebuf rb search_filebuf_size +.size = $ +end virtual + +panels_OnKey.alt_f7: + mov ecx, filesearch_data.size + mov edx, filesearch_vtable + call new_screen + test eax, eax + jnz @f + ret +@@: + mov [ebp+filesearch_data.prev_screen_vtable], panels_vtable + mov ecx, (filesearch_query_template.size + filesearch_search_template.size) / 4 + mov esi, filesearch_query_template + lea edi, [ebp+filesearch_data.query_dlgdata] + rep movsd + lea eax, [ebp+filesearch_data.string.maxlen] + xor ebx, ebx + mov dword [ebp+filesearch_data.query_dlgdata+filesearch_query_template.editptr2-filesearch_query_template], eax + mov dword [eax], 253 + mov [eax+4], ebx + mov [eax+8], ebx + mov [eax+12], bl + sub eax, filesearch_data.string - filesearch_data.mask + mov dword [ebp+filesearch_data.query_dlgdata+filesearch_query_template.editptr1-filesearch_query_template], eax + mov dword [eax], 511 + mov [eax+8], ebx + inc ebx + mov word [eax+12], '*' + mov [eax+4], ebx + mov eax, [find_in_file_dlgdata.flags_case] + and al, 10h + or al, 8 + mov dword [ebp+filesearch_data.query_dlgdata+filesearch_query_template.flags_case-filesearch_query_template], eax + mov eax, [find_in_file_dlgdata.flags_whole] + and al, 10h + or al, 8 + mov dword [ebp+filesearch_data.query_dlgdata+filesearch_query_template.flags_whole-filesearch_query_template], eax + lea edi, [ebp+filesearch_data.caption] + mov dword [ebp+dlgtemplate.title+filesearch_data.search_dlgdata], edi + lea eax, [ebp+filesearch_data.list.curitemptr] + mov dword [ebp+filesearch_data.search_dlgdata+filesearch_search_template.data1-filesearch_search_template], eax +.reinit: + xor ebx, ebx + or [ebp+filesearch_data.tid], -1 + mov [ebp+filesearch_data.slot], ebx + mov [ebp+filesearch_data.result_blocks], ebx + mov [ebp+filesearch_data.cur_result_ptr], 0x4000 + mov [ebp+filesearch_data.list.curitemptr], ebx + mov [ebp+filesearch_data.list.numitems], ebx + mov [ebp+filesearch_data.list.head], ebx + mov [ebp+filesearch_data.list.curitem], ebx + mov [ebp+filesearch_data.list.end], ebx + mov [ebp+filesearch_data.stop], bl + mov al, [dialog_main_color] + mov [ebp+filesearch_data.query_dlgdata+dlgtemplate.main_color], al + mov [ebp+filesearch_data.search_dlgdata+dlgtemplate.main_color], al + mov al, [dialog_border_color] + mov [ebp+filesearch_data.query_dlgdata+dlgtemplate.border_color], al + mov [ebp+filesearch_data.search_dlgdata+dlgtemplate.border_color], al + mov al, [dialog_header_color] + mov [ebp+filesearch_data.query_dlgdata+dlgtemplate.header_color], al + mov [ebp+filesearch_data.search_dlgdata+dlgtemplate.header_color], al +filesearch_OnRedraw: + push ebp + mov byte [draw_image], 0xC3 + mov eax, [ebp+filesearch_data.prev_screen_vtable] + mov ebp, [ebp+filesearch_data.prev_screen_data] + call dword [eax+screen_vtable.OnRedraw] + mov byte [draw_image], 0xC6 + pop ebp + cmp [ebp+filesearch_data.tid], -1 + jnz .prepare_search_dlg + lea ebx, [ebp+filesearch_data.query_dlgdata] + mov eax, [cur_width] + mov [ebx + dlgtemplate.x], 6 + sub eax, 12 + mov [ebx + dlgtemplate.width], eax + dec eax + dec eax + mov [ebx - filesearch_query_template + filesearch_query_template.width2], eax + mov [ebx - filesearch_query_template + filesearch_query_template.width3], eax + shr eax, 1 + dec eax + dec eax + mov [ebx - filesearch_query_template + filesearch_query_template.search_x2], eax + sub eax, aSearchBLength-1 + mov [ebx - filesearch_query_template + filesearch_query_template.search_x1], eax + add eax, aSearchBLength+3 + mov [ebx - filesearch_query_template + filesearch_query_template.cnl_x1], eax + add eax, aCancelBLength-1 + mov [ebx - filesearch_query_template + filesearch_query_template.cnl_x2], eax + mov eax, [cur_height] + sub eax, [ebx + dlgtemplate.height] + shr eax, 1 + mov [ebx + dlgtemplate.y], eax + jmp .dlg_prepared +.prepare_search_dlg: + lea ebx, [ebp+filesearch_data.search_dlgdata] +; width: for big screens use all screen except for one column on each side, +; that is, [cur_width] - 10 (standard frame width is 4); +; if [cur_width]-10 does not contain enough place for all buttons with two spaces between them, +; but [cur_width]-2 does, use fixed size = place for all buttons with two spaces between them +; for small screens use [cur_width]-2 as maximum possible +.btnsize = 2 + aNewSearchLen + 2 + aGotoLen + 2 + aViewLen + 2 + aCancelB2Length + 2 + mov eax, [cur_width] + mov edx, eax + sub eax, 10 + cmp eax, .btnsize + jae @f + add eax, 8 + cmp eax, .btnsize + jb @f + mov al, .btnsize +@@: + mov [ebx + dlgtemplate.width], eax + sub edx, eax + shr edx, 1 + mov [ebx + dlgtemplate.x], edx + dec eax + mov [ebx + filesearch_search_template.width1 - filesearch_search_template], eax + mov [ebx + filesearch_search_template.width4 - filesearch_search_template], eax + cmp [ebp + filesearch_data.slot], 0 + jnz @f + mov [ebx + filesearch_search_template.width3 - filesearch_search_template], eax +@@: + sub eax, aNewSearchLen + aGotoLen + aViewLen + aCancelB2Length - 1 + cdq + push 5 + pop ecx + idiv ecx + sar edx, 1 + add edx, eax + inc eax + mov [ebx + filesearch_search_template.btn1x1 - filesearch_search_template], edx + add edx, aNewSearchLen-1 + mov [ebx + filesearch_search_template.btn1x2 - filesearch_search_template], edx + add edx, eax + mov [ebx + filesearch_search_template.btn2x1 - filesearch_search_template], edx + add edx, aGotoLen-1 + mov [ebx + filesearch_search_template.btn2x2 - filesearch_search_template], edx + add edx, eax + mov [ebx + filesearch_search_template.btn3x1 - filesearch_search_template], edx + add edx, aViewLen-1 + mov [ebx + filesearch_search_template.btn3x2 - filesearch_search_template], edx + add edx, eax + mov [ebx + filesearch_search_template.btn4x1 - filesearch_search_template], edx + add edx, aCancelB2Length-1 + mov [ebx + filesearch_search_template.btn4x2 - filesearch_search_template], edx + mov eax, [cur_height] + mov edx, eax + sub eax, 8 + cmp eax, 6 + jae @f + mov eax, 6 +@@: + mov [ebx + dlgtemplate.height], eax + sub edx, eax + shr edx, 1 + mov [ebx + dlgtemplate.y], edx + dec eax + mov [ebx + filesearch_search_template.btn1y - filesearch_search_template], eax + mov [ebx + filesearch_search_template.btn2y - filesearch_search_template], eax + mov [ebx + filesearch_search_template.btn3y - filesearch_search_template], eax + mov [ebx + filesearch_search_template.btn4y - filesearch_search_template], eax + dec eax + mov [ebx + filesearch_search_template.y5 - filesearch_search_template], eax + dec eax + mov [ebx + filesearch_search_template.y3 - filesearch_search_template], eax + mov [ebx + filesearch_search_template.y4 - filesearch_search_template], eax + dec eax + mov [ebx + filesearch_search_template.y2 - filesearch_search_template], eax + dec eax + mov [ebx + filesearch_search_template.height1 - filesearch_search_template], eax +.dlg_prepared: + call draw_dialog_shadow + push ebx + call DrawDialogBox + ret + +filesearch_OnActivate: + mov eax, [active_screen_data] + cmp eax, ebp + jz @f + mov [ebp+filesearch_data.prev_screen_data], eax + mov eax, [active_screen_vtable] + mov [ebp+filesearch_data.prev_screen_vtable], eax +@@: + mov eax, [ebp+filesearch_data.prev_screen_data] + mov ecx, [num_screens] + mov edx, [screens] + push edx +@@: + cmp [edx+4], eax + jz @f + add edx, 8 + loop @b +@@: + pop edx + jz @f + mov eax, [active_screen] + dec eax + mov ecx, [edx+eax*8+4] + mov [ebp+filesearch_data.prev_screen_data], ecx + mov ecx, [edx+eax*8] + mov [ebp+filesearch_data.prev_screen_vtable], ecx +@@: + cmp [ebp+filesearch_data.slot], 0 + jz @f + mov [idle_interval], 10 +@@: +; ret ; continue to filesearch_OnIdle + +filesearch_OnIdle: + xor eax, eax + xchg al, [ebp+filesearch_data.datachanged] + cmp al, 1 + ja .done + jz .new +.ret: + ret +.done: + call filesearch_wait_thread + call filesearch_done +.new: + jmp filesearch_OnRedraw + +filesearch_OnKey: + cmp al, 0x58 + jz F12 + cmp [ebp+filesearch_data.tid], -1 + jz .handle_generic + cmp al, 0x47 + jb .notforlist + cmp al, 0x49 + jbe @f + cmp al, 0x4F + jb .notforlist + cmp al, 0x51 + ja .notforlist +@@: + push ebp + add ebp, filesearch_data.search_dlgdata + lea ebx, [ebp+dlgtemplate.size+12] + call listbox_key + call draw_listbox + call draw_image + pop ebp + ret +.notforlist: + cmp al, 0x3D + jz .view +.handle_generic: + push ebp + call filesearch_getcurdlg + push 0 + push eax + push 2 + push ebx + call ManagerDlgProc + pop ebp + test eax, eax + jz filesearch_OnIdle.ret + cmp eax, -1 + jz .esc + sub eax, ebp + cmp eax, filesearch_data.query_dlgdata+filesearch_query_template.search_btn-filesearch_query_template + jz .query + cmp eax, filesearch_data.search_dlgdata+filesearch_search_template.btn1-filesearch_search_template + jz .newsearch + cmp eax, filesearch_data.search_dlgdata+filesearch_search_template.btn2-filesearch_search_template + jz .goto + cmp eax, filesearch_data.search_dlgdata+filesearch_search_template.btn3-filesearch_search_template + jz .view +.esc: + cmp dword [ebp+filesearch_data.slot], 0 + jz .exit + mov [ebp+filesearch_data.stop], 2 + call ConfirmCancel + setz [ebp+filesearch_data.stop] +.ret: + ret +.exit: + call filesearch_OnExit + jmp delete_active_screen +.view: + mov esi, [ebp+filesearch_data.list.curitemptr] + test esi, esi + jz .ret + add esi, 8 + mov eax, esi + jmp view_file +.goto: + mov esi, [ebp+filesearch_data.list.curitemptr] + test esi, esi + jz .ret + add esi, 8 + cmp byte [esi], '/' + jnz .ret + cmp byte [esi+1], 0 + jz .ret + push ebp + mov ebp, [active_panel] + push esi + call close_plugin_panels + pop esi + mov ecx, esi +@@: + lodsb + test al, al + jnz @b +@@: + dec esi + cmp byte [esi], '/' + jnz @b + mov byte [esi], 0 + inc esi + mov edi, saved_file_name +@@: + lodsb + stosb + test al, al + jnz @b + mov esi, ecx + lea edi, [ebp + panel1_dir - panel1_data] + push esi edi + call strcmpi + pop edi esi + jz .goto.samedir +@@: + lodsb + stosb + test al, al + jnz @b + and [ebp + panel1_start - panel1_data], 0 + and [ebp + panel1_index - panel1_data], 0 +.goto.samedir: + push @f + push [ebp + panel1_index - panel1_data] + jmp panels_OnKey.ctrl_r.doread +@@: + pop ebp + jmp .exit +.newsearch: + cmp [ebp+filesearch_data.slot], 0 + jz .do.newsearch + call filesearch_stop_thread +.do.newsearch: + call filesearch_free_result + jmp panels_OnKey.alt_f7.reinit +.query: + mov esi, [active_panel] + cmp [esi + panel1_hPlugin - panel1_data], 0 + jz @f + push aCannotSearchOnPlugin + mov eax, esp + push ContinueBtn + push 1 + push eax + push 1 + call SayErr + pop eax + jmp .exit +@@: + add esi, panel1_dir - panel1_data + lea edi, [ebp+filesearch_data.curdir] +@@: + lodsb + stosb + test al, al + jnz @b + push 51 + pop eax + push 1 + pop ebx + mov ecx, filesearch_thread + lea edx, [ebp+filesearch_data.stacktop-4] + mov [edx], ebp + int 40h + cmp eax, -1 + jnz @f + push ContinueBtn + push 1 + push aCannotCreateThread_ptr + push 1 + call SayErr + ret +@@: + mov [ebp+filesearch_data.tid], eax + mov [ebp+filesearch_data.updating], 0 + mov [ebp+filesearch_data.datachanged], 0 + xchg eax, ecx + push 18 + pop eax + push 21 + pop ebx + int 40h + mov [ebp+filesearch_data.slot], eax + mov [idle_interval], 10 + mov esi, aFileSearch + mov edi, dword [ebp+filesearch_data.search_dlgdata+dlgtemplate.title] +@@: + lodsb + stosb + test al, al + jnz @b + mov byte [edi-1], ':' + mov al, ' ' + stosb + lea esi, [ebp+filesearch_data.mask] +@@: + lodsb + stosb + test al, al + jnz @b + lea edi, [ebp+filesearch_data.statusstr] + mov dword [ebp+filesearch_data.search_dlgdata+filesearch_search_template.data3-filesearch_search_template], edi + mov esi, aSearchingIn +@@: + lodsb + stosb + cmp al, '"' + jnz @b + push esi + push 10 + pop ecx + lea esi, [ebp+filesearch_data.string] +@@: + lodsb + test al, al + jz @f + stosb + loop @b +@@: + pop esi + movsb + jz @f + mov byte [edi-1], '.' + mov byte [edi-2], '.' + mov byte [edi-3], '.' + mov byte [edi-4], '"' +@@: + cmp byte [edi-2], '"' + jnz @f + sub edi, 3 +@@: + lodsb + stosb + test al, al + jnz @b + sub edi, dword [ebp+filesearch_data.search_dlgdata+filesearch_search_template.data3-filesearch_search_template] + mov dword [ebp+filesearch_data.search_dlgdata+filesearch_search_template.width3-filesearch_search_template], edi + inc edi + mov dword [ebp+filesearch_data.search_dlgdata+filesearch_search_template.x4-filesearch_search_template], edi + lea eax, [ebp+filesearch_data.curdir] + mov dword [ebp+filesearch_data.search_dlgdata+filesearch_search_template.data4-filesearch_search_template], eax + call filesearch_set_dlgflags ; use it? I think, yes + cmp [ebp+filesearch_data.slot], 0 + jnz @f + call filesearch_done +@@: + jmp filesearch_OnRedraw + +filesearch_done: + cmp [active_screen_data], ebp + jnz @f + or [idle_interval], -1 +@@: + and dword [ebp+filesearch_data.search_dlgdata+filesearch_search_template.data4-filesearch_search_template], 0 + mov edi, dword [ebp+filesearch_data.search_dlgdata+filesearch_search_template.data3-filesearch_search_template] + mov esi, aSearchDone +@@: + lodsb + stosb + cmp al, '?' + jnz @b + dec edi + mov eax, [ebp+filesearch_data.list.numitems] + push -'0' + push 10 + pop ecx +@@: + xor edx, edx + div ecx + push edx + test eax, eax + jnz @b +@@: + pop eax + add al, '0' + jz @f + stosb + jmp @b +@@: + lodsb + stosb + test al, al + jnz @b + ret + +filesearch_getname: +if lang eq ru + mov eax, 'Диал' + stosd + mov eax, 'ог п' + stosd + mov eax, 'оиск' + stosd + mov al, 'а' + stosb +else + mov eax, 'Find' + stosd + mov eax, ' dia' + stosd + mov eax, 'log ' + stosd + mov al, ' ' + stosb +end if + ret + +filesearch_stop_thread: + mov [ebp+filesearch_data.stop], 1 + +filesearch_wait_thread: + mov ecx, [ebp+filesearch_data.slot] + mov edx, [ebp+filesearch_data.tid] + jecxz .secondary_thread_exited +@@: + mov ebx, procinfo + push 9 + pop eax + int 40h + cmp word [ebx+50], 9 + jz .secondary_thread_exited + cmp dword [ebx+30], edx + jnz .secondary_thread_exited + push 5 + pop eax + push 1 + pop ebx + int 40h + jmp @b +.secondary_thread_exited: + and [ebp+filesearch_data.slot], 0 + ret + +filesearch_OnExit: + call filesearch_stop_thread + call filesearch_free_result +; call filesearch_set_dlgflags ; use it? I think, no + ret + +filesearch_IsHandleUsed: + test ebp, ebp + ret + +filesearch_set_dlgflags: + mov eax, dword [ebp+filesearch_data.query_dlgdata+filesearch_query_template.flags_case-filesearch_query_template] + and al, 10h + or al, 8 + mov [find_in_file_dlgdata.flags_case], eax + mov eax, dword [ebp+filesearch_data.query_dlgdata+filesearch_query_template.flags_whole-filesearch_query_template] + and al, 10h + or al, 8 + mov [find_in_file_dlgdata.flags_whole], eax + lea esi, [ebp+filesearch_data.string] + mov edi, SearchString + and dword [edi-4], 0 + and dword [edi-8], 0 +@@: + lodsb + stosb + test al, al + jnz @b + ret + +filesearch_getcurdlg: + lea ebx, [ebp+filesearch_data.query_dlgdata] + cmp [ebp+filesearch_data.tid], -1 + jz @f + add ebx, filesearch_data.search_dlgdata - filesearch_data.query_dlgdata +@@: + ret + +filesearch_free_result: + mov ecx, [ebp+filesearch_data.result_blocks] +@@: + jecxz .ret + push dword [ecx] + call pgfree + pop ecx + jmp @b +.ret: + ret + +filesearch_thread: + pop ebp +; initialize search for string + xor ecx, ecx + xor edx, edx + mov [ebp+filesearch_data.skip_errors_mask], cl + lea ebx, [ebp+filesearch_data.string] + cmp byte [ebx], dl + jz .noprepare + mov esi, tolower_table + test byte [ebp+filesearch_data.query_dlgdata+filesearch_query_template.flags_case-filesearch_query_template], 10h + jz @f + mov esi, identical_table +@@: + test byte [ebp+filesearch_data.query_dlgdata+filesearch_query_template.flags_whole-filesearch_query_template], 10h + setnz al + push eax + push ecx ; force cp866 + call search_string_pre +.noprepare: + push -1 +.enter_recursion: + xor esi, esi ; start position: zero +.read_folder_loop: + push esi + lea esi, [ebp+filesearch_data.curdir] + lea edi, [ebp+filesearch_data.curfile] +@@: + lodsb + stosb + test al, al + jnz @b + pop esi +.read_retry: + lea ebx, [ebp+filesearch_data.fs.func] + mov dword [ebx], 1 + mov dword [ebx+4], esi + and dword [ebx+8], 0 + mov dword [ebx+12], search_dir_query_size + lea eax, [ebp+filesearch_data.dir_area] + mov [ebx+16], eax + push 70 + pop eax + int 40h + test eax, eax + jz .read_folder_ok + cmp eax, 6 + jz .read_folder_ok + xor ebx, ebx + xchg ebx, dword [ebp+filesearch_data.dir_area+4] + test [ebp+filesearch_data.skip_errors_mask], filesearch_data.skip_read_folder + jnz .skip1 + push edx + lea edx, [ebp+filesearch_data.curdir] + call recursive_read_folder_err + pop edx + jz .read_retry + cmp al, 2 + jnz @f + dec eax + or [ebp+filesearch_data.skip_errors_mask], filesearch_data.skip_read_folder +@@: + cmp al, 1 + jnz .cancel +.skip1: +.read_folder_ok: + imul ebx, 304 + lea eax, [ebp+filesearch_data.dir_area+32] + add ebx, eax +.scan_folder_loop: + cmp eax, ebx + jae .scan_folder_done +; ignore special entries "." and ".." + cmp word [eax+40], '.' + jz .scan_folder_next + cmp word [eax+40], '..' + jnz @f + cmp byte [eax+42], 0 + jz .scan_folder_next +@@: + call .check_stop +; construct name + push esi edi ebx eax + lea ebx, [ebp+filesearch_data.curfile+1023] + lea esi, [eax+40] + mov byte [edi-1], '/' +@@: + cmp edi, ebx + jae .namebig + lodsb + stosb + test al, al + jnz @b + pop eax + test byte [eax], 10h + jz .scan_file +; it is nested folder, enter recursion +; to maintain ASCIIZ string coherency, copy backward + lea esi, [edi+filesearch_data.curdir-filesearch_data.curfile] +@@: + dec edi + dec esi + mov al, [edi] + mov [esi], al + cmp al, '/' + jnz @b + mov [ebp+filesearch_data.datachanged], 1 + pop ebx edi + jmp .enter_recursion +.namebig: + pop eax + mov byte [edi], 0 + test [ebp+filesearch_data.skip_errors_mask], filesearch_data.skip_bigname + jnz .namebig.skip + push eax + push edi + test byte [eax], 10h + mov eax, aFileNameTooBig + jz @f + add eax, aFolderNameTooBig - aFileNameTooBig +@@: + push eax + mov eax, esp + push SkipOrCancelBtn + push 3 + push eax + push 2 + call SayErr + cmp al, 1 + jnz @f + dec eax + or [ebp+filesearch_data.skip_errors_mask], filesearch_data.skip_bigname +@@: + test al, al + pop eax eax eax + jnz .cancel +.namebig.skip: + jmp .scan_folder_next_pop +.scan_file: +; it is a file +; first check: does file name match the mask? + push eax edx +; обрюнетить + lea esi, [eax+40] + lea edi, [ebp+filesearch_data.lowername] + push edi + xor eax, eax +@@: + lodsb + mov al, [tolower_table+eax] + stosb + test al, al + jnz @b +; поехали + lea edx, [edi-1] + pop esi + lea edi, [ebp+filesearch_data.mask] + call match_mask_rev_lowercase + pop edx eax + jc .scan_folder_next_pop +; ok, second check: is the string present in this file? + jecxz .file_found + push eax + call filesearch_test_file + pop eax + jc .scan_folder_next_pop +.file_found: + push eax +; allocate memory for new result + lea esi, [ebp+filesearch_data.curfile] + mov ebx, esi +@@: + lodsb + test al, al + jnz @b + sub esi, ebx + mov eax, [ebp+filesearch_data.cur_result_ptr] + add esi, 8 + push ecx + mov ecx, 0x4000 + sub ecx, eax + cmp ecx, esi + jae .nonewblock + mov ecx, 0x4000 + call xpgalloc + test eax, eax + jz .cancel + pushd [ebp+filesearch_data.result_blocks] + popd [eax] + mov [ebp+filesearch_data.result_blocks], eax + push 4 + pop eax + mov [ebp+filesearch_data.cur_result_ptr], eax +.nonewblock: + add eax, [ebp+filesearch_data.result_blocks] + add [ebp+filesearch_data.cur_result_ptr], esi + pop ecx +; eax -> allocated memory, fill it + push eax + lea edi, [eax+8] + mov esi, ebx +@@: + lodsb + stosb + test al, al + jnz @b + pop eax + mov ebx, [ebp+filesearch_data.list.end] + mov [eax+4], ebx + and dword [eax], 0 + mov [ebp+filesearch_data.list.end], eax + test ebx, ebx + jz @f + mov [ebx], eax +@@: + inc [ebp+filesearch_data.list.numitems] + cmp [ebp+filesearch_data.list.curitemptr], 0 + jnz @f + mov [ebp+filesearch_data.list.curitemptr], eax +@@: + cmp [ebp+filesearch_data.list.head], 0 + jnz @f + mov [ebp+filesearch_data.list.head], eax +@@: + mov [ebp+filesearch_data.datachanged], 1 + pop eax +.scan_folder_next_pop: + pop ebx edi esi + mov byte [edi-1], 0 +.scan_folder_next: + inc esi + add eax, 304 + jmp .scan_folder_loop +.scan_folder_done: + cmp dword [ebp+filesearch_data.dir_area+4], search_dir_query_size + jz .read_folder_loop + pop esi + inc esi + jz .done + lea eax, [ebp+filesearch_data.curdir] +@@: + inc eax + cmp byte [eax], 0 + jnz @b +@@: + dec eax + cmp byte [eax], '/' + jnz @b + mov byte [eax], 0 + mov [ebp+filesearch_data.datachanged], 1 + jmp .read_folder_loop +.cancel: +.done: + mov [ebp+filesearch_data.datachanged], 2 + or eax, -1 + int 40h + +.check_stop: + cmp [ebp+filesearch_data.stop], 1 + jz .cancel + ja @f + ret +@@: + push eax ebx + push 5 + pop eax + push 1 + pop ebx + int 40h + pop ebx eax + jmp .check_stop + +filesearch_test_file: + lea ebx, [ebp+filesearch_data.fs.func] + lea eax, [ebp+filesearch_data.filebuf] + mov [ebx+16], eax + xor eax, eax + mov [ebx], eax + mov [ebx+4], eax + mov [ebx+8], eax + mov dword [ebx+12], search_filebuf_size + mov edi, edx + test byte [ebp+filesearch_data.query_dlgdata+filesearch_query_template.flags_whole-filesearch_query_template], 10h + jz .loop + add edi, 256 +.loop: +.read_retry: + call filesearch_thread.check_stop + push 70 + pop eax + lea ebx, [ebp+filesearch_data.fs.func] + int 40h + test eax, eax + jz .readok + cmp eax, 6 + jz .readok + test [ebp+filesearch_data.skip_errors_mask], filesearch_data.skip_read_file + jnz .ret_failed + push edx + lea edx, [ebp+filesearch_data.curfile] + call recursive_read_file_err + pop edx + jz .read_retry + cmp al, 2 + jnz @f + dec eax + or [ebp+filesearch_data.skip_errors_mask], filesearch_data.skip_read_file +@@: + cmp al, 1 + jnz filesearch_thread.cancel +.ret_failed: + stc + ret +.readok: + test ebx, ebx + jz .eof + push ebx + lea esi, [ebp+filesearch_data.filebuf] + add ebx, esi +; edi = current state, edx -> FSM, ecx = last state, +; esi -> current data, ebx -> end of buffer +.scanloop: ; loop unrolled +; get current symbol + movzx eax, byte [esi] +; calculate next state + movzx edi, byte [edi+eax] +; done? + cmp edi, ecx + jz .ret_ok_pop +; no; proceed to next symbol + shl edi, 8 + add edi, edx + cmp esi, ebx + jae .scandone + movzx eax, byte [esi+1] + add esi, 2 + movzx edi, byte [edi+eax] + cmp edi, ecx + jz .ret_ok_pop + shl edi, 8 + add edi, edx + cmp esi, ebx + jb .scanloop +.scandone: + pop ebx +.eof: + add [ebp+filesearch_data.fs.pos_low], ebx + adc [ebp+filesearch_data.fs.pos_high], 0 + cmp ebx, search_filebuf_size + jz .loop +; EOF, last chance for whole-words-only search + test byte [ebp+filesearch_data.query_dlgdata+filesearch_query_template.flags_whole-filesearch_query_template], 10h + jz .ret_failed + movzx edi, byte [edi+' '] + cmp edi, ecx + jnz .ret_failed + clc + ret +.ret_ok_pop: + pop ebx + clc + ret + virtual at 0 _FILE: .pos dq ? diff --git a/programs/fs/kfar/trunk/kfar.asm b/programs/fs/kfar/trunk/kfar.asm index 5c573051a5..d712773551 100644 --- a/programs/fs/kfar/trunk/kfar.asm +++ b/programs/fs/kfar/trunk/kfar.asm @@ -7,8 +7,8 @@ memsize dd mem dd stacktop dd 0, app_path -version equ '0.5' -version_dword equ 0*10000h + 50 +version equ '0.6' +version_dword equ 0*10000h + 60 min_width = 54 max_width = 255 @@ -20,6 +20,7 @@ include 'font.inc' include 'sort.inc' include 'kglobals.inc' include 'dialogs.inc' +include 'search.inc' include 'viewer.inc' include 'editor.inc' include 'tools.inc' @@ -29,10 +30,14 @@ cursor_normal_size = (font_height*15+50)/100 cursor_big_size = font_height start: - mov edi, tolower_table - push 'A' - pop ecx + mov edi, identical_table + mov ecx, 0x100 xor eax, eax +@@: + stosb + inc eax + loop @b + mov cl, 'A' @@: stosb inc eax @@ -68,6 +73,41 @@ start: inc eax loop @b mov byte [edi-256+'Ё'], 'ё' + mov cl, 'A' + inc eax + rep stosb + mov cl, 'Z'-'A'+1 + dec eax + rep stosb + mov cl, 'a'-'Z'-1 + inc eax + rep stosb + mov byte [edi-'a'+'_'], 0 + mov cl, 'z'-'a'+1 + dec eax + rep stosb + mov cl, 'А'-'z'-1 + inc eax + rep stosb + mov cl, 'п'-'А'+1 + dec eax + rep stosb + mov cl, 'р'-'п'-1 + inc eax + rep stosb + mov cl, 'ё'-'р'+1 + dec eax + rep stosb + mov cl, 256-'ё'-1 + inc eax + rep stosb + mov edi, SearchStringEditBuf + mov eax, SearchStringEditBuf.length + stosd + xor eax, eax + stosd + stosd + stosb push 68 pop eax push 11 @@ -116,6 +156,7 @@ start: mov ecx, panels_vtable mov [eax], ecx mov [active_screen_vtable], ecx + mov [active_screen_keybar], keybar_panels ; load libini.obj and kfar.ini mov eax, libini_name mov esi, ini_import @@ -294,12 +335,13 @@ start: add ebx, 3 and ebx, not 3 mov [EditPlugInfo], ebx - add ebx, editor_line.plugdata - imul ebx, max_height - add ebx, editor_data.basesize + 0xFFF - shr ebx, 12 - mov [EditDataSize], ebx .noini: + mov eax, [EditPlugInfo] + add eax, editor_line.plugdata + imul eax, max_height + add eax, editor_data.basesize + 0xFFF + shr eax, 12 + mov [EditDataSize], eax mov esi, def_left_dir mov edi, panel1_dir @@: @@ -327,9 +369,7 @@ start: call read_folder call draw_panel event: - push 10 - pop eax - int 40h + call get_event dec eax jz redraw dec eax @@ -418,6 +458,33 @@ if CHECK_FOR_LEAKS end if or eax, -1 int 40h + +get_event: + push ebx + mov ebx, [idle_interval] + cmp ebx, -1 + jz .infinite + push 23 + pop eax + int 40h + pop ebx + test eax, eax + jnz .ret + mov ebp, [active_screen_data] + mov eax, [active_screen_vtable] + mov eax, [eax+screen_vtable.OnIdle] + test eax, eax + jz get_event + call eax + jmp get_event +.infinite: + pop ebx + push 10 + pop eax + int 40h +.ret: + ret + redraw: ; query kbd state from OS mov al, 66 @@ -1034,6 +1101,12 @@ new_screen: mov [active_screen], eax mov [active_screen_vtable], edx mov [active_screen_data], ebp + or [idle_interval], -1 + mov edx, [edx+screen_vtable.keybar] + test edx, edx + jz @f + mov [active_screen_keybar], edx +@@: jmp draw_keybar next_screen: @@ -1068,16 +1141,29 @@ delete_active_screen: .norealloc: pop ecx call pgfree - and [active_screen], 0 + dec [active_screen] change_screen: pusha + or [idle_interval], -1 mov eax, [active_screen] mov esi, [screens] mov ebp, [esi+eax*8+4] mov eax, [esi+eax*8] + push eax ebp + mov eax, [eax+screen_vtable.OnActivate] + test eax, eax + jz @f + call eax +@@: + pop ebp eax mov [active_screen_vtable], eax mov [active_screen_data], ebp + mov edx, [eax+screen_vtable.keybar] + test edx, edx + jz @f + mov [active_screen_keybar], edx +@@: call draw_keybar mov [cursor_size], cursor_normal_size call [eax+screen_vtable.OnRedraw] @@ -2557,6 +2643,12 @@ end if jmp .copydone .f3: + mov eax, [ebp + panel1_files - panel1_data] + mov ecx, [eax+ecx*4] + test byte [ecx], 10h + jnz .ret2 + lea esi, [ebp + panel1_dir - panel1_data] + xor eax, eax call view_file .ret2: ret @@ -2694,6 +2786,7 @@ end if stosb test al, al jnz @b +.ctrl_r.doread: push [ebp + panel1_start - panel1_data] call read_folder pop [ebp + panel1_start - panel1_data] @@ -3855,8 +3948,7 @@ draw_keybar: or al, 4 @@: imul eax, 6*12 - mov esi, [active_screen_vtable] - mov esi, [esi+screen_vtable.keybar] + mov esi, [active_screen_keybar] add esi, eax xor ecx, ecx inc ecx @@ -7005,6 +7097,8 @@ cursor_size dd cursor_normal_size cur_cursor_pos dd -1 old_cursor_pos dd -1 +idle_interval dd -1 + active_panel dd panel1_data associations dd 0 @@ -7041,6 +7135,8 @@ ctrlkey_tests_num = 5 virtual at 0 screen_vtable: .OnRedraw dd ? + .OnActivate dd ? + .OnIdle dd ? .OnKey dd ? .keybar dd ? .getname dd ? @@ -7050,6 +7146,8 @@ end virtual panels_vtable: dd panels_OnRedraw + dd 0 + dd 0 dd panels_OnKey dd keybar_panels dd panels_getname @@ -7058,6 +7156,8 @@ panels_vtable: viewer_vtable: dd viewer_OnRedraw + dd 0 + dd 0 dd viewer_OnKey dd keybar_viewer dd viewer_getname @@ -7066,12 +7166,24 @@ viewer_vtable: editor_vtable: dd editor_OnRedraw + dd 0 + dd 0 dd editor_OnKey dd keybar_editor dd editor_getname dd editor_OnExit dd editor_IsHandleUsed +filesearch_vtable: + dd filesearch_OnRedraw + dd filesearch_OnActivate + dd filesearch_OnIdle + dd filesearch_OnKey + dd 0 + dd filesearch_getname + dd filesearch_OnExit + dd filesearch_IsHandleUsed + ; additions to this table require changes in tools.inc::get_error_msg errors1: dd error0msg @@ -7222,6 +7334,8 @@ panels_ctrlkeys: dd panels_OnKey.shift_f5 dw 0x41, 0 dd panels_OnKey.f7 + dw 0x41, 0x100 + dd panels_OnKey.alt_f7 dw 0x42, 0 dd panels_OnKey.f8 dw 0x43, 0x100 @@ -7295,6 +7409,10 @@ viewer_ctrlkeys: dd viewer_OnKey.exit dw 0x3E, 0 dd viewer_OnKey.f4 + dw 0x41, 0 + dd viewer_OnKey.f7 + dw 0x41, 1 + dd viewer_OnKey.shift_f7 dw 0x42, 0 dd viewer_OnKey.f8 dw 0x42, 1 @@ -7318,6 +7436,10 @@ editor_ctrlkeys: dd editor_OnKey.backspace dw 0x3C, 0 dd editor_OnKey.f2 + dw 0x41, 0 + dd editor_OnKey.f7 + dw 0x41, 1 + dd editor_OnKey.shift_f7 dw 0x43, 0x100 dd alt_f9 dw 0x44, 0 @@ -7429,6 +7551,9 @@ dialog_edit_color db 30h dialog_unmodified_edit_color db 38h dialog_normal_btn_color db 70h dialog_selected_btn_color db 30h +dialog_list_color db 70h +dialog_selected_list_color db 0Fh +dialog_scroll_list_color db 70h ; Предупреждения и ошибки warning_colors: ; !!! должны быть те же поля и в том же порядке, что и для обычных диалогов !!! @@ -7439,6 +7564,9 @@ warning_edit_color db 30h warning_unmodified_edit_color db 38h warning_normal_btn_color db 4Fh warning_selected_btn_color db 70h +warning_list_color db 3Fh +warning_selected_list_color db 70h +warning_scroll_list_color db 3Fh ; Меню menu_normal_color db 3Fh menu_selected_color db 0Fh @@ -7456,6 +7584,7 @@ cmdbar_normal_color db 7 cmdbar_prefix_color db 7 ; Просмотрщик view_normal_color db 1Bh +view_selected_color db 30h view_status_color db 30h view_arrows_color db 1Eh ; Редактор @@ -7694,6 +7823,237 @@ QuickSearchDlg: dd quick_search_buf dd 1Ch +; диалог поиска в файле для просмотрщика и редактора +find_in_file_dlgdata: + dd 1 +.x dd -1 +.y dd -1 +.width dd ? +.height dd 7 + dd 4, 2 + dd aSearch + dd ?, ? + dd 0, 0 + dd 8 +; Строка "Искать" + dd 1 + dd 1,0,aSearchForLen,0 + dd aSearchFor + dd 0 +; поле редактирования с текстом для поиска + dd 3 + dd 1,1 +.width2 dd ? + dd 1 + dd SearchStringEditBuf +.flags0 dd 0xC +; горизонтальный разделитель + dd 4 + dd -1,2 + dd -1,2 + dd 0 + dd 0 +; флажок "Учитывать регистр" + dd 5 + dd 1,3 + dd -1,3 + dd aCaseSensitive +.flags_case dd 18h ; default: search is case sensitive +; флажок "Только целые слова" + dd 5 + dd 1,4 + dd -1,4 + dd aWholeWords +.flags_whole dd 8 ; default: do NOT search whole words only +; горизонтальный разделитель + dd 4 + dd -1,5 + dd -1,5 + dd 0 + dd 0 +; кнопка "Искать" +.search_btn: + dd 2 +.search_x1 dd ? + dd 6 +.search_x2 dd ? + dd 6 + dd aSearchB +.flags1 dd 18h +; кнопка "отменить" + dd 2 +.cnl_x1 dd ? + dd 6 +.cnl_x2 dd ? + dd 6 + dd aCancelB +.flags2 dd 8 + +; первый диалог поиска в файлах (запрос) +filesearch_query_template: + dd 1 +.x dd ? +.y dd ? +.width dd ? +.height dd 9 + dd 4, 2 + dd aFileSearch + dd ? + dd 0 + dd 0, 0 + dd 10 +; строка-приглашение для ввода маски + dd 1 + dd 1,0,aFileMasksLen,0 + dd aFileMasks + dd 0 +; поле ввода для маски + dd 3 + dd 1, 1 +.width2 dd ? + dd 1 +.editptr1 dd ? + dd 0xC +; строка-приглашение для текста поиска + dd 1 + dd 1,2,aContainingTextLen,2 + dd aContainingText + dd 0 +; поле ввода для текста поиска + dd 3 + dd 1, 3 +.width3 dd ? + dd 3 +.editptr2 dd ? + dd 8 +; горизонтальный разделитель + dd 4 + dd -1,4 + dd -1,4 + dd 0 + dd 0 +; флажок "Учитывать регистр" + dd 5 + dd 1,5 + dd -1,5 + dd aCaseSensitive +.flags_case dd ? ; will be initialized from find_in_file_dlgdata +; флажок "Только целые слова" + dd 5 + dd 1,6 + dd -1,6 + dd aWholeWords +.flags_whole dd ? ; will be initialized from find_in_file_dlgdata +; горизонтальный разделитель + dd 4 + dd -1,7 + dd -1,7 + dd 0 + dd 0 +; кнопка "Искать" +.search_btn: + dd 2 +.search_x1 dd ? + dd 8 +.search_x2 dd ? + dd 8 + dd aSearchB + dd 18h +; кнопка "отменить" + dd 2 +.cnl_x1 dd ? + dd 8 +.cnl_x2 dd ? + dd 8 + dd aCancelB + dd 8 +.size = $ - filesearch_query_template + +; второй диалог поиска в файлах (сканирование) +filesearch_search_template: + dd 1 +.x dd ? +.y dd ? +.width dd ? +.height dd ? + dd 4, 2 +.caption dd ? + dd ? + dd 0 + dd 0, 0 + dd 9 +; список найденных файлов + dd 6 + dd 0, 0 +.width1 dd ? +.height1 dd ? +.data1 dd ? + dd 0 +; горизонтальный разделитель + dd 4 + dd -1 +.y2 dd ? + dd -1 + dd ? + dd 0, 0 +; строка "Поиск в:" либо "Поиск закончен..." + dd 1 + dd 1 +.y3 dd ? +.width3 dd ? + dd ? +.data3 dd ? + dd 0 +; строка с текущей папкой + dd 1 +.x4 dd ? +.y4 dd ? +.width4 dd ? + dd ? +.data4 dd ? + dd 0 +; горизонтальный разделитель + dd 4 + dd -1 +.y5 dd ? + dd -1 + dd ? + dd 0, 0 +; кнопки +.btn1: + dd 2 +.btn1x1 dd ? +.btn1y dd ? +.btn1x2 dd ? + dd ? + dd aNewSearch + dd 8 +.btn2: + dd 2 +.btn2x1 dd ? +.btn2y dd ? +.btn2x2 dd ? + dd ? + dd aGoto + dd 1Ch +.btn3: + dd 2 +.btn3x1 dd ? +.btn3y dd ? +.btn3x2 dd ? + dd ? + dd aView + dd 8 +.btn4: + dd 2 +.btn4x1 dd ? +.btn4y dd ? +.btn4x2 dd ? + dd ? + dd aCancelB2 + dd 8 +.size = $ - filesearch_search_template + RetryOrCancelBtn: dd aRetry dd a_Cancel @@ -7708,18 +8068,23 @@ DeleteOrCancelBtn: dd a_Cancel DeleteErrorBtn: dd aRetry +SkipOrCancelBtn: dd aSkip dd aSkipAll dd a_Cancel ContinueBtn: dd aContinue - EditorExitBtn: dd aSave dd aDontSave dd aContinueEdit +YesOrNoBtn: + dd aYes + dd aNo aCannotOpenFile_ptr dd aCannotOpenFile +aCannotCreateThread_ptr dd aCannotCreateThread +ConfirmCancelMsg dd aConfirmCancel EditConfigErr_ptr: dd aEditConfigErr1 dd aEditConfigErr2 @@ -7731,6 +8096,8 @@ aConfirmDeleteTextMax = $ - aConfirmDeleteText - 2 aDeleteFile db ' файл',0 aCancelB db '[ Отменить ]',0 aCancelBLength = $ - aCancelB - 1 +aCancelB2 db '[ Отмена ]',0 +aCancelB2Length = $ - aCancelB2 - 1 aCopyCaption db 'Копирование',0 aCopy db '[ Копировать ]',0 aCopyLength = $ - aCopy - 1 @@ -7745,6 +8112,8 @@ a_Cancel db ' a_Delete db 'Удалить',0 aSkip db 'Пропустить',0 aSkipAll db 'Пропустить все',0 +aYes db 'Да',0 +aNo db 'Нет',0 error0msg db 'Странно... Нет ошибки',0 error1msg db 'Странно... Не определена база и/или раздел жёсткого диска',0 error2msg db 'Функция не поддерживается для данной файловой системы',0 @@ -7793,8 +8162,32 @@ aTables db ' aSelect db 'Пометить',0 aDeselect db 'Снять',0 aCannotOpenFile db 'Ошибка при открытии файла',0 +aCannotCreateThread db 'Ошибка при создании потока',0 aCannotSetFolder db 'Не могу зайти в папку',0 aSearch db 'Поиск',0 +aSearchB db '[ Искать ]',0 +aSearchBLength = $ - aSearchB - 1 +aSearchFor db 'Искать',0 +aSearchForLen = $ - aSearchFor - 1 +aCaseSensitive db 'Учитывать регистр',0 +aWholeWords db 'Только целые слова',0 +aReverseSearch db 'Обратный поиск',0 +aStringNotFound db 'Строка не найдена',0 +aFileSearch db 'Поиск файла',0 +aFileMasks db 'Одна или несколько масок файлов:',0 +aFileMasksLen = $ - aFileMasks - 1 +aContainingText db 'Содержащих текст:',0 +aContainingTextLen = $ - aContainingText - 1 +aSearchingIn db 'Поиск "" в:',0 +aSearchingInLen = $ - aSearchingIn - 1 +aSearchDone db 'Поиск закончен. Найдено ? файл(ов)',0 +aSearchDoneLen = $ - aSearchDone - 1 +aNewSearch db '[ Новый поиск ]',0 +aNewSearchLen = $ - aNewSearch - 1 +aGoto db '[ Перейти ]',0 +aGotoLen = $ - aGoto - 1 +aView db '[ Смотреть ]',0 +aViewLen = $ - aView - 1 aEditConfigErr1 db 'Ошибка в конфигурации плагинов для редактора.',0 aEditConfigErr2 db 'Попробуйте убрать лишние плагины.',0 aEditNoMemory db 'Файл слишком велик для загрузки в редактор.',0 @@ -7806,6 +8199,9 @@ aSave db ' aDontSave db 'Не сохранять',0 aContinueEdit db 'Продолжить редактирование',0 aCannotSaveToPlugin db 'Сохранение файлов на панелях плагинов не поддерживается',0 +aCannotSearchOnPlugin db 'Поиск на панелях плагинов не поддерживается',0 +aCancelled db 'Действие было прервано',0 +aConfirmCancel db 'Вы действительно хотите отменить действие?',0 else aDeleteCaption db 'Delete',0 aConfirmDeleteText db 'Do you wish to delete',0 @@ -7832,6 +8228,8 @@ a_Cancel db 'Cancel',0 a_Delete db 'Delete',0 aSkip db 'Skip',0 aSkipAll db 'Skip all',0 +aYes db 'Yes',0 +aNo db 'No',0 error0msg db 'Strange... No error',0 error1msg db 'Strange... Hard disk base and/or partition not defined',0 error2msg db 'The file system does not support this function',0 @@ -7880,8 +8278,30 @@ aTables db 'Tables',0 aSelect db 'Select',0 aDeselect db 'Deselect',0 aCannotOpenFile db 'Cannot open the file',0 -aCannotSetFolder db 'Cannot enter to folder',0 +aCannotCreateThread db 'Cannot create a thread',0 +aCannotSetFolder db 'Cannot enter to the folder',0 aSearch db 'Search',0 +aSearchB db '[ Search ]',0 +aSearchBLength = $ - aSearchB - 1 +aSearchFor db 'Search for',0 +aSearchForLen = $ - aSearch - 1 +aCaseSensitive db 'Case sensitive',0 +aWholeWords db 'Whole words',0 +aReverseSearch db 'Reverse search',0 +aStringNotFound db 'Could not find the string',0 +aFileSearch db 'Find file',0 +aFileMasks db 'A file mask or several file masks:',0 +aContainingText db 'Containing text:',0 +aSearchingIn db 'Searching "" in:',0 +aSearchingInLen = $ - aSearchingIn - 1 +aSearchDone db 'Search done. Found ? file(s)',0 +aSearchDoneLen = $ - aSearchDone - 1 +aNewSearch db '[ New search ]',0 +aNewSearchLen = $ - aNewSearch - 1 +aGoto db '[ Go to ]',0 +aGotoLen = $ - aGoto - 1 +aView db '[ View ]',0 +aViewLen = $ - aView - 1 aEditConfigErr1 db 'Error in configuration of plugins for the editor.',0 aEditConfigErr2 db 'Try to remove unnecessary plugins.',0 aLine db ' Line' @@ -7892,6 +8312,8 @@ aSave db 'Save',0 aDontSave db 'Do not save',0 aContinueEdit db 'Continue editing',0 aCannotSaveToPlugin db 'Saving is not supported for plugin panels',0 +aCancelled db 'Operation has been interrupted',0 +aConfirmCancel db 'Do you really want to cancel it?',0 end if aOk db 'OK',0 @@ -8263,6 +8685,7 @@ screens dd ? num_screens dd ? active_screen_vtable dd ? active_screen_data dd ? +active_screen_keybar dd ? default_attr dd ? left_dotdot_entry rb 40+4 ; 40 bytes for attributes + '..' @@ -8273,12 +8696,20 @@ CopySourceTextBuf rb 512 CopyDestEditBuf rb 12+512+1 .length = $ - CopyDestEditBuf - 13 +SearchStringEditBuf rb 12 +SearchString rb 253+1 +SearchStringEditBuf.length = $ - SearchString - 1 + db ? ; used for output (string -> "string") + enter_string_buf rb 12+512+1 bMemForImageValidData db ? align 4 +identical_table rb 256 tolower_table rb 256 +isspace_table rb 256 +composite_table rb 256 layout rb 128 copy_buffer_size = 65536 diff --git a/programs/fs/kfar/trunk/kfar.txt b/programs/fs/kfar/trunk/kfar.txt index 6751c4deda..358d0e142f 100644 --- a/programs/fs/kfar/trunk/kfar.txt +++ b/programs/fs/kfar/trunk/kfar.txt @@ -42,6 +42,7 @@ Alt+< т ъюЄюЁюь ьюцэю ттюфшЄ№ фры№эхщ°шх ёшьтюы√ шьхэш Їрщыр фы  єЄюўэхэш , р Єръцх Ctrl+Enter/Shift+Ctrl+Enter фы  яхЁхьх∙хэш  ъ ёыхфє■∙хьє/яЁхф√фє∙хьє ¤ыхьхэЄє ярэхыш, шь  ъюЄюЁюую эрўшэрхЄё  ё ттхф╕ээ√ї сєът +Alt+F7 - т√чют фшрыюур яюшёър Їрщыют ┬ яЁюёьюЄЁ∙шъх: Esc = F3 = F10 = Numpad5 - т√їюф @@ -66,6 +67,10 @@ Shift+F8 - F12 - т√чют ьхэ■ ¤ъЁрэют Alt+F9 - ЁрчтюЁрўштрэшх юъэр ъ ьръёшьры№эю тючьюцэ√ь ЁрчьхЁрь ш тюёёЄрэютыхэшх ЁрчьхЁют +F7 - яюшёъ ёЄЁюъш ё Єхъє∙хщ яючшЎшш т Їрщых + (ёЄЁюър ш эрёЄЁющъш яюшёър чрфр■Єё  т яю ты ■∙хьё  фшрыюух) +Shift+F7 - яЁюфюыцхэшх яюшёър ёЄЁюъш + (шёяюы№чє■Єё  яюёыхфэшх чрфрээ√х эрёЄЁющъш яюшёър ш ёЄЁюър) ┬ ЁхфръЄюЁх: Esc = F10 - т√їюф; хёыш Їрщы с√ы ьюфшЇшЎшЁютрэ, яюёыхфєхЄ тюяЁюё ю @@ -86,6 +91,10 @@ Ins - F12 - т√чют ьхэ■ ¤ъЁрэют Alt+F9 - ЁрчтюЁрўштрэшх юъэр ъ ьръёшьры№эю тючьюцэ√ь ЁрчьхЁрь ш тюёёЄрэютыхэшх ЁрчьхЁют +F7 - яюшёъ ёЄЁюъш ё Єхъє∙хщ яючшЎшш т Їрщых + (ёЄЁюър ш эрёЄЁющъш яюшёър чрфр■Єё  т яю ты ■∙хьё  фшрыюух) +Shift+F7 - яЁюфюыцхэшх яюшёър ёЄЁюъш + (шёяюы№чє■Єё  яюёыхфэшх чрфрээ√х эрёЄЁющъш яюшёър ш ёЄЁюър) diamond mailto:diamondz@land.ru diff --git a/programs/fs/kfar/trunk/search.inc b/programs/fs/kfar/trunk/search.inc new file mode 100644 index 0000000000..a8d3ccd9e1 --- /dev/null +++ b/programs/fs/kfar/trunk/search.inc @@ -0,0 +1,203 @@ +; in: ebx -> pattern (not empty zero-terminated string), esi -> translation table, +; dword [esp+4] = encoding, byte [esp+8] non-zero for whole words only +; out: edx and ecx -> preprocessed data +; when search will be done, edx must be pgfree()d +search_string_pre: +; FSM is used, number of states is limited by 256, so pattern length must be <= 255 +; anyway, for big patterns FSM uses too many memory, so probably it is not best choice +; get pattern length, m + or ecx, -1 +@@: + inc ecx + cmp byte [ecx+ebx], 0 + jnz @b + cmp byte [esp+8], 0 + jz @f + inc ecx + inc ecx +@@: + push ecx +; allocate m*257 bytes for FSM and prefix function + imul ecx, 257 + call xpgalloc + pop ecx + test eax, eax + jnz @f + ret 8 +@@: + shl ecx, 8 + push eax + add eax, ecx +; calculate prefix function + xor ecx, ecx + mov byte [eax], cl + xor edi, edi + cmp byte [esp+4+8], 0 + jnz .whole.prefixcalc +.prefixcalc: + inc edi + movzx edx, byte [ebx+edi] + mov dl, [esi+edx] + test dl, dl + jz .prefixdone +@@: + push eax + movzx eax, byte [ebx+ecx] + cmp dl, [esi+eax] + pop eax + jz @f + jecxz .prefixint + mov cl, byte [eax+ecx-1] + jmp @b +@@: + inc ecx +.prefixint: + mov [eax+edi], cl + jmp .prefixcalc +.whole.prefixcalc: + inc edi + movzx edx, byte [ebx+edi-1] + mov dl, [esi+edx] + test dl, dl + jz .whole.prefixdone +.whole.prefixloop: + jecxz .whole.testfirst + push eax + movzx eax, byte [ebx+ecx-1] + cmp dl, [esi+eax] + pop eax + jz @f + mov cl, byte [eax+ecx-1] + jmp .whole.prefixloop +.whole.testfirst: + cmp [isspace_table+edx], 0 + jz .whole.prefixint +@@: + inc ecx +.whole.prefixint: + mov [eax+edi], cl + jmp .whole.prefixcalc +.whole.prefixdone: + jecxz @f + push eax + movzx eax, byte [ebx+ecx-1] + mov al, [esi+eax] + cmp [isspace_table+eax], 0 + pop eax + jnz @f + mov cl, byte [eax+ecx-1] + jmp .whole.prefixdone +@@: + inc ecx + mov [eax+edi], cl +.prefixdone: + pop edx +; create reverse table for encoding+translation + push ebp + movzx ebp, byte [esp+8] + cmp ebp, encodings.unicode + jb @f + xor ebp, ebp ; no translations for Unicode encodings, + ; they must be handled separately by caller +@@: + mov ecx, 256 +@@: + push 0 + loop @b + push ebx eax + mov ebx, esp + shl ebp, 7 + xor eax, eax +.createrev: + dec cl + mov al, cl + jns @f + mov al, byte [encodings.tables+ebp+ecx-80h] +@@: + mov al, [esi+eax] + pushd [ebx+8+eax*4] + pushd ecx + mov [ebx+8+eax*4], esp + jnz .createrev +@@: + dec cl + mov al, [esi+ecx] + pushd [ebx+8+eax*4] + popd [ebx+8+ecx*4] + jnz @b +; create FSM + xor ecx, ecx + cmp byte [ebx+259*4+8], 0 + mov eax, [ebx] + mov ebx, [ebx+4] + mov edi, edx + jz .fsmcalc + mov esi, isspace_table + push 256/4 + pop ecx + rep movsd + inc ecx +.fsmcalc: + movzx esi, byte [eax+ecx] + push eax + push ecx + push 256/4 + pop ecx + dec esi + js .fsmzero + shl esi, 8 + add esi, edx + rep movsd + jmp .fsmnext +.fsmzero: + cmp byte [esp+261*4+256*8+8], 0 + jnz .whole.fsmzero + xor eax, eax + rep stosd + jmp .fsmnext +.whole.fsmzero: + mov esi, edx + rep movsd +.fsmnext: + pop ecx + movzx esi, byte [ebx] + inc ecx + mov esi, [esp+4+8*256+8+esi*4] +@@: + test esi, esi + jz @f + lodsd + mov [edi-256+eax], cl + mov esi, [esi] + jmp @b +@@: + inc ebx + pop eax + cmp byte [ebx], 0 + jnz .fsmcalc + cmp byte [esp+259*4+256*8+8], 0 + jz .nowholefin + movzx esi, byte [eax+ecx] + push ecx + mov ecx, 256 + push 256/4 + pop ecx + dec esi + shl esi, 8 + add esi, edx + rep movsd + pop ecx + inc ecx + xor eax, eax +.whole.fsmfin: + cmp [isspace_table+eax], ah + jz @f + mov byte [edi-256+eax], cl +@@: + inc al + jnz .whole.fsmfin +.nowholefin: +; ok, now edx -> FSM, cl = final state + add esp, 8*256+8+4*256 + pop ebp + ret 8 diff --git a/programs/fs/kfar/trunk/viewer.inc b/programs/fs/kfar/trunk/viewer.inc index 1f61f5299f..2c7826133c 100644 --- a/programs/fs/kfar/trunk/viewer.inc +++ b/programs/fs/kfar/trunk/viewer.inc @@ -15,6 +15,8 @@ viewer_data: ; & 4: big-endian unicode .bEofReached db ? rb 1 + .selected_start dq ? + .selected_len dq ? align 200h .filename rb 1024 .hostname rb 1024 @@ -23,22 +25,30 @@ viewer_data: end virtual view_file: - mov eax, [ebp + panel1_files - panel1_data] - mov ecx, [eax+ecx*4] - test byte [ecx], 10h - jz .file - ret -.file: - lea esi, [ebp + panel1_dir - panel1_data] - push ecx + push eax ecx mov ecx, viewer_data.size mov edx, viewer_vtable call new_screen pop ecx test eax, eax + pop eax jnz @f ret @@: + test eax, eax + jz .frompanel + and dword [ebp+viewer_data.hPlugin], 0 + and dword [ebp+viewer_data.hFile], 0 + mov byte [ebp+viewer_data.hostname], 0 + lea edi, [ebp+viewer_data.filename] + push edi +@@: + lodsb + stosb + test al, al + jnz @b + jmp .namecopied +.frompanel: mov eax, dword [esi+panel1_hPlugin-panel1_dir] mov [ebp+viewer_data.hPlugin], eax test eax, eax @@ -63,10 +73,6 @@ view_file: .nocopyhostname: mov eax, dword [esi+panel1_hFile-panel1_dir] mov [ebp+viewer_data.hFile], eax - mov [ebp+viewer_data.encoding], encodings.cp866 - mov [ebp+viewer_data.flags], 0 - and dword [ebp+viewer_data.col], 0 - and dword [ebp+viewer_data.col+4], 0 lea edi, [ebp+viewer_data.filename] push edi @@: @@ -86,6 +92,13 @@ view_file: stosb test al, al jnz @b +.namecopied: + xor eax, eax + mov [ebp+viewer_data.encoding], al ;encodings.cp866 = 0 + mov [ebp+viewer_data.flags], al + mov dword [ebp+viewer_data.col], eax + mov dword [ebp+viewer_data.col+4], eax + call viewer_clear_selection pop eax push eax mov ebx, attrinfo @@ -221,8 +234,7 @@ viewer_OnRedraw: call viewer_draw_text ret -viewer_get_next_char: - pusha +viewer_skip_unicode_marker: cmp [ebp+viewer_data.encoding], encodings.unicode jnz @f cmp [bForHex], 0 @@ -241,15 +253,9 @@ viewer_get_next_char: .skip: add [ebp+viewer_data.buf_pos], 2 @@: - mov eax, [ebp+viewer_data.buf_pos] - lea ecx, [ebp+viewer_data.buf] - add ecx, [ebp+viewer_data.buf_size] - cmp eax, ecx - jb .buffered - mov al, ' ' - sub ecx, ebp - cmp ecx, viewer_data.buf + 16384 - jb .err + ret + +viewer_load_next: mov eax, dword [ebp+viewer_data.buf_start] add eax, 8192 mov dword [ebp+viewer_data.buf_start], eax @@ -300,7 +306,22 @@ viewer_get_next_char: add ebx, 16384-8192 mov [ebp+viewer_data.buf_size], ebx mov eax, [ebp+viewer_data.buf_pos] - cmp ecx, 16384-8192 + cmp ebx, 16384-8192 + ret + +viewer_get_next_char: + pusha + call viewer_skip_unicode_marker + mov eax, [ebp+viewer_data.buf_pos] + lea ecx, [ebp+viewer_data.buf] + add ecx, [ebp+viewer_data.buf_size] + cmp eax, ecx + jb .buffered + mov al, ' ' + sub ecx, ebp + cmp ecx, viewer_data.buf + 16384 + jb .err + call viewer_load_next jnz .buffered .err: stc @@ -408,6 +429,13 @@ uni2ansi_char: add al, 0xA0 ret +viewer_clear_selection: + and dword [ebp+viewer_data.selected_start], 0 + and dword [ebp+viewer_data.selected_start+4], 0 + and dword [ebp+viewer_data.selected_len], 0 + and dword [ebp+viewer_data.selected_len+4], 0 + ret + fld_uint64: fild qword [eax] test byte [eax+7], 80h @@ -698,6 +726,7 @@ end if div ecx pop eax sub ecx, edx + pop edx add eax, ecx test [ebp+viewer_data.flags], 2 jnz @f @@ -713,7 +742,6 @@ end if call .write_char loop @b pop ecx - pop edx jmp .1 .done: setc [ebp+viewer_data.bEofReached] @@ -971,6 +999,24 @@ end if .do: mov al, [esp] mov ah, [view_normal_color] + push edx + mov ecx, [ebp+viewer_data.buf_pos] + sub ecx, ebp + sub ecx, viewer_data.buf + 1 + xor edx, edx + add ecx, dword [ebp+viewer_data.buf_start] + adc edx, dword [ebp+viewer_data.buf_start+4] + sub ecx, dword [ebp+viewer_data.selected_start] + sbb edx, dword [ebp+viewer_data.selected_start+4] + cmp edx, dword [ebp+viewer_data.selected_len+4] + ja .color_ok + jb @f + cmp ecx, dword [ebp+viewer_data.selected_len] + jae .color_ok +@@: + mov ah, [view_selected_color] +.color_ok: + pop edx stosw .skip: pop eax ecx @@ -1585,6 +1631,179 @@ viewer_OnKey: adc dword [ebp+viewer_data.cur_pos+4], 0 and dword [ebp+viewer_data.cur_pos], not 1 jmp .done_redraw_keybar +.f7: + call viewer_clear_selection + call find_in_file_dlg + jz .shift_f7 +.ret2: + ret +.shift_f7: +; search string SearchString in file starting from current position + cmp byte [SearchString], 0 + jz .ret2 + mov eax, dword [ebp+viewer_data.selected_start] + mov edx, dword [ebp+viewer_data.selected_start+4] + inc eax + jnz @f + inc edx +@@: + cmp dword [ebp+viewer_data.selected_len], 0 + jnz @f + cmp dword [ebp+viewer_data.selected_len+4], 0 + jnz @f + mov eax, dword [ebp+viewer_data.cur_pos] + mov edx, dword [ebp+viewer_data.cur_pos+4] +@@: + call viewer_clear_selection + call viewer_seek + call viewer_skip_unicode_marker + mov esi, tolower_table + test [find_in_file_dlgdata.flags_case], 10h + jz @f + mov esi, identical_table +@@: + mov ebx, SearchString + test [find_in_file_dlgdata.flags_whole], 10h + setnz al + push eax + push dword [ebp+viewer_data.encoding] + call search_string_pre + mov esi, [ebp+viewer_data.buf_pos] + lea ebx, [ebp+viewer_data.buf] + add ebx, [ebp+viewer_data.buf_size] + mov edi, edx + cmp esi, ebx + jb @f + sub ebx, ebp + cmp ebx, viewer_data.buf + 16384 + jnz .f7.notfound + pusha + call viewer_load_next + popa + jz .f7.notfound + mov esi, [ebp+viewer_data.buf_pos] + lea ebx, [ebp+viewer_data.buf] + add ebx, [ebp+viewer_data.buf_size] +@@: + test [find_in_file_dlgdata.flags_whole], 10h + jz .search_loop + cmp dword [ebp+viewer_data.buf_start], 0 + jnz @f + cmp dword [ebp+viewer_data.buf_start+4], 0 + jnz @f + lea eax, [ebp+viewer_data.buf] + cmp [ebp+viewer_data.buf_pos], eax + jz .f7.startspace +@@: + xor eax, eax + call viewer_get_prev_char + inc esi + cmp [isspace_table+eax], 0 + jz .search_loop +.f7.startspace: + add edi, 256 +.search_loop: +; edx -> FSM, ecx = last state, edi = current state, +; esi = buf_pos, ebx = end of buffer +; get current symbol + movzx eax, byte [esi] +; calculate next state + movzx edi, byte [edi+eax] +; done? + cmp edi, ecx + jz .f7.found +.search_loop_next: +; no; proceed to next symbol + shl edi, 8 + add esi, 1 + add edi, edx + cmp esi, ebx + jb .search_loop + sub ebx, ebp + cmp ebx, viewer_data.buf + 16384 + jnz .f7.notfound + mov [ebp+viewer_data.buf_pos], esi + pusha + call viewer_load_next + popa + jz .f7.notfoundt + mov esi, [ebp+viewer_data.buf_pos] + lea ebx, [ebp+viewer_data.buf] + add ebx, [ebp+viewer_data.buf_size] + jmp .search_loop +.f7.notfoundt: +; last chance - if we are looking for a whole word, EOF is ok for last symbol + test [find_in_file_dlgdata.flags_whole], 10h + jz .f7.notfound + movzx edi, byte [edi+' '] + inc esi + cmp edi, ecx + jz .f7.found +.f7.notfound: + call search_failed + jmp .done_redraw +.f7.found: + push ecx + mov ecx, edx + call pgfree + mov [ebp+viewer_data.buf_pos], esi + call viewer_set_curpos + pop ecx + mov dword [ebp+viewer_data.selected_len], ecx + and dword [ebp+viewer_data.selected_len+4], 0 + dec ecx + sub eax, ecx + sbb edx, 0 + mov dword [ebp+viewer_data.selected_start], eax + mov dword [ebp+viewer_data.selected_start+4], edx + inc eax + jnz @f + inc edx +@@: + test [find_in_file_dlgdata.flags_whole], 10h + jz @f + sub dword [ebp+viewer_data.selected_len], 2 + sbb dword [ebp+viewer_data.selected_len+4], 0 + mov dword [ebp+viewer_data.selected_start], eax + mov dword [ebp+viewer_data.selected_start+4], edx + inc eax + jnz @f + inc edx +@@: + mov dword [ebp+viewer_data.cur_pos], eax + mov dword [ebp+viewer_data.cur_pos+4], edx + call viewer_seek + call viewer_prev_newline + jmp .done_redraw + +search_failed: + mov ecx, edx + call pgfree + mov eax, SearchString-1 + push dword [eax-3] + push eax + mov byte [eax], '"' +@@: + inc eax + cmp byte [eax], 0 + jnz @b + mov word [eax], '"' + xchg eax, [esp] + push eax + push aStringNotFound + mov eax, esp + push ContinueBtn + push 1 + push eax + push 2 + push aSearch + call SayErrTitle + pop eax + pop eax + pop ecx + mov byte [ecx], 0 + pop dword [eax-3] + ret viewer_getname: if lang eq ru