From 9c17418f43f35a39bdd2aa8a46e35754d2582106 Mon Sep 17 00:00:00 2001 From: Tolik <85737314+Tolik-Trek@users.noreply.github.com> Date: Thu, 3 Apr 2025 20:29:32 +1000 Subject: [PATCH] begin --- .gitmodules | 3 + FM.ASM | 253 ++++ FVIEW/CHFONT.ASM | 133 ++ FVIEW/FVIEW.ASM | 2879 ++++++++++++++++++++++++++++++++++++++++++ FVIEW/FVIEW.INC | 195 +++ FVIEW/FVIEW.Z80 | 14 + FVIEW/MSFVIEW.ASM | 216 ++++ FVIEW/SETVIEW.ASM | 151 +++ MAIN.ASM | 521 ++++++++ MOD0/CHDISK.ASM | 51 + MOD0/CURSOR.ASM | 62 + MOD0/KEYBDRV.ASM | 649 ++++++++++ MOD0/LISTDRV.ASM | 207 +++ MOD0/MOUSEDRV.ASM | 373 ++++++ MOD0/USERMENU.ASM | 548 ++++++++ MOD0/VECTORS.ASM | 104 ++ MOD1/ABORT.Z80 | 30 + MOD1/BUFFERS.ASM | 183 +++ MOD1/CHDISK.Z80 | 27 + MOD1/COLOR.ASM | 55 + MOD1/COLOR.Z80 | 187 +++ MOD1/COMLINE.ASM | 1225 ++++++++++++++++++ MOD1/CONFIRM.ASM | 54 + MOD1/CONFIRM.Z80 | 55 + MOD1/COPY.Z80 | 103 ++ MOD1/DELETE.Z80 | 57 + MOD1/DIALERR.Z80 | 449 +++++++ MOD1/HMENU.Z80 | 128 ++ MOD1/INFO.Z80 | 208 +++ MOD1/INFO2.Z80 | 139 ++ MOD1/INTRFACE.ASM | 105 ++ MOD1/INTRFACE.Z80 | 72 ++ MOD1/MKDIR.Z80 | 42 + MOD1/PANELS.Z80 | 509 ++++++++ MOD1/PULLCMND.ASM | 239 ++++ MOD1/QUIT.Z80 | 30 + MOD1/QVIEW.Z80 | 90 ++ MOD1/RENAME.Z80 | 69 + MOD1/SELDRV.ASM | 110 ++ MOD1/SETCOLOR.ASM | 209 +++ MOD1/SORT.ASM | 447 +++++++ MOD1/SPACE.Z80 | 14 + MOD1/TREE.ASM | 339 +++++ MOD1/UMENU.Z80 | 9 + MOD1/WIDTH.ASM | 71 ++ MOD2/CLOCK.ASM | 104 ++ MOD2/COPY.ASM | 302 +++++ MOD2/DEBUG.ASM | 182 +++ MOD2/DELETE.ASM | 334 +++++ MOD2/ENTER.ASM | 228 ++++ MOD2/EVENT.ASM | 57 + MOD2/FILLSTR.ASM | 560 ++++++++ MOD2/HILIGHT.ASM | 170 +++ MOD2/INFO.ASM | 611 +++++++++ MOD2/KEYBAR.ASM | 344 +++++ MOD2/LAUNCH.ASM | 364 ++++++ MOD2/MKDIR.ASM | 104 ++ MOD2/MOUSE.ASM | 362 ++++++ MOD2/POS.ASM | 100 ++ MOD2/QVIEW.ASM | 487 +++++++ MOD2/READDSK.ASM | 157 +++ MOD2/RENAME.ASM | 106 ++ MOD2/SETUP.ASM | 523 ++++++++ MOD2/SPACE.ASM | 141 +++ MOD2/UTILS.ASM | 360 ++++++ MOD2/__COPY1.ASM | 271 ++++ OBJS/BUTTON.ASM | 229 ++++ OBJS/DIALOG.ASM | 1408 +++++++++++++++++++++ OBJS/DIALOG1.ASM | 64 + OBJS/HMENU.ASM | 1737 +++++++++++++++++++++++++ OBJS/INLINE.ASM | 1207 ++++++++++++++++++ OBJS/LISTBOX.ASM | 1072 ++++++++++++++++ OBJS/PALLETE.ASM | 1046 +++++++++++++++ OBJS/PROCESS.ASM | 262 ++++ OBJS/RADIO.ASM | 789 ++++++++++++ OBJS/UMENU.ASM | 614 +++++++++ SHELL.ASM | 2417 +++++++++++++++++++++++++++++++++++ SPEC/FUNCS.ASM | 159 +++ SPEC/VECT.ASM | 111 ++ Shared_Includes | 1 + VERSION.INC | 3 + fix.! | 1 + readme.txt | 13 + screens/screen01.gif | Bin 0 -> 18172 bytes screens/screen02.gif | Bin 0 -> 15675 bytes screens/screen03.gif | Bin 0 -> 27355 bytes screens/screen04.gif | Bin 0 -> 21890 bytes screens/screen05.gif | Bin 0 -> 13775 bytes screens/screen06.gif | Bin 0 -> 27324 bytes screens/screen07.gif | Bin 0 -> 27701 bytes screens/screen08.gif | Bin 0 -> 26717 bytes screens/screen09.gif | Bin 0 -> 27259 bytes 92 files changed, 28614 insertions(+) create mode 100644 .gitmodules create mode 100755 FM.ASM create mode 100755 FVIEW/CHFONT.ASM create mode 100755 FVIEW/FVIEW.ASM create mode 100755 FVIEW/FVIEW.INC create mode 100755 FVIEW/FVIEW.Z80 create mode 100755 FVIEW/MSFVIEW.ASM create mode 100755 FVIEW/SETVIEW.ASM create mode 100755 MAIN.ASM create mode 100755 MOD0/CHDISK.ASM create mode 100755 MOD0/CURSOR.ASM create mode 100755 MOD0/KEYBDRV.ASM create mode 100755 MOD0/LISTDRV.ASM create mode 100755 MOD0/MOUSEDRV.ASM create mode 100755 MOD0/USERMENU.ASM create mode 100755 MOD0/VECTORS.ASM create mode 100755 MOD1/ABORT.Z80 create mode 100755 MOD1/BUFFERS.ASM create mode 100755 MOD1/CHDISK.Z80 create mode 100755 MOD1/COLOR.ASM create mode 100755 MOD1/COLOR.Z80 create mode 100755 MOD1/COMLINE.ASM create mode 100755 MOD1/CONFIRM.ASM create mode 100755 MOD1/CONFIRM.Z80 create mode 100755 MOD1/COPY.Z80 create mode 100755 MOD1/DELETE.Z80 create mode 100755 MOD1/DIALERR.Z80 create mode 100755 MOD1/HMENU.Z80 create mode 100755 MOD1/INFO.Z80 create mode 100755 MOD1/INFO2.Z80 create mode 100755 MOD1/INTRFACE.ASM create mode 100755 MOD1/INTRFACE.Z80 create mode 100755 MOD1/MKDIR.Z80 create mode 100755 MOD1/PANELS.Z80 create mode 100755 MOD1/PULLCMND.ASM create mode 100755 MOD1/QUIT.Z80 create mode 100755 MOD1/QVIEW.Z80 create mode 100755 MOD1/RENAME.Z80 create mode 100755 MOD1/SELDRV.ASM create mode 100755 MOD1/SETCOLOR.ASM create mode 100755 MOD1/SORT.ASM create mode 100755 MOD1/SPACE.Z80 create mode 100755 MOD1/TREE.ASM create mode 100755 MOD1/UMENU.Z80 create mode 100755 MOD1/WIDTH.ASM create mode 100755 MOD2/CLOCK.ASM create mode 100755 MOD2/COPY.ASM create mode 100755 MOD2/DEBUG.ASM create mode 100755 MOD2/DELETE.ASM create mode 100755 MOD2/ENTER.ASM create mode 100755 MOD2/EVENT.ASM create mode 100755 MOD2/FILLSTR.ASM create mode 100755 MOD2/HILIGHT.ASM create mode 100755 MOD2/INFO.ASM create mode 100755 MOD2/KEYBAR.ASM create mode 100755 MOD2/LAUNCH.ASM create mode 100755 MOD2/MKDIR.ASM create mode 100755 MOD2/MOUSE.ASM create mode 100755 MOD2/POS.ASM create mode 100755 MOD2/QVIEW.ASM create mode 100755 MOD2/READDSK.ASM create mode 100755 MOD2/RENAME.ASM create mode 100755 MOD2/SETUP.ASM create mode 100755 MOD2/SPACE.ASM create mode 100755 MOD2/UTILS.ASM create mode 100755 MOD2/__COPY1.ASM create mode 100755 OBJS/BUTTON.ASM create mode 100755 OBJS/DIALOG.ASM create mode 100755 OBJS/DIALOG1.ASM create mode 100755 OBJS/HMENU.ASM create mode 100755 OBJS/INLINE.ASM create mode 100755 OBJS/LISTBOX.ASM create mode 100755 OBJS/PALLETE.ASM create mode 100755 OBJS/PROCESS.ASM create mode 100755 OBJS/RADIO.ASM create mode 100755 OBJS/UMENU.ASM create mode 100755 SHELL.ASM create mode 100755 SPEC/FUNCS.ASM create mode 100755 SPEC/VECT.ASM create mode 160000 Shared_Includes create mode 100755 VERSION.INC create mode 100755 fix.! create mode 100755 readme.txt create mode 100755 screens/screen01.gif create mode 100755 screens/screen02.gif create mode 100755 screens/screen03.gif create mode 100755 screens/screen04.gif create mode 100755 screens/screen05.gif create mode 100755 screens/screen06.gif create mode 100755 screens/screen07.gif create mode 100755 screens/screen08.gif create mode 100755 screens/screen09.gif diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 0000000..5c22af2 --- /dev/null +++ b/.gitmodules @@ -0,0 +1,3 @@ +[submodule "Shared_Includes"] + path = Shared_Includes + url = https://github.com/Tolik-Trek/Shared_Includes.git diff --git a/FM.ASM b/FM.ASM new file mode 100755 index 0000000..25e6256 --- /dev/null +++ b/FM.ASM @@ -0,0 +1,253 @@ +; Загрузчик ФМ + + + + include 'shared_includes/constants/Sp2000.inc' + include 'shared_includes/constants/bios_equ.inc' + include 'shared_includes/constants/dss_equ.inc' + include 'version.inc' ; версия менеджера +; include 'fm.exp' ; содержит "@label" метки + + + + org 4100h + + db "EXE" ; exe ID + db 0 ; exe версия + dw 512 ; 512, мл. смещ. кода + dw 0 ; ст. смещ. кода + dw end_loader - entry ; end-beg, первичный загрузчик + dw 0,0,0 ; резерв + dw entry ; адрес загрузки кода + dw start ; адрес передачи управления + dw start ; адрес стека + ds 490 + +entry: db "The File Manager, Version " + db major_version + "0" + db "." + db (minor_version / 10) + "0" + db (minor_version % 10) + "0" + db " Copyright (c) 2005-2007 by Vasil Ivanov." + + +start: + ; очистить буфер клавы + ld bc,3135h + rst ToDSS + di + ; сохр. значение портов + in a,(SLOT0) + ld (port_82__),a + in a,(SLOT3) + ld (port_E2__),a + in a,(89h) + ld (port_89__),a + ; сохр. дескриптор менеджера + ld a,(ix-3) + ld (hFile),a + ; закрыть спек. экран + ld a,0C0h + out (89h),a + ; выделить 10 стр. памяти + ld bc,0A3Dh + rst ToDSS + jr nc,ok_malloc ; Ok + ld a,(hFile) ; тек. дескриптор + ld c,12h ; закрыть exe-файл + rst ToDSS + ld hl,no_space ; нет памяти +abort: ei + ld c,5Ch + rst ToDSS + ld bc,0FF41h ; выход в ДОС + rst ToDSS + ret + +ok_malloc: ld (id_block__),a ; хэндл выдел. блока памяти + ; получить список страниц + ld hl,page_sys_screen__ + ld c,0C5h + rst 08h + ; узнать версию ДОС + ld c,0 + rst ToDSS + ld hl,013Ch ; 1.60 + and a + sbc hl,de + call nc,setup_znak ; =< 1.60 уст. знакоген. 19h/1Ah + ; распаковать модуль 1 + ;... + ; загрузить осн. код менеджера + ld a,(page_manager__) ; работает в #8000 + out (SLOT3),a + ld hl,0C000h + ld de,len_modul1 ; размер модуля 1 + ld a,(hFile) + ld c,13h + rst ToDSS + jp c,read_error + ; распаковать модуль 2 + ;... + ; загр. драйверы клавы/мышки, обработчики объектов и диал. окон + ld a,(page_module0__) ; работает в #0000 + out (SLOT3),a + ld hl,0C000h + ld de,len_modul2 ; размер модуля 2 + ld a,(hFile) + ld c,13h + rst ToDSS + jp c,read_error + ld a,(page_spec__) + ld (0C02Ah),a ; сохр. спек-страницу (vectors.asm) + ; распаковать модуль 3 + ;... + ; загрузить описатели панелей + ld a,(page_module1__) + out (SLOT3),a + ld hl,0C000h + ld de,len_modul3 ; размер модуля 3 + ld a,(hFile) + ld c,13h + rst ToDSS + jp c,read_error + ; распаковать модуль 4 + ;... + ; загрузить спек-код + ld a,(page_spec__) + out (SLOT3),a + ld hl,0C000h + ld de,len_modul4 ; размер модуля 4 + ld a,(hFile) + ld c,13h + rst ToDSS + jp c,read_error + ld a,(page_module0__) + ld (0C02Ah),a ; сохр. фм-страницу (vect.asm) + ; распаковать модуль 5 + ;... + ; загрузить вьюер + ld a,(page_viewer__) + out (SLOT3),a + ld hl,0C000h + ld de,len_modul5 ; размер вьюера + ld a,(hFile) + ld c,13h + rst ToDSS + jp c,read_error + ; + ; закрыть exe-файл менеджера +hFile+1: ld a,0 ; сохр. дескриптор менеджера + ld c,12h + rst ToDSS + ; вкл. в #8000 осн. код ФМ + ld a,(page_manager__) + out (SLOT2),a + ; перекачать хэндлы страниц + ld hl,id_block__ ; откуда + ld de,id_block ; куда + ld bc,pages_end - id_block__ + ldir + ; + ld sp,stack ; стек ФМ + ; не менять полож. мышки ФМ + ld c,3 ; узнать статус мышки + rst 30h + ld (Xcoord),hl ; координата X (0..639) + ld (Ycoord),de ; координата Y (0..255) + jp 8000h ; перейти на программу + + + + + +; Хэндлы страниц менеджера +id_block__: db -1 ; дескриптор выдел. блока памяти + ; +page_sys_screen__: + db -1 ; +#0000 сист.экран, +#1400 экран ФМ +page_dial_screen__: + db -1 ; буфер сохр. диал. окон и верт. меню +page_left_dir__: + db -1 ; список левой панели +page_right_dir__: + db -1 ; список правой панели +page_manager__: + db -1 ; осн. код менеджера +page_module0__: db -1 ; драйверы клавы, мышки, диал. код с обраб. +page_module1__: db -1 ; описатели панелей +page_spec__: db -1 ; страница разбора спек-функций +page_viewer__: db -1 ; страница вьюера + db -1 + db 0 ; стоп-байт + ; +port_82__: db -1 ; сохр. порт 82h +port_E2__: db -1 ; сохр. порт 0E2h +port_89__: db -1 ; сохр. порт 89h +pages_end: + + + + + +; ошибка загрузки менеджера +read_error: ld a,(id_block__) + ld c,3Eh ; освоб. выдел. блок памяти + rst ToDSS + ld a,(hFile) + ld c,12h ; закрыть файл + rst ToDSS + ld hl,load_err + jp abort + +no_space: db "Not enough memory to run program !",0Dh,0Ah,0 +load_err: db "Disk loading error !",0Dh,0Ah,0 + + +; Подготовить знакоген. для софт. курсора +setup_znak: ld a,(page_manager__) ; врем. буфер + out (SLOT2),a + ; получить сист. знакоген. + ld de,8000h ; буфер для 2048 байт данных + push de + ld c,0B8h ; получить знакоген. + rst 08h + ; заполнить кодом 0FFh 2 нижние линии + ld hl,8000h+(2048-(2*256)) ; последние 512 байт + ld bc,511 + ld a,1Ah ; номер знакоген. + call fill_data_font + pop hl + ; заполнить остальные 6 линий (полный блок) + ld bc,2048-513 + ld a,19h ; номер знакоген. +; Настройка знакоген. и его регистрация +; вход: a=номер знакоген. +; hl=данные +; bc=размер данных +fill_data_font: ld e,l + ld d,h + ld (hl),-1 + inc de + ldir + ld de,8000h ; знакоген. + ld c,0B6h ; уст. знакоген. + rst 08h + ret + + + +; депакер +;... + + +; Конец загрузчика +end_loader: + + + +;------------------------------------------------- +; Код менеджера +;------------------------------------------------- +; incbin 'Build/fm.bin' + include 'main.asm' diff --git a/FVIEW/CHFONT.ASM b/FVIEW/CHFONT.ASM new file mode 100755 index 0000000..6884e8e --- /dev/null +++ b/FVIEW/CHFONT.ASM @@ -0,0 +1,133 @@ +; вызов из hex-окна +change_code_page1: + ld hl,ABB87 ; вывести страницу hex-дампа + jr $+5 +; вызов из ascii-окна +change_code_page: + ld hl,AB390 ; вывести страницу текста + push hl ; вектор в стек + ld hl,code_page ; 0/1/2 (Dos/Win/Koi) + ld a,(hl) + inc a + cp 3 + jr nz,$+3 + xor a + ld (hl),a + push af + ld c,a + add a,a + add a,c + ld c,a + ld b,0 + ld a,(viewer_mode) ; 0/1 режим вьюера (норм./панельный) + or a + jr nz,ch_code_pg1 + ld hl,TAE00 ; "WinKoiDos" + ld de,TAE02 ; "DOSWINKOI" + add hl,bc + ex de,hl + add hl,bc + ex de,hl + push de + push hl + push hl + ld de,TA29D+1 ; F8-пункт ASCII key-бара + call ch_code_pg + pop hl + ld de,TA33D+1 ; F8-пункт HEX key-бара + call ch_code_pg + ; key-бар + ld de,1F39h ; Y/X полож. + ld c,84h ; уст. курсор + rst 08h + pop hl ; откуда + ld bc,0386h ; вывести строку в 3 символа + rst 08h + ; стат. строка + ld de,0023h ; Y/X полож. + ld c,84h ; уст. курсор + rst 08h + pop hl ; откуда + ld bc,0386h ; вывести строку в 3 символа + rst 08h +ch_code_pg1: + pop af ; тек. кодировка + ; кодовая таблица + ld hl,code_tables ; win-1251 + dec a + jr z,$+5 + ld hl,code_tables+128 ; koi8-r + ld (addr_code_table+1),hl + ret + +ch_code_pg: + ld bc,3 + ldir + ret + + + +;------------------------------------------------- +; Взять символ из кодовой таблицы +;------------------------------------------------- +char_code_page: + cp 80h ; "А" + ret c + db 0Eh ; ld c,.. +code_page: + db 0 + dec c + inc c + ret z + exx + and 7Fh + ld l,a + ld h,0 +addr_code_table: + ld bc,code_tables ; win-1251 + add hl,bc + ld a,(hl) + exx + ret + + + + +;------------------------------------------------- +; Коды 2-й половины ascii-таблицы +;------------------------------------------------- +code_tables: + ; windows-1251 + db 3Fh,3Fh,27h,3Fh,22h,3Ah,0C5h,0D8h + db 3Fh,25h,3Fh,3Ch,3Fh,3Fh,3Fh,3Fh + db 3Fh,27h,27h,22h,22h,07h,2Dh,2Dh + db 3Fh,54h,3Fh,3Eh,3Fh,3Fh,3Fh,3Fh + db 0FFh,0F6h,0F7h,3Fh,0FDh,3Fh,0B3h,15h + db 0F0h,63h,0F2h,3Ch,0BFh,2Dh,52h,0F4h + db 0F8h,2Bh,49h,69h,3Fh,0E7h,14h,0FAh + db 0F1h,0FCh,0F3h,3Eh,3Fh,3Fh,3Fh,0F5h + db 80h,81h,82h,83h,84h,85h,86h,87h + db 88h,89h,8Ah,8Bh,8Ch,8Dh,8Eh,8Fh + db 90h,91h,92h,93h,94h,95h,96h,97h + db 98h,99h,9Ah,9Bh,9Ch,9Dh,9Eh,9Fh + db 0A0h,0A1h,0A2h,0A3h,0A4h,0A5h,0A6h,0A7h + db 0A8h,0A9h,0AAh,0ABh,0ACh,0ADh,0AEh,0AFh + db 0E0h,0E1h,0E2h,0E3h,0E4h,0E5h,0E6h,0E7h + db 0E8h,0E9h,0EAh,0EBh,0ECh,0EDh,0EEh,0EFh + ; koi8-r + db 0C4h,0B3h,0DAh,0BFh,0C0h,0D9h,0C3h,0B4h + db 0C2h,0C1h,0C5h,0DFh,0DCh,0DBh,0DDh,0DEh + db 0B0h,0B1h,0B2h,0F4h,0FEh,0F9h,0FBh,0F7h + db 0F3h,0F2h,0FFh,0F5h,0F8h,0FDh,0FAh,0F6h + db 0CDh,0BAh,0D5h,0F1h,0D6h,0C9h,0B8h,0B7h + db 0BBh,0D4h,0D3h,0C8h,0BEh,0BDh,0BCh,0C6h + db 0C7h,0CCh,0B5h,0F0h,0B6h,0B9h,0D1h,0D2h + db 0CBh,0CFh,0D0h,0CAh,0D8h,0D7h,0CEh,0FCh + db 0EEh,0A0h,0A1h,0E6h,0A4h,0A5h,0E4h,0A3h + db 0E5h,0A8h,0A9h,0AAh,0ABh,0ACh,0ADh,0AEh + db 0AFh,0EFh,0E0h,0E1h,0E2h,0E3h,0A6h,0A2h + db 0ECh,0EBh,0A7h,0E8h,0EDh,0E9h,0E7h,0EAh + db 9Eh,80h,81h,96h,84h,85h,94h,83h + db 95h,88h,89h,8Ah,8Bh,8Ch,8Dh,8Eh + db 8Fh,9Fh,90h,91h,92h,93h,86h,82h + db 9Ch,9Bh,87h,98h,9Dh,99h,97h,9Ah diff --git a/FVIEW/FVIEW.ASM b/FVIEW/FVIEW.ASM new file mode 100755 index 0000000..20fc564 --- /dev/null +++ b/FVIEW/FVIEW.ASM @@ -0,0 +1,2879 @@ +; Вьюер файлов +; +; F8 - смена кодовой страницы (по кругу: dos/win/koi8-r) +; Esc, F3, F10 - выход из вьюера +; +; Перемещения по тексту: +;  курсор - на строку вверх +;  курсор - на строку вниз +; -> курсор - вправо +; <- курсор - влево +; PgUp - на страницу вверх +; PgDwn - на страницу вниз +; Home - в начало файла +; End - в конец файла +; Ctrl+ курсор - на страницу вверх +; Ctrl+ курсор - на страницу вниз +; Ctrl+PgUp - в начало файла +; Ctrl+PgDwn - в конец файла +; Ctrl+"->" - на 26 символов вправо +; Ctrl+"<-" - на 26 символов влево +; Мышка: +; левый бутон: +; текст по-строчно вверх - мышка в верхней половине окна +; текст по-строчно вниз - мышка в нижней половине окна +; правый бутон: +; X-скроллинг вправо - мышка в правой половине окна +; X-скроллинг влево - мышка в левой половине окна +; +; При клике на строке ввода адреса (Goto..), входим в режим редактирования +; строки. При клике за пределами строки ввода, выходим из режима редакти- +; рования с отменой изменений (равносильно нажатию Esc). +; + + + + + +;/////////////////////////////////////////////////////////// +; Вьюер +; +; вход: temp_fname=имя файла +; выход: A=код возврата +; CF - при ошибке, A=код ошибки +;/////////////////////////////////////////////////////////// +viewer: call setup_fview ; настроить константы + ; открыть окно "Please wait, reading file..." + ld hl,win_fview_load_file ; описатель окна + call WinSimple ; вывести окно + ; загр. файл + ld hl,temp_fname ; имя файла + call A837F ; вся работа по загрузке файла в страницы + push af + ; закрыть окно + call CloseWinSimple + pop af + jr c,viewer_exit ; ошибка + ; + ld a,(id_pages) ; идентиф. выдел. блока памяти + ld (D9F03),a + ld hl,(lsize__) ; мл.разряд размера файла + ld (D9F04),hl + ld hl,(hsize__) ; ст.разряд размера файла + ld (D9F06),hl + call save_screen ; сохр. экран + call main_viewer + call rest_screen ; восст. экран + ld a,0 ; код возврата + or a +viewer_exit: + push af + ; освоб. блок памяти + ld a,(id_pages) ; идентиф. блока памяти + ld c,0C3h + rst 08h + pop af + ret + + + + +; Запомнить содержимое окна +save_screen: + ld a,(viewer_mode) ; режим работы вьюера + or a + ret nz ; панельный режим + ld c,0B2h +sv_scrn__: + ld hl,2050h ; высота/ширина экрана + ld ix,0C000h+1400h ; буфер под окно + ld a,(page_sys_screen) ; страница буфера + ld b,a + xor a ; идентиф. глоб. окна + ld e,a ; X полож. + ld d,a ; Y полож. + di + rst 08h + ei + ret + +; Восстановить содержимое окна +rest_screen: + ld a,(viewer_mode) ; режим работы вьюера + or a + ret nz ; панельный режим + ld c,0B3h + jr sv_scrn__ + + + + +file_handle: + db -1 ; дескр. файла + +id_pages: + db -1 ; идентиф. выдел. блока памяти + +lsize__:dw 0 ; мл.разряд размера файла +hsize__:dw 0 ; ст.разряд + + + + + +;=========================================================== +; Вся работа по загрузке файла в страницы +; +; вход: hl=имя файла +;=========================================================== +A837F: ld a,1 ; на чтение + ld c,11h ; открыть файл + rst 10h + ret c + ld (file_handle),a ; дескр. файла + ld hl,0 + ld ix,0 + ld a,(file_handle) ; дескр. файла + ld bc,0215h ; указатель на конец файла + rst 10h + ld (hsize__),hl ; ст.разряд размера файла + ld (lsize__),ix ; мл.разряд + call get_mem_file ; расч. и выдел. страницы под файл + jr c,A83B3 ; не хватает памяти + call A83ED ; загрузить открытый файл в страницы +close_file: + ld a,(file_handle) ; дескр. файла + ld c,12h ; закрыть файл + rst 10h + ret + ; +A83B3: call close_file + ld a,30 ; код "нет памяти" + scf + ret + + +;------------------------------------------------- +; По размеру файла расчитать необходимое +; число страниц и выделить их. +; выход: CF - не хватает памяти +;------------------------------------------------- +get_mem_file: + ld hl,(hsize__) ; ст.разряд размера файла + ld bc,(lsize__) ; мл.разряд + ld de,4000h ; делитель (размер страницы) + xor a + scf +A83C9: rr d + rr e + jr c,A83DD + rr h + rr l + rr b + rr c + jr nc,A83C9 + ld a,1 + jr A83C9 + ; +A83DD: or a + jr z,A83E1 + inc bc +A83E1: xor a + cp b + scf + ret nz + ; выделить блок памяти + ld b,c ; b=число страниц + ld c,0C2h + rst 08h + ld (id_pages),a ; идентиф. блока + ret + + +;------------------------------------------------- +; Загрузить открытый файл в страницы +;------------------------------------------------- +A83ED: ld hl,0 + ld ix,0 + ld a,(file_handle) ; дескр. файла + ld bc,0015h ; указатель на начало файла + rst 10h + ld a,(id_pages) ; идентиф. блока памяти + ld b,0 ; лог. номер страницы в блоке + ld c,0C4h ; получить физ. номер страницы в блоке + rst 08h + ret c +A8404: push af + out (SLOT3),a + ld hl,LC000 ; куда + ld de,4000h ; сколько + ld a,(file_handle) ; дескр. + ld c,13h ; читать файл + rst 10h + pop bc + ret c ; ошибка чтения + inc a ; a=#FF (прочитано меньшее число байт) + ret z ; да + ld a,b ; a=физич. страница + ld c,0C7h ; получить след. номер физ. страницы блока + rst 08h + ret c + cp 255 + jr nz,A8404 ; не последняя страница + ret + + + + + +D9F03: db 0 ; 2-я ячейка списка выдел. страниц + ; +D9F04: dw 0 ; мл.разряд размера файла +D9F06: dw 0 ; ст.разряд размера файла + + + +; массив списка выдел. страниц +list_pages: + ds 255+1 + + +; текущий адрес в дампе +DA109: db 0 ; мл.разряд +DA10A: db 0 +DA10B: db 0 +DA10C: db 0 ; ст.разряд + +; тек. адрес ... ?? +DA10D: db 0 ; мл.разряд +DA10E: db 0 +DA10F: db 0 +DA110: db 0 ; ст.разряд + +DA111: dw 0 +DA113: dw 0 + + +; массив в 256 символов (пишется вывод. на экран строка) +TA115: ds 63 ;  80 симв. +TA154: ds 193 + + +; длина всей строки 80 символов +TA215: db "View: " +TA21B: db " " + db "Bytes " + + + +; статусная строка в ASCII-режиме +TA265: db "1 " +TA26D: db "2Wrap " + db "3 " + db "4Hex " + db "5 " + db "6 " + db "7 " +TA29D: db "8Win " + db "9 " + db "10Quit " + +; статусная строка в HEX-режиме +TA2B5: db "1 " + db "2 " + db "3 " + db "4Ascii " + db "5Goto " + db "6 " + db "7 " +TA33D: db "8Win " + db "9 " + db "10Quit " + + + +; массив 2460 байт +AA355: db 0 +AA356: ds 81 ;len_string+1 +AA3A7: ds 173 +AA454: ds 2205 + + +TACF1: ds 125 +TAD6E: ds 125 +TADEB: ds 125 +TAE68: ds 130 + + +UnWrap: db true ; 0/1 да/нет признак переноса строки + +TAEEF: db "UnWrapWrap " + +TAE00: db "WinKoiDos" +TAE02: db "DOSWINKOI" + +TAEFB: db " ",0 ; буфер вводимого адреса перехода + + +AAF04: ds 2 +DAF06: dw 0 + ds 3 + + + +;=========================================================== +; Начало осн. кода программы +;=========================================================== +main_viewer: + ld hl,0 + ld (DA109),hl ; сбр. тек. адрес в дампе + ld (DA10B),hl + call create_list_pages ; создать список выдел. страниц + ld iy,AAF04 + ld a,(viewer_mode) ; режим работы вьюера + or a + jp nz,AB317 ; в панели, вывести ascii-дамп + call AAF96 ; вывод имени файла в верх. стат. строке + ; очистить осн. окно + ld de,0 ; Y/X полож. окна + ld hl,2050h ; Y/X размеры + ld a,(color_array+39) ; 1Bh атрибут + ld b,a + ld c,89h ; очистка окна + rst 08h + ; очистить буфер номера колонки (посл. 2 цифры) + ld hl,TB1C7+1 ; буфер + ld a," " + ld (hl),a + inc hl + ld (hl),a + ; уст. курсор + ld de,0 ; Y/X + ld c,84h ; уст. курсор + rst 08h + ; окрасить верх. стат. строку + ld hl,TA215 ; буфер строки + ld a,(color_array+41) ; 30h атрибут + ld e,a +loc04: ld b,len_string ; 80 длина строки + ld c,85h ; вывести строку с атрибутом + rst 08h + ; вывести ascii-дамп + jp AB317 + + + +;------------------------------------------------- +; Вывод имени файла в верх. стат. строке +;------------------------------------------------- +AAF96: ld hl,temp_fname ; откуда + ld de,TA21B ; имя файла в стат. строке + push de + ld b,12 ; макс. длина имени +AAFC3: ld a,(hl) + or a + jr z,AAFCC + ld (de),a + inc hl + inc de + djnz AAFC3 +AAFCC: dec b + inc b + jr z,AAFD6 + ld a," " ; допись концовки имени + ld (de),a + inc de + djnz $-2 +AAFD6: pop hl + ; + ld bc,34 ; полож. размера файла в стат. строке + add hl,bc + ex de,hl + ld hl,(D9F04) ; мл.разряд размера файла + exx + ld hl,(D9F06) ; ст.разряд размера файла + exx + call AB1E4 ; вывести в буфер строки (de) размер файла + ; в буфер строки "Col" + ld hl,9 ; X полож. "Col" в стат. строке + add hl,de + ld (hl),"C" + inc hl + ld (hl),"o" + inc hl + ld (hl),"l" + ret + + + + +; Создать список выделенных страниц +create_list_pages: + ld hl,list_pages ; 256 байт, массив списка + ld a,(D9F03) ; идентиф. блока + ld c,0C5h + rst 08h + ret + + + +;============================================================= +; ВЫВОД ДАМПА В ОКНЕ +; +; Вход: a=0 - вывод в ascii-режиме (перенос строк включен) +; a=1 - вывод в ascii-режиме (перенос строк выключен) +; a=2 - вывод в hex-режиме +;============================================================= +DUMP: set 0,(iy+4) + or a + jr z,wrap_on ; Wrap + dec a + jr z,wrap_off ; UnWrap + jp mode_hex ; hex-режим + +; Включен перенос строк +wrap_on:ld hl,(D9F04) ; мл.разряд размера файла + ld (DA10D),hl + ld hl,(D9F06) ; ст.разряд размера файла + ld (DA10F),hl +metk04: ld a,num_strings+1 ; 31 + call AB02B + ld hl,(DA10D) + ld de,(DA10F) + jp AB0B6 + ; +AB02B: ld hl,(DA10D) + ld de,(DA10F) +loc40: ld bc,len_string+2 ; 82 макс. длина строки + push bc + and a + sbc hl,bc + ld bc,0 + ex de,hl + sbc hl,bc + ex de,hl + pop bc ; сколько + ret c + push af + call AB282 ; скопир. блок данных файла из буфера + ld hl,AA355 + ld bc,(DAF06) + add hl,bc + ld b,c + call ABA43 + pop af + dec a + jr nz,AB02B + ret + +; Выключен перенос строк +wrap_off: + ld hl,(D9F04) ; мл.разряд размера файла + ld (DA10D),hl + ld hl,(D9F06) ; ст.разряд размера файла + ld (DA10F),hl +metk05: ld a,num_strings+1 ; 31 +AB06D: ld hl,(DA10D) + ld de,(DA10F) + ld bc,256 ; макс. длина строки + push bc + and a + sbc hl,bc + ld bc,0 + ex de,hl + sbc hl,bc + ex de,hl + pop bc ; сколько + ret c + push af + call AB282 ; скопир. блок данных файла из буфера + ld hl,AA355 + ld bc,(DAF06) + add hl,bc + ld b,c + call ABA43 + pop af + dec a + jr nz,AB06D + ld hl,(DA10D) + ld de,(DA10F) + jr AB0B6 + + +;================================================= +; HEX-режим отображения данных +;================================================= +mode_hex: + ld hl,(D9F04) ; мл.разряд размера файла + ld de,(D9F06) ; ст.разряд размера файла +const20:ld bc,16 * num_strings ; "байт в строке дампа" * "число строк" + and a + sbc hl,bc + ld bc,0 + ex de,hl + sbc hl,bc + ex de,hl + ret c +AB0B6: push hl + push de + push hl + pop ix + ex de,hl + ld bc,100 ; 100% + call AB137 ; hl,ix / bc ? + ld (AB0F1+1),ix + ld (AB100+1),de + ld ix,TACF1 ; ds 125 + ld hl,0 + ld e,l + ld d,h + ld bc,6300h ; "b" счетчик + ld (ix+0),l + inc ix + ld (ix+0),h + inc ix + ld (ix+0),e + inc ix + ld (ix+0),d + inc ix + ld (ix+0),c + inc ix + inc c +AB0F0: push bc +AB0F1: ld bc,0 + add hl,bc + ld (ix+0),l + inc ix + ld (ix+0),h + inc ix + ex de,hl +AB100: ld bc,0 + adc hl,bc + ex de,hl + pop bc + ld (ix+0),e + inc ix + ld (ix+0),d + inc ix + ld (ix+0),c + inc ix + inc c + djnz AB0F0 + pop de + pop hl + ld (ix+0),l + inc ix + ld (ix+0),h + inc ix + ld (ix+0),e + inc ix + ld (ix+0),d + inc ix + ld (ix+0),c + res 0,(iy+4) + ret + +; hl,ix / bc +AB137: ld a,b + or c + ret z + ex de,hl + ld hl,0 + ld a,32 +AB140: add ix,ix + ex de,hl + adc hl,hl + ex de,hl + adc hl,hl + sbc hl,bc + jp nc,AB151 + add hl,bc + dec a + jp nz,AB140 + ret +AB151: inc ix + dec a + jp nz,AB140 + ret + + +AB157: ld a,(viewer_mode) ; режим работы вьюера + or a + ret nz + ld hl,AB1CA + push hl + ld a,100 ; 100 %? + bit 0,(iy+4) + ret nz + ld ix,TADEB + ld hl,(DA109) + ld de,(DA10B) + call AB1AD + jr c,AB1A2 + ld a,(ix+4) + ret z + ld ix,TAE68 + call AB1AD + jr c,AB191 +AB17F: ld a,(ix+4) + ret z + ret c + cp 100 ; 100% + ret z + ld bc,5 + add ix,bc + call AB1AD + jr AB17F + ; +AB191: ld a,(ix+4) + ret z + ret nc + or a + ret z + ld bc,-5 + add ix,bc + call AB1AD + jr AB191 + ; +AB1A2: ld ix,TAD6E + call AB1AD + jr c,AB191 + jr AB17F + +AB1AD: push hl + push de + push bc + ld c,(ix+0) + ld b,(ix+1) + and a + sbc hl,bc + ex de,hl + ld c,(ix+2) + ld b,(ix+3) + sbc hl,bc + jr nz,AB1C6 + ld a,d + or e +AB1C6: pop bc + pop de + pop hl + ret + + +; Вывод на экран номера колонки +; и процентовки +AB1CA: res 0,(iy+0) ; сбр. бит + ; номер колонки + push af + ld a,(iy+5) ; номер тек. колонки + ld l,a + ld h,0 + ld de,TB1C7 ; куда + call LB230 ; "a" в дес.формате -> (de) + pop af + ; процентовка "...%" + res 0,(iy+0) ; с вед. пробелами + ld l,a + ld h,0 + ld de,TAEEA ; куда + call AB230 ; "a" в дес.формате -> (de) + ; + ld de,003Fh ; Y/X полож. + ld c,84h ; уст. курсор + rst 08h + ld hl,TB1C7 ; откуда + ld a,(enable_clock) ; флаг вывода часов + or a + jr z,AB1CB ; нет часов + ld bc,0A86h ;&& вывод строки из 10 симв. без атрибутов + rst 08h + ret + ; +AB1CB: ld de,TB1C8 ; куда + ldi + ldi + ldi + ld hl,TAEEA ; откуда + ld de,TB1C8+13 ; куда + ldi + ldi + ldi + ld hl,TB1C8 ; строка + ld bc,1186h ;&& вывод строки из 10 симв. без атрибутов + rst 08h + ret + + +; строка с часами +TB1C7: db " " ; номер колонки + db " " +TAEEA: db " %" ; 0..100% просмотра текста + +; строка без часов +TB1C8: db " " + db " " + db " %" + + + + +AB1E4: res 0,(iy+0) + ld bc,0CA00h ; 1.000.000.000 + exx + ld bc,3B9Ah + exx + call AB242 + ld bc,0E100h ; 100.000.000 + exx + ld bc,05F5h + exx + call AB242 + ld bc,9680h ; 10.000.000 + exx + ld bc,0098h + exx + call AB242 + ld bc,4240h ; 1.000.000 + exx + ld bc,15 + exx + call AB242 + ld bc,86A0h ; 100.000 + exx + ld bc,1 + exx + call AB242 + ld bc,10000 ; 10.000 + exx + ld bc,0 + exx + call AB242 + ld bc,1000 ; 1000 + call AB266 +AB230: ld bc,100 ; 100 + call AB266 + ld bc,10 ; 10 + call AB266 + ld a,l + add a,"0" + ld (de),a + inc de + ret + ; +AB242: ld a,2Fh + or a +AB245: inc a + sbc hl,bc + exx + sbc hl,bc + exx + jp nc,AB245 + add hl,bc + exx + adc hl,bc + exx + cp "0" + jp z,AB25B + set 0,(iy+0) +AB25B: bit 0,(iy+0) + jp nz,AB263 + ld a," " +AB263: ld (de),a + inc de + ret + ; +AB266: ld a,2Fh + or a +AB269: inc a + sbc hl,bc + jp nc,AB269 + add hl,bc + cp "0" + jp z,AB277 + set 0,(iy+0) +AB277: bit 0,(iy+0) + jp nz,AB27F + ld a," " +AB27F: ld (de),a + inc de + ret + + +; вывод без вед. нулей +; вход: hl=число +LB230: ld bc,100 ; 100 + call LB266 + ld bc,10 ; 10 + call LB266 + ld a,l + add a,"0" + ld (de),a + inc de + ld a," " + ld (de),a ; затереть посл. разряд + ret + ; +LB266: ld a,2Fh + or a +LB269: inc a + sbc hl,bc + jp nc,LB269 + add hl,bc + cp "0" + jp z,LB277 + set 0,(iy+0) +LB277: bit 0,(iy+0) + ret z + ld (de),a + inc de + ret + + + + +;------------------------------------------------- +; Скопировать блок данных файла из буфера +; вход: bc=размер блока +;------------------------------------------------- +AB282: in a,(SLOT3) + push af + push bc + ld (AB2C3+1),hl + ld (AB2C6+1),de + add hl,bc + jr nc,$+3 + inc de + ld c,l + ld b,h + ld hl,(D9F04) ; мл.разряд размера файла + and a + sbc hl,bc + push hl + ld hl,(D9F06) ; ст.разряд размера файла + sbc hl,de + pop de + pop bc + jr nc,AB2B7 + ld hl,0 + and a + sbc hl,de + ld e,l + ld d,h + ld l,c + ld h,b + and a + sbc hl,de + jr nc,AB2B5 + ld hl,0 +AB2B5: ld c,l + ld b,h +AB2B7: ld (DAF06),bc + ld a,b + or c + jr z,AB313 + ld ix,list_pages ; 256 байт, массив списка выдел. страниц +AB2C3: ld hl,0 +AB2C6: ld de,0 + ld a,h + rla + rl e + rla + rl e + ld a,e + db 0DDh + add a,l + db 0DDh + ld l,a + jr nc,AB2D9 + db 0DDh + inc h +AB2D9: ld a,(ix+0) + out (SLOT3),a + ld a,h + or 0C0h ; ст. байт начала буфера + ld h,a + push hl + adc hl,bc + pop hl + jr z,AB2EA + jr c,AB2F1 +AB2EA: ld de,AA355 + ldir + jr AB313 + ; +AB2F1: push bc + ex de,hl + ld hl,0 + and a + sbc hl,de + ld c,l + ld b,h + push bc + ex de,hl + ld de,AA355 + ldir + pop bc + pop hl + and a + sbc hl,bc + ld c,l + ld b,h + ld hl,LC000 + ld a,(ix+1) + out (SLOT3),a + ldir +AB313: pop af + out (SLOT3),a + ret + + + +;------------------------------------------------- +; ASCII-режим статусной строки +;------------------------------------------------- +AB317: xor a ; ascii-окно + ld (cur_mode_dump),a ; флаг + ld de,TA265 ; стат. строка ascii-режима + ld a,(viewer_mode) ; 0/1 режим работы вьюера (норм./панельный) + or a + call z,print_keybar1 ; вывод нижней стат. строки + ld a,(UnWrap) ; 0/1 признак переноса строки + call DUMP ; вывести дамп + ld hl,AA355 + ld de,AA356 +const01:ld bc,(len_string+2)*num_strings ; 82*30 + ld (hl),0 + ldir + ld hl,TA115 ; ds 63 + ld a," " + ld (hl),a + inc hl + djnz $-2 + ld (iy+5),b ; сбр. номер колонки + call AB390 ; вывести страницу текста + ld a,(viewer_mode) ; режим работы вьюера + or a + jr nz,AB33C + ; вывод "DOS" в стат. строке + ld de,0023h ; Y/X полож. + ld c,84h ; уст. курсор + rst 08h + ld a,(code_page) ; 0/1/2 (Dos/Win/Koi) + ld l,a + add a,a + add a,l + ld l,a + ld h,0 + ld de,TAE02 ; "DOSWINKOI" + add hl,de ; откуда + ld bc,0386h ; вывести строку в 3 символа + rst 08h +AB33C: ld hl,half_mode_fview ; флаг выхода из гляделки + xor a ; false + cp (hl) + ld (hl),a ; сбр. флаг + ret nz ; не оставаться в гляделке после ее отработки +; ждем событий от мышки/клавы +AB33F: push ix + push iy + call handle_event ; читаем событие + pop iy + pop ix + ld a,(what) ; список событий + cp evNothing + jr z,AB33F ; нет событий + cp evMouseFr + jp z,fview_mouse_ascii ; бутоны нажаты (msfview.asm) + cp evKeyboard ; обычные клавиши + jr nz,AB350 + ld a,e +; cp 9 ; Tab +; jp z,AB375 + cp 1Bh + jr nz,AB350 +AB348: ld a,(viewer_mode) ; режим работы вьюера + or a + ret z ; норм. режим + ld hl,AB33F + push hl + ret; + ;jp fm_event ; панельный режим (на обработчик ФМ) + ; +AB350: cp evCombKey ; комб. или курс. клавиши + jr nz,AB33F ; не служ. клавиши + res 7,d + ld a,d + cp 3Dh ; F3 Quit + jr z,AB348 + cp 44h ; F10 Quit + jr z,AB348 + cp 3Eh ; F4 Hex-режим + jp z,ABB1C + ld hl,AB33F + push hl +; cp 43h ; F9 +; jp z,fm_event + cp 3Ch ; F2 Wrap/UnWrap + jp z,AB5C8 + cp 42h ; F8 Win/Koi/Dos + jp z,change_code_page + cp 54h ; курсор влево + jp z,AB5FE + cp 56h ; курсор вправо + jp z,AB610 + cp 58h ;  курсор + jp z,AB81D + cp 52h ;  курсор + jp z,AB987 + cp 59h ; PgUp + jp z,AB704 + cp 53h ; PgDwn + jp z,AB79B + cp 57h ; Home "в начало файла" + jp z,AB648 + cp 51h ; End "в конец файла" + jp z,AB661 + bit 5,b ; Ctrl ? + ret z ; нет +; jr z,AB370 ; проверить Alt, Shift + cp 59h ; Ctrl+PgUp в начало файла + jp z,AB648 + cp 53h ; Ctrl+PgDwn в конец файла + jp z,AB661 + cp 54h ; Ctrl+<- "в начало строки" + jp z,AB623 + cp 56h ; Ctrl+-> "на 26 символов вправо" + jp z,AB635 + cp 58h ; Ctrl+ курсор, PgUp + jp z,AB704 + cp 52h ; Ctrl+ курсор, PgDwn + jp z,AB79B + ret + ; проверить Alt, Shift, др. Ctrl +;AB370: ld a,(viewer_mode) +; or a +; jp nz,fm_event_comb ; панельный режим (fview.inc) +; ret ; норм. режим вьюера + +; Tab +;AB375: ld a,(viewer_mode) ; режим гляделки (норм./панельный) +; or a +; jp nz,fm_event_tab ; панельный режим (fview.inc) +; ret ; норм. режим + + + + +;------------------------------------------------- +; Вывод страницы текста +;------------------------------------------------- +AB390: ld hl,AB157 + push hl + ld (iy+6),0 + ld a,(UnWrap) ; 0/1 признак переноса строки + or a + jp nz,AB49C + ; Режим "Wrap" + ld hl,(DA109) + ld (DA111),hl + ld de,(DA10B) + ld (DA113),de +const02:ld bc,(len_string+2)*num_strings ; 82*30 сколько + call AB282 ; скопир. блок данных файла из буфера + ld hl,(DAF06) + ld a,h + or l + ret z + ld hl,AA355 + ld de,(coord) ; строка/колонка +AB3BF: ld (AB3D3+1),de + push hl + ld c,84h ; уст. курсор + rst 08h + pop hl + call AB3FC ; вывести одну строку + ld de,(DAF06) + ld a,d + or e + jr z,AB3DE +AB3D3: ld de,0 + inc d + ld a,d +metk06: cp num_strings+1 ; 31 + jr nz,AB3BF + ret + ; +AB3DE: ld de,(AB3D3+1) + inc d +metk07: ld a,num_strings+1 ; 31 + sub d + ret z + ld (iy+6),a + ld b,a ; число строк стирания +AB3EB: push de ; строка/колонка + push bc + ld c,84h ; уст. курсор + rst 08h +loc06: ld b,len_string ; 80 длина строки + ld a," " ; символ + ld c,82h ;&& вывод строки один. символов без атрибутов + rst 08h + pop bc + pop de + inc d + djnz AB3EB + ret + +; Вывод одной строки в режиме "Wrap" +AB3FC: ld de,TA115 ; ds 63 + db 0DDh + ld l,0 + push hl + push hl +loc07: ld b,len_string ; 80 + ld hl,(DAF06) + ld a,h + or a + jp nz,AB413 + ld a,l +loc08: cp len_string ; 80 + jp nc,AB413 + ld b,l +AB413: pop hl +AB414: ld a,(hl) + inc hl + cp 0Dh + jp nz,AB422 + ld a,(hl) + cp 0Ah + jp nz,AB450 + inc hl + jp AB450 + ; +AB422: cp 0Ah + jp z,AB450 + cp 9 + jp nz,AB444 + db 0DDh + ld a,l + and 0F8h + add a,8 ; ближ. полож. табуляции + db 0DDh + sub l + ld c,a +AB433: ld a," " + ld (de),a ; заполнить шаг табуляции + inc de + db 0DDh + inc l + db 0DDh + ld a,l +loc09: cp len_string ; 80 + jp z,AB450 + dec c + jp nz,AB433 + jp AB414 + ; +AB444: call char_code_page ; взять символ из кодовой страницы + ld (de),a + inc de + db 0DDh + inc l + db 0DDh + ld a,l +loc10: cp len_string ; 80 + jp z,AB450 + djnz AB414 +AB450: ld a,len_string ; 80 + db 0DDh + sub l + jp z,AB45D + ld b,a + ld a," " + ld (de),a + inc de + djnz $-2 +AB45D: pop de + push hl + and a + sbc hl,de + ex de,hl + ld hl,(DAF06) + and a + sbc hl,de + ld (DAF06),hl + ld hl,(DA111) + add hl,de + ld (DA111),hl + jp nc,AB47C + ld hl,(DA113) + inc hl + ld (DA113),hl +AB47C: ld hl,TA115 ; ds 63 + ld a,(color_array+39) ; 1Bh атрибут + ld e,a + ld a,(hl) ; символ + inc hl + push hl + ld bc,0181h ; вывести 1 символ с атрибутом + rst 08h + pop hl +loc20: ld b,len_string-2 ; 78 число символов + push hl + ld c,86h ; вывести символы без атрибутов + rst 08h + pop hl +loc21: ld bc,len_string-2 ; 78 + add hl,bc + ld a,(color_array+39) ; 1Bh атрибут + ld e,a + ld a,(hl) + ld bc,0181h ; вывести 1 символ с атрибутом + rst 08h + pop hl + ret + ; +; Режим "UnWrap" +AB49C: ld hl,(DA109) + ld (DA10D),hl + ld (DA111),hl + ld hl,(DA10B) + ld (DA10F),hl + ld (DA113),hl + ld de,(coord) ; строка/колонка +AB4B1: ld (AB4D0+1),de + ld c,84h ; уст. курсор + rst 08h + ld hl,(DA10D) + ld de,(DA10F) + ld bc,255 ; сколько (макс. длина строки) + call AB282 ; скопир. блок данных файла из буфера + ld de,(DAF06) + ld a,d + or e + jr z,AB4DB + call AB4F8 ; вывести одну строку +AB4D0: ld de,0 + inc d + ld a,d +metk08: cp num_strings+1 ; 31 + jp nz,AB4B1 + ret + ; +AB4DB: ld de,(AB4D0+1) +metk09: ld a,num_strings+1 ; 31 + sub d + ret z + ld (iy+6),a + ld b,a ; высота окна вывода +AB4E7: push de ; строка/колонка + push bc + ld c,84h ; уст. курсор + rst 08h +loc11: ld b,len_string ; 80 длина строки + ld a," " ; символ + ld c,82h ; вывод символов без атрибута + rst 08h + pop bc + pop de + inc d + djnz AB4E7 + ret + +; Вывод одной строки в режиме "UnWrap" +AB4F8: ld hl,AA355 +AB4FB: push hl + push hl + db 0DDh + ld l,0 + ld hl,(DAF06) + ld a,h + or a + ld b,255 ; счетчик (макс. длина строки) + jp nz,AB50A + ld b,l +AB50A: ld de,TA115 ; ds 63 + pop hl +AB50E: ld a,(hl) + inc hl + cp 0Dh + jp nz,AB51C + ld a,(hl) + cp 0Ah + jp nz,AB548 + inc hl + jp AB548 + ; +AB51C: cp 0Ah + jp z,AB548 + cp 9 + jp nz,AB53D + db 0DDh + ld a,l + and 0F8h + add a,8 + db 0DDh + sub l + ld c,a +AB52D: ld a," " + ld (de),a + inc de + db 0DDh + inc l + db 0DDh + ld a,l + inc a + jp z,AB548 + dec c + jp nz,AB52D + jp AB50E + ; +AB53D: call char_code_page ; взять символ из кодовой страницы + ld (de),a + inc de + db 0DDh + inc l + db 0DDh + ld a,l + inc a + jp z,AB548 + djnz AB50E +AB548: pop bc + and a + sbc hl,bc + ld bc,(DA10D) + add hl,bc + ld (DA10D),hl + ld (DA111),hl + jp nc,AB563 + ld hl,(DA10F) + inc hl + ld (DA10F),hl + ld (DA113),hl +AB563: db 0DDh + ld a,l + push af + push de + ex de,hl + ld de,TA115 ; ds 63 + and a + sbc hl,de +loc12: ld a,len_string ; 80 + add a,(iy+5) + ld e,a + ld a,0 + adc a,a + ld d,a + or a + ex de,hl + sbc hl,de + pop de + jp z,AB588 + jp c,AB588 + ld b,l + ld a," " + ld (de),a + inc de + djnz $-2 +AB588: ld hl,TA115 ; ds 63 + ld a,l + add a,(iy+5) + ld l,a + jp nc,AB593 + inc h +AB593: ld a,(iy+5) + or a + ld a,(color_array+39) ; 1Bh атрибут + ld e,a + ld a,(hl) + jp z,AB5A0 + ld a,(color_array+42) ; 1Eh атрибут + ld e,a + ld a,"" ; "<" +AB5A0: inc hl + push hl + ld bc,0181h ; вывести 1 символ с атрибутом + rst 08h + pop hl +loc22: ld b,len_string-2 ; 78 число символов + ld c,86h ; вывести символы без атрибута + push hl + rst 08h + pop hl +loc23: ld bc,len_string-2 ; 78 + add hl,bc + ld a,(color_array+39) ; 1Bh атрибут + ld e,a + ld c,(hl) + pop af + sub (iy+5) + jp c,AB5C2 +loc30: cp len_string+1 ; 80+1 + jp c,AB5C2 + ld a,(color_array+42) ; 1Eh атрибут + ld e,a + ld c,1Ah ; "->" +AB5C2: ld a,c + ld bc,0181h ; вывести 1 символ с атрибутом + rst 08h + ret + + + +; Режим переноса строки Wrap/UnWrap (ascii-режим) +AB5C8: ld a,(UnWrap) ; признак режима + xor 1 + ld (UnWrap),a + ld c,a + ld a,(viewer_mode) ; режим работы вьюера + or a + jr nz,AB5F1 + ld a,c + add a,a + ld c,a + add a,a + add a,c + ld hl,TAEEF + add a,l + ld l,a + jr nc,AB5DC + inc h +AB5DC: ld de,TA26D+1 + push de + ld bc,6 ; длина "UnWrap" или "Wrap " + ldir +metk10: ld d,num_strings+1 ; 31 строка + ld e,9 ; колонка + ld c,84h ; уст. курсор + rst 08h + ld bc,0686h ; вывести строку без атрибутов (b=длина строки) + pop hl + rst 08h +AB5F1: ld (iy+5),0 ; сбр. номер колонки + ld a,(UnWrap) ; 1/0 признак переноса строки + call DUMP ; вывести дамп + jp AB390 ; вывести страницу текста + + +; Курсор влево +AB5FE: ld a,(UnWrap) ; 0/1 признак переноса строки + or a + ret z + ld a,(iy+5) + or a + ret z + dec a + ld (iy+5),a + jp AB390 ; вывести страницу текста + + +; Курсор вправо +AB610: ld a,(UnWrap) ; 0/1 признак переноса строки + or a + ret z + ld a,(iy+5) +AB618: cp 175 ; 255-80 макс. полож. левой стороны окна + ret nc + inc a + ld (iy+5),a + jp AB390 ; вывести страницу текста + + +; Ctrl+"<-" на 26 символов влево (ascii-режим) +AB623: ld a,(UnWrap) ; 0/1 признак переноса строки + or a + ret z + ; перенос строки выключен + ld a,(iy+5) + or a + ret z + sub 26 ; (26 кратно 78-ми) + jr nc,$+3 + xor a + ld (iy+5),a + jp AB390 ; вывести страницу текста + + +; Ctrl+"->" на 26 символов вправо (ascii-режим) +AB635: ld a,(UnWrap) ; 0/1 признак переноса строки + or a + ret z + ; перенос строки выключен +AB63A: ld h,175 ; 255-80 + ld a,(iy+5) + add a,26 ; (26 кратно 78-ми) +AB63F: cp h ; макс. полож. левой стороны окна + jr nc,$+3 + ld h,a + ld (iy+5),h + jp AB390 ; вывести страницу текста + + +; Home "в начало файла" +AB648: ld hl,(DA109) + ld de,(DA10B) + ld a,h + or d + or l + or e + ret z + ld hl,0 + ld (DA109),hl + ld (DA10B),hl + jp AB390 ; вывести страницу текста + +; End "в конец файла" +AB661: ld hl,(DA111) + ld de,(DA113) + ld bc,(D9F04) ; мл.разряд размера файла + and a + sbc hl,bc + ld bc,(D9F06) ; ст.разряд размера файла + ex de,hl + sbc hl,bc + ex de,hl + ret nc + ld hl,(D9F04) ; мл.разряд размера файла + ld (DA10D),hl + ld hl,(D9F06) ; ст.разряд размера файла + ld (DA10F),hl + ld a,(UnWrap) ; 0/1 признак переноса строки + or a + jr nz,AB6C7 +mt01: ld a,num_strings-1 ; 29 счетчик + call AB02B + ld hl,(DA10D) + ld (DA109),hl + ld hl,(DA10F) + ld (DA10B),hl + jp AB390 ; вывести страницу текста + + +AB6C7: ld a,num_strings ; 30 +AB6C9: ld hl,(DA10D) + ld de,(DA10F) + ld bc,255 + push bc + and a + sbc hl,bc + ld bc,0 + ex de,hl + sbc hl,bc + ex de,hl + pop bc ; сколько + ret c + push af + call AB282 ; скопир. блок данных файла из буфера + ld hl,AA355 + ld bc,(DAF06) + add hl,bc + ld b,c + call ABA43 + pop af + dec a + jr nz,AB6C9 + ld hl,(DA10D) + ld (DA109),hl + ld hl,(DA10F) + ld (DA10B),hl + jp AB390 ; вывести страницу текста + +; PgUp +AB704: ld hl,(DA109) + ld de,(DA10B) + ld a,h + or d + or l + or e + ret z + ld (DA10D),hl + ld (DA10F),de + ld a,(UnWrap) ; 0/1 признак переноса строки + or a + jr nz,AB75C +met03: ld a,num_strings ; 30 +AB71F: ld hl,(DA10D) + ld de,(DA10F) +loc41: ld bc,len_string+2 + push bc + and a + sbc hl,bc + ld bc,0 + ex de,hl + sbc hl,bc + ex de,hl + pop bc ; сколько + jp c,AB648 + push af + call AB282 ; скопир. блок данных файла из буфера + ld hl,AA355 + ld bc,(DAF06) + add hl,bc + ld b,c + call ABA43 + pop af + dec a + jr nz,AB71F + ld hl,(DA10D) + ld (DA109),hl + ld hl,(DA10F) + ld (DA10B),hl + jp AB390 ; вывести страницу текста + ; + ; строка развернута +AB75C: ld a,num_strings ; 30 +AB75E: ld hl,(DA10D) + ld de,(DA10F) + ld bc,255 + push bc + and a + sbc hl,bc + ld bc,0 + ex de,hl + sbc hl,bc + ex de,hl + pop bc ; сколько + jp c,AB648 + push af + call AB282 ; скопир. блок данных файла из буфера + ld hl,AA355 + ld bc,(DAF06) + add hl,bc + ld b,c + call ABA43 + pop af + dec a + jr nz,AB75E + ld hl,(DA10D) + ld (DA109),hl + ld hl,(DA10F) + ld (DA10B),hl + jp AB390 ; вывести страницу текста + +; PgDw +AB79B: ld hl,(DA109) + ld (DA10D),hl + ld de,(DA10B) + ld (DA10F),de + ld a,(UnWrap) ; 0/1 признак переноса строки + or a + jr nz,AB7E5 +const03:ld bc,(len_string+2)*num_strings ; 82*30 сколько + call AB282 ; скопир. блок данных файла из буфера + ld hl,AA355 +metk11: ld b,num_strings+1 ; 31 +AB7BA: ex de,hl + ld hl,(DAF06) + ld a,h + or l + ret z + push bc + ld a,h + or a +loc13: ld b,len_string ; 80 + jr nz,AB7CE + ld a,l +loc14: cp len_string ; 80 + jr nc,AB7CE + ld b,l +AB7CE: ex de,hl + call ABAC5 + pop bc + djnz AB7BA + ld hl,(DA10D) + ld (DA109),hl + ld hl,(DA10F) + ld (DA10B),hl + jp AB390 ; вывести страницу текста + ; +AB7E5: ld b,num_strings ; 30 +AB7E7: ld hl,(DA10D) + ld de,(DA10F) + push bc + ld bc,256 ; сколько + call AB282 ; скопир. блок данных файла из буфера + pop bc + ld hl,(DAF06) + ld a,h + or l + ret z + push bc + ld b,255 + ld a,h + or a + jr nz,$+3 + ld b,l + ld hl,AA355 + call ABAC5 + pop bc + djnz AB7E7 ; цикл 30 + ld hl,(DA10D) + ld (DA109),hl + ld hl,(DA10F) + ld (DA10B),hl + jp AB390 ; вывести страницу текста + +; курсор вверх +AB81D: ld hl,(DA109) + ld de,(DA10B) + ld a,h + or d + or l + or e + ret z + ld (DA10D),hl + ld (DA10F),de + ld a,(UnWrap) ; 0/1 признак переноса строки + or a + jp nz,AB8DF +loc42: ld bc,len_string+2 + push bc + and a + sbc hl,bc + ld bc,0 + ex de,hl + sbc hl,bc + ex de,hl + pop bc + jr nc,AB850 + add hl,bc + ld c,l + ld b,h + ld hl,0 + ld e,l + ld d,h +AB850: push bc ; сколько + call AB282 ; скопир. блок данных файла из буфера + pop bc + ld hl,(DAF06) + push hl + ld hl,AA355 + add hl,bc + ld (hl),0Ah + ld b,c + call ABA43 + ld (AB895+1),hl + pop hl + ld (DAF06),hl + ld hl,(DA10D) + ld de,(DA10F) + ld a,h + or d + or l + or e + jp z,AB648 ; Home "в начало файла" + ld (DA109),hl + ld (DA10B),de + ; + ld de,(winpos) ; Y/X левого угла + ld hl,(winsize) ; Y/X размеры окна + ld a,1 ; не очищать строку + ld bc,0255h ; скролл. вниз + call Func_55 + ld de,(coord) + ld c,84h ; уст. курсор + rst 08h + ; + ld hl,(DA111) + ld de,(DA113) + push hl + push de +AB895: ld hl,0 + call AB3FC ; вывод одной строки + pop de + pop hl + ld (DA10D),hl + ld (DA111),hl + ld (DA10F),de + ld (DA113),de + ld a,(iy+6) + or a + jr z,AB8B5 + dec (iy+6) + ret + ; +AB8B5: ld bc,len_string+2 ; 82 + push bc + and a + sbc hl,bc + ld bc,0 + ex de,hl + sbc hl,bc + ex de,hl + pop bc ; сколько + call AB282 ; скопир. блок данных файла из буфера + ld hl,AA3A7 +loc43: ld b,len_string+2 ; 82 + call ABA43 + ld hl,(DA10D) + ld (DA111),hl + ld hl,(DA10F) + ld (DA113),hl + jp AB157 + ; +; строка развернута +AB8DF: ld bc,255 + push bc + and a + sbc hl,bc + ld bc,0 + ex de,hl + sbc hl,bc + ex de,hl + pop bc + jr nc,AB8F8 + add hl,bc + ld c,l + ld b,h + ld hl,0 + ld e,l + ld d,h +AB8F8: push bc ; сколько + call AB282 ; скопир. блок данных файла из буфера + pop bc + ld hl,(DAF06) + push hl + ld hl,AA355 + add hl,bc + ld (hl),0Ah + ld b,c + call ABA43 + ld (AB93D+1),hl + pop hl + ld (DAF06),hl + ld hl,(DA10D) + ld de,(DA10F) + ld a,h + or d + or l + or e + jp z,AB648 + ld (DA109),hl + ld (DA10B),de + ; + ld de,(winpos) ; Y/X левого угла + ld hl,(winsize) ; Y/X размеры окна + ld a,1 ; не очищать строку + ld bc,0255h ; скролл. вниз + call Func_55 + ld de,(coord) + ld c,84h ; уст. курсор + rst 08h + ; + ld hl,(DA111) + ld de,(DA113) + push hl + push de +AB93D: ld hl,0 + call AB4FB + pop de + pop hl + ld (DA10D),hl + ld (DA111),hl + ld (DA10F),de + ld (DA113),de + ld a,(iy+6) + or a + jr z,AB95D + dec (iy+6) + ret + +AB95D: ld bc,255 + push bc + and a + sbc hl,bc + ld bc,0 + ex de,hl + sbc hl,bc + ex de,hl + pop bc ; сколько + call AB282 ; скопир. блок данных файла из буфера + ld hl,AA454 + ld b,255 + call ABA43 + ld hl,(DA10D) + ld (DA111),hl + ld hl,(DA10F) + ld (DA113),hl + jp AB157 + +; Курсор вниз +AB987: ld hl,(DA111) + ld (DA10D),hl + ld de,(DA113) + ld (DA10F),de + ld a,(UnWrap) ; 0/1 признак переноса строки + or a + jr nz,AB9F3 +loc44: ld bc,len_string+2 ; 82 сколько + call AB282 ; скопир. блок данных файла из буфера + ld hl,(DAF06) + ld a,h + or l + ret z + ; + ld de,(winpos) ; Y/X левого угла + ld hl,(winsize) ; Y/X размеры окна + ld a,1 ; не очищать строку + ld bc,0155h ; скролл. вверх + call Func_55 + ld de,(coord) +met07: ld d,num_strings ; 30 строка + ld c,84h ; уст. курсор + rst 08h + ; + ld hl,AA355 + call AB3FC ; вывод одной строки + ld hl,(DA109) + ld (DA10D),hl + ld de,(DA10B) + ld (DA10F),de +loc45: ld bc,len_string+2 ; 82 сколько + call AB282 ; скопир. блок данных файла из буфера + ld hl,(DAF06) + ld a,h + or a +loc15: ld b,len_string ; 80 + jr nz,AB9DD + ld a,l +loc16: cp len_string ; 80 + jr nc,AB9DD + ld b,l +AB9DD: ld hl,AA355 + call ABAC5 + ld hl,(DA10D) + ld (DA109),hl + ld hl,(DA10F) + ld (DA10B),hl + jp AB157 + ; + ; строка развернута +AB9F3: ld bc,255 ; сколько + call AB282 ; скопир. блок данных файла из буфера + ld hl,(DAF06) + ld a,h + or l + ret z + ; + ld de,(winpos) ; Y/X левого угла + ld hl,(winsize) ; Y/X размеры окна + ld a,1 ; не очищать строку + ld bc,0155h ; скролл. вверх + call Func_55 + ld de,(coord) +met09: ld d,num_strings ; 30 строка + ld c,84h ; уст. курсор + rst 08h + ; + call AB4F8 + ld hl,(DA109) + ld (DA10D),hl + ld de,(DA10B) + ld (DA10F),de + ld bc,255 ; сколько + call AB282 ; скопир. блок данных файла из буфера + ld hl,(DAF06) + ld b,255 + ld a,h + or a + jr nz,$+3 + ld b,l + ld hl,AA355 + call ABAC5 + ld hl,(DA10D) + ld (DA109),hl + ld hl,(DA10F) + ld (DA10B),hl + jp AB157 + + +ABA43: ld (iy+1),b + ld e,l + ld d,h + dec hl + ld a,(hl) + cp 0Dh + jr z,ABA5E + cp 0Ah + jr nz,ABA66 + dec (iy+1) + dec b + jr z,ABAA2 + dec hl + ld a,(hl) + cp 0Dh + jr nz,ABA66 +ABA5E: dec (iy+1) + dec b + jr z,ABAA2 +ABA64: dec hl + ld a,(hl) +ABA66: dec (iy+1) + cp 0Ah + jr nz,ABA77 + dec hl + ld a,(hl) + inc hl + cp 0Dh + jr nz,ABA96 + dec hl + jr ABA96 + ; +ABA77: cp 0Dh + jr z,ABA96 + cp 9 + jr nz,ABA94 + ld a,(iy+1) + and 7 + sub 8 + neg + ld c,a +ABA89: dec b + jr z,ABA96 + dec (iy+1) + dec c + jr nz,ABA89 + jr ABA64 + ; +ABA94: djnz ABA64 +ABA96: ld a,(hl) + cp 0Dh + jr nz,ABA9D + inc hl + ld a,(hl) +ABA9D: cp 0Ah + jr nz,ABAA2 + inc hl +ABAA2: push hl + ex de,hl + and a + sbc hl,de + ex de,hl + ld hl,(DAF06) + and a + sbc hl,de + ld (DAF06),hl + ld hl,(DA10D) + and a + sbc hl,de + ld (DA10D),hl + jr nc,ABAC3 + ld hl,(DA10F) + dec hl + ld (DA10F),hl +ABAC3: pop hl + ret + + +ABAC5: ld (iy+1),0 + ld e,l + ld d,h +ABACB: ld a,(hl) + inc hl + cp 0Dh + jr nz,ABAD9 + ld a,(hl) + cp 0Ah + jr nz,ABAFC + inc hl + jr ABAFC + ; +ABAD9: cp 0Ah + jr z,ABAFC + cp 9 + jr nz,ABAF7 + ld a,(iy+1) + and 0F8h ; получить ближ. положение Tab + add a,8 + sub (iy+1) + ld c,a +ABAEC: inc (iy+1) + dec b + jr z,ABAFC + dec c + jr nz,ABAEC + jr ABACB + ; +ABAF7: inc (iy+1) + djnz ABACB +ABAFC: push hl + and a + sbc hl,de + ex de,hl + ld hl,(DAF06) + and a + sbc hl,de + ld (DAF06),hl + ld hl,(DA10D) + add hl,de + ld (DA10D),hl + jr nc,ABB1A + ld hl,(DA10F) + inc hl + ld (DA10F),hl +ABB1A: pop hl + ret + + +;================================================= +; HEX-режим статусной строки +;================================================= +ABB1C: ld a,1 ; hex-окно + ld (cur_mode_dump),a ; флаг + ld a,(DA109) + and 0F0h ; выделить старший ниббл + ld (DA109),a + ld de,TA2B5 ; стат. строка hex-режима + ld a,(viewer_mode) ; режим работы вьюера + or a + call z,print_keybar1 ; вывод нижней стат. строки + ld a,2 ; уст. hex-режим вывода + call DUMP ; вывести дамп + ld hl,AA355 + ld de,AA356 +const04:ld bc,(len_string+2)*num_strings ; 82*30 + ld (hl),0 + ldir + ld hl,TA115 ; ds 63 +loc17: ld b,len_string ; 80 + ld a," " + ld (hl),a + inc hl + djnz $-2 + ld (iy+5),b ; сбр. номер колонки + call ABB87 ; вывести страницу hex-дампа + ld hl,half_mode_fview ; флаг выхода из гляделки + xor a ; false + cp (hl) + ld (hl),a ; сбр. флаг + ret nz ; не оставаться в гляделке после ее отработки +; ждем событий от мышки/клавы +ABB4A: push ix + push iy + call handle_event ; читаем событие + pop iy + pop ix + ld a,(what) ; список событий + cp evNothing + jr z,ABB4A ; нет событий + cp evMouseFr + jp z,fview_mouse_hex ; бутоны нажаты (msfview.asm) + cp evKeyboard ; обычные клавиши + jr nz,ABB60 + ld a,e +; cp 9 ; Tab +; jp z,AB375 + cp 1Bh + jr nz,ABB60 +ABB58: ld a,(viewer_mode) ; режим работы вьюера + or a + ret z ; норм. режим + ld hl,ABB4A + push hl + ret; + ;jp fm_event ; панельный режим (на обработчик ФМ) + ; +ABB60: cp evCombKey ; комб. или курс. клавиши + jr nz,ABB4A ; не служ. клавиши + res 7,d + ld a,d + cp 3Dh ; F3 Quit + jr z,ABB58 + cp 44h ; F10 Quit + jr z,ABB58 + cp 3Eh ; F4 Ascii-режим + jp z,AB317 + ld hl,ABB4A + push hl +; cp 43h ; F9 +; jp z,fm_event ; на обработчик ФМ + cp 3Fh ; F5 Goto перейти на адрес... + jp z,ABDF3 + cp 42h ; F8 Win/Koi/Dos + jp z,change_code_page1 + cp 58h ;  курсор + jp z,ABC9A + cp 52h ;  курсор + jp z,ABCDB + cp 59h ; PgUp + jp z,ABD9D + cp 53h ; PgDwn + jp z,ABDC3 + cp 57h ; Home в начало файла + jp z,ABD3B + cp 51h ; End в конец файла + jp z,ABD54 + bit 5,b ; Ctrl ? + ret z ; нет +; jp z,AB370 ; проверить Alt, Shift + cp 59h ; Ctrl+PgUp в начало файла + jp z,ABD3B + cp 53h ; Ctrl+PgDwn в конец файла + jp z,ABD54 + cp 58h ; Ctrl+ курсор, PgUp + jp z,ABD9D + cp 52h ; Ctrl+ курсор, PgDwn + jp z,ABDC3 + ret +; jp AB370 ; проверить Alt, Shift, др. Ctrl + + + +ABB87: ld hl,AB157 + push hl + ld hl,(DA109) + ld (DA10D),hl + ld de,(DA10B) + ld (DA10F),de +const21:ld bc,16 * num_strings ; "байт в строке дампа" * "число строк" + call AB282 ; скопир. блок данных файла из буфера + ld ix,AA355 + ld de,(coord) ; строка/колонка +ABBA6: ld (ABBC9+1),de + push ix + ld c,84h ; уст. курсор + rst 08h + pop ix + call ABBEF + jr c,ABBD4 + ld hl,(DA10D) + ld de,16 + add hl,de + ld (DA10D),hl + jr nc,ABBC9 + ld hl,(DA10F) + inc hl + ld (DA10F),hl +ABBC9: ld de,0 + inc d + ld a,d +metk12: cp num_strings+1 ; 31 число строк дампа + jp nz,ABBA6 + ret + ; +ABBD4: ld de,(ABBC9+1) + inc d +metk13: ld a,num_strings+1 ; 31 число строк дампа + sub d + ret z + ld b,a +ABBDE: push de ; строка/колонка + push bc + ld c,84h ; уст. курсор + rst 08h +loc18: ld b,len_string ; 80 длина строки + ld a," " ; символ + ld c,82h ;&& вывод один. символов без атрибута + rst 08h + pop bc + pop de + inc d + djnz ABBDE + ret + + +ABBEF: ld (iy+1),0 + ld hl,(DAF06) + ld a,h + or a + ld c,16 ; число байт hex-строки + jr nz,ABC02 + ld a,l + cp c + jr nc,ABC02 + ld c,l +ABC02: xor a + ld b,a + sbc hl,bc + ld (DAF06),hl + push hl + ld hl,TA115 ; hex-буфер ds 63 + ld de,TA154 ; ascii буфер + ld (hl),"0" ; вед. нуль (просто для выравн. дампа) + inc hl + ld a,(DA110) ; ст.разряд тек. адреса + call HEXA ; a -> (hl) + ld a,(DA10F) + call HEXA + ld a,(DA10E) + call HEXA + ld a,(DA10D) ; мл.разряд + call HEXA + ld (hl),":" ; разделитель адреса + inc hl + inc hl + inc de ; доп. разделитель hex - ascii полей + ld b,c +ABC2F: ld a,(ix+0) + inc ix + push af + call char_code_page ; взять символ из кодовой страницы + ld (de),a ; ascii-поле + pop af + call HEXA ; a -> (hl) + inc hl + inc de + inc (iy+1) + ld a,(iy+1) + cp 4 + jr z,ABC4C + cp 8 + jr nz,ABC48 ; jr z,ABC4C + ld (hl),"│" ; разделитель середины hex-строки + inc hl + jr ABC4C +ABC48: cp 12 + jr nz,$+3 +ABC4C: inc hl + djnz ABC2F + ; тест на допись не полной hex-строки + ld a,16 ; число байт hex-строки + sub (iy+1) + jr z,ABC75 ; строка полная + ld b,a +ABC57: ld a," " ; символ заполнения + ld (hl),a + inc hl + ld (hl),a + inc hl + inc hl + ld (de),a + inc de + inc (iy+1) + ld a,(iy+1) + cp 4 + jr z,ABC72 + cp 8 + jr nz,ABC6E + ld (hl),"│" ; разделитель середины hex-строки + inc hl + jr ABC72 +ABC6E: cp 12 + jr nz,$+3 +ABC72: inc hl + djnz ABC57 +ABC75: push ix + ld hl,TA115 ; ds 63 адрес строки +loc19: ld b,len_string ; 80 длина строки + ld a,(color_array+39) ; 1Bh атрибут + ld e,a + ld a,(viewer_mode) ; режим работы вьюера + or a + jr z,$+4 + ld b,38 ; длина строки панели + ld c,85h ;&& вывод строки с атрибутом + rst 08h + pop ix + pop hl + ld a,h + or l + ret nz + scf + ret + + +; "a" в hex-формате -> (hl) +HEXA: push af + rrca + rrca + rrca + rrca + call $+4 + pop af + and 0Fh + add a,90h + daa + adc a,40h + daa + ld (hl),a + inc hl + ret + + +ABC9A: ld hl,(DA109) + ld de,(DA10B) + ld a,h + or d + or l + or e + ret z + ld bc,16 + and a + sbc hl,bc + ld (DA109),hl + ld (DA10D),hl + jr nc,ABCB5 + dec de +ABCB5: ld (DA10B),de + ld (DA10F),de + ld bc,16 ; сколько + call AB282 ; скопир. блок данных файла из буфера + ; + ld de,(winpos) ; Y/X левого угла + ld hl,(winsize) ; Y/X размеры окна + ld a,1 ; не очищать строку + ld bc,0255h ; скролл. вниз + call Func_55 + ld de,(coord) + ld c,84h ; уст. курсор + rst 08h + ; + ld ix,AA355 + call ABBEF + jp AB157 + + +ABCDB: ld hl,(DA109) + ld bc,(DA10B) +const22:ld de,16 * num_strings ; "байт в строке дампа" * "число строк" + add hl,de + push hl + jr nc,$+3 + inc bc + push bc + ex de,hl + ld hl,(D9F04) ; мл.разряд размера файла + and a + sbc hl,de + ex de,hl + ld hl,(D9F06) ; ст.разряд размера файла + sbc hl,bc + pop bc + pop hl + ret c + jr nz,ABD00 + ld a,d + or e + ret z +ABD00: push hl + push bc + ld hl,(DA109) + ld de,(DA10B) + ld bc,16 ; сколько + add hl,bc + jr nc,$+3 + inc de + ld (DA109),hl + ld (DA10B),de + pop de + pop hl + ld (DA10D),hl + ld (DA10F),de + call AB282 ; скопир. блок данных файла из буфера + ; + ld de,(winpos) ; Y/X левого угла + ld hl,(winsize) ; Y/X размеры окна + ld a,1 ; не очищать строку + ld bc,0155h ; скролл. вверх + call Func_55 + ld de,(coord) +met12: ld d,num_strings ; 30 строка + ld c,84h ; уст. курсор + rst 08h + ; + ld ix,AA355 + call ABBEF + jp AB157 + + +ABD3B: ld hl,(DA109) + ld bc,(DA10B) + ld a,h + or b + or l + or c + ret z + ld hl,0 + ld (DA109),hl + ld (DA10B),hl + jp ABB87 + + +ABD54: ld hl,(DA109) + ld bc,(DA10B) +const23:ld de,16 * num_strings ; "байт в строке дампа" * "число строк" + add hl,de + jr nc,$+3 + inc bc + ex de,hl + ld hl,(D9F04) ; мл.разряд размера файла + push hl + and a + sbc hl,de + ex de,hl + ld hl,(D9F06) ; ст.разряд размера файла + push hl + sbc hl,bc + pop bc + pop hl + ret c + jr nz,ABD79 + ld a,d + or e + ret z +ABD79: ld de,16 * num_strings ; "байт в строке дампа" * "число строк" + and a + sbc hl,de + jr nc,$+3 + dec bc + ld a,l + and 0Fh + jr z,ABD92 + ld a,l + and 0F0h + ld l,a + ld de,16 + add hl,de + jr nc,$+3 + inc bc +ABD92: ld (DA109),hl + ld (DA10B),bc + jp ABB87 + + +ABD9D: ld hl,(DA109) + ld bc,(DA10B) + ld a,h + or b + or l + or c + ret z +const25:ld de,16 * num_strings ; "байт в строке дампа" * "число строк" + sbc hl,de + jr nc,ABDB8 + ld a,b + or c + dec bc + jr nz,ABDB8 + inc bc + ld l,c + ld h,b +ABDB8: ld (DA109),hl + ld (DA10B),bc + jp ABB87 + + +ABDC3: ld hl,(DA109) + ld bc,(DA10B) +const26:ld de,16 * num_strings ; "байт в строке дампа" * "число строк" + add hl,de + push hl + jr nc,$+3 + inc bc + push bc + ex de,hl + ld hl,(D9F04) ; мл.разряд размера файла + and a + sbc hl,de + ex de,hl + ld hl,(D9F06) ; ст.разряд размера файла + sbc hl,bc + pop bc + pop hl + ret c + jr nz,ABDE8 + ld a,d + or e + ret z +ABDE8: ld (DA109),hl + ld (DA10B),bc + jp ABB87 + + +;------------------------------------------------- +; Goto "перейти на адрес..." +;------------------------------------------------- +ABDF3: ld hl,(D9F04) ; мл.разряд размера файла + ld de,(D9F06) ; ст.разряд размера файла + ld a,h + or d + or e + jr nz,ABE03 + ld a,l + cp 11h + ret c +ABE03: ld hl,TAEFB + xor a + ld (ABE4E+1),a + inc a + ld (ABE48+1),a + ld a,(DA10C) + call HEXA ; a -> (hl) + ld a,(DA10B) + call HEXA + ld a,(DA10A) + call HEXA + ld a,(DA109) + call HEXA +ABE26: call ABEBE +ABE29: halt + call ABEE6 + call get_mouse_info + jp nz,fview_mouse_goto ; бутоны нажаты +; ввод адреса перехода + ld a,2 ; опрос без ожидания + rst 20h + jr z,ABE29 + or a + jr z,ABE8F ; нажаты курс. клавиши + cp 0Dh ; Enter + jp z,ABF17 + cp 8 ; Backspace + jr z,ABE75 + cp 1Bh ; Esc + jp z,ABF5C + cp " " + jr c,ABE29 + ld c,a +ABE48: ld a,0 + or a + call nz,ABE65 +ABE4E: ld a,0 + ld b,a + ld hl,TAEFB + add a,l + ld l,a + jr nc,ABE59 + inc h +ABE59: ld (hl),c + ld a,b + cp 7 + jr z,ABE26 + inc a + ld (ABE4E+1),a + jr ABE26 + +ABE65: ld hl,TAEFB ; " ",0 + ld b,8 + ld a," " ; стереть пункт стат. строки + ld (hl),a + inc hl + djnz $-2 + xor a + ld (ABE48+1),a + ret + +ABE75: xor a + ld (ABE48+1),a + ld a,(ABE4E+1) + or a + jr z,ABE29 + dec a + ld (ABE4E+1),a + ld hl,TAEFB + add a,l + ld l,a + jr nc,$+3 + inc h + ld (hl)," " + jr ABE26 + +ABE8F: ld a,d + cp 54h ; курсор влево + jr z,ABE9A + cp 56h ; курсор вправо + jr z,ABEAB + jr ABE29 + +; Курсор влево +ABE9A: xor a + ld (ABE48+1),a + ld a,(ABE4E+1) + or a + jp z,ABE29 + dec a + ld (ABE4E+1),a + jp ABE26 + +; Курсор право +ABEAB: xor a + ld (ABE48+1),a + ld a,(ABE4E+1) + cp 7 + jp z,ABE29 + inc a + ld (ABE4E+1),a + jp ABE26 + + +ABEBE: ld de,(coord) ; строка/колонка ввода адреса + inc e + ld c,84h ; уст. курсор + rst 08h + ld hl,TAEFB ; " ",0 + ld bc,0886h ; выв. строку без атрибутов (b=длина строки) + rst 08h + ld a,(ABE4E+1) + inc a + ld e,a ; колонка + ld d,1 ; строка + ld c,84h ; уст. курсор + rst 08h + ld a,"█" ; нач. курсор в режиме ввода адреса перехода + ld bc,0182h ; вывод 1-го символа без атрибута + rst 08h + ld a,1 + ld (ABF04+1),a + ld a,6 ; автоповтор ? + ld (ABEE6+1),a + ret + + +ABEE6: ld a,0 + dec a + ld (ABEE6+1),a + ret nz + ld hl,TAEFB + ld a,(ABE4E+1) + ld e,a ; колонка + inc e + ld d,1 ; строка редакт. адреса перехода + add a,l + ld l,a + jr nc,ABEFC + inc h +ABEFC: push hl + ld c,84h ; уст. курсор + rst 08h + pop hl + ld bc,0182h ; вывод 1-го символа без атрибута +ABF04: ld a,0 + xor 1 + ld (ABF04+1),a + ld a,(hl) + jr z,ABF10 + ld a,"█" ; осн. курсор в режиме ввода адреса +ABF10: rst 08h + ld a,12 ; частота мигания + ld (ABEE6+1),a + ret + + +ABF17: xor a + ld (ABE4E+1),a + ld bc,TAEFB ; " ",0 + call ABF84 + jp c,ABE26 + ld c,e + ld b,d + ld a,l + and 0F0h + ld l,a + ex de,hl + ld hl,(D9F04) ; мл.разряд размера файла + and a + sbc hl,de + ld hl,(D9F06) ; ст.разряд размера файла + sbc hl,bc + jr c,ABF3E + jr nz,ABF50 + ld a,d + or e + jr nz,ABF50 +ABF3E: ld hl,(D9F04) ; мл.разряд размера файла + ld bc,16 + and a + sbc hl,bc + ex de,hl + ld hl,(D9F06) ; ст.разряд размера файла + jr nc,ABF4E + dec hl +ABF4E: ld c,l + ld b,h +ABF50: ld (DA109),de + ld (DA10B),bc + jp ABB87 + +; Esc +ABF5C: ld hl,TAEFB ; буфер вводимого адреса перехода + push hl + ld a,(DA10C) ; ст.разряд тек.адреса + call HEXA ; в hex-формате сохр. в буфере + ld a,(DA10B) + call HEXA + ld a,(DA10A) + call HEXA + ld a,(DA109) ; мл.разряд тек.адреса + call HEXA + ld de,(coord) ; строка/колонка начала адреса + inc e + ld c,84h ; уст. курсор + rst 08h + pop hl + ld bc,0886h ; вывод строки без атриб. (b=длина) + rst 08h + ret + + +ABF84: ld hl,0 + ld e,l + ld d,h +ABF89: ld a,(bc) + inc bc + or a + ret z + cp " " + jr z,ABF89 + cp "a" + jr c,ABF97 + sub 20h +ABF97: cp "0" + ret c + cp "F"+1 + ccf + ret c + sub "0" + cp 9+1 + jr c,ABFA9 + sub 7 + cp 9+1 + ret c +ABFA9: add hl,hl + ex de,hl + adc hl,hl + ex de,hl + add hl,hl + ex de,hl + adc hl,hl + ex de,hl + add hl,hl + ex de,hl + adc hl,hl + ex de,hl + add hl,hl + ex de,hl + adc hl,hl + ex de,hl + or l + ld l,a + jr ABF89 + + + +;------------------------------------------------- +; Скроллинг окна +; вход: b=1 вверх +; b=2 вниз +;------------------------------------------------- +Func_55:djnz fnc_551 + ld c,h + db 0DDh + ld h,d + db 0DDh + ld l,e + inc d + dec h + ld c,0B7h ; перемещ. окна + jp scrn5__ + ; +; скроллинг вниз +fnc_551:ld c,l + db 0DDh + ld h,d + db 0DDh + ld l,e + db 0DDh + inc h + dec h + ld c,0B7h + jp scrn5__ diff --git a/FVIEW/FVIEW.INC b/FVIEW/FVIEW.INC new file mode 100755 index 0000000..c51ad59 --- /dev/null +++ b/FVIEW/FVIEW.INC @@ -0,0 +1,195 @@ +; Процедуры, расположенные в осн. странице ФМ. +; Вызываются из страницы гляделки. +; + + + + + +; флаг выхода из гляделки после вывода содержимого файла +half_mode_fview: + db false ; 0/1 не выходить/выйти + + + + +;------------------------------------------------- +; Вызов вьюера на исполнение +; выход: CF - при ошибке, A=код ошибки +;------------------------------------------------- +; Панельный режим +;alt_file_viewer: +; ld a,true ; вывести данные и выйти из fview +; ld (half_mode_fview),a ; уст. флаг +; ld c,true ; панельный режим работы вьюера +; jr $+4 +; Обычный режим +file_viewer: + ld c,false ; норм. режим работы вьюера + call test_show_panels ; тест на режим вкл. панелей + ret z + ld a,(format_mode) ; формат акт. панели + and form_info + ret nz + ld hl,(all_files) + ld a,l + or h + ret z ; пустая панель + ld a,c + ld (viewer_mode),a ; 0/1 режим работы вьюера + call get_record ; hl=начало записи, a=атрибут файла + and 10h + ret nz ; папка + push hl + call set_path_from_activ_panel ; уст. сист. диск и путь от акт. панели + pop hl + ret c + ld de,temp_fname ; куда + ld bc,0044h ; 11 -> 8.3 + rst 10h + ret c + ;ld (evcomb_stack+1),sp ; сохр. стек + ld a,(page_viewer) ; стр. вьюера + out (SLOT1),a + call viewer ; вьюер + ex af,af' ; код возврата + ld a,(page_module1) + out (SLOT1),a ; восст. стр. + ex af,af' + ret + + + + + + + +;----------------------------------------------------------- +; Вызов из fview. Обработка клавиш без комбинаций +; вход: e=ascii-код +; d=скен-код +; b=биты служ. клавиш +;----------------------------------------------------------- +;fm_event: +; ld a,(viewer_mode) ; режим работы вьюера +; or a +; ret z ; норм. режим +; ; fview в панельном режиме +; push iy +; push ix +; ld a,(page_module1) +; out (SLOT1),a ; восст. стр. +; call main_event ; обработчик ФМ +; ld a,(page_viewer) ; стр. вьюера +; out (SLOT1),a +; pop ix +; pop iy +; ret + + +;------------------------------------------------- +; Tab. Вызов из fview +;------------------------------------------------- +;fm_event_tab: +; ld a,(page_module1) +; out (SLOT1),a ; восст. стр. +; pop de ; убрать "call viewer" +; jp tab ; сменить акт. панель + + + + + +; точка выхода в fview +;event_comb_return: +; ld a,(page_viewer) ; стр. вьюера +; out (SLOT1),a +; ; настроить полож. дампа +; ld hl,panel_left ; полож. акт. панели +; ld d,(hl) ; Y полож. панели +; inc hl +; ld e,(hl) ; X полож. панели +; inc d +; inc e +; ld (coord),de ; полож. курсора +; ld (winpos),de ; полож. окна +; ret + +;----------------------------------------------------------- +; Вызов из fview. Обработка комбинаций клавиш +; вход: e=ascii-код +; d=скен-код +; b=биты служ. клавиш +;----------------------------------------------------------- +;fm_event_comb: +; ld hl,event_comb_return ; точка выхода +; push hl +; ld a,(page_module1) +; out (SLOT1),a ; восст. стр. фм +; ld a,d +; ; с возвратом в fview qview-панели +; cp 18h ; Ctrl+O убрать/показать панели +; jp z,hidd;en_panels +; cp 16h ; Ctrl+U обмен панелей +; jp z,swap;_panels +; cp 12h ; Ctrl+E пред. строка истории +; jp z,prev_history +; cp 2Bh ; Ctrl+X след. строка истории +; jp z,next_history +; cp 4Fh ; Ctrl+Del, очистить историю команд +; jp z,clear_history +; ; без возврата в fview qview-панели +; cp 2 ; "1" краткий акт. панели +; jr z,event_comb_done +; cp 3 ; "2" средний акт. панели +; jr z,event_comb_done +; cp 4 ; "3" полный акт. панели +; jr z,event_comb_done +; cp 10h ; Ctrl+Q скрыть/показать панели +; jr z,event_comb_done +; cp 25h ; Ctrl+L панель информации +; jr z,event_comb_done +; ret +;event_comb_done: +;evcomb_stack: +; ld sp,0 ; восст. стек до входа в fview +; jp keybar_options ; отработать Ctrl,Alt,Shift комбинации + + +;hidd: push iy +; push ix +; ld a,true +; ld (set_qview_fl),a ; уст. флаг "не заходить снова в fview" +; call hidden_panels +; pop ix +; pop iy +; call test_show_panels ; тест на режим вкл. панелей +; ret z ; выкл. +; pop hl ; восст. баланс стека +; call event_comb_return ; вкл. стр. гляделки +; ; вывести содерж. файла в панели +; ld hl,AB317 ; ascii-окно +; ld a,(cur_mode_dump) ; 0/1 флаг тек. окна (ascii/hex) +; or a +; jr z,$+5 +; ld hl,ABB1C ; hex-окно +; jp (hl) + + +;swap: push iy +; push ix +; call swap_panels +; pop ix +; pop iy +; ret + + + + +;------------------------------------------------- +; Ctrl+Q. Вызов из fview +;------------------------------------------------- +;qv_panel: +; ld a,(page_module1) +; out (SLOT1),a ; восст. стр. +; jp alt_qview_panel diff --git a/FVIEW/FVIEW.Z80 b/FVIEW/FVIEW.Z80 new file mode 100755 index 0000000..0d8ce74 --- /dev/null +++ b/FVIEW/FVIEW.Z80 @@ -0,0 +1,14 @@ +;╔═══════ fview ═══════╗ +;║ ║ +;║ Reading file... ║ +;║ ║ +;╚═════════════════════╝ +; Описатель окна функции "fview" +win_fview_load_file: + dw 0A1Ch,0517h ; Yo,Xo,lenY,lenX + db "fview",0 ; титл окна + ; + db TextLine + dw 0205h ; Yo,Xo + db "Reading file...",0 + db -1 ; конец описателя diff --git a/FVIEW/MSFVIEW.ASM b/FVIEW/MSFVIEW.ASM new file mode 100755 index 0000000..9085b72 --- /dev/null +++ b/FVIEW/MSFVIEW.ASM @@ -0,0 +1,216 @@ +;----------------------------------------------------------- +; Обработка мышки в ASCII окне +; +; вход: hl=Y/X текст. координаты мышки +; d=биты нажатия бутонов +;----------------------------------------------------------- +fview_mouse_ascii: + ld a,(viewer_mode) ; режим работы вьюера + or a + jp nz,get_fire ; панельный режим + ld bc,AB33F ; точка выхода + push bc + ld a,h + or a ; 0-я строка + jp z,get_fire ; верхняя статус. линия + cp 31 ; key-бар + jr c,fv_ms_ascii ; события в окне + ; события key-бара + bit 0,d ; правый бутон ? + jp nz,get_fire ; да + push hl + call get_fire ; защита от "залипания" + pop hl + ld a,l ; X координата + cp 8 + ret c; ; F1 пункт + cp 16 + jp c,AB5C8 ; F2 пункт Wrap/UnWrap + cp 24 + ret c; ; F3 пункт + pop bc ; восст. баланс стека (для пункта F4) + cp 32 + jp c,ABB1C ; F4 пункт HEX-режим + push bc ; точку выхода в стек + cp 40 + ret c; ; F5 пункт + cp 48 + ret c; ; F6 пункт + cp 56 + ret c; ; F7 пункт + cp 64 + jp c,change_code_page ; F8 пункт Смена код. страницы + cp 72 + ret c; ; F9 пункт + ; F10 пункт + pop bc ; восст. баланс стека + ret ; F10 пункт + + +; События окна +; вход: hl=Y/X коорд. мышки (Y=1..30, X=0..79) +; d=биты нажатия бутонов +fv_ms_ascii: + bit 0,d ; правый бутон ? + jr nz,fv_ms_ascii_right ; да + ld a,h ; X координата + cp 16 ; начало нижней половины окна + jp c,fv_ms_ascii1 + ; на строку вниз + call AB987 + halt + call get_mouse_info + and 3 + jr nz,$-9 ; бутоны нажаты + ld a,evNothing + ld (what),a ; список событий + ret + ; на строку вверх +fv_ms_ascii1: + call AB81D + halt + call get_mouse_info + and 3 + jr nz,$-9 ; бутоны нажаты + ld a,evNothing + ld (what),a ; список событий + ret + +; Правый бутон +fv_ms_ascii_right: + ld a,l ; Y координата + cp 40 ; начало правой половины окна + jr c,fv_ms_ascii_right1 + ; курсор вправо + call AB610 + halt + call get_mouse_info + and 3 + jr nz,$-9 ; бутоны нажаты + ld a,evNothing + ld (what),a ; список событий + ret + ; курсор влево +fv_ms_ascii_right1: + call AB5FE + halt + call get_mouse_info + and 3 + jr nz,$-9 ; бутоны нажаты + ld a,evNothing + ld (what),a ; список событий + ret + + + + + + + +;----------------------------------------------------------- +; Обработка мышки в HEX окне +; +; вход: hl=Y/X текст. координаты мышки. +; d=биты нажатия бутонов +;----------------------------------------------------------- +fview_mouse_hex: + ld a,(viewer_mode) ; режим работы вьюера + or a + jp nz,get_fire ; панельный режим + ld bc,ABB4A ; точка выхода + push bc + ld a,h + or a ; 0-я строка + jp z,get_fire ; верхняя статус. линия + cp 31 ; key-бар + jr c,fv_ms_hex ; события в окне + ; события key-бара + bit 0,d ; правый бутон ? + jp nz,get_fire ; да + push hl + call get_fire ; защита от "залипания" + pop hl + ld a,l ; X координата + cp 8 + ret c; ; F1 пункт + cp 16 + ret c; ; F2 пункт + cp 24 + ret c; ; F3 пункт + pop bc ; восст. баланс стека (для пункта F4) + cp 32 + jp c,AB317 ; F4 пункт ASCII-режим + push bc ; точку выхода в стек + cp 40 + jp c,ABDF3 ; F5 пункт Goto... + cp 48 + ret c; ; F6 пункт + cp 56 + ret c; ; F7 пункт + cp 64 + jp c,change_code_page1 ; F8 пункт Смена код. страницы + cp 72 + ret c; ; F9 пункт + ; F10 пункт + pop bc ; восст. баланс стека + ret ; F10 пункт + + +; События окна +; вход: hl=Y/X коорд. мышки (Y=1..30, X=0..79) +; d=биты нажатия бутонов +fv_ms_hex: + bit 0,d ; правый бутон ? + ret nz ; да + ld a,h ; X координата + cp 1 + jr nz,$+9 + ld a,l ; X координата + cp 9 ; на поле ввода адреса ? + jp c,ABDF3 ; да, Goto... + ld a,h + cp 16 ; начало нижней половины окна + jp c,fv_ms_hex1 + ; на строку вниз + call ABCDB + halt + call get_mouse_info + and 3 + jr nz,$-9 ; бутоны нажаты + ld a,evNothing + ld (what),a ; список событий + ret + ; на строку вверх +fv_ms_hex1: + call ABC9A + halt + call get_mouse_info + and 3 + jr nz,$-9 ; бутоны нажаты + ld a,evNothing + ld (what),a ; список событий + ret + + + +;----------------------------------------------------------- +; Обработка мышки в поле ввода адреса Goto... +; +; вход: hl=Y/X текст. координаты мышки. +; a=биты нажатия бутонов +;----------------------------------------------------------- +fview_mouse_goto: + ld a,(viewer_mode) ; режим работы вьюера + or a + jp nz,get_fire ; панельный режим + ld bc,ABE29 ; точка выхода + push bc + ld a,h + dec a ; 1-я строка + jr nz,$+6 + ld a,l ; X координата + cp 9 + ret c ; остаться в поле ввода + pop bc ; восст. баланс стека + call get_fire ; панельный режим + jp ABF5C ; Esc diff --git a/FVIEW/SETVIEW.ASM b/FVIEW/SETVIEW.ASM new file mode 100755 index 0000000..9a18a95 --- /dev/null +++ b/FVIEW/SETVIEW.ASM @@ -0,0 +1,151 @@ +; normal: 80 - длина строки +; 30 - число строк +; qview: 38 - длина строки +; 28 - число строк +; + + +len_string equ 80 ; длина строки +num_strings equ 30 ; число строк + + +; Полож. курсора +coord: dw 0100h ; Y/X + +; Полож. окна +winpos: dw 0 ; Y/X + +; Размеры окна +winsize:dw 0 ; Y/X 1C26h=28/38, 1E50h=30/80 + +cur_mode_dump: + db 0 ; 0/1 флаг тек. окна (ascii/hex) + + + + +; Настроить константы вьюера +setup_fview: + ld de,0100h ; Y/X + ld a,(viewer_mode) ; 0/1 режим вьюера (норм./панельный) + ld c,a + or a + jr z,setp__ ; обойти при норм. режиме + ld hl,panel_right ; координаты пасс. панели + ld d,(hl) ; Y полож. панели + inc hl + ld e,(hl) ; X полож. панели + inc d + inc e +setp__: ld (coord),de ; полож. курсора + ld (winpos),de ; полож. окна + ;xor true + ;ld (UnWrap),a ; 0/1 режим переноса строк + ; + ld hl,1E50h ; 30/80 норм. режим + dec c + inc c + jr z,$+5 + ld hl,1C26h ; 28/38 панельный режим + ld (winsize),hl ; размеры окна + ; + ; Константа 1 + ld hl,82*30 ; норм. режим (len_string * num_strings) + dec c + inc c + jr z,$+5 + ld hl,40*28 ; панельный режим + ld (const01+1),hl + ld (const02+1),hl + ld (const03+1),hl + ld (const04+1),hl + ; Константа 2 + ld hl,16*30 ; норм. режим (16 * num_strings) + dec c + inc c + jr z,$+5 + ld hl,16*28 ; панельный + ld (const20+1),hl + ld (const21+1),hl + ld (const22+1),hl + ld (const23+1),hl + ld (ABD79+1),hl + ld (const25+1),hl + ld (const26+1),hl + ; Число строк + ; -1 + ld a,29 ; норм. режим + dec c + inc c + jr z,$+4 + ld a,27 ; панельный + ld (mt01+1),a + inc a ; +0 + ld (met03+1),a + ld (met07+1),a + ld (met09+1),a + ld (met12+1),a + ld (AB6C7+1),a + ld (AB75C+1),a + ld (AB7E5+1),a + inc a ; +1 + ld (metk04+1),a + ld (metk05+1),a + ld (metk06+1),a + ld (metk07+1),a + ld (metk08+1),a + ld (metk09+1),a + ld (metk10+1),a + ld (metk11+1),a + ld (metk12+1),a + ld (metk13+1),a + ; Длина строки + ; -2 + ld hl,78 ; норм. режим + dec c + inc c + jr z,$+5 + ld hl,36 ; панельный + ld a,l + ld (loc20+1),a + ld (loc22+1),a + ld (loc21+1),hl + ld (loc23+1),hl + add a,2 ; +0 + ld (loc04+1),a + ld (loc06+1),a + ld (loc07+1),a + ld (loc08+1),a + ld (loc09+1),a + ld (loc10+1),a + ld (loc11+1),a + ld (loc12+1),a + ld (loc13+1),a + ld (loc14+1),a + ld (loc15+1),a + ld (loc16+1),a + ld (loc17+1),a + ld (loc18+1),a + ld (loc19+1),a + ld (AB450+1),a + inc a ; +1 + ld (loc30+1),a + inc a ; +2 + ld l,a + ld h,0 + ld (loc43+1),a + ld (loc40+1),hl + ld (loc41+1),hl + ld (loc42+1),hl + ld (loc44+1),hl + ld (loc45+1),hl + ld (AB8B5+1),hl + ; Крайнее X левое полож. окна при скроллинге вправо + ld a,255-80 ; 175 норм. режим + dec c + inc c + jr z,$+4 + ld a,255-38 ; панельный + ld (AB618+1),a + ld (AB63A+1),a + ret diff --git a/MAIN.ASM b/MAIN.ASM new file mode 100755 index 0000000..3cbff58 --- /dev/null +++ b/MAIN.ASM @@ -0,0 +1,521 @@ +; Последнее редактирование: 4.01.2006 +; + +; В странице (page_sys_screen) сохранения сист. экрана и временного +; сохранения экрана менеджера, по адресу #E800 находятся буферы +; данных User-меню. Остаток страницы после всего массива #0944 байт. +; +; При сканировании папки (процедура ScanTree), для врем. буфера выделяется +; 1 страница памяти. После отработки процедуры, страница освобождается. +; +; +; include 'shared_includes/constants/Sp2000.inc' + +EDEPTH equ 36 ; слишком большая влож. папок или >= 1024 папок +EUABORT equ 37 ; User abort (операция прервана пользователем) + +max_len_comline equ 126;254 ; макс. длина ком-строки (больше не делать) +history_size equ 128;256 ; размер history-буфера + + +; Адреса секций врем. массива цветов в буфере +;tmp_color_list equ work_buffer + 511 - len_color_array ; начало врем. массива +;color_list2 equ tmp_color_list + col_lst1 +;color_list3 equ color_list2 + col_lst2 +;color_list4 equ color_list3 + col_lst3 +;color_list5 equ color_list4 + col_lst4 +;color_list6 equ color_list5 + col_lst5 +;color_list7 equ color_list6 + col_lst6 +;color_list8 equ color_list7 + col_lst7 +;color_list9 equ color_list8 + col_lst8 +;color_list10 equ color_list9 + col_lst9 +;color_list11 equ color_list10 + col_lst10 + + +;---- Цвета менеджера ---- +; Панель +color_pointer equ 3Fh ; указатель +color_markpoint equ 3Eh ; выдел. указатель +color_panel equ 1Bh ; панель/список файлов +color_markfile equ 1Eh ; помеч. файлы списка +color_seltitle equ 3Fh ; выдел. титл панели +color_title equ 1Eh ; титл колонок панели +color_markline equ 3Eh ; информ. строка отмеч. файлов +color_highlighted_info equ 1Eh ; данные в info/qview панелях +color_info_names equ 1Fh ; файлы/путь в info/qview панелях +; Гориз. меню +color_hmenu equ 30h ; меню +color_hmenu_pointer equ 0Fh ; указатель +color_hmenu_hotkey equ 0Eh ; hot-буквы +; Pull-меню +color_vmenu equ 3Fh ; popup-меню +color_vmenu_pointer equ 0Fh ; указатели меню +color_vmenu_hotkey equ 0Eh ; hot-буквы меню (мл.ниббл) +; Key-бар +kb_f equ 30h ; пункты +kb_b equ 0Eh ; hot-числа +; Командная строка +color_comline equ 07h +; Диал. окна +color_dial_win equ 70h ; диал. окна +color_dial_hotkey equ 0Eh ; hot-букв диал. окон +color_sel_dial_title equ 30h ; Selected title объекта диал. окна +color_info_win equ 70h ; info-окна +color_warn_win equ 4Fh ; warning/errors окна +color_listbox equ 17h ; ListBox +color_list_point equ 2Fh ; указателя ListBox-а +color_list_hpoint equ 1Eh ; после указателя +color_vscrl_bar equ 13h ; скролл-бара ListBox-а +color_inputline equ 30h ; строка ввода +color_selbuttons equ 30h ; выдел. бутон +color_selbuttons_err equ 70h ; выдел. бутон Warning/Errors окон +color_shadow equ 03h ; тень окон (не настраивается) +; Вьюер +color_viewer equ 1Bh ; Normal text +color_viewer_seltext equ 30h ; Selected text +color_viewer_status equ 30h ; Status line +color_viewer_scrl_arrow equ 1Eh ; Scrolling arrows +; Редактор +color_editor equ 1Bh ; Normal text +color_edit_seltext equ 30h ; Selected text +color_edit_status equ 30h ; Status line +; Окно помощи +color_help equ 30h ; Normal text +color_help_seltext equ 3Eh ; Highlighted text +color_help_title equ 3Fh ; Title +color_help_scrl_bar equ 30h ; Scrollbar +; Остальное +color_process_line equ 30h ; линейка процесса +color_clock equ 30h ; часы +; Раскраска файлов +color_folder equ 1Fh ; папки +color_exe equ 1Ah ; исполняемые файлы (exe,bat) +color_archive equ 1Dh ; архивы +color_ro equ 17h ; файлы r/o, system +color_hidden equ 13h ; скрытые файлы +color_spec equ 1Ch ; спек-файлы (trd, scl) + + + + + +; include 'version.inc' ; версия менеджера + + ; export id_block + ; export len_modul1 + ; export len_modul2 + ; export len_modul3 + ; export len_modul4 + ; export len_modul5 + ; export stack + ; export Xcoord + ; export Ycoord + + + org 8000h + +mod0: ; метка для вычисл. размера +;//////////////////////////////////////////////////////////////////////// +; +; Точка входа в менеджер +; +;//////////////////////////////////////////////////////////////////////// + + jp begin + + +; Хэндлы страниц менеджера +id_block: db -1 ; дескриптор выдел. блока памяти + ; +page_sys_screen:db -1 ; +0 сист. экран, +2800h данные user-menu +page_dial_screen: + db -1 ; буфер сохр. диал. окон и верт. меню +page_left_dir: db -1 ; список левой панели +page_right_dir: db -1 ; список правой панели +page_manager: db -1 ; осн. код менеджера +page_module0: db -1 ; драйверы клавы, мышки, диал. код с обраб. +page_module1: db -1 ; описатели панелей +page_spec: db -1 ; страница разбора спек-функций +page_viewer: db -1 ; страница вьюера + db -1 + db 0 ; стоп-байт + ; +port_82: db -1 ; сохр. порт 82h +port_E2: db -1 ; сохр. порт 0E2h +port_89: db -1 ; сохр. порт 89h + + +lastdrive: db 'B'-'A' ; последний диск в системе (0..25) + + + +;------------------------------------------------- +; Вызов ДОС-рестарта +;------------------------------------------------- +int10: ex af,af' + di + ld a,(port_82) ; дос-страница + out (SLOT0),a + ei + ex af,af' + rst 10h +int__: ex af,af' + di + ld a,(page_module0) + out (SLOT0),a ; восст. стр. драйверов клавы, мышки + ei + ex af,af' + ret + +;------------------------------------------------- +; Вызов RST 18h +;------------------------------------------------- +int18: ex af,af' + di + ld a,(port_82) ; дос-страница + out (SLOT0),a + ei + ex af,af' + rst 18h + jr int__ + + +;------------------------------------------------- +; Вызов RST 10h из спек-страницы +;------------------------------------------------- +alt10: ex af,af' + di + ld a,(port_82) ; дос-страница + out (SLOT0),a + ei + ex af,af' + rst 10h +alt__: ex af,af' + di + ld a,(page_spec) + out (SLOT0),a ; восст. стр. + ei + ex af,af' + ret + +;------------------------------------------------- +; Вызов RST 18h из спек-страницы +;------------------------------------------------- +alt18: ex af,af' + di + ld a,(port_82) ; дос-страница + out (SLOT0),a + ei + ex af,af' + rst 18h + jr alt__ + + + + include 'fview/fview.inc' ; процедуры выхода из гляделки + + + + + +; рабочий буфер ФМ +work_buffer: ds 512 + + + ds 80 +stack: ; стек ФМ + + + +begin: + ; узнать boot-диск системы + ld bc,0009h + rst 10h + add a,"A" + ld (ccp_name),a ; launch.asm + ; иниц. номера страниц в структурах панелей + ld a,(page_left_dir) + ld (cash_left_dir),a + ld a,(page_right_dir) + ld (cash_right_dir),a + ; вкл. в #4000 стр. ФМ + ld a,(page_module1) + out (SLOT1),a + ; сохр. тек. диск + ld c,2 + rst 10h + ld (save_disk),a + ; сохр. текущий путь + ld hl,save_path + ld c,1Eh + rst 10h + + + include 'shell.asm' ; файлер + include 'mod2/fillstr.asm' ; заполнение строки файлера + include 'mod2/event.asm' ; чтение событий + include 'mod2/mouse.asm' ; мышка + include 'mod2/keybar.asm' ; key-бар + include 'mod2/clock.asm' ; часы панелей + include 'mod2/setup.asm' ; чтение/запись ini-файла, mnu-файл + include 'mod2/space.asm' ; своб. объем диска + include 'mod2/hilight.asm' ; подсветка файлов + include 'mod2/readdsk.asm' ; чтение новой папки + include 'mod2/enter.asm' ; обработка нажатия + include 'mod2/launch.asm' ; запуск файлов + include 'mod2/pos.asm' ; позиц. указателя после смены списка + include 'mod2/utils.asm' ; вспом. процедуры + include 'mod2/copy.asm' ; копирование файлов + include 'mod2/info.asm' ; info-режим панели + include 'mod2/qview.asm' ; qview-режим панели + include 'mod2/mkdir.asm' ; создание папки (F7) + include 'mod2/delete.asm' ; удаление файла/папки (F8) + include 'mod2/rename.asm' ; переименование файла (F6) + + include 'mod2/debug.asm' + + + +; Режим работы вьюера +viewer_mode: db 0 ; 0=обычный, 1=панельный + +attr_record: db 0 ; атрибут тек. записи списка каталога + +del_confirm: db true ; флаг подтв. удаления файлов/папок + +flag_del_non_empty: + db true ; флаг подтв. удаления не пустых папок + +move_home_end: db false ; флаг отработки Home/End при откр. панелях + +enable_mnu_file:db false ; флаг наличия mnu-файла + + + + + + +;------------------------------------------------- +; Стандартный выход в ДОС +;------------------------------------------------- +exit: ld a,b + ld (return_code+1),a ; сохр. код возврата + ; восст. ДОС-страницу + di + ld a,(port_82) + out (SLOT0),a + ei + ; полож. сист. мышки по местному драйверу +Xcoord+1: ld hl,0 ; координата X (0..639) +Ycoord+1: ld de,0 ; координата Y (0..255) + ld c,4 ; уст. полож. мышки + rst 30h + ; уст. сист. диск и путь акт. панели + call set_path_from_activ_panel + ; восст. значение порта + ld a,(port_89) + out (89h),a + ; восст. сист. экран + ld c,0B3h + ld a,(page_sys_screen) ; страница буфера + call screen__ + ; восст. значение порта + ld a,(port_E2) + out (SLOT3),a + ; восст. полож. курсора сист. экрана +sys_cursor_coords: + ld de,0 + ld c,84h + rst 08h + ; освоб. выделенный блок памяти + ld a,(id_block) + ld c,3Eh + rst 10h + ; очистить буфер сист. клавы + ld bc,3135h + rst 10h +return_code: ld b,0 ; код возврата + ld c,41h + rst 10h + ret + + + + +;----------------------------------------------------------- +; Сохранить/восст. полный системный экран +;----------------------------------------------------------- +; вход: C = #B2/#B3 сохр./восст. экран +; A = номер страницы буфера окна +screen__: ld hl,2050h ; высота/ширина экрана +scrn1__: ld ix,0C000h ; адрес буфера для данных +scrn2__: ld b,a + xor a ; идентиф. глоб. окна + ld e,a ; X полож. + ld d,a ; Y полож. + di + rst 08h + ei + ret + +;----------------------------------------------------------- +; Сохранить/восст. системный экран до ком. строки +;----------------------------------------------------------- +; вход: C = #B2/#B3 сохр./восст. экран +; A = номер страницы буфера окна (page_sys_screen) +screen1__: ld hl,1E50h ; высота/ширина экрана + jr scrn1__ + +;----------------------------------------------------------- +; Сохранить/восст. полный экран менеджера +;----------------------------------------------------------- +; in: c=#B2/#B3 сохр./восст. экран +; a=номер страницы буфера окна (page_sys_screen) +screen2__: ld hl,2050h ; высота/ширина экрана + ld ix,0C000h+1400h ; начало экрана менеджера + jr scrn2__ + +;----------------------------------------------------------- +; Рестарт для Меню и диал. окон +;----------------------------------------------------------- +scrn4__: ld b,a +scrn5__: xor a ; идентиф. глоб. окна + di + rst 08h + ei + ret + + + + + + + +mod1: ; метка для вычисл. размера + +;=========================================================== +; Подгружаемый Модуль 1 +; Драйверы клавы, мышки, обработчик диал. окон, tv-объекты +;=========================================================== +; всегда подключен (кроме вызовов rst 10h, rst 18h) + + phase 0000h + + include 'mod0/vectors.asm' ; векторы прерываний + include 'mod0/keybdrv.asm' ; драйвер клавы + include 'mod0/cursor.asm' ; программный курсор + include 'mod0/mousedrv.asm' ; драйвер мышки + + include 'objs/dialog.asm' ; обработчик диал. окон + include 'objs/button.asm' ; объект ~Button~ + include 'objs/inline.asm' ; объекты ~Input Line~, ~Inp Line~ + include 'objs/listbox.asm' ; объект ~List Box~ + include 'objs/radio.asm' ; объекты ~Radio Button~, ~Check Box~ + include 'objs/process.asm' ; объект ~Process Line~ + include 'objs/pallete.asm' ; объект ~Pallete~ + include 'objs/dialog1.asm' ; объекты ~Text Line~, ~Horiz. Line~ + include 'objs/hmenu.asm' ; Меню: "Horizontal", "Pull", "Select disk" + include 'objs/umenu.asm' ; вызов User-Menu + + include 'mod0/chdisk.asm' ; вызов меню Select Disk + include 'mod0/listdrv.asm' ; иниц. список типов дисков + include 'mod0/usermenu.asm' ; подготовка Меню Пользователя + + dephase + +mod2: + +;=========================================================== +; Подгружаемый Модуль 2 +;=========================================================== +; постоянно включен + + phase 4000h + + include 'mod1/buffers.asm' ; раб. буферы объектов + include 'mod1/comline.asm' ; ком-строка + include 'mod1/width.asm' ; огран. длины пути панели + include 'mod1/sort.asm' ; сортировка списка + include 'mod1/tree.asm' ; сканирование папки + include 'mod1/pullcmnd.asm' ; переходы на выполн. pull-пунктов + include 'mod1/seldrv.asm' ; выбор левого/правого дисков панелей + include 'mod1/intrface.asm' ; настройка "Interface settings" + include 'mod1/confirm.asm' ; настройка "Confirmations" + include 'mod1/color.asm' ; настройка "Colors" + include 'mod1/setcolor.asm' ; настройка цветов ФМ + include 'mod1/panels.z80' ; описатели форматов панелей + include 'mod1/info.z80' ; описатель info-панели + include 'mod1/info2.z80' ; описатель info-панели спек-формата + include 'mod1/qview.z80' ; описатель qview-панели + include 'mod1/hmenu.z80' ; описатели гориз/pull меню + include 'mod1/chdisk.z80' ; описатель окна Select Disk + include 'mod1/umenu.z80' ; описатель окна User Menu + include 'mod1/intrface.z80' ; описатель окна "Interface settings" + include 'mod1/confirm.z80' ; описатель окна "Confirmations" + include 'mod1/color.z80' ; описатель окна "Colors" + include 'mod1/quit.z80' ; описатель окна выхода из ФМ + include 'mod1/space.z80' ; описатель окна "Calc. free space disk" + include 'mod1/abort.z80' ; описатель окна "Operation has been interrupted" + include 'mod1/dialerr.z80' ; описатели окон ошибок + include 'mod1/copy.z80' ; описатели окон копирования + include 'mod1/mkdir.z80' ; описатель окна создания папки + include 'mod1/delete.z80' ; описатель окна удаление файла/папки + include 'mod1/rename.z80' ; описатель окна переимен. файла + dephase + +mod3: + +;=========================================================== +; Подгружаемый Модуль 3. Спек-код +;=========================================================== +; подкл. на время вызова спек-функций + + phase 0000h + + include 'spec/vect.asm' ; векторы + include 'spec/funcs.asm' ; спек-функции + + dephase + +mod4: + +;=========================================================== +; Подгружаемый Модуль 4. Вьюер +;=========================================================== +; подкл. на время вызова вьюера + + phase 4000h + + include 'fview/fview.asm' ; вьюер + include 'fview/msfview.asm' ; события мышки + include 'fview/setview.asm' ; настройка вьюера + include 'fview/chfont.asm' ; win-1251, koi8-r кодовые таблицы + include 'fview/fview.z80' ; описатель окна "Reading file..." + + dephase + + + + +; Адреса секций врем. массива цветов в буфере +tmp_color_list equ work_buffer + 511 - len_color_array ; начало врем. массива +color_list2 equ tmp_color_list + col_lst1 +color_list3 equ color_list2 + col_lst2 +color_list4 equ color_list3 + col_lst3 +color_list5 equ color_list4 + col_lst4 +color_list6 equ color_list5 + col_lst5 +color_list7 equ color_list6 + col_lst6 +color_list8 equ color_list7 + col_lst7 +color_list9 equ color_list8 + col_lst8 +color_list10 equ color_list9 + col_lst9 +color_list11 equ color_list10 + col_lst10 + + + + +addr_id_block equ id_block ; адрес ячейки id_block +len_modul1 equ mod1 - mod0 ; размер осн. кода (#8000) +len_modul2 equ mod2 - mod1 ; размер модуля (#0000) +len_modul3 equ mod3 - mod2 ; размер модуля (#4000) +len_modul4 equ mod4 - mod3 ; размер спек-модуля (#0000) +len_modul5 equ $ - mod4 ; размер вьюера (#4000) diff --git a/MOD0/CHDISK.ASM b/MOD0/CHDISK.ASM new file mode 100755 index 0000000..f25eb22 --- /dev/null +++ b/MOD0/CHDISK.ASM @@ -0,0 +1,51 @@ +;///////////////////////////////////////////////// +; Левое меню выбора дисков +;///////////////////////////////////////////////// +select_left_drive: + call test_show_panels ; тест на режим вкл. панелей + ret z + call make_struct_drives ; создать описатель меню выбора дисков + ld hl,disk ; диск акт. панели + ld de,format_mode ; формат акт. панели + ld a,(cur_panel) ; тек. панель + or a + jr z,$+8 ; акт. левая + ld hl,disk1 ; диск пасс. панели + ld de,format_mode1 ; формат пасс. панели + ld (set_ldrive_dsk+1),hl + ld (set_ldrive_frm+1),de + ld a,(hl) ; номер диска (полож. пункта меню) + inc a + ld hl,table_left_drive ; таблица меню выбора + call put_menu_select ; отрисовка меню + call get_fire ; защита от "залипания" бутонов + call event_menu_select ; обработчик событий меню + ; уст. диск панели + jp set_left_drive ; seldrv.asm + + + +;///////////////////////////////////////////////// +; Правое меню выбора дисков +;///////////////////////////////////////////////// +select_right_drive: + call test_show_panels ; тест на режим вкл. панелей + ret z + call make_struct_drives ; создать описатель меню выбора дисков + ld hl,disk ; диск акт. панели + ld de,format_mode ; формат акт. панели + ld a,(cur_panel) ; тек. панель + or a + jr nz,$+8 ; акт. правая + ld hl,disk1 ; диск пасс. панели + ld de,format_mode1 ; формат пасс. панели + ld (set_rdrive_dsk+1),hl + ld (set_rdrive_frm+1),de + ld a,(hl) ; номер диска (полож. пункта меню) + inc a + ld hl,table_right_drive ; таблица меню выбора + call put_menu_select ; отрисовка меню + call get_fire ; защита от "залипания" бутонов + call event_menu_select ; обработчик событий меню + ; уст. диск панели + jp set_right_drive ; seldrv.asm diff --git a/MOD0/CURSOR.ASM b/MOD0/CURSOR.ASM new file mode 100755 index 0000000..b4539b2 --- /dev/null +++ b/MOD0/CURSOR.ASM @@ -0,0 +1,62 @@ +CursorPos: + dw 1E00h ; Y/X позиция курсора (экран. коорд.) + + +;----------------------------------------------------------- +; Курсор объекта "Input Line" и функции "Command Line" +;----------------------------------------------------------- +PrnILCr:db 3Eh ; ld a,.. +Timer: db 1 ; пауза мигания + dec a + call z,PutILCr + ld (Timer),a + ret + + +PutILCr:db 3Eh ; ld a,.. +Flag: db 0 ; флаг курсора 00-нет/01-есть + cpl + ld (Flag),a +PILCurs:ld de,(CursorPos) ; Y/X позиция курсора + ld (CursPos1+1),de + xor a + ld c,0B4h ; получить символ + rst 08h + ld bc,1BB5h ; b=знакоген., с=символ на экран + ld a,(Flag) + or a + jr z,curs__ + ld b,1Ah ; черта + ld a,(D0642) ; флаги клавы + bit 1,a ; бит Ins + jr nz,$+4 + ld b,19h ; блок +curs__: xor a ; номер окна + rst 08h + ld a,1 + ld (CurILFl),a ; a=1 + ld a,11 + ret + +; Выключить курсор +ResILCr:db 3Eh ; ld a,.. +CurILFl:db 0 ; флаг курсора 00-выкл/01-вкл + or a + ret z + ld a,-1 + ld (Flag),a + inc a + ld (CurILFl),a + ld a,11 + ld (Timer),a +CursPos1: + ld de,0 ; Y/X полож. + bit 7,e + ret nz + ld c,0B4h ; получить символ + xor a + rst 08h + xor a + ld bc,1BB5h ; символ на экран + rst 08h + ret diff --git a/MOD0/KEYBDRV.ASM b/MOD0/KEYBDRV.ASM new file mode 100755 index 0000000..8891f4f --- /dev/null +++ b/MOD0/KEYBDRV.ASM @@ -0,0 +1,649 @@ +; Метки T0600 и A0900 выравниваются на границу xx00h! +; + + + + + +; RST 20h. Драйвер клавиатуры +KeybDrv:or a ; a=0 иниц. клаву + jp z,init_keyb + dec a ; a=1 очистить буфер клавы + jr z,func_35 + dec a ; a=2 опрос без ожидания + jr z,func_31 + ;dec a ; a=3 тест нажатия клавиши (NZ-да, Z-нет) + jr func_33 + ;ret + + + + +;///////////////////////////////////////////////////////////////////// +; Функция #31. Опрос клавиатуры без ожидания. +; +; выход: A=код символа +; D=скен-код, Е=код символа +; B=биты Ctrl,Alt,Shift +; Z - нет клавиш +;///////////////////////////////////////////////////////////////////// +func_31:;ld hl,D0641 + ;ld a,(D0640) + ;cp (hl) + ;ret z ; нет клавиши + call A06FC + ld a,e + ret + + +;///////////////////////////////////////////////////////////////////// +; Функция #33. Получить состояние клавиатуры. +; Возвращает состояние клавиатуры на данный момент. +; +; выход: Z - нет символов в буфере +; B=биты Ctrl,Alt,Shift +;///////////////////////////////////////////////////////////////////// +func_33:ld hl,D0641 + ld a,(D0640) + cp (hl) + ld bc,(D0642) ; флаги клавы + ld a,0 + ret z ; z - не нажата + dec a ; nz - нажата + ret + + +;///////////////////////////////////////////////////////////////////// +; Функция #35. Очистить буфер клавиатуры +;///////////////////////////////////////////////////////////////////// +func_35:ld a,(D0641) + ld (D0640),a + ret + + + + ds 0100h-$ ; выровнить на границу xx00h + +; раб. ячейки клавы + +T0600: ds 64 + ; +D0640: db 0 ; тек. адрес конца кольц. буфера? +D0641: db 0 ; адрес начала кольц. буфера? +; флаги клавы +D0642: db 2 + db 0 + db 0 + db 3 + ; +D0646: dw 0 + + +A06DD: ld hl,D0640 + ld a,(D0641) + sub 4 + and 3Fh ; ограничить адрес конца кольц. буфера + cp (hl) + jr z,A0716 ; конец кольц. буфера + ld a,(hl) + inc (hl) ; ячейка D0640 + inc (hl) + inc (hl) + inc (hl) + res 6,(hl) ; значение 40h -> 00h (сбр. конец кольц. буфера?) + ld l,a + ld h,T0600 / 256 ; 06h ст. байт адреса + ld (hl),e + inc l + ld (hl),d + inc l + ld (hl),b + inc l + ld (hl),c + ret + +A06FC: ld hl,D0641 + ld a,(D0640) + cp (hl) + ret z ; нет клавиши + ld a,(hl) + inc (hl) + inc (hl) + inc (hl) + inc (hl) + res 6,(hl) ; значение 40h -> 00h (сбр. конец кольц. буфера?) + ld l,a + ld h,T0600 / 256 ; 06h ст. байт адреса + ld e,(hl) + inc l + ld d,(hl) + inc l + ld b,(hl) + inc l + ld c,(hl) + ret + +; бип +A0716: ex af,af' + bit 0,(ix+3) + jr z,A0728 + exx + ld de,230 ; задержка внутр. цикла + ld hl,50 ; задержка внеш. цикла + call beep ; звук + exx +A0728: ex af,af' + ret + + + +A072A: set 7,(ix+2) + jr A0740 + +A0730: set 6,(ix+2) ; уст. бит "отжата" + jr A0740 + +A0736: set 5,(ix+2) + jr A0740 + +; сканирование клавы +keyb_scan: + ld ix,D0642 ; флаги клавы +A0740: in a,(19h) ; порт статуса + bit 0,a ; 0-bit, байт пришел ? + ret z ; нет + ld a,1 + ld (KeyPres+1),a ; драйвер мышки + in a,(18h) + cp 0F0h ; клавиша отжата ? + jr z,A0730 ; да + cp 0E0h + jr z,A072A ;7bit + cp 0E1h ; Pause + jr z,A0736 ;5bit + bit 6,(ix+2) + jr nz,A07B3 + ld l,a + call A0990 + call A0892 + res 7,(ix+2) + res 5,(ix+2) + ret z + call A09B4 + ; + ld hl,1C00h ; Caps Lock + and a + sbc hl,de + call z,A07C8 + ld hl,0B800h ; Space + Ctrl, Alt + and a + sbc hl,de + call z,A07D1 + ld hl,5000h ; Ins + and a + sbc hl,de + call z,A07EF + ld hl,4900h ; Num Lock + and a + sbc hl,de + call z,A07F8 ; инв. 3-й бит (бит Num Lock) + ld hl,0C900h ; Pause или Num Lock+80h (Num Lock+Ctrl/Atl/Shift) + and a + sbc hl,de + call z,A0801 + ld hl,4800h ; Scroll Lock + and a + sbc hl,de + call z,A081E ; инв. 2-й бит (бит Scroll Lock) + ld hl,0CF00h ; Del+80h (с Shift) + and a + sbc hl,de + call z,reboot_system ; тест на Ctrl+Alt + ld bc,(D0642) ; флаги клавы + jp A06DD + ;call A06DD ; сохр. de,bc в кольц. буфере клавы + ;ret ; не оптимизить + +A07B3: res 6,(ix+2) + ld l,a + call A0990 + call A0837 + res 7,(ix+2) + ld h,0 + ld (D0646),hl + ret + +A07C8: ld a,(ix+0) + xor 1 + ld (ix+0),a + ret + +A07D1: bit 5,(ix+1) ; бит Ctrl + ret z + ld a,(ix+0) + xor 80h ; 7-й бит (1=RUS,0=LAT) + ld (ix+0),a + bit 1,(ix+3) + ret z + exx + ld de,190 ; задержка внутр. цикла + ld hl,20 ; задержка внеш. цикла + call beep ; звук + exx + ret + +A07EF: ld a,(ix+0) + xor 2 ; 1-й бит (Ins) + ld (ix+0),a + ret + +A07F8: ld a,(ix+0) + xor 8 ; 3-й бит + ld (ix+0),a + ret + +; Pause или Num Lock + Ctrl, Atl, Shift +A0801: bit 5,(ix+1) ; бит Ctrl ? + ret z ; нет +; pop hl ; ?? + ld a,(ix+0) + xor 40h ; 6-й бит + ld (ix+0),a + bit 6,(ix+0) + ret z + ei +A0815: halt + bit 6,(ix+0) + jr nz,A0815 + di + ret + +A081E: ld a,(ix+0) + xor 4 + ld (ix+0),a + ret + +; клавиша Del +reboot_system: + ;bit 5,(ix+1) ; бит Ctrl + ;ret z + ;bit 4,(ix+1) ; бит Alt + ;ret z + ld c,00110000b ; биты Ctrl, Alt + ld a,(ix+1) + and c + cp c + ret nz + ; софтовый ребут + xor a + ld bc,01FDh + rst 08h + ret + ;db 0,0; + +A0837: ld a,l + cp 37h + jr nz,A084A + res 2,(ix+1) + bit 0,(ix+1) + ret nz + res 4,(ix+1) + ret + ; +A084A: cp 39h + jr nz,A085C + res 0,(ix+1) + bit 2,(ix+1) + ret nz + res 4,(ix+1) + ret + ; +A085C: cp 36h + jr nz,A086E + res 3,(ix+1) + bit 1,(ix+1) + ret nz + res 5,(ix+1) + ret + ; +A086E: cp 3Ah + jr nz,A0880 + res 1,(ix+1) + bit 3,(ix+1) + ret nz + res 5,(ix+1) + ret + ; +A0880: cp 29h + jr nz,A0889 + res 7,(ix+1) + ret + ; +A0889: cp 34h + ;jr nz,A0891 + ret nz + res 6,(ix+1) + ret +;A0891: ret + + +A0892: ld a,l + cp 37h + jr nz,A08A0 + set 2,(ix+1) + set 4,(ix+1) + ret + ; +A08A0: cp 39h + jr nz,A08AD + set 0,(ix+1) + set 4,(ix+1) + ret + ; +A08AD: cp 36h + jr nz,A08BA + set 3,(ix+1) + set 5,(ix+1) + ret + ; +A08BA: cp 3Ah + jr nz,A08C7 + set 1,(ix+1) + set 5,(ix+1) + ret + ; +A08C7: cp 29h + jr nz,A08D0 + set 7,(ix+1) + ret + ; +A08D0: cp 34h + ;jr nz,A08D8 + ret nz + set 6,(ix+1) + ret +;A08D8: ret + + + +A0990: bit 7,(ix+2) + jr z,A09B0 + cp 11h + ld l,39h + ret z + cp 14h + ld l,3Ah + ret z + cp 5Ah + ld l,4Eh + ret z + cp 4Ah + ld l,4Ah + ret z + cp 7Ch + ld l,47h + ret z + ld l,a +A09B0: ld h,A0900 / 256 ; 09h ст. байт адреса + ld l,(hl) + ret + + +A09B4: ld d,l + ld e,0 + bit 7,(ix+0) + jp nz,A09F6 + ld a,(ix+1) + and 0C0h + jr nz,A09E3 + set 7,d + bit 4,(ix+1) + ret nz + bit 5,(ix+1) + ret nz + ld d,l + bit 0,(ix+0) + ld bc,T0B75 + jr nz,A09DE + ld bc,T0AC1 +A09DE: ld h,0 + add hl,bc + ld e,(hl) + ret + ; +A09E3: ld bc,T0B1B + bit 0,(ix+0) + jr z,A09EF + ld bc,T0BCF +A09EF: ld h,0 + add hl,bc + ld e,(hl) + set 7,d + ret + ; +A09F6: ld a,(ix+1) + and 0C0h + jr nz,A0A1B + set 7,d + bit 4,(ix+1) + ret nz + bit 5,(ix+1) + ret nz + ld d,l + bit 0,(ix+0) + ld bc,T0CDD + jr nz,A0A16 + ld bc,T0C29 +A0A16: ld h,0 + add hl,bc + ld e,(hl) + ret + ; +A0A1B: ld bc,T0C83 + bit 0,(ix+0) + jr z,A0A27 + ld bc,T0D37 +A0A27: ld h,0 + add hl,bc + ld e,(hl) + set 7,d + ret + + + ds 0400h-$ ; выровнить на границу xx00h + +; Должно начинаться с границы xx00h! +; 144 байта. +A0900: db 0,43h,0,3Fh,3Dh,3Bh,3Ch,46h + db 0,44h,42h,40h,3Eh,0Fh,0,0 + db 0 + db 37h,29h,0 + db 36h,10h,2,0 + db 0,0,2Ah,1Eh,1Dh,11h,3,0 + db 0,2Ch,2Bh,1Fh,12h,5,4,0 + db 0,38h,2Dh,20h,14h,13h,6,0 + db 0,2Fh,2Eh,22h,21h,15h,7,0 + db 0 +A0939: db 0 +A093A: db 30h,23h,16h,8,9,0,0,31h + db 24h,17h,18h,0Bh,0Ah +A0947: db 0,0,32h +A094A: db 33h,25h,26h,19h +A094E: db 0Ch,0,0,0,27h,0,1Ah,0Dh + db 0,0,1Ch,34h + db 28h,1Bh,0,35h + db 0,0,0,0,0,0,0,0 + db 0Eh,0,0,51h,0,54h,57h,0 + db 0,0,50h,4Fh,52h,55h,56h,58h + db 1,49h,45h,4Dh,53h,4Ch + db 4Bh,59h + db 48h,0,0,0,0,41h,0,0 + db 0,0,0,0,0,0,0,0 + db 0,0 + + + +; Таблица кодов клавиш (8 секций по 90 байт) +T0AC1: db "`",1Bh,"1","2","3","4","5","6","7","8","9","0","-","=",8 + db 9,"q","w","e","r","t","y","u","i","o","p","[","]" + db 0 ; CapsLock + db "a","s","d","f","g","h","j","k","l",";","'",0Dh + db 0 ; Left Shift + db "z","x","c","v","b","n","m",",",".","/" + db 0 ; Right Shift + db '\' + db 0 ; Ctrl + db 0 ; Alt + db 20h ; Space + db 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 + ; доп. поле + db 0 ; NumLock + db "/","*","-","+",0Dh + db 0,0,0,0,0,0,0,0,0,0,0 + ; + ; +T0B1B: db "~",1Bh,"!","@","#","$","%","^","&","*","(",")","_","+",8 + db 9,"Q","W","E","R","T","Y","U","I","O","P","{","}" + db 0 ; CapsLock + db "A","S","D","F","G","H","J","K","L",":",'"',0Dh + db 0 ; Left Shift + db "Z","X","C","V","B","N","M","<",">","?" + db 0 ; Right Shift + db "|",0,0 + db 20h ; Space + db 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 + ; доп. поле + db 0 ; NumLock + db "/","*","-","+",0Dh + db 0,0,0,0,0,0,0,0,0,0,0 + ; + ; +T0B75: db "`",1Bh,"1","2","3","4","5","6","7","8","9","0","-","=",8 + db 9,"Q","W","E","R","T","Y","U","I","O","P","[","]",0 + db "A","S","D","F","G","H","J","K","L",";","'",0Dh,0 + db "Z","X","C","V","B","N","M",",",".","/",0 + db '\',0,0 + db 20h ; Space + db 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 + ; доп. поле + db 0 ; NumLock + db "/","*","-","+",0Dh + db 0,0,0,0,0,0,0,0,0,0,0 + ; + ; +T0BCF: db "~",1Bh,"!","@","#","$","%","^","&","*","(",")","_","+",8 + db 9,"q","w","e","r","t","y","u","i","o","p","{","}",0 + db "a","s","d","f","g","h","j","k","l",":",'"',0Dh,0 + db "z","x","c","v","b","n","m","<",">","?",0 + db "|",0,0 + db 20h ; Space + db 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 + ; доп. поле + db 0 ; NumLock + db "/","*","-","+",0Dh + db 0,0,0,0,0,0,0,0,0,0,0 + ; + ; +T0C29: db "ё",1Bh,"1","2","3","4","5","6","7","8","9","0","-","=",8 + db 9,"й","ц","у","к","е","н","г","ш","щ","з","х","ъ",0 + db "ф","ы","в","а","п","р","о","л","д","ж","э",0Dh,0 + db "я","ч","с","м","и","т","ь","б","ю",".",0 + db '\',0,0 + db 20h ; Space + db 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 + ; доп. поле + db 0 ; NumLock + db "/","*","-","+",0Dh + db 0,0,0,0,0,0,0,0,0,0,0 + ; + ; +T0C83: db "Ё",1Bh,"!",'"',"#","$",":",",",".",";","?","%","_","+",8 + db 9,"Й","Ц","У","К","Е","Н","Г","Ш","Щ","З","Х","Ъ",0 + db "Ф","Ы","В","А","П","Р","О","Л","Д","Ж","Э",0Dh,0 + db "Я","Ч","С","М","И","Т","Ь","Б","Ю",",",0 + db "|",0,0 + db 20h ; Space + db 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 + ; доп. поле + db 0 ; NumLock + db "/","*","-","+",0Dh + db 0,0,0,0,0,0,0,0,0,0,0 + ; + ; +T0CDD: db "Ё",1Bh,"1","2","3","4","5","6","7","8","9","0","-","=",8 + db 9,"Й","Ц","У","К","Е","Н","Г","Ш","Щ","З","Х","Ъ",0 + db "Ф","Ы","В","А","П","Р","О","Л","Д","Ж","Э",0Dh,0 + db "Я","Ч","С","М","И","Т","Ь","Б","Ю",".",0 + db '\',0,0 + db 20h ; Space + db 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 + ; доп. поле + db 0 ; NumLock + db "/","*","-","+",0Dh + db 0,0,0,0,0,0,0,0,0,0,0 + ; + ; +T0D37: db "ё",1Bh,"!",'"',"#","$",":",",",".",";","?","%","_","+",8 + db 9,"й","ц","у","к","е","н","г","ш","щ","з","х","ъ",0 + db "ф","ы","в","а","п","р","о","л","д","ж","э",0Dh,0 + db "я","ч","с","м","и","т","ь","б","ю",",",0 + db "|",0,0 + db 20h ; Space + db 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 + ; доп. поле + db 0 + db "/","*","-","+",0Dh + db 0,0,0,0,0,0,0,0,0,0,0 + + + + +;------------------------------------------------- +; Иниц. LPT-портов для клавы +;------------------------------------------------- +init_keyb: + ld a,0 + out (19h),a + ld a,1 + out (19h),a + ld a,0 + out (19h),a + ld a,3 + out (19h),a + ld a,0C1h + out (19h),a + ld a,4 + out (19h),a + ld a,7 + out (19h),a + ld a,5 + out (19h),a + ld a,62h + out (19h),a + ret + + +; Звук. +; вход: hl=задержка внеш. цикла +; de=задержка внутр. цикла +beep: ld a,10h + out (0FEh),a ; порт + ld b,d + ld c,e + dec bc + ld a,b + or c + jr nz,$-3 + ld a,0 + out (0FEh),a ; порт + ld b,d + ld c,e + dec bc + ld a,b + or c + jr nz,$-3 + dec hl + ld a,h + or l + jr nz,beep + ret diff --git a/MOD0/LISTDRV.ASM b/MOD0/LISTDRV.ASM new file mode 100755 index 0000000..1544ffe --- /dev/null +++ b/MOD0/LISTDRV.ASM @@ -0,0 +1,207 @@ +;------------------------------------------------- +; Иниц. список типов дисков системы +; (послед. читает BPB каждого диска) +;------------------------------------------------- +init_list_types_drives: + ld a,(disk) ; диск акт. панели + ld c,1 ; уст. диск + rst 10h + jr nc,init_list_types_drv1 + ; исп. номер boot-диска + ld bc,0009h + rst 10h + ld (disk),a + ; узнать номер посл. диска в системе + ld c,1 ; уст. диск + rst 10h +init_list_types_drv1: + ld (lastdrive),a ; послед. диск в системе (0..25) + cp 1+1 + jr c,init_list_types_done ; только A,B диски + dec a + ld b,a + ld c,2 ; начать с "C:" + ld hl,scan_code_letters+5 ; таблица дисков с "C:" +make_dlist_loop: + push bc + push hl + ; прочитать BPB диска + push bc + ld a,c ; номер диска + ld c,1 ; open device + rst 18h + pop bc + jr c,make_dlist_err + push bc + ld a,c + ld de,work_buffer ; буфер + ld c,4 ; get BPB + rst 18h + pop bc + jr c,make_dlist_err + ld a,c ; номер диска + ld c,2 ; close device + rst 18h + pop hl + pop bc + ld a,(work_buffer+21) ; байт формата носителя + ld (hl),a + inc hl + inc hl ; след. ячейка типа диска + inc c ; ++номер диска + djnz make_dlist_loop +init_list_types_done: + ; тест на доступность диска у пасс. панели + ld hl,disk1 + ld a,(lastdrive) + dec a + cp (hl) + ret nc + ld (hl),a + ret + ; +make_dlist_err: + pop hl + pop bc + jr init_list_types_done + + + + + +;---------------------------------------------------------------------- +; Структура списка меню выбора дисков +; <номер пункта>, <имя пункта,0>, <скен-код буквы>, <номер контекста> +;---------------------------------------------------------------------- +; db 0,"&A: removable",0 +; db 1Dh ; скен-код +; db CTnodef ; контекст (не исп.) +; ; +; db 1,"&B: removable",0 +; db 2Eh +; db CTnodef +; ; +; db 2,"&C: fixed",0 +; db 2Ch ; скен-код +; db CTnodef +; ; +; db 3,"&D: CD-ROM",0 +; db 1Fh +; db CTnodef +; ; +; db 4,"&E: RAM-disk",0 +; db 12h +; db CTnodef +; ; +; db -1 ; конец описателя + + +;------------------------------------------------- +; Создать в буфере структуру списка дисков +;------------------------------------------------- +make_struct_drives: + exx + ld hl,scan_code_letters ; список скен-кодов букв + exx + ld a,(lastdrive) + ld b,a + ld c,0 ; A=0 + ld hl,work_buffer +make_drives_loop: + ld (hl),c ; номер диска (команды) + inc hl + ld (hl),"&" + inc hl + ld a,"A" + add a,c + ld (hl),a + inc hl + ld (hl),":" + inc hl + ld (hl)," " + inc hl + exx + ld a,(hl) ; скен-код + ex af,af' + inc hl + ld a,(hl) ; тип диска + inc hl + exx + ld de,fix_drive ; винт + cp 0F8h + jr z,make_drives_type + ld de,ram_drive ; ram-диск + cp 0FAh + jr z,make_drives_type + ld de,rem_drive ; дискета + cp 0F0h ; 1.44Mb + jr z,make_drives__ + cp 0F9h ; 720kB + jr z,make_drives__ + ld de,cd_drive ; cd-rom + jr make_drives_type +make_drives__: + ld a,c + cp 2 ; меньше "C:" ? + jr c,make_drives_type + ld de,ram_drive ; ram-диск +make_drives_type: + ; скопир. тип диска + ld a,(de) + ld (hl),a + inc hl + inc de + or a + jr nz,$-5 + ex af,af' + ld (hl),a ; скен-код + inc hl + inc hl ; пройти контекст + inc c ; ++номер диска + djnz make_drives_loop + ld (hl),-1 ; конец списка + ; настроить Y полож. меню от числа дисков + ld c,5 ; Y полож. меню + ld a,(lastdrive) ; 0..25 + cp 14+1 + jr c,$+9 + dec c + cp 18+1 + jr c,$+4 + ld c,2 + ld a,c + ld (table_left_drive+1),a + ld (table_right_drive+1),a + ret + + + +; Таблица букв дисков +; <скен-код>, <байт формата диска> +scan_code_letters: + db 1Dh,0F0h ; A + db 2Eh,0F0h ; B + db 2Ch,0F8h ; C + db 1Fh,0F8h ; D + db 12h,0F8h ; E + db 20h,0F8h ; F + db 21h,0F8h ; G + db 22h,0F8h ; H + db 17h,0F8h ; I + db 23h,0F8h ; J + db 24h,0F8h ; K + db 25h,0F8h ; L + db 30h,0F8h ; M + db 2Fh,0F8h ; N + db 18h,0F8h ; O + db 19h,0F8h ; P + db 10h,0F8h ; Q + db 13h,0F8h ; R + db 1Eh,0F8h ; S + db 14h,0F8h ; T + db 16h,0F8h ; U + db 2Dh,0F8h ; V + db 11h,0F8h ; W + db 2Bh,0F8h ; X + db 15h,0F8h ; Y + db 2Ah,0F8h ; Z diff --git a/MOD0/MOUSEDRV.ASM b/MOD0/MOUSEDRV.ASM new file mode 100755 index 0000000..7451977 --- /dev/null +++ b/MOD0/MOUSEDRV.ASM @@ -0,0 +1,373 @@ +Cmouse equ 1Bh +Dmouse equ 1Ah + + + +; RST 30h. Mouse Driver (текстовый экран) +; На вход номер функции: +; A=00h Инициализация мыши +; A=01h Вывести мышиный курсор на экран +; A=02h Убрать мышиный курсор с экрана +; A=03h Получить координаты мышки и состояние кнопок +; A=04h Получить координаты мышки и состояние кнопок +; после их отпускания +MouseDrv: + or a ; a=0 + jr z,Init_MS + dec a ; a=1 + jr z,SetMouse + dec a ; a=2 + jp z,ResMouse + dec a ; a=3 + jp z,ExmFire + dec a ; a=4 + jp z,GetFire + ret + + +; Initialization LPT port & Mouse +Init_MS:di + ld a,55h + out (10h),a + ld a,2Dh + out (10h),a + ld a,0 + out (1Bh),a + ld a,1 + out (1Bh),a + ld a,0 + out (1Bh),a + ld a,3 + out (1Bh),a + ld a,41h + out (1Bh),a + ld a,4 + out (1Bh),a + ld a,47h + out (1Bh),a + ld a,5 + out (1Bh),a + ld a,0E0h + out (1Bh),a + ei + xor a + ld (MSbutt),a + ret + + +; Set Mouse & Print Cursor Mouse on Screen +SetMouse: + di + push ix + push hl + push de + push bc + call Refresh + pop bc + pop de + pop hl + pop ix + ld a,1 + ld (MouseFlg),a + ei + ret + + +; Res Mouse & Clear Cursor Mouse from Screen +ResMouse: + ld a,(MouseFlg) + or a + ret z + di + xor a + ld (MouseFlg),a + ld (MSbutt),a + push ix + push hl + push de + push bc + call RestorM + pop bc + pop de + pop hl + pop ix + ei + ret + + +; Examination on Fire +; Input: None +; OutPut: Z-Not Fire +; NZ-Yes Fire: +; HL=Y,X (in Znak) +; A=0-bit Right Button +; A=1-bit Left Button +ExmFire:ld hl,(Tcoords) + ld a,(MSbutt) + and 3 + ret + + +; Get Fire (Wait Not Fire) +; Input: None +; OutPut: Z-Not Fire +; NZ-Yes Fire: +; HL=Y,X (in Znak) +; A=0-bit Right Button +; A=1-bit Left Button +GetFire:ld hl,(Tcoords) + ld a,(MSbutt) + and 3 + ret z + push af + ld a,(MSbutt) + and 3 + jr nz,$-5 + pop af + ret + + +; Refresh Mouse on Screen +Refresh:call GetMousInfo + db 3Eh ; ld a,.. +hidden_mouse: + db true ; true - прятать мышь при работе с клавой + or a + jr z,RefrMs + ld hl,(Xcoord) + srl h + rr l + srl h + rr l + srl l + ld a,(Ycoord) + rra + rra + rra + and 1Fh + ld h,a + ld de,(TempXY) + sbc hl,de + jr nz,RefrMs +KeyPres:ld a,0 + or a + jr z,RefrMs1 + jp RestorM + ; +RefrMs: xor a + ld (KeyPres+1),a +RefrMs1:call RestorM + jp MousWrt + +; Restore Screen from Mouse +RestorM:ld de,(TempXY) + in a,(89h) + ld c,a + in a,(0E2h) + ld b,a + push bc + ld a,5Ch ; 54h видео-страница + out (0E2h),a + ld a,d + add a,a + add a,a + ld l,a + ld h,0C3h + in a,(0C9h) + rrca + and 80h + or 1 + add a,e + out (89h),a + inc l + inc l + ld a,(hl) + ld (hl),a + pop bc + ld a,b + out (0E2h),a + ld a,c + out (89h),a + ret + +; Put Text Mouse Cursor On Screen +MousWrt:ld de,(Xcoord) + srl d + rr e + srl d + rr e + srl e + ld a,(Ycoord) + rra + rra + rra + and 1Fh + ld d,a + ld (TempXY),de + in a,(89h) + ld c,a + in a,(0E2h) + ld b,a + push bc + ld a,5Ch ; 54h видео-страница + out (0E2h),a + ld a,d + add a,a + add a,a + ld l,a + ld h,0C3h + in a,(0C9h) + rrca + and 80h + or 1 + add a,e + out (89h),a + inc l + inc l + ld a,(hl) + xor 77h + ld (hl),a + pop bc + ld a,b + out (0E2h),a + ld a,c + out (89h),a + ret + +; Получить новую информацию о мышке +GetMousInfo: + call Read_MS + ret c + ld de,(Xcoord) + srl d + rr e + srl d + rr e + srl e + ld a,(Ycoord) + rra + rra + rra + and 1Fh + ld d,a + ld (Tcoords),de + ret + +; Input Mouse Data from LPT ports +Read_MS:scf + in a,(Cmouse) + bit 0,a + ret z + in a,(Dmouse) + ld l,a + bit 6,a + ret z +Read_L1:in a,(Cmouse) + rrca + jr nc,Read_L1 + in a,(Dmouse) + ld e,a + bit 6,a + ret nz +Read_L2:in a,(Cmouse) + rrca + jr nc,Read_L2 + in a,(Dmouse) + ld d,a + bit 6,a + ret nz + ld a,e + and 3Fh + ld e,a + ld a,l + and 3 + rrca + rrca + or e + ld c,a ; X addition + ld a,d + and 3Fh + ld d,a + ld a,l + and 0Ch + rrca + rrca + rrca + rrca + or d + ld b,a ; Y addition + ld a,l + and 30h + rrca + rrca + rrca + rrca + ld (MSbutt),a ; Button Pressed +; Corrected Mouse Place + ld hl,(Xcoord) + bit 7,c + ld e,c + jr nz,subX + ld d,0 + add hl,de + ld de,027Fh + ex de,hl + sbc hl,de + add hl,de + jr c,$+3 + ex de,hl + ld (Xcoord),hl + jr NxtCoord + ; +subX: ld d,0FFh + add hl,de + jr c,$+5 + ld hl,0 + ld (Xcoord),hl +NxtCoord: + ld hl,(Ycoord) + bit 7,b + ld a,l + jr nz,subY + add a,b + jr nc,$+4 + ld a,0FFh + ld l,a + ld (Ycoord),hl + and a + ret + ; +subY: add a,b + jr c,$+3 + xor a + ld l,a + ld (Ycoord),hl + and a + ret + + + + +; Флаг мышки +MouseFlg: + db 0 ; 00 - мышки нет + ; 01 - мышка есть +; Координаты мышки в точках +;Coords: +;Xcoord: dw 320 ; координата X (0..639) +;Ycoord: dw 128 ; координата Y (0..255) + +; Временные координаты в знакоместах +TempXY: dw 0000h ; X (0..79), Y (0..31) + +; Состояние кнопок +MSbutt: db 0 ; 0-bit правая кнопка + ; 1-bit левая кнопка +; Координаты мышки в знакоместах +Tcoords: +TcoordX:db 40 ; координата X (0..79) +TcoordY:db 16 ; координата Y (0..31) + +; Буфер для хранения информации из под мышки +MouseBuff: + db 0 diff --git a/MOD0/USERMENU.ASM b/MOD0/USERMENU.ASM new file mode 100755 index 0000000..0b3e9e3 --- /dev/null +++ b/MOD0/USERMENU.ASM @@ -0,0 +1,548 @@ +; Меню Пользователя +; +; +; Если файл "FM.MNU" не найден, то вызов Меню Пользователя будет не дос- +; тупен. При этом никаких предупреждающих сообщений выводиться не будет. +; Если переменная окружения файл-менеджера определена, то mnu-файл читается +; и записывается только в ней. Если переменной окружения нет, mnu-файл чита- +; ется и записывается в текущем пути менеджера. +; +; Строки названий пунктов и командных строк могут начинаться с пробелов или +; табуляций. Пункты и их ком-строки могут разделяться пустыми строками (или со- +; держащими одни пробелы или табуляции). +; Каждой строке пункта должна соответствовать командная строка, выполняемая +; по этому пункту. +; +; Если первый символ в строке "-", то строка считается разделителем пунктов +; меню и последующие символы строки игнорируются. +; Если строка начинается с символа ";", то данная строка воспринимается как +; комментарий и также пропускается. +; +; В именах пунктов можно задавать hot-символы вызова этих пунктов. В качест- +; ве hot-символов можно использовать алфавитно-цифровые символы основного поля +; клавиатуры. При определении hot-символов латинских и русских пунктов, может +; возникнуть ситуация, когда hot-символы латинских и русских пунктов совпадут. +; Ничего страшного в этом нет, просто по данному hot-символу будет вызываться +; пункт, стоящий первым от начала меню. +; +; Максимальное число обрабатываемых пунктов равно 26. При этом учитываются +; также разделители пунктов. Максимальная длина имен пунктов и ком-строк равна +; 70 символам. +; +; Будьте внимательны - в конце ком-строк не должно быть лишних пробелов или +; табуляций!. +; +; Типичный пример записи файла "FM.MNU" (отступы для ком-строк сделаны для +; наглядности): +; +; ; это комментарий +; &GoldED +; c:\mail\golded\gedw32.exe -f +; ; еще один комментарий +; Тосс&ить почту +; c:\mail\utils\inar.bat +; &T-Mail +; c:\mail\t-mail\t-mailnt.exe +; П&уржить почту +; c:\mail\utils\purge.bat +; - Это разделитель пунктов +; &FFormat +; c:\nc\fformat.exe +; &Rar 2.50 +; c:\nc\rar.exe +; + + + + + +; Формат описателя пунктов Меню Пользователя +; <имя пункта,0>, <скен-код hot-буквы> +;----------------------------------------------------------- +;list1: db "&GoldED",0 + ;db 21h ; скен-код + ;db "Т&оссить почту",0 + ;db 23h + ;db "&T-Mail",0 + ;db 14h + ;db "П&уржить почту",0 + ;db 12h + ;db -2 ; разделитель + ;db "&FFormat",0 + ;db 20h + ;db "&Rar 2.50",0 + ;db 13h + ; + ;db -1 ; конец описателя + + + +max_user_len equ 70 ; макс. длина строк (лишнее обрезается) +max_user_puncts equ 26 ; макс. число пунктов (лишние игнорируются) + + +;------------------------------------------------- +; Прочитать MNU-файл и подготовить описатель +; Меню Пользователя. +; +; макс. 26 пунктов (26*2 строк) +; макс. 70 символов в пункте/ком-строке +;------------------------------------------------- +make_user_menu: + in a,(SLOT3) + push af + ;ld a,(page_dial_screen) ; в качестве врем. буфера + ld a,(page_sys_screen) ; в качестве врем. буфера + out (SLOT3),a + call make_user_menu__ ; чтение файла Меню Пользователя + pop af + out (SLOT3),a + ret + + +make_user_menu__: + call read_mnu_file ; чтение mnu-файла + ld a,(enable_mnu_file) ; флаг наличия mnu-файла + or a + ret z + ld de,array_read ; начало mnu-файла + ld iy,array_user1 ; массив указателей на ком-строки + ld hl,array_user2 ; массив пунктов меню + ld ix,array_user3 ; массив ком-строк + ld b,0 ; счетчик числа пунктов +make_user_newline: + xor a + ld c,a ; сбр. счетчик длины пункта + dec a + ld (make_user_hot+1),a ; сбр. скен-код буквы +make_user_skip: + ; пройти пробелы в начале строки + ld a,(de) + inc de + cp " " + jr z,make_user_skip + cp 9 ; Tab + jr z,make_user_skip + or a + jr nz,$+10 +make_user_done: + ld (hl),-1 ; конец описателя + ret +make_user_done1: + xor a + ld (hl),a ; конец пункта в описатель + inc hl + jr make_user_done + ; + cp 0Dh ; пустая строка + jr nz,$+5 + inc de ; пройти 0Ah + jr make_user_newline + ; + cp ";" ; комментарий + jr z,make_user_to_end ; пройти до конца строки + cp "-" ; разделитель + jr nz,make_user_loc1 + ld (hl),-2 ; разделитель пунктов + inc hl + inc b ; ++число пунктов + ld a,b + cp max_user_puncts ; 26 + jr nc,make_user_done + ; пройти до конца строки +make_user_to_end: + ld a,(de) + inc de + or a ; конец файла + jr z,make_user_done + cp 0Dh ; конец строки + jr nz,make_user_to_end + inc de ; пройти 0Ah + jr make_user_newline ; на новую строку + ; +make_user_loc1: + dec de +make_user_loc2: + ld a,(de) + inc de + cp "&" ; hot-буква + jr nz,make_user_loc3 + ld (hl),a + inc hl + inc c ; ++длина пункта + ld a,(de) + ld (hl),a ; в описатель + inc hl + inc c ; ++длина пункта + push bc + call get_key_scancode ; узнать скен-код hot-буквы + ld a,c + pop bc + ld (make_user_hot+1),a ; скен-код буквы + inc de + jr make_user_loc2 +make_user_loc3: + or a ; конец файла + jr z,make_user_done1 + cp 0Dh ; конец строки + jr z,make_user_loc4 + ld (hl),a ; в описатель + inc hl + inc c ; ++длина пункта + ld a,c + cp max_user_len ; 70 + jr c,make_user_loc2 + ; пройти до конца строки + ld a,(de) + inc de + or a ; конец файла + jr z,make_user_done1 + cp 0Dh ; конец строки + jr z,make_user_loc4 + jr $-9 +make_user_loc4: + ld (hl),0 ; конец пункта в описатель + inc hl +make_user_hot: + ld (hl),-1 ; скен-код в описатель + inc hl + inc de ; пройти 0Ah + push bc + call copy_user_string ; скопир. ком-строку + pop bc + inc b ; ++число пунктов + ld a,b + cp max_user_puncts ; 26 + jr nc,make_user_done + jp make_user_newline ; на разбор новой строки + + + +;----------------------------------------------------------- +; Скопир. ком-строку с перех. на след. новую строку +; ix=массив ком-строк +; iy=массив указателей на ком-строки +;----------------------------------------------------------- +copy_user_string: + push ix + pop bc + ld (iy+0),c ; сохр. адрес строки + inc iy + ld (iy+0),b + inc iy + ld c,0 ; счетчик длины строки +copy_usr_loop: + ; пройти вед. пробелы + ld a,(de) + inc de + cp " " + jr z,copy_usr_loop + cp 9 ; Tab + jr z,copy_usr_loop + cp 0Dh ; пустая строка + jr nz,copy_usr_loop1 + inc de ; пройти 0Ah + jr copy_usr_loop + ; +copy_usr_loop1: + or a ; конец файла + jr z,copy_usr_done1 + cp 0Dh ; конец строки + jr nz,copy_usr_nxt +copy_usr_done: + inc de ; пройти 0Ah + jr $+3 +copy_usr_done1: + dec de + xor a + ld (ix+0),a ; в конец ком-строки + inc ix + ret +copy_usr_nxt: + ld (ix+0),a + inc ix + inc c ; ++длина ком-строки + ld a,c + cp max_user_len ; 70 + jr nc,copy_usr_nxt1 ; пройти до конца строки + ld a,(de) + inc de + jr copy_usr_loop1 + ; +copy_usr_nxt1: + ld a,(de) + inc de + or a ; конец файла + jr z,copy_usr_done1 + cp 0Dh ; конец строки + jr nz,copy_usr_nxt1 + jr copy_usr_done + + + + +;------------------------------------------------- +; Символьные клавиши осн. поля клавиатуры +; вход: a=hot-клавиша +; выход: c=скен-код клавиши +;------------------------------------------------- +get_key_scancode: + ld c,0 ; счетчик скен-кода + cp "ё" + ret z + cp "Ё" + ret z + cp "`" + ret z + cp "~" + ret z + cp "_" + jr z,get_key_scancod1+2 + cp "р" + jr c,get_key_scancod1 + cp "я"+1 + jp nc,get_key_scancod2 + sub 50h +get_key_scancod1: + res 5,a + ld c,2 + cp "1" + ret z + cp "!" + ret z + inc c + cp "2" + ret z + cp "@" + ret z + inc c + cp "3" + ret z + cp "#" + ret z + inc c + cp "4" + ret z + cp "$" + ret z + inc c + cp "5" + ret z + cp "%" + ret z + inc c + cp "6" + ret z + cp "^" + ret z + inc c + cp "7" + ret z + cp "&" + ret z + inc c + cp "8" + ret z + cp "*" + ret z + inc c + cp "9" + ret z + cp "(" + ret z + inc c + cp "0" + ret z + cp ")" + ret z + inc c + cp "-" + ret z + cp "_" + ret z + inc c + cp "=" + ret z + cp "+" + ret z + ld c,10h + cp "Q" + ret z + cp "Й" + ret z + inc c + cp "W" + ret z + cp "Ц" + ret z + inc c + cp "E" + ret z + cp "У" + ret z + inc c + cp "R" + ret z + cp "К" + ret z + inc c + cp "T" + ret z + cp "Е" + ret z + inc c + cp "Y" + ret z + cp "Н" + ret z + inc c + cp "U" + ret z + cp "Г" + ret z + inc c + cp "I" + ret z + cp "Ш" + ret z + inc c + cp "O" + ret z + cp "Щ" + ret z + inc c + cp "P" + ret z + cp "З" + ret z + inc c + cp "[" + ret z + cp "{" + ret z + cp "Х" + ret z + inc c + cp "]" + ret z + cp "}" + ret z + cp "Ъ" + ret z + ld c,1Dh + cp "A" + ret z + cp "Ф" + ret z + inc c + cp "S" + ret z + cp "Ы" + ret z + inc c + cp "D" + ret z + cp "В" + ret z + inc c + cp "F" + ret z + cp "А" + ret z + inc c + cp "G" + ret z + cp "П" + ret z + inc c + cp "H" + ret z + cp "Р" + ret z + inc c + cp "J" + ret z + cp "О" + ret z + inc c + cp "K" + ret z + cp "Л" + ret z + inc c + cp "L" + ret z + cp "Д" + ret z + ld c,27h + cp "'" + ret z + cp "Э" + ret z + ld c,2Ah + cp "Z" + ret z + cp "Я" + ret z + inc c + cp "X" + ret z + cp "Ч" + ret z + inc c + cp "C" + ret z + cp "С" + ret z + inc c + cp "V" + ret z + cp "М" + ret z + inc c + cp "B" + ret z + cp "И" + ret z + inc c + cp "N" + ret z + cp "Т" + ret z + inc c + cp "M" + ret z + cp "Ь" + ret z + inc c + cp "," + ret z + cp "Б" + ret z + cp "<" + ret z + inc c + cp "." + ret z + cp "Ю" + ret z + cp ">" + ret z + inc c + cp "/" + ret z + cp "." + ret z + cp "?" + ret z + ld c,35h + cp '\' ; + ret z + cp "|" + ret z + ld c,38h + cp " " + ret z +get_key_scancod2: + ld c,-1 + ret diff --git a/MOD0/VECTORS.ASM b/MOD0/VECTORS.ASM new file mode 100755 index 0000000..db51353 --- /dev/null +++ b/MOD0/VECTORS.ASM @@ -0,0 +1,104 @@ + ; rst 00h + jp $+3 + db -1 + db -1 + db -1 + db -1 + db -1 + ; RST 08h. Вызов Биоса + push af + ld a,0 ; вкл. ПЗУ Биоса в 0-е окно + out (7Ch),a + pop af + ret + db -1 + ; RST 10h. Вызов ДОС-а + jp int10 ; fm.asm + db -1 + db -1 + db -1 + db -1 + db -1 + ; RST 18h. Вызов векторов девайсов + jp int18 + db -1 + db -1 + db -1 + db -1 + db -1 + ; RST 20h. Драйвер клавы ФМ + jp KeybDrv + db -1 + db -1 + db -1 + db -1 + db -1 + ; RST 28h. Вызов спек-кода + push af + ld a,0 ; сохр. page_spec + out (82h),a + pop af + ret + db -1 + ; RST 30h. Драйвер мышки ФМ + jp MouseDrv + db -1 + db -1 + db -1 + db -1 + db -1 + ; + ; RST 38h. Main Interrupt + jp $+3 + di + push iy + push ix + push hl + push de + push bc + push af + ex af,af' + exx + push hl + push de + push bc + push af + call main_interrupt + pop af + pop bc + pop de + pop hl + exx + ex af,af' + pop af + pop bc + pop de + pop hl + pop ix + pop iy + ei + reti + + + db -1,-1,-1,-1,-1,-1 ; на границу 0064h + +;0064h + retn + db 0 ; 0066h (от немаск. прерывания в IM0) + db 0 + db 0 + jp $-5 + + +main_interrupt: + ld a,(CurILFl) + or a + call nz,PrnILCr ; софтовый курсор + call show_clock ; отображение часов панелей + di + ld a,(MouseFlg) + or a + call nz,Refresh ; опрос драйвера мышки + jp keyb_scan ; опрос драйвера клавы + +;================ Конец блока Векторов рестартов ===================== diff --git a/MOD1/ABORT.Z80 b/MOD1/ABORT.Z80 new file mode 100755 index 0000000..dde7d5b --- /dev/null +++ b/MOD1/ABORT.Z80 @@ -0,0 +1,30 @@ +;╔══ Operation has been interrupted ══╗ +;║ ║ +;║ Do you really want to cancel it? ║ +;║ ║ +;║ Yes No ║ +;╚════════════════════════════════════╝ +; Описатель окна "Прерывание операции" +dial_abort: + dw 0D15h,0626h ; Yo,Xo,lenY,lenX + db "Operation has been interrupted",0 ; титл окна + ; + db TextLine + dw 0203h ; Yo,Xo + db "Do you really want to cancel it?",0 + ; + db Button ; номер объекта + dw 0414h ; Yo,Xo + db " &No ",0 ; имя бутона + db 2Fh ; скен-код hot-клавиши + db cmCancel ; номер команды + db 1 ; контекст + ; + db Button ; номер объекта + dw 040Eh ; Yo,Xo + db " &Yes ",0 ; имя бутона + db 15h ; скен-код hot-клавиши + db cmOkey ; номер команды + db 0 ; контекст + ; + db -1 ; конец описателя diff --git a/MOD1/BUFFERS.ASM b/MOD1/BUFFERS.ASM new file mode 100755 index 0000000..e6b3b77 --- /dev/null +++ b/MOD1/BUFFERS.ASM @@ -0,0 +1,183 @@ +; Рабочие буферы + + + + +; Маска имен левой панели +mask_left_fname: + db "*.*",0,0,0,0,0,0,0,0,0 + db 0 + +; Маска имен правой панели +mask_right_fname: + db "*.*",0,0,0,0,0,0,0,0,0 + db 0 + + + + +; Буферы не разъединять, используются как блок 512 байт (запись ini-файла) +; +; буфер пути левой панели +buff_left: + db '\' + ds 255 +; буфер пути правой панели +buff_right: + db '\' + ds 255 + + + +; тек. системный путь +save_disk: + db 0 +save_path: + ds 256 + + + +;------------------------------------------------- +; Массив указателей на записи левого каталога +;------------------------------------------------- +left_pointers: + ds 512*2 ; макс. 512 записей папки +;------------------------------------------------- +; Массив указателей на записи правого каталога +;------------------------------------------------- +right_pointers: + ds 512*2 + + + + + +; Буфер истории команд ком-строки +history_buff: + ds history_size ; 128 ;256 + + +; "перевалочный" буфер цветов +temp_colors: + ds len_color_array + + + + +; Структура командной строки +ComLineBuff: + db max_len_comline ;+0 254 макс. число ввод. символов + db 0 ;+1 флаг ReadyString + db 0 ;+2 X тек. полож. курсора в пределах строки + db 0 ;+3 X смещ. строки за левый край (в символах) + db 0 ;+4 число введенных символов + ds max_len_comline+1 ;+5 строка ввода + + +; Структура строки ввода "Copy" +input_line_copy: + db max_len_comline ;+0 макс. число ввод. символов + db 0 ;+1 флаг ReadyString + db 0 ;+2 X тек. полож. курсора в пределах строки + db 0 ;+3 X смещ. строки за левый край (в символах) + db 0 ;+4 число введенных символов (Inp.Symb) + ds max_len_comline+1 ;+5 строка ввода + + +; Структура строки ввода "Make directory" +input_line_makedir: + db max_len_comline ;+0 макс. число ввод. символов + db 0 ;+1 флаг ReadyString + db 0 ;+2 X тек. полож. курсора в пределах строки + db 0 ;+3 X смещ. строки за левый край (в символах) + db 0 ;+4 число введенных символов (Inp.Symb) + ds max_len_comline+1 ;+5 строка ввода + + +; Структура строки ввода "Rename/Remove" +input_line_rename: + db max_len_comline ;+0 макс. число ввод. символов + db 0 ;+1 флаг ReadyString + db 0 ;+2 X тек. полож. курсора в пределах строки + db 0 ;+3 X смещ. строки за левый край (в символах) + db 0 ;+4 число введенных символов (Inp.Symb) + ds max_len_comline+1 ;+5 строка ввода + + + +; Структура строки ввода даты +InpDateStr: + db 10 ;+0 макс. число ввод. символов + db 0 ;+1 флаг ReadyString + db 0 ;+2 X тек. полож. курсора в пределах строки + db 0 ;+3 X смещ. строки за левый край (в символах) + db 0 ;+4 число введенных символов (Inp.Symb) + db " ",0 ;+5 строка ввода + +; Структура строки ввода времени +InpTimeStr: + db 8 ;+0 макс. число ввод. символов + db 0 ;+1 флаг ReadyString + db 0 ;+2 X тек. полож. курсора в пределах строки + db 0 ;+3 X смещ. строки за левый край (в символах) + db 0 ;+4 число введенных символов (Inp.Symb) + db " ",0 ;+5 строка ввода + + + + + +;----------------------------------------------------------- +; Массив ячеек CheckBox окна "Interface settings" +;----------------------------------------------------------- +interface_ceil0: + db false ; Highlight files +interface_ceil1: + db false ; Mouse +interface_ceil2: + db true ; Clock in panels +interface_ceil3: + db false ; Select folders +interface_ceil4: + db false ; Show line summary information +interface_ceil5: + db false ; Show sort mode letter +interface_ceil6: + db false ; Ins moves down +interface_ceil7: + db false ; Show system screen +interface_ceil8: + db false ; Enable Home/End in comline + + + +;----------------------------------------------------------- +; Массив ячеек CheckBox окна "Confirmations" +;----------------------------------------------------------- +confirm_ceil0: + db true ; Copy (перезапись) +confirm_ceil1: + db true ; Move (перезапись) +confirm_ceil2: + db true ; Delete +confirm_ceil3: + db true ; Delete non-empty folders +confirm_ceil4: + db true ; Exit + + + +;----------------------------------------------------------- +; Масив ячеек CheckBox окна "Attributes" +;----------------------------------------------------------- +attrib_ceil0: + db false ; Read only +attrib_ceil1: + db false ; Archives +attrib_ceil2: + db false ; Hidden +attrib_ceil3: + db false ; System + ; +attrib_ceil4: + db false ; Process subfolders diff --git a/MOD1/CHDISK.Z80 b/MOD1/CHDISK.Z80 new file mode 100755 index 0000000..6b5a4fe --- /dev/null +++ b/MOD1/CHDISK.Z80 @@ -0,0 +1,27 @@ +; таблица левого меню выбора дисков +table_left_drive: + dw 0504h ; Y/X полож. меню + dw title_menu_drive ; адрес заголовка окна + dw work_buffer ; адрес описателя меню + +; таблица правого меню выбора дисков +table_right_drive: + dw 052Ch ; Y/X полож. меню + dw title_menu_drive ; адрес заголовка окна + dw work_buffer ; адрес описателя меню + + +; Заголовок меню выбора дисков +; <длина строки>, <строка> +title_menu_drive: + db 5,"Drive" + +; типы дисков +rem_drive: + db "removable",0 +fix_drive: + db "fixed",0 +cd_drive: + db "cd-rom",0 +ram_drive: + db "ram-disk",0 diff --git a/MOD1/COLOR.ASM b/MOD1/COLOR.ASM new file mode 100755 index 0000000..28f4d72 --- /dev/null +++ b/MOD1/COLOR.ASM @@ -0,0 +1,55 @@ +;//////////////////////////////////////////////////////////////////////// +; +; Вызов окна настройки цветов (Options->Colors) +; +;//////////////////////////////////////////////////////////////////////// +setup_colors: + ; массив цветов во врем. буфер + ld hl,color_array ; откуда + ld de,tmp_color_list ; куда (врем. буфер) + ld bc,len_color_array ; размер массива + ldir + ; вывод окна + ld hl,dial_colors ; описатель окна + call DialogW + cp evCommand ; событие "команда" + jr nz,set_colors_done + ld a,(hl) ;+1 what + cp cmOkey ; "Set" + jr nz,set_colors_done + ; цвет. настройки в промеж. буфер + ld hl,tmp_color_list ; откуда + ld de,temp_colors ; куда (врем. буфер) + ld bc,len_color_array ; размер массива + ldir +set_colors_done: + ; Применить настройки "Colors" + call test_show_panels ; тест на режим вкл. панелей + ret z + ld hl,what ; поле событий + ld a,(hl) + cp evCommand + ret nz + inc hl + ld a,(hl) + cp cmDefault + jr nz,$+7 + ld hl,default_colors ; массив цветов по-умолчанию + jr $+8 + cp cmOkey + ret nz + ; применить цвет. настройки + ld hl,temp_colors ; откуда + ld de,color_array ; куда + ld bc,len_color_array ; размер массива + ldir + call set_colors ; настройка цветов оболочки + ; обновить цвета панелей +;apply_colors__: ; <- из set_attrib + call change_panel ; сменить панель + call A20FC ; обновить панель + call change_panel + call A20FC + call print_compath ; обновить ком-строку + call print_keybar ; обновить key-бар + jp show_pointer ; обновить указатель diff --git a/MOD1/COLOR.Z80 b/MOD1/COLOR.Z80 new file mode 100755 index 0000000..7b50a03 --- /dev/null +++ b/MOD1/COLOR.Z80 @@ -0,0 +1,187 @@ +;///////////////////////////////////////////////////////////////////// +; +; Описатель окна настройки цветов +; +;///////////////////////////////////////////////////////////////////// +dial_colors: + dw 0309h,153Eh ; Yo,Xo,lenY,lenX + db "Colors",0 + ; + db PResident1 + ; + db ListBox + dw 0219h,0B10h ; Yo,Xo,lenY,lenX + db "Group &items",0 + db 17h ; скен-код hot-буквы + db 1 ; контекст + dw ItemList1 ; адрес списка + ; + db PResident2 + dw tmp_color_list + ; + db TestColor + dw 0F1Ah ; Yo,Xo + dw tmp_color_list + db "Text Text Text Text",0 + ; + db PalleteBox + dw 022Eh,0404h ; Yo,Xo,lenY,lenX + db "&Foreground",0 + db 20h ; скен-код hot-клавиши + db 2 ; контекст + db 0Fh ; маска цвета + dw tmp_color_list ; ячейка тек. цвета + ; + db PalleteBox + dw 0C2Eh,0204h ; Yo,Xo,lenY,lenX + db "&Background",0 + db 2Eh ; скен-код hot-клавиши + db 3 ; контекст + db 0F0h ; маска фона + dw tmp_color_list ; ячейка тек. цвета + ; + db Button ; номер объекта + dw 1315h ; Yo,Xo + db "[ S&et ]",0 ; имя бутона + db 12h ; скен-код hot-клавиши + db cmOkey ; номер команды + db 4 ; контекст + ; + db Button ; номер объекта + dw 131Fh ; Yo,Xo + db "[ Ca&ncel ]",0 ; имя бутона + db 2Fh ; скен-код hot-клавиши + db cmCancel ; номер команды + db 5 ; контекст + ; + db Button ; номер объекта + dw 1004h ; Yo,Xo + db "[ &Default colors ]",0 ; имя бутона + db 1Fh ; скен-код hot-клавиши + db cmDefault ; номер команды + db 6 ; контекст + ; + db ListBox + dw 0202h,0C12h ; Yo,Xo,lenY,lenX + db "Color &groups",0 + db 21h ; скен-код hot-буквы + db 0 ; контекст + dw GroupList ; адрес списка + ; + db -1 ; конец описателя + + + +; Список ListBox-а "Color groups" +GroupList: + db "Panel",0Dh + db "Horizontal menu",0Dh + db "Menu",0Dh + db "Key bar",0Dh + db "Command line",0Dh + db "Dialog",0Dh + db "Viewer",0Dh + db "Editor",0Dh + db "Help",0Dh + db "Miscelions",0Dh + db "Files highlighting",0Dh + db 0 + + + +ItemTab:dw ItemList1, tmp_color_list ; Panel + dw ItemList2, color_list2 ; Horizontal menu + dw ItemList3, color_list3 ; Menu + dw ItemList4, color_list4 ; Key bar + dw ItemList5, color_list5 ; Command line + dw ItemList6, color_list6 ; Dialog + dw ItemList7, color_list7 ; Viewer + dw ItemList8, color_list8 ; Editor + dw ItemList9, color_list9 ; Help + dw ItemList10, color_list10 ; Miscelions + dw ItemList11, color_list11 ; Files highlighting + + +; +ItemList1: + db "Normal cursor",0Dh ;+0 + db "Selected cursor",0Dh ;+1 + db "Normal text",0Dh ;+2 + db "Selected text",0Dh ;+3 + db "Selected title",0Dh ;+4 + db "Column title",0Dh ;+5 + db "Selected info",0Dh ;+6 + db "Highlighted info",0Dh ;+7 + db "Info names",0Dh ;+8 + db 0 + +; +ItemList2: + db "Normal text",0Dh ;+12 + db "Highlighted text",0Dh ;+13 + db "Hot keys",0Dh ;+14 + db 0 +; +ItemList3: + db "Normal text",0Dh ;+15 + db "Highlighted text",0Dh ;+16 + db "Hot keys",0Dh ;+17 + db 0 +; +ItemList4: + db "Key names",0Dh ;+20 + db "Key numbers",0Dh ;+21 + db 0 +; +ItemList5: + db "Normal text",0Dh ;+22 + db 0 +; +ItemList6: + db "Normal text",0Dh ;+24 + db "Hot keys",0Dh ;+25 + db "Selected title",0Dh ;+26 + db "Info message",0Dh ;+27 + db "Warning message",0Dh ;+28 + db "ListBox",0Dh ;+29 + db "LB highlight",0Dh ;+30 + db "LB highlight hd",0Dh ;+31 + db "LB scroll bar",0Dh ;+32 + db "Text input",0Dh ;+33 + db "Selected buttons",0Dh ;+34 + db "Sel.butt.Wrn/Err",0Dh ;+35 + db 0 +; +ItemList7: + db "Normal text",0Dh ;+39 + db "Selected text",0Dh ;+40 + db "Status line",0Dh ;+41 + db "Scrolling arrows",0Dh ;+42 + db 0 +; +ItemList8: + db "Normal text",0Dh ;+43 + db "Selected text",0Dh ;+44 + db "Status line",0Dh ;+45 + db 0 +; +ItemList9: + db "Normal text",0Dh ;+46 + db "Highlighted text",0Dh ;+47 + db "Title",0Dh ;+48 + db "Scrollbar",0Dh ;+49 + db 0 +; +ItemList10: + db "Process line",0Dh ;+50 + db "Clock",0Dh ;+51 + db 0 +; +ItemList11: + db "Folder",0Dh ;+ + db "Execution",0Dh ;+ + db "Archive",0Dh ;+ + db "R/o, system",0Dh ;+ + db "Hidden",0Dh ;+ + db "Spectrum",0Dh ;+ + db 0 diff --git a/MOD1/COMLINE.ASM b/MOD1/COMLINE.ASM new file mode 100755 index 0000000..2087f9b --- /dev/null +++ b/MOD1/COMLINE.ASM @@ -0,0 +1,1225 @@ +; Клавиши управления ком-строки: +; +; Ctrl+Enter - вставить имя файла (папки) или тек. путь панели +; +; Esc, Ctrl+Y - очистить ком-строку. Ctrl+Y используется, +; когда отключена Esc. При нажатиях на Esc, Ctrl+Y +; в пустой ком-строке - выходим в менеджер. +; +; навигация по истории команд: +; +; Ctrl+E - предыдущая строка истории +; Ctrl+X - следующая строка истории +; Ctrl+Del - очистить историю команд +; +; при убранных панелях: +; +; PageUp - в начало истории +; PageDown - в конец истории +; +; + + + + +ComLineWidth: + db 76 ; макс. ширина поля ввода + + + + +;--------------------------------------------------------------------- +; Прорисовка объекта +;--------------------------------------------------------------------- +PutComLine: + ld a,(disk) ; номер диска + add a,"A" + ld hl,(char_disk) ; адрес буквы диска акт. панели + ld (hl),a + call width_path ; путь из path-буфера в буфер пути панели + ; + call print_compath ; вывести путь + новая ширина поля ввода + in a,(SLOT3) + push af + ld a,(page_dial_screen) ; стр. буфера + out (SLOT3),a + ; +YXpos: ld de,1E04h ; Y/X начало ком-строки + ld (CursorPos),de ; Y/X позиция курсора + call GetPutB + ; перекачать данные из буфера строки в экран. буфер + ex de,hl ; hl=адрес в экран. буфере + ld de,ComLineBuff+5 ; строка + ld a,(ComLineWidth) ; ширина поля ввода + ld b,a + ld a,(color_array+22) ; цвет ком-строки + ld c,a + ld a,(de) + inc de + ld (hl),a + inc hl + ld (hl),c ; цвет строки + inc hl + djnz $-6 + pop af + out (SLOT3),a + jr PrnComLn ; вывод строки на экран + + + +;----------------------------------------------------------- +; По значению координат узнать адрес вставки в памяти +; Input: BC - Y/X координаты от начала окна +; Output: DE - адрес вставки +;----------------------------------------------------------- +GetPutB:ld hl,LC000+MaxDialWin + ld d,0 + add hl,de ;DE-shiftX + add hl,de + ex de,hl ;DE-Address + ret + + +;------------------------------------------------- +; Установить фокус на объект "Input Line" +;------------------------------------------------- +ComLineI: + ld de,(CursorPos) ; Y/X позиция курсора + call PILCurs ; вкл. курсор + ei + ret + + + +;----------------------------------------------------------- +; Вывод строки объекта "Command Line" на экран +;----------------------------------------------------------- +PrnComLn: + ld a,(CurILFl) + push af + call ResILCr ; выкл. курсор + ld de,(YXpos+1) ; начало поля ввода + ld c,84h ; уст. курсор + rst 08h + ld hl,ComLineBuff ; структура буфера + push hl + pop iy + ld a,(iy+3) ;+3 смещ. строки за левый край + add a,l + ld l,a + jr nc,$+3 + inc h + inc hl + inc hl + inc hl + inc hl + inc hl + ld a,(ComLineWidth) ; ширина поля + ld e,a + ld c,a + ld b,a + push bc + xor a + ld b,e + ld de,work_buffer ; врем. буфер + push de + ld (de),a + inc de + djnz $-2 + ld a,(iy+0) + sub (iy+3) + cp c + jr nc,$+3 + ld c,a + ld b,0 + ld a,(iy+4) ; число введ. символов + sub c + jr nc,$+4 + add a,c + ld c,a + pop de + push de + ld a,b + or c + jr z,$+4 + ldir + pop hl + pop bc + ld a,b ; длина строки + or a + jr z,prne__ + ld a,(color_array+22) ; цвет ком-строки + ld e,a + ld c,85h ; вывод строки с атрибутами + rst 08h +prne__: ld a,(YXpos+1) ; начало поля ввода + ld e,(iy+2) ;+2 тек. полож. курсора в строке + add a,e + cp 80 + jr c,prne1__ + ld b,79 + sub b + ld d,a ; "наезд" за правый край + ld a,e + sub d + ld (iy+2),a ;+2 новое полож. курсора + ld a,b +prne1__:ld (CursorPos),a ; X полож. курсора на экране + pop af + or a + call nz,PILCurs ; вкл. курсор + ei + ld de,(YXpos+1) ; начало поля ввода + call GetPutB + ld hl,work_buffer ; врем. буфер + ld bc,(ComLineWidth) ; ширина поля + ld b,0 + in a,(SLOT3) + push af + ld a,(page_dial_screen) ; стр. буфера + out (SLOT3),a + ldi + inc de + jp pe,$-3 + pop af + out (SLOT3),a + ret + + + + + + + +step equ 1 ; шаг скроллинга + + +;===================================================================== +; +; Обработчик событий ~Command Line~ +; +;===================================================================== +EvComLine: + call handle_event ; Читаем событие +EvComLine1: + ld hl,EvComLine + push hl + ld iy,ComLineBuff ; структура буфера + ld hl,what ; список событий + ld a,(hl) + inc hl + cp evMouseFr + jr z,EvComMouse + cp evKeyboard + jp z,EvComKeys + cp evCombKey + jp z,EvComComb + ret + + +; Ctrl+Y +com_clear: + pop hl ; восст. стек от "ComLineWex" +; тест на режим отработки +ComEsc: ld a,(ComLineBuff+4) ; число введ. символов + or a + jp nz,ClearComLine ; очистить ком-строку +; выйти в менеджер при пустой ком-строке +ComExit:ld a,evNothing ; событие + jr com_enter__ + +; +ComEnter: + xor a + ld (work_buffer+127),a ;+255 задать пустую строку + ld hl,ComLineBuff+4 ; число введ. символов + ld e,(hl) + cp e + jr z,ComExit ; пустая строка + ld c," " ; пробел + ld d,a + add hl,de + ld a,(hl) + cp c + jr nz,ent1__ ; нет конц. пробелов + ld b,e + ; убрать конц. пробелы ком-строки + ld a,(hl) + cp c + jr nz,$+5 + dec hl + djnz $-5 + inc hl + ld (hl),d ; в конец ком-строки + ld a,b + or a + jr z,ComExit ; были одни пробелы + ld de,ComLineBuff+4 ; число введ. символов + ld (de),a ; новое число (для history_adding) +ent1__: call history_adding ; добавить строку в history + ; скопир. строку во врем. буфер + ld hl,ComLineBuff+5 ; откуда + ld de,work_buffer+127;255 ; куда + call copy_string ; скопир. строку (с нулем) + ld a,evRunComLine ; событие "отработать ком-строку" +com_enter__: + pop hl ; восст. баланс стека + ld hl,what ; поле событий + ld (hl),a ; номер события + call ResILCr ; выкл. курсор + call ClearComLine ; очистить ком-строку + ; уст. историю на посл. пустую строку + ld a,(history_count) ; число строк в истории + ld (history_cur_string),a ; номер тек. строки истории + jp get_fire + + +; Событие - Мышка +EvComMouse: + ld e,(hl) ; X coord + inc hl + ld d,(hl) ; Y coord + ld a,(YXpos+2) ; Y полож. ком-строки + cp d + jr nz,ComExit ; мышка не в ком-строке +EvComMouse1: + ld c,4 ; X начало строки ввода + ld hl,ComLineBuff+1 ; структура буфера + ld a,e + sub c + ret c ; мышка левее строки ввода + ld (hl),0 ;+1 уст. флаг "не стирать строку" + inc hl + cp (hl) ;+2 X тек. полож. курсора в строке + ret z ; мышка в начале строки ввода + ld e,a + inc hl + add a,(hl) ;+3 смещ. строки за левый край + inc hl + cp (hl) ;+4 число введ. символов + ld a,(hl) + dec hl + dec hl + jr z,$+8 + jr c,$+6 + inc hl + sub (hl) ;+3 смещ. строки за левый край + dec hl + ld e,a + ld (hl),e ;+2 X тек. полож. курсора в строке + call PrnComLn ; вывести строку на экран + jp get_fire + +; Событие - обычная клавиша +EvComKeys: + ld a,(hl) ;+1 what + cp 1Bh + jp z,ComEsc ; обработка Esc + ld c,cmOkey ; номер команды + cp 0Dh + jp z,ComEnter + cp 9 ; Tab смена панели + jp z,tab + ; работа в строке редактирования + cp 8 ; "забой" + jr z,$+5 + cp " " + ret c + ; + ld de,ComLineWex + push de + ld hl,ComLineBuff ; структура буфера + ex af,af' ; сохр. символ + res 7,(iy+1) ;+1 флаг ReadyString + ld a,(D0642) ; флаги клавы + bit 1,a ; бит Ins + ld a,1 ; вставка + jr nz,$+3 + dec a ; замена + and 1 + rrca ; вправо (мл.бит -> перенос) + or (iy+1) + ld (iy+1),a ;+1 флаг ReadyString + ex af,af' + cp 8 ; "забой" + jp z,backspace + ex af,af' ; сохр. символ + ld a,(iy+4) ; InputSymb + cp (iy+0) ; Max len + jr nz,ILn___ + ld a,(iy+2) + add a,(iy+3) + cp (iy+0) + ret nc + bit 7,(iy+1) + ret nz +ILn___: ld a,(iy+4) + sub (iy+3) + sub (iy+2) + jr z,no_insrt + dec (iy+4) + bit 7,(iy+1) + jr z,no_insrt + inc (iy+4) + ; ввод в середину текста (вставка) + ld c,a + ld b,0 + ld hl,ComLineBuff ; структура буфера + ld a,(iy+4) ;+4 число введ. символов + add a,l + ld l,a + jr nc,$+3 + inc h + inc hl + inc hl + inc hl + inc hl + inc hl + ld d,h + ld e,l + dec hl + lddr +no_insrt: + ld hl,ComLineBuff ; структура буфера + ld a,(iy+2) ; X тек. полож. курсора в строке + add a,(iy+3) + add a,l + ld l,a + jr nc,$+3 + inc h + inc hl + inc hl + inc hl + inc hl + inc hl + ex af,af' + ld (hl),a ; сохр. символ в строке + inc (iy+4) + inc (iy+2) + ld a,(ComLineWidth) ; ширина поля + cp (iy+2) ; X тек. полож. курсора в пределах строки + jr nz,$+8 + ; курсор за полем + inc (iy+3) ; смещ. строки за левый край + dec (iy+2) ; X тек. полож. курсора в пределах строки + call PrnComLn ; вывести строку на экран + pop de ; восст. баланс стека +ComLineWex: + ret + + + +; Событие - курс. клавиши или комбинации +EvComComb: + ld b,(hl) ;+1 what + inc hl + ld a,(hl) ;+2 what + cp 44h ; F10 + jp z,ComExit + ld hl,ComLineBuff ; структура буфера + ld de,ComLineWex + push de + cp 54h ; курсор влево + jp z,ComLeft + cp 56h ; курсор вправо + jp z,ComRight + cp 4Fh ; Del, удалить символ в тек. позиции + jp z,ComDel + cp 57h ; Home, в начало строки + jp z,ComHome + cp 51h ; End, в конец строки + jp z,ComEnd + ; + ld d,a + bit 5,b ; бит Ctrl + jr z,com_comb_next + cp 18h+80h ; Ctrl+O, убрать/показать панели + jp z,hidden_panels + cp 15h+80h ; Ctrl+Y, очистить ком-строку + jp z,com_clear + cp 12h+80h ; Ctrl+E пред. строка истории + jp z,history_prev + cp 2Bh+80h ; Ctrl+X след. строка истории + jp z,history_next + cp 4Fh+80h ; Ctrl+Del, очистить историю команд + jp z,alt_clear_history + ; Enter + ld a,(format_mode) ; тек. формат панели + and form_info+form_qview ; info, qview + jr nz,com_comb_ext + ld a,d + cp 28h+80h ; Ctrl+Enter, имя/путь в ком-строку + jp z,copy_name_to_comline + cp 4Eh+80h ; Ctrl+Enter цифр. поля + jp z,copy_name_to_comline + ; + cp 1Ah+80h ; Ctrl+[ путь левой панели в ком-строку + jp z,copy_left_path_panel_to_comline_alt + cp 1Bh+80h ; Ctrl+] путь правой панели в ком-строку + jp z,copy_right_path_panel_to_comline_alt + ; +com_comb_next: + call test_show_panels ; тест на режим вкл. панелей + ld a,d + jr z,com_comb_next1 + cp 58h ; курсор вверх + jp z,up + cp 52h ; курсор вниз + jp z,down + cp 53h ; PageDown + jp z,page_down + cp 59h ; PageUp + jp z,page_up +com_comb_ext: + pop de + ret +; панели выключены +com_comb_next1: + cp 58h ; курсор вверх, пред. строка истории + jp z,history_prev + cp 52h ; курсор вниз, след. строка истории + jp z,history_next + cp 59h ; PageUp, в начало истории + jp z,history_begin + cp 53h ; PageDown, в конец истории + jp z,history_last + pop de + ret + + +; Курсор влево на одно место +ComLeft:ld a,(iy+2) + dec a + jp p,ComPrint + ld a,(iy+3) ; смещ. строки за левый край + sub step ; шаг скроллинга + ret c ; курсор в крайнем левом полож. + ld (iy+3),a ; X смещ. строки за левый край (в символах) + ld a,(iy+2) ; X полож. курсора в пределах строки + add a,step-1 ; шаг скроллинга +ComPrint: + ld (iy+2),a + jp PrnComLn ; вывести строку на экран + +; Курсор вправо на одно место +ComRight: + ld a,(iy+2) ; X полож. курсора в пределах строки + add a,(iy+3) ; смещ. строки за левый край + cp (iy+4) ; число введ. символов + ret z + ld a,(ComLineWidth) ; ширина поля + ld b,a + ld a,(iy+2) ; X полож. курсора в пределах строки + inc a + cp b + jr nz,ComPrint + inc (iy+3) ; смещ. строки за левый край + ld a,(iy+2) ; X полож. курсора в пределах строки + sub step-1 ; шаг скроллинга + jr ComPrint + +; Забой - удалить символ левее курсора +backspace: + ld a,(iy+2) ; X тек. полож. курсора в строке + or a + jr nz,backspac1 + ld a,(iy+3) ; смещ. строки за левый край + sub step ; шаг скроллинга + ret c + ld (iy+3),a + inc (iy+2) ;+2 тек. полож. курсора в строке +backspac1: + ld hl,ComLineBuff ; структура буфера + LD A,(IY+2) ;+2 X тек. полож. курсора в строке + ADD A,(IY+3) ;+3 смещ. строки за левый край + ADD A,L + LD L,A + JR NC,$+3 + INC H + INC HL + INC HL + INC HL + INC HL + INC HL + LD D,H + LD E,L + DEC DE + ld a,(iy+4) ;+4 число введ. символов + sub (iy+3) ; смещ. строки за левый край + sub (iy+2) ; X полож. курсора в пределах строки + jr z,$+7 ; курсор за концом строки + ld c,a + ld b,0 + ldir ; обновить остаток строки + xor a + ld (de),a ; в конец строки + dec (iy+2) ; X полож. курсора в пределах строки + dec (iy+4) ; число введ. символов + jp PrnComLn ; вывести строку на экран + +; Delete - удалить символ в тек. позиции +ComDel: ld hl,ComLineBuff ; структура буфера + ld a,(iy+2) ; X тек. полож. курсора в строке + inc a + add a,(iy+3) ; смещ. строки за левый край + add a,l + ld l,a + jr nc,$+3 + inc h + inc hl + inc hl + inc hl + inc hl + inc hl + ld d,h + ld e,l + dec de + ld a,(iy+4) ;+4 число введ. символов + sub (iy+3) ; смещ. строки за левый край + sub (iy+2) ; X тек. полож. курсора в строке + ret z ; курсор за концом строки + ld c,a + ld b,0 + ldir ; обновить остаток строки + xor a + ld (de),a ; в конец строки + dec (iy+4) ; число введ. символов + jp PrnComLn ; вывести строку на экран + +; Home - в начало строки +ComHome:ld a,(move_home_end) + or a + jr nz,$+8 + call test_show_panels ; тест на режим вкл. панелей + jp nz,home_list ; в начало списка файлов + ; + ld a,(iy+2) ; X тек. полож. курсора в строке + add a,(iy+3) ; смещ. строки за левый край + ret z + xor a ; X полож. курсора + ld (iy+2),a ; X полож. курсора в пределах строки + ld (iy+3),a ; смещ. строки за левый край + jp ComPrint ; вывести строку на экран + +; End - в конец строки +ComEnd: ld a,(move_home_end) + or a + jr nz,$+8 + call test_show_panels ; тест на режим вкл. панелей + jp nz,end_list ; в конец списка файлов + ; + ld a,(iy+4) ;+4 число введ. символов + sub (iy+3) ;+3 смещ. строки за левый край + cp (iy+2) ;+2 X тек. полож. курсора в строке + ret z + add a,(iy+3) ; смещ. строки за левый край + ld c,a + ld (iy+3),0 ; смещ. строки за левый край + ld a,(ComLineWidth) ; ширина поля + sub c + jr z,ComEndLp + jr nc,ComEndNIL + neg +ComEndLp: + inc (iy+3) ; X смещ. строки за левый край + sub step ; шаг скроллинга + jr nc,ComEndLp +ComEndNIL: + ld a,(iy+4) ; число введ. символов + sub (iy+3) ; смещ. строки за левый край + jp ComPrint ; вывести строку на экран + + + +;------------------------------------------------- +; Очистить буфер ком-строки +;------------------------------------------------- +ClearComLine: + call clear_combuffer + jp PrnComLn ; вывести строку на экран + +clear_combuffer: + ld hl,ComLineBuff ; структура буфера +clear_struct_inline: + xor a + ld b,(hl) ;+0 макс. длина строки + inc hl + ld (hl),a ;+1 сбр. флаг ReadyString + inc hl + ld (hl),a ;+2 X тек. полож. курсора в строке + inc hl + ld (hl),a ;+3 смещ. строки за левый край + inc hl + ld (hl),a ;+4 число введ. символов + inc hl ;+5 буфер редакт. строки + ld (hl),a + djnz $-2 + ret + + + +;--------------------------------------------------------------- +; Вывод пути в ком-строке на экран + новая ширина поля ввода +;--------------------------------------------------------------- +print_compath: + ; очистить старый путь на экране + ld a,(ComLineWidth) ; ширина поля ввода + ld l,a + ld a,80 + sub l + ld l,a ; ширина окна + ld h,1 + ld de,1E00h ; Y/X полож. + ld a,(color_array+22) ; цвет ком-строки + ld b,a + ld c,89h ; очистить окно + rst 08h + ; вывести новый путь + ld de,1E00h ; Y/X полож. ком-строки + ld c,84h ; уст. курсор + rst 08h + ld hl,(__path) ; адрес описателя пути акт. панели + ld a,(hl) ; длина строки + dec a + ld (YXpos+1),a ; X полож. курсора + ld (EvComMouse1+1),a ; начало поля ввода + dec a ; без конц. пробела + ld b,a + ld a,79 ; ширина экрана - 1 + sub b + ld (ComLineWidth),a ; новая ширина поля ввода (48..76) + ld de,5 ; смещ. до строки + add hl,de + ld a,(color_array+22) ; цвет ком-строки + ld e,a + push de + ld c,85h ; вывод строки с атрибутами + rst 08h + pop de + ld a,">" + ld bc,0181h ; символ с атрибутом + rst 08h + jp PrnComLn ; вывести ком-строку на экран + + + + +; Флаг формата вставляемого имени ms-dos/spec +; (заюзать при выполнении командной строки) +format_name: + db 0 + + + + + +;----------------------------------------------------------- +; Вставить путь/имя файла в ком-строку (Ctrl+Enter) +; с установкой фокуса на ком-строку. +;----------------------------------------------------------- +put_name_to_comline: + ld a,(format_mode) ; формат акт. панели + and form_info+form_qview + ret nz + ld (format_name),a ; флаг формата вставляемого имени + call print_keybar ; обновить key-бар в норм. вид + ld de,(YXpos+1) ; начало поля ввода ком-строки + ld (CursorPos),de ; полож. курсора на экране + call copy_name_to_comline__ ; вставить строку +; фокус на ком-строку (от мышки) +enter_to_comline: + call ComLineI ; вкл. курсор + jp EvComLine ; вход в ком-строку + + + +;----------------------------------------------------------- +; Вставить путь/имя файла в ком-строку (Ctrl+Enter) +; без установки фокуса на ком-строку. +;----------------------------------------------------------- +copy_name_to_comline: + call ResILCr ; выкл. курсор + call copy_name_to_comline__ + jp ComLineI ; вкл. курсор + + +copy_name_to_comline__: + ld iy,ComLineBuff ; структура буфера + ld a,(iy+4) ; число введ. символов + cp max_len_comline ; 126 ;254 + ret z ; строка заполнена + ld hl,PrnComLn ; точка выхода (вывести строку) + push hl + ld hl,status_string+4 ; имя файла статусной строки + ld a,(hl) + cp "." ; ".." + jr z,copy_path_to_comline + ; скопировать имя файла + ld b,12 ; макс. длина имени + ld a,(hl) + cp " " + jp z,put_char + inc hl + call put_char + ld a,(iy+4) ; число введ. символов + cp max_len_comline ; 126 ;254 + ret z + djnz $-16 +copy_name_to_comline1__: + ld a," " ; концевой пробел + jp put_char + + +;----------------------------------------------------------- +; Скопировать путь акт. панели в ком-строку +;----------------------------------------------------------- +copy_path_to_comline: + ld hl,(char_disk) ; диск акт. панели + ld de,(__buff) ; путь акт. панели + call copy_path_to_comline1 + jr copy_name_to_comline1__ ; вставить концевой пробел + + + + +;----------------------------------------------------------- +; Вставить путь левой панели в ком-строку (Ctrl+[) +;----------------------------------------------------------- +copy_left_path_panel_to_comline: + ld hl,EvComLine ; вход в ком-строку + push hl +; Вставить путь в ком-строку без установки фокуса +copy_left_path_panel_to_comline_alt: + call ResILCr ; выкл. курсор + ld hl,disk_left ; диск левой панели + ld de,buff_left ; путь левой панели buff_right +copy_path_panel__: + call copy_path_to_comline1 + jp ComLineI ; вкл. курсор + +;----------------------------------------------------------- +; Вставить путь правой панели в ком-строку (Ctrl+]) +;----------------------------------------------------------- +copy_right_path_panel_to_comline: + ld hl,EvComLine ; вход в ком-строку + push hl +; Вставить путь в ком-строку без установки фокуса +copy_right_path_panel_to_comline_alt: + call ResILCr ; выкл. курсор + ld hl,disk_right ; диск правой панели + ld de,buff_right ; путь правой панели + jr copy_path_panel__ + + +; Скопировать путь в ком-строку +; вход: hl=диск панели +; deпуть панели +copy_path_to_comline1: + ld iy,ComLineBuff ; структура буфера + ld a,(iy+4) ; число введ. символов + cp max_len_comline ; 126 ;254 + ret nc ; строка заполнена + ld bc,PrnComLn ; точка выхода (вывести строку) + push bc + push de ; сохр. путь левой/правой панели + ld a,(hl) ; буква диска левой/правой панели + inc hl + call put_char + ld a,":" + call put_char + pop hl ; восст. путь + ld a,(hl) + or a + jr z,$+14 ; конец строки пути + call put_char + ld a,(iy+4) ; число введ. символов + cp max_len_comline ; 126 ;254 + ret z + inc hl + jr $-14 + ; + ld a,'\' + dec hl + cp (hl) ; корень ? + call nz,put_char ; нет, вставить "\" + ret + + + +; Вставить один символ в ком-строку. +; Символ всегда вставляется, в независимости +; от текущего режима "вставка/замена". +; вход: a=символ +put_char: + push hl + ex af,af' ; сохр. символ + res 7,(iy+1) ;+1 флаг ReadyString + ld a,1 ; вставка + rrca ; вправо (мл.бит -> перенос) + or (iy+1) + ld (iy+1),a ;+1 флаг ReadyString + ld a,(iy+4) ; InputSymb + cp (iy+0) ; Max len + jr nz,ILn1__ + ld a,(iy+2) + add a,(iy+3) + cp (iy+0) + ret nc + bit 7,(iy+1) + ret nz +ILn1__: ld a,(iy+4) + sub (iy+3) + sub (iy+2) + jr z,no_insrt1 + dec (iy+4) + bit 7,(iy+1) + jr z,no_insrt1 + inc (iy+4) + ; ввод в середину текста (вставка) + ld c,a + ld b,0 + ld hl,ComLineBuff ; структура буфера + ld a,(iy+4) ;+4 число введ. символов + add a,l + ld l,a + jr nc,$+3 + inc h + inc hl + inc hl + inc hl + inc hl + inc hl + ld d,h + ld e,l + dec hl + lddr +no_insrt1: + ld hl,ComLineBuff ; структура буфера + ld a,(iy+2) ; X тек. полож. курсора в строке + add a,(iy+3) + add a,l + ld l,a + jr nc,$+3 + inc h + inc hl + inc hl + inc hl + inc hl + inc hl + ex af,af' + ld (hl),a ; символ в ком-строку + pop hl + inc (iy+4) ; число введ. символов + inc (iy+2) ; X тек. полож. курсора в строке + ld a,(ComLineWidth) ; ширина поля ввода + cp (iy+2) ; X тек. полож. курсора в пределах строки + ret nz + ; курсор за правым краем поля ввода + inc (iy+3) ; смещ. строки за левый край + dec (iy+2) ; X тек. полож. курсора в пределах строки + ret + + + + +;------------------------------------------------- +; Вставить строку из history-буфера +; вход: de=структура строки: +; +0=длина строки, +1=строка +;------------------------------------------------- +put_from_history: + call clear_combuffer ; очистить строку ввода + ld iy,ComLineBuff ; структура буфера + ld a,(de) ;+0 длина строки + ld b,a + inc de + ld a,(de) + call put_char + djnz $-5 + jp PrnComLn ; вывести строку на экран + + + +; Вызов из самой ком-строки +alt_clear_history: + call ClearComLine + jr $+5 +;------------------------------------------------- +; Очистить историю команд +;------------------------------------------------- +clear_history: + call clear_combuffer ; очистить строку ввода + xor a + ld (history_count),a ; число строк в history + ld (history_cur_string),a ; номер тек. строки history + ld hl,history_buff ; конец посл. строки + ld (history_end),hl + ret + + + + + + + +;/////////////////////////////////////////////////////////////////////////////// +; +; History Код +; +;/////////////////////////////////////////////////////////////////////////////// + +history_count: + db 0 ; число строк в истории + ; +history_cur_string: + db 0 ; номер тек. строки истории + ; +history_end: + dw history_buff ; конец послед. строки истории + + + +;------------------------------------------------- +; В начало истории +;------------------------------------------------- +history_begin: + ld a,(history_count) + or a + ret z ; нет строк + xor a + ld (history_cur_string),a + jr history_copy ; перейти на 1-ю строку + +;------------------------------------------------- +; В конец истории +;------------------------------------------------- +history_last: + ld a,(history_count) + or a + ret z ; нет строк + ld (history_cur_string),a ; уст. послед. пустую строку + jp ClearComLine ; вернуть пустую строку + +;------------------------------------------------- +; Следующая строка +;------------------------------------------------- +history_next: + ld a,(history_count) + or a + ret z ; нет строк + dec a + ld b,a + ld hl,history_cur_string + ld a,(hl) + cp b + jr c,$+7 + inc b + ld (hl),b + jp ClearComLine ; вернуть пустую строку + ; + inc a + ld (hl),a + jr history_copy + +;------------------------------------------------- +; Предыдущая строка +;------------------------------------------------- +history_prev: + ld a,(history_count) + or a + ret z ; нет строк + ld b,a + ld hl,history_cur_string + ld a,(hl) + or a + jr z,history_copy ; уперлись в начало истории + cp b + jr c,$+3 + ld a,b + dec a + ld (hl),a +; перейти на строку по ее индексу +history_copy: + call history_index + jp put_from_history ; строку из history в буфер ком-строки + +; вход: а=индекс строки +; выход: de=строка (ее структура из history-буфера) +history_index: + ld b,0 + ld hl,history_buff ; буфер истории + or a ; индекс строки + jr z,hist_index ; 1-я строка истории + ld c,(hl) ; размер строки + inc c + add hl,bc ; на след. строку + dec a + jr nz,$-4 +hist_index: + ex de,hl + ret + + +;----------------------------------------------------------- +; Добавить новую строку в конец буфера истории. +; Если строка не влезает, удаляются самые старые строки до +; тех пор, пока появится достаточно места для новой строки. +;----------------------------------------------------------- +history_adding: + ld de,ComLineBuff+4 ; структура строки + call history_compare ; сравнить строки + ret z ; уже есть такая строка + ld bc,(history_end) ; адрес конца посл. строки + ld hl,history_buff+history_size ; адрес конца буфера + and a + sbc hl,bc ; hl=размер своб. места + ld a,(de) ; длина новой строки + inc a + ld c,a + xor a + ld b,a + sbc hl,bc ; умещ. в своб. месте буфера истории ? + jr nc,history_add_ok ; да + ; удалить первую (самую старую) строку из буфера + ;push de + ld de,history_buff ; буфер истории + ld a,(de) ; длина 1-й строки + inc a + ld c,a + xor a + ld b,a + ld hl,(history_end) + sbc hl,bc + ld (history_end),hl ; конец посл. строки + ld l,e ; hl=history_buff + ld h,d + add hl,bc ; начало 2-й строки + push hl + ld hl,history_size ; размер буфера + and a + sbc hl,bc + ld c,l ; размер остатка буфера + ld b,h + pop hl ; начало 2-й строки + ldir + ld hl,history_count + dec (hl) ; --число строк в history + ;pop de ; восст. адрес ComLineBuff+4 + jr history_adding + ; +history_add_ok: + ld hl,(history_end) ; адрес конца посл. строки + ex de,hl + ldir + ld (history_end),de ; конец посл. строки + ld hl,history_count + ld a,(hl) + ld (history_cur_string),a ; тек. строка history + inc (hl) ; ++число строк в history + ret + + +; Сравнить строки. Если строки равны, то переместить +; тек. строку в конец истории. +; вход: de=структура строки: +0=длина строки, +1=строка +; выход: Z-есть строка +; NZ-нет строки +history_compare: + ld hl,history_count + ld b,(hl) ; число строк в history + dec b + inc b + jr z,hist_comp_quit ; history-буфер пустой + ex af,af' + xor a ; сбр. индекс сравн. строки + ex af,af' + ld hl,history_buff ; буфер истории +history_comp_loop: + push de + ld (move_cur_str+1),hl ; тек. строка истории + ld c,(hl) ; длина тек. строки history + ld a,(de) ; длина новой строки + inc hl + inc de + cp c + jr z,hist_comp_loop ; строки одинаковой длины + ld a,l + add a,c + ld l,a + ld a,h + adc a,0 + ld h,a + jr hist_comp_next + ; +; сравнить строки +hist_comp_loop: + ld a,(de) + cp (hl) + jr nz,hist_comp_notequal ; строки не равны + inc hl + inc de + dec c + jr nz,hist_comp_loop + ; строки равны + jr move_to_end_history ; найденную строку в конец истории + ; +hist_comp_notequal: + inc hl + dec c + jr nz,$-2 ; до конца строки +hist_comp_next: + pop de + ex af,af' + inc a ; ++индекс сравн. строки + ex af,af' + djnz history_comp_loop +hist_comp_quit: + xor a + dec a ; NZ-флаг + ret + +; переместить тек. строку в конец истории +move_to_end_history: + ld a,(history_count) ; число строк истории + ld c,a + dec c + ex af,af' ; индекс найденной строки + cp c + jr nc,not_move_to_end ; найденная строка уже в конце + ; сохр. строку во врем. буфере +move_cur_str: + ld hl,0 ; тек. строка истории + ld de,work_buffer ; врем. буфер + ld c,(hl) ;+0 длина строки + inc c ; учесть ячейку длины строки + xor a + ld b,a + push bc + push hl + ldir + pop de ; куда (на место старой строки) + pop bc + ; сдвинуть остаток буфера на место сохр. строки + push hl + ld hl,(history_end) ; конец посл. строки истории + and a + sbc hl,de + and a + sbc hl,bc + ld c,l ; величина сдвига + ld b,h + pop hl ; откуда + ldir + ; восст. строку из врем. буфера в конец истории + ld hl,work_buffer ; врем. буфер + ld c,(hl) + inc c + ld b,a + ldir +not_move_to_end: + ld a,(history_count) + dec a + ld (history_cur_string),a ; тек. строка history + xor a ; Z флаг + pop de + ret diff --git a/MOD1/CONFIRM.ASM b/MOD1/CONFIRM.ASM new file mode 100755 index 0000000..0a4ee1b --- /dev/null +++ b/MOD1/CONFIRM.ASM @@ -0,0 +1,54 @@ +;//////////////////////////////////////////////////////////////////////// +; +; Вызов окна настройки подтверждений (Options->Confirmations) +; +;//////////////////////////////////////////////////////////////////////// +set_confirm: + ; настроить массив ячеек CheckBox-а + call prep_confirm_ceils + ; вывод окна + ld hl,win_dial_confirm ; описатель окна + call DialogW + cp evCommand ; событие "команда" + ret nz + ld a,(hl) ;+1 what + cp cmOkey ; "Yes" + ret nz + ; Сохранить настройки + ld hl,confirm_ceil0 ; начало массива ячеек + ld a,(hl) + ld (copy_overwrite),a ; copy + inc hl + ld a,(hl) + ;ld (),a ; move + inc hl + ld a,(hl) + ld (del_confirm),a ; delete + inc hl + ld a,(hl) + ld (flag_del_non_empty),a ; delete non-empty folders + inc hl + ld a,(hl) + ld (confirm_quit),a ; exit + ret + + +; Подготовка массива ячеек CheckBox-а +prep_confirm_ceils: + ld hl,confirm_ceil0 ; начало массива ячеек + ld a,false + ld a,(copy_overwrite) ; copy + ld (hl),a + inc hl + ;ld a,() ; move + ld (hl),a + inc hl + ld a,(del_confirm) ; delete + ld (hl),a + inc hl + ld a,(flag_del_non_empty) ; delete non-empty folders + ld (hl),a + inc hl + ld a,(confirm_quit) ; exit + ld (hl),a + ret diff --git a/MOD1/CONFIRM.Z80 b/MOD1/CONFIRM.Z80 new file mode 100755 index 0000000..068c065 --- /dev/null +++ b/MOD1/CONFIRM.Z80 @@ -0,0 +1,55 @@ +;╔════════ Confirmations ═════════╗ +;║ ║ +;║ [x] Copy ║ +;║ [x] Move ║ +;║ [x] Delete ║ +;║ [x] Delete non-empty folders ║ +;║ [x] Exit ║ +;║ ║ +;║────────────────────────────────║ +;║ [ Ok ] [ Cancel ] ║ +;╚════════════════════════════════╝ +; Описатель окна настройки подтверждений +win_dial_confirm: + dw 0617h,0B22h ; Yo,Xo,lenY,lenX + db "Confirmations",0 ; титл окна + ; + db HLine + dw 0801h ; Yo,Xo + db 32 ; длина линии + db "─" ; символ заполнения + ; + db Button ; номер объекта + dw 0908h ; Yo,Xo + db "[ &Ok ]",0 ; имя бутона + db 18h ; скен-код hot-клавиши + db cmOkey ; номер команды + db 5 ; контекст + ; + db Button ; номер объекта + dw 0910h ; Yo,Xo + db "[ Ca&ncel ]",0 ; имя бутона + db 2Fh ; скен-код hot-клавиши + db cmCancel ; номер команды + db 6 ; контекст + ; + db ClsCheckBox ; номер объекта + dw 0202h,051Ch ; Yo,Xo,lenY,lenX (с "[x] ") + db "&Copy",0 ; имя элемента + db 2Ch ; скен-код hot-буквы + dw confirm_ceil0 ; адрес ячейки + db "&Move",0 ; имя элемента + db 30h ; скен-код hot-буквы + dw confirm_ceil1 ; адрес ячейки + db "&Delete",0 ; имя элемента + db 1Fh ; скен-код hot-буквы + dw confirm_ceil2 ; адрес ячейки + db "Delete non-empty &folders",0 ; имя элемента + db 20h ; скен-код hot-буквы + dw confirm_ceil3 ; адрес ячейки + db "E&xit",0 ; имя элемента + db 2Bh ; скен-код hot-буквы + dw confirm_ceil4 ; адрес ячейки + db 0 ; конец кластера + ; + db -1 ; конец описателя diff --git a/MOD1/COPY.Z80 b/MOD1/COPY.Z80 new file mode 100755 index 0000000..aa8b34b --- /dev/null +++ b/MOD1/COPY.Z80 @@ -0,0 +1,103 @@ +;╔══════════════════════════════════ Copy ══════════════════════════════════╗ +;║ ║ +;║ Copy FILENAME.EXT to: ║ +;║ ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░ ║ +;║──────────────────────────────────────────────────────────────────────────║ +;║ [ Copy ] [ Cancel ] ║ +;╚══════════════════════════════════════════════════════════════════════════╝ +; Описатель начального окна копирования +dial_copy: + dw 0902h,074Ch ; Yo,Xo,lenY,lenX + db "Copy",0 ; титл окна + ; + db TextLine + dw 0202h ; Yo,Xo + db "Copy " +copy_name: + db "FILENAME.EXT"," to:",0 ; имя файла (остаток зап. пробелами) + ; + db HLine + dw 0401h ; Yo,Xo + db 74 ; длина линии + db "─" ; символ заполнения + ; + db Button ; номер объекта + dw 051Bh ; Yo,Xo + db "[ &Copy ]",0 ; имя бутона + db 2Ch ; скен-код hot-клавиши + db cmOkey ; номер команды + db 1 ; контекст + ; + db Button ; номер объекта + dw 0527h ; Yo,Xo + db "[ Ca&ncel ]",0 ; имя бутона + db 2Fh ; скен-код hot-клавиши + db cmCancel ; номер команды + db 2 ; контекст + ; + db InputLine ; характер объекта + dw 0302h ; Yo,Xo + db 72 ; длина строки + db 0 ; контекст + dw input_line_copy ; буфер строки ввода + ; + db -1 ; конец описателя + + + +;╔══════════════════ Copy ══════════════════╗ +;║ ║ +;║ Copying the file ║ +;║ FILENAME.EXT to: ║ +;║ A:\FILENAME.EXT ║ +;║ ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░ ║ +;║────────── Total: 0,000,000,000 ──────────║ +;║ ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░ ║ +;║ ║ +;╚══════════════════════════════════════════╝ +; Описатель окна процесса копирования +dial_copy_total_process: + dw 0912h,0A2Ch ; Yo,Xo,lenY,lenX + db "Copy",0 ; титл окна + ; + db TextLine + dw 0202h ; Yo,Xo + db "Copying the file",0 + ; + db TextLine + dw 0302h ; Yo,Xo +copy_name1: + db "FILENAME.EXT"," to:",0 ; имя файла (остаток зап. пробелами) + ; + db TextLine + dw 0402h ; Yo,Xo +copy_name2: + db 'A:\FILENAME.EXT ',0 ; 34 байта + ; + db HLine + dw 0601h ; Yo,Xo + db 42 ; длина линии + db "─" ; символ заполнения + ; + db TextLine + dw 060Bh ; Yo,Xo + db " Total: " + db "0,000,000,000 ",0 + ; 2-я линейка (общая) + db ProcesLine + dw 0702h ; Y,X полож. + db 40 ; длина линейки + dw max_file_bytes1 ; адрес ячейки с MAX числом + dw curr_bytes1 ; адрес ячейки с тек. числом +subrout_process1: + dw copy_file ; сохр. адрес п/программы процесса + ; 1-я линейка + db ProcesLine + dw 0502h ; Y,X полож. + db 40 ; длина линейки + dw max_file_bytes ; адрес ячейки с MAX числом + dw curr_bytes ; адрес ячейки с тек. числом +subrout_process: + dw copy_file ; сохр. адрес п/программы процесса + ; + db -1 ; конец описателя diff --git a/MOD1/DELETE.Z80 b/MOD1/DELETE.Z80 new file mode 100755 index 0000000..9bc9a37 --- /dev/null +++ b/MOD1/DELETE.Z80 @@ -0,0 +1,57 @@ +;╔══════════ Delete ═════════╗ +;║ ║ +;║ Do you wish to delete ║ +;║ ║ +;║ XXXXXXXXXXXX ║ +;║ ║ +;║ Delete Cancel ║ +;╚═══════════════════════════╝ +dial_delete: + dw 091Ah,081Dh ; Yo,Xo,lenY,lenX + db "Delete",0 ; титл окна + ; + db TextLine + dw 0204h ; Yo,Xo + db "Do you wish to delete",0 + ; + db TextLine + dw 0408h ; Yo,Xo +delete_name: + db "FILENAME.EXT",0 ; имя файла/папки + ; + db Button ; номер объекта + dw 060Fh ; Yo,Xo + db " Ca&ncel ",0 ; имя бутона + db 2Fh ; скен-код hot-клавиши + db cmCancel ; номер команды + db 1 ; контекст + ; + db Button ; номер объекта + dw 0606h ; Yo,Xo + db " &Delete ",0 ; имя бутона + db 1Fh ; скен-код hot-клавиши + db cmOkey ; номер команды + db 2 ; контекст + ; + db -1 ; конец описателя + + + +;╔═════════════ Delete ═════════════╗ +;║ Deleting the file or folder ║ +;║ XXXXXXXXXXXX ║ +;╚══════════════════════════════════╝ +dial_delete_current: + dw 0B16h,0424h ; Yo,Xo,lenY,lenX + db "Delete",0 ; титл окна + ; + db TextLine + dw 0105h ; Yo,Xo + db "Deleting the file or folder",0 + ; + db TextLine + dw 020Ch ; Yo,Xo +delete_name1: + db "FILENAME.EXT",0 ; имя файла/папки + ; + db -1 ; конец описателя diff --git a/MOD1/DIALERR.Z80 b/MOD1/DIALERR.Z80 new file mode 100755 index 0000000..1dbe0aa --- /dev/null +++ b/MOD1/DIALERR.Z80 @@ -0,0 +1,449 @@ +; Описатели окон ошибок операций с файлами/папками + + + + + +;╔═════════════════ Error ═════════════════╗ +;║ ║ +;║ Cannot copy FILENAME.EXT to: ║ +;║ | A:\FILENAME.EXT | ║ +;║ ║ +;║ Retry Skip Skip all Cancel ║ +;╚═════════════════════════════════════════╝ +; Описатель окна "Ошибка копирования" +dial_error_copy: + dw 0A12h,072Bh ; Yo,Xo,lenY,lenX + db "Error",0 ; титл окна + ; + db TextLine + dw 0208h ; Yo,Xo + db "Cannot " +dial_error_op: + db "copy " +copy_name3: + db "FILENAME.EXT"," to:",0 ; имя файла (остаток зап. пробелами) + ; + db TextLine + dw 0305h ; Yo,Xo +copy_name4: + db 'A:\FILENAME.EXT ',0 ; 34 байта + ; + db Button ; номер объекта + dw 050Dh ; Yo,Xo + db " &Skip ",0 ; имя бутона + db 1Eh ; скен-код hot-клавиши + db cmSkip ; номер команды + db 1 ; контекст + ; + db Button ; номер объекта + dw 0513h ; Yo,Xo + db " S&kip all ",0 ; имя бутона + db 24h ; скен-код hot-клавиши + db cmSkipAll ; номер команды + db 2 ; контекст + ; + db Button ; номер объекта + dw 051Dh ; Yo,Xo + db " Ca&ncel ",0 ; имя бутона + db 2Fh ; скен-код hot-клавиши + db cmCancel ; номер команды + db 3 ; контекст + ; + db Button ; номер объекта + dw 0506h ; Yo,Xo + db " &Retry ",0 ; имя бутона + db 13h ; скен-код hot-клавиши + db cmOkey ; номер команды + db 0 ; контекст + ; + db -1 ; конец описателя + + + + +;╔════════════════════ Warning ═════════════════════╗ +;║ ║ +;║ File already exists ║ +;║ | A:\TEMP\BP.EXE | ║ +;║──────────────────────────────────────────────────║ +;║ New 496978 01.10.92 18:00:00 ║ +;║ Existing 27921 21.06.04 11:23:34 ║ +;║──────────────────────────────────────────────────║ +;║ ║ +;║ Overwrite All Skip Skip all Append Cancel ║ +;╚══════════════════════════════════════════════════╝ +; Описатель окна "Файл уже существует" +dial_existing: + dw 090Eh,0B34h ; Yo,Xo,lenY,lenX + db "Warning",0 ; титл окна + ; + db TextLine + dw 0210h ; Yo,Xo + db "File already exists",0 + ; + db TextLine + dw 0308h ; Yo,Xo +exists_name: + db 'A:\TEMP\BP.EXE ',0 ; 34 байта + ; + db TextLine + dw 0502h ; Yo,Xo + db "New " +exists_size: + db " 496978" ; размер файла + db " " +exists_date: + db "01.10.92" ; дата + db " " +exists_time: + db "18:00:00",0 ; время + ; + db TextLine + dw 0602h ; Yo,Xo + db "Existing " +exists_size1: + db " 27921" ; размер файла + db " " +exists_date1: + db "21.06.04" ; дата + db " " +exists_time1: + db "11:23:34",0 ; время + ; + db HLine + dw 0401h ; Yo,Xo + db 50 ; длина линии + db "─" ; символ заполнения + ; + db HLine + dw 0701h ; Yo,Xo + db 50 ; длина линии + db "─" ; символ заполнения + ; + db Button ; номер объекта + dw 090Dh ; Yo,Xo + db " &All ",0 ; имя бутона + db 1Dh ; скен-код hot-клавиши + db cmAll ; номер команды + db 0 ; контекст + ; + db Button ; номер объекта + dw 0912h ; Yo,Xo + db " &Skip ",0 ; имя бутона + db 1Eh ; скен-код hot-клавиши + db cmSkip ; номер команды + db 1 ; контекст + ; + db Button ; номер объекта + dw 0918h ; Yo,Xo + db " S&kip all ",0 ; имя бутона + db 24h ; скен-код hot-клавиши + db cmSkipAll ; номер команды + db 2 ; контекст + ; + db Button ; номер объекта + dw 0922h ; Yo,Xo + db " A&ppend ",0 ; имя бутона + db 19h ; скен-код hot-клавиши + db cmAppend ; номер команды + db 0 ; контекст + ; + db Button ; номер объекта + dw 092Ah ; Yo,Xo + db " Ca&ncel ",0 ; имя бутона + db 2Fh ; скен-код hot-клавиши + db cmCancel ; номер команды + db 3 ; контекст + ; + db Button ; номер объекта + dw 0902h ; Yo,Xo + db " &Overwrite ",0 ; имя бутона + db 18h ; скен-код hot-клавиши + db cmOkey ; номер команды + db 0 ; контекст + ; + db -1 ; конец описателя + + + + +;╔═══════════════ Error ════════════════╗ +;║ ║ +;║ Cannot create the folder ║ +;║ | FILENAME.EXT | ║ +;║ ║ +;║ Retry Cancel ║ +;╚══════════════════════════════════════╝ +; Описатель окна "Ошибка создания папки" +dial_error_make_folder: + dw 0A17h,0728h ; Yo,Xo,lenY,lenX + db "Error",0 ; титл окна + ; + db TextLine + dw 0207h ; Yo,Xo + db "Cannot create the folder",0 + ; + db TextLine + dw 0302h ; Yo,Xo +create_name: + db 'A:\..TVISION\SOURCES\LMDTOOLS\TEMP',0 ; 34 байта + ; + db Button ; номер объекта + dw 0514h ; Yo,Xo + db " Ca&ncel ",0 ; имя бутона + db 2Fh ; скен-код hot-клавиши + db cmCancel ; номер команды + db 1 ; контекст + ; + db Button ; номер объекта + dw 050Ch ; Yo,Xo + db " &Retry ",0 ; имя бутона + db 13h ; скен-код hot-клавиши + db cmOkey ; номер команды + db 0 ; контекст + ; + db -1 ; конец описателя + + + + +;╔═════════════ Delete ══════════════╗ +;║ ║ +;║ Cannot delete the file ║ +;║ FILENAME.EXT ║ +;║ ║ +;║ Retry Skip Skip all Cancel ║ +;╚═══════════════════════════════════╝ +; Описатель окна Ошибки удаления +dial_error_delete: + dw 0A15h,0725h ; Yo,Xo,lenY,lenX + db "Delete",0 ; титл окна + ; + db TextLine + dw 0207h ; Yo,Xo + db "Cannot delete the file",0 + ; + db TextLine + dw 030Ch ; Yo,Xo +delete_name2: + db "FILENAME.EXT",0 + ; + db Button ; номер объекта + dw 050Ah ; Yo,Xo + db " &Skip ",0 ; имя бутона + db 1Eh ; скен-код hot-клавиши + db cmSkip ; номер команды + db 1 ; контекст + ; + db Button ; номер объекта + dw 0510h ; Yo,Xo + db " S&kip all ",0 ; имя бутона + db 24h ; скен-код hot-клавиши + db cmSkipAll ; номер команды + db 2 ; контекст + ; + db Button ; номер объекта + dw 051Ah ; Yo,Xo + db " Ca&ncel ",0 ; имя бутона + db 2Fh ; скен-код hot-клавиши + db cmCancel ; номер команды + db 3 ; контекст + ; + db Button ; номер объекта + dw 0503h ; Yo,Xo + db " &Retry ",0 ; имя бутона + db 13h ; скен-код hot-клавиши + db cmOkey ; номер команды + db 0 ; контекст + ; + db -1 ; конец описателя + + +;╔═══════════════ Warning ═══════════════╗ +;║ ║ +;║ The file is read only ║ +;║ FILENAME.EXT ║ +;║ Do you wish to delete it? ║ +;║ ║ +;║ Delete All Skip Skip all Cancel ║ +;╚═══════════════════════════════════════╝ +; Описатель окна Ошибки удаления +dial_delete_ro: + dw 0A14h,0829h ; Yo,Xo,lenY,lenX + db "Warning",0 ; титл окна + ; + db TextLine + dw 020Ah ; Yo,Xo + db "The file is read only",0 + ; + db TextLine + dw 030Eh ; Yo,Xo +delete_name3: + db "FILENAME.EXT",0 + ; + db TextLine + dw 0408h ; Yo,Xo + db "Do you wish to delete it?",0 + ; + db Button ; номер объекта + dw 060Ah ; Yo,Xo + db " &All ",0 ; имя бутона + db 1Dh ; скен-код hot-клавиши + db cmAll ; номер команды + db 0 ; контекст + ; + db Button ; номер объекта + dw 060Fh ; Yo,Xo + db " &Skip ",0 ; имя бутона + db 1Eh ; скен-код hot-клавиши + db cmSkip ; номер команды + db 1 ; контекст + ; + db Button ; номер объекта + dw 0615h ; Yo,Xo + db " S&kip all ",0 ; имя бутона + db 24h ; скен-код hot-клавиши + db cmSkipAll ; номер команды + db 2 ; контекст + ; + db Button ; номер объекта + dw 061Fh ; Yo,Xo + db " Ca&ncel ",0 ; имя бутона + db 2Fh ; скен-код hot-клавиши + db cmCancel ; номер команды + db 3 ; контекст + ; + db Button ; номер объекта + dw 0602h ; Yo,Xo + db " &Delete ",0 ; имя бутона + db 1Fh ; скен-код hot-клавиши + db cmOkey ; номер команды + db 0 ; контекст + ; + db -1 ; конец описателя + + + +;╔════════════ Delete folder ════════════╗ +;║ ║ +;║ The following folder will be deleted: ║ +;║ | A:\FILENAME.EXT | ║ +;║ ║ +;║ Delete All Skip Cancel ║ +;╚═══════════════════════════════════════╝ +; Описатель окна Предупреждения удаления не пустой папки +;dial_nonempty_delete_folder: +; dw 0A14h,0729h ; Yo,Xo,lenY,lenX +; db "Delete folder",0 ; титл окна +; ; +; db TextLine +; dw 0202h ; Yo,Xo +; db "The following folder will be deleted:",0 +; ; +; db TextLine +; ;dw 0303h ; Yo,Xo +; dw 030Eh +;delete_name4: +; ;db 'A:\FILENAME.EXT ',0 ; 34 байта +; db "FILENAME.EXT",0 +; ; +; db Button ; номер объекта +; dw 050Fh ; Yo,Xo +; db " &All ",0 ; имя бутона +; db 1Dh ; скен-код hot-клавиши +; db cmAll ; номер команды +; db 1 ; контекст +; ; +; db Button ; номер объекта +; dw 0514h ; Yo,Xo +; db " &Skip ",0 ; имя бутона +; db 1Eh ; скен-код hot-клавиши +; db cmSkip ; номер команды +; db 2 ; контекст +; ; +; db Button ; номер объекта +; dw 051Ah ; Yo,Xo +; db " Ca&ncel ",0 ; имя бутона +; db 2Fh ; скен-код hot-клавиши +; db cmCancel ; номер команды +; db 3 ; контекст +; ; +; db Button ; номер объекта +; dw 0507h ; Yo,Xo +; db " &Delete ",0 ; имя бутона +; db 1Fh ; скен-код hot-клавиши +; db cmOkey ; номер команды +; db 0 ; контекст +; ; +; db -1 ; конец описателя + + +;╔════════════ Delete folder ════════════╗ +;║ ║ +;║ The following folder will be deleted: ║ +;║ FILENAME.EXT ║ +;║ ║ +;║ Delete Cancel ║ +;╚═══════════════════════════════════════╝ +; Описатель окна Предупреждения удаления не пустой папки +dial_nonempty_delete_folder: + dw 0914h,0729h ; Yo,Xo,lenY,lenX + db "Delete folder",0 ; титл окна + ; + db TextLine + dw 0202h ; Yo,Xo + db "The following folder will be deleted:",0 + ; + db TextLine + dw 030Eh ; Yo,Xo +delete_name4: + db "FILENAME.EXT",0 + ; + db Button ; номер объекта + dw 0515h ; Yo,Xo + db " Ca&ncel ",0 ; имя бутона + db 2Fh ; скен-код hot-клавиши + db cmCancel ; номер команды + db 1 ; контекст + ; + db Button ; номер объекта + dw 050Ch ; Yo,Xo + db " &Delete ",0 ; имя бутона + db 1Fh ; скен-код hot-клавиши + db cmOkey ; номер команды + db 0 ; контекст + ; + db -1 ; конец описателя + + + +;╔══════════════ Delete ══════════════╗ +;║ ║ +;║ Cannot delete the file or folder ║ +;║ FILENAME.EXT ║ +;║ ║ +;║ Ok ║ +;╚════════════════════════════════════╝ +; Описатель окна Ошибки удаления +dial_error_delete_tiny: + dw 0915h,0726h ; Yo,Xo,lenY,lenX + db "Delete",0 ; титл окна + ; + db TextLine + dw 0203h ; Yo,Xo + db "Cannot delete the file or folder",0 + ; + db TextLine + dw 030Dh ; Yo,Xo +delete_name5: + db "FILENAME.EXT",0 + ; + db Button ; номер объекта + dw 0510h ; Yo,Xo + db " &Ok ",0 ; имя бутона + db 13h ; скен-код hot-клавиши + db cmOkey ; номер команды + db 0 ; контекст + ; + db -1 ; конец описателя diff --git a/MOD1/HMENU.Z80 b/MOD1/HMENU.Z80 new file mode 100755 index 0000000..b926b31 --- /dev/null +++ b/MOD1/HMENU.Z80 @@ -0,0 +1,128 @@ +; Описатели гориз. Меню и Pull-меню +; + + + + +;--------------------------------------------------------------------------- +; Описатель Горизонтального Меню +; +; <название пункта,0>, <скен-код hot-клавиши>, <адрес описателя верт. меню> +;--------------------------------------------------------------------------- +MenuTab:db "&Left",0,25h+80h + dw PullMenu_Left ; описатель верт. меню "Left" + db "&Files",0,20h+80h + dw PullMenu_Files + db "&Commands",0,2Ch+80h + dw PullMenu_Commands + db "&Options",0,18h+80h + dw PullMenu_Options + db "&Right",0,13h+80h + dw PullMenu_Right + db 0 ; конец описателя + + + +;---------------------------------------------------------------------------- +; Описатели вертикальных Меню +; +; <номер пункта>, <имя пункта,0>, <скен-код hot-клавиши>, <номер контекста> +;---------------------------------------------------------------------------- +PullMenu_Left: + db cmLBrief,"&Brief Ctrl+1",0,2Eh +LBrief: db CTnodef ; контекст "brief" + db cmLMed,"&Medium Ctrl+2",0,30h +LMed: db CTnodef + db cmLFull,"&Full Ctrl+3",0,20h +LFull: db CTdef + db -2 ; разделитель + db cmLInfo,"&Info panel Ctrl+L",0,17h +LInfo: db CTnodef + db cmLQview,"&Qview panel Ctrl+Q",0,10h +LQview: db CTnodef + db -2 + db cmLName,"&Name Ctrl+F3",0,2Fh +LName: db CTdef + db cmLExt,"E&xtension Ctrl+F4",0,2Bh +LExt: db CTnodef + db cmLDate,"&Date Ctrl+F5",0,1Fh +LDate: db CTnodef + db cmLSize,"&Size Ctrl+F6",0,1Eh +LSize: db CTnodef + db cmLUnsort,"&Unsorted Ctrl+F7",0,16h +LUnsort:db CTnodef + db -2 + db cmLFilter,"Fi<er...",0,25h,CTnodef + db cmLChangeDrv,"&Change drive Alt+F1",0,2Ch,CTnodef + db -1 ; конец описателя + ; +PullMenu_Files: + db cmHelp,"&Help F1",0,22h,CTnodef + db cmUsrMenu,"&User menu F2",0,16h,CTnodef + db cmView,"&View F3",0,2Dh,CTnodef + db cmEdit,"&Edit F4",0,12h,CTnodef + db cmCopy,"&Copy F5",0,2Ch,CTnodef + db cmRename,"&Rename or move F6",0,13h,CTnodef + db cmMkFolder,"&Make folder F7",0,30h,CTnodef + db cmDelete,"&Delete F8",0,1Fh,CTnodef + db -2 + db cmAttrib,"File &attributes Ctrl+A",0,1Dh,CTnodef + db -2 + db cmSelGroup,"Select &group Gray +",0,21h,CTnodef + db cmUSelGroup,"U&nselect group Gray -",0,2Fh,CTnodef + db -2 + db cmQuit,"&Quit F10",0,10h,CTnodef + db -1 + ; +PullMenu_Commands: + db cmFind, "&Find file Alt+F7",0,20h,CTnodef + db cmVolume, "&Volume label Ctrl+F8",0,2Dh,CTnodef + db -2 + db cmSwap, "&Swap panels Ctrl+U",0,1Eh,CTnodef + db cmPanelsOn,"&Panels On/Off Ctrl+O",0,19h,CTnodef + db -2 + db cmNullTRD,"&Create TRD-image",0,2Ch,CTnodef + db cmCopyTRD,"TRD-&image -> Disk",0,17h,CTnodef + db cmSaveTRD,"&Disk -> TRD-image",0,1Fh,CTnodef + db -1 + ; +PullMenu_Options: + db cmInterface,"&Interface settings",0,17h,CTnodef + db cmConfirm,"Co&nfirmations",0,2Fh,CTnodef + db -2 + db cmColors,"Co&lors",0,25h,CTnodef + db cmHighlight,"Files &highlighting",0,22h,CTnodef + db -2 + db cmViewSet,"&Viewer settings",0,2Dh,CTnodef + db cmEditSet,"&Editor settings",0,12h,CTnodef + db -2 + db cmSaveSetup,"&Save setup Shift+F9",0,1Eh,CTnodef + db -1 + ; +PullMenu_Right: + db cmRBrief,"&Brief Ctrl+1",0,2Eh +RBrief: db CTnodef ; контекст "brief" + db cmRMed,"&Medium Ctrl+2",0,30h +RMed: db CTnodef + db cmRFull,"&Full Ctrl+3",0,20h +RFull: db CTnodef + db -2 + db cmRInfo,"&Info panel Ctrl+L",0,17h +RInfo: db CTdef + db cmRQview,"&Qview panel Ctrl+Q",0,10h +RQview: db CTnodef + db -2 + db cmRName,"&Name Ctrl+F3",0,2Fh +RName: db CTnodef + db cmRExt, "E&xtension Ctrl+F4",0,2Bh +RExt: db CTdef + db cmRDate,"&Date Ctrl+F5",0,1Fh +RDate: db CTnodef + db cmRSize,"&Size Ctrl+F6",0,1Eh +RSize: db CTnodef + db cmRUnsort,"&Unsorted Ctrl+F7",0,16h +RUnsort:db CTnodef + db -2 + db cmRFilter,"Fi<er...",0,25h,CTnodef + db cmRChangeDrv,"&Change drive Alt+F2",0,2Ch,CTnodef + db -1 diff --git a/MOD1/INFO.Z80 b/MOD1/INFO.Z80 new file mode 100755 index 0000000..c9cab2d --- /dev/null +++ b/MOD1/INFO.Z80 @@ -0,0 +1,208 @@ +;╔══════════ Information ══════════╗ +;║ ║ +;║ Calculating disk space... ║ +;║ ║ +;╚═════════════════════════════════╝ +; Описатель окна +win_info_panel: + dw 0A16h,0523h ; Yo,Xo,lenY,lenX + db "Information",0 ; титл окна + ; + db TextLine + dw 0205h ; Yo,Xo + db "Calculating disk space...",0 + db -1 ; конец описателя + + + + + +;------------------------------------------------- +; титл-описатель info-формата +;------------------------------------------------- +title_info: + db 13 ; длина строки +info_color1__: + db color_pointer ; 3Fh цвет + dw 0D00h ; X/Y полож. + db " Information " + ; + db 30 ; длина строки +info_color2__: + db color_panel ; 1Bh цвет + dw 0502h ; X/Y полож. + db "The File Manager, Version " + db major_version + "0" + db "." + db (minor_version / 10) + "0" + db (minor_version % 10) + "0" + ; + db 40 ; длина строки +info_color4__: + db color_panel ; цвет + dw 0005h ; X/Y полож. + db "╟──────────────────────────────────────╢" + ; + db 8 ; длина строки +info_color23__: + db color_panel ; 1Bh цвет + dw 0206h ; X/Y полож. + db "Board ID" + ; + db 15 ; длина строки +info_color24__: + db color_folder ; цвет + dw 1706h ; X/Y полож. +info_board_id: + db "xx-xx-xxxxxxxxx" + ; + db 12 ; длина строки +info_color25__: + db color_panel ; цвет + dw 0207h ; X/Y полож. + db "BIOS Version" + ; + db 9 ; длина строки +info_color26__: + db color_folder ; цвет + dw 1D07h ; X/Y полож. +info_bios_version: + db "00.00.000" + ; + db 4 ; длина строки +info_color27__: + db color_panel ; цвет + dw 0208h ; X/Y полож. + db "CMOS" + ; + db 3 ; длина строки +info_color28__: + db color_folder ; цвет + dw 2308h ; X/Y полож. +info_cmos_string: + db " No" + ; + db 40 ; длина строки +info_color29__: + db color_panel ; цвет + dw 0009h ; X/Y полож. + db "╟─────────" +info_type_device: + db " Removable disk A: ──────────╢" + ; + db 11 ; длина строки +info_color5__: + db color_panel ; цвет + dw 020Ah ; X/Y полож. + db "Total bytes" + ; + db 13 ; длина строки +info_color6__: + db color_title ; цвет + dw 190Ah ; X/Y полож. +info_total_bytes: + db "0,000,000,000" + ; + db 10 ; длина строки +info_color7__: + db color_panel ; цвет + dw 020Bh ; X/Y полож. + db "Free bytes" + ; + db 13 ; длина строки +info_color8__: + db color_title ; цвет + dw 190Bh ; X/Y полож. +info_free_bytes: + db "0,000,000,000" + ; + db 12 ; длина строки +info_color9__: + db color_panel ; цвет + dw 020Ch ; X/Y полож. + db "Volume label" + ; + db 11 ; длина строки +info_color10__: + db color_title ; цвет + dw 1B0Ch ; X/Y полож. +info_volume: + db " " + ; + db 13 ; длина строки +info_color11__: + db color_panel ; цвет + dw 020Dh ; X/Y полож. + db "Serial number" + ; + db 9 ; длина строки +info_color12__: + db color_title ; цвет + dw 1D0Dh ; X/Y полож. +info_serial: + db "xxxx-xxxx" + ; + db 40 ; длина строки +info_color13__: + db color_panel ; цвет + dw 000Eh ; X/Y полож. + db "╟────────────── Memory ────────────────╢" + ; + db 12 ; длина строки +info_color15__: + db color_panel ; цвет + dw 020Fh ; X/Y полож. + db "Total memory" + ; + db 9 ; длина строки +info_color16__: + db color_title ; цвет + dw 1D0Fh ; X/Y полож. +info_total_memory: + db "0,000,000" + ; + db 11 ; длина строки +info_color17__: + db color_panel ; цвет + dw 0210h ; X/Y полож. + db "Free memory" + ; + db 9 ; длина строки +info_color18__: + db color_title ; цвет + dw 1D10h ; X/Y полож. +info_free_memory: + db "0,000,000" + ; + db 40 ; длина строки +info_color19__: + db color_panel ; цвет + dw 0011h ; X/Y полож. + db "╟──────────────────────────────────────╢" + ; +info_date: + db 17 ; длина строки +info_color3__: + db color_panel ; цвет + dw 0B03h ; X/Y полож. +info_date_string: + db " 4 September 2004" ; тек. дата + ; + db 0 ; конец описателя + + + +; типы лог. дисков +info_hdd: + db "── Fixed disk C: ──" +info_cdrom: + db "── CD-ROM disk D: ─" +info_fdd: + db " Removable disk A: " +info_ram: + db "─── RAM-disk D: ───" + + +cmos_yes: + db "Yes" ; м/с CMOS есть +cmos_no:db " No" ; м/с CMOS нет diff --git a/MOD1/INFO2.Z80 b/MOD1/INFO2.Z80 new file mode 100755 index 0000000..aa935ab --- /dev/null +++ b/MOD1/INFO2.Z80 @@ -0,0 +1,139 @@ +;------------------------------------------------- +; Дополнительный info-описатель спек-формата +;------------------------------------------------- +title_info_trd: + db 40 ; длина строки +info_color33__: + db color_panel ; цвет + dw 0011h ; X/Y полож. + db "╟────── TRD-DOS disk image info ───────╢" + ; + db 10 ; длина строки +info_color34__: + db color_panel ; 1Bh цвет + dw 0212h ; X/Y полож. + db "Image type" + ; + db 3 ; длина строки +info_color35__: + db color_title ; 1Eh цвет + dw 2312h ; X/Y полож. +img_type: + db "TRD" + ; + db 10 ; длина строки +info_color36__: + db color_panel ; 1Bh цвет + dw 0213h ; X/Y полож. + db "Disk title" + ; + db 11 ; длина строки +info_color37__: + db color_title ; 1Eh цвет + dw 1B13h ; X/Y полож. +trd_vol:db "ADVENT#12/2" + ; + db 9 ; длина строки +info_color38__: + db color_panel ; 1Bh цвет + dw 0214h ; X/Y полож. + db "Disk type" + ; + db 5 ; длина строки +info_color39__: + db color_title ; 1Eh цвет + dw 2114h ; X/Y полож. +trd_type: + db "??/??" + ; + db 16 ; длина строки +info_color40__: + db color_panel ; 1Bh цвет + dw 0215h ; X/Y полож. + db "Write protection" + ; + db 7 ; длина строки +info_color41__: + db color_title ; 1Eh цвет + dw 1F15h ; X/Y полож. +trd_protect: + db " absent" ; " absent", "present" + ; + db 40 ; длина строки +info_color42__: + db color_panel ; цвет + dw 0016h ; X/Y полож. + db "╟──────────── Files info ──────────────╢" + ; + db 15 ; длина строки +info_color43__: + db color_panel ; 1Bh цвет + dw 0217h ; X/Y полож. + db "Number of files" + ; + db 3 ; длина строки +info_color44__: + db color_title ; 1Eh цвет + dw 2317h ; X/Y полож. +trd_files: + db " 0" + ; + db 19 ; длина строки +info_color45__: + db color_panel ; 1Bh цвет + dw 0218h ; X/Y полож. + db "Number of del files" + ; + db 3 ; длина строки +info_color46__: + db color_title ; 1Eh цвет + dw 2318h ; X/Y полож. +trd_delfiles: + db " 0" + ; + db 40 ; длина строки +info_color47__: + db color_panel ; цвет + dw 0019h ; X/Y полож. + db "╟────────── Free area info ────────────╢" + ; + db 14 ; длина строки +info_color48__: + db color_panel ; 1Bh цвет + dw 021Ah ; X/Y полож. + db "First free trk" + ; + db 5 ; длина строки +info_color49__: + db color_title ; 1Eh цвет + dw 211Ah ; X/Y полож. +ffree_trk: + db " 0" + ; + db 14 ; длина строки +info_color50__: + db color_panel ; 1Bh цвет + dw 021Bh ; X/Y полож. + db "First free sec" + ; + db 5 ; длина строки +info_color51__: + db color_title ; 1Eh цвет + dw 211Bh ; X/Y полож. +ffree_sec: + db " 0" + ; + db 22 ; длина строки +info_color52__: + db color_panel ; 1Bh цвет + dw 021Ch ; X/Y полож. + db "Number of free sectors" + ; + db 5 ; длина строки +info_color53__: + db color_title ; 1Eh цвет + dw 211Ch ; X/Y полож. +free_sec: + db " 0" + ; + db 0 ; конец описателя diff --git a/MOD1/INTRFACE.ASM b/MOD1/INTRFACE.ASM new file mode 100755 index 0000000..2701534 --- /dev/null +++ b/MOD1/INTRFACE.ASM @@ -0,0 +1,105 @@ +;//////////////////////////////////////////////////////////////////////// +; +; Вызов окна настройки интерфейса (Options->Interface settings) +; +;//////////////////////////////////////////////////////////////////////// +set_interface: + ; настроить массив ячеек CheckBox-а + call prep_interface_ceils + ; вывод окна + ld hl,win_dial_interface ; описатель окна + call DialogW + cp evCommand ; событие "команда" + ret nz + ld a,(hl) ;+1 what + cp cmOkey ; "Yes" + ret nz + ; Применить настройки + call test_show_panels ; тест на режим вкл. панелей + ret z + ; сохранить настройки + call save_interface_settings + ; обновить панели согласно настройкам + call fresh_show_summary_line ; Show line summary information + call change_panel ; сменить панель + call A20FC ; обновить панель + call change_panel + call A20FC + jp show_pointer ; показать указатель + + +; Подготовка массива ячеек CheckBox-а +prep_interface_ceils: + ld a,(hilight_enable) ; раскраска файлов + ld hl,interface_ceil0 ; начало массива ячеек + ld (hl),a + inc hl + ld a,(hidden_mouse) ; прятать мышку при работе с клавой + ld (hl),a + inc hl + ld a,(enable_clock) ; вывод часов в панелях + ld (hl),a + inc hl + ld a,(mark_folders) ; отметка папок + ld (hl),a + inc hl + ld a,(flag_summary_info) ; вывод строки суммарной информации + ld (hl),a + inc hl + ld a,(sort_char_flag) ; вывод буквы режима сортировки + ld (hl),a + inc hl + ld a,(enable_down_mark) ; смещ. курсора вниз при выдел. файлов + ld (hl),a + inc hl + ld a,(flag_esc) ; врем. просмотр сист. экрана + ld (hl),a + inc hl + ld a,(move_home_end) ; отработка Home/End в ком-строке при откр. панелях + ld (hl),a + ret + + +; Сохранить настройки окна "Interface settings" +save_interface_settings: + ld hl,interface_ceil0 ; начало массива ячеек + ld a,(hl) + ld (hilight_enable),a ; раскраска файлов + inc hl + ld a,(hl) + ld (hidden_mouse),a ; прятать мышку при работе с клавой + inc hl + ld a,(hl) + ld (enable_clock),a ; вывод часов в панелях + inc hl + ld a,(hl) + ld (mark_folders),a ; отметка папок + inc hl + ld a,(hl) + ld (flag_summary_info),a ; вывод строки суммарной информации + inc hl + ld a,(hl) + ld (sort_char_flag),a ; вывод буквы режима сортировки + inc hl + ld a,(hl) + ld (enable_down_mark),a ; смещ. курсора вниз при выдел. файлов + inc hl + ld a,(hl) + ld (flag_esc),a ; врем. просмотр сист. экрана + inc hl + ld a,(hl) + ld (move_home_end),a ; отработка Home/End в ком-строке + ret + + + +;------------------------------------------------- +; Настройка вывода строки суммарной инфы +;------------------------------------------------- +fresh_show_summary_line: + call test_show_panels ; тест на режим вкл. панелей + ret z ; выкл. + ld a,(flag_summary_info) ; флаг + or a + ret z ; false + jp get_total_free_space ; узнать своб. место на дисках панелей diff --git a/MOD1/INTRFACE.Z80 b/MOD1/INTRFACE.Z80 new file mode 100755 index 0000000..694e74d --- /dev/null +++ b/MOD1/INTRFACE.Z80 @@ -0,0 +1,72 @@ +;╔═════════ Interface settings ═════════╗ +;║ ║ +;║ [x] Highlight files ║ +;║ [x] Hidden mouse ║ +;║ [x] Clock in panels ║ +;║ [x] Select folders ║ +;║ [x] Show line summary information ║ +;║ [x] Show sort mode letter ║ +;║ [x] Ins moves down ║ +;║ [x] Show system screen ║ +;║ [x] Enable Home/End in comline ║ +;║ ║ +;║──────────────────────────────────────║ +;║ [ Ok ] [ Cancel ] ║ +;╚══════════════════════════════════════╝ +; Описатель окна настройки интерфейса +; 42x17=714*2=1428 (0594h) +win_dial_interface: + dw 0614h,0F28h ; Yo,Xo,lenY,lenX + db "Interface settings",0 ; титл окна + ; + db HLine + dw 0C01h ; Yo,Xo + db 38 ; длина линии + db "─" ; символ заполнения + ; + db Button ; номер объекта + dw 0D0Bh ; Yo,Xo + db "[ &Ok ]",0 ; имя бутона + db 18h ; скен-код hot-клавиши + db cmOkey ; номер команды + db 7 ; контекст + ; + db Button ; номер объекта + dw 0D13h ; Yo,Xo + db "[ Ca&ncel ]",0 ; имя бутона + db 2Fh ; скен-код hot-клавиши + db cmCancel ; номер команды + db 8 ; контекст + ; + db ClsCheckBox ; номер объекта + dw 0202h,0A21h ; Yo,Xo,lenY,lenX (с "[x] ") + db "Hi&ghlight files",0 ; имя элемента + db 21h ; скен-код hot-буквы + dw interface_ceil0 ; адрес ячейки + db "Hidden &mouse",0 ; имя элемента + db 30h ; скен-код hot-буквы + dw interface_ceil1 ; адрес ячейки + db "&Clock in panels",0 ; имя элемента + db 2Ch ; скен-код hot-буквы + dw interface_ceil2 ; адрес ячейки + db "Select &folders",0 ; имя элемента + db 20h ; скен-код hot-буквы + dw interface_ceil3 ; адрес ячейки + db "Show line &summary information",0 ; имя элемента + db 1Eh ; скен-код hot-буквы + dw interface_ceil4 ; адрес ячейки + db "Show sort mode &letter",0 ; имя элемента + db 25h ; скен-код hot-буквы + dw interface_ceil5 ; адрес ячейки + db "&Ins moves down",0 ; имя элемента + db 17h ; скен-код hot-буквы + dw interface_ceil6 ; адрес ячейки + db "Show s&ystem screen",0 ; имя элемента + db 15h ; скен-код hot-буквы + dw interface_ceil7 ; адрес ячейки + db "&Enable Home/End in comline",0 ; имя элемента + db 12h ; скен-код hot-буквы + dw interface_ceil8 ; адрес ячейки + db 0 ; конец кластера + ; + db -1 ; конец описателя diff --git a/MOD1/MKDIR.Z80 b/MOD1/MKDIR.Z80 new file mode 100755 index 0000000..1c7da8d --- /dev/null +++ b/MOD1/MKDIR.Z80 @@ -0,0 +1,42 @@ +; Создание папки (72 символа в строке) +;╔══════════════════════════════ Make folder ═══════════════════════════════╗ +;║ Create the folder ║ +;║ ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░ ║ +;╟──────────────────────────────────────────────────────────────────────────╢ +;║ [ Ok ] [ Cancel ] ║ +;╚══════════════════════════════════════════════════════════════════════════╝ +; Описатель окна создания папки +dial_folder: + dw 0902h,064Ch ; Yo,Xo,lenY,lenX + db "Make folder",0 ; титл окна + ; + db TextLine + dw 0102h ; Yo,Xo + db "Create the folder",0 + ; + db HLine + dw 0301h ; Yo,Xo + db 74 ; длина линии + db "─" ; символ заполнения + ; + db Button ; номер объекта + dw 041Dh ; Yo,Xo + db "[ &Ok ]",0 ; имя бутона + db 18h ; скен-код hot-клавиши + db cmOkey ; номер команды + db 1 ; контекст + ; + db Button ; номер объекта + dw 0425h ; Yo,Xo + db "[ Ca&ncel ]",0 ; имя бутона + db 2Fh ; скен-код hot-клавиши + db cmCancel ; номер команды + db 2 ; контекст + ; + db InputLine ; характер объекта + dw 0202h ; Yo,Xo + db 72 ; длина строки + db 0 ; контекст + dw input_line_makedir ; буфер строки ввода + ; + db -1 ; конец описателя diff --git a/MOD1/PANELS.Z80 b/MOD1/PANELS.Z80 new file mode 100755 index 0000000..38205bf --- /dev/null +++ b/MOD1/PANELS.Z80 @@ -0,0 +1,509 @@ +;------------------------------------------------------------------------- +; +; Описатели форматов панелей +; +;------------------------------------------------------------------------- + + + + + + +;------------------------------------------------- +; Описатель форматов правой панели +;------------------------------------------------- +deskr_right: + dw deskr_full ; описатель full-формата + dw deskr_med ; описатель medium-формата + dw deskr_brief ; описатель brief-формата + dw deskr_info ; описатель info формата + dw deskr_qview ; описатель qview формата + dw deskr_spec ; описатель спек-форматов + +;------------------------------------------------- +; Описатель форматов левой панели +;------------------------------------------------- +deskr_left: + dw deskr_full ; описатель full-формата + dw deskr_med ; описатель medium-формата + dw deskr_brief ; описатель brief-формата + dw deskr_info ; описатель info формата + dw deskr_qview ; описатель qview формата + dw deskr_spec ; описатель спек-форматов + +; полный формат +deskr_full: + dw title_full ; титл панели + dw up_full ; линия "╔═════╤══╤═══╤═╗" + dw footer_full ; линия "╟─────┴──┴───┴─╢" + dw botline ; линия "╚══════════════╝" + db files_per_colon ; 1 колонка в 25 файлов + db 0 +; средний формат +deskr_med: + dw title_medium ; титл панели + dw up_med ; линия "╔══════╤═══════╗" + dw footer_med ; линия "╟──────┴───────╢" + dw botline ; линия "╚══════════════╝" + db files_per_colon*2 ; 2 колонки по 25 файлов + db 0 +; краткий формат +deskr_brief: + dw title_brief ; титл панели + dw up_brief ; линия "╔════╤════╤════╗" + dw footer_brief ; линия "╟────┴────┴────╢" + dw botline ; линия "╚══════════════╝" + db files_per_colon*3 ; 3 колонки по 25 файлов + db 0 +; info формат +deskr_info: + dw title_info ; титл панели + dw up_info ; линия "╔═══════════════╗" + dw footer_info ; линия "║ ║" + dw botline ; линия "╚═══════════════╝" + db files_per_colon ; 1 колонка в 25 файлов + db 0 +; qview формат +deskr_qview: + dw title_qview ; титл панели + dw up_info ; линия "╔═══════════════╗" + dw footer_info ; линия "║ ║" + dw botline ; линия "╚═══════════════╝" + db files_per_colon ; 1 колонка в 25 файлов + db 0 +; спек-формат +deskr_spec: + dw title_spec ; титл панели + dw up_spec ; линия "╔═════╤══╤══╤═╤═╤═╗" + dw footer_spec ; линия "╟─────┴──┴──┴─┴─┴─╢" + dw botline ; линия "╚═════════════════╝" + db files_per_colon ; 1 колонка в 25 файлов + db 0 + + + + +;------------------------------------------------- +; описатель верхней строки панели +;------------------------------------------------- +; полный формат +up_full: + db 40 ; длина строки +up_color1__: + db color_panel ; 1Bh цвет + dw 0000h ; X/Y полож. + db "╔═══════════════╤═══════╤════════╤═════╗" + db 0 + +; средний формат +up_med: + db 40 ; длина строки +up_color2__: + db color_panel ; цвет + dw 0000h ; X/Y полож. + db "╔══════════════════╤═══════════════════╗" + db 0 + +; краткий формат +up_brief: + db 40 ; длина строки +up_color3__: + db color_panel ; цвет + dw 0000h ; X/Y полож. + db "╔════════════╤════════════╤════════════╗" + db 0 + +; info, qview форматы +up_info: + db 40 ; длина строки +up_color31__: + db color_panel ; 3Fh цвет + dw 0000h ; X/Y полож. + db "╔══════════════════════════════════════╗" + db 0 ; конец описателя + +; спек-формат +up_spec: + db 40 ; длина строки +up_color4__: + db color_panel ; цвет + dw 0000h ; X/Y полож. + db "╔══════════════╤═════╤═════╤═══╤═══╤═══╗" + db 0 + + + + +;------------------------------------------------- +; описатель footer-строки панели +;------------------------------------------------- +; полный формат +footer_full: + db 40 ; длина строки +footer_color1__: + db color_panel ; 1Bh цвет + dw 001Bh ; X/Y полож. + db "╟───────────────┴───────┴────────┴─────╢" + db 0 + +; средний формат +footer_med: + db 40 ; длина строки +footer_color2__: + db color_panel ; цвет + dw 001Bh ; X/Y полож. + db "╟──────────────────┴───────────────────╢" + db 0 + +; краткий формат +footer_brief: + db 40 ; длина строки +footer_color3__: + db color_panel ; цвет + dw 001Bh ; X/Y полож. + db "╟────────────┴────────────┴────────────╢" + db 0 + +; info, qview форматы +footer_info: + db 40 ; длина строки +footer_color41__: + db color_panel ; цвет + dw 001Bh ; X/Y полож. +midline4: + db "║ ║" + db 0 + +; спек-формат +footer_spec: + db 40 ; длина строки +footer_color4__: + db color_panel ; цвет + dw 001Bh ; X/Y полож. + db "╟──────────────┴─────┴─────┴───┴───┴───╢" + db 0 + + + + +;------------------------------------------------- +; описатель botline-строки панели +;------------------------------------------------- +botline: + db 40 ; длина строки +botline_color_: + db color_panel ; цвет + dw 001Dh ; X/Y полож. +botline1: + db "╚══════════════════════════════════════╝" + db 0 + + + + + +;----------------------------------------------------------- +; описатель строки отмеченных файлов левой панели +;----------------------------------------------------------- +markline_left: + db 1 ; длина строки +markline_color_: + db color_markline ; 3Eh цвет + dw 021Bh ; X/Y полож. + db " 0,000,000,000 bytes in 00000 files " + + +;----------------------------------------------------------- +; описатель строки отмеченных файлов правой панели +;----------------------------------------------------------- +markline_right: + db 1 ; длина строки +markline_color1_: + db color_markline ; 3Eh цвет + dw 021Bh ; X/Y полож. + db " 0,000,000,000 bytes in 00000 files " + + +mark_string1__: + db " bytes in " ; 10 байт +mark_string2__: + db " files" ; 6 байт + + +folder_string: + db " Folder" +up_string: + db " Up " + + + + +;------------------------------------------------- +; описатель статус. строки панели +;------------------------------------------------- +status_string: + db 38 ; длина строки +status_color__: + db color_panel ; цвет + dw 011Ch ; X/Y полож. + ; "Filenamm.Ext 0005940 21.06.04 18:50" + db " " + db 0 + + + + + +; средняя часть рамки панели +midline1: + db "║ │ │ │ ║" ; full +midline2: + db "║ │ ║" ; medium +midline3: + db "║ │ │ ║" ; brief +midline_spec: + db "║ │ │ │ │ │ ║" ; full-spectrum + + + + + +;------------------------------------------------- +; титл full-формата +;------------------------------------------------- +title_full: + db 4 ; длина строки +full_color1__: + db color_title ; 1Eh цвет + dw 0701h ; X/Y полож. + db "Name" + ; + db 1 ; длина строки +full_color2__: + db color_panel ; 1Bh цвет + dw 1001h ; X/Y полож. + db "│" + ; + db 4 ; длина строки +full_color3__: + db color_title ; цвет + dw 1301h ; X/Y полож. + db "Size" + ; + db 1 ; длина строки +full_color4__: + db color_panel ; цвет + dw 1801h ; X/Y полож. + db "│" + ; + db 4 ; длина строки +full_color5__: + db color_title ; цвет + dw 1B01h ; X/Y полож. + db "Date" + ; + db 1 ; длина строки +full_color6__: + db color_panel ; цвет + dw 2101h ; X/Y полож. + db "│" + ; + db 4 ; длина строки +full_color7__: + db color_title ; цвет + dw 2201h ; X/Y полож. + db "Time" + db 0 ; конец описателя + +;------------------------------------------------- +; титл medium-формата +;------------------------------------------------- +title_medium: + db 4 ; длина строки +med_color1__: + db color_title ; 1Eh цвет + dw 0801h ; X/Y полож. + db "Name" + ; + db 1 ; длина строки +med_color2__: + db color_panel ; 1Bh цвет + dw 1301h ; X/Y полож. + db "│" + ; + db 4 ; длина строки +med_color3__: + db color_title ; цвет + dw 1B01h ; X/Y полож. + db "Name" + db 0 ; конец описателя + +;------------------------------------------------- +; титл brief-формата +;------------------------------------------------- +title_brief: + db 4 ; длина строки +brief_color1__: + db color_title ; 1Eh цвет + dw 0501h ; X/Y полож. + db "Name" + ; + db 1 ; длина строки +brief_color2__: + db color_panel ; 1Bh цвет + dw 0D01h ; X/Y полож. + db "│" + ; + db 4 ; длина строки +brief_color3__: + db color_title ; цвет + dw 1201h ; X/Y полож. + db "Name" + ; + db 1 ; длина строки +brief_color4__: + db color_panel ; 1Bh цвет + dw 1A01h ; X/Y полож. + db "│" + ; + db 4 ; длина строки +brief_color5__: + db color_title ; цвет + dw 1F01h ; X/Y полож. + db "Name" + db 0 ; конец описателя + +;------------------------------------------------- +; титл спек-формата +;------------------------------------------------- +title_spec: + db 4 ; длина строки +spec_color1__: + db color_title ; 1Eh цвет + dw 0601h ; X/Y полож. + db "Name" + ; + db 1 ; длина строки +spec_color2__: + db color_panel ; 1Bh цвет + dw 0F01h ; X/Y полож. + db "│" + ; + db 4 ; длина строки +spec_color3__: + db color_title ; цвет + dw 1101h ; X/Y полож. + db "Size" + ; + db 1 ; длина строки +spec_color4__: + db color_panel ; 1Bh цвет + dw 1501h ; X/Y полож. + db "│" + ; + db 5 ; длина строки +spec_color5__: + db color_title ; цвет + dw 1601h ; X/Y полож. + db "Start" + ; + db 1 ; длина строки +spec_color6__: + db color_panel ; 1Bh цвет + dw 1B01h ; X/Y полож. + db "│" + ; + db 3 ; длина строки +spec_color7__: + db color_title ; цвет + dw 1C01h ; X/Y полож. + db "SSz" + ; + db 1 ; длина строки +spec_color8__: + db color_panel ; 1Bh цвет + dw 1F01h ; X/Y полож. + db "│" + ; + db 3 ; длина строки +spec_color9__: + db color_title ; цвет + dw 2001h ; X/Y полож. + db "Trk" + ; + db 1 ; длина строки +spec_color10__: + db color_panel ; 1Bh цвет + dw 2301h ; X/Y полож. + db "│" + ; + db 3 ; длина строки +spec_color11__: + db color_title ; цвет + dw 2401h ; X/Y полож. + db "Sec" + ; + db 0 ; конец описателя + + + + + +;------------------------------------------------- +; описатель буквы сортировки +;------------------------------------------------- +sort_char: + db 2 ; длина строки +sort_color__: + db color_title ; цвет + dw 0101h ; X/Y полож. +sort_char__: + db "n" ; n/e/d/s/u + db 0 + + + + + +;------------------------------------------------- +; описатель суммарной информации (внизу панели) +;------------------------------------------------- +deskr_summary: + db 38 ; длина строки +summary_color__: + db color_panel ; цвет + dw 011Dh ; X/Y полож. +summary_string: + db " 0,000,000,000 (0000) ═ 0,000,000,000 " + db 0 + + + + + +;------------------------------------------------- +; описатель path-строки левой панели +;------------------------------------------------- +path_left: + db 5 ; длина строки +path_color1__: + db color_pointer ; 30h цвет + dw 0200h ; X/Y полож. строки от начала панели + db " " ; начало строки +disk_left: + db "X:" + ds width_max+2 ; 33+1 буфер пути + + +;------------------------------------------------- +; описатель path-строки правой панели +;------------------------------------------------- +path_right: + db 5 ; длина строки +path_color2__: + db color_pointer ; 30h цвет + dw 0200h ; X/Y полож. строки от начала панели + db " " ; начало строки +disk_right: + db "X:" + ds width_max+2 ; 33+1 буфер пути diff --git a/MOD1/PULLCMND.ASM b/MOD1/PULLCMND.ASM new file mode 100755 index 0000000..a063287 --- /dev/null +++ b/MOD1/PULLCMND.ASM @@ -0,0 +1,239 @@ +;/////////////////////////////////////////////////////////// +; +; Выполнение пунктов pull-меню +; +;/////////////////////////////////////////////////////////// +pull_commands: + ld hl,what ; поле событий + ld a,(hl) + cp evCommand ; событие "команда" ? + ret nz ; нет + inc hl + ld a,(hl) ;+1 номер команды (пункта) + ld c,a ; сохр. номер + add a,a + ld e,a + ld d,0 + ld hl,pull_array ; список обработчиков + add hl,de + ld e,(hl) + inc hl + ld d,(hl) + ex de,hl + ld a,c ; восст. номер команды + jp (hl) ; a=входн. параметр + + +; список обработчиков pull-меню +pull_array: + ; Left + dw left_right ; brief-формат + dw left_right ; medium-формат + dw left_right ; full-формат + dw left_info ; info-формат + dw left_qview ; qview-формат + dw left_right ; sort "Name" + dw left_right ; sort "Ext" + dw left_right ; sort "Date" + dw left_right ; sort "Size" + dw left_right ; "Unsort" + dw pull_empty ;LFilter + dw select_left_drive ; меню выбора дисков + ; Files + dw pull_empty ;Help + dw user_menu ; вызов Меню Пользователя + dw pull_empty ;View + dw pull_empty ;Edit + dw copy ; Copy + dw rename ; Rename + dw make_folder ; Make folder + dw delete ; Delete + dw pull_empty;set_attrib2 ; вывод окна атрибутов файла/папки + dw pull_empty ;SelGroup + dw pull_empty ;USelGroup + dw quit ; выход в ДОС + ; Commands + dw pull_empty ;Find + dw pull_empty ;Volume + dw swap_panels ; обмен панелей + dw hidden_panels ; убрать/показать панели + dw pull_empty ;Create TRD-image + dw pull_empty ;TRD-image -> Disk + dw pull_empty ;Disk -> TRD-image + ; Options + dw set_interface ; окно настройки интерфейса + dw set_confirm ; окно настройки подтверждений + dw setup_colors ; настройка цветов менеджера + dw pull_empty ;Highlight + dw pull_empty ;ViewSet + dw pull_empty ;EditSet + dw write_ini_file ; записать ini-файл + ; Right + dw left_right ; brief-формат + dw left_right ; medium-формат + dw left_right ; full-формат + dw right_info ; info-формат + dw right_qview ; qview-формат + dw left_right ; sort "Name" + dw left_right ; sort "Ext" + dw left_right ; sort "Date" + dw left_right ; sort "Size" + dw left_right ; "Unsort" + dw pull_empty ;RFilter + dw select_right_drive ; меню выбора дисков + +; заглушка +pull_empty: + ret + + + + + +;/////////////////////////////////////////////////////////// +; Пункты меню Left/Right (до "Filter...") +; вход: a=номер pull-пункта +;/////////////////////////////////////////////////////////// +left_right: + ld (punct_left_right),a + ld hl,show_pointer ; точка выхода + push hl + cp cmLUnsort+1 + ld a,(cur_panel) ; 0/#80 левая/правая акт. панель + jr c,punct_left +; Right-пункт меню + rlca + jr c,pars_left_right ; акт. правая +lft_right1: + call change_panel + call pars_left_right + jp change_panel + +; Left-пункт меню +punct_left: + rlca + jr c,lft_right1 ; акт. правая + ; +pars_left_right: + db 3Eh ; ld a,.. +punct_left_right: + db 0 ; номер pull-пункта + ; форматы списка + cp cmLBrief + jp z,set_format_brief + cp cmRBrief + jp z,set_format_brief + cp cmLMed + jp z,set_format_medium + cp cmRMed + jp z,set_format_medium + cp cmLFull + jp z,set_format_full + cp cmRFull + jp z,set_format_full + ; сортировки списка + ld c,"n" ; name + cp cmLName + jr z,punct_sort + cp cmRName + jr z,punct_sort + ld c,"x" ; ext + cp cmLExt + jr z,punct_sort + cp cmRExt + jr z,punct_sort + ld c,"d" ; date + cp cmLDate + jr z,punct_sort + cp cmRDate + jr z,punct_sort + ld c,"s" ; size + cp cmLSize + jr z,punct_sort + cp cmRSize + jr z,punct_sort + ld c,"u" ; unsorted + cp cmLUnsort + jr z,punct_sort + cp cmRUnsort + jr z,punct_sort + ret + + + +;/////////////////////////////////////////////////////////// +; На сортировку списка +;/////////////////////////////////////////////////////////// +punct_sort: + jp sorting_list + + + + +;/////////////////////////////////////////////////////////// +; Вызов info-панели +;/////////////////////////////////////////////////////////// +; Left-пункт +;left_info: +; ld hl,show_pointer +; push hl +; ld a,(cur_panel) ; 0/#80 левая/правая акт. панель +; rlca +; jp c,alt_info_panel ; акт. правая (данные акт. панели -> в пасс. панель) +; jp set_info_actpanel ; данные пасс. панели -> в акт. панель +; +; +; Right-пункт +;right_info: +; ld hl,show_pointer +; push hl +; ld a,(cur_panel) ; 0/#80 левая/правая акт. панель +; rlca +; jp nc,alt_info_panel ; акт. левая (данные акт. панели -> в пасс. панель) +; jp set_info_actpanel ; данные пасс. панели -> в акт. панель +left_info: + ld hl,show_pointer + push hl + ld a,(cur_panel) ; 0/#80 левая/правая акт. панель + rlca + jp c,alt_info_panel ; акт. правая +lft_info1: + call change_panel + call alt_info_panel + jp change_panel + +; Right-пункт +right_info: + ld hl,show_pointer + push hl + ld a,(cur_panel) ; 0/#80 левая/правая акт. панель + rlca + jp nc,alt_info_panel ; акт. левая + jr lft_info1 + + + +;/////////////////////////////////////////////////////////// +; Вызов qview-панели +;/////////////////////////////////////////////////////////// +; Left-пункт +left_qview: + ld hl,show_pointer + push hl + ld a,(cur_panel) ; 0/#80 левая/правая акт. панель + rlca + jp c,alt_qview_panel ; акт. правая +lft_qview1: + call change_panel + call alt_qview_panel + jp change_panel + + +; Right-пункт +right_qview: + ld hl,show_pointer + push hl + ld a,(cur_panel) ; 0/#80 левая/правая акт. панель + rlca + jp nc,alt_qview_panel ; акт. левая + jr lft_qview1 diff --git a/MOD1/QUIT.Z80 b/MOD1/QUIT.Z80 new file mode 100755 index 0000000..5a1949a --- /dev/null +++ b/MOD1/QUIT.Z80 @@ -0,0 +1,30 @@ +;╔══════════ Quit ══════════╗ +;║ ║ +;║ Do you want to quit FM ? ║ +;║ Yes No ║ +;║ ║ +;╚══════════════════════════╝ +; Описатель окна подтверждения выхода из менеджера +win_dial_quit: + dw 0A1Ah,061Ch ; Yo,Xo,lenY,lenX + db "Quit",0 ; титл окна + ; + db TextLine + dw 0202h ; Yo,Xo + db "Do you want to quit FM ?",0 + ; + db Button ; номер объекта + dw 030Eh ; Yo,Xo + db " &No ",0 ; имя бутона + db 2Fh ; скен-код hot-клавиши + db cmCancel ; номер команды + db 1 ; контекст + ; + db Button ; номер объекта + dw 0309h ; Yo,Xo + db " &Yes ",0 ; имя бутона + db 15h ; скен-код hot-клавиши + db cmOkey ; номер команды + db 0 ; контекст + ; + db -1 ; конец описателя diff --git a/MOD1/QVIEW.Z80 b/MOD1/QVIEW.Z80 new file mode 100755 index 0000000..774516a --- /dev/null +++ b/MOD1/QVIEW.Z80 @@ -0,0 +1,90 @@ +;╔══════════ Information ══════════╗ +;║ ║ +;║ Scanning the folder... ║ +;║ ║ +;╚═════════════════════════════════╝ +; Описатель окна +win_scan_folder: + dw 0A16h,0523h ; Yo,Xo,lenY,lenX + db "Information",0 ; титл окна + ; + db TextLine + dw 0207h ; Yo,Xo + db "Scanning the folder...",0 + db -1 ; конец описателя + + + + + +;------------------------------------------------- +; титл-описатель qview-формата для папок +;------------------------------------------------- +qview_folder_panel: + db 6 ; длина строки +qview_color2__: + db color_panel ; 1Bh цвет + dw 0203h ; X/Y полож. + db "Folder" + ; + db 29 ; длина строки +qview_color3__: + db color_folder ; 1Fh цвет + dw 0903h ; X/Y полож. +qview_name_folder: + db " " ; макс. 29 символов + ; + db 9 ; длина строки +qview_color4__: + db color_panel ; цвет + dw 0205h ; X/Y полож. + db "Contains:" + ; + db 7 ; длина строки +qview_color5__: + db color_panel ; цвет + dw 0207h ; X/Y полож. + db "Folders" + ; + db 6 ; длина строки +qview_color6__: + db color_title ; цвет + dw 1707h ; X/Y полож. +qview_total_folders: + db "00,000" + ; + db 5 ; длина строки +qview_color7__: + db color_panel ; цвет + dw 0208h ; X/Y полож. + db "Files" + ; + db 6 ; длина строки +qview_color8__: + db color_title ; цвет + dw 1708h ; X/Y полож. +qview_total_files: + db "00,000" + ; + db 10 ; длина строки +qview_color9__: + db color_panel ; цвет + dw 0209h ; X/Y полож. + db "Files size" + ; + db 13 ; длина строки +qview_color10__: + db color_title ; цвет + dw 1009h ; X/Y полож. +qview_total_bytes: + db "0,000,000,000" + ; +; титл qview-формата +title_qview: + db 12 ; длина строки +qview_color1__: + db color_pointer ; 3Fh цвет + dw 0E00h ; X/Y полож. + db " Quick view " + ; + db 0 ; конец описателя diff --git a/MOD1/RENAME.Z80 b/MOD1/RENAME.Z80 new file mode 100755 index 0000000..33303f6 --- /dev/null +++ b/MOD1/RENAME.Z80 @@ -0,0 +1,69 @@ +;╔═════════════════════════════════ Rename ═════════════════════════════════╗ +;║ ║ +;║ ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░ ║ +;║──────────────────────────────────────────────────────────────────────────║ +;║ [ Ok ] [ Cancel ] ║ +;╚══════════════════════════════════════════════════════════════════════════╝ +; Описатель начального окна копирования +dial_rename: + dw 0902h,064Ch ; Yo,Xo,lenY,lenX + db "Rename",0 ; титл окна + ; + db HLine + dw 0301h ; Yo,Xo + db 74 ; длина линии + db "─" ; символ заполнения + ; + db Button ; номер объекта + dw 041Dh ; Yo,Xo + db "[ &Ok ]",0 ; имя бутона + db 18h ; скен-код hot-клавиши + db cmOkey ; номер команды + db 1 ; контекст + ; + db Button ; номер объекта + dw 0425h ; Yo,Xo + db "[ Ca&ncel ]",0 ; имя бутона + db 2Fh ; скен-код hot-клавиши + db cmCancel ; номер команды + db 2 ; контекст + ; + db InputLine ; характер объекта + dw 0202h ; Yo,Xo + db 72 ; длина строки + db 0 ; контекст + dw input_line_rename ; буфер строки ввода + ; + db -1 ; конец описателя + + + +;╔══════════════ Rename ══════════════╗ +;║ ║ +;║ Cannot rename the file or folder ║ +;║ FILENAME.EXT ║ +;║ ║ +;║ Ok ║ +;╚════════════════════════════════════╝ +; Описатель окна Ошибки удаления +dial_error_rename: + dw 0915h,0726h ; Yo,Xo,lenY,lenX + db "Rename",0 ; титл окна + ; + db TextLine + dw 0203h ; Yo,Xo + db "Cannot rename the file or folder",0 + ; + db TextLine + dw 030Dh ; Yo,Xo +rename_name1: + db "FILENAME.EXT",0 + ; + db Button ; номер объекта + dw 0510h ; Yo,Xo + db " &Ok ",0 ; имя бутона + db 13h ; скен-код hot-клавиши + db cmOkey ; номер команды + db 0 ; контекст + ; + db -1 ; конец описателя diff --git a/MOD1/SELDRV.ASM b/MOD1/SELDRV.ASM new file mode 100755 index 0000000..f294de3 --- /dev/null +++ b/MOD1/SELDRV.ASM @@ -0,0 +1,110 @@ +;///////////////////////////////////////////////// +; +; Применение пункта "Left->Change disk" +; +;///////////////////////////////////////////////// +set_left_drive: + ld hl,what + ld a,(hl) ;+0 + cp evCommand ; событие "команда" + ret nz + call test_show_panels ; тест на режим вкл. панелей + ret z ; выкл. + inc hl ;+1 +set_ldrive_frm: + ld de,format_mode ; формат панели + ld a,(de) + and form_info+form_qview ; info, qview + ret nz +set_ldrive_dsk: + ld de,disk ; ячейка диска акт. панели + ld a,(de) + ld (set_ldrive_altdsk+1),a ; сохр. диск + ld a,(hl) ;+1 номер диска + ld (de),a ; номер диска акт. панели + ; обновление панелей при смене диска + ld a,(cur_panel) ; тек. панель + or a + jr nz,set_ldrive_next + call get_new_flist ; акт. левая + jr set_ldrive_next1 + ; пасс. панель +set_ldrive_next: + call change_panel + call get_new_flist ; акт. правая + push af + call change_panel + pop af +set_ldrive_next1: + ld a,true + ld (enter_done3+1),a ; уст. флаг обновления info-панели + jp nc,enter_done1 ; Ok, тест на qview-формат др.панели (enter.asm) + ; ошибка чтения диска + ; заново вызвать Окно Выбора дисков + ld hl,(set_ldrive_dsk+1) +set_ldrive_altdsk: + ld a,0 + ld (hl),a ; восст. диск панели + jp select_left_drive ; акт. левая панель + + + +;///////////////////////////////////////////////// +; +; Применение пункта "Right->Change disk" +; +;///////////////////////////////////////////////// +set_right_drive: + ld hl,what + ld a,(hl) ;+0 + cp evCommand ; событие "команда" + ret nz + call test_show_panels ; тест на режим вкл. панелей + ret z ; выкл. + inc hl ;+1 +set_rdrive_frm: + ld de,format_mode ; формат панели + ld a,(de) + and form_info+form_qview ; info, qview + ret nz +set_rdrive_dsk: + ld de,disk ; ячейка диска акт. панели + ld a,(de) + ld (set_rdrive_altdsk+1),a ; сохр. диск + ld a,(hl) ;+1 номер диска + ld (de),a ; номер диска акт. панели + ld a,(cur_panel) ; тек. панель + or a + jr z,set_rdrive_next ; вывод пасс. панели + call get_new_flist ; акт. левая + jr set_rdrive_next1 + ; пасс. панель +set_rdrive_next: + call change_panel + call get_new_flist ; акт. правая + push af + call change_panel + pop af +set_rdrive_next1: + ld a,true + ld (enter_done3+1),a ; уст. флаг обновления info-панели + jp nc,enter_done1 ; Ok, тест на qview-формат др.панели (enter.asm) + ; ошибка чтения диска + ; заново вызвать Окно Выбора дисков + ld hl,(set_rdrive_dsk+1) +set_rdrive_altdsk: + ld a,0 + ld (hl),a ; восст. диск панели + jp select_right_drive + + + +;------------------------------------------------- +; Прочитать новый список панели (диск/папка) +;------------------------------------------------- +get_new_flist: + call read_new_folder ; новый список каталога + размер папки + ret c + call dinqview_set_flag ; уст. флаг "отработать dinamqview" + call sorting ; раздельный список указателей + сорт. списка + jp A20FC ; вывод акт. панели diff --git a/MOD1/SETCOLOR.ASM b/MOD1/SETCOLOR.ASM new file mode 100755 index 0000000..77ca437 --- /dev/null +++ b/MOD1/SETCOLOR.ASM @@ -0,0 +1,209 @@ +;----------------------------------------------------------- +; Настройка цветов менеджера +;----------------------------------------------------------- +set_colors: + call set_keybar_colors ; настройка цвета key-бара + call set_qview_colors ; настройка цвета qview-панели + call set_info_colors ; настройка цвета info-панели + call set_info_trd_colors ; настройка цвета info-описателя спек-формата + ; Normal text + ld a,(color_array+2) ; 1Bh + ld (full_color2__),a + ld (full_color4__),a + ld (full_color6__),a + ld (med_color2__),a + ld (brief_color2__),a + ld (brief_color4__),a + ld (spec_color2__),a + ld (spec_color4__),a + ld (spec_color6__),a + ld (spec_color8__),a + ld (spec_color10__),a + ld (botline_color_),a + ld (footer_color1__),a + ld (footer_color2__),a + ld (footer_color3__),a + ld (footer_color4__),a + ld (footer_color41__),a + ld (up_color1__),a + ld (up_color2__),a + ld (up_color3__),a + ld (up_color31__),a + ld (up_color4__),a + ld (status_color__),a + ld (summary_color__),a + ; Column title + ld a,(color_array+5) ; 1Eh + ld (full_color1__),a + ld (full_color3__),a + ld (full_color5__),a + ld (full_color7__),a + ld (med_color1__),a + ld (med_color3__),a + ld (brief_color1__),a + ld (brief_color3__),a + ld (brief_color5__),a + ld (spec_color1__),a + ld (spec_color3__),a + ld (spec_color5__),a + ld (spec_color7__),a + ld (spec_color9__),a + ld (spec_color11__),a + ld (sort_color__),a + ; Selected info + ld a,(color_array+6) ; 3Eh + ld (markline_color_),a + ld (markline_color1_),a + ; Selected title + ld a,(color_array+4) ; 30h + ld (path_color1__),a ; path-строка левой панели + ld (path_color2__),a ; path-строка правой панели + ; Часы в панелях + ld b,5 ; число ячеек + ld hl,clock_attr + ld a,(color_array+53) + ld (hl),a + inc hl + djnz $-2 + ; цвет строк ввода (InputLine, InpLine) + ld a,(color_array+33) + ld (ColorInLn+1),a + ret + + + +;------------------------------------------------- +; Инициализация цвета key-бара +;------------------------------------------------- +; f 30h (color_array+20) +; b 0Eh (color_array+21) +; +; b ffffff b +; 0 123456 7 - 9 строк +; +; bb ffffff +; 01 234567 - 1 строка +; +set_keybar_colors: + ld hl,keybar_attr ; массив атрибутов + ld c,9 ; число пунктов с одинаковыми атрибутами + ld de,(color_array+20) ; 0Eh/30h b/f +set_keybar__: + ld b,1 ; число байт + ld a,d + call set_keybar1__ ; цвет hot-числа + ld b,6 + ld a,e + call set_keybar1__ ; цвет пункта + ld b,1 + ld a,d + call set_keybar1__ + dec c + jr nz,set_keybar__ + ; последний пункт + ld b,2 + call set_keybar1__ + ld b,6 + ld a,e +set_keybar1__: + ld (hl),a + inc hl + djnz $-2 + ret + + +;------------------------------------------------- +; Настройка цветов панели быстрого просмотра +;------------------------------------------------- +; qview.z80 +set_qview_colors: + ; Normal text + ld a,(color_array+2) ; 1Bh + ld (qview_color2__),a + ld (qview_color4__),a + ld (qview_color5__),a + ld (qview_color7__),a + ld (qview_color9__),a + ; Highlighted info + ld a,(color_array+7) ; 1Eh + ld (qview_color6__),a + ld (qview_color8__),a + ld (qview_color10__),a + ; Info names + ld a,(color_array+8) ; 1Fh + ld (qview_color3__),a + ret + + +;------------------------------------------------- +; Настройка цветов информационной панели +;------------------------------------------------- +; info.z80 +set_info_colors: + ; Normal text + ld a,(color_array+2) ; 1Bh + ld (info_color2__),a + ld (info_color3__),a + ld (info_color4__),a + ld (info_color5__),a + ld (info_color7__),a + ld (info_color9__),a + ld (info_color11__),a + ld (info_color13__),a + ld (info_color15__),a + ld (info_color17__),a + ld (info_color19__),a + ;ld (info_color20__),a + ;ld (info_color21__),a + ;ld (info_color22__),a + ld (info_color23__),a + ld (info_color25__),a + ld (info_color27__),a + ld (info_color29__),a + ;ld (info_color30__),a + ; Highlighted info + ld a,(color_array+7) ; 1Eh + ld (info_color6__),a + ld (info_color8__),a + ld (info_color10__),a + ld (info_color12__),a + ld (info_color16__),a + ld (info_color18__),a + ; Info names + ld a,(color_array+8) ; 1Fh + ld (info_color24__),a + ld (info_color26__),a + ld (info_color28__),a + ret + +;------------------------------------------------- +; Настройка цветов инфо-панели спек-формата +;------------------------------------------------- +; info2.z80 +set_info_trd_colors: + ; Normal text + ld a,(color_array+2) ; 1Bh + ld (info_color33__),a + ld (info_color34__),a + ld (info_color36__),a + ld (info_color38__),a + ld (info_color40__),a + ld (info_color42__),a + ld (info_color43__),a + ld (info_color45__),a + ld (info_color47__),a + ld (info_color48__),a + ld (info_color50__),a + ld (info_color52__),a + ; Color_title + ld a,(color_array+5) ; 1Eh + ld (info_color35__),a + ld (info_color37__),a + ld (info_color39__),a + ld (info_color41__),a + ld (info_color44__),a + ld (info_color46__),a + ld (info_color49__),a + ld (info_color51__),a + ld (info_color53__),a + ret diff --git a/MOD1/SORT.ASM b/MOD1/SORT.ASM new file mode 100755 index 0000000..d3b9fb9 --- /dev/null +++ b/MOD1/SORT.ASM @@ -0,0 +1,447 @@ +; +; Shell-Metzner алгоритм сортировки +; + + + + + +;------------------------------------------------- +; Сортировка списка панели (вызов из оболочки) +; вход: c = буква сортировки (n/x/d/s/u) +;------------------------------------------------- +sorting_list: + call test_show_panels ; тест на режим вкл. панелей + ret z ; выкл. + ld hl,(all_files) ; число файлов и папок + ld a,l + or h + ret z + ld a,(format_mode) ; фомат акт. панели + and form_trd ; trd/scl spectrum + ret nz + ld hl,(sort_type) ; тип сорт. акт. панели + ld a,h + xor 1 ; инверсия сортировки + ld h,a + ld a,l + cp c ; новый = старому ? + jr z,$+4 ; инверсия режима сортировки + ld h,0 ; сбр. сортировку в "" + ld l,c + ld (sort_type),hl + call sorting ; раздельный список указателей + сорт. списка + jp A20FC ; обновить список + + + + +;----------------------------------------------------------- +; Создание раздельного списка указателей и сортировка +; списков папок и файлов. +; +; вход: de=кол-во записей списка +;----------------------------------------------------------- +sorting:ld de,(all_files) ; число файлов и папок + ld a,e + or d + ret z + call make_array_pointer ; создать раздельный список указателей + ld hl,sort_type+1 + ld a,(hl) ; 00/01 / + or a + ld a,0D2h ; "jp nc,.." + jr z,$+4 + ld a,0DAh ; "jp c,.." + ld (sort_mode),a ; / сортировка + dec hl + ld a,(hl) ; hl=sort_type + cp "n" ; name + jr z,sort_name + cp "x" ; extension + jr z,sort_ext + cp "d" ; date + jr z,sort_date + cp "s" ; size + jr z,sort_size + jr unsorted_list ; создать общий список указателей + + +; Сортировка папок +sort_folders: + ld de,(all_folders) ; число папок в списке + ld hl,(directory) ; начало списка указателей папок + ld c,(hl) + inc hl + ld b,(hl) + dec hl + ld a,(bc) ;+0 имя файла + cp "." ; ".." первая запись ? + jr nz,$+5 ; нет + dec de ; --число папок + inc hl ; на след. указатель + inc hl + jp metzner_sort + + +; Ctrl+F3. Сортировка по имени +sort_name: + ld hl,cmp_names ; процедура сравнения +sort__: ld (sort_func+1),hl + call sort_folders ; сортировка папок + ld hl,(all_files) ; число записей списка + ld de,(all_folders) ; число папок списка + and a + sbc hl,de + ex de,hl ; de=число файлов в списке + ld hl,(directory+2) ; начало списка указателей файлов + jp metzner_sort ; сортировка + +; Ctrl+F4. Сортировка по расширению +sort_ext: + ld hl,cmp_extensions ; процедура сравнения + jr sort__ + +; Ctrl+F5. Сортировка по дате +sort_date: + ld hl,cmp_date ; процедура сравнения + jr sort__ + +; Ctrl+F6. Сортировка по размеру +sort_size: + ld hl,cmp_size ; процедура сравнения + jr sort__ + +; Ctrl+F7. Без сортировки. +unsorted_list: + ld a,(cash_left_dir) ; банка каталога акт. панели + out (SLOT3),a ; подкл. страницу каталога + ld iy,0C000h ; начало сканируемой папки + ld hl,(directory) ; начало буфера списка адресов + ld bc,32 ; ms-dos запись + ld a,(format_mode) ; формат акт. панели + and form_trd ; trd/scl spectrum + jr z,$+5 +unsorted_spec: ; <- переход из "make_array_pointer" + ld bc,16 ; spec-запись +; создать общ. список указателей + ld de,(all_files) ; число файлов и папок в списке +unsorted_loop: + db 0FDh + ld a,l + ld (hl),a + inc hl + db 0FDh + ld a,h + ld (hl),a + inc hl + add iy,bc ; на след. запись + dec de + ld a,e + or d + jp nz,unsorted_loop + ret + + +;----------------------------------------------------------- +; Создание массива указателей на записи списка +; +; вход: de = кол-во записей списка +; выход: directory+2 - содержит начало списка файлов +; all_folders - содержит число папок в списке +; NZ - спек-список +;----------------------------------------------------------- +make_array_pointer: + ld iy,0C000h ; начало сканируемого каталога + ld a,(cash_left_dir) ; банка каталога акт. панели + out (SLOT3),a ; подкл. страницу каталога + ld hl,(directory) ; начало списка указателей + ld a,(format_mode) ; формат акт. панели + and form_trd ; trd/scl spectrum + jr z,make_msdos_list + ; спек-список + ld a,"u" + ld (sort_type),a ; уст. режим "unsort" + ld bc,0 + ld (all_folders),bc ; число папок в списке + ld (directory+2),hl ; начало списка файлов + jr unsorted_spec ; создать общ. список указателей + +; создать раздельный список указателей +make_msdos_list: + exx + ld bc,32 ; ms-dos запись + exx + ; создать указатели на папки + ld a,0CAh ; "jp z," + call make_flist1__ ; создать список папок + ld (all_folders),bc ; число папок в списке + ld (directory+2),hl ; начало списка файлов + ; создать указатели на файлы + ld iy,0C000h ; начало сканируемого каталога + ld de,(all_files) ; число файлов и папок + ld a,0C2h ; "jp nz," + ; +make_flist1__: + ld (make_flist_code),a + ld bc,0 ; счетчик числа папок/файлов +make_flist_loop: + bit 4,(iy+11) ;+11 атрибут файла +make_flist_code: + jp z,make_flist_next + db 0FDh + ld a,l + ld (hl),a + inc hl + db 0FDh + ld a,h + ld (hl),a + inc hl + inc bc ; ++число папок/файлов +make_flist_next: + exx + add iy,bc ; на след. ms-dos запись + exx + dec de + ld a,e + or d + jp nz,make_flist_loop + ret + + + + + +;------------------------------------------------- +; Сортировка списка. Shell-Metzner алгоритм. +; Работает с указателями на записи. +; +; вход: hl=адрес массива указателей +; de=кол-во записей в списке +;------------------------------------------------- +metzner_sort: + ld (sort_base+1),hl ; адрес массива + ld (sort_count+1),de ; кол-во элементов (не изм.) + ld (sort_count1),de ; (счетчик) + ; разделить тек. число элементов на 2 +sort_divide: + db 21h ; ld hl,.. +sort_count1: + dw 0 ; тек. кол-во элементов / 2 + and a + ld a,h + rra + ld h,a + ld a,l + rra + ld l,a + ld a,l + or h + ret z ; все элементы отсортированы + ld (sort_count1),hl ;6,3,1,0 тек. кол-во элементов / 2 + ex de,hl +sort_count: + ld hl,0 ;12 (count) кол-во элементов + and a + sbc hl,de ; sreclen = sort_count - sort_count1 + ld (sreclen+1),hl ;6,9,11 + ld hl,1 + ld (sortv1),hl + ld (sstadr),hl + dec l + add hl,de + add hl,de + ld (sortv2),hl ;+42,+21,+0B смещ. до середины тек. массива + ex de,hl +sort_base: + ld hl,0 ; начало массива + ; +sort_ndone: + ld (sortv4),hl ; адрес след. записи 1-й половины массива  + ld (sortv3),hl + ex de,hl + add hl,de ; смещ.до середины массива + адрес след. записи + ex de,hl ; de=адрес след. записи 2-й половины массива  +sort_compre: + ld (srtptr2+1),de + ld (srtptr1+1),hl + ; разадресация de и hl + ld a,(de) + ld c,a + inc de + ld a,(de) + ld d,a + ld e,c + ld a,(hl) + inc hl + ld h,(hl) + ld l,a + ld (srtptr3+1),hl + ld (srtptr4+1),de + ; +sort_func: + call cmp_extensions ; тек. п/п сортировки + jp z,noswap_items ; элементы равны +sort_mode: + jp nc,noswap_items ; nc/c тип / сортировки + ; обменять адреса указателей +srtptr2:ld de,0 ; адрес записи 2-й половины списка +srtptr1:ld hl,0 ; адрес записи 1-й половины списка + ld a,(de) + ld c,a + ld a,(hl) + ld (de),a + ld (hl),c + inc de + inc hl + ld a,(de) + ld c,a + ld a,(hl) + ld (de),a + ld (hl),c + ; + ld hl,(sort_count1) ;6,3,1 тек. кол-во элементов / 2 + ld a,h + cpl + ld d,a + ld a,l + cpl + ld e,a + db 21h ; ld hl,.. +sortv1: dw 0 + add hl,de ;-7, -4, -2 + jp nc,noswap_items + inc hl + ld (sortv1),hl ; порядк. номера записей + db 11h ; ld de,.. +sortv3: dw 0 ; тек. запись 1-й половины массива + ld hl,(sortv2) ;+42,+21,+0B смещ. до середины тек. массива + ld a,e + sub l + ld l,a + ld a,d + sbc a,h + ld h,a + ld (sortv3),hl ; адреса записей + jp sort_compre ; сравнить элементы (de и hl) + ; +noswap_items: + db 21h ; ld hl,.. +sstadr: dw 0 ; от 1 + inc hl ; ++incr + ld (sstadr),hl ; + ld (sortv1),hl + ex de,hl +sreclen:ld hl,0 ;6,9,11 (sreclen) длина элемента + and a + sbc hl,de ; cmp sreclen и incr + jp c,sort_divide + db 21h +sortv4: dw 0 ; адрес след. записи 1-й половины массива + inc hl ; на след. указатель + inc hl + db 11h ; ld de,.. +sortv2: dw 0 ;+42,+21,+0B смещ. до середины тек. массива + jp sort_ndone + + + +;------------------------------------------------- +; Сравнить имена +; +; in: hl=адрес записи 1-й половины массива +; de=адрес записи 2-й половины массива +; out: z - равны +; nz - не равны +;------------------------------------------------- +cmp_names: + ld b,11 ; полное имя +srtptr3:ld hl,0 +srtptr4:ld de,0 +cmp__: ld a,(de) ; 2-я половина массива + cp "_" + jp z,cmp1__ + or 00100000b + cp "Ё" ; 240 + jp nz,cmp1__ + inc a ; 241 = "ё" +cmp1__: ld c,(hl) ; 1-я половина массива + cp "_" + jp z,cmp2__ + set 5,c + cp "Ё" ; 240 + jp nz,cmp2__ + inc c ; 241 = "ё" +cmp2__: sub c + ret nz ; элементы не равны + inc hl + inc de + djnz cmp__ + ret + + +;------------------------------------------------- +; Сравнить расширения +; +; in: hl=адрес записи 1-й половины массива +; de=адрес записи 2-й половины массива +; out: z - равны +; nz - не равны +;------------------------------------------------- +cmp_extensions: + ld bc,8 ; смещ. до элем. сравнения + ex de,hl + add hl,bc ; смещ. до ячеек сравнения + ex de,hl + add hl,bc ; смещ. до ячеек сравнения + ld b,3 ; длина элем. сравнения +ecmp__: ld a,(de) ; 2-я половина массива + cp "_" + jp z,ecmp1__ + or 00100000b + cp "Ё" ; 240 + jp nz,ecmp1__ + inc a ; 241 = "ё" +ecmp1__:ld c,(hl) ; 1-я половина массива + cp "_" + jp z,ecmp2__ + set 5,c + cp "Ё" ; 240 + jp nz,ecmp2__ + inc c ; 241 = "ё" +ecmp2__:sub c + ret nz ; элементы не равны + inc hl + inc de + djnz ecmp__ + ; элементы совпадают + ld b,8 ; длина элем. сравнения + jp srtptr3 ; сравнить имена + + +;------------------------------------------------- +; Сравнить даты/размеры +; +; in: hl=адрес конца записи (1-я половина массива) +; de=адрес конца записи (2-я половина массива) +; out: z - равны +; nz - не равны +;------------------------------------------------- +cmp_date: + ld bc,25 ; смещ. на конец даты + jp $+6 +cmp_size: + ld bc,31 ; смещ. на конец размера + ex de,hl + add hl,bc ; + смещ. до ячеек сравнения + ex de,hl + add hl,bc ; + смещ. до ячеек сравнения + ld b,4 ; длина элем. сравнения + ld a,(de) ; 2-я половина массива + sub (hl) ; 1-я половина массива + ret nz ; элементы не равны + dec hl + dec de + djnz $-5 + ; элементы совпадают + jp cmp_names ; сравнить имена diff --git a/MOD1/SPACE.Z80 b/MOD1/SPACE.Z80 new file mode 100755 index 0000000..fa9ab19 --- /dev/null +++ b/MOD1/SPACE.Z80 @@ -0,0 +1,14 @@ +;╔══════════ Information ══════════╗ +;║ ║ +;║ Calculating free space... ║ +;║ ║ +;╚═════════════════════════════════╝ +; Описатель окна функции "get_free_disk" +win_free_disk: + dw 0A16h,0523h ; Yo,Xo,lenY,lenX + db "Information",0 ; титл окна + ; + db TextLine + dw 0205h ; Yo,Xo + db "Calculating free space...",0 + db -1 ; конец описателя diff --git a/MOD1/TREE.ASM b/MOD1/TREE.ASM new file mode 100755 index 0000000..4927a53 --- /dev/null +++ b/MOD1/TREE.ASM @@ -0,0 +1,339 @@ +; Сканирование папки +; +; Для врем. буфера выделяется 1 страница памяти. После отработки процедуры, +; страница освобождается. +; Макс. глубина вложенности папок равна 20-ти (можно поставить другое). +; Для массива элементов используется целая банка, вмещающая 1024 +; (16*1024=4000h) элементов. Общее число папок, отслеживаемое процедурой, +; органичивается размером этого массива. +; +; Перед вызовом процедуры, необходимо установить диск и путь. +; + + + + + +max_depth equ 20+1 ; макс. число вложенности папок + + +;----------------------------------------------------------- +; Сканирование папки +; выход: NC - нормальное завершение +; C - операция прервана пользователем (A=0FFh) +;----------------------------------------------------------- +ScanTree: + ld (tree_stack),sp + ld bc,3135h ; очистить буфер сист. клавы + rst 10h + ld sp,work_buffer+512 ; стек процедуры + in a,(SLOT3) + ld (tree_page),a ; сохр. порт + ; выделить 1 стр. под врем. буфер + ld bc,01C2h + rst 08h + ld (tmppage+1),a ; сохр. дескр. стр. + jr nc,$+9 ; без ошибок + xor a + ld (tmppage+1),a + ld a,(page_dial_screen) ; исп. для врем. буфера + out (SLOT3),a + xor a + ld l,a + ld h,a + ld (depth_tree),a ; сбр. номер уровня вложений + ld (count_dirs),hl ; сбр. число папок + ld (count_files),hl ; сбр. число файлов + ld (size_files),hl ; сбр. размер файлов + ld (size_files+2),hl + push hl ; тек. элемент (корень) в стек + ld (cur_tree_adr+1),hl ; инит. ячейку + ld hl,LC000+16 ; начало буфера элементов вложений + ld (end_tree),hl ; начало след. 16-ти байтного элемента + ld b,16 ; размер элемента вложений + ld (hl),a ; a=0 + inc hl + djnz $-2 + call scan_cur_level ; сканир. одного уровня + стопка элем. + jr nc,tree_exit ; нет папок + ; войти в папку след. уровня +tree_loop: + push hl ; адрес старого элемента (после LoadDIR) + ld c,31h ; опрос сист. клавы + rst 10h + call nz,abort_tree_scan ; вывести окно "прерыв. операции" + pop hl + ld a,(depth_tree) ; номер тек. уровня вложений + inc a + cp max_depth+1 ; 20+1 макс. число вложений папок + jr c,tree_depth_ok +tree_depth_err: + ld a,EDEPTH ; 36 код "слишком большая вложенность папок" + jr tree_abort1 + ; +tree_depth_ok: + ld (depth_tree),a + ld de,(count_dirs) ; тек. число папок + bit 2,d ; >= 1024 папок (> 1 банки элементов) + jr nz,tree_depth_err ; ошибка, выйти + push hl ; тек. имя папки в стек + ld a,(hl) + or a + jr z,dirs_end ; нет вложений, вернуться в нач. уровень + ld (cur_tree_adr+1),hl ; имя папки тек. уровня + ld c,1Dh ; уст. путь на папку тек. уровня + rst 10h + call scan_cur_level ; сканир. одного уровня + стопка элем. + jr c,tree_loop ; есть папки + ; вернуться на пред. уровень +dirs_end: + ld c,31h ; опрос сист. клавы + rst 10h + call nz,abort_tree_scan ; вывести окно "прерыв. операции" + pop hl ; тек. элемент из стека + ld a,h + or l + jr z,tree_exit ; в стартовой папке + push hl ; hl=адрес имени папки + ld a,(scan_mode) ; режим работы процедуры + cp 2 ; уст. атрибутов папки + jr nz,dirs_end1 + ;call attrib_folder; + ds 3; + jr dirs_end2 +dirs_end1: + cp 3 ; удаление папки + jr c,dirs_end2 + call delete_folder; ; a=3,4 удаление/перенос папки + jr dirs_end3 +dirs_end2: + ld hl,parent_level ; ".." + ld c,1Dh ; уст. путь + rst 10h +dirs_end3: + ld hl,depth_tree ; номер тек. уровня вложений + dec (hl) + pop hl + ld de,16-1 ; размер элемента вложений - 1 + add hl,de + ld a,(hl) + inc hl + inc a + jr nz,tree_loop + jr dirs_end ; назад в цикл + ; +tree_abort: + ld a,EUABORT ; 37 код "операция прервана пользователем" +tree_abort1: + scf + jr $+3 +tree_exit: + xor a ; a=Ok и сбр. CF + push af +tmppage:ld a,0 ; дескр. стр. + or a + ld bc,01C3h ; освоб. 1 стр. памяти + call nz,0008h + db 3Eh ; ld a,.. +tree_page: + db 0 + out (SLOT3),a ; восст. порт + pop af ; возвр. код процедуры + db 31h ; ld sp,.. +tree_stack: + dw 0 ; сохр. стек + ret + + + +;------------------------------------------------- +; Сканировать один уровень +; выход: C - есть папки +; NC - нет папок +; hl=адрес старого элемента +;------------------------------------------------- +scan_cur_level: + ld de,(end_tree) + push de ; сохр. адрес старого элемента + ld ix,0 ; счетчик папок + ld hl,scan_mask ; имя файла (шаблон поиска) + ld de,work_buffer ; раб. буфер + push ix + push de + ld a,37h ; все, кроме метки тома + ld bc,0119h ; f_first 8.3 + rst 10h + pop hl + pop ix + jr c,scan_level_exit ; не найдено +scan_level_loop: + call tree_record ; для папок созд. стопку элементов + jr c,scan_level_exit ; ошибка, выход за границу банки + push ix + ld de,work_buffer ; раб. буфер + push de + ld c,1Ah ; f_next + rst 10h + pop hl + pop ix + jr nc,scan_level_loop ; назад в цикл +scan_level_exit: + ld hl,(end_tree) ; начало след. элемента + dec hl + ld (hl),-1 ; +xF в конец пред. + db 0DDh + ld c,l ; ld bc,ix + db 0DDh + ld b,h + ld hl,(count_dirs) ; тек. число папок + add hl,bc ; + число папок просканир. уровня + ld (count_dirs),hl + pop hl ; восст. адрес старого элемента + ld a,c + or b + ret z ; нет папок + ; сохр. в первом элементе в +0D..0E адрес посл. элемента +cur_tree_adr: + ld de,0 ; адрес тек. имени папки + ld a,e + or d + jr z,scan_level_exit1 + ex de,hl + ld bc,0Dh ; смещ. ячейки адреса посл. элемента + add hl,bc + ld (hl),e ; сохр. адрес посл. элемента + inc hl + ld (hl),d + ex de,hl +scan_level_exit1: + scf ; есть след. уровень + ret + + +;------------------------------------------------- +; Обработка найденной записи. +; Для папок - создает стопку элементов. +; вход: hl=раб. буфер записи +; выход: при ошибке CF, выход за границу банки +;------------------------------------------------- +; элемент: +00..0C - имя папки (с нулем) +; +0D..0E - адрес посл. элемента (в записи первого элемента) +;------------------------------------------------- +tree_record: + ld a,(work_buffer+32) ; атрибут найд. записи + bit 4,a ; папка ? + jr nz,ins_tree_item ; да + ; найден файл + ld a,(scan_mode) ; режим работы процедуры + or a ; a=0 сканир. папку + jr z,tree_record_next + dec a ; a=1 копир. папку + ;jp z,copy_file + dec a ; a=2 уст. атриб. файлов папки + ;jp z,attrib_file + dec a ; a=3 удаление папки + jp z,delete_file + dec a ; a=4 перенос папки + ;jp z,move_file + or a ; сбр. CF + ret + ; ++объем файлов +tree_record_next: + ld de,(work_buffer+28) ; мл. разряд + ld hl,(size_files) + add hl,de + ld (size_files),hl + ld de,(work_buffer+30) ; ст. разряд + ld hl,(size_files+2) + adc hl,de + ld (size_files+2),hl + ; ++число файлов + ld hl,(count_files) + inc hl + ld (count_files),hl + or a ; сбр. CF + ret +; найдена папка +ins_tree_item: + ex de,hl + ld hl,(end_tree) ; начало нового элемента + ld bc,16 ; размер элемента + add hl,bc + sbc hl,bc + ex de,hl + ret c ; за пределом банки (> 0FFFFh) + ld bc,33 + add hl,bc + ld a,(hl) ;+33 имя файла + cp "." ; ".", ".." + ret z + inc ix ; ++число папок + ld c,16 ; размер элемента вложений + xor a + ldi + cp (hl) + jr nz,$-3 ; скопир. в элемент имя папки + ld b,c ; обнулить остаток элемента + ld (de),a + inc de + djnz $-2 + ld (end_tree),de ; начало след. 16-ти байтного элемента + ld a,(scan_mode) ; режим работы процедуры + cp 1 ; копир. папки + ;jp z,create_folder + cp 4 ; move папки + ;jp z,create_folder; + or a ; сбр. CF + ret + + +;------------------------------------------------- +; Вывод окна прерывания операции +;------------------------------------------------- +abort_tree_scan: + ld bc,3135h ; очистить буфер сист. клавы + rst 10h + ld hl,dial_abort ; описатель окна + call DialogEr + cp evCommand ; событие "команда" + ret nz + ld a,(hl) ;+1 what + cp cmOkey ; Yes + jp z,tree_abort ; выйти из процедуры + ret + + + + +; Режим работы процедуры: +; 0 - сканирование папки +; 1 - копирование папки +; 2 - уст. атрибутов файлов папки +; 3 - удаление папки +; 4 - перенос папки +scan_mode: + db 0 + +; шаблон поиска (также исп. для поиска метки тома) +scan_mask: + db "*.*",0 +; верхний уровень +parent_level: + db "..",0 +; номер тек. уровня вложений +depth_tree: + db 0 +; начало след. 16-ти байтного элемента +end_tree: + dw 0 + +; число папок +count_dirs: + dw 0 +; число файлов папки +count_files: + dw 0 +; общ. размер файлов папки +size_files: + dw 0 ; мл. разряд + dw 0 ; ст. разряд diff --git a/MOD1/UMENU.Z80 b/MOD1/UMENU.Z80 new file mode 100755 index 0000000..47036e8 --- /dev/null +++ b/MOD1/UMENU.Z80 @@ -0,0 +1,9 @@ +; Таблица меню пользователя +user_table: + dw title_user_menu ; адрес заголовка окна + dw array_user2 ; адрес описателя меню + +; Заголовок меню пользователя +; <длина строки>, <строка> +title_user_menu: + db 9,"User menu" diff --git a/MOD1/WIDTH.ASM b/MOD1/WIDTH.ASM new file mode 100755 index 0000000..ee2fa2d --- /dev/null +++ b/MOD1/WIDTH.ASM @@ -0,0 +1,71 @@ +width_max equ 32 ; макс. длина пути панели + + +;------------------------------------------------- +; Ограничение строки пути (макс. 32 символа) +;------------------------------------------------- +width_path: + xor a + ld (width1__),a ; сбр. флаг переполн. строки + ; узнать длину пути + ld iy,(__path) ; описатель пути акт. панели + ld hl,(__buff) ; буфер пути акт. панели + ld e,l + ld d,h + ld bc,127;255 ; макс. длина пути ;!HARDCODE cmd len + cpir + dec hl + push hl ; сохр. конец пути в буфере + sbc hl,de + ld a,l + cp width_max+1 ; 33 + jr c,width__ + ; длина пути > 32 + ld a,width_max ; 32 + ld (width1__),a ; уст. флаг +width__: + ld c,a ; длина строки пути + ld b,0 + add a,3+1 ; + имя диска и концевой пробел + ld (iy+0),a ; полная длина строки + ex af,af' + push iy + pop hl + ld de,7 + add hl,de + ex de,hl ; de=приемный буфер + pop hl ; восст. конец пути в буфере + ; скопировать строку + and a + sbc hl,bc ; hl=начало перекачки + push de + ldir + ld a," " + ld (de),a ; концевой пробел + inc de + xor a + ld (de),a ; конец описателя + pop de +width1__+1: + ld a,0 ; 0/32 нет/да флаг переполн. строки + or a + jr z,width2__ + ld a,'\' + ld (de),a + inc de + ld a,"." + ld (de),a + inc de + ld (de),a + ; центрировать строку +width2__: + ex af,af' ; полная длина строки + srl a ; / 2 + ld c,a + ld a,20 ; ширина панели / 2 + sub c + ld (iy+3),a ; X полож. строки + ld a,(disk) ; номер диска акт. панели + add a,"A" + ld (iy+5),a + ret diff --git a/MOD2/CLOCK.ASM b/MOD2/CLOCK.ASM new file mode 100755 index 0000000..9599749 --- /dev/null +++ b/MOD2/CLOCK.ASM @@ -0,0 +1,104 @@ +;------------------------------------------------- +; Вывод часов вверху панели +;------------------------------------------------- +show_clock: + db 3Eh ; ld a,.. +enable_clock: + db false ; флаг вывода часов + or a + ret z + call test_show_panels ; тест на режим вкл. панелей + ret z ; выкл. + call get_systime ; узнать сист. время + ld de,clock_string ; буфер часов + ld hl,0301h ; с 0-й строки + in a,(89h) + ld b,a ; сохр. порт + in a,(SLOT0) + ld c,a ; сохр.порт + di + ld a,50h ; видео-страница + out (SLOT0),a + ld a,75+81h ; +0 (смещ. слева) + out (89h),a ; колонка + ; вывод текста + ld d,d ; уст. размер блока + ld a,5 ; длина строки + ld b,b ; выкл. аксель + ld l,l ; копировать блок + ld a,(de) + ld b,b ; выкл. аксель + ld a,a ; копирование блока (верт. линии) + ld (hl),a + ld b,b ; выкл. аксель + ; вывод атрибутов + ld de,clock_attr ; строка атрибутов + ld a,75+81h ; +0 (смещ. слева) + out (89h),a + inc hl ; перейти на атрибуты + ld d,d ; уст. размер блока + ld a,5 ; длина строки + ld b,b ; выкл. аксель + ld l,l ; копировать блок + ld a,(de) + ld b,b ; выкл. аксель + ld a,a ; копирование блока (верт. линии) + ld (hl),a + ld b,b ; выкл. аксель + ld a,b + out (89h),a ; восст. порт + ld a,c + out (SLOT0),a ; восст. порт + ei + ret + + +;------------------------------------------------- +; Убрать часы +;------------------------------------------------- +hidden_clock: + ld a,(cur_panel) ; акт. панель 0/80h - левая/правая + or a + push af + call z,change_panel ; перейти на правую + call print_up_path ; затереть часы + pop af + call z,change_panel ; вернуть акт. панель + ret + + +; Прочитать сист. время из регистра "A" CMOS +get_systime: + ld hl,clock_string ; буфер строки + ld d,04h ; регистр часов (0=рег.A, адрес = +4) + call get_systime__ + inc hl + ld d,02h ; регистр минут + ; Чтение cmos-регистра + ; вход: d=номер регистра и адрес +get_systime__: + ld bc,0DFBDh ; порт записи адреса CMOS + out (c),d + ld bc,0FFBDh ; порт чтения данных CMOS + in a,(c) + ; hex-формат + ld c,a + rra + rra + rra + rra + call $+4 + ld a,c + and 0Fh + cp 9+1 + sbc a,69h + daa + ld (hl),a + inc hl + ret + + +clock_string: + db "00:00" ; строка часов +clock_attr: + db 30h,30h,30h,30h,30h ; цвет часов diff --git a/MOD2/COPY.ASM b/MOD2/COPY.ASM new file mode 100755 index 0000000..1cf1c09 --- /dev/null +++ b/MOD2/COPY.ASM @@ -0,0 +1,302 @@ +;=========================================================== +; +; Процесс копирования файлов +; +;=========================================================== +copy: call test_show_panels ; тест на режим вкл. панелей + ret z + call get_fire ; защита от "залипания" бутонов + ld a,(format_mode) ; тек. формат панели + and form_info+form_qview ; info, qview + ret nz + ; скопир. имя файла/папки (если нет выдел.) + call prep_copy_name ; настроить имя копир. файла в описат. окон и др. + ret c ; текущий ".." и нет отмеч. файлов + ; вывод начального окна + ld hl,dial_copy ; описатель окна + call DialogW + cp evCommand ; событие "команда" + ret nz + ld a,(hl) ;+1 what + cp cmOkey ; "Copy" + ret nz + ; вывод начального окна процесса + ld hl,copy_file ; обработчик процесса ~Process Line~ + ld (subrout_process),hl + ld (subrout_process1),hl; + ld hl,dial_copy_total_process ; описатель окна с 2-мя линейками + call DialogW + cp evCommand; ; событие "команда" + ret nz; + ld a,(hl); ;+1 what + cp cmOkey; ; "Yes" + ret nz; + ; + ; + ; вывод окна ошибки копирования + ld hl,dial_error_copy + call DialogEr + cp evCommand ; событие "команда" + ret nz + ld a,(hl) ;+1 what + cp cmSkip ; "Skip" + cp cmSkipAll ; "Skip all" + cp cmOkey ; "Retry" + ret nz + ; + ; вывести окно прерывания операции + ld hl,dial_abort ; описатель окна + call DialogEr + cp evCommand ; событие "команда" + ret nz + ld a,(hl) ;+1 what + cp cmOkey ; "Yes" + ret nz + ; + ; вывод окна "файл уже существует" + ; заполнить ячейки + ld hl,dial_existing + call DialogEr + cp evCommand ; событие "команда" + ret nz + ld a,(hl) ;+1 what + cp cmOkey ; "Overwrite" + cp cmAll ; "All" + cp cmSkip ; "Skip" + cp cmSkipAll ; "Skip all" + cp cmAppend ; "Append" + ret nz + ;.. + ret + + + + + + + +; Имя копир. файла в описатели окон и буфер строки "Copy" +prep_copy_name: +; ld hl,input_line_copy ; структура +; call clear_struct_inline ; очистить структуру ~input line~ +; ld hl,(__buff1) ; путь пасс. панели +; ld de,input_line_copy+5 ; строка ~input line~ +; ld b,2 ; счетчик длины строки +; ld a,(disk1) +; add a,"A" +; ld (de),a +; inc de +; ld a,":" +; ld (de),a +; inc de +; ld a,(hl) +; ld (de),a +; or a +; jr z,$+7 +; inc hl +; inc de +; inc b +; jr $-8 +; dec hl +; ld a,'\' +; cp (hl) +; jr z,$+7 +; inc b +; ld (de),a +; inc de +; xor a +; ld (de),a +; ld a,b +; ld (input_line_copy+4),a ; структура строки ~input line~ + ; + ld bc,copy_name ; куда + call copyname + ret c ; текущий ".." и нет отмеч. файлов + ; + ld iy,input_line_copy ; структура + ; очистить структуру буфера + ld hl,input_line_copy ; структура + call clear_struct_inline + ; вставить диск + ld hl,input_line_copy+5 ; куда + ld a,(disk1) + add a,"A" + call put_char1 ; вставить символ + inc hl + ld a,":" + call put_char1 + inc hl + ; вставить путь + ld de,(__buff1) ; путь пасс. панели +prep_copy_loop: + ld a,(de) + or a + jr z,prep_copy_next + call put_char1 ; вставить символ + inc de + inc hl + jr prep_copy_loop + ; +prep_copy_next: + dec hl + ld a,'\' + cp (hl) + jr z,$+6 + inc hl + call put_char1 + inc hl + ; вставить имя + ld de,work_buffer ; откуда +prep_copy_loop1: + ld a,(de) + or a + jr z,prep_copy_next1 + call put_char1 ; вставить символ + inc de + inc hl + jr prep_copy_loop1 + ; +prep_copy_next1: + ld (hl),a + ; + ; начальное окно копирования + ;ld bc,copy_name ; куда + ;call copyname + ;ret c ; текущий ".." и нет отмеч. файлов + ; + ; окно процесса копирования с 2-мя линейками + ld hl,copy_name ; откуда + ld de,copy_name1 ; куда + call copy_string ; (hl) -> (de) + ; скопир. путь + ld hl,input_line_copy+5 ; структура строки ~input line~ + ld de,copy_name2 ; куда + call copy_dstname ; скопир. путь+имя файла/папки + ; + ; окно "ошибка копирования в:" + ld hl,copy_name ; откуда + ld de,copy_name3 ; куда + call copy_string ; (hl) -> (de) + ; с центровкой имени + ; путь назначения окна "ошибка копирования" + ld hl,input_line_copy+5 ; структура строки ~input line~ + ld de,copy_name4 ; куда + call copy_dest_name ; скопир. путь+имя файла/папки + ; + ; путь назначения окна "файл уже существует" + ld hl,copy_name4 ; откуда + ld de,exists_name ; куда + call copy_string ; (hl) -> (de) + ; имя файла + ;ld hl,work_buffer+33; + ;dec de; + ;call copy_string; ; (hl) -> (de) + ret + + + + + + + + + + + + + + + + + + + + + +;----------------------------------------------------------- +; Создать папку по тек. пути на диске назначения +;----------------------------------------------------------- +create_folder: + ; создать тек. таргет-путь в work_buffer+128 ;256 + ; основываясь на базовом пути work_buffer (точка отсчета) + or a; + ret + + +;----------------------------------------------------------- +; Скопировать файл тек. пути на диск назначения. +; Процедура линейки процесса копирования. +; При завершении (или прерывании) копирования +; выдает флаг "Carry". +;----------------------------------------------------------- +copy_file: + ; создать файл по тек. таргет-пути (в work_buffer+128 ;256) + ;... + scf; + or a; + ret + + + + + + + + + +; Ячейки 1-й линейки процесса +max_file_bytes: + dw 0 ; размер файла (папки) + dw 0 ; ст. разряд + ; +curr_bytes: + dw 0 ; тек. число обраб. байтов + dw 0 ; ст. разряд + +; Ячейки 2-й линейки процесса (общей) +max_file_bytes1: + dw 0 ; размер файла (папки) + dw 0 ; ст. разряд + ; +curr_bytes1: + dw 0 ; тек. число обраб. байтов + dw 0 ; ст. разряд + + +copy_overwrite: + db false ; флаг подтв. перезаписи при копировании + + + + + + + + +; Конвертировать размер файла в число банок +; вход: de=ст. разряд +; hl=мл. разряд +; выход: de=ст. разряд? +; hl=мл. разряд? +ConvLenToBank: + ld a,h + ld h,l + ld l,0 + sla a + rl e + rl d + rl l + sla a + rl e + rl d + rl l + or h + ld h,0 + ex de,hl + jr z,$+3 + inc hl + ld a,h + or l + ret nz + inc de + ret diff --git a/MOD2/DEBUG.ASM b/MOD2/DEBUG.ASM new file mode 100755 index 0000000..4e39416 --- /dev/null +++ b/MOD2/DEBUG.ASM @@ -0,0 +1,182 @@ +PR: push iy + push ix + push hl + push de + push bc + push af + ;push hl; + ld de,1D31h + ld c,84h + rst 08h + ld hl,work_buffer+33;256 + ld c,1Eh + rst 10h + ;ld hl,work_buffer+256 + ;xor a + ;ld c,a + ;ld b,a + ;cpir + ;dec hl + ;ex de,hl + ;pop hl; + ;call copy_string + ; + ld hl,work_buffer+33;256 + ld c,5Ch + rst 10h + ld a," " + call symb + ld a," " + call symb + ld a," " + call symb + call wait + pop af + pop bc + pop de + pop hl + pop ix + pop iy + ret + +PR1: push af + ld de,1D30h + ld c,84h + rst 08h + pop af + jp HEX1 + ;ld a," " + ;call symb + ;ld a,(type_title_qview) + ;jp HEX1 + + +PR2: push iy + push ix + push hl + push de + push bc + push af + push af; + push hl; + ld de,1D01h + ld c,84h + rst 08h + pop hl; + ;ld c,5Ch + ;rst 10h + ;ld a," " + ;call symb + ;ld a," " + ;call symb + ;ld a," " + ;call symb + pop af; + ld hl,input_line_copy+4 ; структура строки ~input line~ + ld a,(hl) + call HEX1 + ld a," " + call symb + ;call wait + pop af + pop bc + pop de + pop hl + pop ix + pop iy + ret + +PR3: push iy + push ix + push hl + push de + push bc + push af + ld de,1D01h + ld c,84h + rst 08h + ld a,(depth_tree) ; номер тек. уровня вложений + call HEX1 + pop af + pop bc + pop de + pop hl + pop ix + pop iy + ret + + + + + +HEXHL: ld a,h + push hl + call HEX1 + pop hl + ld a,l +HEX1: push af + rra + rra + rra + rra + call HEX2 + pop af +HEX2: and 0Fh + add a,90h + daa + adc a,40h + daa +symb: ld c,5Bh ; вывод символа на экран + jp int10 + +newline:ld a,0Dh + call symb ; вывод "a" на экран + ld a,0Ah + jp symb + + +wait: ld a,2 + rst 20h + jr z,$-3 ; ждем нажатия клавиши + ret + +wait1s: ld b,49 + halt + djnz $-1 + ret + + +delay: push iy + push ix + push hl + push de + push bc + push af + call wait + pop af + pop bc + pop de + pop hl + pop ix + pop iy + ret + +HEXAF: push iy + push ix + push hl + push de + push bc + push af + push af + ld de,1D17h + ld c,84h + rst 08h + pop af + call HEX1 + pop af + pop bc + pop de + pop hl + pop ix + pop iy + ret diff --git a/MOD2/DELETE.ASM b/MOD2/DELETE.ASM new file mode 100755 index 0000000..ec297fc --- /dev/null +++ b/MOD2/DELETE.ASM @@ -0,0 +1,334 @@ +;=========================================================== +; +; Процесс удаления файла/папки +; +;=========================================================== +delete: call test_show_panels ; тест на режим вкл. панелей + ret z + call get_fire ; защита от "залипания" бутонов + ld a,(format_mode) ; тек. формат панели + and form_info+form_qview ; info, qview + ret nz + xor a + ld (show_dial_ro_all+1),a ; сбр. флаг не вывода диалога "файл r/o" + ld de,(mark_files) ; число выдел. файлов + ld hl,1 + sbc hl,de + jp c,delete_group_files ; >= 2 выдел. файлов + call prep_delete_name ; имя файла в описатель окна + ret c ; ".." запись + call set_path_from_activ_panel ; уст. диск и путь акт. панели + ret c + ; очистить буфер клавы + ld a,1 + rst 20h + ; + ld a,(del_confirm) ; флаг подтверждения + or a + jr z,delete_ok + ; вывод начального окна + ld hl,dial_delete ; описатель окна + call DialogW + cp evCommand ; событие "команда" + ret nz + ld a,(hl) ;+1 what + cp cmOkey ; "Ok" + ret nz +delete_ok: + call deleting_files + ret c ; ошибки или прерывание операции + jp fresh_two_panels ; без ошибок, обновить панели + + +; УДАЛЕНИЕ ФАЙЛА/ПАПКИ +; выход: NC - Ok +; CF - прерывание операции или ошибка +; a= -1 отмена операции +; a= -2 отмена удаления тек. не пустой папки +; a=номер команды (cmCancel, cmSkip, cmSkipAll) +deleting_files: + ; + ld a,(attr_record) ; атрибут файла (глоб. ячейка) + bit 4,a ; папка ? + jr nz,delete1 ; да + bit 0,a ; Read-Only ? + jr z,delete1 ; нет +show_dial_ro_all: + ld a,false ; флаг не вывода диалога "файл r/o" + or a + jr nz,delete_yes1 + ; вывод окна "файл r/o" + ld hl,delete_name ; откуда + ld de,delete_name3 ; куда (буфер 12 байт) + call copy_string ; (hl) -> (de) с нулем + ld hl,dial_delete_ro ; "The file is read only" + call DialogEr + cp evCommand ; событие "команда" + ld a,-1 ; код "отмена операции" + scf + ret nz + ld a,(hl) ;+1 what + cp cmOkey ; "Delete" + jr z,delete_yes1 + cp cmAll ; "All" + scf + ret nz ; Cancel, Skip, Skip all + ld (show_dial_ro_all+1),a ; уст. флаг +delete_yes1: + ; снять "r/o" атрибут + ld hl,attr_record ; атрибут файла (глоб. ячейка) + res 0,(hl) ; обновить атрибут + ld a,(hl) + ld hl,temp_fname ; имя файла/папки + ld bc,0116h ; уст. атрибут файла + rst 10h +delete1: + ; скопир. имя файла/папки в описатель инфо-окна + ld hl,delete_name ; откуда + ld de,delete_name1 ; куда + call copy_string +delete_try: + ; вывод инфо-окна имени файла/папки + ld hl,dial_delete_current + call WinSimple ; открыть окно + ; удаление файла/папки + ld c,1Ch ; удалить папку + ld a,(attr_record) ; атрибут файла (глоб. ячейка) + bit 4,a ; папка ? + jr nz,$+4 ; да + ld c,0Eh ; удалить файл + ld hl,temp_fname ; имя файла/папки + rst 10h + ; закрыть инфо-окно + push af + call CloseWinSimple + pop af + ret nc ; файл (папка) удален без ошибок + ; ошибки + cp 0Bh ; не пустая папка ? + jr z,folder_not_empty ; да + ; вывод окна ошибки удаления + ld hl,delete_name ; откуда + ld de,delete_name2 ; куда (буфер 12 байт) + call copy_string ; (hl) -> (de) с нулем + ld hl,dial_error_delete ; "Cannot delete the file" + call DialogEr + cp evCommand ; событие "команда" + ld a,-1 ; код "отмена операции" + scf + ret nz + ld a,(hl) ;+1 what + cp cmOkey ; "Retry" + jr z,delete_try + scf + ret ; Cancel, Skip, Skip all + + +; Удаляемая папка не пустая +folder_not_empty: + ld a,(flag_del_non_empty) ; флаг подтверждения + or a + jr z,delete_full_folder + ; вывод окна предупреждения + ld hl,delete_name ; откуда + ld de,delete_name4 ; куда + call copy_string + ld hl,dial_nonempty_delete_folder ; "The following folder will be deleted" + call DialogEr + cp evCommand ; событие "команда" + ld a,-2 ; отмена удаления тек. не пустой папки + scf + ret nz + ld a,(hl) ;+1 what + cp cmOkey ; Delete + ld a,-2 ; отмена удаления тек. не пустой папки + scf + ret nz ; Cancel + ; удалить не пустую папку +delete_full_folder: + ld a,3 ; режим удаления +del_full_fold_rec: + ld hl,0 ; сохр. адрес записи (из п/п "prep_delete_name") + call scan_folder_alt ; уст. путь + сканир. папки (qview.asm) + jr c,delete_full_folder_err + ; Нет ошибок, удалить стартовую папку + ; скопир. имя файла в описатель инфо-окна + ld hl,temp_fname ; откуда + ld de,delete_name1 ; куда + call copy_cur_fname_alt ; скопир. имя файла и отцентровать + ; вывод инфо-окна + ld hl,dial_delete_current + call WinSimple ; открыть окно + ; составить путь стартовой папки + ld hl,(__buff) ; путь акт. панели + ld de,work_buffer ; куда (в конец строки) + call copy_string + ex de,hl + dec hl + dec hl + ld a,'\' + cp (hl) + jr z,$+3 + inc hl + ld (hl),a + inc hl + ex de,hl ; de=куда + ld hl,temp_fname ; откуда (имя папки) + call copy_string + ; удалить папку + ld hl,work_buffer ; куда (в конец строки) + ld c,1Ch ; удалить папку + rst 10h + ; закрыть инфо-окно + call CloseWinSimple + or a + ret + + +delete_full_folder_err: + ; выход из сканир. по ошибке + cp EUABORT ; 37 код "операция прервана пользователем" + scf + ret z + ; Окно ошибки удаления + ; вывод имени тек. папки + ;ld hl,work_buffer+33; ; откуда + ;ld de,delete_name5; ; куда (буфер 12 байт) + ;call copy_cur_fname_alt; ; скопир. имя файла и отцентровать + ; вывод имени стартовой папки + ld hl,delete_name ; откуда + ld de,delete_name5 ; куда + call copy_string + ld hl,dial_error_delete_tiny ; "Cannot delete the file or folder" + call DialogEr + ld a,-1 ; код "отмена операции" + scf + ret + + + +; Скопировать тек. имя удаляемого файла/папки в описатель окна. +; Обработка макс. одной выдел. записи +prep_delete_name: + ld de,(mark_files) ; число выдел. файлов + ld a,d + or e + jr nz,prep_del_name1 ; есть один выдел. файл + ; нет выдел. файлов + call get_record ; запись в тек. положении указателя + ld (attr_record),a ; атрибут файла (глоб. ячейка) + ld (del_full_fold_rec+1),hl + ld a,(hl) + cp "." ; ".." + scf + ret z + jr $+5 +prep_del_name1: + call scan_mark_records ; поиск отмеч. файла (с начала списка) +prep_del_name2: + ld (del_full_fold_rec+1),hl + ; вход: hl=запись файла + ld bc,delete_name ; куда (буфер 12 байт) + jp copy_cur_fname ; скопир. имя файла и отцентровать + + +;======== Блок работает в составе ScanTree =============== +; Удаление текущего файла +delete_file: + push ix + ; скопир. имя файла в описатель инфо-окна + ld hl,work_buffer+33 ; откуда + ld de,delete_name1 ; куда + call copy_cur_fname_alt ; скопир. имя файла и отцентровать + ; вывод инфо-окна + ld hl,dial_delete_current + call WinSimple ; открыть окно + ; + ld hl,work_buffer+32 ; атрибут найд. записи + ld a,(hl) + bit 0,a ; Read-Only ? + jr z,delete_file_next ; нет + ; снять "r/o" атрибут + res 0,(hl) ; обновить атрибут + ld a,(hl) + inc hl ; +33 (имя файла) + ld bc,0116h ; уст. атрибут файла + push af + rst 10h + pop af +delete_file_next: + ld c,0Eh ; удалить файл +delete_file_next1: + ld hl,work_buffer+33 ; имя файла + rst 10h + push af + ; закрыть инфо-окно + call CloseWinSimple + pop af + pop ix + ret + +; Удаление текущей папки +; вх: hl=адрес имени тек. папки +delete_folder: + push ix + ; скопир. имя папки в описатель инфо-окна + ld de,delete_name1 ; куда + call copy_cur_fname_alt ; скопир. имя файла и отцентровать + ; + ld hl,work_buffer+33 + ld c,1Eh ; узнать путь + rst 10h + ; вывод инфо-окна + ld hl,dial_delete_current + call WinSimple ; открыть окно + ld c,1Ch ; удалить папку + jr delete_file_next1 +;======================================================== + + + + + + +;-------------------------------------------------------------- +; Групповое удаление файлов/папок +;-------------------------------------------------------------- +delete_group_files: + call set_path_from_activ_panel ; уст. диск и путь акт. панели + ret c + ; найти отмеч. файл (с начала списка) + копир. и центровка имени + call prep_del_name1 ; найти отмеч. файл + центровка имени + ; + ld a,(del_confirm) ; флаг подтверждения + or a + jr z,delete_group_loop + ; вывод начального окна + ld hl,dial_delete ; описатель окна + call DialogW + cp evCommand ; событие "команда" + ret nz + ld a,(hl) ;+1 what + cp cmOkey ; "Ok" + ret nz +delete_group_loop: + call deleting_files ; удалить тек. файл/папку + jr nc,delete_group_next ; процесс Ok + ; отмена операции или ошибка + cp -1 ; отмена операции ? + jp z,fresh_two_panels ; да, обновить панели + cp -2 ; отмена удаления тек. не пустой папки + jr z,delete_group_next + cp cmSkipAll ; Skip all + jp z,fresh_two_panels + cp cmSkip ; Skip + jr z,delete_group_next + cp EUABORT ; 37 код "операция прервана пользователем" + jp nz,fresh_two_panels ; Cancel + call set_path_from_activ_panel ; уст. стартовый путь + jp c,fresh_two_panels ; ошибка, обновить панели +delete_group_next: + call scan_mark_loop ; поиск отмеч. файла (след. по списку) + jp c,fresh_two_panels ; нет отмеч. записей, обновить панели + call prep_del_name2 ; найти след. отмеч. запись + центровка имени + jr delete_group_loop diff --git a/MOD2/ENTER.ASM b/MOD2/ENTER.ASM new file mode 100755 index 0000000..ef32c7c --- /dev/null +++ b/MOD2/ENTER.ASM @@ -0,0 +1,228 @@ +;=========================================================== +; Выполнение команды на тек. записи +;=========================================================== +Press_Enter: + ld hl,(all_files) + ld a,l + or h + ret z ; пустая панель + call get_record ; hl=начало записи, a=атрибут файла + ; скопир. имя файла/папки в буфер + push af + ld de,work_buffer ; куда + ld bc,0044h ; 11 -> 8.3 + rst 10h + pop af + and 10h + jp z,Launch_File ; выполнить файл (launch.asm) + ;----------------------------------------- + ; Навигация по папкам + ;----------------------------------------- + ld a,true + ld (enter_to_folder),a ; уст. флаг "навигация по папкам" + ld de,work_buffer ; имя папки "file.ext" формата + ld hl,(__buff) ; адрес абс. пути акт. панели + ld bc,127;255 ; макс. длина имени + ld a,(de) + cp "." ; ".." ? + jr z,return_to_parent ; назад в родит. папку + ; создать новый путь + xor a + cpir ; на конец пути панели + dec hl + dec hl + ld a,'\' + cp (hl) + jr z,$+3 + inc hl + ld (hl),a + inc hl + ex de,hl + call copy_string ; (hl) -> (de) до нуля + ; войти в папку + call fresh_list_panel ; обновить список панели (space.asm) +enter_done: + xor a + ld l,a + ld h,a + ld (enter_to_folder),a ; флаг "навигация по папкам" + ld (fresh_list_point),hl ; сбр. полож. указателя (space.asm) + ld (fresh_list_offset),hl ; сбр. смещ. списка (space.asm) +enter_done1: ; <- вызов из "seldrv.asm" + call tab1 ; обн. путь ком-строки + вывести указатель + ; тест вкл. qview-режима на др. панели + ld a,(format_mode1) ; формат пасс. панели + bit 3,a ; info + jr nz,enter_done3 + ret + ;bit 4,a ; qview + ;ret z + ;ld a,true + ;ld (dinqview_flag),a + ;jp dinam_qview_panel ; обновить qview-панель + ; +enter_done3: + ld a,0 ; флага обновления info-панели + or a + ret z ; не отраб. при навигации по папкам + xor a + ld (enter_done3+1),a ; сбр. флаг + jp set_info_noactpanel ; обновить info-панель + + +;------------------------------------------------- +; Назад в родит. папку +;------------------------------------------------- +return_to_parent: + ; создать новый путь + call cut_path_to_prev_dir ; ограничить путь родит. папкой + ; войти в родит. папку + push af + push hl + call read_new_folder ; новый список каталога + размер папки + call sorting ; раздельный список указателей + сорт. списка + pop hl + pop af + ; скопир. имя родит. папки + ld de,work_buffer+127;255 ; куда + cp '\' ; корень пути ? + jr z,$+4 + ld (de),a ; восст. имя дочерней папки + inc de + inc hl + call copy_string + ; 8.3 -> 11 формат имени + ld hl,work_buffer+127;255 ; откуда + ld de,temp_fname ; куда (launch.asm) + ld bc,0144h + rst 10h + ; позиц. указатель на имя папки + call calc_index_name ; вычислить индекс имени + call set_pointer ; расч. полож. указателя/списка + ld (fresh_list_offset),hl ; смещ. списка (space.asm) + ld (fresh_list_point),bc ; полож. указателя (space.asm) + call fresh_list_pan ; обновить список панели (space.asm) + jr enter_done ; обновить путь ком-строки + + +; Вычислить полож. имени папки в списке панели +; вход: bc=индекс полож. имени папки +; выход: bc=полож. указателя +; hl=смещ. списка +set_pointer: + ld hl,(all_files) + ld de,(_0D01+1) ; размер страницы - 1 + call cmphlde + jr nc,setpnt2 + ; число файлов меньше списка панели +setpnt1:ld hl,0 + ret + ; +; Если индекс имени не умещается на первой странице, +; то имя установить в конец страницы и настроить +; соотв. образом смещ. списка. +setpnt2:ld a,c + sub e + ld a,b + sbc a,d + jr c,setpnt1 ; указ. в пределах первой страницы списка + ; bc=индекс имени + ; de=размер страницы-1 + ld l,c + ld h,b + ld bc,-1 ; счетчик смещ. списка + dec hl + inc bc + call cmphlde ; hl и "размер страницы - 1" + jr nc,$-5 + ld hl,(offset_list) ; смещ. списка + ld a,l + sub c ; offset_list - счетчик + ld a,h + sbc a,b + jr nc,$+4 + ld l,c ; hl=смещ. списка + ld h,b + ; указатель в пределах послед. страницы списка + ld c,e ; bc=полож. указателя + ld b,d + ret + + +; Вычислить индекс полож. имени папки в списке +; вход: temp_fname - имя папки +; выход: bc=индекс имени +calc_index_name: + ld bc,0 ; индекс положения + exx + ld hl,(all_folders) ; число папок + ld a,(sort_type) ; режим сортировки + cp "u" ; unsorted + jr nz,$+5 + ld hl,(all_files) ; число папок+файлов + ld a,l + or h + exx + ret z + ld hl,(directory) ; массив указателей на папки +calc_index__: + ld e,(hl) + inc hl + ld d,(hl) + inc hl + push hl + ex de,hl ; имя списка + ld de,temp_fname ; имя пути (launch.asm) + call compare_fnames ; сравнить имена + pop hl + ret z + inc bc ; ++индекс положения + exx + dec hl + ld a,l + or h + exx + jp nz,calc_index__ + ret + +; Сравнить строки +; вход: hl=string1 +; de=string2 +; выход: "z" - совпадают +; "nz" - не совпадают +compare_fnames: + ld a,11 ; длина сравнения + ex af,af' + ld a,(de) + cp (hl) + ret nz + inc hl + inc de + ex af,af' + dec a + jr nz,$-8 + ret + + +; Ограничить путь предыдущей папкой +; вход: hl=строка пути +; выход: hl=начало имени затертой папки +; a=затертый символ имени папки +cut_path_to_prev_dir: + ld e,l + ld d,h + xor a + cpir ; на конец строки + dec hl + ld bc,127;255 + ld a,'\' + cpdr + inc hl + ex de,hl + sbc hl,de ; корень пути ? + ex de,hl + jr nz,$+3 ; нет + inc hl + ld a,(hl) ; сохр. затир. символ + ld (hl),0 ; откинуть послед. папку + ret diff --git a/MOD2/EVENT.ASM b/MOD2/EVENT.ASM new file mode 100755 index 0000000..091cc25 --- /dev/null +++ b/MOD2/EVENT.ASM @@ -0,0 +1,57 @@ +;------------------------------------------------- +; Инициализация обработчика событий +;------------------------------------------------- +InitEvent: + ld hl,what + ld b,8 + xor a + ld (hl),a + inc hl + djnz $-2 + ld a,1 ; очистить буфер клавы + rst 20h + ld a,4 ; Get Mouse coord and buttons + rst 30h + ret + + +;------------------------------------------------- +; Чтение событий +;------------------------------------------------- +handle_event: + ld ix,what ; поле событий + ld (ix+0),evNothing + call get_mouse_info ; Get mouse coords & buttons + jr nz,ButtPress ; Button Press + ld a,2 ; опрос клавы без ожидания + rst 20h + ret z ; no keys + or a + jr z,CursKey + bit 7,d + jr z,CodeKey ; no press combination + cp 9 ; Tab + CombKeys + jr z,CursKey +CodeKey: + ld (ix+0),evKeyboard + ld (ix+1),e ; code key + ld (ix+2),d ; scan code + ret +CursKey:ld (ix+0),evCombKey ; Keyboard combination + ld (ix+1),b ; keyboard flag + ld (ix+2),d ; код курс. клавиш + ret +ButtPress: + ld d,a + ;bit 0,a ; правый бутон ? + ;jr nz,RgtButt ; да + ld (ix+0),evMouseFr ; Mouse buttons press + ld (ix+1),l ; coord X + ld (ix+2),h ; coord Y + ret +;RgtButt:ld (ix+0),evCommand + ;ld (ix+1),cmLocMenuM + ;ret + +; поле событий +what: ds 8 diff --git a/MOD2/FILLSTR.ASM b/MOD2/FILLSTR.ASM new file mode 100755 index 0000000..d436172 --- /dev/null +++ b/MOD2/FILLSTR.ASM @@ -0,0 +1,560 @@ +;------------------------------------------------- +; Заполнение строки списка по формату панели +;------------------------------------------------- +; вход: b=формат панели +; hl=начало записи каталога +; de=ячейка атрибутов файла +fill_string: + ld ix,string_of_list ; буфер строки + bit 1,b ; Medium + jp nz,fill_med + bit 2,b ; Brief + jp nz,fill_brief + ; Full + bit 6,b + jp nz,fill_full_spec ; full-spec + ; ms-dos + ld a,(de) ; байт атрибутов + bit 4,a ; папка ? + jp nz,dir_name_full ; да, вывод имени + ; формат "file ext" + ld b,8 + call L22BD ; имя файла + ld b,4 ; число пробелов + call spaces ; вставить пробелы + ld b,3 + call L22BD ; расш. файла +fill_string1__: + call separator ; "│" (или " ") разделитель колонок + ; 2 колонка (размер файла) + push hl + ld de,17 ; смещ. на размер файла + add hl,de + call L0020 ; de = размер файла + ld c,(hl) + inc hl + ld b,(hl) + push bc + exx + pop hl + exx + ex de,hl + ld a,1 + ld (put_mega),a ; уст. флаг + ld bc,0120h ; ведущие пробелы + call dec32 ; вывод размера файла (в панели) + ld hl,put_mega + ld (hl),0 ; сбр. флаг + pop hl +A2290: call separator ; "│" (или " ") разделитель колонок + ; 3 колонка (дата) + ld de,13 + add hl,de ;+24 перейти на дату + ex de,hl + ld a,(de) + and 1Fh + call dec8 ; вывод дня + ld (ix+0),"." ; разделитель "день.месяц" + inc ix + ld a,(de) + and 0E0h + ld b,a + inc de + ld a,(de) + and 1 + or b + rlca + rlca + rlca + call dec8 ; вывод месяца + ld (ix+0),"." ; разделитель "месяц.год" + inc ix + ld a,(de) + and 0FEh + rrca + add a,80 + cp 100 + jr c,$+4 + sub 100 + call dec8 ; вывод года + call separator ; "│" (или " ") разделитель колонок + ; 4 колонка (время) + dec de + dec de + ld a,(de) ;+22 ячейка времени + and 0F8h + rrca + rrca + rrca + call dec8 ; вывод часов + ld (ix+0),":" ; разделитель "часы:минуты" + inc ix + ld a,(de) ;+22 + and 7 + ld b,a + dec de + ld a,(de) ;+21 + and 0E0h + or b + rlca + rlca + rlca + jp dec8 ; вывод минут + ; +; вывод имени папки +; in: hl=адрес имени +dir_name_full: + ld a,(hl) + push af + call dir_name ; вставить имя папки + ld b,3 ; число пробелов + call spaces ; вставить пробелы + call separator ; "│" (или " ") разделитель колонок + pop af + ; 2 колонка + ld de,folder_string ; "Folder " + cp "." ; родит. папка ? + jr nz,A2304_ + ld de,up_string ; " Up " +A2304_: ex de,hl + ld b,7 ; длина строки +A2307_: ld a,(hl) + ld (ix+0),a ; символ в строку + inc hl + inc ix + djnz A2307_ + ex de,hl + jp A2290 ; вывод даты и времени + + +;------------------------------------------------- +; вывод имени папки +;------------------------------------------------- +; in: hl=начало записи каталога +; ix=буфер +dir_name: + ; формат "dir.ext" (всегда выводит 12 символов) + call directory1__ + dec e + inc e + ret z + ld b,e + jp spaces ; добавить концевые пробелы + ; +directory1__: + ld e,1 ; счетчик дополн. пробелов + ld b,8 ; имя папки + call directory3__ + ld a,(hl) + cp " " + jr z,directory2__ + dec e + ld (ix+0),"." ; символ в строку + inc ix +directory2__: + ld b,3 ; расш. папки +directory3__: + ld a,(hl) + cp " " + jr z,directory4__ + ; вывод символа + ld (ix+0),a ; символ в строку + inc ix + inc hl + djnz directory3__ + ret +directory4__: + inc hl + inc e + djnz directory4__ + ret + + +;------------------------------------------------- +; Medium +;------------------------------------------------- +fill_med: + bit 6,b + jp nz,fill_med_spec ; med-spec + ; ms-dos + ld a,(de) ;+11 смещ. до байта атрибутов + bit 4,a ; папка ? + jp nz,dir_name_med ; да, вывод имени + ; формат "file.ext" (всегда выводит 15 символов) + ld d,0 ; маленькие буквы +fill_med1: + call fill_med1__ +fill_med__: + ld a,(string_len) + sub 15 ; 15=длина строки имени + ld b,a + jp spaces + ; +fill_med1__: + call fill_med2__ +fill_med11__: + ld b,e + jp spaces ; добавить концевые пробелы + ; +fill_med2__: + ld b,8 ; имя файла + ld e,1+3 ; счетчик дополн. пробелов + call fill_med4__ + ld a,(hl) + cp " " + jr z,fill_med3__ + dec e + ld (ix+0),"." ; символ в строку + inc ix +fill_med3__: + ld b,3 ; расш. +fill_med4__: + ld a,(hl) + cp " "+1 + jr c,fill_med7__ + ; вывод символа + bit 0,d + jr nz,fill_med6__ ; не менять регистр букв + cp "_" + jr z,fill_med6__ + set 5,a + cp "Ё" ; 240 + jr nz,fill_med6__ + inc a ; 241 = "ё" +fill_med6__: + ld (ix+0),a ; символ в строку + inc ix + inc hl + djnz fill_med4__ + ret +fill_med7__: + inc hl + inc e + djnz fill_med7__ + ret + ; +dir_name_med: + call dir_name ; вставить имя папки + ld a,(string_len) + sub 12 ; длина имени папки + ld b,a ; число пробелов + jp spaces ; вставить пробелы + +; вставить спек-имя "file.ext" формата +;-------------------------------------- +fill_med_spec: + call fill_med_spec_name + jr fill_med__ + ; +fill_med_spec_name: + ld b,8-1 ; имя файла + ld e,1+3 ; счетчик дополн. пробелов + call fill_med_spec2 + ld a,(hl) + cp " " + jr z,fill_med_spec1 + dec e + ld (ix+0),"." ; символ в строку + inc ix +fill_med_spec1: + call fill_spec_ext1 ; скопир. расш. + jr fill_med11__ ; добавить конц. пробелы + ; +fill_med_spec2: + ld a,(hl) + and 7Fh ; сбр.7-й бит (марк.файла) + ld (ix+0),a + inc ix + inc hl +fill_med_spec3: + ld a,(hl) + cp " " + jr nz,fill_med_spec4 + inc hl + ld a,(hl) + dec hl + cp " " + jr z,fill_med_spec5 + ld a,b + dec a + jr z,fill_med_spec5 + ld a,"_" ;" " ; символ внутри имени +fill_med_spec4: + ld (ix+0),a + inc ix + inc hl + djnz fill_med_spec3 + ret + ; +fill_med_spec5: + inc hl + inc e + djnz fill_med_spec5 + ret + + +;------------------------------------------------- +; Brief +;------------------------------------------------- +fill_brief: + bit 6,b + jr nz,fill_brief_spec ; brief-spec + ; ms-dos + ld a,(de) ;+11 смещ. до байта атрибутов + bit 4,a ; папка ? + jp nz,dir_name ; да, вывод имени + ; формат "filename ext" + ld b,8 + call L22BD ; имя файла + ld (ix+0)," " + inc ix + ld b,3 + jp L22BD ; расш. файла + ; +; формат "filename ext" +fill_brief_spec: + ld b,1 ; число пробелов между "Filename" и "Ext" + jp fill_spec_name + + +;------------------------------------------------- +; Full-Spec +;------------------------------------------------- +;║ Name │ Size│Start│SSz│Trk│Sec║ +;║Filename Ext│00000│00000│000│000│000║ +; +fill_full_spec: + ld b,3 ; число пробелов между "Filename" и "Ext" + call fill_spec_name ; вывод "Filename Ext" +fill_full_spec1: + inc hl ; на старт. адрес файла (2-я буква расш.) + push hl + ; колонка "Size" + inc hl + inc hl + call L0020 ; в de размер файла в байтах + call dec16s ; 16-bit число с вед. пробелами + call separator ; "│" + pop hl + ; колонка "Start" + call L0020 ; в de старт. адрес + call dec16s + call separator + inc hl + inc hl + ; колонка "SSz" + ld a,(hl) ; размер файла в секторах + inc hl + call dec9 ; 0..999 число с вед. пробелами + call separator + db 3Eh ; ld a,.. +trd_records: + db true ; флаг trd-списка файлов + or a + jr z,fill_spec_scl + ; колонка "Trk" (номер дорожки файла) + inc hl + ld a,(hl) + call dec9 + call separator + dec hl + ; колонка "Sec" (номер первого сектора файла) + ld a,(hl) + jp dec9 + ; + ; SCL-список файлов +fill_spec_scl: + ld b,3 + call spaces ; очистить колонку "Trk" + call separator + ld b,3 + jp spaces ; очистить колонку "Sec" + +; Имя спек-файла формата "Filename Ext" +; вход: b=число пробелов между "Filename" и "Ext" +fill_spec_name: + push bc + ld a,(hl) + and 7Fh ; сбр.7-й бит (марк.файла) + ld (ix+0),a + inc ix + inc hl + ld b,7 + call A0E90 ; скопир. имя файла + pop bc + call spaces + push hl + call fill_spec_ext1 ; скопир. расш. + call separator ; "│" + pop hl + ret + ; +; Копирование спек-расширения файла +fill_spec_ext1: + ; запрещены в ms-dos + ; " + , . / : ; < = > [ \ ] | + ; 22 2B 2C 2E 2F 3A 3B 3C 3D 3E 5B 5C 5D 7C + ; + ld bc,0320h ; расш./пробел + ld a,(hl) + cp "B" ; (B)asic-файл + jr nz,fill_spec_ext__+1 + ld (ix+0),a ; символ в строку + inc ix + inc hl + dec b + jr fill_spec_ext2__ +fill_spec_ext__: + ld a,(hl) + cp " "+1 + jr c,fill_spec_ext2__ ; нет расш. + cp "z"+1 + jr nc,fill_spec_ext2__ + cp '"' + jr z,fill_spec_ext2__ + cp "-" + jr z,fill_spec_ext1__ + cp "," ; 2Ch + jr c,fill_spec_ext1__ + cp "/"+1 ; 2Fh+1 + jr c,fill_spec_ext2__ + cp ":" ; 3Ah + jr c,fill_spec_ext1__ + cp ">" ; 3Eh + jr c,fill_spec_ext2__ + cp "[" + jr c,fill_spec_ext1__ + cp "_"+1 + jr c,fill_spec_ext2__ + cp "`" + jr z,fill_spec_ext2__ +fill_spec_ext1__: + ld (ix+0),a ; символ в строку + inc ix + inc hl + djnz fill_spec_ext__ + ret + ; +fill_spec_ext2__: + ld (ix+0),c ; символ в строку + inc ix + inc hl + djnz fill_spec_ext2__ + ret + + + + + + + + + + + + +;------------------------------------------------- +; Вставка строки в буфер (маленькими буквами) +;------------------------------------------------- +; in: hl=строка +; ix=буфер +; b=длина вход. строки +; +L22BD: ld a,(hl) + inc hl + cp "_" + jr z,A22D0_ + set 5,a + cp "Ё" ; 240 + jr nz,A22D0_ + inc a ; 241 = "ё" +A22D0_: ld (ix+0),a ; символ в строку + inc ix + djnz L22BD + ret + + + + + + +;----------------------------------------------------------- +; Вывод информ. строки внизу панели +;----------------------------------------------------------- +print_status: + call test_show_panels ; тест на режим вкл. панелей + ret z ; выкл. + ld a,(format_mode) + and form_info+form_qview + ret nz + call get_record ; адрес тек. записи в папке + ld b,a ;+11 атрибут файла + jr print_status6__ + ; +print_status1: + db 21h ; ld hl,.. +print_status1__: + dw 0 ; сохр. начало записи (из каталога) + db 6 ; ld b,.. +print_status2__: + db 0 ; атрибут файла +print_status6__: + ; очистить стат. строку + di + ld (print_stat_stack),sp ; сохр. стек + ld de,2020h ; пробелы + ld sp,status_string+42 ; конец строки - 1 + ld a,19 ; 38/2 +print_stat_loop: + push de + dec a + jr nz,print_stat_loop + db 31h ; ld sp,.. +print_stat_stack: + dw 0 + ei + ld ix,status_string+4 ; буфер строки + ld a," " + ld (separ__),a + ld a,(format_mode) ; формат акт. панели + bit 6,a ; spec + jr nz,print_status_spec + bit 4,b ; папка ? + jr z,print_status4__ ; нет + bit 0,a ; full + jr z,print_status3__ ; нет + call dir_name ; вставить только имя папки + jr print_status5__ + ; +print_status3__: + call dir_name_full ; вставить имя+дата+время папки + jr print_status5__ + ; +; имя файла +print_status4__: + ld d,1 ; не менять регистр букв + call fill_med1__ ; формат "file.ext" (выводит 15 симв.) + ld a,(format_mode) ; формат акт. панели + bit 0,a ; full + call z,fill_string1__ ; вставить размер+дата+время +print_status5__: + ld a,"│" + ld (separ__),a ; восст. разделитель + ld (ix+0),0 ; конец описателя + ; вывод готовой строки + ld hl,status_string ; описатель строки + jp draw_text ; позиц. вывод строки + ; + ; +; заполнение спек-строки +print_status_spec: + ; формат "file.ext" + push hl + call fill_med_spec_name ; вставить спек. имя + pop hl + ld bc,8 ; смещ. на 1-ю букву расш. + add hl,bc ; для п/п fill_full_spec1 + ld a,(format_mode) ; формат акт. панели + bit 0,a ; full + call z,fill_full_spec1 ; вставить "Size-Start-SSz-Trk-Sec" + jr print_status5__ ; вывод готовой строки diff --git a/MOD2/HILIGHT.ASM b/MOD2/HILIGHT.ASM new file mode 100755 index 0000000..4401d54 --- /dev/null +++ b/MOD2/HILIGHT.ASM @@ -0,0 +1,170 @@ +;------------------------------------------------- +; Подсветка файлов +; +; вход: de=адрес атрибута файла (+11) +; b=формат акт. панели +; выход: c=индекс цвета +;------------------------------------------------- +hilight_types: + ld c,index_markfile; ; 3 индекс цвета марк. файла + ex de,hl + inc hl + ld a,(hl) ;+12 ячейка маркировки файла + rlca ; отмечен ? + ret c ; да + dec c; ; c=2 + db 3Eh ; ld a,.. +hilight_enable: + db true ; флаг раскраски файлов + or a + ret z + bit 6,b ; spec-формат ? + ret nz ; да + dec hl + bit 4,(hl) ;+11 папка ? + ld c,60; ; индекс цвета папки + ret nz ; да + ld c,62; ; c=62 индекс цвета архивов + dec hl ;+10 hl=конец расш. + ld a,(hl) ; J + dec hl + ld d,(hl) ; R + dec hl + ld e,(hl) ; A + res 5,d + res 5,e + cp " " + jp nz,hilight + ; 2-х букв. расширение архивов + ld hl,"AH" ; ha + and a + sbc hl,de + ret z + ld hl,"ZG" ; gz + and a + sbc hl,de + ret z + jp hilight_normal + ; +hilight:and 11011111b ; сбр. 5-bit + dec c; ; c=61 индекс цвета исполняемых файлов + ; исполняемые файлы + ld hl,"XE" ; exe + and a + sbc hl,de + jp nz,hilight1 + cp "E" + ret z + jp hilight_normal +hilight1: + ld hl,"AB" ; bat + and a + sbc hl,de + jp nz,hilight_spec + cp "T" + ret z + jp hilight_normal + ; расш. scl,trd спек-файлов +hilight_spec: + ld c,65; ; индекс цвета спек-файлов + ld hl,"CS" ; scl + and a + sbc hl,de + jp nz,hilight2 + cp "L" + ret z + jp hilight_normal +hilight2: + ld hl,"RT" ; trd + and a + sbc hl,de + jp nz,hilight_arc + cp "D" + ret z + jp hilight_normal + ; архивы +hilight_arc: + ld c,62; ; индекс цвета архивов + ld hl,"IZ" ; zip + and a + sbc hl,de + jp nz,hilight3 + cp "P" + ret z + jp hilight_normal +hilight3: + ld hl,"RH" ; hrp (hrip) + and a + sbc hl,de + jp nz,hilight4 + cp "P" + ret z + jp hilight_normal +hilight4: + ld hl,"AR" ; rar + and a + sbc hl,de + jp nz,hilight5 + cp "R" + ret z + jp hilight_normal +hilight5: + ld hl,"AC" ; cab + and a + sbc hl,de + jp nz,hilight6 + cp "B" + ret z + jp hilight_normal +hilight6: + ld hl,"RA" ; arj + and a + sbc hl,de + jp nz,hilight7 + cp "J" + ret z + cp "C" ; ar(c) + ret z + jp hilight_normal +hilight7: + ld hl,"CA" ; ace + and a + sbc hl,de + jp nz,hilight8 + cp "E" + ret z + jp hilight_normal +hilight8: + ld hl,"ZL" ; lzh + and a + sbc hl,de + jp nz,hilight9 + cp "H" + ret z + jp hilight_normal +hilight9: + ld hl,"CI" ; ice + and a + sbc hl,de + jp nz,hilight10 + cp "E" + ret z + jp hilight_normal +hilight10: + ld hl,"GT" ; tgz + and a + sbc hl,de + jp nz,hilight11 + cp "Z" + ret z + jp hilight_normal +hilight11: + ld hl,"OZ" ; zoo + and a + sbc hl,de + jp nz,hilight_normal + cp "O" + ret z +hilight_normal: + ld c,2; ; индекс цвета панели + ret diff --git a/MOD2/INFO.ASM b/MOD2/INFO.ASM new file mode 100755 index 0000000..9e3f72e --- /dev/null +++ b/MOD2/INFO.ASM @@ -0,0 +1,611 @@ +;///////////////////////////////////////////////////////////////////// +; Вывод данных акт. панели -> в пасс. панель (вызывается из файлера) +; <триггерная фитча> +;///////////////////////////////////////////////////////////////////// +alt_info_panel: + call test_show_panels ; тест на режим вкл. панелей + ret z ; выкл. + ; тест наличия qview-формата на акт. панели + ld a,(format_mode) ; формат акт. панели + and form_info + jr nz,set_norm_actpanel2 ; вывести норм. активную панель + ld hl,info1_ ; триггер пасс. панели + ld a,(hl) + or a + jr nz,set_norm_noactpanel2 ; вывести норм. пассивную панель + jr set_info_noactpanel ; info-панель в пасс. панели (акт. данные) + + + +;-------------------------------------------------- +; Вывести нормальной акт. панель +;-------------------------------------------------- +set_norm_actpanel2: + ld hl,info_ ; триггер акт. панели + ld (hl),0 ; сбр. триггер + inc hl + ld a,(hl) ; ячейка form_under_info + ld (format_mode),a ; формат акт. панели + jp A20FC ; вывести панель + +;-------------------------------------------------- +; Вывести нормальной пасс. панель +;-------------------------------------------------- +set_norm_noactpanel2: + call change_panel + call set_norm_actpanel2 + jp change_panel + + + +;---------------------------------------------------- +; Вывести info-панель в акт. панели (пасс. данные) +; (вызывается из Меню) +;---------------------------------------------------- +set_info_actpanel: + ; заполнить данными титл-описатель + уст. его тип + call change_panel + call get_info_data + call change_panel +set_info_actpanel1: + ld de,format_mode ; формат акт. панели + ld a,(de) + bit 3,a ; info + ret nz ; не отраб. повторно + bit 4,a ; qview + jr z,$+5 + ld a,(form_under_qview) ; формат под qview-панелью + ld hl,info_ ; триггер акт. панели + ld (hl),1 ; уст. триггер + inc hl + ld (hl),a ; form_under_info + and form_trd ; учесть 6-й бит спек-формата + or form_info + ld (de),a ; уст. info-формат + xor a + ld (qview_),a ; сбр. qview-триггер + ld (enter_done3+1),a ; сбр. флаг обновления info-панели + ret + +;---------------------------------------------------- +; Вывести qview-панель в пасс. панели (акт. данные) +;---------------------------------------------------- +set_info_noactpanel: + ; заполнить данными титл-описатель + уст. его тип + call get_info_data + xor a + ld (D48B1),a ; сбр. инверсию титла + call change_panel + call set_info_actpanel1 ; вывод акт. панели + call draw_half_frame ; очистить панель + call prn_up_path ; вывести заполн. описатель + call change_panel + ld a,true + ld (D48B1),a ; уст. инверсию титла + ret + + + + +;----------------------------------------------------------- +; Заполнить титл-описатель данными диска (акт. данные) +;----------------------------------------------------------- +get_info_data: + ld hl,win_info_panel ; описатель "Calculating disk space..." + call WinSimple ; открыть окно + ; + ; настроить строку тек. даты + call info_get_date + ; + ; Тест на наличие м/с CMOS + ld c,0F5h + rst 08h + ld hl,cmos_yes ; "Yes" + jr nc,$+5 + ld hl,cmos_no ; " No" + ld b,3 ; длина строки + ld ix,info_cmos_string + call A0E90 ; скопировать строку + ; + ; Версия BIOS + ld hl,work_buffer ; врем. буфер + ld c,0EFh ; инфа о версии Биоса и железа + rst 08h + push bc + push de + xor a + ld l,d + ld h,a + ld ix,info_bios_version ; буфер + exx + ld l,a ; ст. разряд + ld h,a + exx + ld bc,0120h ; с ведущ. пробелом + ld iy,tmp1__ + res 7,(iy+0) + call dec2 + pop hl + ld a,l + ld (ix+0),"." + inc ix + call dec8 + pop hl + ld h,0 + ld (ix+0),"." + inc ix + call dec16 + ; + ; Board ID + ld bc,01EDh + rst 08h + ld ix,info_board_id ; буфер + push de + push hl + ld a,b + call hex8 ; hex + ld (ix+0),"-" + inc ix + ld a,c + call hex8 ; hex + ld (ix+0),"-" + inc ix + pop hl ; мл. разряд + exx + ld hl,0 ; ст. разряд + exx + ld bc,0130h ; с ведущ. нулями + ld iy,tmp1__ + res 7,(iy+0) + call dec5 ; 16-bit десят. вывод (с вед. нулями) + pop hl + call hex16 ; hex + ; + ; Текущий диск + ld a,(disk) + add a,"A" + ld (info_hdd+14),a ; ячейка буквы диска + ld (info_cdrom+15),a + ld (info_fdd+16),a + ld (info_ram+13),a + ; прочитать BPB диска + ld a,(disk) ; номер диска + ld c,1 ; open device + rst 18h + jr c,get_inf_data_err + ld a,(disk) + ld de,work_buffer ; буфер + ld c,4 ; get BPB + rst 18h + push af + ld a,(disk) ; номер диска + ld c,2 ; close device + rst 18h + pop af + jr c,get_inf_data_err + ; байт формата носителя + ld a,(work_buffer+21) + ld (media_byte),a +get_inf_data_err: + ; Серийный номер лог. диска + ld ix,info_serial ; xxxx-xxxx + ld hl,(work_buffer+41) ; ст.часть + call hex16 + ld (ix+0),"-" + inc ix + ld hl,(work_buffer+39) ; мл.часть + call hex16 + ; + ; Метка диска + ld a,(disk) ; номер диска + cp 2 ; меньше "C:" ? + jr nc,get_inf_data1 ; метка в BPB + ; floppy, метка - запись файла + ld c,1 ; уст. диск + rst 10h + ld hl,scan_mask ; "*.*" имя поиска метки тома + ld de,work_buffer+127;255 + ld a,8 ; атрибут метки тома + ld bc,0019h ; F_FIRST, формат "FilenameExt" + rst 10h + jr c,get_inf_data1 ; метки нет + ld hl,work_buffer+127+43 ;+255+43 откуда (конец метки) + jr $+5 +get_inf_data1: + ld hl,work_buffer+53 ; откуда (конец метки) + ld de,info_volume+10 ; куда (конец строки) + ld ix,info_volume + call copy_volume ; скопир. метку + ; + ; Объем диска + ld a,(disk) ; номер диска + ld c,3 ; инфа о диске + rst 10h + jr nc,get_inf_data_ok + xor a + ld l,a + ld h,a + ld e,a + ld d,a + ld c,a + ld b,a + inc a +get_inf_data_ok: + ; a=размер кластера в секторах + ; bc=размер сектора в байтах + ; hl=общее кол-во кластеров + ; de=своб. кластеров + push de + push hl + ld hl,0 + add hl,bc ; вычислить размер кластера + dec a + jr nz,$-2 + ex de,hl ; de=размер кластера + pop bc ; общ.кол-во кластеров + call mul_bcde ; bc*de=hlbc общий объем диска + push hl + exx + pop hl ; ст.разряд + exx + ld l,c ; мл.разряд + ld h,b + push de + ld ix,info_total_bytes ; 0,000,000,000 + call decimal32 + ; свободное место + pop de ; размер кластера + pop bc ; своб. кластеров + call mul_bcde ; bc*de=hlbc своб. место + push hl + exx + pop hl ; ст.разряд + exx + ld l,c ; мл.разряд + ld h,b + ld ix,info_free_bytes ; 0,000,000,000 + call decimal32 + ; Всего памяти + ld c,3Ch ; информация о памяти + rst 10h + push bc + ld ix,info_total_memory ; 0,000,000 + call conv_kbytes ; kbytes -> bytes и вывод в буфер + pop hl + ; Свободная память + ld ix,info_free_memory ; 0,000,000 + call conv_kbytes ; kbytes -> bytes и вывод в буфер + ; + ; вывод строки диска акт. панели + db 3Eh ; ld a,.. +media_byte: + db 0 ; байт формата из BPB + ld hl,info_hdd ; fixed disk + cp 0F8h + jr z,get_inf_data2 + ld hl,info_fdd ; removable disk + cp 0F0h ; 1.44Mb + jr z,get_inf_data3 + cp 0F9h ; 720kB + jr z,get_inf_data3 + ld hl,info_ram ; ram-disk + cp 0FAh + jr z,$+5 + ld hl,info_cdrom ; cd-rom +get_inf_data2: + ld de,info_type_device ; куда + ld bc,19 ; длина строки + ldir + ; тест на спек-формат + ld a,(format_mode) + and form_trd + call nz,get_spec_info ; заполнить спек-описатель + ; очистить буфер клавы + ld a,1 + rst 20h + ; закрыть окно "Calculating disk space..." + jp CloseWinSimple + +get_inf_data3: + ld a,(disk) ; номер диска + cp 2 ; меньше "C:" ? + jr c,$+5 + ld hl,info_ram ; ram-диск + jr get_inf_data2 + + + +; Скопировать в буфер имя метки диска. +; вход: hl=откуда (конец метки) +; de=куда (конец строки метки) +; ix=начало строки метки +copy_volume: + ld bc,11 ; длина метки + ld a,(hl) + cp " "+1 + jr nc,$+10 + dec hl + dec c + jr nz,$-7 + ld a,11 + jr $+7 + ; + ld a,11 + sub c + lddr + ld b,a + or a ; длина метки 11 симв. ? + call nz,spaces ; дополнить вед. пробелы + ret + + +; Перевод числа страниц в байты и вывод числа в буфер +; вход: hl=число страниц +; ix=буфер +conv_kbytes: + add hl,hl ; размер памяти в kB + add hl,hl ; x4 + add hl,hl ; x8 + add hl,hl ; x16 + ; переводим в байты + ex de,hl + ld bc,1024 ; 1 килобайт + call mul_bcde ; bc*de=hlbc всего памяти + push hl + exx + pop hl ; ст.разряд + exx + ld l,c ; мл.разряд + ld h,b + ld iy,tmp2__ + res 7,(iy+0) + jp decimal24 + + + + +;------------------------------------------------- +; Настроить в info-описателе строку тек. даты +;------------------------------------------------- +info_get_date: + ld c,21h ; сист. дата + rst 10h + push ix ; год + push de ; день/месяц + ld ix,info_date_string ; буфер + ld bc,0120h ; с ведущ. пробелом + ld iy,tmp1__ + res 7,(iy+0) + ld l,d ; день + ld h,0 + call dec2 ; 0..99 число + pop hl + ld c,l ; месяц + ld h,0 + add hl,hl + ld de,info_array_months-2 + add hl,de + ld e,(hl) + inc hl + ld d,(hl) + ex de,hl + ld de,info_date_string+3 ; буфер + ; скопир. имя месяца +info_get_date_loop: + ld a,(hl) + ld (de),a + inc hl + inc de + or a + jr nz,info_get_date_loop + dec de + ld a," " + ld (de),a + inc de + push de + pop ix ; буфер + pop hl ; год + push bc + ld b,0 ; не вставлять ведущ. символ + ld iy,tmp1__ + res 7,(iy+0) + call dec4 ; 0..9999 число + ld (ix+0),0 ; конец описателя + pop bc ; c=месяц + ; настроить ячейки описателя + ld a,c + ld c,7+8 ; полная длина строки + ld b,0Ch + dec a ; a=1 + jr z,info_get_date1 + inc c + dec a ; a=2 + jr z,info_get_date1 + ld c,5+8 + inc b ; b=0Dh + dec a ; a=3 + jr z,info_get_date1 + dec a ; a=4 + jr z,info_get_date1 + inc b ; b=0Eh + ld c,3+8 + dec a ; a=5 + jr z,info_get_date1 + inc c + dec a ; a=6 + jr z,info_get_date1 + dec a ; a=7 + jr z,info_get_date1 + dec b ; b=0Dh + ld c,6+8 + dec a ; a=8 + jr z,info_get_date1 + dec b + dec b ; b=0Bh + ld c,9+8 + dec a ; a=9 + jr z,info_get_date1 + inc b ; b=0Ch + ld c,7+8 + dec a ; a=10 + jr z,info_get_date1 + inc c +info_get_date1: + ld hl,info_date_string-1 + ld (hl),b ; X полож. строки + ld hl,info_date + ld (hl),c ; длина строки + ret + + +info_array_months: + dw inf_jan + dw inf_feb + dw inf_mar + dw inf_apr + dw inf_may + dw inf_jun + dw inf_jul + dw inf_aug + dw inf_sep + dw inf_oct + dw inf_nov + dw inf_dec + +inf_jan:db "January",0 +inf_feb:db "February",0 +inf_mar:db "March",0 +inf_apr:db "April",0 +inf_may:db "May",0 +inf_jun:db "June",0 +inf_jul:db "July",0 +inf_aug:db "August",0 +inf_sep:db "September",0 +inf_oct:db "October",0 +inf_nov:db "November",0 +inf_dec:db "December",0 + + + + +;------------------------------------------------- +; Заполнить спек-описатель данными спек-имиджа +; вход: заполн. буфер данными спек-имиджа +;------------------------------------------------- +get_spec_info: + ; Тип образа + ld a,(image_type); ; индекс типа + ld c,a + add a,a ;1+1=2 + add a,c ;2+1=3 + ld c,a + ld b,0 + ld hl,list_image_types ; список типов образа + add hl,bc ; откуда + ld de,img_type ; куда + ld bc,3 + ldir + ; Метка диска + ld hl,test_vol+10; ; откуда (конец метки) + ld de,trd_vol+10 ; куда (конец строки) + ld ix,trd_vol ; начало строки метки + call copy_volume ; скопир. метку + ; Тип диска + ld a,(spec_type); ; индекс типа + ld c,a + add a,a ;1+1=2 + add a,a ;2+2=4 + add a,c ;4+1=5 + ld c,a + ld b,0 + ld hl,list_disk_types ; список типов спек-диска + add hl,bc ; откуда + ld de,trd_type ; куда + ld bc,5 + ldir + ; Защита от записи + ld a,0; ; флаг защиты 0=нет, 1=есть + or a + ld hl,"a " ; " absent" + ld a,"b" + jr z,$+7 + ld hl,"rp" ; "present" + ld a,"e" + ld (trd_protect),hl ; переписать три + ld (trd_protect+2),a ; первые символы + ; Всего файлов + ld a,255; ; число + ld ix,trd_files ; буфер + call dec9 ; вывод чисел 0..999 с ведущ. пробелом + ; Удаленных файлов + ld a,0; ; число + ld ix,trd_delfiles ; буфер + call dec9 + ; для SCL-имиджа дальше обнулить + ld a,(image_type) ; тип имиджа + or a + jr nz,get_spec_inf_scl ; scl, обнулить + ; Первая свободная дорожка + ld de,1; ; число + ld ix,ffree_trk ; буфер + call dec16s ; вывод чисел 0..65535 с вед. пробелом + ; Первый свободный сектор + ld de,0; ; число + ld ix,ffree_sec ; буфер + call dec16s + ; Свободных секторов + ld de,2544; ; число + ld ix,free_sec ; буфер + jp dec16s + + +; обнулить 3 значения +get_spec_inf_scl: + ld bc,5 + ld a,c + ld hl,spec_null ; откуда + ld de,ffree_trk ; буфер "First free trk" + ldir + ld hl,spec_null + ld de,ffree_sec ; буфер "First free sec" + ld c,a + ldir + ld hl,spec_null + ld de,free_sec ; буфер "Number of free sectors" + ld c,a + ldir + ret + +spec_null: + db " 0" ; обнулялка + + +; Тип спек-имиджа (0=TRD, 1=SCL) +image_type: + db 0 ; индекс + +; Тип спек-диска (0=2S/DD, 1=2S/SD, 2=1S/DD, 3=1S/SD, 4=??/??) +spec_type: + db 0 ; индекс + + +; список типов имиджей +list_image_types: + db "TRD" ; 0 + db "SCL" ; 1 + +; список типов спек-дисков +list_disk_types: + db "2S/DD" ; 0 + db "2S/SD" ; 1 + db "1S/DD" ; 2 + db "1S/SD" ; 3 + db "??/??" ; 4 + + + + + +; тестовая строка. убрать +test_vol:; + db "ADVENT#10/2"; diff --git a/MOD2/KEYBAR.ASM b/MOD2/KEYBAR.ASM new file mode 100755 index 0000000..16e1e0c --- /dev/null +++ b/MOD2/KEYBAR.ASM @@ -0,0 +1,344 @@ +;----------------------------------------------------------- +; Вывод разных состояний key-бара и обработчики его опций +;----------------------------------------------------------- + + +; нормальная строка key-бара +keybar_norm: + db "1Help " + db "2UserMn " + db "3View " + db "4Edit " + db "5Copy " + db "6RenMov " + db "7MkFold " + db "8Delete " + db "9ConfMn " + db "10Quit " + +; строка key-бара с Ctrl+.. +keybar_ctrl: + db "1 " + db "2 " + db "3Name " + db "4Extens " + db "5Date " + db "6Size " + db "7Unsort " + db "8 " + db "9 " + db "10 " + +; строка key-бара с Alt+.. +keybar_alt: + db "1Left " + db "2Right " + db "3 " ; "3View.. " + db "4 " ; "4Edit.. " + db "5 " ; "5Print " + db "6 " + db "7 " ; "7Find " + db "8 " + db "9 " + db "10 " + +; строка key-бара с Shift+.. +keybar_shift: + db "1 " + db "2 " + db "3 " + db "4 " + db "5 " + db "6 " + db "7 " + db "8 " + db "9 " + db "10 " + + +; атрибуты строки key-бара +keybar_attr: + db kb_b,kb_f,kb_f,kb_f,kb_f,kb_f,kb_f,kb_b ; 1 + db kb_b,kb_f,kb_f,kb_f,kb_f,kb_f,kb_f,kb_b ; 2 + db kb_b,kb_f,kb_f,kb_f,kb_f,kb_f,kb_f,kb_b ; 3 + db kb_b,kb_f,kb_f,kb_f,kb_f,kb_f,kb_f,kb_b ; 4 + db kb_b,kb_f,kb_f,kb_f,kb_f,kb_f,kb_f,kb_b ; 5 + db kb_b,kb_f,kb_f,kb_f,kb_f,kb_f,kb_f,kb_b ; 6 + db kb_b,kb_f,kb_f,kb_f,kb_f,kb_f,kb_f,kb_b ; 7 + db kb_b,kb_f,kb_f,kb_f,kb_f,kb_f,kb_f,kb_b ; 8 + db kb_b,kb_f,kb_f,kb_f,kb_f,kb_f,kb_f,kb_b ; 9 + db kb_b,kb_b,kb_f,kb_f,kb_f,kb_f,kb_f,kb_f ; 10 + + + + + + + +__pointer: + call show_pointer ; вывести указатель (если панели вкл.) +;----------------------------------------------------------- +; Начальный вывод строки key-бара (строка с атрибутами) +;----------------------------------------------------------- +print_keybar: + ld de,keybar_norm ; текст +print_keybar1: + ld hl,037Dh ; 0301h + (4*31) + in a,(89h) + ld b,a ; сохр. порт + in a,(SLOT0) + ld c,a ; сохр.порт + di + ld a,50h ; видео-страница + out (SLOT0),a + ld a,81h ; +0 (смещ. слева) + out (89h),a ; колонка + ; вывод текста + ld d,d ; уст. размер блока + ld a,80 ; длина строки + ld b,b ; выкл. аксель + ld l,l ; копировать блок + ld a,(de) + ld b,b ; выкл. аксель + ld a,a ; копирование блока (верт. линии) + ld (hl),a + ld b,b ; выкл. аксель + ; вывод атрибутов + ld de,keybar_attr ; строка атрибутов + ld a,81h ; +0 (смещ. слева) + out (89h),a + inc hl ; перейти на атрибуты + ld d,d ; уст. размер блока + ld a,80 ; длина строки + ld b,b ; выкл. аксель + ld l,l ; копировать блок + ld a,(de) + ld b,b ; выкл. аксель + ld a,a ; копирование блока (верт. линии) + ld (hl),a + ld b,b ; выкл. аксель + ld a,b + out (89h),a ; восст. порт + ld a,c + out (SLOT0),a ; восст. порт + ei + ret + + + +;----------------------------------------------------------- +; Вывод строки key-бара для спец-клавиш (Ctrl,Alt,Shift) +; и переход на обработчики опций key-бара. +; (строка key-бара для спец-клавиш выводится без атрибутов) +;----------------------------------------------------------- +; вход: a = признак нажатия Ctrl,Alt,Shift +; +change_keybar: + ld (keybar2__+1),a + ld de,keybar_ctrl ; строка + bit 5,a ; Ctrl+ + jr nz,keybar__ + ld de,keybar_alt ; строка + bit 4,a ; Alt+ + jr nz,keybar__ + ld de,keybar_shift ; строка +keybar__: + ld hl,037Dh ; 0301h + (4*31) + in a,(89h) + ld b,a ; сохр. порт + in a,(SLOT0) + ld c,a ; сохр.порт + di + ld a,50h ; видео-страница + out (SLOT0),a + ld a,81h ; +0 (смещ. слева) + out (89h),a ; колонка + ; вывод текста + ld d,d ; уст. размер блока + ld a,80 ; длина строки + ld b,b ; выкл. аксель + ld l,l ; копировать блок + ld a,(de) + ld b,b ; выкл. аксель + ld a,a ; копирование блока (верт. линии) + ld (hl),a + ld b,b ; выкл. аксель + ld a,b + out (89h),a ; восст. порт + ld a,c + out (SLOT0),a ; восст. порт + ei + ld hl,__pointer ; точка выхода + push hl + ; тест на "залипание" клавиш +keybar1__: + ld a,3 ; тест нажатия клавиш + rst 20h + ld a,b + and 11110000b ; test Ctrl,Alt,Shift + jr nz,keybar1__ ; пока нажаты + ld a,2 ; опрос клавы + rst 20h + ret z ; были только Crtl,Alt,Shift +keybar2__: + ld b,0 ; сохр. биты клавиш Ctrl,Alt,Shift +keybar_options: + res 7,d ; сбр. 7-й бит + ld a,d + ; b=бит клавиш Ctrl, Alt, Shift + ; a=скен-код клавиши +;//////////////////////////////////////////////////////////////////////// +; +; Обработка опций key-бара +; +;//////////////////////////////////////////////////////////////////////// + bit 5,b ; Ctrl+.. + jr nz,options_ctrl + bit 4,b ; Alt+.. + jr nz,_option_alt +;===================================================================== +; +; Shift-опции +; +; вход: a=скен-код +;===================================================================== + cp 43h ; F9 + jp z,write_ini_file ; записать ini-файл + ret + + + + +;===================================================================== +; +; Ctrl-опции +; +; вход: a=скен-код +;===================================================================== +options_ctrl: + cp 2 ; "1" краткий акт. панели + jp z,set_format_brief + cp 3 ; "2" средний акт. панели + jp z,set_format_medium + cp 4 ; "3" полный акт. панели + jp z,set_format_full + cp 16h ; Ctrl+U обмен панелей + jp z,swap_panels + cp 25h ; Ctrl+L панель информации + jp z,alt_info_panel + cp 10h ; Ctrl+Q панель быстрого просмотра + jp z,alt_qview_panel + cp 18h ; Ctrl+O убрать/показать панели + jp z,hidden_panels + cp 12h ; Ctrl+E пред. строка истории + jp z,prev_history + cp 2Bh ; Ctrl+X след. строка истории + jp z,next_history + cp 4Fh ; Ctrl+Del, очистить историю команд + jp z,clear_history + ; + ld c,"n" ; name + cp 3Dh ; Ctrl+F3 сорт. по имени + jp z,sorting_list + ld c,"x" ; ext + cp 3Eh ; Ctrl+F4 сорт. по расш. + jp z,sorting_list + ld c,"d" ; date + cp 3Fh ; Ctrl+F5 сорт. по дате + jp z,sorting_list + ld c,"s" ; size + cp 40h ; Ctrl+F6 сорт. по размеру + jp z,sorting_list + ld c,"u" ; unsorted + cp 41h ; Ctrl+F7 без сортировки + jp z,sorting_list + ; + cp 1Dh ; Ctrl+A вывод окна атриб. файла/папки + ;jp z,set_attrib2 + cp 28h ; Enter + jp z,put_name_to_comline ; скопировать имя/путь в ком-строку + cp 4Eh ; Enter цифр. поля + jp z,put_name_to_comline + ; + cp 1Ah ; Ctrl+[ путь левой панели в ком-строку + jp z,copy_left_path_panel_to_comline + cp 1Bh ; Ctrl+] путь правой панели в ком-строку + jp z,copy_right_path_panel_to_comline + ret + + + + +;===================================================================== +; +; Alt-опции +; +; вход: a=скен-код +;===================================================================== +_option_alt: + cp 3Bh ; F1 + jp z,select_left_drive + cp 3Ch ; F2 + jp z,select_right_drive + ret + + + + + + + +;------------------------------------------------- +; Ctrl+E. Вставить пред. строку истории +; и войти в ком-строку +;------------------------------------------------- +prev_history: + call print_keybar ; восст. норм. key-бар + jp up1 + +;------------------------------------------------- +; Ctrl+X. Вставить след. строку истории +; и войти в ком-строку +;------------------------------------------------- +next_history: + call print_keybar ; восст. норм. key-бар + jp down1 + + + +;------------------------------------------------- +; Ctrl+O. Убрать/показать панели +;------------------------------------------------- +hidden_panels: + ld hl,enable_panels + ld a,(hl) + xor 1 + ld (hl),a + jr nz,hidden_off +; Скрыть панели + ; выкл. вывод часов + ld hl,enable_clock ; флаг + ld a,(hl) + ld (clock__+1),a ; сохр. флаг + ld (hl),false + ; восст. сист. экран до ком-строки + ld c,0B3h + ld a,(page_sys_screen) ; страница буфера + jp screen1__ + +; Показать панели +hidden_off: + ; сохр. сист. экран до ком-строки + ld c,0B2h + ld a,(page_sys_screen) ; страница буфера + call screen1__ + ; восст. экран менеджера + call A20FC ; вывести аст. панель + call change_panel ; сменить панель + call A20FC ; вывести пасс. панель + call change_panel + call show_pointer ; вывод указателя + ; вкл. вывод часов + ld a,(clock__+1) + ld (enable_clock),a + ret diff --git a/MOD2/LAUNCH.ASM b/MOD2/LAUNCH.ASM new file mode 100755 index 0000000..6bcfbc8 --- /dev/null +++ b/MOD2/LAUNCH.ASM @@ -0,0 +1,364 @@ +; метки не разделять! +ccp_name: + db 'X:\SYSTEM.EXE ' ; шелл +temp_fname: + ds 13 ; буфер под имя запуск. файла + + + + +; число дос-команд +count_dos_commands equ 23 ; индекс + +; Команды ДОС +array_dos_commands: + db "CD"," " ;23 индекс (счетчика "b") + db "CHDIR"," " ;22 + ; изменяют список файлов + db "DEL"," " ;21 + db "ERASE"," " ;20 + db "MD"," " ;19 + db "MKDIR"," " ;18 + db "RD"," " ;17 + db "RMDIR"," " ;16 + db "REN"," " ;15 + db "RENAME"," " ;14 + ; не изменяют список файлов + db "CLS"," " + db "DATE"," " + db "DIR"," " + db "ECHO"," " + db "EXIT"," " + db "HELP"," " + db "PATH"," " + db "PAUSE"," " + db "REM"," " + db "SET"," " + db "TIME"," " + db "VER"," " + db "VERSION"," " + + + + +count_extentions equ 4 ; кол-во расширений + +; зарез. расширения файлов +array_extensions: + db "EXE"," " + db "BAT"," " + db "TRD"," " + db "SCL"," " + + + + +;------------------------------------------------- +; Сравнить строки без учета регистра. +; Образец должен быть в верхнем регистре +; и заканчиваться пробелом. +; вход: de - string1 +; hl - string2 (образец) +; выход: Z - равны +; NZ - не равны +;------------------------------------------------- +stricmp:ld a,(de) + cp "a" + jr c,$+4 + and 11011111b ; сбр. 5-bit + cp (hl) + jr z,stricmp1 + ; на след. образец + ld a,(hl) ; образец + inc hl + cp " " + jr nz,$-4 + dec a + ret +; совпадает +stricmp1: + inc hl + inc de + ld a,(hl) ; образец + cp " "+1 + jr nc,stricmp ; образец не закончен + inc hl ; на след. образец + ld a,(de) + cp " " + ret z + or a + ret + + +; Выделить и установить диск +cut_disk: + ld hl,work_buffer ; откуда + ld de,ComLineBuff+5 ; куда + ld bc,0145h + rst 10h + ld c,1 ; уст. диск + rst 10h + ret + +; Выделить и установить путь +cut_path: + ld hl,work_buffer ; откуда + ld de,ComLineBuff+5+2 ; куда + push de + ld bc,0245h + rst 10h + pop hl + ld c,1Dh ; уст. путь + rst 10h + ret + +; Выделить имя файла из строки +cut_filename: + ld hl,work_buffer ; откуда + ld de,temp_fname ; куда + ld bc,0345h ; формат "file.ext" + rst 10h + ret + + + + +;------------------------------------------------- +; Выполнить файл +; вход: work_buffer - набранная строка +;------------------------------------------------- +Launch_File: + xor a ; false + ld (present_doscmnd),a ; сбр. флаг признака дос-команд + call set_path_from_activ_panel ; уст. сист. диск и путь от акт. панели + ret c + ld hl,ComLineBuff+5 + xor a + ld (hl),a ; сбр. ячейку + inc hl + inc hl + ld (hl),a ; +257 сбр. ячейку + ; выделить расш. файла из ком-строки + ld hl,work_buffer ; откуда + ld de,temp_fname ; куда + ld bc,0445h + rst 10h + bit 3,a ; указан диск ? + push af + call nz,cut_disk ; выделить и уст. диск + pop af + bit 2,a ; указан путь ? + push af + call nz,cut_path ; выделить и уст. путь + pop af + bit 1,a ; указано расширение ? + jr z,no_file_extension ; нет + ; тест на расширения файла + ld b,count_extentions ; 4 кол-во расширений + ld hl,array_extensions ; расширения + ld de,temp_fname ; строка1 + call stricmp ; сравнить строки + jr z,ext_parsing ; зарез. расширения + djnz $-8 + jr ext_execute + ; +ext_parsing: + ld a,b + cp count_extentions ; "exe" + jr z,ext_execute + cp count_extentions-1 ; "bat" + jr z,ext_execute + cp count_extentions-2 ; "trd" + ;jp z,ext_trd + cp count_extentions-3 ; "scl" + ;jp z,ext_scl + ; обраб. др. расширений + ;... + ret + +ext_execute: +no_file_extension: + call cut_filename ; выделить имя файла из строки + pop bc ; восст. баланс стека + ld hl,ccp_name ; "system.exe " + ld de,work_buffer+127;255 ; куда + ld bc,temp_fname - ccp_name ; длина имени + ldir + ; вставить букву диска + ld hl,ComLineBuff+5 + ld a,(hl) ; диск задан ? + or a + jr nz,$+7 ; да + ld a,(disk) ; диск акт. панели + add a,"A" + ld (de),a + inc de + ld a,":" + ld (de),a + inc de + ; вставить путь + ld hl,ComLineBuff+5+2 + ld a,(hl) ; путь задан ? + or a + jr nz,$+5 ; да + ld hl,(__buff) ; путь акт. панели + call copy_string ; (hl) -> (de) до нуля + dec de + dec de + ld a,(de) + cp '\' + jr z,$+6 + inc de + ld a,'\' + ld (de),a + inc de + ; вставить имя файла + ld hl,temp_fname ; откуда + call copy_string ; (hl) -> (de) до нуля + ; вставить хвост команды + ld hl,work_buffer + ld bc,2000h ; пробел/нуль + ld a,(hl) + inc hl + cp c + jr z,$+10 ; нет хвоста + cp b + jr nz,$-6 + dec hl + dec de + call copy_string ; (hl) -> (de) до нуля +run_dos_command: + ; отработать exe/bat файлы и дос-команды + call call_shell ; вызов шелла системы + + ld sp,stack ; стек ФМ + ; "поднять" послед. строку вывода экрана + ld c,8Eh ; узнать полож. курсора + rst 08h + cp 30 ; номер ком-строки + jr c,$+10 + jr z,$+5 + call new_line + call new_line + di + ld a,(page_module0) ; драйверы клавы, мышки, объекты + out (SLOT0),a + ei + ld a,(page_module1) ; описатели панелей, раб. буферы + out (SLOT1),a + db 3Eh ; ld a,.. +present_doscmnd: + db false ; 01/00 да/нет флаг дос-команд + or a + jp z,cold_entry ; холодный вход в ФМ + ; была дос-команда + db 3Eh ; ld a,.. +this_cd:db false ; признак "cd","chdir" команд + or a + call nz,set_path_to_activ_panel ; уст. новый путь акт. панели + jp warm_entry ; теплый вход в ФМ + + +; новая строка +new_line: + ld a,0Dh + call $+5 + ld a,0Ah + ld c,5Bh ; вывод символа на экран + rst 10h + ret + + + +;--------------------------------------------------- +; Вызов шелла системы для отработки файлов/команд +;--------------------------------------------------- +call_shell: + ; скрыть мышку ФМ + call hide_mouse + ; выкл. вывод часов панелей + ld hl,enable_clock ; флаг + ld a,(hl) + or a + jr z,$+7 ; уже выкл. + ld (clock__+1),a ; сохр. флаг (shell.asm) + ld (hl),false + ; восст. дос-страницу + di + ld a,(port_82) + out (SLOT0),a + ei + ; восст. системный экран + ld c,0B3h + ld a,(page_sys_screen) ; страница буфера + call screen__ + ; восст. полож. курсора сист. экрана + ld de,(sys_cursor_coords+1) ; Y/X + ld c,84h + rst 08h + ; восст. значение порта + ld a,(port_89) + out (89h),a + ; выполнить файл + ld (stack1+1),sp + ld hl,work_buffer+127;255 ; имя файла + ld bc,0040h + rst 10h + ; скрыть сист. мышку + ld c,2 + rst 30h +stack1: ld sp,0 + ret + + + + + +;----------------------------------------------------------- +; Разбор командной строки +;----------------------------------------------------------- +parsing_command_line: + ld hl,what ; поле событий + ld (hl),evNothing ; событие + xor a + ld hl,work_buffer+127;255 ; набранная строка + cp (hl) + ret z ; пустая ком-строка + ; поиск дос-команд + ld b,count_dos_commands ; число дос-команд + ld hl,array_dos_commands ; массив дос-команд + ld de,work_buffer+127;255 ; набранная строка + call stricmp ; сравнить строки + jr z,found_dos_command ; нашли + djnz $-8 + ; не дос-команда + ld hl,work_buffer+127;255 ; откуда + ld de,work_buffer ; куда + call copy_string ; (hl) -> (de) до нуля + jp Launch_File ; отработать файл + +; ДОС-команда найдена +found_dos_command: + ld a,true + ld (present_doscmnd),a ; уст. признак дос-команд + ld a,b + ld (number_command),a ; номер команды (shell.asm) + cp 23 ; "cd" ? + jr z,$+6 + cp 22 ; "chdir" ? + jr nz,dos_cmnd + ld (this_cd),a ; уст. признак "cd","chdir" команд + ld (change),a ; уст. флаг смены тек. диска или пути +dos_cmnd: + call set_path_from_activ_panel ; уст. сист. диск и путь от акт. панели + ld hl,ccp_name ; "system.exe " + ld de,work_buffer ; куда + ld bc,temp_fname - ccp_name ; длина имени + ldir + ld hl,work_buffer+127;255 ; откуда + call copy_string ; (hl) -> (de) до нуля + ld hl,work_buffer ; готовая строка + ld de,work_buffer+127;255 ; куда + call copy_string ; (hl) -> (de) до нуля + pop bc ; восст. баланс стека + jp run_dos_command ; отработать дос-команду diff --git a/MOD2/MKDIR.ASM b/MOD2/MKDIR.ASM new file mode 100755 index 0000000..155cbf5 --- /dev/null +++ b/MOD2/MKDIR.ASM @@ -0,0 +1,104 @@ +;=========================================================== +; +; Процесс создания папки +; +;=========================================================== +make_folder: + call test_show_panels ; тест на режим вкл. панелей + ret z + call get_fire ; защита от "залипания" бутонов + ld a,(format_mode) ; тек. формат панели + and form_info+form_qview ; info, qview + ret nz + ; вывод начального окна + ld hl,dial_folder ; описатель окна + call DialogW + cp evCommand ; событие "команда" + ret nz + ld a,(hl) ;+1 what + cp cmOkey ; "Ok" + ret nz + ; Создание папки + ld a,(input_line_makedir+4); длина введ. строки + or a + ret z ; пустая строка + ; + call set_path_from_activ_panel ; уст. диск и путь акт. панели + ret c + ; + ; выделить имя папки + ld hl,input_line_makedir+5 ; откуда + ld de,temp_fname ; куда (13 байт) + ld bc,0345h + rst 10h + push af + push af + or a + bit 3,a ; указан диск ? + call nz,cut_disk ; выделить и уст. диск + jr c,make_fold_err1 + pop af + or a + bit 2,a ; указан путь ? + call nz,cut_path ; выделить и уст. путь + jr c,make_fold_err2 + pop af + and 00001100b ; диск и путь задавались ? + jr z,try_make_fold ; нет + ld (fresh_two_panels_flag+1),a ; уст. флаг обновл. двух панелей + jr try_make_folder + ; +try_make_fold: +; call set_path_from_activ_panel ; нет, уст. диск и путь акт. панели +; ret c + ; создать папку +try_make_folder: + ld hl,temp_fname ; имя папки + ld c,1Bh ; создать папку + rst 10h + jr c,make_fold_err + ; обновить список панелей +fresh_two_panels: ;<- обращение из delete.asm + ; акт. панель + call read_new_list ; заполнить банку новым списком + размер файлов + jr c,make_fold_err + call sorting ; раздельный список указателей + сорт. списка + call A20FC ; обновить панель +fresh_two_panels_flag: + ld a,0 ; признак обновления двух панелей + or a + jr nz,$+8 + ; сравнить пути панелей (при совпад. обновить вторую) + call compare_path_two_panels + jp nz,show_pointer ; не равны, показать указатель + xor a + ld (fresh_two_panels_flag+1),a ; сбр. флаг + ; пасс. панель + call change_panel + call read_new_list ; заполнить банку новым списком + размер файлов + jr c,make_fold_err + call sorting ; раздельный список указателей + сорт. списка + call A20FC + call change_panel ; сменить панель + jp show_pointer ; показать указатель + + +make_fold_err1: + pop af +make_fold_err2: + pop af + ; Ошибка +make_fold_err: + ; центровка имени папки + ld hl,input_line_makedir+5 ; структура строки ~input line~ + ld de,create_name ; куда + call copy_dest_name ; скопир. путь+имя файла/папки + ; вывод окна ошибки создания папки + ld hl,dial_error_make_folder + call DialogEr + cp evCommand ; событие "команда" + ret nz + ld a,(hl) ;+1 what + cp cmOkey ; "Retry" + jr z,try_make_folder + ret diff --git a/MOD2/MOUSE.ASM b/MOD2/MOUSE.ASM new file mode 100755 index 0000000..6c50eb6 --- /dev/null +++ b/MOD2/MOUSE.ASM @@ -0,0 +1,362 @@ +;------------------------------------------------- +; Инициализация мышки и вывод ее на экран +;------------------------------------------------- +init_mouse: + xor a + rst 30h + jr show_mouse + + +;------------------------------------------------- +; Вывести курсор мышки +;------------------------------------------------- +show_mouse: + ld a,1 + rst 30h + ret + + +;------------------------------------------------- +; Скрыть курсор мышки +;------------------------------------------------- +hide_mouse: + ld a,2 + rst 30h + ret + + +;------------------------------------------------- +; Получить новую информацию о мышке +;------------------------------------------------- +get_mouse_info: + ld a,3 ; получить коорд. мышки + rst 30h + ret + + +;------------------------------------------------- +; Ждем, пока нажаты бутоны мышки +;------------------------------------------------- +get_fire: + call get_mouse_info + and 3 + jr nz,$-5 ; бутоны нажаты + ret + + + + + + +;--------------------------------------------------------------------- +; Обработка нажатия бутонов мышки на панелях менеджера +; +; вход: hl=Y/X текст. координаты мышки. +; d=биты нажатия бутонов +;--------------------------------------------------------------------- +buttons_press: + ld a,d + ld (buttons_bits),a ; сохр. биты нажатия бутонов + ld a,h + cp 27 ; нижняя граница списка + jp nc,event_keybar ; тест на comline и key-бар + or a ; 0-я строка + jp z,main_menu ; гориз. Меню + call test_show_panels ; тест на режим вкл. панелей + ret z + call mouse_set_active_panel ; уст. мышкой акт. панель + ld a,(format_mode) ; формат акт. панели + and form_info+form_qview + ret nz ; info, qviev + ld a,h ; Y координата мышки + cp 2 ; верхняя граница списка + jp c,event_title ; тест на заголовок панели + sub 2 + ld b,l ; сохр. X координату + ld l,a ; Y координата мышки + ld h,0 + ; + ld de,(all_files) ; число файлов и папок + ld a,e + or d + jp z,get_fire ; защита от "залипания" бутонов + ld a,(cur_panel) ; тек. акт. панель + ld c,a ; 0=левая, 80h=правая + ld a,(format_mode) ; формат акт. панели + bit 0,a ; full, full-спек + jr nz,event_set__ ; ничего не менять + push de + call event_calc_pointer ; вычислить полож. указателя + pop de +event_set__: + ; hl=полож. указателя по коорд. мышки + ; de=all_files + call cmphlde ; сравнить hl с de + jr nc,event_set_end ; указатель в конец списка + ; мышка в пределах списка (не в пустом месте колонки) + call A0E12_ ; обновить полож. указателя + ld a,(buttons_bits) ; биты нажатия бутонов + bit 1,a ; левый ? + jr nz,button_left ; да + ; поставить/снять выделение файла + call A0E13 + jp get_fire ; защита от "залипания" бутонов + ; + ; указатель в конец списка +event_set_end: + dec de + ex de,hl ; hl = all_files-1 + call A0E12_ ; обновить полож. указателя + jp get_fire ; защита от "залипания" бутонов + ; +button_left: + call get_fire + ei + ld b,9 ; ожидание + push bc + call get_mouse_info ; чтение состояния мышки + pop bc + jr nz,double_press ; кнопки нажаты + halt + djnz $-8 + ret + ; двойной клик +double_press: + xor a + ld (MSbutt),a ; сбр. статус бутонов + jp Press_Enter ; enter.asm + + + + + +;----------------------------------------------------------- +; Вычисление положения указателя по координатам мышки +; для "краткого" и "среднего" форматов панелей. +; +; вход: a=формат панели +; hl=Y координата мышки +; b=X координата мышки +; c=тек. акт. панель (0=левая, 80h=правая) +; выход: hl=полож. указателя +;----------------------------------------------------------- +event_calc_pointer: + ld de,files_per_colon ; 25 файлов на колонку + and form_brief + ld a,b ; X координата + jr z,event_medium__ + ; "краткий" формат + dec c ; акт. левая панель ? + inc c + ; левая панель + ld c,14 ; начало средней колонки + ld b,27 ; начало правой колонки + jr z,event_calc__ ; да, левая + ; правая панель + ld c,54 ; начало средней колонки + ld b,67 ; начало правой колонки +event_calc__: + cp c ; начало средней колонки + ret c + add hl,de ; коорд.мышки + файлов на колонку +event_calc1__: + cp b ; начало правой колонки + ret c + add hl,de + ret + ; + ; "средний" формат +event_medium__: + dec c ; акт. левая панель ? + inc c + ; левая панель + ld b,20 ; начало средней колонки + jr z,event_calc1__ ; да, левая + ; правая панель + ld b,60 ; начало средней колонки + jr event_calc1__ + + + +;----------------------------------------------------------- +; Установка мышкой активной панели +; +; вход: hl=Y/X координаты +; выход: h=Y коррект. координата +;----------------------------------------------------------- +mouse_set_active_panel: + ld a,(cur_panel) ; 0=левая, 80h=правая + or a + ld a,l + jr nz,mouse_set__ ; акт. правая + cp 40 ; начало правой панели + call nc,mouse_set_panel ; уст. акт. панель + ret +mouse_set__: + cp 40 ; начало правой панели + call c,mouse_set_panel ; уст. акт. панель + ret + ; +mouse_set_panel: + push hl ; сохр. координаты мышки + ld hl,D48B1 ; флаг инверсии + ld (hl),false ; сбр. инверсию path-строки + push hl + call clear_pointer ; убрать указатель + call prn_up_path ; вывод пути тек. панели без инверсии + call change_panel ; сменить акт. панель + pop hl + ld (hl),true ; инверсия path-строки + call prn_up_path ; вывод пути тек. панели с инверсией + call print_compath ; вывод пути в ком-строке + pop hl + ret + + + + +;----------------------------------------------------------- +; Обработка мышки на титле панели +; +; вход: hl=Y/X текст. координаты мышки +;----------------------------------------------------------- +event_title: + ld a,(buttons_bits) ; биты нажатия бутонов + bit 0,a ; правый бутон ? + jr nz,event_title_right ; да + ld a,l ; X координата + cp 1 ; буква сортировки + jp z,select_left_drive ; меню выбора дисков + cp 41 ; буква сортировки + jp z,select_right_drive ; меню выбора дисков + cp 2 ;  левой панели + jr z,event_title_sort + cp 42 ;  правой панели + jr z,event_title_sort + ; Указатель на строку вверх + call up ; указатель на строку вверх + jr event_title_wait ; задержка перемещ. указателя + ; +; Листание страницей +event_title_right: + call page_up ; PageUp + call get_fire + jr event_title_wait + + + + + + +;----------------------------------------------------------- +; На строку вниз, если мышка на 27-й строке +;----------------------------------------------------------- +event_footerline: + call test_show_panels ; тест на режим вкл. панелей + ret z + push bc + call mouse_set_active_panel ; уст. мышкой акт. панель + pop bc + bit 0,c ; правый бутон ? + jr nz,event_foot_right ; да + ; Указатель на строку вниз + call down +event_title_wait: + call show_pointer ; вывести указатель (когда не выводят up/down) + ei + halt + halt + halt + ret + ; +; Листание страницей +event_foot_right: + call page_down ; PageDown + call get_fire + jr event_title_wait + + + + +;----------------------------------------------------------- +; Обработка символа "стрелка" сортировки панелей +;----------------------------------------------------------- +event_title_sort: + ld hl,sort_type + ld c,(hl) ; n/x/.. буква сортировки + ld a,"u" + cp c ; unsort ? + call nz,sorting_list ; обновить панель с новой сортировкой + call show_pointer ; вывести указатель + jp get_fire ; защита от "залипания" бутонов + + + + + +;--------------------------------------------------------------------- +; Обработка мышки на key-баре +; +; вход: hl=Y/X текст. координаты мышки +;--------------------------------------------------------------------- +event_keybar: + db 3Eh ; ld a,.. +buttons_bits: + db 0 ; биты нажатия бутонов + ld c,a + ld a,h + cp 27 ; Y координата + jr z,event_footerline + bit 0,c ; правый бутон ? + ret nz ; да + ld a,h + cp 31 ; Y координата + jp nz,event_comline ; тест на ком. строку + ld a,l ; X координата + push af + call get_fire ; защита от "залипания" + pop af + cp 8 + ret c; ; F1 пункт + cp 16 + jp c,user_menu ; F2 пункт + cp 24 + jp c,file_viewer ; F3 пункт + cp 32 + ret c; ; F4 пункт + cp 40 + jp c,copy ; F5 пункт + cp 48 + jp c,rename ; F6 пункт + cp 56 + jp c,make_folder ; F7 пункт + cp 64 + jp c,delete ; F8 пункт + cp 72 + jp nc,quit ; F10 пункт + ; F9 пункт + jp main_menu + + + + + + +;--------------------------------------------------------------------- +; Обработка мышки на командной строке +;--------------------------------------------------------------------- +event_comline: + cp 30 ; Y полож. ком-строки + ret nz + ld a,(EvComMouse1+1) ; X начало поля ввода ком-строки + ld h,a + push hl ; l=X координата + call get_fire ; защита от "залипания" + pop hl + ld a,l + sub h + ret c ; мышка левее строки ввода + ld de,(YXpos+1) ; начало поля ввода ком-строки + ld (CursorPos),de + ld iy,ComLineBuff ; структура буфера ком-строки + jp enter_to_comline diff --git a/MOD2/POS.ASM b/MOD2/POS.ASM new file mode 100755 index 0000000..9585176 --- /dev/null +++ b/MOD2/POS.ASM @@ -0,0 +1,100 @@ +old1: dw 0 ; полож. указателя +old2: dw 0 ; смещ. списка +old3: dw 0 ; число записей +; флаг смены тек. диска или пути +change: db false ; 01/00 менялся/нет + + + + +; Сохранить полож. указателя и списка +save_pos_list: + ld hl,(cur_pointer) ; старое полож. указателя + ld (old1),hl + ld hl,(offset_list) ; старое смещ. списка + ld (old2),hl + ld hl,(all_files) ; старое число записей + ld (old3),hl + ret + + +; Установить полож. указателя и списка +; после нового чтения списка. +set_newpos_list: + ld a,(change) ; флаг смены тек. диска или пути + or a + jr nz,set_zero_pos ; менялся, сбр. полож. указателя + ld de,(all_files) ; новое число записей + ld hl,(old3) ; прежнее число записей + and a + sbc hl,de ; число записей изменилось ? + jr nz,set_new_pos ; да +set_old_pos: + ld hl,(old1) ; прежнее полож. указателя + ld (cur_pointer),hl + ld hl,(old2) ; прежнее смещ. списка + ld (offset_list),hl + ret +set_new_pos: + ld hl,(old1) ; прежнее полож. указателя + ld bc,(old2) ; прежнее смещ. списка + add hl,bc + and a + sbc hl,de + jr c,set_old_pos + ; прежнее полож. указателя > нового числа записей + jr set_to_end_list ; в конец списка + +; сбросить полож. указателя и списка +; диск или путь менялся. +set_zero_pos: + xor a + ld l,a + ld h,a + ld (change),a ; сбр. флаг смены тек. диска или пути + ld (offset_list),hl ; смещ. списка +set_zr: ld (cur_pointer),hl ; тек. полож. указателя + ret + +; уст. указатель на конец списка +set_to_end_list: + ld bc,(all_files) ; число записей + ld hl,(cur_pointer) + ld de,(offset_list) ; смещ. списка + add hl,de + inc hl + ld a,l + sub c + ld a,h + sbc a,b + ret z ; указатель в конце списка + ld de,(_0D01+1) ; размер страницы - 1 + ld l,c ; hl=all_files + ld h,b + call cmphlde + jr nc,set_end_lst2 + ; число файлов меньше списка панели +set_end_lst1: + dec hl + jr set_zr ; уст. тек. полож. указателя + ; +set_end_lst2: + ld bc,-1 ; счетчик + dec hl ; --all_files + inc bc + call cmphlde ; hl и "размер страницы - 1" + jr nc,$-5 + ld hl,(offset_list) ; смещ. списка + and a + sbc hl,bc + jr c,set_end_lst3 + ; указатель в пределах послед. страницы списка + ex de,hl + jr set_end_lst1 + ; +set_end_lst3: + dec bc + ld (offset_list),bc + inc de + ld (cur_pointer),de + ret diff --git a/MOD2/QVIEW.ASM b/MOD2/QVIEW.ASM new file mode 100755 index 0000000..3594dbf --- /dev/null +++ b/MOD2/QVIEW.ASM @@ -0,0 +1,487 @@ +;///////////////////////////////////////////////////////////////////// +; Вывод данных акт. панели -> в пасс. панель (вызывается из файлера) +; <триггерная фитча> +;///////////////////////////////////////////////////////////////////// +alt_qview_panel: + call test_show_panels ; тест на режим вкл. панелей + ret z ; выкл. + ; тест наличия qview-формата на акт. панели + ld a,(format_mode) ; формат акт. панели + and form_qview + jr nz,set_norm_actpanel ; вывести норм. активную панель + ld hl,qview1_ ; триггер пасс. панели + ld a,(hl) + or a + jr nz,set_norm_noactpanel ; вывести норм. пассивную панель + jr set_qview_noactpanel ; qview-панель в пасс. панели (акт. данные) + + + +;-------------------------------------------------- +; Вывести нормальной акт. панель +;-------------------------------------------------- +set_norm_actpanel: + ld hl,qview_ ; триггер акт. панели + ld (hl),0 ; сбр. триггер + inc hl + ld a,(hl) ; ячейка form_under_qview + ld (format_mode),a ; формат акт. панели + jp A20FC ; вывести панель + +;-------------------------------------------------- +; Вывести нормальной пасс. панель +;-------------------------------------------------- +set_norm_noactpanel: + call change_panel + call set_norm_actpanel + jp change_panel + + + +;---------------------------------------------------- +; Вывести qview-панель в акт. панели (пасс. данные) +; (вызывается из Меню) +;---------------------------------------------------- +set_qview_actpanel: + ; заполнить данными титл-описатель + уст. его тип + call change_panel + call get_qview_data ; пасс. данные +; push af + call change_panel + jr set_qview_actpanel1 +; pop af +; ret nc ; папка + ; вывод содерж. файла +; call draw_half_frame ; очистить панель +;set_qview_file: +; ld hl,up_info ; описатель "╔══════════╗" +; call draw_text +; ld hl,title_qview ; описатель одного титла +; call draw_text +; db 3Eh;- +;set_qview_fl: +; db false ; флаг +; or a +; ld a,0 +; ld (set_qview_fl),a ; сбр. флаг +; jr nz,$+11;- +; call change_panel +; call alt_file_viewer ; вывести содерж. файла +; call change_panel +; scf +; ret + +; настр. формат +set_qview_actpanel1: + call dinqview_res_flag ; "dinamqview" уже отработал + ld de,format_mode ; формат акт. панели + ld a,(de) + bit 4,a ; qview + ret nz ; не отраб. повторно + bit 3,a ; info + jr z,$+5 + ld a,(form_under_info) ; формат под info-панелью + ld hl,qview_ ; триггер акт. панели + ld (hl),1 ; уст. триггер + inc hl + ld (hl),a ; form_under_qview + and form_trd ; учесть 6-й бит спек-формата + or form_qview + ld (de),a ; уст. qview-формат + xor a + ld (info_),a ; сбр. info-триггер + ret + + +;---------------------------------------------------- +; Вывести qview-панель в пасс. панели (акт. данные) +;---------------------------------------------------- +set_qview_noactpanel: + ; заполнить данными титл-описатель + уст. его тип + call get_qview_data +; push af + xor a + ld (D48B1),a ; сбр. инверсию титла + call change_panel + call set_qview_actpanel1 ; настр. формат + call draw_half_frame ; очистить панель +; pop af +; jr c,set_qview_noactp2 ; файл + call prn_up_path ; вывести заполн. описатель папки +;set_qview_noactp1: + call change_panel + ld a,true + ld (D48B1),a ; уст. инверсию титла + ret + +; настроить цвет qview-титла +;set_qview_noactp2: +; ld a,(D48B1) ; флаг инверсии path-строки акт. панели +; or a +; ld a,(color_array+4) ; 30h цвет "Selected title" +; jr nz,$+5 +; ld a,(color_array+2) ; 1Bh цвет "Normal text" +; ld (qview_color1__),a ; цвет +; call set_qview_file +; jr set_qview_noactp1 + + + + + + + +type_title_qview: + db 0 ; флаг 00/01 - папка/файл + +;----------------------------------------------------------- +; Заполнить титл-описатель данными диска акт. панели +; и установить тип выводимого титла-описателя. +;----------------------------------------------------------- +get_qview_data: + ; вставить имя тек. папки или путь + сканирование + call print_qview_name + ret c ; указатель на файле + ; число папок + exx + ld hl,0 ; ст.разряд + exx + ld hl,(count_dirs) ; число папок + ld iy,tmp2__ + res 7,(iy+0) + ld ix,qview_total_folders ; "00,000" + call decimal16 + ; число файлов + exx + ld hl,0 ; ст.разряд + exx + ld hl,(count_files) ; число файлов в папке + ld iy,tmp2__ + res 7,(iy+0) + ld ix,qview_total_files ; "00,000" + call decimal16 + ; общ. размер файлов + exx + ld hl,(size_files+2) ; ст.разряд + exx + ld hl,(size_files) ; мл.разряд + ld ix,qview_total_bytes ; "0,000,000,000" + jp decimal32 + + + + + + +qview_max_name equ 29 ; макс. длина строки пути для ".." + +;------------------------------------------------------------------------ +; Вывод имени папки (или пути ".." папки) и вычисление ее параметров. +; Если указатель на ".." папке, то вычисляются ее параметры. +; Если указатель на имени файла, то выйти. +; +; выход: CF - указатель на файле +;------------------------------------------------------------------------ +print_qview_name: + ; очистить прежнее имя папки + ld hl,qview_name_folder ; буфер имени + ld b,qview_max_name ; 29 счетчик + ld a," " + ld (hl),a + inc hl + djnz $-2 + ; + call get_record + ld a,(de) ;+11 атрибут файла + and 10h ; папка ? + ld a,true ; файл + ld (type_title_qview),a ; флаг типа qview-описателя + scf + ret z + xor a ; папка + ld (type_title_qview),a ; флаг типа qview-описателя + call qview_scan_folder ; вычислить размер папки + ld a,(hl) ; начало имени папки + cp "." + jr z,qview_parent_name ; ".." папка + ld ix,qview_name_folder ; буфер имени + jp dir_name ; вставить имя папки + + + +;----------------------------------------------------------- +; Вставить путь для ".." папки. Длинный путь обрезается +; ;вход: de=куда копировать +;----------------------------------------------------------- +qview_parent_name: + ld de,qview_name_folder ; куда + ld hl,(__path) ; описателя пути акт. панели + ld a,(hl) ; длина строки + sub 2 ; минус пробелы начала-конца строки + ld bc,5 ; смещ. до буквы диска + add hl,bc ; hl=начало буквы диска строки + ld bc,qview_max_name ; 29 макс. длина пути + cp qview_max_name+1 + jr c,qview_parent_loop + ; обрезать длинную строку + ldi ; скопировать "X:\" + ldi + ldi + sub (qview_max_name-5)+3 ; длина остатка пути + длина "X:\" + ld c,a + add hl,bc ; на начало макс. длинной строки + ld a,"." ; .. + ld (de),a + inc de + ld (de),a + inc de + ld bc,qview_max_name-5 ; минус длину строки "X:\.." +qview_parent_loop: + ld a,(hl) + ldi + ret po ; весь путь скопирован + or a + jr nz,qview_parent_loop + push de + pop ix ; буфер + ld b,c + jp spaces ; дописать хвостовые пробелы + + + + +;--------------------------------------------------------------------- +; Вывод 32-х битных чисел в буфер, в десятичном формате с +; разделением разрядов запятой и ведущими пробелами +;--------------------------------------------------------------------- +; in: hl' = ст. разряд +; hl = мл. разряд +; ix = буфер +;--------------------------------------------------------------------- +decimal32: + ld de,0CA00h + exx + ld de,3B9Ah ; 1.000.000.000 + exx + ld iy,tmp2__ + res 7,(iy+0) + call GetN32 + call print_comma1 + ld de,0E100h + exx + ld de,05F5h ; 100.000.000 + exx + call GetN32 + ld de,9680h + exx + ld de,98h ; 10.000.000 + exx + call GetN32 +decimal24: + ld de,4240h + exx + ld de,0Fh ; 1.000.000 + exx + call GetN32 + call print_comma1 + ld de,86A0h + exx + ld de,1 ; 100.000 + exx + call GetN32 +decimal16: + ld de,10000 + exx + ld de,0 ; 10.000 + exx + call GetN32 + ld de,1000 ; 1.000 + call GetN16 + call print_comma1 + ld de,100 ; 100 + call GetN16 + ld de,10 ; 10 + call GetN16 + ld a,l + add a,"0" + jr GetN163 + +tmp2__: db 0 + +GetN32: ld a,2Fh + and a +GetN321:inc a + sbc hl,de + exx + sbc hl,de + exx + jp nc,GetN321 + add hl,de + exx + adc hl,de + exx + jr GetN160 + ; +GetN16: ld a,2Fh + and a +GetN161:inc a + sbc hl,de + jp nc,GetN161 + add hl,de +GetN160:cp "0" + jr z,GetN162 + set 7,(iy+0) +GetN162:bit 7,(iy+0) + jr nz,GetN163 + ld a," " ; ведущий пробел +GetN163:ld (ix+0),a ; сохр. в буфере + inc ix + ret + +; разделитель разрядов +print_comma1: + ld a,"," + jr nz,prn_com__ + ld a," " +prn_com__: + ld (ix+0),a + inc ix + ret + + + + + +;----------------------------------------------------------- +; Динамический вывод акт. панели в пассивной +; выход: NZ - сменить сост. key-бара +;----------------------------------------------------------- +dinam_qview_panel: + call test_show_panels ; тест на режим вкл. панелей + ret z ; выкл. + ld a,(format_mode1) ; формат пасс. панели + and form_qview + ret z ; режим выкл. + ; задержка перед отработкой + ld b,60 ; 0,6 сек. +dinqview_loop: + push bc + call get_mouse_info ; чтение состояния мышки + pop bc + jr z,dinqview_next ; кнопки не нажаты + ld a,h + cp 28 ; Y коорд. мышки + jr nc,dinqview_res_flag + jr dinqview_set_flag +dinqview_next: + push bc + ld a,3 ; опрос клавы + rst 20h + ex af,af' + ld a,b + pop bc + and 11110000b ; нажаты Ctrl,Alt,Shift ? + ret nz ; да + ex af,af' + jr nz,dinqview_exit ; есть символ + halt + djnz dinqview_loop + db 3Eh ; ld a,.. +dinqview_flag: + db true ; флаг необх. отработки "dinam_qview_panel" + or a + ret z ; не отрабатывать + call get_qview_data ; заполнить описатель +; jr c,dinqview_file ; указатель на файле + call change_panel + call draw_half_frame ; очистить панель + call upath6_ ; вывести заполн. описатель + call change_panel +dinqview_res_flag: + xor a ; false + jr $+4 +dinqview_set_flag: + ld a,true + ld (dinqview_flag),a +dinqview_exit: + xor a ; Z-флаг + ret + + + + +; Вывести содержимое файла в пасс. панели +;dinqview_file: +; call change_panel +; call draw_half_frame ; очистить панель +; ld hl,title_qview ; описатель одного титла +; call draw_text +; call change_panel +; call alt_file_viewer ; вывести содерж. файла +; jr dinqview_res_flag ; сбр. флаг отработки "dinqview" + + + + + +;------------------------------------------------- +; Подсчитать размер папки +; вход: hl=начало записи +;------------------------------------------------- +qview_scan_folder: + push hl + push hl + ld hl,win_scan_folder ; описатель "Scanning the folder..." + call WinSimple ; открыть окно + pop hl + call scan_folder ; сканир. папку + call CloseWinSimple ; закрыть окно + ld a,1 ; очистить буфер клавы + rst 20h + pop hl + ret + +;------------------------------------------------- +; Сканирование папки акт. панели +; вход: hl=начало записи +;------------------------------------------------- +scan_folder: + xor a ; режим "простое сканир. папки" +scan_folder_alt: + ld (scan_mode),a ; режим работы процедуры + ; скопир. путь панели во врем. буфер + push hl + ld hl,(__buff) ; откуда, адрес пути акт. панели + ld de,work_buffer ; куда + ld a,(disk) ; диск панели + add a,"A" + ld (de),a + inc de + ld a,":" + ld (de),a + inc de + call copy_string ; (hl) -> (de) до нуля + pop hl + ld a,(hl) + cp "." ; ".." ? + jr z,scan_fold1 ; только путь родит. папки + ; создать новый путь + push hl + ex de,hl + dec hl + dec hl + ld a,'\' + cp (hl) + jr z,$+3 + inc hl + ld (hl),a + inc hl + ex de,hl ; de=куда + pop hl ; откуда + ld bc,0044h ; 11 -> 8.3 + rst 10h +scan_fold1: + ld hl,work_buffer + ld c,1Dh ; уст. путь + rst 10h + jp ScanTree ; сканир. папку diff --git a/MOD2/READDSK.ASM b/MOD2/READDSK.ASM new file mode 100755 index 0000000..39bdd69 --- /dev/null +++ b/MOD2/READDSK.ASM @@ -0,0 +1,157 @@ +;----------------------------------------------------------- +; Заполнить банку каталога + размер файлов списка +; выход: CF - ошибка чтения диска +;----------------------------------------------------------- +read_new_folder: + call read_new_list ; заполнить банку новым списком + размер файлов + ret c + ld a,(format_mode) ; формат акт. панели + and form_trd + ;jp z,msdos_scan_folder ; сканир. папку -> scan_folder ? + ret z + ;------------------------------------------------------------- + ; Вычислить объем файлов спек-имиджа (инфа из 9-го сектора) + ;------------------------------------------------------------- + ld a,(cash_left_dir) ; номер банки каталога акт. панели + out (SLOT3),a ; подкл. страницу каталога + ; весь объем диска + ld hl,0Ah ; 655,360 (000A:0000) + ld (total_space_disk+2),hl ; ст. разряд + ld hl,0 + ld (total_space_disk),hl ; мл. разряд + ; расчитать общ. размер файлов + exx + ld bc,16 ; размер trd-записи + ld hl,0 ; ст. разряд + exx + ld hl,0 ; мл. разряд + ld ix,0C000h+11 ; ячейка размера файла + ld bc,(all_files) ; число файлов диска +spec_scan_loop: + ld e,(ix+0) + ld d,(ix+1) + add hl,de ; мл.разряд + exx + ld de,0 + adc hl,de ; ст.разряд + add ix,bc ; на след. запись + exx + dec bc ; --число файлов + ld a,c + or b + jr nz,spec_scan_loop + exx + ld (files_size+2),hl ; ст.разряд + exx + ld (files_size),hl ; мл. разряд + ; расчитать своб. место на диске + ld de,(total_space_disk) ; мл.разряд + ex de,hl + sbc hl,de + ld (free_space_disk),hl + exx + ld de,(total_space_disk+2) ; ст.разряд + ex de,hl + sbc hl,de + ld (free_space_disk+2),hl + exx + ret + + +;------------------------------------------------- +; Сканирование папки и подсчет ее размера +;------------------------------------------------- +;msdos_scan_folder: ; <- заменить на scan_folder ? + ;call get_record + ;jp scan_folder + ;ret + + + + +;------------------------------------------------- +; Заполнить банку списком нового каталога +; выход: CF - ошибка уст. диска/пути +;------------------------------------------------- +read_new_list: + call set_path_from_activ_panel ; уст. диск и путь от акт. панели + jr nc,read_nlist + inc a + scf + ret z ; нет диска + ; нет данного пути + ld hl,(__buff) ; адрес пути акт. панели + ld (hl),'\' ; корень в путь акт. панели + inc hl + ld (hl),0 + dec hl + ld c,1Dh ; смена тек. каталога + rst 10h + ret c ; ошибка +read_nlist: + xor a + ld l,a + ld h,a + ; сбр. ячейки + ld (files_size),hl ; общ. размер файлов в списке + ld (files_size+2),hl + ld (all_folders),hl ; число папок в списке + ld (all_files),hl ; число записей в списке акт. панели + ld (cur_pointer),hl ; тек. полож. указателя + ld (offset_list),hl ; смещ. списка + ld (mark_files),hl ; число выдел. файлов + ld (low_size),hl ; мл. разряд размера выдел. файлов + ld (high_size),hl ; ст. разряд + ld h,0C0h ; hl=0C000h + ld (copy_rec_addr),hl + ; + ld hl,(__mask) ; "*.*" маска имён файлов + ld bc,0019h ; найденное имя в 11 симв. формате +read_nlist_loop: + ld de,work_buffer ; куда + ld a,37h ; все, кроме метки тома + rst 10h + ccf + ret nc ; больше нет записей + call copy_record ; скопир. запись в банку каталога + ld c,1Ah ; поиск след. + jr read_nlist_loop + + +; Скопир. запись в банку каталога +copy_record: + ld a,(cash_left_dir) ; номер банки каталога акт. панели + out (SLOT3),a ; подкл. стр. каталога + ld hl,work_buffer+33 ; откуда + ld a,"." + cp (hl) + jr nz,copy_record1 + inc hl + cp (hl) + ret nz ; "." тек. запись + dec hl +copy_record1: + db 11h ; ld de,.. +copy_rec_addr: + dw 0C000h ; куда (тек. адрес) + ld bc,11 + ldir ; имя файла + ld hl,work_buffer+32 ; откуда + ldi ; атрибут записи + ld hl,work_buffer+12 ; откуда + ld bc,20 + ldir + ld (copy_rec_addr),de + ld hl,(all_files) + inc hl ; ++число записей в списке + ld (all_files),hl + ; новый общий размер файлов (total_file_size + found file_size) + ld hl,(work_buffer+28) ; мл. разряд + ld de,(files_size) + add hl,de + ld (files_size),hl + ld hl,(work_buffer+30) ; ст. разряд + ld de,(files_size+2) + adc hl,de + ld (files_size+2),hl + ret diff --git a/MOD2/RENAME.ASM b/MOD2/RENAME.ASM new file mode 100755 index 0000000..92fe136 --- /dev/null +++ b/MOD2/RENAME.ASM @@ -0,0 +1,106 @@ +;=========================================================== +; +; Процесс переименования файла/папки +; +;=========================================================== +rename: call test_show_panels ; тест на режим вкл. панелей + ret z + call get_fire ; защита от "залипания" бутонов + ld a,(format_mode) ; тек. формат панели + and form_info+form_qview ; info, qview + ret nz + call set_path_from_activ_panel ; уст. диск и путь акт. панели + ret c + call prep_rename_name ; имя файла в описатель окна + ret c ; ".." запись + ; вывод начального окна + ld hl,dial_rename ; описатель окна + call DialogW + cp evCommand ; событие "команда" + ret nz + ld a,(hl) ;+1 what + cp cmOkey ; "Ok" + ret nz + ; переименование файла + ld hl,temp_fname ; старое имя + ld de,input_line_rename+5 ; новое имя + ld c,10h ; переимен. файл + rst 10h + jp nc,fresh_two_panels ; без ошибок, обновить панели + ; + ; вывод окна ошибки переименования + ld hl,dial_error_rename ; "Cannot rename the file or folder" + jp DialogEr + + + +; Скопировать тек. имя переимен. файла/папки в описатель окна. +; Обработка макс. одной выдел. записи +; выход: hl=адрес записи +prep_rename_name: + ld de,(mark_files) ; число выдел. файлов + ld hl,1 + sbc hl,de + ret c ; >= 2 выдел. файлов + jr z,prep_ren_name1 ; есть один выдел. файл + ; нет выдел. файлов + call get_record ; запись в тек. положении указателя + ld a,(hl) + cp "." ; ".." + scf + ret z + jr $+5 +prep_ren_name1: + call scan_mark_records ; поиск отмеч. файла (с начала списка) + ; вход: hl=запись файла + ld bc,rename_name1 ; куда (буфер 12 байт) + push hl + call copy_cur_fname ; скопир. имя файла и отцентровать + pop hl + ; hl=откуда + ld de,temp_fname ; куда + ld bc,0044h ; 11 -> 8.3 + rst 10h + ; очистить структуру буфера + ld hl,input_line_rename ; структура буфера + call clear_struct_inline + ; вставить имя в структуру буфера + ld iy,input_line_rename ; структура буфера + ld de,temp_fname ; откуда + ld hl,input_line_rename+5 ; куда +prep_ren_loop: + ld a,(de) + or a + ret z + call put_char1 ; вставить символ + inc de + inc hl + jr prep_ren_loop + + +; Вставить символ в буфер структуры +; вход: iy=структура буфера +; hl=куда +; a=символ +put_char1: + push hl + push iy + pop hl ; структура буфера + ex af,af' ; сохр. символ + ld a,(iy+2) ; X тек. полож. курсора в строке + add a,(iy+3) + add a,l + ld l,a + jr nc,$+3 + inc h + inc hl + inc hl + inc hl + inc hl + inc hl + ex af,af' + ld (hl),a ; символ в ком-строку + pop hl + inc (iy+4) ; число введ. символов + inc (iy+2) ; X тек. полож. курсора в строке + ret diff --git a/MOD2/SETUP.ASM b/MOD2/SETUP.ASM new file mode 100755 index 0000000..16909a7 --- /dev/null +++ b/MOD2/SETUP.ASM @@ -0,0 +1,523 @@ +; Если переменная окружения найдена, ini-файл читается/записывается +; только в ней. +; Если переменной окружения нет, ini-файл читается/записывается по +; текущему пути менеджера. +; +; Если ini-файл не найден - в панелях устанавливается диск и текущий +; путь менеджера. Если ini-файл найден, диски и пути панелей устанав- +; ливаются согласно данных ini-файла. +; + + + + + + + +; +; Структура ini-файла: +; +; +0 - Флаг активной панели (0=левая, 80h=правая) +; +1 - Номер диска левой панели (0=A,1=B,..) +; +2 - Номер диска правой панели (0=A,1=B,..) +; +3 - Раскраска файлов (true/false) +; +4 - Флаг скрытия мышки при работе с клавой (true/false) +; Режим сортировки левой панели: +; +5 - n/x/d/s/u (name/ext/date/size/unsort) +; +6 - 0=, 1= (восходящая/нисходящая) +; Режим сортировки правой панели: +; +7 - n/x/d/s/u (name/ext/date/size/unsort) +; +8 - 0=, 1= (восходящая/нисходящая) +; +9 - Формат левой панели: full/med/brief/info/qview +; +10 - Формат правой панели: full/med/brief/info/qview +; +11 - Флаг вывода букв режима сортировки (true/false) +; +12 - Флаг вывода строки суммарной информации (true/false) +; +13 - Смещение курсора вниз при выделении файлов (true/false) +; +14 - Флаг вывода часов вверху правой панели (true/false) +; +15 - Флаг подтверждения выхода из менеджера (true/false) +; +16 - Флаг отметки папок (true/false) +; +17 - Флаг временного просмотра сист. экрана по Esc (true/false) +; +18 - Флаг отработки Home/End в ком-строке при открытых панелях (false/true) +; ;+19 - Флаг вывода общей линейки процесса копирования (false/true) +; +20 - резерв +; +21 - резерв +; +22 - резерв +; +; +23 - Массив цветов менеджера (color_array), 66 байт +; +; +88 - Флаг подтверждения перезаписи при копировании (Copy) +; +89 - Флаг подтверждения перезаписи при перемещении (Move) +; +90 - Флаг подтверждения при удалении (Delete) +; +91 - Флаг подтверждения удаления не пустых папок (Delete non-empty folders) +; +92 - резерв +; +93 - резерв +; +94 - резерв +; +95 - резерв +; +; +96 - Путь левой панели (256 байт) +; +353 - Путь правой панели (256 байт) +; + + + +block1 equ 23 ; ячейки 1-го блока настроек +block2 equ 8 ; ячейки 2-го блока + +size_ini_part1 equ block1+len_color_array+block2 ;97 байт (настройки FM) + + + +;----------------------------------------------------------- +; Настроить опциональные ячейки менеджера +; и установить диски и пути панелей. +; вход: заполненный work_buffer, при наличии ini-файла +;----------------------------------------------------------- +init_option_cells: + ; флаг наличия ini-файла + db 3Eh ; ld a,.. +enable_ini_file: + db false + or a + jr nz,yes_ini__ + ;-------------------------------- + ; нет ini-файла + ;-------------------------------- + ; использовать цвета по-умолчанию + ld hl,default_colors ; откуда + ld de,color_array ; куда + ld bc,len_color_array + ldir + ; уст. одинаковые диски в панелях + ld c,2 ; получить номер тек. диска + rst 10h + ld (disk),a ; номер диска акт. панели + ld (disk1),a ; номер диска пасс. панели + ; уст. одинаковые пути в панелях + ld hl,buff_left ; буфер пути левой панели + ld c,1Eh ; получить тек. путь + rst 10h + ld hl,buff_left ; путь левой панели + ld de,buff_right ; путь правой панели + jp copy_string ; скопир. строку до нуля (с нулем) + +yes_ini__: + ;---------------------------------------- + ; Использовать настройки из ini-файла + ;---------------------------------------- + ; Уст. активную панель + ld de,panel_left+1 + ld hl,panel_right+1 + ld a,(work_buffer) ;+0 из ini-файла (0=левая, 80h=правая) + or a + ld a,0 + jr z,$+3 + ex de,hl + ld (de),a ; X полож. одной панели + ld (hl),40 ; X полож. другой панели + inc de + inc hl + ld (de),a ; cur_panel + ld (hl),80h ; cur_panel др.панели + ; Уст. диски панелей + ld a,(work_buffer+1) + ld (disk),a ; диск акт. панели + ld a,(work_buffer+2) + ld (disk1),a ; диск пасс. панели + ; Раскраска файлов + ld a,(work_buffer+3) + ld (hilight_enable),a + ; Прятать мышку при работе с клавой + ld a,(work_buffer+4) + ld (hidden_mouse),a ; флаг (в 0-й стр. ФМ, уже включена) + ; Режимы сортировок панелей + ; l=n/x/d/s/u (name/ext/date/size/unsort) + ; h=0/1 (00=, 01=) + ld hl,(work_buffer+5) + ld (sort_type),hl ; акт. + ld hl,(work_buffer+7) + ld (sort_type1),hl ; пасс. + ; Форматы панелей + ld a,(work_buffer+9) ; full/med/... + ld (format_mode),a ; акт. + ld a,(work_buffer+10) + ld (format_mode1),a ; пасс. + ; Флаг вывода буквы режима сортировки + ld a,(work_buffer+11) ; true/false + ld (sort_char_flag),a ; флаг + ; Флаг вывода суммарной информации (внизу панелей) + ld a,(work_buffer+12) ; false/true + ld (flag_summary_info),a ; флаг + ; Смещение курсора вниз при выделении файлов + ld a,(work_buffer+13) + ld (enable_down_mark),a ; флаг + ; Флаг вывода часов + ld a,(work_buffer+14) + ld (clock__+1),a ; тек. сост. режима вывода + ld (enable_clock),a ; флаг + ; Флаг подтверждения выхода из менеджера + ld a,(work_buffer+15) + ld (confirm_quit),a + ; Флаг отметки папок + ld a,(work_buffer+16) + ld (mark_folders),a + ; Флаг врем. просмотра сист. экрана по Esc + ld a,(work_buffer+17) + ld (flag_esc),a + ; Флаг отработки Home/End в ком-строке при откр. панелях + ld a,(work_buffer+18) + ld (move_home_end),a + ; Флаг подтверждения перезаписи при копировании (Copy) + ld a,(work_buffer+88) + ;ld (),a + ;ld (confirm_ceil0),a + ; Флаг подтверждения перезаписи при перемещении (Move) + ld a,(work_buffer+89) + ;ld (),a + ;ld (confirm_ceil1),a + ; Флаг подтверждения при удалении (Delete) + ld a,(work_buffer+90) + ld (del_confirm),a + ld (confirm_ceil2),a + ; Флаг подтверждения удаления не пустых папок (Delete non-empty folders) + ld a,(work_buffer+91) + ld (flag_del_non_empty),a + ld (confirm_ceil3),a + ; Настроить цвета менеджера + ld hl,work_buffer+23 ; начало цвет. массива в ini-файле + ld de,color_array ; массив цветов менеджера + ld bc,len_color_array + ldir + ret + + + + + +;------------------------------------------------- +; Чтение ini-файла +;------------------------------------------------- +read_ini_file: + ; проверить переменную окружения Far-а + ld bc,0146h ; получить переменную окружения + ld hl,env_name ; имя переменной + ld de,work_buffer ; буфер для значения переменной + rst 10h + jr c,no_ini_string ; ошибка + or a + jr nz,read_ini_file__ ; переменная найдена + ; исп. текущий сист. путь + ld hl,save_path ; откуда + ld de,work_buffer ; куда + call copy_string ; скопир. строку + dec de + dec de + ld a,(de) + cp '\' + jr z,$+3 + inc de +read_ini_file__: + push de ; конец строки переменной окружения + ld hl,name_ini_file ; имя ini-файла + ld bc,len_ini_name + ldir ; к диск+путь + имя ini-файла + ; найти файл + ld hl,work_buffer ; имя файла (диск+путь) + ld de,work_buffer+127;255 ; буфер + ld bc,0119h + ld a,20h ; "архивный" + rst 10h + pop de ; конец строки переменной окружения + jr nc,found_ini_file ; файл найден +no_ini_string: + xor a ; false + ld (enable_ini_file),a ; флаг наличия ini-файла + jr ini_done + ; +found_ini_file: + ld hl,work_buffer ; полное имя файла (диск+путь+имя) + ld a,1 ; на чтение + ld c,11h ; открыть файл + rst 10h + jr c,no_ini_string ; ошибка открытия + ld (handle_ini_file),a ; сохр. дескриптор + ; прочитать настройки менеджера + ld hl,work_buffer ; буфер под данные + ld de,size_ini_part1 ; число читаемых байт + ld c,13h ; чтение файла + rst 10h + jr c,read_ini_error + ; прочитать пути левой и правой панелей + ld hl,buff_left ; буфер под данные + ld de,256+256 ; 512 число читаемых байт + ld a,(handle_ini_file) ; дескриптор + ld c,13h ; чтение файла + rst 10h + ld a,true + jr nc,read_ini_ok ; без ошибок +read_ini_error: + xor a +read_ini_ok: + ld (enable_ini_file),a ; флаг наличия ini-файла +close_ini_file: + db 3Eh +handle_ini_file: + db -1 + ld c,12h ; закрыть файл + rst 10h +ini_done: +restore_sys_path: + ld a,(save_disk) + ld c,1 ; уст. диск + rst 10h + ret c + ld hl,save_path + ld c,1Dh ; уст. каталог + rst 10h + ret + + + + +env_name: + db "FM",0 ; имя переменной окружения + +name_ini_file: + db '\FM.INI',0 ; имя ini-файла + +len_ini_name equ $ - name_ini_file + + + +name_mnu_file: + db '\FM.MNU',0 ; файл Меню Пользователя + +len_mnu_name equ $ - name_mnu_file + + + + + +;------------------------------------------------------------------ +; Запись настроек в ini-файл (97+256+256=609 байт). +; Если переменная окружения не найдена - запись производится +; в текущем пути. +;------------------------------------------------------------------ +write_ini_file: + ld hl,show_pointer ; начальный вывод указателя + push hl + call clear_pointer ; скрыть указатель + ; проверить переменную окружения Far`а + ld bc,0146h ; получить переменную окружения + ld hl,env_name ; имя переменной + ld de,work_buffer ; буфер для значения переменной + rst 10h + ret c ; ошибка + or a + jr nz,write_ini_file__ ; переменная найдена + ; исп. текущий сист. путь + ld hl,save_path ; откуда + ld de,work_buffer ; куда + call copy_string ; скопир. строку + dec de + dec de + ld a,(de) + cp '\' + jr z,$+3 + inc de +write_ini_file__: + ld hl,name_ini_file ; имя ini-файла + ld bc,len_ini_name + ldir ; диск+путь + имя ini-файла + ld hl,work_buffer ; полное имя файла (диск+путь+имя) + ld a,20h ; "архивный" + ld c,0Ah ; создать файл + rst 10h + jr c,ini_done ; ошибка создания + ld (handle_ini_file),a ; сохр. дескриптор + ; + call prep_ini_buffer ; заполнить ini-буфер + ; + ; записать настройки менеджера + ld hl,work_buffer ; буфер данных + ld de,size_ini_part1 ; 97 число запис. байт + ld a,(handle_ini_file) ; дескриптор + ld c,14h ; запись файла + rst 10h + jr c,close_ini_file ; закрыть файл + ; записать путь левой панели + ld hl,(__buff) ; адрес строки левой панели + ld de,256 ; число запис. байт + ld a,(handle_ini_file) ; дескриптор + ld c,14h ; запись файла + rst 10h + jr c,close_ini_file ; закрыть файл + ; записать путь правой панели + ld hl,(__buff1) ; адрес строки правой панели + ld de,256 ; число запис. байт + ld a,(handle_ini_file) ; дескриптор + ld c,14h ; запись файла + rst 10h + jp close_ini_file ; закрыть файл + + + +;------------------------------------------------- +; Подготовить буфер для записи в ini-файл +;------------------------------------------------- +prep_ini_buffer: + ; Активная панель + ld a,(cur_panel) ; 0=левая, 80h=правая + ld (work_buffer),a ;+0 + ;or a + ; корректно скопировать панеле-зависимые ячейки + ;push af + ;call nz,change_panel + call prep_ini_buffer1 + ;pop af + ;call nz,change_panel + ; + ; Раскраска файлов + ld a,(hilight_enable) + ld (work_buffer+3),a + ; Прятать мышку при работе с клавой + ld a,(hidden_mouse) ; флаг (в 0-й стр. ФМ) + ld (work_buffer+4),a + ; Флаг вывода буквы режима сортировки + ld a,(sort_char_flag) + ld (work_buffer+11),a + ; Флаг вывода суммарной информации (внизу панелей) + ld a,(flag_summary_info) + ld (work_buffer+12),a + ; Смещение курсора вниз при выделении файлов + ld a,(enable_down_mark) + ld (work_buffer+13),a + ; Флаг вывода часов + ld a,(enable_clock) + ld (work_buffer+14),a + ; Флаг подтверждения выхода из менеджера + ld a,(confirm_quit) + ld (work_buffer+15),a + ; Флаг отметки папок + ld a,(mark_folders) + ld (work_buffer+16),a + ; Флаг врем. просмотра сист. экрана по Esc + ld a,(flag_esc) + ld (work_buffer+17),a + ; Флаг отработки Home/End в ком-строке при откр. панелях + ld a,(move_home_end) + ld (work_buffer+18),a + ; Флаг подтверждения перезаписи при копировании (Copy) + ;ld a,() + ld (work_buffer+88),a + ; Флаг подтверждения перезаписи при перемещении (Move) + ;ld a,() + ld (work_buffer+89),a + ; Флаг подтверждения при удалении (Delete) + ld a,(del_confirm) + ld (work_buffer+90),a + ; Флаг подтверждения удаления не пустых папок (Delete non-empty folders) + ld a,(flag_del_non_empty) + ld (work_buffer+91),a + ; Перекачать массив цветов менеджера + ld hl,color_array + ld de,work_buffer+23 ; начало цвет. массива в ini-файле + ld bc,len_color_array + ldir + ret + + +; Копирование в ini-буфер панеле-зависимых ячеек +prep_ini_buffer1: + ; Номер диска акт. панели + ld a,(disk) + ld (work_buffer+1),a + ; Номер диска пасс. панели + ld a,(disk1) + ld (work_buffer+2),a + ; Режимы сортировок панелей + ld hl,(sort_type) ; акт. + ld (work_buffer+5),hl + ld hl,(sort_type1) ; пасс. + ld (work_buffer+7),hl + ; Форматы панелей + ld a,(format_mode) ; акт. + ld (work_buffer+9),a + ld a,(format_mode1) ; пасс. + ld (work_buffer+10),a + ret + + + + + + + +array_read equ 0C000h ; буфер mnu-файла + +;------------------------------------------------- +; Чтение файла fm.mnu +;------------------------------------------------- +read_mnu_file: + ; проверить переменную окружения Far-а + ld bc,0146h ; получить переменную окружения + ld hl,env_name ; имя переменной + ld de,work_buffer ; буфер для значения переменной + rst 10h + jr c,no_mnu_string ; ошибка + or a + jr nz,read_mnu_file__ ; переменная найдена + ; исп. текущий сист. путь + ld hl,save_path ; откуда + ld de,work_buffer ; куда + call copy_string ; скопир. строку + dec de + dec de + ld a,(de) + cp '\' + jr z,$+3 + inc de +read_mnu_file__: + push de ; конец строки переменной окружения + ld hl,name_mnu_file ; имя mnu-файла + ld bc,len_mnu_name + ldir ; к диск+путь + имя mnu-файла + ; найти файл + ld hl,work_buffer ; имя файла (диск+путь) + ld de,work_buffer+127;255 ; буфер + ld bc,0119h + ld a,20h ; "архивный" + rst 10h + pop de ; конец строки переменной окружения + jr nc,found_mnu_file ; файл найден +no_mnu_string: + xor a ; false + ld (enable_mnu_file),a ; флаг наличия mnu-файла + jr mnu_done + ; +found_mnu_file: + ld hl,work_buffer ; полное имя файла (диск+путь+имя) + ld a,1 ; на чтение + ld c,11h ; открыть файл + rst 10h + jr c,no_mnu_string ; ошибка открытия + ld (handle_mnu_file),a ; сохр. дескриптор + ; прочитать файл + ld hl,array_read ; 0C000h буфер под данные + ld de,73*52 ; 3796 макс. число читаемых байт + ld c,13h ; чтение файла + rst 10h + ld a,true + jr nc,read_mnu_ok ; без ошибок + xor a +read_mnu_ok: + ld (enable_mnu_file),a ; флаг наличия mnu-файла + ld hl,array_read + add hl,de + ld (hl),0 ; в конец файла + db 3Eh ; ld a,.. +handle_mnu_file: + db -1 + ld c,12h ; закрыть файл + rst 10h +mnu_done: + jp restore_sys_path ; восст. тек. путь diff --git a/MOD2/SPACE.ASM b/MOD2/SPACE.ASM new file mode 100755 index 0000000..1674369 --- /dev/null +++ b/MOD2/SPACE.ASM @@ -0,0 +1,141 @@ +;----------------------------------------------------------- +; Вычислить свободное место на 2 дисках панелей +;----------------------------------------------------------- +get_total_free_space: + ; акт. панель + ld hl,free_space_disk ; ячейки акт. панели + ld a,(format_mode) ; формат акт. панели + ld b,a + ld a,(disk) ; диск акт. панели + ld c,a + push bc + call get_free_space ; своб. место на диске + pop bc + ld a,(disk1) ; диск пасс. панели + cp c ; диски на панелях равны ? + jr nz,get_free_noact ; нет + ld hl,free_space_disk ; ячейки акт. панели + ld de,free_space_disk1 ; ячейки пасс. панели + ld bc,4 + ldir + ret + ; +get_free_noact: + ; пасс. панель + ld c,a ; номер диска + ld a,(format_mode1) ; формат пасс. панели + ld b,a + ld hl,free_space_disk1 ; ячейки пасс. панели +;------------------------------------------------- +; Вычислить свободное место на диске +; вход: c=номер диска (A=0, B=1,...) +; b=формат панели +; hl=ячейки "free_space_disk" панели +;------------------------------------------------- +get_free_space: + ld a,(flag_summary_info) ; флаг вывода суммарной инфы + or a + ret z ; false + bit 6,b ; спек-формат + ret nz + ; вывести окно "Calculating free space..." + push bc + push hl + ld hl,win_free_disk ; описатель окна + call WinSimple ; вывести окно + pop hl + pop bc + ld a,c + push hl + bit 6,b ; спек-формат + jr nz,get_free_spec +;---------------------------------------------------- +; Вычислить своб. место на MS-DOS диске +;---------------------------------------------------- + ld c,3 ; инфа о диске + rst 10h + jr nc,get_free_ok + ld bc,0 + ld e,c + ld d,c + jr get_free__ + ; +get_free_ok: + ; a=размер кластера в секторах + ; bc=размер сектора в байтах + ; de=своб. кластеров + push de + ld hl,0 + add hl,bc ; вычислить размер кластера + dec a + jr nz,$-2 + ex de,hl ; de=размер кластера + pop bc ; своб. кластеров + call mul_bcde ; bc*de=hlbc своб. место + ex de,hl +get_free__: + pop hl + ; мл.разряд + ld (hl),c ; hl=free_space_disk (free_space_disk1) + inc hl + ld (hl),b + inc hl + ; ст.разряд + ld (hl),e + inc hl + ld (hl),d + ; закрыть окно "Calculating free space..." + jp CloseWinSimple + + + +;---------------------------------------------------- +; Вычислить своб. место на спектрумовском диске +; (отделить trd-формат от scl-формата) +; (655,360 байт trd-диска) +; вход: hl уже в стеке +; a=номер диска +;---------------------------------------------------- +get_free_spec: + ; вычислить число своб. кластеров + ; ... + ; + ld de,640; ; своб. кластеров + ; + ld a,1 ; размер кластера в секторах + ld bc,1024 ; размер сектора в байтах + jr get_free_ok ; заполнить строку + + + + + + +;----------------------------------------------------------- +; Обновление списка панели при навигации по папкам +;----------------------------------------------------------- +fresh_list_panel: + call read_new_folder ; новый список каталога + размер папки + ret c + call sorting ; раздельный список указателей + сорт. списка +fresh_list_pan: + ; вычислить своб. место диска + ld hl,free_space_disk ; ячейки акт. панели + ld a,(format_mode) + ld b,a + ld a,(disk) + ld c,a + db 3Eh ; ld a,.. +enter_to_folder: + db false ; флаг "навигация по папкам" + or a + call z,get_free_space + db 21h ; ld hl,.. +fresh_list_point: + dw 0 ; сохр. полож. указателя + ld (cur_pointer),hl ; тек. полож. указателя + db 21h ; ld hl,.. +fresh_list_offset: + dw 0 ; сохр. смещ. списка + ld (offset_list),hl ; смещение списка + jp A20FC ; вывод панели diff --git a/MOD2/UTILS.ASM b/MOD2/UTILS.ASM new file mode 100755 index 0000000..41bbb67 --- /dev/null +++ b/MOD2/UTILS.ASM @@ -0,0 +1,360 @@ +max_width_dest equ 34 ; размер буфера строки описателей + + + +;-------------------------------------------------------------- +; Сравнение путей (и дисков) двух панелей +; выход: Z - равны +; NZ - не равны +;-------------------------------------------------------------- +compare_path_two_panels: + ; сравнить диски + ld a,(disk) ; диск акт. панели + ld hl,disk1 ; диск пасс. панели + cp (hl) + ret nz + ; сравнить пути + ld hl,(__buff) ; путь акт. панели + ld de,(__buff1) ; путь пасс. панели +comp_path_two_pan: + ld a,(de) + cp (hl) + ret nz + inc de + inc hl + ld a,(de) + or a + jr nz,comp_path_two_pan + cp (hl) + ret + + + + +;-------------------------------------------------------------- +; Поиск отмеченной записи в списке панели +; (поиск идет с начала списка) +; выход: hl=найденная запись +; de=ячейка атрибута записи +; a=атрибут записи +; "Carry" - не нашли запись +;-------------------------------------------------------------- +scan_mark_records: + ld bc,(all_files) ; число записей списка + inc bc + ld hl,0 ; начать с начала списка + ld (scan_mark_numb+1),bc + ld (scan_mark_loop+1),hl +scan_mark_loop: + ld hl,0 ; след. положение в списке +scan_mark_numb: + ld bc,0 ; число оставшихся записей в списке + push hl + call get_record1 ; сканир. список панели + ld (scan_mark_rec+1),hl + ld (attr_record),a ; атрибут файла (глоб. ячейка) + inc de + pop hl + inc hl ; на след. запись + dec bc + ld (scan_mark_loop+1),hl + ld (scan_mark_numb+1),bc + ld a,c + or b + scf + ret z ; конец списка + ld a,(de) ;+12 ячейка отметки + and 80h + jr z,scan_mark_loop ; запись не отмечена + ; нашли запись +scan_mark_rec: + ld hl,0 ; адрес записи + dec de + ld a,(de) ;+11 атрибут файла + or a ; сбр. "Carry" + ret + + + + + + +;----------------------------------------------------------- +; Ограничение набранной строки первыми 34-мя символами +; с центровкой. +; вход: hl=буфер ввода ~input line~ +; de=куда +;----------------------------------------------------------- +copy_dest_name: + push hl + push de + ; очистить строку описателя + ld b,max_width_dest ; 34 размер буфера + ld a," " + ld (de),a + inc de + djnz $-2 + xor a + ld (width_dest1__),a ; сбр. флаг переполн. строки + dec hl + ld a,(hl) ;+4 длина введ. строки + cp max_width_dest+1 ; 34+1 + jr c,$+7 ; длина пути =< 32 + ld a,max_width_dest ; 34 + ld (width_dest1__),a ; уст. флаг переполн. строки +width_dest__: + ld c,a + ; центровка имени + ld a,max_width_dest ; 34 ширина буфера строки + sub c + srl a ; /2 + ld e,a + ld d,0 + ld b,d + pop hl ; куда + add hl,de + ex de,hl ; de=начало строки в описателе + pop hl ; откуда + ; скопир. строку + ld a,(hl) + cp "a" + jr c,$+4 + res 5,a ; a..z -> A..Z + ld (de),a + inc hl + inc de + dec bc + ld a,c + or b + jr nz,$-13 + db 3Eh ; ld a,.. +width_dest1__: + db false + or a + ret z + ; записать концевые ".." + dec de + dec de + ld a,"." + ld (de),a + inc de + ld (de),a + ret + + + +;------------------------------------------------- +; Скопировать исходное имя файла/папки "file.ext" +; в строку описателя окна. +; вход: bc=куда +; выход: CF - ".." текущая запись +;------------------------------------------------- +copy_source_name: + ld hl,(mark_files) ; число выдел. файлов + ld a,l + or h + ret nz + call get_record ; тек. запись + ld (attr_record),a ; атрибут файла (глоб. ячейка) + ld a,(hl) ; имя файла + cp "." + scf + ret z ; текущий ".." +;----------------------------------------------------------- +; Скопировать имя файла "file.ext" и отцентровать в строке +; вход: hl=запись файла +; bc=строка описателя окна +; выход: заполненный буфер temp_fname +;----------------------------------------------------------- +copy_cur_fname: + call copyfname + ; центровка имени + ld a,12 ; буфер строки + sub c + srl a ; /2 + ld l,a + ld h,0 + ld b,h + add hl,de + ex de,hl ; de=начало строки в описателе + push bc + ld hl,work_buffer ; откуда + ldir + pop bc + ld hl,work_buffer ; откуда + ld de,temp_fname ; куда + ldir + xor a + ld (de),a + ret + + +; вход: bc=куда +; выход: CF - ".." текущая запись +copyname: + ld hl,(mark_files) ; число выдел. файлов + ld a,l + or h + ret nz + call get_record ; тек. запись + ld (attr_record),a ; атрибут файла (глоб. ячейка) + ld a,(hl) ; имя файла + cp "." + scf + ret z ; текущий ".." + call copyfname + ld hl,work_buffer ; откуда + xor a + ld b,a + push bc + ldir + ;inc hl + ld (hl),a + ex de,hl + ld (hl)," " + inc hl + ld (hl),"t" + inc hl + ld (hl),"o" + inc hl + ld (hl),":" + inc hl + pop bc + ld a,12 + sub c + ret z + ; дописать пробелы + ld (hl)," " + inc hl + dec a + jr nz,$-4 + ret + + + + +; скопир. имя файла +; вход: bc=куда (буфер 12 байт) +; hl=имя файла +; выход: c=длина имени +copyfname: + ; очистить строку описателя + push bc + ld a," " + ld d,12 + ld (bc),a + inc bc + dec d + jr nz,$-3 + ; имя в формат file.ext + ld ix,work_buffer ; врем. буфер + ld d,1 ; не менять регистр букв + bit 4,a ; атрибут файла + jr nz,$+19 ; папка + ld a,(format_mode) ; формат акт. панели + and form_trd ; 6-й бит спек-формата + jr z,$+7 + call fill_med_spec_name ; спек-имя + jr $+10 + call fill_med1__ ; "Filename.Ext" (всегда выводит 12 симв.) + jr $+5 + call dir_name_med ; вывод папки (всегда выводит 12 симв.) + ; узнать длину имени + ld a,15 ; константа + sub e + ld c,a + pop de ; куда + ret + + + + +;----------------------------------------------------------- +; Ограничение набранной строки первыми 34-мя символами +; вход: hl=буфер ввода ~input line~ +; de=куда +;----------------------------------------------------------- +copy_dstname: + push hl + push de + ; очистить строку описателя + ld b,max_width_dest ; 34 размер буфера + ld a," " + ld (de),a + inc de + djnz $-2 + xor a + ld (width_dst1__),a ; сбр. флаг переполн. строки + dec hl + ld a,(hl) ;+4 длина введ. строки + cp max_width_dest+1 ; 34+1 + jr c,$+7 ; длина пути =< 32 + ld a,max_width_dest ; 34 + ld (width_dst1__),a ; уст. флаг переполн. строки + ld c,a + ld b,0 + pop de ; куда + pop hl ; откуда + ; скопир. строку + ld a,(hl) + cp "a" + jr c,$+4 + res 5,a ; a..z -> A..Z + ld (de),a + inc hl + inc de + dec bc + ld a,c + or b + jr nz,$-13 + db 3Eh ; ld a,.. +width_dst1__: + db false + or a + ret z + ; записать концевые ".." + dec de + dec de + ld a,"." + ld (de),a + inc de + ld (de),a + ret + + + +;----------------------------------------------------------- +; Скопировать имя файла "file.ext" и отцентровать в строке +; при сканировании папки. +; вход: hl=имя файла в формате file.ext +; de=строка описателя окна +;----------------------------------------------------------- +copy_cur_fname_alt: + ; очистить строку описателя + push de + ld a," " + ld bc,0C00h ; счетчики + ld (de),a + inc de + djnz $-2 + pop de + push hl + ; узнать длину имени + ld a,(hl) + or a + jr z,$+6 + inc c ; ++длина имени + inc hl + jr $-6 + ; центровка имени + ld a,12 ; буфер строки + sub c + srl a ; /2 + ld l,a + ld h,0 + ld b,h + add hl,de + ex de,hl ; de=начало строки в описателе + pop hl ; откуда + ldir + ret diff --git a/MOD2/__COPY1.ASM b/MOD2/__COPY1.ASM new file mode 100755 index 0000000..f3c02e9 --- /dev/null +++ b/MOD2/__COPY1.ASM @@ -0,0 +1,271 @@ +;=========================================================== +; +; Процесс копирования файлов +; +;=========================================================== +copy: call test_show_panels ; тест на режим вкл. панелей + ret z + call get_fire ; защита от "залипания" бутонов + ld a,(format_mode) ; тек. формат панели + and form_info+form_qview ; info, qview + ret nz + ; скопир. имя файла/папки (если нет выдел.) + call prep_copy_name ; настроить имя копир. файла в описат. окон и др. + ret c ; текущий ".." и нет отмеч. файлов + ld a,1 ; копирование + ld (scan_mode),a ; режим работы tree-процедуры + jp __tree; + ; + ; вывод начального окна + ld hl,dial_copy ; описатель окна + call DialogW + cp evCommand ; событие "команда" + ret nz + ld a,(hl) ;+1 what + cp cmOkey ; "Copy" + ret nz + ; вывод окна процесса + ld hl,copy_file ; обработчик процесса ~Process Line~ + ld (subrout_process),hl + ld hl,dial_copy_total_process ; описатель окна с 2-мя линейками + call DialogW + cp evCommand; ; событие "команда" + ret nz; + ld a,(hl); ;+1 what + cp cmOkey; ; "Yes" + ret nz; + ; + ; вывод окна ошибки копирования + ld hl,dial_error_copy + call DialogEr + cp evCommand ; событие "команда" + ret nz + ld a,(hl) ;+1 what + cp cmSkip ; "Skip" + cp cmSkipAll ; "Skip all" + cp cmOkey ; "Retry" + ret nz + ; вывести окно прерывания операции + ld hl,dial_abort ; описатель окна + call DialogEr + cp evCommand ; событие "команда" + ret nz + ld a,(hl) ;+1 what + cp cmOkey ; "Yes" + ret nz + ; вывод окна "файл уже существует" + ; заполнить ячейки: + ld hl,dial_existing + call DialogEr + cp evCommand ; событие "команда" + ret nz + ld a,(hl) ;+1 what + cp cmOkey ; "Overwrite" + cp cmAll ; "All" + cp cmSkip ; "Skip" + cp cmSkipAll ; "Skip all" + cp cmAppend ; "Append" + ret nz + ;.. + ret + + + + + + + +; Имя копир. файла в описатели окон и буфер строки "Copy" +prep_copy_name: + ld hl,input_line_copy ; структура + call clear_struct_inline ; очистить структуру ~input line~ + ld hl,(__buff1) ; путь пасс. панели + ld de,input_line_copy+5 ; строка ~input line~ + ld b,2 ; счетчик длины строки + ld a,(disk1) + add a,"A" + ld (de),a + inc de + ld a,":" + ld (de),a + inc de + ld a,(hl) + ld (de),a + or a + jr z,$+7 + inc hl + inc de + inc b + jr $-8 + dec hl + ld a,'\' + cp (hl) + jr z,$+7 + inc b + ld (de),a + inc de + xor a + ld (de),a + ld a,b + ld (input_line_copy+4),a ; структура строки ~input line~ + ; начальное окно копирования + ld bc,copy_name ; куда + call copyname + ret c ; текущий ".." и нет отмеч. файлов + ; окно процесса копирования с 1-й линейкой + ld hl,copy_name-1 ; откуда + ld de,copy_name1 ; куда + call copy_string ; (hl) -> (de) + ld hl,input_line_copy+5 ; структура строки ~input line~ + ld de,copy_name2 ; куда + call copy_dstname ; скопир. путь+имя файла/папки + ; окно процесса копирования с 2-мя линейками + ld hl,copy_name-1 ; откуда + ld de,copy_name3 ; куда + call copy_string ; (hl) -> (de) + ld hl,copy_name2 ; откуда + ld de,copy_name4 ; куда + call copy_string ; (hl) -> (de) + ; + ; окно "ошибка копирования" + ld hl,copy_name-1 ; откуда + ld de,copy_name5 ; куда + call copy_string ; (hl) -> (de) + ; с центровкой имени + ; путь назначения окна "ошибка копирования" + ld hl,input_line_copy+5 ; структура строки ~input line~ + ld de,copy_name6 ; куда + call copy_dest_name ; скопир. путь+имя файла/папки + ; путь назначения окна "файл уже существует" + ld hl,copy_name6 ; откуда + ld de,exists_name ; куда + call copy_string ; (hl) -> (de) + ; имя файла + ld hl,work_buffer+33; + dec de; + call copy_string; ; (hl) -> (de) + ret + + + + + + + + + + + + + + + + + + + + + +;----------------------------------------------------------- +; Создать папку по тек. пути на диске назначения +;----------------------------------------------------------- +create_folder: + ; создать тек. таргет-путь в work_buffer+128 ;256 + ; основываясь на базовом пути work_buffer (точка отсчета) + or a; + ret + + +;----------------------------------------------------------- +; Скопировать файл тек. пути на диск назначения. +; Процедура линейки процесса копирования. +; При завершении (или прерывании) копирования +; выдает флаг "Carry". +;----------------------------------------------------------- +copy_file: + ; создать файл по тек. таргет-пути (в work_buffer+128 ;256) + ;... + scf + or a; + ret + + + +;__tree: +; ; скопир. путь акт. панели во врем. буфер (создать базовый путь сорца) +; push hl +; ld hl,(__buff) ; откуда, адрес пути акт. панели +; ld de,work_buffer ; куда +; ld a,(disk) ; диск панели +; add a,"A" +; ld (de),a +; inc de +; ld a,":" +; ld (de),a +; inc de +; call copy_string ; (hl) -> (de) до нуля +; pop hl +; ld a,(hl) +; cp "." ; ".." ? +; ret z ; выйти, родит. папка +; ; +; push de +; ;ld a,(format_mode) ; тек. фомат панели +; ;ld b,a +; call get_record ; hl=начало записи, a=атрибут файла +; pop de +; and 10h +; jr z,__tr1 ; файл, не добавлять имя папки +; ; тест на концевой слеш +; push hl +; ex de,hl +; dec hl +; dec hl +; ld a,'\' +; cp (hl) +; jr z,$+3 +; inc hl +; ld (hl),a +; inc hl +; ex de,hl ; de=куда +; pop hl ; откуда +; ; добавить имя папки +; ; de=куда +; ld bc,0044h ; 11 -> 8.3 +; rst 10h +;__tr1: ; +; ;call PR; +; ld hl,work_buffer +; ld c,1Dh ; уст. тек. путь +; rst 10h +; ;xor a ; сканир. папки +; ;ld (scan_mode),a ; режим работы процедуры +; jp ScanTree ; сканир. папку +; ;ret; + + + + + + +; Ячейки 1-й линейки процесса +max_file_bytes: + dw 0 ; размер файла (папки) + dw 0 ; ст. разряд + ; +curr_bytes: + dw 0 ; тек. число обраб. байтов + dw 0 ; ст. разряд + +; Ячейки 2-й линейки процесса +max_file_bytes1: + dw 0 ; размер файла (папки) + dw 0 ; ст. разряд + ; +curr_bytes1: + dw 0 ; тек. число обраб. байтов + dw 0 ; ст. разряд + + +copy_overwrite: + db false ; флаг подтв. перезаписи при копировании diff --git a/OBJS/BUTTON.ASM b/OBJS/BUTTON.ASM new file mode 100755 index 0000000..44bf7e3 --- /dev/null +++ b/OBJS/BUTTON.ASM @@ -0,0 +1,229 @@ +;===================================================================== +; Прорисовка объекта +; object ~Button~ (имеет фокус) +; Input: HL=описатель объекта +; Format table: +; +0 - номер объекта ~Claster check buttons" +; +1 - Xo левая позиция объекта +; +2 - Xi правая позиция объекта +; +3 - Y позиция объекта +; +4 - номер команды +; +5 - скен-код hot-клавиши +; +6 - контекст +;--------------------------------------------------------------------- +; Формат описателя: +; db Button ; номер объекта +; dw 0205h ; Yo,Xo +; db " ~O~k ",0 ; имя бутона +; db 18h ; скен-код hot-клавиши +; db cmOkey ; номер команды +; db 5 ; контекст +;===================================================================== +PutButton: + push iy + inc iy ; пройти ячейку размера таблицы + ld (iy+0),a ; +0 номер объекта + ld a,(hl) ; X pos + inc hl + ld c,a + add a,(ix+0) ; Pos X from begin screen + ld (iy+1),a ; +1 Xo left + ld a,(hl) ; Y pos + inc hl + ld b,a + add a,(ix+1) ; Pos Y from begin screen + ld (iy+3),a ;+3 Yo + call GetPutA + ex de,hl + ld a,(color_array+24) ; цвет диал. окна + ld c,a + ld b,0 ; счетчик ширины бутона + ld (iy+5),b ; hot-key + ; вставить имя бутона + ld a,(de) +PButLp1:inc de + cp "&" + jr nz,PButN0 + ; вставить hot-букву + ld a,(de) + ld (hl),a ; hot-букву в буфер + inc hl + inc de + push bc + ld a,(color_array+25) ; цвет hot-буквы диал. окна + ld b,a + ld a,c ; цвет бутона + and 0F0h + or b + ld (hl),a ; атрибут + pop bc + inc hl + inc b + ld a,(de) + inc de +PButN0: ld (hl),a + inc hl + ld (hl),c + inc hl + inc b + ld a,(de) + or a + jr nz,PButLp1 ; не конец имени + inc de + ld a,(de) ; скен-код hot-клавиши + inc de + ld (iy+5),a ; hot-клавиша + ld a,(iy+1) ; Xi left + add a,b ; + ширина бутона + ld (iy+2),a ; Xi right + ex de,hl + ld a,(hl) ; описатель объекта + inc hl + ld (iy+4),a ; номер команды + ld a,(hl) + inc hl + ld (iy+6),a ; контекст + ld bc,7 ; размер таблицы объекта "Button" + add iy,bc + push iy + exx + pop hl + pop de ; de=iy + and a + sbc hl,de ; de=DialTab+5 + ld a,l + ld (de),a ; размер таблицы объекта "Button" + exx + ret + + +;------------------------------------------------- +; Фокус на объект "Button" +;------------------------------------------------- +ButtonI:ld de,color_array+34 ; цвет Selected buttons + ld (set_dial_tmp_inv+1),de + ld e,(ix+2) ; Xo left + ld d,(ix+4) ; Y + ld a,(ix+3) ; Xi right + sub e + ld c,a + call SetDialInv ; выделить цветом + ld hl,color_array+26 ; Selected title (объекта) + ld (set_dial_tmp_inv+1),hl ; восст. ячейку + ret + + + + +;===================================================================== +; +; Обработчик событий объектов "Button" +; +;===================================================================== +EvButton: + ld hl,what ; поле событий + ld a,(hl) ;+0 + inc hl + cp evMouseFr + jr z,EBmouse + cp evKeyboard + jp z,EBkeys + cp evCombKey + ret nz + bit 7,(ix+1) ; sel or nosel + ret nz ; объект уже выделен + ld b,(hl) ;+1 what + inc hl + ld a,(hl) ;+2 what + cp 56h ; курсор вправо + jr z,tb__ + push ix + ld e,(ix+0) ; размер таблицы "Button" + ld d,0 + add ix,de + bit 7,(ix+0) + pop ix + ret z ; еще не конец объектов + cp 54h ; курсор влево + jr z,tb__ + ld a,b + and 00111111b ; биты Ctrl, Alt + ret nz + ld a,(hl) ;+2 what + cp 15+80h ; Tab скен-код+80h + ret nz + ; Shift+Tab +tb__: xor a + ld (_Push+1),a ; Push flag + jp SetButton ; select my + +; Событие - мышка +EBmouse:ld e,(hl) ;+1 X coord + inc hl + ld d,(hl) ;+2 Y coord + ld a,d + cp (ix+4) ; Y pos button + jr nz,get_fr ; if <> exit + ld a,e + bit 7,(ix+2) + jr nz,$+6 + cp (ix+2) ; Xo pos + jr c,get_fr ; < + bit 7,(ix+3) + jr nz,get_fr + cp (ix+3) ; Xi pos + jr nc,get_fr ; > + xor a + inc a + ld (_Push+1),a ; Push flag + bit 7,(ix+1) + jr nz,_Push + jr SetButton + +; Событие - обычная клавиша +EBkeys: xor a + ld (_Push+1),a ; Push flag + ld a,(hl) ;+1 what код клавиши + bit 7,(ix+1) ; Sel or nosel + jr nz,EBkeyN + cp 9 ; Tab + jr z,SetButton ; if tab then set button + jr EBkeyN1 + ; +EBkeyN: cp 0Dh ; Enter + jr z,EBent +EBkeyN1:inc hl + ld a,(hl) ;+2 what скен-код + cp (ix+6) ; hot-буква + ret nz +EBent: ld a,1 + ld (_Push+1),a +SetButton: + call MoveObj ; Select Button + call ResDialInv ; Reset previos invert + ld ix,DialTab+5 + ld de,color_array+34 ; цвет Selected buttons + ld (set_dial_tmp_inv+1),de + ld e,(ix+2) ; Xo + ld d,(ix+4) ; Y + ld a,(ix+3) ; Xi + sub e + ld c,a + call SetDialInv ; выделить бутон цветом + ld de,color_array+26 ; цвет Selected title (объекта) + ld (set_dial_tmp_inv+1),de +_Push: ld a,0 + or a + jr z,BTexit + call PushBut ; засветить курсор + ld hl,what + ld (hl),evCommand + inc hl + ld a,(ix+5) ; номер команды + ld (hl),a +get_fr: jp get_fire + ; +; Button exit +BTexit: ld hl,what + ld (hl),evNothing + ret diff --git a/OBJS/DIALOG.ASM b/OBJS/DIALOG.ASM new file mode 100755 index 0000000..299543f --- /dev/null +++ b/OBJS/DIALOG.ASM @@ -0,0 +1,1408 @@ +; Раскомментарить обработчики Original, Current, Blank + + +; Номера объектов +TextLine equ 0 ; строка текста +InputLine equ 1 ; строка редакт. текста +InpLine equ 2 ; вариант строки ввода для окна "Attributes" +ClsCheckBox equ 3 ; Check Box +ClsRadioBut equ 4 ; Radio Button +Button equ 5 ; Button +HLine equ 6 ; гориз. линия +PalleteBox equ 7 +TestColor equ 8 +ListBox equ 9 +PResident1 equ 10 +PResident2 equ 11 +ProcesLine equ 12 + +; Команды (внутренние) +cmOkey equ 0 +cmCancel equ 1 +cmOriginal equ 2 ; от окна "Attributes" +cmCurrent equ 3 ; от окна "Attributes" +cmBlank equ 4 ; от окна "Attributes" +cmSelect equ 5 +cmDefault equ 6 +cmSkip equ 7 +cmSkipAll equ 8 +cmAll equ 9 +cmAppend equ 10 + +; События (внутренние) +evNothing equ 0 ; нет событий +evMouseFr equ 1 ; нажата кнопка мыши +evKeyboard equ 2 ; нажата клавиша +evCombKey equ 3 ; нажата комбинация клавиш +evCommand equ 4 ; есть команда +evMessage equ 5 ; передача сообщения +evRunComLine equ 6 ; отработать ком-строку + +; Сообщения (внутренние) +msHiddInvr equ 80h +; объект ~палитра~ +msNewColor equ 81h +msNewElem equ 82h +msNewList equ 83h + + +; буфер сохр. экрана под строкой гориз. меню +WinHMenuBuff equ 0C000h+1400h ; буфер за SysScrn ;+ManScrn +MaxDialWin equ 1400h ; макс. размер окна + + + + + + +; бордюр окон +FramDSl:db "╔╗╚╝═║║║" + +WinBoxBuff: + dw 0C000h ; сохр. начало буферов окон + + +;------------ данные главного обработчика диалоговых окон -------------- +DialData: + ds 16 ; таблица главного диал. окна +DialName: + ds 25 ; буфер заголовков окон +DialTab: + ds 128 ; главная таблица объектов +;----------------------------------------------------------------------- + + +DialData1: + ds 16 ; таблица обычного окна + + + + + + + +;--------------------------------------------------------------------- +; Переместить объект (его таблицу) в начало Таблицы объектов +; +; Вход: IX-таблица объекта +; Выход: таблица объекта в начале Таблицы объектов и +; объект отмечен, как "в фокусе" (7-й бит). +;--------------------------------------------------------------------- +MoveObj:set 6,(ix+0) ; отметить объект в его таблице + ld hl,DialTab+5 ; Таблица всех объектов +MoveOlp:bit 6,(hl) ; тек. объект отмечен ? + res 6,(hl) ; сбр. флаг отметки + ret nz ; да, таблица объекта уже в начале + inc hl + res 7,(hl) ; сбр. признак фокуса объекта + dec hl + ld de,work_buffer ; Move first object in buffer + ld c,(hl) ; Len object label + ld b,0 + res 6,c + ldir ; Move + push hl + push hl + ld c,(hl) ; -6 + res 6,c + add hl,bc ; Search end table + bit 7,(hl) + jr z,$-6 + pop bc + or a ; HL-End table,BC-Address 2 obj + sbc hl,bc ; HL-BC=Len table -1 object + ld c,l ; BC=Len table + ld b,h + pop hl + ld de,DialTab+5 ; Move to begin table + push de + ld a,b + or c + jr z,$+4 + ldir + ld hl,work_buffer ; Move from buffer to end table + ld c,(hl) ; object BC=len Object label + res 6,c + ldir + pop hl + inc hl ; ячейка номера объекта (+0) + set 7,(hl) ; уст. признак фокуса объекта + dec hl + jr MoveOlp + + + + + + +;------------------------------------------------- +; Сохранить место под диал. окно +;------------------------------------------------- +SavDial:PUSH IX + LD A,(IX+2) ;with shadow + ADD A,2 + LD L,A + LD A,(IX+3) + INC A + LD H,A ; Wind len + LD E,(IX+0) + LD D,(IX+1) + LD IX,(WinBoxBuff) ; Address Box buffers + LD A,(page_dial_screen) ; Page buffer + LD C,0B2h ; копир. из окна в буфер + call scrn4__ + POP IX + RET + + +;----------------------------------------------------------- +; Процедура очистки площади цветом диал. окна +; На вход: IX - описатель +;----------------------------------------------------------- +PutDialRc: + LD HL,(WinBoxBuff) + ld bc,MaxDialWin; + add hl,bc; + LD B,(IX+3) ;Len Y + LD C,(IX+2) ;Len X + LD E," " ; символ заполнения + LD A,(color_array+24) ; цвет диал. окна +putRc1_:LD D,C + LD (HL),E + INC HL + LD (HL),a ; цвет окна + INC HL + DEC D + JR NZ,$-5 + INC HL ; место для тени + INC HL + INC HL + INC HL + DJNZ putRc1_ + RET + + +;--------------------------------------------------------------------- +; Процедура наложения рамки на прямоугольную площадь диал. окна +; На вход: IX - описатель +; HL - адрес описателя рамки +;--------------------------------------------------------------------- +PutDialFr: + PUSH IY + PUSH HL + POP IY + LD HL,(WinBoxBuff) + ld bc,MaxDialWin; + add hl,bc; + LD A,(color_array+24) ; цвет диал. окна + LD C,A + LD A,(IY+0) + LD (HL),A ;First Line + INC HL + LD (HL),C + INC HL + LD B,(IX+2) ;Len DialX + DEC B + DEC B + LD A,(IY+4) + LD (HL),A + INC HL + LD (HL),C + INC HL + DJNZ $-4 + LD A,(IY+1) + LD (HL),A + INC HL + LD (HL),C + INC HL + INC HL + INC HL + INC HL + INC HL + ; + LD E,(IX+2) ;lenX + DEC E + DEC E + LD D,B + LD B,(IX+3) ;lenY + DEC B + DEC B + LD A,(IY+5) +PutDialFr2__: + LD (HL),A ;middle space window + INC HL + LD (HL),C + INC HL + ADD HL,DE + ADD HL,DE + LD (HL),A ;middle space window + INC HL + LD (HL),C + INC HL + INC HL + INC HL + INC HL + INC HL + DJNZ PutDialFr2__ + ; + LD A,(IY+2) + LD (HL),A ;End Line + INC HL + LD (HL),C + INC HL + LD B,(IX+2) ;Len X + DEC B + DEC B + LD A,(IY+4) + LD (HL),A + INC HL + LD (HL),C + INC HL + DJNZ $-4 + LD A,(IY+3) + LD (HL),A + INC HL + LD (HL),C + INC HL + LD HL,DialName ; титл окна + LD E,L + LD D,H + LD B,1 + INC B ;B=Len name+2 (for space) + LD A,(HL) + INC HL + OR A ;0-End name + JR NZ,$-4 + LD A,(IX+2) ;Len X + SUB B ;LenX-Len name=Len empty + SRL A ;Len empty/2=shift + LD HL,(WinBoxBuff) + ld bc,MaxDialWin; + add hl,bc; + LD C,A + LD B,0 + ADD HL,BC ;get address name place + ADD HL,BC + LD (HL)," " ; вед. пробел имени окна + INC HL + INC HL + EX DE,HL ;HL=Adr.Name,DE=Adr.Place +PutDialFr5__: + LDI ;Move + INC DE ;Attrib place + LD A,(HL) + OR A ;0-End name + JR NZ,PutDialFr5__ + LD A," " ; закр. пробел имени окна + LD (DE),A + POP IY + RET + + +;------------------------------------------------- +; Процедура вывода в буфер тени окна +; На вход: IX - адрес описателя +;------------------------------------------------- +PutDialSh: + LD HL,(WinBoxBuff) + ld de,MaxDialWin; + add hl,de; + LD A,(IX+2) ; Xlen + LD E,A + LD D,0 + ADD HL,DE + ADD HL,DE + EXX + LD E,A ; ширина окна X + BIT 7,(IX+0) ; Xpos + JR Z,ExShD1 ; правая граница экрана + LD A,(IX+0) + NEG ; в A-на сколько окно залезло за экран + SUB E ; -длина окна=-видимая часть + NEG + LD E,A ; длина видимой части +ExShD1: LD D,0 + LD HL,(WinBoxBuff) + ADD HL,DE + ADD HL,DE + LD A,(HL) ; первая линия без тени + INC HL + EXX + LD (HL),A + INC HL + EXX + LD A,(HL) + INC HL + EXX + LD (HL),A + INC HL + EXX + LD A,(HL) + INC HL + EXX + LD (HL),A + INC HL + EXX + LD A,(HL) + INC HL + EXX + LD (HL),A + INC HL + ; середина окна + LD B,(IX+3) ; длина окна Y-1 + DEC B +DShadLp:ADD HL,DE + ADD HL,DE + EXX + ADD HL,DE + ADD HL,DE + LD A,(HL) + INC HL + EXX + LD (HL),A + INC HL + EXX + ;LD A,(HL) + INC HL + EXX + ;AND 7 + ;JR NZ,$+4 + ;LD A,7 + ;LD (HL),A + ld (hl),color_shadow ; цвет тени + INC HL + EXX + LD A,(HL) + INC HL + EXX + LD (HL),A + INC HL + EXX + ;LD A,(HL) + INC HL + EXX + ;AND 7 + ;JR NZ,$+4 + ;LD A,7 + ;LD (HL),A + ld (hl),color_shadow ; цвет тени + INC HL + DJNZ DShadLp + ADD HL,DE ; конец линии для тени + ADD HL,DE + INC HL + INC HL + INC HL + INC HL + EXX + ADD HL,DE ; конец буфера + ADD HL,DE + INC HL + INC HL + INC HL + INC HL + EXX + LD B,E +DShadL1:EXX + DEC HL ; заполняем с конца + ;LD A,(HL) + EXX + DEC HL + ;AND 7 + ;JR NZ,$+4 + ;LD A,7 + ;LD (HL),A + ld (hl),color_shadow ; цвет тени + EXX + DEC HL + LD A,(HL) + EXX + DEC HL + LD (HL),A + DJNZ DShadL1 + EXX ; два первых знакоместа без изменений + DEC HL + LD A,(HL) + EXX + DEC HL + LD (HL),A + EXX + DEC HL + LD A,(HL) + EXX + DEC HL + LD (HL),A + EXX + DEC HL + LD A,(HL) + EXX + DEC HL + LD (HL),A + EXX + DEC HL + LD A,(HL) + EXX + DEC HL + LD (HL),A + RET + + +;----------------------------------------------------------- +; По значению координат узнать адрес вставки в памяти +; Input: BC - Y/X координаты от начала окна +; Output: DE - адрес вставки +;----------------------------------------------------------- +GetPutA:PUSH HL + LD HL,(WinBoxBuff) + ld de,MaxDialWin; + add hl,de; + LD A,(IX+2) ;Len X-2 + ADD A,2 ;Full len with shadow + ADD A,A ;With attributs + LD E,A ;LenX in bytes + LD D,0 + LD A,B + OR A + JR Z,$+5 + ADD HL,DE + DJNZ $-1 + LD E,C ;$+5 + ADD HL,DE ;DE-shiftX + ADD HL,DE + EX DE,HL ;DE-Address + POP HL + RET + + + +;----------------------------------------------------------- +; Процедура подготовки и вывода диалогового окна +; На вход: HL - Адрес описателя +;----------------------------------------------------------- +PutDialWn: + PUSH IY + LD IY,DialTab ; Таблица объектов, имеющих фокус + LD IX,DialData ; таблица диал. окна + IN A,(SLOT3) + PUSH AF + LD A,(page_dial_screen) ; стр. буфера + OUT (SLOT3),A + LD A,(HL) ; X полож. диал. окна + LD (IX+0),A ;+0 Xpos + INC HL + LD A,(HL) ; Y полож. диал. окна + LD (IX+1),A ;+1 Ypos + INC HL + LD A,(HL) ; ширина диал. окна + LD (IX+2),A ;+2 Xlen + INC HL + LD A,(HL) ; высота диал. окна + LD (IX+3),A ;+3 Ylen + INC HL + LD DE,DialName ; титл диал. окна +PutDialWn1__: + LDI + LD A,(HL) + OR A + JR NZ,PutDialWn1__ + LDI + PUSH HL + CALL SavDial ; сохр. площадь экрана + CALL PutDialRc ; очистить место цветом окна + LD HL,FramDSl + CALL PutDialFr ; вставить рамку и титл окна + CALL PutDialSh ; вставить тень + LD A,(IX+0) ; move window + LD (IY+0),A ;+0 + INC IY + ADD A,(IX+2) ; номер объекта + LD (IY+0),A ;+1 + INC IY + LD A,(IX+1) + LD (IY+0),A ;+2 + INC IY + LD A,(IX+0) ; координаты |■| (закр.окно) + LD (IY+0),A ;+3 + INC IY + LD A,(IX+1) + LD (IY+0),A ;+4 + INC IY + POP HL + ; iy=DialTab+5 + ; цикл сканир. на объекты в описателе окна +DialCycle: + ld a,(hl) ; тип след. объекта описателя + inc hl + bit 7,a ; 0FFh test + jr nz,DialExit ; конец описателя диал. окна + ld de,DialCycle + push de + cp TextLine + jp z,PutTextLine ; вставить текст. строку + cp HLine + jp z,PutHLine ; вставить раздел. линию + cp InputLine + jp z,PutInputLine ; вставить строку редактир. + cp InpLine + jp z,PutInpLine ; вставить строку редактир. + cp Button + jp z,PutButton + cp ClsRadioBut + jp z,PutClsRadioBut ; put claster radio buttons + cp ClsCheckBox + jp z,PutClsCheckBox ; put claster check buttons + cp PalleteBox + jp z,PPallete + cp TestColor + jp z,PTestCol + cp ProcesLine + jp z,PProcess + cp ListBox + jp z,PListBox + cp PResident1 + jp z,PResid1 + cp PResident2 + jp z,PResid2 + pop de +DialExit: + ld (iy+0),80h ;+5 конец таблицы объектов + call PutDial ; вывести окно на экран + pop af + out (SLOT3),a + pop iy + ; Найти последний (с фитчей фокуса) объект в описателе + ld hl,DialTab+5 ; начало "местных" таблиц в DialTab + ld d,0 +SelEndL:ld e,(hl) ; размер "местной" таблицы в DialTab + add hl,de + bit 7,(hl) ; 80h (см. метку "DialExit") + jr z,SelEndL ; не конец таблицы объектов DialTab + and a + sbc hl,de ; вернуться на послед. объект + ; перекачать в буфер таблицу послед. объекта + ld de,work_buffer ; врем. буфер + ld b,0 + ld c,(hl) ; размер "местной" таблицы + ld a,c + ldir ; заполн. буферы DialTab+5 + ld c,a + DEC HL + LD E,L + LD D,H + OR A + SBC HL,BC + PUSH HL + LD BC,DialTab+4 + OR A + SBC HL,BC + LD C,L + LD B,H + POP HL + LD A,B + OR C + JR Z,$+4 + LDDR + LD HL,work_buffer ; врем. буфер + LD DE,DialTab+5 + LD C,(HL) + LDIR + ;xor a + ;ld (CIflag+1),a ; для объекта "буттон" + ; Установить фокус на объект + ld ix,DialTab+5 ; начало Таблицы объектов + ld hl,DIALe__ + push hl + ld a,(ix+1) + set 7,(ix+1) ; уст. признак фокуса + cp InputLine + jp z,InpLineI ; вывести курсор в объекте + cp InpLine + jp z,InpLineI ; вывести курсор в объекте + cp Button + jp z,ButtonI ; фокус на бутон + cp ClsRadioBut + jp z,ClastI + cp ClsCheckBox + jp z,ClastI + cp ListBox + jp z,PLstBoxI + cp PalleteBox + jp z,PLstBoxI + pop hl +DIALe__:ret + + + + + + + + + + +;/////////////////////////////////////////////////////////// +; Вызов диалогового окна +; вход: hl=описатель диал. окна +;/////////////////////////////////////////////////////////// +DialogW:ld de,(CursorPos) ; сохр. полож. курсора в ком. строке + push de + call Dialog + pop de + ld (CursorPos),de ; восст. полож. курсора + ld hl,what ; поле событий + ld a,(hl) + inc hl + ret + + +;/////////////////////////////////////////////////////////// +; Вызов диалогового окна ошибки +; вход: hl=описатель диал. окна +;/////////////////////////////////////////////////////////// +DialogEr: + ld de,color_array+34 ; Select buttons + ld a,(de) + push af + push de + ld a,(color_array+35) ; Sel.buttons Warning/Errors + ld (de),a + ld de,color_array+24 ; Normal text dial. window + ld a,(de) + push af + push de + ld a,(color_array+28) ; Warning/Errors window + ld (de),a + ld de,(CursorPos) ; сохр. полож. курсора в ком. строке + push de + call Dialog + pop de + ld (CursorPos),de ; восст. полож. курсора + pop de + pop af + ld (de),a + pop de + pop af + ld (de),a + ld hl,what ; поле событий + ld a,(hl) + inc hl + ret + + +;/////////////////////////////////////////////////////////// +; Вызов простого информ. окна +; вход: hl=описатель окна +;/////////////////////////////////////////////////////////// +WinSimple: + ld de,0C000h+1400h+1400h + ld (WinBoxBuff),de + call PutWindow ; вывести окно + ld hl,0C000h + ld (WinBoxBuff),hl + ret + + +;------------------------------------------------- +; Закрытие простого информ. окна +;------------------------------------------------- +CloseWinSimple: + ld de,0C000h+1400h+1400h + ld (WinBoxBuff),de + call close_window + ld hl,0C000h + ld (WinBoxBuff),hl + ret + + +;/////////////////////////////////////////////////////////// +; Вызов простого информ. окна ошибки +; вход: hl=описатель окна +;/////////////////////////////////////////////////////////// +WinSimpleEr: + ld a,(color_array+27) ; Information window + push af + ld a,(color_array+28) ; Warning/Errors window + ld (color_array+27),a + call WinSimple ; вывести окно + pop af + ld (color_array+27),a + ; ждем нажатия клавиши/мышки + call get_mouse_info + jr nz,CloseWinSimple ; бутоны нажаты + ld a,2 ; опрос без ожидания + rst 20h + jr z,$-8 ; не нажаты + ld a,1 ; очистить буфер клавы + rst 20h + jr CloseWinSimple + + + + +;----------------------------------------------------------- +; Основной обработчик диалогового окна +; +; вход: hl-описатель окна +;----------------------------------------------------------- +Dialog: call PutDialWn ; вывести диал. окно + ; Основной цикл событий окна +DialogLoop: + call handle_event ; Читаем событие + ld ix,DialTab+5 ; Таблица объектов + ; цикл проверки на события каждого из объектов +DialLoop: + ld hl,DialWex___ + push hl + ld a,(ix+1) ; начало таблицы тек. объекта + res 7,a ; убрать флаг фокуса + ; (только фокусные объекты) + cp InputLine + jp z,EvInputLine + cp InpLine + jp z,EvInpLine + cp Button + jp z,EvButton + cp ClsRadioBut + jp z,EvClasterBut + cp ClsCheckBox + jp z,EvClasterBut + cp ListBox + jp z,EListBox + cp ProcesLine + jp z,EProcess + cp PalleteBox + jp z,EPallete + cp TestColor + jp z,ETestCol + cp PResident1 + jp z,EResident1 + cp PResident2 + jp z,EResident2 + pop hl +DialWex___: + ld c,(ix+0) ; длина таблицы объекта в DialTab + ld b,0 + add ix,bc ; на таблицу след. объекта + bit 7,(ix+0) ; конец Таблицы объектов ? + jr z,DialLoop ; нет + ; проверка на события самого окна + ;ld de,DialogC___ + ld de,DialogLoop + push de + ld hl,what ; поле событий + ld a,(hl) + inc hl + cp evMouseFr ; Fire from mouse + jr z,TstExtD1 ; test on Close window + cp evKeyboard ; Event keyboard + jr z,TstKeyD ; тест на Esc/Enter + cp evCombKey ; Event keyboard + jr z,TstQuitD ; тест на F10 + cp evCommand + jr z,TstCmnD ; проверка команд от мышки, клавы + ret ; назад в осн. цикл окна + + +TstKeyD:ld a,(hl) ;+1 what + cp 1Bh ; Esc + jr z,CancelD + cp 0Dh ; Enter + jr z,OkeyD + ret + ; +TstQuitD: + inc hl + ld a,(hl) ;+2 what + cp 44h ; F10 + jr z,CancelD + ret + ; +TstCmnD:ld a,(hl) ;+1 what + cp cmCancel + jr z,CancelD + ; + ; бутоны Original, Current, Blank + ld a,(hl) ;+1 what + cp cmOriginal + ;jp z,OriginalAttr + cp cmCurrent + ;jp z,CurrentAttr + cp cmBlank + ;jp z,BlankAttr + ; + jr OkeyDn___ + +; Ok +OkeyD: ld hl,what + ld (hl),evCommand ; тип события + inc hl + ld (hl),cmOkey ;+1 номер команды +OkeyDn___: + ld ix,DialTab+5 ; Таблица объектов +OkeyLp___: + ld de,OkeyN___ ; Find clasters & get data + push de + ld a,(ix+1) ; номер тек. объекта + res 7,a ; убрать признак фокуса + cp ClsRadioBut + jp z,GetClsData ; узнать сост. ячейки кластера + cp ClsCheckBox + jp z,GetClsData + cp ListBox + jp z,GetLstBox + pop de +OkeyN___: + ld c,(ix+0) ; размер таблицы тек. объекта + ld b,0 + add ix,bc ; на таблицу след. объекта + bit 7,(ix+0) ; конец Таблицы объектов ? + jr z,OkeyLp___ ; нет +DialogE___: + ; выйти из диал. окна + call Close_Dial_Win ; закрыть окно + pop de ; баланс стека (осн. цикла окна) + jp get_fire + +; Cancel +CancelD:ld hl,what ; поле событий + ld (hl),evCommand + inc hl + ld (hl),cmCancel ; номер команды + jr DialogE___ + + +; Проверка координат мышки и диал. окна +TstExtD1: + ld e,(hl) ;+1 X Get mouse coords in DE + inc hl + ld d,(hl) ;+2 Y + ld ix,DialData ; таблица осн. диал. окна + ld c,(ix+0) ; Xo левая + ld b,(ix+1) ; Xi правая + ld l,(ix+2) ; ширина + ld h,(ix+3) ; высота + add hl,bc + ld a,e + cp c + jr c,CancelD ; < Xo левая + cp l + jr nc,CancelD ; > Xi правая + ld a,d + cp b + jr c,CancelD ; < Yo левая + cp h + jr nc,CancelD ; > Yi правая + ret ; не выходить из диал. окна + + + + + + + +;----------------------------------------------------------- +; Вывести диалоговое окно на экран +;----------------------------------------------------------- +PutDial:push ix + ld a,(ix+2) ; with shadow + add a,2 + ld l,a + ld a,(ix+3) + inc a + ld h,a ; Win len + ld e,(ix+0) + ld d,(ix+1) + ld ix,(WinBoxBuff) ; Address Box buffers + ld bc,MaxDialWin; + add ix,bc; + ld a,(page_dial_screen) ; Page buffer + ld c,0B3h ; из буфера в текст. окно + call scrn4__ + pop ix + ret + + +;----------------------------------------------------------- +; Закрыть простое окно +;----------------------------------------------------------- +close_window: + ld ix,DialData1 ; таблица осн. диал. окна + jr close_dial_win1 +;----------------------------------------------------------- +; Закрыть диалоговое окно и восст. место под ним +;----------------------------------------------------------- +Close_Dial_Win: + call ResILCr ; сбросить курсор + ld ix,DialData ; таблица осн. диал. окна +close_dial_win1: + ld a,(ix+2) ; with shadow + add a,2 + ld l,a + ld a,(ix+3) + inc a + ld h,a ; Win len + ld e,(ix+0) + ld d,(ix+1) + ld ix,(WinBoxBuff) ; Address Box buffers + ld a,(page_dial_screen) ; Page buffer + ld c,0B3h ; из буфера в текст. окно + jp scrn4__ + + + + + + +;----------------------------------------------------------- +; Setting dialog invert objects +; +; Input: e=X pos +; d=Y pos +; c=X len +;----------------------------------------------------------- +SetDialInv: + push ix + ld ix,DialData ; таблица осн. диал. окна + in a,(SLOT3) + push af + ld a,(page_dial_screen) ; Page buffer + out (SLOT3),a + ld l,c + ld h,1 + ld (RDlIlen+1),hl ; сохр. размер + ld (RDlIpos+1),de ; сохр. полож. + ld a,e + sub (ix+0) + ld c,a + ld a,d + sub (ix+1) + ld b,a + call GetPutA + ex de,hl + ld (RDlIbuf+2),hl + dec e; ; 0-я длина ? (когда "Input Line" без имени) + inc e; + jr z,SetDia1; ; выйти + ld b,e +set_dial_tmp_inv: + ld a,(color_array+26) ; 30h цвет Selected title (объекта) + ld e,a + ld a,(color_array+25) ; цвет hot-буквы диал. окна + ld d,a +SetDin1:inc hl + ld a,(hl) + and 0Fh + cp d ; hot-буква ? + ld a,e + jr nz,$+5 + and 0F0h + or d + ld (hl),a + inc hl + djnz SetDin1 + ld ix,(RDlIbuf+2) ; Put Name with invert + ld hl,(RDlIlen+1) + ld de,(RDlIpos+1) + call PutDialLn +SetDia1:pop af + out (SLOT3),a + pop ix + ret + + +;------------------------------------------------- +; Set claster buttons invert +; Input: +; E - X pos +; D - Y pos +; C - X len +; (для CheckBox) +;------------------------------------------------- +SetClasInv: + ;PUSH IX + ;LD IX,DialData ; таблица осн. диал. окна + ;IN A,(SLOT3) + ;PUSH AF ; сохр. page4 + ;LD A,(page_dial_screen) + ;OUT (SLOT3),A ; вкл. буфер + ;PUSH HL + ;LD L,C ; Len X + ;LD H,1 ; Len Y + ;LD (RClIlen+1),HL ; Save len + ;LD (RClIpos+1),DE ; Save pos + ;dec c ; 0-я длина ? (когда "Input Line" без имени) + ;inc c + ;jr z,SetDia3 ; выйти + ;LD A,E + ;SUB (IX+0) + ;LD C,A + ;LD A,D + ;SUB (IX+1) + ;LD B,A + ;CALL GetPutA + ;EX DE,HL + ;LD (RClIbuf+2),HL + ;LD B,E + ;ld a,(color_array+26) ; 30h цвет выдел. объекта + ;ld a,(ColDialWn) ; цвет диал. окна + ;ld e,a + ;ld a,(color_array+25) ; цвет hot-буквы диал. окна + ;ld d,a +;SetDin2:inc hl + ;ld a,(hl) + ;and 0Fh + ;cp d ; hot-буква ? + ;ld a,e + ;jr nz,$+5 + ;and 0F0h + ;or d + ;ld (hl),a + ;inc hl + ;djnz SetDin2 + ;LD IX,(RClIbuf+2) ; Put Name with invert + ;LD HL,(RClIlen+1) + ;LD DE,(RClIpos+1) + ;CALL PutDialLn +;SetDia3:POP HL + ;POP AF + ;OUT (SLOT3),A + ;POP IX + ld e,(ix+2) ; Xo pos element + inc e + ;inc e + ;inc e + ld d,(hl) ; Y pos element + ld (CursorPos),de + push hl + call PILCurs ; Set cursor + pop hl + ;ld a,1 + ;ld (CIflag+1),a + ret + + + +;----------------------------------------------------------- +; Res dialog invert objects +; Input: None +;----------------------------------------------------------- +ResDialInv: + push ix + in a,(SLOT3) + push af + ld a,(page_dial_screen) ; Page buffer + out (SLOT3),a + ld a,(RDlIlen+1) + or a; ; 0-я длина ? (когда "Input Line" без имени) + jr z,ResDia1; ; выйти + ld hl,(RDlIbuf+2) + ld b,a + ld a,(color_array+24) ; цвет диал. окна + ld e,a + ld a,(color_array+25) ; цвет hot-буквы диал. окна + ld d,a +ResDin1:inc hl + ld a,(hl) + and 0Fh + cp d ; hot-буква ? + ld a,e + jr nz,$+5 + and 0F0h + or d + ld (hl),a + inc hl + djnz ResDin1 +RDlIbuf:ld ix,0 ; Put Name with invert +RDlIlen:ld hl,0 +RDlIpos:ld de,0 + call PutDialLn +;CIflag: ld a,0 ; 1 - Was claster invert + ;or a + ;call nz,ResClasInv +ResDia1:call ResILCr ; выкл. курсор объекта "Input Line" + pop af + out (SLOT3),a + pop ix + ld hl,what + ld (hl),evMessage ; тип события + inc hl + ld (hl),msHiddInvr ; внутр. команда + jp TransMessage ; передать сообщение + + +;------------------------------------------------- +; Res Claster invert +; Input: None +;------------------------------------------------- +ResClasInv: + push ix + IN A,(SLOT3) + PUSH AF ; сохр. page4 + LD A,(page_dial_screen) + OUT (SLOT3),A ; вкл. буфер + push hl + ;LD HL,(RClIbuf+2) + ;ld a,(RClIlen+1) + ;or a; ; 0-я длина ? (когда "Input Line" без имени) + ;jr z,ResDia2; ; выйти + ;ld b,a + ;ld a,(color_array+24) ; цвет диал. окна + ;ld e,a + ;ld a,(color_array+25) ; цвет hot-буквы диал. окна + ;ld d,a +;ResDin2:inc hl + ;ld a,(hl) + ;and 0Fh + ;cp d ; hot-буква ? + ;ld a,e + ;jr nz,$+5 + ;and 0F0h + ;or d + ;ld (hl),a + ;inc hl + ;djnz ResDin2 +;RClIbuf:LD IX,0 ; Put Name with invert +;RClIlen:LD HL,0 +;RClIpos:LD DE,0 + ;CALL PutDialLn +;ResDia2: + call ResILCr ; выкл. курсор + ;xor a + ;LD (CIflag+1),a + pop hl + POP AF + OUT (SLOT3),A + pop ix + ret + + + + + +;------------------------------------------------- +; Вывод на экран +;------------------------------------------------- +PutDialLn: + ld a,d + cp 31 + ret nc + bit 7,e + jr z,pdln__ + ld a,e + ld e,0 + neg + ld c,a + sub l + neg + ld l,a + ret z + ret m + ld a,c + add a,a + db 0DDh + add a,l + db 0DDh + ld l,a + jr nc,pdln__ + db 0DDh + inc h +pdln__: ld a,e + cp 80 + ret nc + add a,l + cp 80 + jr c,$+6 + ld a,80 + sub e + ld l,a + ld a,(page_dial_screen) + ld c,0B3h ; копир. с буфера на экран + jp scrn4__ + + + + + + +;------------------------------------------------- +; Выделить бутон +;------------------------------------------------- +PushBut:in a,(SLOT3) + push af + ld a,(page_dial_screen) ; Page buffer + out (SLOT3),a + push ix + ld e,(ix+2) ; Xo left + ld d,(ix+4) ; Y + ld a,(ix+3) ; Xi right + sub e + ld l,a + ld h,1 ; Y len + push hl ; save Len + push de ; save Pos + ld a,l + ld ix,DialData ; таблица осн. диал. окна + ld a,e + sub (ix+0) + ld c,a + ld a,d + sub (ix+1) + ld b,a + call GetPutA + ld c,l + sla c + ld b,0 + ld hl,work_buffer + ex de,hl + ldir ; скопир. в буфер + pop de + pop hl + ld ix,work_buffer + in a,(SLOT3) ; Page1 + ld c,0B3h ; из буфера на экран + call scrn4__ + ld b,8 + halt + djnz $-1 + pop ix + pop af + out (SLOT3),a + ret + + + + + + + + + +;--------------------------------------------------------------------- +; Передача сообщений по объектам с текущего объекта +;--------------------------------------------------------------------- +TransMessUp: + push iy + push ix + jr TransEx + +;--------------------------------------------------------------------- +; Передача сообщений по объектам с первого объекта +;--------------------------------------------------------------------- +TransMessage: + push iy + push ix + ld ix,DialTab+5 ; Таблица объектов +TransLp:ld hl,TransEx + push hl + ld a,(ix+1) ; текущий объект + and 7Fh ; сбр. 7-й бит (флаг выделения объекта) + cp InputLine + jp z,EvInputLine + cp InpLine + jp z,EvInpLine + cp Button + jp z,EvButton + cp ClsCheckBox + jp z,EvClasterBut + cp ClsRadioBut + jp z,EvClasterBut + cp ListBox + jp z,EListBox + cp PalleteBox + jp z,EPallete + cp TestColor + jp z,ETestCol + cp PResident1 + jp z,EResident1 + cp PResident2 + jp z,EResident2 + pop hl +TransEx:ld c,(ix+0) + ld b,0 + add ix,bc ; след. объект + bit 7,(ix+0) + jr z,TransLp ; не конец таблицы объектов + pop ix + pop iy + ld hl,what ; поле событий + ld a,(hl) + cp evMessage ; тип события + ret nz ; test command + ld (hl),evNothing + ret + + + + + + + +;=========================================================== +; Вывод Обычного Окна +;=========================================================== + + + +;----------------------------------------------------------- +; Процедура подготовки и вывода обычного окна. +; Используется для вывода инф. окон. +; вход: hl=описатель окна +;----------------------------------------------------------- +PutWindow: + ld a,(color_array+24) ; цвет диал. окна + push af + ld a,(color_array+27) ; цвет информ. окон + ld (color_array+24),a ; цвет диал. окна + ld ix,DialData1; ; таблица диал. окна + in a,(SLOT3) + push af + ld a,(page_dial_screen) ; стр. буфера окна + out (SLOT3),a + ld a,(hl) ; X полож. окна + ld (ix+0),a ;+0 Xpos + inc hl + ld a,(hl) ; Y полож. окна + ld (ix+1),a ;+1 Ypos + inc hl + ld a,(hl) ; ширина окна + ld (ix+2),a ;+2 Xlen + inc hl + ld a,(hl) ; высота окна + ld (ix+3),a ;+3 Ylen + inc hl + ld de,DialName ; титл окна +put_win1__: + ldi + ld a,(hl) + or a + jr nz,put_win1__ + ldi + push hl + call SavDial ; сохр. площадь экрана + call PutDialRc ; очистить место цветом окна + ld hl,FramDSl + call PutDialFr ; вставить рамку и титл окна + call PutDialSh ; вставить тень + pop hl + ; цикл сканир. на объекты описателя окна +put_win_cycle: + ld a,(hl) ; тип след. объекта описателя + inc hl + bit 7,a ; -1 ? + jr nz,put_win_done ; конец описателя окна + ld de,put_win_cycle + push de + cp TextLine + jp z,PutTextLine ; вставить текст. строку + cp HLine + jp z,PutHLine ; вставить раздел. линию + ;cp Frame + ;jp z,PFrame ; вставить рамку + pop de +put_win_done: + call PutDial ; вывести окно на экран + pop af + out (SLOT3),a + pop af + ld (color_array+24),a ; восст. цвет + ret diff --git a/OBJS/DIALOG1.ASM b/OBJS/DIALOG1.ASM new file mode 100755 index 0000000..bcb44bf --- /dev/null +++ b/OBJS/DIALOG1.ASM @@ -0,0 +1,64 @@ +; Объекты, не имеющие фокуса +; + + + + +;===================================================================== +; Прорисовка объекта +; Object ~Text Line~ (не может иметь фокус) +; Input: HL-описатель объекта +; Format table: нет +;--------------------------------------------------------------------- +; Формат описателя: +; db TextLine +; dw 0205h ; Yo,Xo +; db "Calculating free space...",0 +;===================================================================== +PutTextLine: + ld c,(hl) ; X pos + inc hl + ld b,(hl) ; Y pos + inc hl + call GetPutA + ldi + inc de ; пройти атрибут + ld a,(hl) + cp -1 ; конец описателя окна + ret z + or a ; конец описателя TextLine + jr nz,$-8 + inc hl + ret + + + + + +;===================================================================== +; Прорисовка объекта +; Object ~Horizontal Line~ (не может иметь фокус) +; Input: HL-описатель объекта +; Format table: нет +;--------------------------------------------------------------------- +; Формат описателя: +; db HLine +; dw 0801h ; Yo,Xo +; db 40 ; длина линии +; db "─" ; символ заполнения +;===================================================================== +PutHLine: + ld c,(hl) ; X pos + inc hl + ld b,(hl) ; Y pos + inc hl + call GetPutA + ld b,(hl) ; длина линии + inc hl + ld a,(hl) ; символ заполнения + inc hl + ld (de),a + inc de + inc de ; пройти атрибут + djnz $-3 + ret diff --git a/OBJS/HMENU.ASM b/OBJS/HMENU.ASM new file mode 100755 index 0000000..e36c909 --- /dev/null +++ b/OBJS/HMENU.ASM @@ -0,0 +1,1737 @@ +; Обработчики Гориз. меню, Pull-меню, Меню выбора дисков. +; Также содержит п/программу настройки меток "√" пунктов меню. +; + + + + +; Номера пунктов +; Left +cmLBrief equ 0 +cmLMed equ cmLBrief+1 +cmLFull equ cmLMed+1 +cmLInfo equ cmLFull+1 +cmLQview equ cmLInfo+1 +cmLName equ cmLQview+1 +cmLExt equ cmLName+1 +cmLDate equ cmLExt+1 +cmLSize equ cmLDate+1 +cmLUnsort equ cmLSize+1 +cmLFilter equ cmLUnsort+1 +cmLChangeDrv equ cmLFilter+1 +; Files +cmHelp equ cmLChangeDrv+1 +cmUsrMenu equ cmHelp+1 +cmView equ cmUsrMenu+1 +cmEdit equ cmView+1 +cmCopy equ cmEdit+1 +cmRename equ cmCopy+1 +cmMkFolder equ cmRename+1 +cmDelete equ cmMkFolder+1 +cmAttrib equ cmDelete+1 +cmSelGroup equ cmAttrib+1 +cmUSelGroup equ cmSelGroup+1 +cmQuit equ cmUSelGroup+1 +; Commands +cmFind equ cmQuit+1 +cmVolume equ cmFind+1 +cmSwap equ cmVolume+1 +cmPanelsOn equ cmSwap+1 +cmNullTRD equ cmPanelsOn+1 ; создать пустой TRD image +cmCopyTRD equ cmNullTRD+1 ; TRD image -> Disk +cmSaveTRD equ cmCopyTRD+1 ; Disk -> TRD image +; Options +cmInterface equ cmSaveTRD+1 +cmConfirm equ cmInterface+1 +cmColors equ cmConfirm+1 +cmHighlight equ cmColors+1 +cmViewSet equ cmHighlight+1 +cmEditSet equ cmViewSet+1 +cmSaveSetup equ cmEditSet+1 +; Right +cmRBrief equ cmSaveSetup+1 +cmRMed equ cmRBrief+1 +cmRFull equ cmRMed+1 +cmRInfo equ cmRFull+1 +cmRQview equ cmRInfo+1 +cmRName equ cmRQview+1 +cmRExt equ cmRName+1 +cmRDate equ cmRExt+1 +cmRSize equ cmRDate+1 +cmRUnsort equ cmRSize+1 +cmRFilter equ cmRUnsort+1 +cmRChangeDrv equ cmRFilter+1 + +; флаги маркеров пунктов меню +CTnodef equ 0 ; "по-умолчанию" не выделено +CTdef equ 1 ; "по-умолчанию" выделено "√" + + +LC000 equ 0C000h ; адрес буфера окна + + + + + + + + +; рабочая таблица верт. меню +BoxData: +CurBox: dw 0 ;+0,+1 +Xo: db 0 +Xi: db 0 +Ypos: db 0 ; полож. +Xlen: db 0 ; ширина + + + +CurMenu:db 0 ; тек. полож. указателя гориз. меню +CurMBox:db 0 ; Current mark MenuBox +BarFlag:db 0 ; Flag barinvert (0=нет, 1=да) + + + +;----------------------------------------------------------- +; Таблица горизонтального Меню +; формат: +0 - Xo coord +; +1 - Xi coord +; +2 - код hot-клавиши +; +3,4 - адрес описателя верт. меню +;----------------------------------------------------------- +BarTabl:ds 5*5 ; блок пункта * число пунктов гор. меню + db 80h ; конец таблицы + + +;----------------------------------------------------------- +; Таблица вертикальных меню +; формат: Положение окна меню: +; +0 - Xo coord +; +1 - Xi coord +; +2 - Yo coord +; +3 - Yi coord +; +4 - Положение пункта меню: +; +0 - Xo coord +; +1 - Xi coords +; +2 - Y coords +; +3 - номер команды +; +4 - hot-клавиша +; +5 - номер контекста +;----------------------------------------------------------- +BoxTabl:ds 4 ; +0..+3 + ds 6*26 ; блок пункта * макс. число пунктов + db 0 ; конец таблицы + + + + + + + +;/////////////////////////////////////////////////////////// +; Вызов Горизонтального Меню +;/////////////////////////////////////////////////////////// +main_menu: + in a,(SLOT3) + push af + ld a,(page_sys_screen) ; стр. буфера окна диалога + out (SLOT3),a + ; сохр. экран под строкой гориз. меню + ld ix,WinHMenuBuff ; address Box buffers + ld hl,0150h + ld de,0000h + ld a,(page_sys_screen) ; page buffer + ld c,0B2h ; копир. из окна в буфер + call scrn4__ + call init_hmenu ; подготовка меню + call menu_exec ; работа в меню + call get_fire ; защита от "залипания" мышки + ; восст. экран под строкой гориз. меню + ld ix,WinHMenuBuff ; address Box buffers + ld hl,0150h + ld de,0000h + ld a,(page_sys_screen) ; page buffer + ld c,0B3h ; копир. из буфера в окно + call scrn4__ + pop af + out (SLOT3),a + ; на выполн. пунктов pull-меню + jp pull_commands ; pullcmnd.asm + + + + + + + +;----------------------------------------------------------- +; Инициализация строки гориз. меню и таблицы мышки +;----------------------------------------------------------- +init_hmenu: + ; корректно настроить панеле-зависимые ячейки + ld a,(cur_panel) ; 0=левая, 80h=правая + or a + push af + call nz,change_panel + call prep_default_puncts ; уст. "√" метки пунктов + pop af + call nz,change_panel + ; + call InitEvent ; иниц. обработчика событий + xor a + ld (CurMBox),a + ld (BarFlag),a + inc a + ld (CurMenu),a ; нач. полож. указателя гориз. меню + ; подгот. строку меню во временном буфере + ld ix,BarTabl ; таблица гориз. меню + ld hl,work_buffer ; врем. буфер + ld de,MenuTab ; описатель гориз. Меню + ld b,1 ; начало X координат + ld a,(color_array+12) ; цвет гориз. меню + ld c,a + ld (hl)," " ; начальный пробел + inc hl + ld (hl),c + inc hl + ; цикл вывода всех пунктов +InBarL1__: + ld (hl)," " ; раздел. пунктов + inc hl + ld (hl),c + inc hl + ld (ix+0),b ;+0 left X coords + inc ix + inc b + ld a,(de) ; Get name submenu + ; цикл вывода пункта +InBarL2__: + inc de + cp "&" + call z,Bhotkey__ ; уст. цвет для hot-буквы + ld (hl),a + inc hl + ld (hl),c + inc hl + inc b + ld a,(de) + or a + jr nz,InBarL2__ + ld (hl)," " ; концовка пункта + inc hl + ld (hl),c + inc hl + inc b + ld (ix+0),b ;+1 Right X coords + inc ix + inc de + ld a,(de) ; код hot-клавиши + ld (ix+0),a ;+2 + inc ix + inc de + ld a,(de) + ld (ix+0),a ;+3,+4 - адрес описателя верт. меню + inc ix + inc de + ld a,(de) + ld (ix+0),a ;+4 + inc ix + inc de + ld a,(de) + or a + jr nz,InBarL1__ + ; конец пунктов гориз. меню + ld (ix+0),80h ; конец Mouse Table + ld a,80 ; ширина экрана + sub b + jr z,InBarEx__ + ; заполнить остаток строки до конца экрана + ld b,a + ld (hl)," " + inc hl + ld (hl),c + inc hl + djnz $-5 + ; вывести готовую строку гориз. меню на экран +InBarEx__: + ld ix,work_buffer ; буфер строки + ld hl,0150h ; Y/X размер окна + ld de,0000h ; полож. окна (строки) + in a,(SLOT3) + ld c,0B3h ; копир. из буфера на экран + call scrn4__ + jp SetMBar ; вывести выдел. указатель + + +;------------------------------------------------- +; Установить цвет hot-буквы гориз. меню +;------------------------------------------------- +Bhotkey__: + ld a,(de) + ld (hl),a ; hot-букву в буфер + inc hl + inc de + push de + ld a,(color_array+14) ; цвет hot-буквы гориз. меню + and 0Fh + ld e,a + ld a,(color_array+12) ; цвет гориз. меню + and 0F0h + or e + ld (hl),a ; атрибут + pop de + inc hl + ld a,(de) + inc de + inc b + ret + + +;------------------------------------------------- +; Установить выдел. указатель в гориз. Меню +;------------------------------------------------- +SetBarI:ld a,(BarFlag) + or a + ret nz + inc a + ld (BarFlag),a + ld hl,BarTabl ; рабочая таблица гориз. меню + ld a,(CurMenu) ; тек. полож. указателя гориз. меню + dec a + ld c,a ; *5 + add a,a + add a,a + add a,c + add a,l + ld l,a + jr nc,$+3 + inc h + ld e,(hl) ; Xo + inc hl + ld d,0 ; Y = 0 + ld a,(hl) + sub e ; Xi - Xo = ширина + ld l,a + ld h,1 ; высота + ld (RBrIlen+1),hl + ld (RBrIpos+1),de + push af ; сохр. ширину + ld ix,work_buffer + in a,(SLOT3) + ld c,0B2h ; копир. с окна в буфер + call scrn4__ + ld a,(color_array+13) ; цвет указателя гориз. меню + ld c,a + ld a,(color_array+14) ; цвет hot-буквы гориз. меню + and 0Fh + ld b,a + pop af ;Reset LenX + ; подготовить в буфере выдел. указатель + ld hl,work_buffer ; буфер +SetInvB__: + ex af,af' + inc hl + ld a,(hl) + and 0Fh + cp b ; hot-буква? + ld a,c + jr nz,$+5 + and 0F0h + or b + ld (hl),a + inc hl + ex af,af' + dec a + jr nz,SetInvB__ + ; вывести на экран выдел. пункт (указатель) + ld ix,work_buffer ; буфер + ld hl,(RBrIlen+1) ; Y/X размер окна + ld de,(RBrIpos+1) ; полож. окна + in a,(SLOT3) + ld c,0B3h ; копир. из буфера на экран + jp scrn4__ + + +;------------------------------------------------- +; Сбросить выдел. указатель в гориз. Меню +;------------------------------------------------- +ResBarI:ld a,(BarFlag) + or a + ret z + xor a + ld (BarFlag),a + ; скопир. указатель с экрана в буфер + ld ix,work_buffer +RBrIlen:ld hl,0 ; сохр. ширина указателя +RBrIpos:ld de,0 ; сохр. полож. указателя + ld a,l + push af + in a,(SLOT3) ; порт + ld c,0B2h ; копир. с экрана в буфер + call scrn4__ + ld a,(color_array+12) ; цвет гориз. меню + ld c,a + ld a,(color_array+14) ; цвет hot-буквы гориз. меню + and 0Fh + ld b,a + pop af ;Reset LenX + ; сбросить выдел. указатель в буфере + ld hl,work_buffer ; буфер +ResInvB__: + ex af,af' + inc hl + ld a,(hl) + and 0Fh + cp b ; hot-буква? + ld a,c + jr nz,$+5 + and 0F0h + or b + ld (hl),a + inc hl + ex af,af' + dec a + jr nz,ResInvB__ + ; вывести сброшенный пункт на экран + ld ix,work_buffer + ld hl,(RBrIlen+1) ; размеры окна (указателя) + ld de,(RBrIpos+1) ; Y/X полож. + in a,(SLOT3) + ld c,0B3h ; копир. из буфера на экран + jp scrn4__ + + + + + +;------------------------------------------------- +; Установить цвет hot-буквы верт. меню +;------------------------------------------------- +Bhotkey1__: + ld a,(de) + ld (hl),a ; hot-букву в буфер + inc hl + inc de + push de + ld a,(color_array+17) ; цвет hot-буквы меню + and 0Fh + ld e,a + ld a,(color_array+15) ; цвет верт. меню + and 0F0h + or e + ld (hl),a ; атрибут + pop de + inc hl + ld a,(de) + inc de + inc b + ret + + +;----------------------------------------------------------- +; Установить выдел. указатель верт. меню +;----------------------------------------------------------- +SetBoxI:ld a,(CurMBox) + dec a + ;*6 + add a,a ;1+1=2 + ld c,a ;2 +SetBoxI1: + add a,a ;2+2=4 + add a,c ;4+2=6 + ld hl,BoxTabl+4 ; рабочая таблица верт. меню + 4 + add a,l + ld l,a + jr nc,$+3 + inc h + ld e,(hl) + inc hl + ld a,(hl) + inc hl + ld d,(hl) + sub e ; Xi - Xo = LenX + ld l,a + ld h,1 ; высота + ld (RBxIlen+1),hl + ld (RBxIpos+1),de + ; + push af + ld ix,work_buffer + in a,(SLOT3) + ld c,0B2h + call scrn4__ + ld a,(color_array+16) ; цвет указателя верт. меню + ld c,a + ld a,(color_array+17) ; цвет hot-буквы верт. меню + and 0Fh + ld b,a + pop af ; LenX + ; подготовить в буфере выдел. указатель + ld hl,work_buffer ; буфер +SetInvX__: + ex af,af' + inc hl + ld a,(hl) + and 0Fh + cp b ; hot-буква? + ld a,c + jr nz,$+5 + and 0F0h + or b + ld (hl),a + inc hl + ex af,af' + dec a + jr nz,SetInvX__ + ; вывести на экран выдел. пункт меню + ld ix,work_buffer ; буфер + ld hl,(RBxIlen+1) + ld de,(RBxIpos+1) + in a,(SLOT3) + ld c,0B3h + jp scrn4__ + + +;----------------------------------------------------------- +; Сбросить выдел. указатель верт. меню +;----------------------------------------------------------- +ResBoxI:ld ix,work_buffer +RBxIlen:ld hl,0 +RBxIpos:ld de,0 + ld a,l + push af + in a,(SLOT3) + ld c,0B2h + call scrn4__ + ld a,(color_array+15) ; цвет верт. меню + ld c,a + ld a,(color_array+17) ; цвет hot-буквы верт. меню + and 0Fh + ld b,a + pop af + ; сбросить указатель в буфере + ld hl,work_buffer ; буфер +ResInvX__: + ex af,af' + inc hl + ld a,(hl) + and 0Fh + cp b ; цвет hot-буквы? + ld a,c + jr nz,$+5 + and 0F0h + or b + ld (hl),a + inc hl + ex af,af' + dec a + jr nz,ResInvX__ + ; вывести сброшенный пункт на экран + ld ix,work_buffer + ld hl,(RBxIlen+1) + ld de,(RBxIpos+1) + in a,(SLOT3) + ld c,0B3h + jp scrn4__ + + + + + + +;----------------------------------------------------------- +; Главный цикл гориз. Меню +;----------------------------------------------------------- +menu_exec: + call handle_event ; читаем событие + ld hl,what + ld de,menu_exec + push de + ld a,(hl) ;+0 узнать событие + inc hl + cp evMouseFr ; нажаты бутоны мышки + jp z,MBmouse + cp evKeyboard ; нажаты обычные клавиши + jr z,MBkeys + cp evCombKey ; нажаты курс. клавиши и служ. + jr z,MBcbkey + ret + +; выйти, если меню закрыто +MenuExt:ld a,(CurMBox) ; box open + or a + jp nz,CloseBx ; закрыть верт. меню +; выйти из гориз. меню +MenuExit: + pop de ; восст. баланс стека + ld hl,what + ld (hl),evNothing ; уст. "нет событий" + ret + +;------------------------------------------------- +; Обычные клавиши (для верт. меню) +;------------------------------------------------- +MBkeys: ld a,(hl) ;+1 код клавиши + cp 1Bh ; Esc + jr z,MenuExt + cp 0Dh ; Enter + jr nz,MBkeysN + ld a,(CurMBox) ; if not box then open + or a + jp z,OpenBox ; открыть окно верт. меню + ld b,a + ld ix,BoxTabl-2 ; поиск пункта верт. меню + ld de,6 + add ix,de + djnz $-2 + jp BxEnter + ; +MBkeysN:ld a,(CurMBox) + or a + ret z ; верт. меню не открыто + inc hl + ld a,(hl) ;+2 скен-код клавиши + ld ix,BoxTabl-2 ; рабочая таблица верт. меню - 2 + ld bc,6 + ld h,b +MBkeys1__: + inc h + add ix,bc + bit 7,(ix+0) ; конец описателя меню ? + ret nz ; да, hot-клавиша не найдена + cp (ix+4) ; скен-код hot-клавиши + jr nz,MBkeys1__ + jp BxHotEx + +;----------------------------------------------------------- +; Клавиши управл. курсором и комбинации с hot-буквами +;----------------------------------------------------------- +MBcbkey:inc hl + ld a,(hl) ;+2 what + cp 58h ; вверх + jp z,MBup + cp 52h ; вниз + jp z,MBdown + cp 54h ; влево + jp z,MBleft + cp 56h ; вправо + jp z,MBright + cp 57h ; Home + jp z,MBhome + cp 51h ; End + jp z,MBend + cp 44h ; F10 + jr z,MenuExt + ; тест на скен-коды букв. клавиш + ld ix,BarTabl-5 ; рабочая таблица гориз. меню + ld bc,5 + ld h,b +MBcbLp: inc h ; поиск hot-клавиши + add ix,bc + bit 7,(ix+0) ; 80h конец описателя меню ? + ret nz ; не выходить из гориз. меню по не той комб. клавиш + cp (ix+2) ; hot-клавиша ? + jr nz,MBcbLp ; нет + ld a,(CurMenu) ; тек. полож. указателя гориз. меню + cp h + jr nz,MBcbnxt + ld a,(CurMBox) + or a + ret nz ; окно меню открыто +MBcbnxt:ld a,h + ld (CurMenu),a ; тек. полож. указателя гориз. меню + call SetMBar + call ResBarI ; сбросить выдел. указатель + call SetBarI ; вывести выдел. указатель + call ClosBox + jp OpenBox + +; Курсор вверх +MBup: ld a,(CurMBox) + or a + call z,OpenBox ; открыть меню + ld a,(CurMBox) + dec a + jr nz,MBupNxt + ld ix,BoxTabl-2 ; рабочая таблица верт. меню - 2 + ld bc,6 + ld a,b + dec a +MBupLp: inc a ; поиск последнего элемента + add ix,bc + bit 7,(ix+0) + jr z,MBupLp +MBupNxt:ld (CurMBox),a + ld b,a + ld ix,BoxTabl-2 ; рабочая таблица верт. меню - 2 + ld de,6 + add ix,de + djnz $-2 + push ix + call ResBoxI + call SetBoxI + pop ix + ret + +; Курсор вниз +MBdown: ld a,(CurMBox) + or a + jp z,OpenBox + inc a + ld ix,BoxTabl-2 ; рабочая таблица верт. меню - 2 + ld bc,6 + ld h,b ; тест на последний элемент +MBdnLp: inc h + add ix,bc + bit 7,(ix+0) + jr z,MBdnLp + cp h + jr nz,$+4 + ld a,1 + jr MBupNxt + +; Курсор влево +MBleft: ld a,(CurMenu) ; тек. полож. указателя гориз. меню + dec a + jr nz,MBlfNxt + ld ix,BarTabl-5 ; рабочая таблица гориз. меню + ld bc,5 + ld a,b + dec a +MBlfLp: inc a ; поиск последнего пункта + add ix,bc + bit 7,(ix+0) + jr z,MBlfLp +MBlfNxt:ld (CurMenu),a ; тек. полож. указателя гориз. меню + call ResBarI ; сбросить выдел. указатель + call SetBarI ; вывести выдел. указатель + ld a,(CurMBox) + or a + ret z + call ClosBox + jp OpenBox + +; Курсор вправо +MBright:ld a,(CurMenu) ; тек. полож. указателя гориз. меню + inc a + ld ix,BarTabl-5 ; рабочая таблица гориз. меню + ld bc,5 + ld h,b +MBrgLp: inc h ; проверка на последний пункт + add ix,bc + bit 7,(ix+0) + jr z,MBrgLp + cp h + jr nz,$+4 + ld a,1 + jr MBlfNxt + +; Home +MBhome: ld a,(CurMBox) + or a + ret z + dec a + ret z + ld a,1 + jp MBupNxt + +; End +MBend: ld a,(CurMBox) + or a + ret z + ld h,a + ld ix,BoxTabl-2 ; рабочая таблица верт. меню - 2 + ld bc,6 + ld a,b + dec a +MBendLp:inc a ; поиск последнего элемента + add ix,bc + bit 7,(ix+0) + jr z,MBendLp + cp h + ret z + jp MBupNxt + +;------------------------------------------------- +; События мышки +;------------------------------------------------- +MBmouse:ld e,(hl) ;+1 X coord + inc hl + ld d,(hl) ;+2 Y coord + ld a,d + or a + jr nz,MBmousB ; Y<>0 then test on Box Open + ld ix,BarTabl-5 ; рабочая таблица гориз. меню + ld bc,5 + ld h,b + ld a,e ; поиск пункта гориз. меню +MBmous1:inc h + add ix,bc + bit 7,(ix+0) ; конец описателя меню ? + jp nz,CloseBx ; да, закрыть popup-меню + cp (ix+0) + jr c,MBmous1 ; < Xo + cp (ix+1) + jr nc,MBmous1 ; > Xi + ld a,(CurMenu) ; тек. полож. указателя гориз. меню + cp h + jr nz,MBopenB + ld a,(CurMBox) ; Test on current open menu + or a + jp nz,SetMBar +MBopenB:ld a,h ; пункт найден + ld (CurMenu),a ; тек. полож. указателя гориз. меню + call SetMBar + call ClosBox + call ResBarI ; сбросить выдел. указатель + call SetBarI ; вывести выдел. указатель + jp OpenBox + +; Проверка на координаты мышки и окна верт. меню +MBmousB:ld a,(CurMBox) + or a + jp z,MenuExit ; нет откр. popup-меню, выйти в менеджер + ld ix,BoxTabl ; рабочая таблица верт. меню + ld a,e + cp (ix+0) + jr c,MBoxExt ; < Xo + cp (ix+1) + jr nc,MBoxExt ; > Xi + ld a,d + cp (ix+2) + jr c,MBoxExt ; < Yo + cp (ix+3) + jr nc,MBoxExt ; > Yi + dec ix + dec ix + ld bc,6 + ld h,b +MBloopB:inc h + add ix,bc + bit 7,(ix+0) ; конец описателя меню ? + ret nz ; да + ld a,d + cp (ix+2) + jr nz,MBloopB + ld a,e ; поиск пункта меню + cp (ix+0) + jr c,MBloopB ; < Xo + cp (ix+1) + jr nc,MBloopB ; > Xi +BxHotEx:ld a,(CurMBox) + cp h + jr z,BxEnter ; уст. пункт меню + ld a,h + ld (CurMBox),a + push ix + call ResBoxI + call SetBoxI + pop ix + halt + halt + halt + halt + ; выполн. пункта Pop-меню по или мышке +BxEnter:ld hl,what + ld (hl),evCommand ; уст. событие "команда" + inc hl + ld a,(ix+3) + ld (hl),a ;+1 номер команды + call CloseBx ; закрыть верт. меню + pop de + ret ; выйти из гориз. меню + +MBoxExt:call ClosBox ; закрыть верт. меню + jp MenuExit ; выйти в менеджер + ; +CloseBx:call ClosBox ; закрыть верт. меню + jp get_fire + + + + + + +SetMBar:ld a,(BarFlag) + or a + ret nz + ;call ResCurs + jp SetBarI + + +ResMBar:ld a,(BarFlag) + or a + ret z + jp ResBarI + + + + + + +;----------------------------------------------------------- +; Открыть окно вертикального Меню +; +; вход. параметры: (CurMenu) - Number MenuBox +;----------------------------------------------------------- +OpenBox:ld a,1 + ld (CurMBox),a ; номер пункта верт. меню + ld b,a ; нач. верхняя строка окна + ld hl,BarTabl ; табл. гориз. меню (поиск начала меню) + ld a,(CurMenu) + dec a + ld c,a ; *5 + add a,a + add a,a + add a,c + add a,l + ld l,a + jr nc,$+3 + inc h + ; +PutMenu:push iy + ld iy,BoxTabl ; Generes MenuBox mouse table + ld ix,BoxData + ld a,(hl) + dec a + inc hl + ld (iy+0),a ; Xo position MenuBox + inc a + ld (ix+2),a ; Xo for element box + ld (iy+2),b ; Yo position MenuBox + ld (ix+4),b ; Temp Y posit for element box + inc hl + inc hl + ld a,(hl) ; адрес описателя тек. меню + ld (ix+0),a ; сохр. адрес описателя + inc hl + ld h,(hl) + ld (ix+1),h + ld l,a + call GetLenB ; get in DE len Y,X MenuBox + ld a,e ; Xi position MenuBox + sub 2 + ld (ix+5),a ; ширина окна без рамки + ld a,e + add a,(iy+0) + ld (iy+1),a + dec a + ld (ix+3),a ; Xi for element box + ld a,d + add a,(iy+2) ; Yi position MenuBox + ld (iy+3),a + call SaveBox ; сохр. экран под будущим окном + ; + in a,(SLOT3) + push af + ld a,(page_dial_screen) ; Page buffer + out (SLOT3),a + ; начало вставки окна с тенью в буфер + ld hl,LC000+MaxDialWin + ld bc,4 + add iy,bc ; адрес описателя верт. меню + exx + ld hl,LC000 + ld a,(ix+5) ; ширина окна + inc a + inc a + add a,a + ld e,a + ld d,0 + add hl,de + exx + ld a,(color_array+15) ; цвет верт. меню + ld c,a + ; рамка окна + ld (hl),"┌" ; левый верх. угол + inc hl + ld (hl),c ; цвет + inc hl + ld b,(ix+5) ; ширина окна + ld a,"─" + ld (hl),a + inc hl + ld (hl),c + inc hl + djnz $-4 + ld (hl),"┐" ; правый верх. угол + inc hl + ld (hl),c + inc hl + ld b,3 + call copy_cell + exx + ld a,(hl) + inc hl + add hl,de + exx + ld (hl),a + inc hl + ld e,(ix+0) + ld d,(ix+1) +; Цикл вывода пунктов меню +MainPutBox: + inc (ix+4) ; увеличить Y-полож. пункта меню + ld a,(de) + inc de + cp -2 ; разделитель ? + jr nz,PutBln2 + ; вставить разделитель пунктов + ld (hl),"├" + inc hl + ld (hl),c + inc hl + ld b,(ix+5) + ld a,"─" + ld (hl),a + inc hl + ld (hl),c + inc hl + djnz $-4 + ld (hl),"┤" + jr PutBln51 + ; +PutBln2:cp -1 ; конец описателя ? + jp z,BoxExit ; да + ld b,a + ld a,(ix+2) + ld (iy+0),a + inc iy + ld a,(ix+3) + ld (iy+0),a + inc iy + ld a,(ix+4) + ld (iy+0),a + inc iy + ld a,b + ld (iy+0),a + inc iy + ld (hl),"│" + inc hl + ld (hl),c + inc hl + ld (PutBln4+1),hl ; адрес места под метку "√" + ld b,2 ; 2 пробела в начале пункта + ld (hl)," " + inc hl + ld (hl),c + inc hl + djnz $-5 + inc b ; b=1 + ld a,(de) +PutBln3:inc de + cp "&" + call z,Bhotkey1__ ; вставить hot-букву + ld (hl),a ; Put name element + inc hl + ld (hl),c + inc hl + inc b + ld a,(de) + or a ; конец имени ? + jr nz,PutBln3 + inc de + ld a,(de) ; ячейка скен-кода пункта + ld (iy+0),a ; скен-код hot-клавишы в таблицу + inc iy + inc de + ld a,(de) ; ячейка контекста + inc de + ld (iy+0),a ; вставить код контекста + ; вставить метку пункта "√" (если надо) + push hl +PutBln4:ld hl,0 + or a + jr z,PutBln5 + ld (hl),"√" ; пункт "по-умолчанию" +PutBln5:pop hl + inc iy + ld a,(ix+5) ; ширина тек. пункта + dec a + sub b + ld b,a + ld (hl)," " ; заполнить остаток пункта + inc hl + ld (hl),c + inc hl + djnz $-5 + ld (hl),"│" +PutBln51: + inc hl + ld (hl),c + inc hl + exx + ld a,(hl) + inc hl + inc hl + exx + ld (hl),a + inc hl + ld (hl),color_shadow ; цвет тени + inc hl + exx + ld a,(hl) + inc hl + inc hl + add hl,de + exx + ld (hl),a + inc hl + ld (hl),color_shadow ; цвет тени + inc hl + jp MainPutBox ; назад в цикл + + +BoxExit:ld (iy+0),80h ; конец таблицы + ld (hl),"└" + inc hl + ld (hl),c + inc hl + ld b,(ix+5) + ld a,"─" + ld (hl),a + inc hl + ld (hl),c + inc hl + djnz $-4 + ld (hl),"┘" +BoxExit__: + inc hl + ld (hl),c + inc hl + ; вставить 2 тени угла "┘" + ld b,2 + call print_shadow + ; вставить нижнюю тень + ld b,4 + call copy_cell ; скопир. ячейки + ld b,(ix+5) ; Full Len box + inc b + inc b + call print_shadow + pop af + out (SLOT3),a + call PutBox + pop iy + jp SetBoxI ; Set box invert + + +; скопировать ячейки (b=счетчик) +copy_cell: + exx + ld a,(hl) + inc hl + exx + ld (hl),a + inc hl + djnz copy_cell + ret + +; вставить тень +print_shadow: + exx + ld a,(hl) + inc hl + inc hl + exx + ld (hl),a + inc hl + ld (hl),color_shadow ; цвет тени + inc hl + djnz print_shadow + ret + + + +;----------------------------------------------------------- +; Вычислить ширину текущего окна верт. меню +; +; вход: hl=описатель меню +; выход: de=высота/ширина окна +; (доработан к "ширина+2" для дополн. крайних пробелов) +;---------------------------------------------------------- +GetLenB:ld de,0206h + ld b,e + dec b +GetLnL1:ld a,(hl) + inc hl + cp -1 ; конец описателя ? + ret z + cp -2 ; разделитель пунктов ? + jr z,AddLine +GetLnL2:inc b +GetLnL3:ld a,(hl) + inc hl + cp "&" ; кавычка hot-буквы ? + jr z,GetLnL3 + or a ; конец названия пункта ? + jr nz,GetLnL2 ; нет + inc hl + inc hl ; пройти скен-код + ld a,b + cp e + jr c,AddLine + ld e,b +AddLine:inc d + ld b,5 + jr GetLnL1 + + + +;------------------------------------------------- +; Сохранить экран под будущим окном +;------------------------------------------------- +SaveBox:push ix + inc e ; с тенью + inc e + inc d + ld l,(iy+0) ; позиция окна + ld h,(iy+2) + ld a,l + add a,e + cp 80+2 ; за пределом экрана ? + jr c,GetBnxt + sub 80+2 + ld l,a + ld a,(ix+2) + sub l + ld (ix+2),a + ld a,(ix+3) + sub l + ld (ix+3),a + ld a,(iy+0) + sub l + ld (iy+0),a + ld a,(iy+1) + sub l + ld (iy+1),a + ld a,80+2 + sub e + ld l,a +GetBnxt:ld ix,LC000 ; Address Box buffers + ex de,hl + ld (BoxLen+1),hl + ld (BoxPos+1),de + ld a,(page_dial_screen) ; стр. буфера + ld c,0B2h + call scrn4__ + pop ix + ret + + +;------------------------------------------------- +; Вывести окно меню на экран +;------------------------------------------------- +PutBox: push ix + ld ix,LC000+MaxDialWin ; address Box buffers +BoxLen: ld hl,0 ; len box +BoxPos: ld de,0 ; pos box + ld a,(page_dial_screen) ; стр. буфера + ld c,0B3h + call scrn4__ + pop ix + ret + + +;------------------------------------------------- +; Закрыть окно меню и восст. экран +;------------------------------------------------- +ClosBox:ld a,(CurMBox) + or a + ret z + ld ix,LC000 ; Address Box buffers + ld hl,(BoxLen+1) ; len box + ld de,(BoxPos+1) ; pos box + ld a,(page_dial_screen) ; Page buffer + ld c,0B3h + call scrn4__ + xor a + ld (CurMBox),a + ret + + + + + + + + +; Функция вывода Меню выбора. Обработчик событий Меню выбора. + + + +;----------------------------------------------------------- +; Отрисовка меню выбора +; +; вход: hl=таблица меню +; a=полож. пункта меню +;----------------------------------------------------------- +put_menu_select: + ld (CurMBox),a ; номер пункта меню + push iy + ld iy,BoxTabl ; Generes MenuBox mouse table + ld ix,BoxData + ld a,(hl) + dec a + inc hl + ld b,(hl) + inc hl + ld (iy+0),a ; Xo position MenuBox + inc a + ld (ix+2),a ; Xo for element box + ld (iy+2),b ; Yo position MenuBox + ld (ix+4),b ; Temp Y posit for element box + ld e,(hl) + inc hl + ld d,(hl) + inc hl + ld (selmenu_title+1),de ; адрес заголовка окна + ld a,(hl) ; адрес описателя тек. меню + ld (ix+0),a ; сохр. адрес описателя + inc hl + ld h,(hl) + ld (ix+1),h + ld l,a + call GetLenB ; get in DE len Y,X MenuBox + inc e; ; сделать по-шире + ld a,e ; Xi position MenuBox + sub 2 + ld (ix+5),a ; ширина окна без рамки + ld a,e + add a,(iy+0) + ld (iy+1),a + dec a + ld (ix+3),a ; Xi for element box + ld a,d + add a,(iy+2) ; Yi position MenuBox + ld (iy+3),a + call SaveBox ; сохр. экран под будущим окном + in a,(SLOT3) + push af + ld a,(page_dial_screen) ; Page buffer + out (SLOT3),a + ; начало вставки окна с тенью в буфер + ld hl,LC000+MaxDialWin + ld bc,4 + add iy,bc ; адрес описателя верт. меню + exx + ld hl,LC000 + ld a,(ix+5) ; ширина окна + inc a + inc a + add a,a + ld e,a + ld d,0 + add hl,de + exx + ld a,(color_array+15) ; цвет верт. меню + ld c,a + ; центровка заголовка + push hl + ld de,(selmenu_title+1) ; адрес заголовка окна + ld a,(de) ; длина заголовка + ld b,a + ld a,(ix+5) ; ширина окна + sub b + srl a ; /2 + add a,a ; учесть атрибуты (результат всегда четный) + ld e,a + ld d,0 + add hl,de + ld (selmenu_addr+1),hl ; адрес вставки + pop hl + ; рамка окна + ld (hl),"╔" ; левый верх. угол + inc hl + ld (hl),c ; цвет + inc hl + ld b,(ix+5) ; ширина окна + ld a,"═" + ld (hl),a + inc hl + ld (hl),c + inc hl + djnz $-4 + ld (hl),"╗" ; правый верх. угол + inc hl + ld (hl),c + inc hl + ; + push hl +selmenu_title: + ld de,0 ; адрес титла окна +selmenu_addr: + ld hl,0 ; адрес вставки + ld a,(de) + ld b,a ; длина строки + inc de + ld (hl)," " + inc hl + inc hl + ld a,(de) + ld (hl),a + inc hl + inc hl ; атрибут + inc de + djnz $-5 + ld (hl)," " + pop hl + ; + ld b,3 + call copy_cell + exx + ld a,(hl) + inc hl + add hl,de + exx + ld (hl),a + inc hl + ld e,(ix+0) + ld d,(ix+1) +; цикл вывода пунктов меню +selmenu_loop: + inc (ix+4) ; увеличить Y-полож. пункта меню + ld a,(de) + inc de + cp -2 ; разделитель + jr nz,selmenu1__ + ; вставить разделитель пунктов + ld (hl),"╟" + inc hl + ld (hl),c + inc hl + ld b,(ix+5) ; ширина пункта + ld a,"─" + ld (hl),a + inc hl + ld (hl),c + inc hl + djnz $-4 + ld (hl),"╢" + jr selmenu3__ +selmenu1__: + cp -1 ; конец описателя ? + jp z,selmenu4__ ; да + ld b,a + ld a,(ix+2) + ld (iy+0),a + inc iy + ld a,(ix+3) + ld (iy+0),a + inc iy + ld a,(ix+4) + ld (iy+0),a + inc iy + ld a,b + ld (iy+0),a + inc iy + ld (hl),"║" + inc hl + ld (hl),c + inc hl + ld b,2 ; 2 пробела в начале пункта + ld (hl)," " + inc hl + ld (hl),c + inc hl + djnz $-5 + inc b ; b=1 + ld a,(de) +selmenu2__: + inc de + cp "&" + call z,Bhotkey1__ ; вставить hot-букву + ld (hl),a ; Put name element + inc hl + ld (hl),c + inc hl + inc b + ld a,(de) + or a ; конец имени ? + jr nz,selmenu2__ + inc de + ld a,(de) ; ячейка скен-кода пункта + ld (iy+0),a ; скен-код hot-клавишы в таблицу + inc iy + inc de + inc de ; не исп. ячейку контекста + inc iy ; + ld a,(ix+5) ; ширина тек. пункта + dec a + sub b + ld b,a + ld (hl)," " ; заполнить остаток пункта + inc hl + ld (hl),c + inc hl + djnz $-5 + ld (hl),"║" +selmenu3__: + inc hl + ld (hl),c + inc hl + exx + ld a,(hl) + inc hl + inc hl + exx + ld (hl),a + inc hl + ld (hl),color_shadow ; цвет тени + inc hl + exx + ld a,(hl) + inc hl + inc hl + add hl,de + exx + ld (hl),a + inc hl + ld (hl),color_shadow ; цвет тени + inc hl + jp selmenu_loop ; назад в цикл + ; +selmenu4__: + ld (iy+0),80h ; конец таблицы + ld (hl),"╚" + inc hl + ld (hl),c + inc hl + ld b,(ix+5) + ld a,"═" + ld (hl),a + inc hl + ld (hl),c + inc hl + djnz $-4 + ld (hl),"╝" + jp BoxExit__ + + + + +;----------------------------------------------------------- +; +; Обработчик событий Меню выбора +; +;----------------------------------------------------------- +event_menu_select: + call handle_event ; читаем событие + ld hl,what + ld de,event_menu_select + push de + ld a,(hl) ;+0 узнать событие + inc hl + cp evMouseFr ; нажаты бутоны мышки + jp z,sel_menu_mouse + cp evKeyboard ; нажаты обычные клавиши + jr z,sel_menu_keys + cp evCombKey ; нажаты курс. клавиши и служ. + jr z,sel_menu_ckeys + ret + ; +sel_menu_exit: + call CloseBx ; закрыть меню + pop de ; восст. баланс стека + ld hl,what + ld (hl),evNothing ; "нет событий" + ret + +;------------------------------------------------- +; Обычные клавиши +;------------------------------------------------- +sel_menu_keys: + ld a,(hl) ;+1 код клавиши + cp 1Bh ; Esc + jr z,sel_menu_exit + cp 0Dh ; Enter + jr nz,sel_menu_keys1 + ld a,(CurMBox) ; if not box then open + ld b,a + ld ix,BoxTabl-2 ; поиск пункта верт. меню + ld de,6 + add ix,de + djnz $-2 + jp BxEnter + ; +sel_menu_keys1: + inc hl + ld a,(hl) ;+2 скен-код клавиши + ld ix,BoxTabl-2 ; рабочая таблица верт. меню - 2 + ld bc,6 + ld h,b +sel_menu_keys2: + inc h + add ix,bc + bit 7,(ix+0) ; конец описателя меню ? + ret nz ; да, hot-клавиша не найдена + cp (ix+4) ; скен-код hot-клавиши + jr nz,sel_menu_keys2 + jp BxHotEx + +;------------------------------------------------- +; Клавиши управл. курсором и F10 +;------------------------------------------------- +sel_menu_ckeys: + inc hl + ld a,(hl) ;+2 what + cp 44h ; F10 + jr z,sel_menu_exit + cp 58h ; вверх + jp z,MBup + cp 52h ; вниз + jp z,MBdown + cp 54h ; влево + jp z,MBup + cp 56h ; вправо + jp z,MBdown + cp 57h ; Home + jp z,MBhome + cp 51h ; End + jp z,MBend + ret + +;------------------------------------------------- +; События мышки +;------------------------------------------------- +sel_menu_mouse: + ld e,(hl) ;+1 X coord + inc hl + ld d,(hl) ;+2 Y coord + ; проверка на коорд. мышки и окна + ld ix,BoxTabl ; рабочая таблица + ld a,e + cp (ix+0) + jp c,sel_menu_exit ; < Xo + cp (ix+1) + jp nc,sel_menu_exit ; > Xi + ld a,d + cp (ix+2) + jp c,sel_menu_exit ; < Yo + cp (ix+3) + jp nc,sel_menu_exit ; > Yi + dec ix + dec ix + ld bc,6 + ld h,b +selmenu_mouse_loop: + inc h + add ix,bc + bit 7,(ix+0) ; конец описателя меню ? + ret nz ; да + ld a,d + cp (ix+2) + jr nz,selmenu_mouse_loop + ld a,e ; поиск пункта меню + cp (ix+0) + jr c,selmenu_mouse_loop ; < Xo + cp (ix+1) + jr nc,selmenu_mouse_loop ; > Xi + jp BxHotEx + + + + + + + +;------------------------------------------------- +; Настройка "√" меток пунктов меню +;------------------------------------------------- +prep_default_puncts: + ld c,CTdef ; "√" по-умолчанию выделено + ld a,CTnodef ; " " по-умолчанию не выделено + ; Сбросить пункты + ; Left-меню + ld (LBrief),a + ld (LMed),a + ld (LFull),a + ld (LInfo),a + ld (LQview),a + ; сортировка + ld (LName),a + ld (LExt),a + ld (LDate),a + ld (LSize),a + ld (LUnsort),a + ; Right-меню + ld (RBrief),a + ld (RMed),a + ld (RFull),a + ld (RInfo),a + ld (RQview),a + ; сортировка + ld (RName),a + ld (RExt),a + ld (RDate),a + ld (RSize),a + ld (RUnsort),a + ; Настроить пункты + ld hl,LFull + ld a,(format_mode) ; формат акт. панели + bit 0,a ; full + jr nz,prep_default1__ + ld hl,LMed + bit 1,a ; medium + jr nz,prep_default1__ + ld hl,LBrief + bit 2,a ; brief + jr nz,prep_default1__ + ld hl,LInfo + bit 3,a ; info + jr nz,prep_default1__ + ld hl,LQview ; qview +prep_default1__: + ld (hl),c + ; сортировка + ld hl,LName + ld a,(sort_type) ; сорт. акт. панели + cp "n" + jr z,prep_default2__ + ld hl,LExt + cp "x" + jr z,prep_default2__ + ld hl,LDate + cp "d" + jr z,prep_default2__ + ld hl,LSize + cp "s" + jr z,prep_default2__ + ld hl,LUnsort +prep_default2__: + ld (hl),c + ; Right-меню + ld hl,RFull + ld a,(format_mode1) ; формат пасс. панели + bit 0,a ; full + jr nz,prep_default3__ + ld hl,RMed + bit 1,a ; medium + jr nz,prep_default3__ + ld hl,RBrief + bit 2,a ; brief + jr nz,prep_default3__ + ld hl,RInfo + bit 3,a ; info + jr nz,prep_default3__ + ld hl,RQview ; qview +prep_default3__: + ld (hl),c + ; сортировка + ld hl,RName + ld a,(sort_type1) ; сорт. пасс. панели + cp "n" + jr z,prep_default4__ + ld hl,RExt + cp "x" + jr z,prep_default4__ + ld hl,RDate + cp "d" + jr z,prep_default4__ + ld hl,RSize + cp "s" + jr z,prep_default4__ + ld hl,RUnsort +prep_default4__: + ld (hl),c + ret diff --git a/OBJS/INLINE.ASM b/OBJS/INLINE.ASM new file mode 100755 index 0000000..1b4b939 --- /dev/null +++ b/OBJS/INLINE.ASM @@ -0,0 +1,1207 @@ +; Содержит объекты ~Input Line~ и ~Inp Line~ (ввод даты/времени файлов) +; + + + + + +;===================================================================== +; Прорисовка объекта +; object ~Input Line~ (имеет фокус) +; Input: HL-описатель объекта +; Format table (данная таблица в DialTab): +; +0 - номер объекта ~Input Line~ +; +1 - Xo левая позиция объекта +; +2 - Xi правая позиция объекта +; +3 - Y позиция объекта +; +4 - Xi position text (позиция имени кластера ?) +; +5 - Xo левая позиция поля ввода +; +6 - ;Hot-keys (имени кластера) +; +7 - контекст +; +8,9 - адрес структуры строки ввода +;--------------------------------------------------------------------- +; Формат описателя: +; db InputLine ; номер объекта +; dw 0503h ; Yo,Xo +; db 10 ; ширина поля ввода +; db 1 ; контекст +; dw InputBuffer ; структура строки ввода +;===================================================================== +PutInputLine: + push iy ; iy=DialTab+5 + inc iy ; пройти ячейку длины данной таблицы + ld (iy+0),a ;+0 номер объекта "Input Line" + ld a,(hl) ; X pos + inc hl + ld c,a + add a,(ix+0) ; X полож. от начала экрана + ld (iy+1),a ;+1 Xo + ld (ix+4),a ; X temp coord + ld a,(hl) ; Y pos + inc hl + ld b,a + add a,(ix+1) ; Pos Y от начала экрана + ld (iy+3),a ;+3 Yo позиция курсора + call GetPutA + ld a,(ix+4) ; левый край поля ввода (экран. координаты) + ld (iy+4),a ; Xi правая позиция начала текста + ld (iy+5),a ;+5 Xi правая позиция курсора + ld (pInputAddr+1),de ; адрес в экран. буфере + ld a,(hl) ; ширина поля ввода (из описателя) + ld (pInputWidth+1),a + inc hl + ld a,(hl) ; контекст + inc hl + ld (iy+7),a ;+7 + ld e,(hl) + inc hl + ld d,(hl) + ld (iy+8),e ;+8 de=структура строки ввода + ld (iy+9),d ;+9 + inc hl + inc de ; пройти ячейку "+0" + ; Инициализация структуры строки ввода + push hl + ld hl,4 ; смещ. до буфера строки + add hl,de + xor a + ld c,a + ld b,a + cpir ; найти конец строки + ld a,c + cpl + ld b,a ; длина строки + ld c,0 ; смещ. строки за левый край + ld a,(pInputWidth+1) ; ширина поля ввода + sub b ; ширина поля - длина строки + jr nc,pInputLine1 ; строка короче поля редактирования + neg + inc a + ld c,a ; смещ. строки за левый край + ld a,(pInputWidth+1) ; ширина поля ввода + dec a + jr $+3 +pInputLine1: + ld a,b + pop hl + ex de,hl + ld (hl),1 ;+1 флаг=1 ReadyString + inc hl + ld (hl),a ;+2 X позиция курсора в пределах строки + inc hl + ld (hl),c ;+3 X смещ. строки за левый край + inc hl + ld (hl),b ;+4 кол-во введ. символов + inc hl + ex de,hl + push hl + add a,(iy+5) ; X позиция курсора + ld l,a + ld h,(iy+3) ; Y позиция курсора + ld (CursorPos),hl ; Y/X позиция курсора + ld b,0 + ex de,hl + add hl,bc ; de=остаток видимой строки + ex de,hl + ; перекачать данные из буфера строки в экран. буфер +pInputAddr: + ld hl,0 ; адрес в экран. буфере + ld a,(color_array+33) ; цвет строки ввода + and 0F0h + or 08h + ld c,a ; цвет не редакт. строки ввода +pInputWidth: + ld b,1 ; ширина поля ввода + ld a,(de) + inc de + ld (hl),a + inc hl + ld (hl),c ; цвет строки + inc hl + inc (ix+4) ; X ++правый край поля ввода (экран. координаты) + djnz $-9 +pInputLine2: ; из "PutInpLine" + pop hl + ld a,(ix+4) ; X правый край поля ввода (экран. координаты) + ld (iy+2),a ; Xi правая позиция объекта + ld bc,10 ; размер таблицы + add iy,bc ; IY-next element + ; сохр. размер таблицы в Таблице объектов + push iy + exx + pop hl + pop de ; de=iy + and a + sbc hl,de ; длина таблицы "Input Line" + ld a,l + ld (de),a ; DialTab+5 + exx + ret + + + + + +;===================================================================== +; +; Обработчик событий объектов "Input Line" +; +;===================================================================== +step_scroll equ 1 ; шаг скроллинга + + +EvInputLine: + ld hl,what ; список событий + ld a,(hl) + inc hl + cp evMouseFr + jr z,EvInputMouse + cp evKeyboard + jr z,EvInputKeys + cp evCombKey + jp z,EvInputComb + ret + +; Событие - Мышка +EvInputMouse: + LD E,(HL) ; X coord + INC HL + LD D,(HL) ; Y coord + LD A,D + CP (IX+4) ; Y pos input line + RET NZ + LD A,E + BIT 7,(IX+2) + JR NZ,$+6 + CP (IX+2) ; Xo pos + RET C + BIT 7,(IX+3) + RET NZ + CP (IX+3) ; Xi pos + RET NC + BIT 7,(IX+1) ; Sel or nosel + JR Z,SetInputLine ; выделить, объект не в фокусе + BIT 7,(IX+6) + JR NZ,$+6 + CP (IX+6) ; Xo input line + RET C + SUB (IX+6) ; Shift from begin + LD C,A + LD L,(IX+9) ; структура буфера + LD H,(IX+10) + INC HL + LD (HL),0 ;+1 уст. флаг "не стирать строку" + INC HL + CP (HL) ;+2 X тек. полож. курсора в строке + RET Z + ;PUSH HL + INC HL + ADD A,(HL) ;+3 X смещ. строки за левый край + INC HL + CP (HL) ;+4 число введ. символов + LD A,(HL) + ;POP HL + dec hl; + dec hl; + JR Z,EIM + JR C,EIM + INC HL + SUB (HL) ;+3 + DEC HL + LD C,A +EIM: ld (hl),c ;+2 X тек. полож. курсора в строке + dec hl + dec hl + push iy + push hl + pop iy + call PrnInLn ; вывести строку на экран + pop iy + jr InputLineExt + +; Событие - обычная клавиша +EvInputKeys: + bit 7,(ix+1) ; Sel or nosel + jr nz,InputLineWork ; объект уже выделен + ld a,(hl) ;+1 what + cp 9 ; Tab + ret nz +; фокус на объект "Input Line" +SetInputLine: + call MoveObj ; Select "Input line" + call ResDialInv ; Reset previos object + ld ix,DialTab+5 ; Таблица объектов + push iy + ld l,(ix+9) ; hl=структура строки ввода "Input Line" + ld h,(ix+10) + push hl + pop iy + inc hl + ld (hl),1 ;+1 флаг ReadyString (1=очистить строку при вводе) + ld a,(color_array+33) ; цвет строки ввода + and 0F0h + or 08h + ld (ColorInLn+1),a ; цвет не редакт. строки + call PrnInLn ; вывести строку на экран + ld a,(color_array+33) + ld (ColorInLn+1),a ; восст. цвет + pop iy + call PILCurs ; вкл. курсор + ei +InputLineExt: + ld hl,what ; поле событий + ld (hl),evNothing + jp get_fire + +; Работа в строке редактирования +InputLineWork: + LD A,(HL) ; what+1 код клавиши + CP 8 ; "забой" + JR Z,$+5 + CP " " + RET C + PUSH IY + LD DE,InputLineWex + PUSH DE + LD L,(IX+9) ; hl=структура строки ввода + LD H,(IX+10) + PUSH HL + POP IY + ex af,af' + res 7,(iy+1) ;+1 флаг ReadyString + ld a,(D0642) ; флаги клавы + bit 1,a ; бит Ins + ld a,1 ; вставка + jr nz,$+3 + dec a ; замена + and 1 + rrca ; вправо (мл.бит -> перенос) + or (iy+1) + ld (iy+1),a + ex af,af' + CP 8 ; "забой" + JP Z,BackDelete + EX AF,AF' + BIT 0,(IY+1) ;+1 флаг ReadyString + CALL NZ,ClearIL ; очистить всю строку и ее буфер + LD A,(IY+4) ; InputSymb + CP (IY+0) ; Max len + JR NZ,InLineWork + LD A,(IY+2) + ADD A,(IY+3) + CP (IY+0) + RET NC + BIT 7,(IY+1) + RET NZ +InLineWork: + LD A,(IY+4) + SUB (IY+3) + SUB (IY+2) + JR Z,NoInsert + DEC (IY+4) + BIT 7,(IY+1) + JR Z,NoInsert + INC (IY+4) + ; ввод в середину текста (вставка) + LD C,A + LD B,0 + LD L,(IX+9) + LD H,(IX+10) + LD A,(IY+4) + ADD A,L + LD L,A + JR NC,$+3 + INC H + INC HL + INC HL + INC HL + INC HL + INC HL + LD D,H + LD E,L + DEC HL + LDDR +NoInsert: + LD L,(IX+9) + LD H,(IX+10) + LD A,(IY+2) + ADD A,(IY+3) + ADD A,L + LD L,A + JR NC,$+3 + INC H + INC HL + INC HL + INC HL + INC HL + INC HL + EX AF,AF' + LD (HL),A + INC (IY+4) + INC (IY+2) + LD A,(IX+3) + SUB (IX+6) + CP (IY+2) ; X тек. полож. курсора в пределах строки + CALL Z,OutIL ; курсор за полем ввода + CALL PrnInLn ; вывести строку на экран + POP DE +InputLineWex: + LD HL,what ; поле событий + LD (HL),evNothing + POP IY + RET + +; Курсор за полем ввода +OutIL: ld a,(iy+3) + add a,step_scroll ; шаг скроллинга + ld (iy+3),a + ld a,(iy+2) + sub step_scroll ; шаг скроллинга + ld (iy+2),a + ret + +; Очистить редакт. строку +ClearIL:xor a + ld b,(iy+0) ;+0 длина буфера редакт. строки + ld l,(ix+9) ; hl=структура строки ввода + ld h,(ix+10) + inc hl + inc hl + inc hl + inc hl + inc hl ;+5 буфер редакт. строки + ld (hl),a + djnz $-2 + ld (iy+2),a ;+2 X позиция курсора в пределах строки + ld (iy+3),a ;+3 X смещ. строки за левый край + ld (iy+4),a ;+4 сбр. число введенных символов + res 0,(iy+1) ;+1 сбр. флаг ReadyString + ret + +; Событие - курс. клавиши или комбинации +EvInputComb: + bit 7,(ix+1) ; sel or nosel + jr nz,EvInputComb1 ; объект уже выделен + ld b,(hl) ;+1 what + inc hl + ld a,(hl) ;+2 what + cp 56h ; курсор вправо + jp z,SetInputLine + push ix + ld e,(ix+0) ; размер таблицы "Input Line" + ld d,0 + add ix,de + bit 7,(ix+0) + pop ix + ret z ; еще не конец объектов + cp 54h ; курсор влево + jp z,SetInputLine + ld a,b + and 00111111b ; биты Ctrl, Alt + ret nz + ld a,(hl) ;+2 what + cp 15+80h ; Tab скен-код+80h + ret nz + jp SetInputLine ; Shift+Tab, на предыдущий объект + ; +EvInputComb1: + push iy + inc hl + ld a,(hl) ;+2 what + ld l,(ix+9) ; Address buffer + ld h,(ix+10) + ld de,InputLineWex + push de + push hl + pop iy + cp 54h ; курсор влево + jr z,InputLeft + cp 56h ; курсор вправо + jr z,InputRight + cp 4Fh ; Del удалить символ в тек. позиции + jp z,InputDel + cp 57h ; Home в начало строки + jp z,InputHome + cp 51h ; End в конец строки + jp z,InputEnd + pop de + pop iy + ret + +; Курсор влево на одно место +InputLeft: + ld a,(iy+2) + dec a + jp p,InLeft + ld a,(iy+3) + sub step_scroll ; шаг скроллинга + ret c ; курсор в крайнем левом полож. + ld (iy+3),a ; X смещ. строки за левый край (в символах) + ld a,(iy+2) ; X полож. курсора в пределах строки + add a,step_scroll-1 ; шаг скроллинга +InLeft: ld (iy+2),a + call PrnInLn ; вывести строку на экран + res 0,(iy+1) ;+1 ReadyString сбр.флаг "стереть строку" + ret + +; Курсор вправо на одно место +InputRight: + ld a,(iy+2) + add a,(iy+3) + cp (iy+4) + jr z,InputRight2 ; для "сменить цвет строки" + ld a,(ix+3) + sub (ix+6) + ld b,a + ld a,(iy+2) + inc a + cp b + jr nz,InRight + ld a,(iy+3) ; X смещ. строки за левый край (в символах) + add a,step_scroll ; шаг скроллинга + ld (iy+3),a + ld a,(iy+2) ; X полож. курсора в пределах строки + sub step_scroll-1 ; шаг скроллинга +InRight:ld (iy+2),a +InputRight2: + call PrnInLn ; вывести строку на экран + res 0,(iy+1) ;+1 ReadyString сбр.флаг "стереть строку" + ret + +; Забой - удалить символ левее курсора +BackDelete: + LD A,(IY+2) + OR A + JR NZ,BackDelete1 + LD A,(IY+3) + SUB step_scroll ; шаг скроллинга + RET C + LD (IY+3),A + LD A,(IY+2) + ADD A,step_scroll ; шаг скроллинга + LD (IY+2),A +BackDelete1: + LD L,(IX+9) + LD H,(IX+10) + LD A,(IY+2) + ADD A,(IY+3) + ADD A,L + LD L,A + JR NC,$+3 + INC H + INC HL + INC HL + INC HL + INC HL + INC HL + LD D,H + LD E,L + DEC DE + LD A,(IY+4) + SUB (IY+3) + SUB (IY+2) + jr z,$+7 + LD C,A + LD B,0 + LDIR + xor a + ld (de),a + DEC (IY+2) ; X полож. курсора в пределах строки + DEC (IY+4) ; число введ. символов + CALL PrnInLn ; вывести строку на экран + RES 0,(IY+1) ;+1 ReadyString сбр.флаг "стереть строку" + RET + +; Delete - удалить символ в тек. позиции +InputDel: + LD L,(IX+9) + LD H,(IX+10) + LD A,(IY+2) + INC A + ADD A,(IY+3) + ADD A,L + LD L,A + JR NC,$+3 + INC H + INC HL + INC HL + INC HL + INC HL + INC HL + LD D,H + LD E,L + DEC DE + LD A,(IY+4) + SUB (IY+3) + SUB (IY+2) + RET Z + LD C,A + LD B,0 + LDIR + SUB A + LD (DE),A + DEC (IY+4) ; число введ. символов + CALL PrnInLn ; вывести строку на экран + RES 0,(IY+1) ;+1 ReadyString сбр.флаг "стереть строку" + RET + +; Home - в начало строки +InputHome: + ld a,(iy+2) ; X полож. курсора в пределах строки + add a,(iy+3) ; смещ. строки за левый край + ret z + xor a + ld (iy+2),a ; X полож. курсора в пределах строки + ld (iy+3),a ; смещ. строки за левый край + call PrnInLn ; вывести строку на экран + res 0,(iy+1) ;+1 ReadyString сбр.флаг "стереть строку" + ret + +; End - в конец строки +InputEnd: + ld a,(iy+4) + sub (iy+3) + cp (iy+2) + jr z,InEnd1 ; для "сменить цвет строки" + add a,(iy+3) + ld c,a + ld (iy+3),0 + ld a,(ix+3) + sub (ix+6) + sub c + jr z,$+6 + jr nc,InEndNIL + neg +InEndLp:ld c,a + ld a,(iy+3) ; X смещ. строки за левый край (в символах) + add a,step_scroll ; шаг скроллинга + ld (iy+3),a + ld a,c + sub step_scroll ; шаг скроллинга + jr nc,InEndLp +InEndNIL: + ld a,(iy+4) + sub (iy+3) + ld (iy+2),a ; X полож. курсора в пределах строки +InEnd1: call PrnInLn ; вывести строку на экран + res 0,(iy+1) ;+1 ReadyString сбр.флаг "стереть строку" + ret + + + + + +;----------------------------------------------------------- +; Вывод строки объекта "Input Line" на экран +;----------------------------------------------------------- +PrnInLn:LD A,(CurILFl) + PUSH AF + CALL ResILCr ; выкл. курсор + LD HL,0 + LD E,(IX+6) ;Xo pos inp.line + LD D,(IX+4) ;Y pos object + BIT 7,(IX+3) + JP NZ,prne + BIT 7,E + JR Z,$+7 ; -> "ld a,e" + LD A,E + NEG + LD L,A + LD E,H + LD (prnadd+1),HL + LD C,84h ; уст. позицию курсора + RST 08h + LD L,(IX+9) ; hl=структура строки ввода + LD H,(IX+10) + LD A,(IY+3) + ADD A,L + LD L,A + JR NC,$+3 + INC H + INC HL + INC HL + INC HL + INC HL + INC HL + LD A,(IX+3) ; Xi - Xo (inp.line) = Len inp.line + SUB (IX+6) + LD E,A + LD C,A + LD B,A + LD A,(IX+6) + ADD A,C + CP 80+1 + JR C,$+8 + LD A,80 + SUB (IX+6) + LD B,A + BIT 7,(IX+6) + JR Z,$+11 + LD A,(IX+6) + NEG + SUB C + NEG + LD B,A + PUSH BC + SUB A + LD B,E + ld de,work_buffer ; раб. буфер InputLine + PUSH DE + LD (DE),A + INC DE + DJNZ $-2 + LD A,(IY+0) + SUB (IY+3) + CP C + JR NC,$+3 + LD C,A + LD B,0 + LD A,(IY+4) + SUB C + JR NC,$+4 + ADD A,C + LD C,A + POP DE + PUSH DE + LD A,B + OR C + JR Z,$+4 + LDIR + POP HL + POP BC +prnadd: LD DE,0 + ADD HL,DE + LD A,B ; длина строки + OR A + JR Z,prne +ColorInLn: + ld e,31h ; цвет выдел. объекта (color_array+26) + ld c,85h ; вывод строки с атрибутами + RST 08h +prne: LD A,(IY+2) + ADD A,(IX+6) + LD E,A + LD D,(IX+4) + LD (CursorPos),de ; Y/X позиция курсора + POP AF + OR A + CALL NZ,PILCurs ; вкл. курсор + EI + PUSH IY + LD IY,DialData ; таблица осн. диал. окна + LD A,(IX+6) + SUB (IY+0) + LD C,A + LD A,(IX+4) + SUB (IY+1) + LD B,A + POP IY + PUSH IX + LD IX,DialData ; таблица осн. диал. окна + CALL GetPutA + POP IX + ld hl,work_buffer ; раб. буфер InputLine + LD A,(IX+3) ; Xi - Xo (inp.line) = Len inp.line + SUB (IX+6) + LD C,A + LD B,0 + IN A,(SLOT3) + PUSH AF + LD A,(page_dial_screen) + OUT (SLOT3),A + LDI + INC DE + JP PE,$-3 + POP AF + OUT (SLOT3),A + RET + + + +;------------------------------------------------- +; Установить фокус на объект "Input Line" +;------------------------------------------------- +InpLineI: + ld de,color_array+33 ; цвет строки ввода + ld (set_dial_tmp_inv+1),de + ld e,(ix+2) ; Xo left коорд. имени кластера + ld d,(ix+4) ; Y + ld a,(ix+5) ; Xi right коорд. имени кластера + sub e + ld c,a ; длина выдел. метки + call SetDialInv + ld de,color_array+26 ; цвет Selected title (объекта) + ld (set_dial_tmp_inv+1),de + ld de,(CursorPos) ; Y/X позиция курсора + call PILCurs ; вкл. курсор + ei + ret + + + + + +;--------------------------------------------------------------------- + + + + + +;===================================================================== +; Прорисовка объекта ~Inp Line~ +; +; Отличие от "Input Line" - режим "замены" текста; нет цвета не ред. +; строки; при получении фокуса курсор уст. в начало строки. +; Вводятся только символы 0..9, ".", ":". +; +; object ~Inp Line~ (имеет фокус) +; Input: HL-описатель объекта +; Format table (данная таблица в DialTab): +; +0 - номер объекта ~Input Line~ +; +1 - Xo левая позиция объекта +; +2 - Xi правая позиция объекта +; +3 - Y позиция объекта +; +4 - Xi position text (позиция имени кластера ?) +; +5 - Xo левая позиция поля ввода +; +6 - ;Hot-keys (имени кластера) +; +7 - контекст +; +8,9 - адрес структуры строки ввода +;--------------------------------------------------------------------- +; Формат описателя: +; db InpLine ; номер объекта +; dw 0503h ; Yo,Xo +; db 12 ; ширина поля ввода +; db 4 ; контекст +; dw Buffer ; структура строки ввода +;===================================================================== +PutInpLine: + push iy ; iy=DialTab+5 + inc iy ; пройти ячейку длины данной таблицы + ld (iy+0),a ;+0 номер объекта "Input Line" + ld a,(hl) ; X pos + inc hl + ld c,a + add a,(ix+0) ; X полож. от начала экрана + ld (iy+1),a ;+1 Xo + ld (ix+4),a ; X temp coord + ld a,(hl) ; Y pos + inc hl + ld b,a + add a,(ix+1) ; Pos Y от начала экрана + ld (iy+3),a ;+3 Yo позиция курсора + call GetPutA + ld a,(ix+4) ; левый край поля ввода (экран. координаты) + ld (iy+4),a ; Xi правая позиция начала текста + ld (iy+5),a ;+5 Xi правая позиция курсора + ld (pInpAddr__+1),de ; адрес в экран. буфере + ld b,(hl) ; ширина поля ввода (из описателя) + inc hl + ld a,(hl) ; контекст + inc hl + ld (iy+7),a ;+7 + ld e,(hl) + inc hl + ld d,(hl) + ld (iy+8),e ;+8 de=структура строки ввода + ld (iy+9),d ;+9 + inc hl + inc de ; пройти ячейку "+0" + ; иниц. структуры строки ввода + ex de,hl + xor a + ld (hl),a ;+1 флаг=0 ReadyString (не очищать строку) + inc hl + ld (hl),a ;+2 X позиция курсора в пределах строки + inc hl + ld (hl),a ;+3 X смещ. строки за левый край + inc hl + ld (hl),b ;+4 кол-во введ. символов + inc hl + ;cp (hl) ;+5 есть строка? + ;jr nz,$+5 ; да + ;dec hl + ;ld (hl),a ;+4 нет введ. символов + ;inc hl + ex de,hl + push hl + add a,(iy+5) ; X позиция курсора + ld l,a + ld h,(iy+3) ; Y позиция курсора + ld (CursorPos),hl ; Y/X позиция курсора + ; перекачать данные из буфера строки в экран. буфер +pInpAddr__: + ld hl,0 ; адрес в экран. буфере + ld a,(color_array+33) ; цвет строки ввода + ld c,a + ; b=ширина поля ввода + ;dec de + ;ld a,(de) ;+4 число введ. символов + ;inc de + ;or a + ;jr z,pInpBlank ; нет строки + ld a,(de) + inc de + ld (hl),a + inc hl + ld (hl),c ; цвет строки + inc hl + inc (ix+4) ; X ++правый край поля ввода (экран. координаты) + djnz $-9 + jp pInputLine2 + ; +;pInpBlank: + ;ld a," " + ;ld (hl),a + ;inc hl + ;ld (hl),c ; цвет строки + ;inc hl + ;inc (ix+4) ; X ++правый край поля ввода (экран. координаты) + ;djnz $-7 + ;jp pInputLine2 + + + + +;===================================================================== +; +; Обработчик событий объектов ~Inp Line~ +; +;===================================================================== +EvInpLine: + ld hl,what ; список событий + ld a,(hl) + inc hl + cp evMouseFr + jr z,EvInpMouse + cp evKeyboard + jr z,EvInpKeys + cp evCombKey + jp z,EvInpComb + ret + +; Событие - Мышка +EvInpMouse: + ld e,(hl) ; X coord + inc hl + ld d,(hl) ; Y coord + ld a,d + cp (ix+4) ; Y pos input line + ret nz + ld a,e + bit 7,(ix+2) + jr nz,$+6 + cp (ix+2) ; Xo pos + ret c + bit 7,(ix+3) ; Xi правый край поля ввода + ret nz + cp (ix+3) ; Xi правый край поля ввода + ret nc + bit 7,(ix+1) ; Sel or nosel + jr z,SetInpLine ; выделить - объект не в фокусе + bit 7,(ix+6) + jr nz,$+6 + cp (ix+6) ; Xo input line + ret c + sub (ix+6) ; Shift from begin + ld c,a + ld l,(ix+9) ; структура буфера + ld h,(ix+10) + inc hl + ld (hl),0 ;+1 уст. флаг "не стирать строку" + inc hl + cp (hl) ;+2 X тек. полож. курсора в строке + ret z + push hl + inc hl + inc hl + cp (hl) ;+4 число введ. символов + ld a,(hl) + pop hl + jr z,$+5 + jr c,$+3 + ld c,a ; число введ. символов + ld (hl),c + dec hl + dec hl + push iy + push hl + pop iy + call PrnInLn ; вывести строку на экран + pop iy + jr InpLineExt + +; Событие - обычная клавиша +EvInpKeys: + bit 7,(ix+1) ; Sel or nosel + jr nz,InpLineWork ; объект уже выделен + ld a,(hl) ;+1 what + cp 9 ; Tab + ret nz +; фокус на объект "Inp Line" +SetInpLine: + call MoveObj ; Select "Inp line" + call ResDialInv ; Reset previos object + ld ix,DialTab+5 ; Таблица объектов + push iy + ld l,(ix+9) ; hl=структура строки ввода "Inp Line" + ld h,(ix+10) + push hl + pop iy + inc hl + xor a + ld (hl),a ;+1 флаг ReadyString (1=очистить строку при вводе) + inc hl + ld (hl),a ;+2 X позиция курсора в пределах строки + inc hl + ld (hl),a ;+3 X смещ. строки за левый край + inc hl + call PrnInLn ; вывести строку на экран + pop iy + call PILCurs ; вкл. курсор + ei +InpLineExt: + ld hl,what ; поле событий + ld (hl),evNothing + jp get_fire + +; Работа в строке редактирования +InpLineWork: + ld a,(hl) ; what+1 код клавиши + cp 8 ; "забой" + jr z,$+12 + cp "." + jr z,$+8 + cp "0" + ret c + cp ":"+1 + ret nc + ; символы ".", 0..9, ":" + push iy + ld de,InpLineWex + push de + ld l,(ix+9) ; структура буфера + ld h,(ix+10) + push hl + pop iy + ex af,af' + res 7,(iy+1) ;+1 флаг ReadyString + ld a,1; ; 01/00 вставка/замена + and 1 + rrca ; вправо (мл.бит -> перенос) + or (iy+1) + ld (iy+1),a ;+1 флаг ReadyString + ex af,af' + cp 8 ; "забой" + jp z,BackDel + ex af,af' + ld a,(iy+4) ;+4 число введ. символов + cp (iy+0) ;+0 макс. длина строки + jr z,no_ins + sub (iy+2) ; X тек. полож. курсора в строке + jr z,no_ins ; не раздв. строку + dec (iy+4) ;+4 число введ. символов + bit 7,(iy+1) ;+1 флаг ReadyString + jr z,no_ins ; не раздв. строку + inc (iy+4) ;+4 число введ. символов + ; ввод в середину текста (вставка) + ld c,a + ld b,0 + ld l,(ix+9) ; структура буфера + ld h,(ix+10) + ld a,(iy+4) ;+4 число введ. символов + add a,l + ld l,a + jr nc,$+3 + inc h + inc hl + inc hl + inc hl + inc hl + inc hl + ld d,h + ld e,l + dec hl + lddr +no_ins: ld l,(ix+9) ; структура буфера + ld h,(ix+10) + ld a,(iy+2) ; X тек. полож. курсора в строке + add a,l + ld l,a + jr nc,$+3 + inc h + inc hl + inc hl + inc hl + inc hl + inc hl + ex af,af' + ld (hl),a ; сохр. символ в строке + ld a,(iy+4) ; число введ. символов + cp (iy+0) ; макс. длина строки + jr z,$+5 ; вся строка заполнена + inc (iy+4) ; ++число введ. символов + inc (iy+2) ; X ++полож. курсора в строке + ld a,(ix+3) ; Xi правый край поля ввода + sub (ix+6) ; Xo левый край поля + cp (iy+2) ; X тек. полож. курсора в строке + jr nz,$+5 ; курсор не за полем ввода + dec (iy+2) ; X --полож. курсора + call PrnInLn ; вывести строку на экран + pop de +InpLineWex: + ld hl,what ; поле событий + ld (hl),evNothing + pop iy + ret + + +; Событие - курс. клавиши или комбинации +EvInpComb: + bit 7,(ix+1) ; sel or nosel + jr nz,EvInpComb1 ; объект уже выделен + ld b,(hl) ;+1 what + inc hl + ld a,(hl) ;+2 what + cp 56h ; курсор вправо + jp z,SetInpLine + push ix + ld e,(ix+0) ; размер таблицы "Inp Line" + ld d,0 + add ix,de + bit 7,(ix+0) + pop ix + ret z ; еще не конец объектов + cp 54h ; курсор влево + jp z,SetInpLine + ld a,b + and 00111111b ; биты Ctrl, Alt + ret nz + ld a,(hl) ;+2 what + cp 15+80h ; Tab скен-код+80h + ret nz + jp SetInpLine ; Shift+Tab, на предыдущий объект + ; +EvInpComb1: + push iy + inc hl + ld a,(hl) ;+2 what + ld l,(ix+9) ; структура буфера + ld h,(ix+10) + ld de,InpLineWex + push de + push hl + pop iy + cp 54h ; курсор влево + jr z,InpLeft + cp 56h ; курсор вправо + jr z,InpRight + cp 4Fh ; Del удалить символ в тек. позиции + jp z,InpDel + cp 57h ; Home в начало строки + jp z,InpHome + cp 51h ; End в конец строки + jp z,InpEnd + pop de + pop iy + ret + +; Курсор влево на одно место +InpLeft:ld a,(iy+2) ; X тек. полож. курсора в строке + dec a + ret m ; за левым краем поля +InpPrint: + ld (iy+2),a + jp PrnInLn ; вывести строку на экран + +; Курсор вправо на одно место +InpRight: + ld a,(iy+2) ;+2 X тек. полож. курсора в строке + cp (iy+4) ;+4 число введ. символов + ret z ; конец строки + ld a,(ix+3) ; Xi правый край поля ввода + sub (ix+6) ; Xo левый край поля + ld b,a + ld a,(iy+2) ;+2 X тек. полож. курсора в строке + inc a + cp b + ret z ; уперлись в правый край поля + jr InpPrint + +; Забой - удалить символ левее курсора +BackDel:ld a,(iy+2) ; X тек. полож. курсора в строке + or a + ret z ; дошли до левого края поля + ld l,(ix+9) ; структура буфера + ld h,(ix+10) + ld a,(iy+2) ; X тек. полож. курсора в строке + add a,l + ld l,a + jr nc,$+3 + inc h + inc hl + inc hl + inc hl + inc hl + inc hl + ld d,h + ld e,l + dec de + ld a,(iy+4) ; число введ. символов + sub (iy+2) ; X тек. полож. курсора в строке + jr z,$+7 ; курсор за концом строки + ld c,a + ld b,0 + ldir ; обновить остаток строки + xor a + ld (de),a ; в конец строки + dec (iy+2) ; X тек. полож. курсора в строке + dec (iy+4) ; число введ. символов + jp PrnInLn ; вывести строку на экран + +; Delete - удалить символ в тек. позиции +InpDel: ld l,(ix+9) ; структура буфера + ld h,(ix+10) + ld a,(iy+2) ; X тек. полож. курсора в строке + inc a + add a,l + ld l,a + jr nc,$+3 + inc h + inc hl + inc hl + inc hl + inc hl + inc hl + ld d,h + ld e,l + dec de + ld a,(iy+4) ;+4 число введ. символов + sub (iy+2) ; X тек. полож. курсора в строке + ret z ; курсор за концом строки + ld c,a + ld b,0 + ldir ; обновить остаток строки + xor a + ld (de),a ; в конец строки + dec (iy+4) ; число введ. символов + jp PrnInLn ; вывести строку на экран + +; Home - в начало строки +InpHome:ld a,(iy+2) ; X тек. полож. курсора в строке + or a + ret z + xor a ; X полож. курсора + jp InpPrint ; вывести строку на экран + +; End - в конец строки +InpEnd: ld a,(iy+4) ;+4 число введ. символов + cp (iy+2) ; X тек. полож. курсора в строке + ret z + ld c,a + ld a,(ix+3) ; Xi правый край поля ввода + sub (ix+6) ; Xo левый край поля + cp c + ld a,c + jp nz,InpPrint ; строка меньше ширины поля + dec a ; --полож. курсора + jp InpPrint ; вывести строку на экран diff --git a/OBJS/LISTBOX.ASM b/OBJS/LISTBOX.ASM new file mode 100755 index 0000000..c99833e --- /dev/null +++ b/OBJS/LISTBOX.ASM @@ -0,0 +1,1072 @@ +;----------------------------------------------------------- +; Прорисовка объекта +; Object ~List Box~ +; Input: HL-label +; Format mouse table: +; +0 - Object ~List Box" +; +1 - Xo position object +; +2 - Xi position object +; +3 - Yo position object +; +4 - Yi position object +; +5 - Xi position name +; +6 - тек. элемент +; +7 - число элементов в ListBox +; +8,9 - адрес списка +; +10 - Y pos line up +; +11 - Y pos line down +; +12 - Previos Y pos bar +; +13 - hot-буква +; +14 - контекст +;----------------------------------------------------------- +PListBox: + LD (IY+1),A + LD A,(HL) ;X pos + INC HL + LD C,A + LD (IX+4),A ;Save X pos + ADD A,(IX+0) ;Pos X from begin window + LD (IY+2),A ;+1 Xo + LD A,(HL) ;Y pos + INC HL + LD B,A + LD (IX+5),A ;Save Y pos + ADD A,(IX+1) ;Pos Y from begin window + LD (IY+4),A ;+3 Yo + CALL GetPutA + LD A,(HL) ;len X + INC HL + ADD A,3 + LD (IX+6),A + LD B,A + ADD A,2 + ADD A,(IY+2) + LD (IY+3),A ;Xi pos + LD A,(HL) ;len Y + INC HL + ADD A,2 ;Yi pos + ADD A,(IY+4) + LD (IY+5),A + LD A,"┌" + LD (DE),A + INC DE + INC DE + LD A," " ; ведущий пробел + LD (DE),A + INC DE + INC DE + DEC B + LD A,(color_array+24) ; цвет диал. окна + LD C,A + LD A,(HL) +LstBox0:INC HL + CP "&" + JR NZ,LstBox1 + LD A,(HL) + LD (DE),A ; hot-букву в буфер + INC HL + INC DE + push bc + ld a,(color_array+25) ; цвет hot-буквы диал. окна + ld b,a + ld a,c + and 0F0h + or b + ld (de),a ; атрибут + pop bc + inc de + DEC B + LD A,(HL) + INC HL +LstBox1:LD (DE),A + INC DE + INC DE + DEC B + LD A,(HL) + OR A + JR NZ,LstBox0 + INC HL + ld a,(hl) + inc hl + ld (iy+15),a ; hot-буква + LD A," " ; концевой пробел + LD (DE),A + INC DE + INC DE + DEC B + LD A,(IX+6) + SUB B + ADD A,(IY+2) + inc a + LD (IY+6),A ; Xi полож. заголовка + LD A,B + OR A + JR Z,LstBox2 + LD A,"─" + LD (DE),A + INC DE + INC DE + DJNZ $-3 +LstBox2:LD A,"┐" + LD (DE),A + INC (IX+5) + LD A,(HL) ; контекст + INC HL + LD (IY+16),A + SUB A + LD (IY+7),A ;Тек.элем. + LD (IY+8),A ;Первый элем. на странице + LD (IY+9),A ;Кол-во элем. + LD E,(HL) + INC HL + LD (IY+10),E ;Адрес списка + LD (IY+17),E ;Адрес списка + LD D,(HL) + INC HL + LD (IY+11),D + LD (IY+18),D + PUSH HL + EX DE,HL + LD A,(HL) + OR A + JP Z,EndBox + ; Next element list +LstBox3:LD C,(IX+4) ;pos element + LD B,(IX+5) + CALL GetPutA + LD A,(IX+6) + SUB 3 + LD B,A + EX DE,HL + LD (HL),"│" + INC HL + INC HL + LD A,(IY+4) + SUB (IX+1) + INC A + CP (IX+5) + LD A,(color_array+29) ; цвет ListBox-а + JR NZ,$+5 + LD A,(color_array+31) ; цвет после указателя + LD C,A + LD (HL)," " + INC HL + LD (HL),C + INC HL +LstBox4:LD A,(DE) + INC DE + CP 0Dh ; конец строки + JR Z,NxtLst + LD (HL),A + INC HL + LD (HL),C + INC HL + DJNZ LstBox4 + LD A,(DE) + INC DE + CP 0Dh ; конец строки + JR NZ,$-4 +NxtLst: LD A,B + OR A + JR Z,LstBox5 + LD A," " + LD (HL),A + INC HL + LD (HL),C + INC HL + DJNZ $-4 +LstBox5:LD (HL)," " + INC HL + LD (HL),C + INC HL + LD A,(IY+4) + SUB (IX+1) + INC A + CP (IX+5) + LD B,"" + JR Z,PutLsBr + INC A + CP (IX+5) + LD B,"■" + JR Z,PutLsBr + LD A,(IY+5) + SUB (IX+1) + SUB 2 + CP (IX+5) + LD B,"" + JR Z,PutLsBr + LD B,"▒" +PutLsBr:LD (HL),B + INC HL + LD A,(color_array+32) ; цвет скролл-бара + LD (HL),A + INC HL + LD (HL),"│" + EX DE,HL + INC (IY+9) + INC (IX+5) + LD A,(IY+5) + SUB (IX+1) + DEC A + CP (IX+5) + JR Z,EndBox1 + LD A,(HL) + OR A + JP NZ,LstBox3 +EndBox: LD A,(IY+5) + SUB (IX+1) + SUB (IX+5) + DEC A + JR Z,EndBox1 + LD B,A +LstBox6:PUSH BC + LD C,(IX+4) ;pos element + LD B,(IX+5) + CALL GetPutA + LD A,(IX+6) + DEC A + LD B,A + EX DE,HL + LD (HL),"│" + INC HL + INC HL + LD A,(color_array+29) ; цвет ListBox-а + LD C,A + LD A," " + LD (HL),A + INC HL + LD (HL),C + INC HL + DJNZ $-4 + LD A,(IY+4) + SUB (IX+1) + INC A + CP (IX+5) + LD B,"" + JR Z,PutLsB1 + INC A + CP (IX+5) + LD B,"■" + JR Z,PutLsB1 + LD A,(IY+5) + SUB (IX+1) + SUB 2 + CP (IX+5) + LD B,"" + JR Z,PutLsB1 + LD B,"▒" +PutLsB1:LD (HL),B + INC HL + LD A,(color_array+32) ; цвет скролл-бара + LD (HL),A + INC HL + LD (HL),"│" + EX DE,HL + INC (IX+5) + POP BC + DJNZ LstBox6 + ; +EndBox1:LD A,(HL) + OR A + JR Z,EndBox2 + CP 0Dh ; конец строки + INC HL + LD A,(HL) + JR NZ,$-4 + INC (IY+9) + JR EndBox1+1 + ; +EndBox2:LD C,(IX+4) ;End string + LD B,(IX+5) + CALL GetPutA + EX DE,HL + LD (HL),"└" + INC HL + INC HL + LD B,(IX+6) + LD A,"─" + LD (HL),A + INC HL + INC HL + DJNZ $-3 + LD (HL),"┘" + LD A,(IY+4) + INC A + LD (IY+12),A ;line up + INC A + LD (IY+14),A ;prev pos + LD A,(IY+5) + SUB 2 + LD (IY+13),A ;line down + POP HL + LD BC,19 + LD (IY+0),C + ADD IY,BC + RET + + + +GetLstBox: + LD HL,what + INC HL + INC HL + LD A,(IX+7) + ADD A,(IX+8) + LD (HL),A + RET + + + + + +;------------------------------------------------- +; Обработчик событий объектов ~List Box~ +;------------------------------------------------- +EListBox: + ld hl,what ; поле событий + ld a,(hl) + inc hl + cp evMouseFr + jp z,ELmouse + cp evKeyboard + jp z,ELkeys + cp evMessage + jr z,ELmess + cp evCombKey + ret nz + bit 7,(ix+1) ; sel or nosel + jp nz,ELcomb ; объект уже выделен + ld b,(hl) ;+1 what + inc hl + ld a,(hl) ;+2 what + cp 56h ; курсор вправо + jp z,SetLstBox + push ix + ld e,(ix+0) ; размер таблицы "List Box" + ld d,0 + add ix,de + bit 7,(ix+0) + pop ix + ret z ; еще не конец объектов + cp 54h ; курсор влево + jp z,SetLstBox + ld a,b + and 00111111b ; биты Ctrl, Alt + ret nz + ld a,(hl) ;+2 what + cp 15+80h ; Tab скен-код+80h + ret nz + ; Shift+Tab + jp SetLstBox ; select my + +; Событие - сообщения +ELmess: LD A,(HL) ;+1 what + INC HL + CP msHiddInvr + JR NZ,ELmess1 + BIT 7,(IX+1) + RET NZ + LD A,(IX+9) + OR A + RET Z + JP HdLstBoxI + ; +ELmess1:CP msNewList + RET NZ + LD E,(HL) + INC HL + LD D,(HL) + LD (IX+10),E + LD (IX+11),D + LD (IX+17),E + LD (IX+18),D + LD B,0 +ELmess2:LD A,(DE) + INC DE + CP 0Dh + JR NZ,ELmess2 + INC B + LD A,(DE) + OR A + JR NZ,ELmess2 +ELmessE:LD (IX+9),B + CALL RsLstBoxI + SUB A + LD (IX+7),A + LD (IX+8),A + LD A,(IX+9) + OR A + JR Z,ELmesE1 + BIT 7,(IX+1) + PUSH AF + CALL Z,HdLstBoxI + POP AF + CALL NZ,StLstBoxI +ELmesE1:CALL PrnLstBox + CALL LstBoxBar + JP ELboxex + +; Событие - курсорные клавиши +ELcomb: inc hl + ld de,ELexit + push de + ld a,(hl) ;+2 what + cp 58h ; курсор вверх + jr z,ELup + cp 52h ; курсор вниз + jp z,ELdown + cp 54h ; курсор влево + jp z,ELpgup + cp 56h ; курсор вправо + jp z,ELpgdwn + cp 59h ; PageUp + jp z,ELpgup + cp 53h ; PageDown + jp z,ELpgdwn + cp 57h ; Home + jp z,ELhome + cp 51h ; End + jp z,ELend + pop de + ret + +ELup: LD A,(IX+9) + CP 2 + RET C + LD A,(IX+7) + DEC A + JP M,ELup1 + CALL RsLstBoxI + LD (IX+7),A + CALL StLstBoxI + CALL LstBoxBar + JP ELboxex + ; +ELup1: LD A,(IX+8) + DEC A + RET M + LD (IX+8),A + LD L,(IX+10) + LD H,(IX+11) + JR Z,ELupn1 + LD L,(IX+17) + LD H,(IX+18) + DEC HL + DEC HL + LD A,(HL) + CP 0Dh + JR NZ,$-4 + INC HL +ELupn1: LD (IX+17),L + LD (IX+18),H + CALL PrnLstBox + CALL LstBoxBar + JP ELboxex + +ELdown: LD A,(IX+9) + CP 2 + RET C + LD A,(IX+5) + SUB (IX+4) + SUB 2 + LD C,A + LD A,(IX+7) + ADD A,(IX+8) + INC A + CP (IX+9) + RET Z + SUB (IX+8) + CP C + JR Z,ELdown1 + CALL RsLstBoxI + LD (IX+7),A + CALL StLstBoxI + CALL LstBoxBar + JP ELboxex + ; +ELdown1:LD A,(IX+8) + INC A + LD (IX+8),A + LD L,(IX+10) + LD H,(IX+11) + JR Z,ELdwn1 + LD L,(IX+17) + LD H,(IX+18) + LD A,(HL) + INC HL + CP 0Dh + JR NZ,$-4 +ELdwn1: LD (IX+17),L + LD (IX+18),H + CALL PrnLstBox + CALL LstBoxBar + JP ELboxex + +; Page Up +ELpgup: LD A,(IX+9) + CP 2 + RET C + LD A,(IX+8) + OR A + LD B,1 + JP Z,ELnopg + LD A,(IX+5) + SUB (IX+4) + SUB 2 + LD C,A + LD A,(IX+8) + SUB C + JR NC,$+3 + SUB A + LD (IX+8),A + JR ELpgex + +ELpgdwn:LD A,(IX+9) + CP 2 + RET C + LD A,(IX+5) + SUB (IX+4) + SUB 2 + LD C,A + LD A,(IX+9) + SUB (IX+8) + LD B,A + CP C + JR C,ELnopg + JR Z,ELnopg + LD A,(IX+8) + ADD A,C + CP (IX+9) + JR C,$+6 + LD A,(IX+9) + SUB C + LD (IX+8),A + ADD A,C + CP (IX+9) + JR C,ELpgex + JR Z,ELpgex + LD A,(IX+9) + SUB C + LD (IX+8),A + ; +ELpgex: LD L,(IX+10) + LD H,(IX+11) + LD A,(IX+8) + OR A + JR Z,ELpgex1 + LD B,A + LD A,(HL) + INC HL + CP 0Dh + JR NZ,$-4 + DJNZ $-6 +ELpgex1:LD (IX+17),L + LD (IX+18),H + CALL PrnLstBox + CALL LstBoxBar + LD A,(IX+7) + ADD A,(IX+8) + CP (IX+9) + JR C,ELboxex + LD A,(IX+9) + SUB (IX+8) + LD B,A + ; +ELnopg: DEC B + LD A,B + CP (IX+7) + RET Z + CALL RsLstBoxI + LD (IX+7),A + CALL StLstBoxI + CALL LstBoxBar + ; +ELboxex:LD HL,what + LD (HL),evMessage + INC HL + LD (HL),msNewElem + INC HL + LD A,(IX+7) + ADD A,(IX+8) + LD (HL),A ; тек. элемент + call TransMessUp + jp get_fire + ;ld b,8 + ;call get_mouse_info + ;ret z + ;HALT + ;DJNZ $-5 + ;RET + +; Home +ELhome: LD A,(IX+8) + OR A + JR Z,ELhome1 + LD (IX+8),0 + LD L,(IX+10) + LD H,(IX+11) + LD (IX+17),L + LD (IX+18),H + CALL PrnLstBox +ELhome1:LD A,(IX+7) + OR A + RET Z + CALL RsLstBoxI + LD (IX+7),0 + CALL StLstBoxI + jp LstBoxBar + +; End +ELend: LD A,(IX+8) + ADD A,(IX+7) + INC A + CP (IX+9) + RET Z + LD A,(IX+5) + SUB (IX+4) + SUB 2 + LD C,A + LD A,(IX+9) + SUB C + JR C,ELend1 + JR Z,ELend1 + LD A,(IX+9) + SUB C + LD (IX+8),A + LD L,(IX+10) + LD H,(IX+11) + LD B,A + LD A,(HL) + INC HL + CP 0Dh + JR NZ,$-4 + DJNZ $-6 + LD (IX+17),L + LD (IX+18),H + CALL RsLstBoxI + CALL PrnLstBox + LD A,(IX+9) + DEC A + SUB (IX+8) + LD (IX+7),A + CALL StLstBoxI + jp LstBoxBar + ; +ELend1: CALL RsLstBoxI + LD A,(IX+9) + DEC A + LD (IX+7),A + CALL StLstBoxI + jp LstBoxBar + +; Событие - мышка +ELmouse:LD E,(HL) ; X coord + INC HL + LD D,(HL) ; Y coord + LD A,E + BIT 7,(IX+2) + JR NZ,$+6 + CP (IX+2) ;Xo pos + RET C ;< + BIT 7,(IX+3) + RET NZ + CP (IX+3) ;Xi pos + RET NC ;> + LD A,D + CP (IX+4) ;Yo pos list box + RET C + CP (IX+5) ;Yi pos list box + RET NC + BIT 7,(IX+1) ;Sel or nosel + PUSH DE + CALL Z,SetLstBox + POP DE + LD HL,ELexit + PUSH HL + LD A,(IX+9) + OR A + RET Z + LD A,E + ADD A,2 + CP (IX+3) + JR Z,ELmous1 + RET NC + LD A,E + CP (IX+2) + RET Z + LD A,D + CP (IX+4) + RET Z + INC A + CP (IX+5) + RET Z + LD A,D + SUB (IX+4) + DEC A + ADD A,(IX+8) + CP (IX+9) + JR C,$+6 + LD A,(IX+9) + DEC A + SUB (IX+8) + CP (IX+7) + JR Z,SelLine + CALL RsLstBoxI + LD (IX+7),A + CALL StLstBoxI + CALL LstBoxBar + jp ELboxex + ; +SelLine:POP HL + LD HL,what ; поле событий + LD (HL),evCommand + INC HL + LD (HL),cmSelect + RET + +ELmous1:LD A,D + CP (IX+12) + RET C + JP Z,ELup + CP (IX+13) + JP Z,ELdown + RET NC + CP (IX+14) + RET Z + JP C,ELpgup + JP NC,ELpgdwn + RET + +; Событие - обычные клавиши +ELkeys: ld a,(hl) + bit 7,(ix+1) ; sel or nosel + ret nz + cp 9 ; Tab + jr z,SetLstBox ; set button + inc hl + ld a,(hl) ;+2 what скен-код + cp (ix+15) ; hot-буква + ret nz +SetLstBox: + CALL MoveObj ;Select Button + CALL ResDialInv ;Reset previos invert + LD IX,DialTab+5 + LD E,(IX+2) ;Xo + INC E + LD D,(IX+4) ;Y + LD A,(IX+6) ;Xi + SUB E + LD C,A + CALL SetDialInv + LD A,(IX+9) + OR A + CALL NZ,StLstBoxI + LD HL,what ; поле событий + LD (HL),evMessage + INC HL + LD (HL),msNewElem + INC HL + LD A,(IX+7) + ADD A,(IX+8) + LD (HL),A ; тек. элемент + CALL TransMessUp +ELexit: LD HL,what + LD (HL),evNothing + RET + + + + +RsLstBoxI: + PUSH AF + LD A,(color_array+29) ; цвет ListBox-а + CALL LstBoxInv + POP AF + RET + + +HdLstBoxI: + LD A,(color_array+31) ; цвет после указателя + JR LstBoxInv + ; +StLstBoxI: + LD A,(color_array+30) ; цвет указателя ListBox-а +LstBoxInv: + LD (lbcolor+1),A + PUSH IY + PUSH IX + PUSH IX + POP IY + LD IX,DialData ; таблица осн. диал. окна + LD A,(IY+2) + SUB (IX+0) + INC A + LD C,A + LD A,(IY+4) + SUB (IX+1) + INC A + ADD A,(IY+7) + LD B,A + CALL GetPutA + PUSH DE + IN A,(SLOT3) + PUSH AF + LD A,(page_dial_screen) + OUT (SLOT3),A + LD A,(IY+3) + SUB (IY+2) + SUB 3 + LD L,A + LD H,1 + LD B,L +lbcolor:LD A,0 + INC DE + LD (DE),A + INC DE + DJNZ $-3 + POP AF + OUT (SLOT3),A + POP IX + LD E,(IY+2) + INC E + LD A,(IY+4) + INC A + ADD A,(IY+7) + LD D,A + CALL PutDialLn + POP IX + POP IY + RET + +LstBoxBar: + LD A,(IX+7) + ADD A,(IX+8) + LD E,A + LD A,(IX+13) + SUB (IX+12) + SUB 2 + LD C,A + CALL Mult8X8 ;CurLine*LenScrollBar=num16bit + LD A,H + OR L + JR Z,LBB1 + LD A,(IX+9) ;num16bit/EquipElem + OR A + JR Z,$+3 + DEC A + LD C,A + CALL Divis16X8 +LBB1: LD A,(IX+12) ;Смещение от начала + INC A + ADD A,L + CP (IX+14) + RET Z + PUSH IY + PUSH IX + PUSH AF + PUSH IX + POP IY + LD IX,DialData + LD A,(IY+3) + SUB (IX+0) + SUB 2 + LD C,A + LD A,(IY+14) + SUB (IX+1) + LD B,A + CALL GetPutA + IN A,(SLOT3) + PUSH AF + LD A,(page_dial_screen) + OUT (SLOT3),A + LD A,"▒" + LD (DE),A + POP AF + OUT (SLOT3),A + LD A,(IY+3) + SUB 2 + LD E,A + LD D,(IY+14) + LD A,D + CP 31 + JR NC,LBe + BIT 7,E + JR NZ,LBe + LD A,E + CP 80 + JR NC,LBe + LD A,(color_array+32) ; цвет скролл-бара + LD H,A + LD L,"▒" + LD BC,1BB5h + SUB A + RST 08h +LBe: LD A,(IY+3) + SUB 2 + LD E,A + POP AF + LD (IY+14),A + LD D,A + PUSH DE + CP 31 + JR NC,LBe1 + BIT 7,E + JR NZ,LBe1 + LD A,E + CP 80 + JR NC,LBe1 + LD A,(color_array+32) ; цвет скролл-бара + LD H,A + LD L,"■" + LD BC,1BB5h + SUB A + RST 08h +LBe1: POP DE + LD A,E + SUB (IX+0) + LD C,A + LD A,D + SUB (IX+1) + LD B,A + CALL GetPutA + IN A,(SLOT3) + PUSH AF + LD A,(page_dial_screen) + OUT (0E2h),A + LD A,"■" + LD (DE),A + POP AF + OUT (SLOT3),A + POP IX + POP IY + RET + + +PrnLstBox: + PUSH IY + PUSH IX + IN A,(SLOT3) + PUSH AF + LD A,(page_dial_screen) + OUT (SLOT3),A + PUSH IX + POP IY + LD IX,DialData ; таблица осн. диал. окна + LD L,(IY+17) + LD H,(IY+18) + LD A,(IY+2) + SUB (IX+0) + ADD A,2 + LD C,A + LD A,(IY+4) + SUB (IX+1) + INC A + LD B,A + LD A,(IY+5) + SUB (IY+4) + SUB 2 +PrLsBx0:PUSH AF + PUSH BC + CALL GetPutA + LD A,(IY+3) + SUB (IY+2) + SUB 5 + LD B,A +PrLsBx1:LD A,(HL) + INC HL + CP 0Dh + JR Z,PrLsBx2 + LD (DE),A + INC DE + INC DE + DJNZ PrLsBx1 + LD A,(HL) + INC HL + CP 0Dh + JR NZ,$-4 +PrLsBx2:LD A,B + OR A + JR Z,PrLsBx3 + LD A," " ; конц. пробелы тек. пункта + LD (DE),A + INC DE + INC DE + DJNZ $-3 +PrLsBx3:POP BC + INC B + POP AF + DEC A + JR Z,PrLsBx4 + LD E,(HL) + INC E + DEC E + JR NZ,PrLsBx0 +PrLsBx4:OR A + JR Z,PrLsBx6 +PrLsBx5:PUSH AF + PUSH BC + CALL GetPutA + LD A,(IY+3) + SUB (IY+2) + SUB 5 + LD B,A + SUB A + LD (DE),A + INC DE + INC DE + DJNZ $-3 + POP BC + INC B + POP AF + DEC A + JR NZ,PrLsBx5 +PrLsBx6:CALL PutDial + POP AF + OUT (SLOT3),A + POP IX + POP IY + RET + + + + + +; Процедура деления (16x8bit) +; вход: HL/C +; выход: l=целое, h=остаток +Divis16X8: + LD B,8 +Div16X8:ADD HL,HL + LD A,H + JR C,Div1 + SUB C + JR NC,Div2 + ADD A,C + LD H,A + DJNZ Div16X8 + RET +Div1: SUB C +Div2: LD H,A + INC HL + DJNZ Div16X8 + RET + + + +; Процедура умножения (8*8bit) +; вход: e * c +; выход: hl=результат +Mult8X8:SUB A + LD L,A + LD H,A + LD D,A + CP C + RET Z + CP E + RET Z + LD H,C + LD B,8 +Mlt8x8: ADD HL,HL + JR NC,$+3 + ADD HL,DE + DJNZ Mlt8x8 + RET diff --git a/OBJS/PALLETE.ASM b/OBJS/PALLETE.ASM new file mode 100755 index 0000000..0a6cf66 --- /dev/null +++ b/OBJS/PALLETE.ASM @@ -0,0 +1,1046 @@ +;----------------------------------------------------------- +; Прорисовка объекта ~Pallete Box~ +; Input: HL-label +; Format mouse table: +; +0 - Object ~Pallete Box" +; +1 - Xo position object +; +2 - Xi position object +; +3 - Yo position object +; +4 - Yi position object +; +5 - Xi position name +; +6 - число цвет. полей по X +; +7 - число цвет. полей по Y +; +8 - тек.элемент +; +9 - hot-буква +; +10 - контекст +;----------------------------------------------------------- +; db PalleteBox +; dw 022Bh,0404h ; Yo,Xo,lenY,lenX +; db "&Foreground",0 +; db 0 ; контекст +; db 0Fh ; маска +; dw ColPal ; адрес нач. цвета +;----------------------------------------------------------- +; +PPallete: + LD (IY+1),A + LD A,(HL) ; X pos + INC HL + LD C,A + LD (IX+4),A ; Save X pos + ADD A,(IX+0) ; Pos X from begin window + LD (IY+2),A ;+1 Xo + LD A,(HL) ; Y pos + INC HL + LD B,A + LD (IX+5),A ; Save Y pos + ADD A,(IX+1) ; Pos Y from begin window + LD (IY+4),A ;+3 Yo + CALL GetPutA + LD A,(HL) ; len X + INC HL + LD (IY+7),A ; число цветн. полей по X + LD C,A + ADD A,A ;1+1=2 + ADD A,C ;2+1=3 + LD (IX+6),A + LD B,A + ADD A,2 + ADD A,(IY+2) + LD (IY+3),A ; Xi pos + LD A,(HL) ; len Y + INC HL + LD (IY+8),A ; число цветн. полей по Y + ADD A,A + ADD A,2 ; Yi pos + ADD A,(IY+4) + LD (IY+5),A + LD A,"┌" + LD (DE),A + INC DE + INC DE + LD A," " ; вед. пробел заголовка + LD (DE),A + INC DE + INC DE + DEC B + LD A,(color_array+24) ; цвет диал. окна + LD C,A + LD A,(HL) +PltBox0:INC HL + CP "&" + JR NZ,PltBox1 + LD A,(HL) + LD (DE),A ; hot-букву в буфер + INC HL + INC DE + push bc + ld a,(color_array+25) ; цвет hot-буквы диал. окон + ld b,a + ld a,c ; цвет бутона + and 0F0h + or b + ld (de),a ; атрибут + pop bc + inc de + DEC B + LD A,(HL) + INC HL +PltBox1:LD (DE),A + INC DE + INC DE + DEC B + LD A,(HL) + OR A + JR NZ,PltBox0 + INC HL + ld a,(hl) + inc hl + ld (iy+10),a ; hot-буква + LD A," " ; конц. пробел заголовка + LD (DE),A + INC DE + INC DE + DEC B + LD A,(IX+6) + SUB B + ADD A,(IY+2) + inc a + LD (IY+6),A ; Xi полож. заголовка + LD A,B + OR A + JR Z,PltBox2 + LD A,"─" + LD (DE),A + INC DE + INC DE + DJNZ $-3 +PltBox2:LD A,"┐" + LD (DE),A + INC (IX+5) + LD A,(HL) ; контекст + INC HL + LD (IY+11),A + LD A,(HL) + INC HL + LD (IY+9),A ; маска цветов из описателя + LD A,(HL) + INC HL + LD (IY+12),A ; адрес начального цвета + LD A,(HL) + INC HL + LD (IY+13),A + PUSH HL + LD A,(color_array+24) ; цвет диал. окна + AND 0F0h + LD (IX+6),A ; начальный цвет + LD B,(IY+8) + ; цикл вывода цветн. полей +PltBox3:PUSH BC + LD C,(IX+4) ; pos element + LD B,(IX+5) + CALL GetPutA + EX DE,HL + LD (HL),"│" ; начальный символ цветн. поля + INC HL + INC HL + LD B,(IY+7) ; высота цветн. поля в символах + LD A,(IX+6) ; начальный цвет + LD C,"█" ; символ заполнения цветн. поля +PltBox4:LD (HL),C + INC HL + LD (HL),A + INC HL + LD (HL),C + INC HL + LD (HL),A + INC HL + LD (HL),C + INC HL + LD (HL),A + INC HL + INC A + DJNZ PltBox4 + LD (HL),"│" ; конечный символ цветн. поля + EX DE,HL + INC (IX+5) ; ++Y полож. поля + LD C,(IX+4) ; bc=Y/X полож. цветн. поля + LD B,(IX+5) + CALL GetPutA + EX DE,HL + LD (HL),"│" ; начальный символ цветн. поля + INC HL + INC HL + LD B,(IY+7) + LD A,(IX+6) + LD C,"█" ; символ заполнения цветн. поля +PltBox5:LD (HL),C + INC HL + LD (HL),A + INC HL + LD (HL),C + INC HL + LD (HL),A + INC HL + LD (HL),C + INC HL + LD (HL),A + INC HL + INC A + DJNZ PltBox5 + LD (HL),"│" ; конечный символ цветн. поля + EX DE,HL + INC (IX+5) + LD A,(IY+7) + ADD A,(IX+6) + LD (IX+6),A + POP BC + DJNZ PltBox3 + ; все цветн. поля выведены + LD C,(IX+4) ; pos element + LD B,(IX+5) + CALL GetPutA + EX DE,HL + LD (HL),"└" + INC HL + INC HL + LD A,(IY+3) + SUB (IY+2) + SUB 2 + LD B,A + LD A,"─" + LD (HL),A + INC HL + INC HL + DJNZ $-3 + LD (HL),"┘" + LD L,(IY+12) ; адрес начального цвета + LD H,(IY+13) + LD A,(HL) ; цвет + AND (IY+9) + BIT 7,(IY+9) + JR Z,$+6 + RRCA + RRCA + RRCA + RRCA + LD B,-1 + INC B + SUB (IY+7) + JR NC,$-4 + ADD A,(IY+7) + LD C,A + ADD A,A ;1+1=2 + ADD A,C ;2+1=3 гориз. шаг + inc a + LD C,A + LD A,B + ADD A,A ;1+1=2 верт. шаг + INC A + LD B,A + LD A,(IY+2) + SUB (IX+0) + INC A + ADD A,C + LD C,A + LD A,(IY+4) + SUB (IX+1) + INC A + ADD A,B + LD B,A + CALL GetPutA + LD A,"*" + LD (DE),A + INC DE + LD A,(color_array+24) ; цвет диал. окна + LD (DE),A + POP HL + LD BC,14 + LD (IY+0),C + ADD IY,BC + RET + + + + + +;------------------------------------------------- +; Object ~Pallette Resident 1 or 2~ +; Format mouse table: +; +0 - Object ~Pallette Resident~ +;------------------------------------------------- +PResid2:EX AF,AF' + LD E,(HL) + INC HL + LD D,(HL) + INC HL + LD (AdrCol+1),DE ; тек. адрес в массиве цветов + LD A,(page_dial_screen) ; page buffer + OUT (SLOT3),A + EX AF,AF' + JR PResid1 + +;------------------------------------------------- +; Object ~Pallette Resident 1 or 2~ +; Format mouse table: +; +0 - Object ~Pallette Resident~ +;------------------------------------------------- +PResid1:LD (IY+0),2 ; длина таблицы "Pallette Resident" ? + INC IY + LD (IY+0),A ;+0 номер объекта ~Pallette Resident 1 или 2~ + INC IY + RET + + + + + +;------------------------------------------------- +; Прорисовка объекта ~Test color~ +; Format mouse table: +;------------------------------------------------- +PTestCol: + LD (IY+1),A ;+0 object + LD (IY+4),0 + LD A,(HL) ; X pos + INC HL + LD C,A + ADD A,(IX+0) ; Pos X from begin screen + LD (IY+2),A ;+1 Xo + LD A,(HL) ; Y pos + INC HL + LD B,A + ADD A,(IX+1) ; Pos Y from begin screen + LD (IY+3),A ;+3 Yo + LD (PTestC2+1),BC + CALL GetPutA + PUSH DE + LD E,(HL) + INC HL + LD D,(HL) + INC HL + LD A,(DE) ; цвет строки + LD C,A + ;INC DE + ;LD A,(DE) + ;CPL + ;LD B,A + POP DE + PUSH HL + ; текст. строка + LD A,(HL) +PTestC1:INC HL + LD (DE),A + INC DE + ;LD A,(DE) + ;AND B + ;OR C + ld a,c + LD (DE),A ; атрибут + INC DE + INC (IY+4) + LD A,(HL) + OR A + JR NZ,PTestC1 + POP HL + ; вывод 2-й строки + PUSH BC +PTestC2:LD BC,0 + INC B ; ниже на строку + CALL GetPutA + POP BC + LD A,(HL) +PTestC3:INC HL + LD (DE),A + INC DE + ;LD A,(DE) + ;AND B + ;OR C + ld a,c + LD (DE),A ; атрибут + INC DE + LD A,(HL) + OR A + JR NZ,PTestC3 + INC HL + LD BC,5 + LD (IY+0),C + ADD IY,BC + RET + + + + +;----------------------------------------------------------- +; Обработчик событий объекта ~Test Color~ +;----------------------------------------------------------- +ETestCol: + LD HL,what + LD A,(HL) + INC HL + CP evMessage + RET NZ + LD A,(HL) ;+1 + CP msNewColor + RET NZ + INC HL + LD A,(HL) + INC HL + LD H,(HL) + LD L,A + LD C,(HL) ; цвет из массива нач. цветов + ;INC HL + ;LD B,(HL) + ;LD A,B + ;CP 0FFh + ;JR Z,ETestC1 + ;CPL + ;LD B,A + ;LD A,(color_array+24) ; цвет диал. окна + ;AND B + ;OR C + ;LD C,A +;ETestC1: + PUSH IY + PUSH IX + PUSH IX + POP IY + IN A,(SLOT3) + PUSH AF + LD A,(page_dial_screen) + OUT (SLOT3),A + LD IX,DialData ; таблица осн. диал. окна + LD A,C + PUSH AF + LD A,(IY+2) + SUB (IX+0) + LD C,A + LD A,(IY+3) + SUB (IX+1) + LD B,A + CALL GetPutA + EX DE,HL + POP AF + PUSH AF + PUSH IX + PUSH HL + LD B,(IY+4) + INC HL + LD (HL),A + INC HL + DJNZ $-3 + LD E,(IY+2) + LD D,(IY+3) + LD L,(IY+4) + LD H,1 + POP IX + CALL PutDialLn + POP IX + LD A,(IY+2) + SUB (IX+0) + LD C,A + LD A,(IY+3) + SUB (IX+1) + INC A + LD B,A + CALL GetPutA + EX DE,HL + POP AF + PUSH HL + LD B,(IY+4) + INC HL + LD (HL),A + INC HL + DJNZ $-3 + LD E,(IY+2) + LD D,(IY+3) + INC D + LD L,(IY+4) + LD H,1 + POP IX + CALL PutDialLn + POP AF + OUT (SLOT3),A + POP IX + POP IY + RET + + + + +;----------------------------------------------------------- +; Обработчик событий объекта ~Pallete Box~ +;----------------------------------------------------------- +EPallete: + ld hl,what + ld a,(hl) + inc hl + cp evMouseFr + jp z,EPmouse + cp evKeyboard + jp z,EPkeys + cp evMessage + jr z,EPmess + cp evCombKey + ret nz +; Событие - комбинация клавиш + bit 7,(ix+1) + jr nz,EPcomb ; объект уже выделен + ld b,(hl) ;+1 what + inc hl + ld a,(hl) ;+2 what + cp 56h ; курсор вправо + jp z,SetPalBox + push ix + ld e,(ix+0) ; размер таблицы "Pallete Box" + ld d,0 + add ix,de + bit 7,(ix+0) + pop ix + ret z ; еще не конец объектов + cp 54h ; курсор влево + jp z,SetPalBox + ld a,b + and 00111111b ; биты Ctrl, Alt + ret nz + ld a,(hl) ;+2 what + cp 15+80h ; Tab скен-код+80h + ret nz + ; Shift+Tab + jp SetPalBox ; выделить пред. объект + +; Событие - сообщение +EPmess: ld a,(hl) ;+1 what + inc hl + cp msNewColor + ret nz + ld e,(hl) ;+2 + inc hl + ld d,(hl) ;+3 + ld l,(ix+12) ; адрес ColList + ld h,(ix+13) + ex de,hl ; hl=старый адрес цвета + ;INC DE + ;LD A,(DE) + ;AND (IX+9) + ;JR Z,EPmess1 + ;DEC DE + ;LD A,(DE) ; итоговый цвет + ;AND (IX+9) ; маска из описателя объекта + ;LD B,A + ;INC HL + ;LD A,(HL) + ;DEC HL + ;AND (IX+9) + ;JR Z,EPmess1 + ;LD A,(HL) + ;AND (IX+9) + ;CP B + ;JR Z,EPmess1+3 +;EPmess1: + call ResPalCurs + ld (ix+12),l ; hl=новый адрес цвета + ld (ix+13),h + ;INC HL + ;LD A,(HL) + ;AND (IX+9) + jp SetPalCurs + ;CALL NZ,SetPalCurs + ;RET + +; Событие - курсорные клавиши +EPcomb: inc hl + ld de,EPexit + push de + ld a,(hl) ;+2 + cp 58h ; вверх + jp z,EPup + cp 52h ; вниз + jp z,EPdown + cp 54h ; влево + jp z,EPleft + cp 56h ; вправо + jp z,EPright + pop de + ret + +; курсор вверх +EPup: LD L,(IX+12) + LD H,(IX+13) + ;INC HL + ;LD A,(HL) + ;AND (IX+9) + ;RET Z + ;DEC HL + LD A,(HL) + AND (IX+9) + BIT 7,(IX+9) + JR Z,$+6 + RRCA + RRCA + RRCA + RRCA + SUB (IX+7) + RET C + JP EPex + +; курсор вниз +EPdown: LD B,(IX+8) + SUB A + ADD A,(IX+7) + DJNZ $-3 + LD C,A + LD L,(IX+12) + LD H,(IX+13) + ;INC HL + ;LD A,(HL) + ;AND (IX+9) + ;RET Z + ;DEC HL + LD A,(HL) + AND (IX+9) + BIT 7,(IX+9) + JR Z,$+6 + RRCA + RRCA + RRCA + RRCA + ADD A,(IX+7) + CP C + RET NC + JP EPex + +; курсор влево +EPleft: LD L,(IX+12) + LD H,(IX+13) + LD A,(HL) + AND (IX+9) + BIT 7,(IX+9) + JR Z,$+6 + RRCA + RRCA + RRCA + RRCA + DEC A + RET M + JP EPex + +; курсор вправо +EPright:ld b,(ix+8) ; число цветн. полей по Y + xor a + add a,(ix+7) ; число цветн. полей по X + djnz $-3 + ld c,a + ld l,(ix+12) ; hl=адрес начального цвета + ld h,(ix+13) + ld a,(hl) ; нач. цвет + and (ix+9) ; маска цветов + bit 7,(ix+9) + jr z,$+6 + rrca + rrca + rrca + rrca + inc a + cp c + ret nc +EPex: call ResPalCurs + bit 7,(ix+9) + jr z,$+6 + RLCA + RLCA + RLCA + RLCA + LD C,A + LD A,(IX+9) + CPL + LD B,A + LD A,(HL) + AND B + OR C + LD (HL),A + CALL SetPalCurs + LD HL,what + LD (HL),evMessage + INC HL + LD (HL),msNewColor + INC HL + LD A,(IX+12) + LD (HL),A + INC HL + LD A,(IX+13) + LD (HL),A + call TransMessUp + jp get_fire + +; Событие - мышка +EPmouse:LD E,(HL) ; X coord + INC HL + LD D,(HL) ; Y coord + LD A,E + BIT 7,(IX+2) + JR NZ,$+6 + CP (IX+2) ; Xo pos + RET C ; < + BIT 7,(IX+3) + RET NZ + CP (IX+3) ; Xi pos + RET NC ; > + LD A,D + CP (IX+4) ; Yo pos list box + RET C + CP (IX+5) ; Yi pos list box + RET NC + BIT 7,(IX+1) ; sel or nosel + PUSH DE + CALL Z,SetPalBox ; выделить объект + POP DE + LD HL,EPexit + PUSH HL + LD L,(IX+12) + LD H,(IX+13) + LD A,E + CP (IX+2) + RET Z + INC A + CP (IX+3) + RET Z + SUB (IX+2) + SUB 2 + LD C,A + LD A,D + CP (IX+4) ; Yo pos list box + RET Z + INC A + CP (IX+5) ; Yi pos list box + RET Z + SUB (IX+4) + SUB 2 + SRL A + JR Z,EPmous1 + LD B,A + SUB A + ADD A,(IX+7) + DJNZ $-3 +EPmous1:LD E,A + LD A,C + LD B,-1 + INC B + sub 3 ; минус шаг по гориз. + JR NC,$-3 + LD A,B + ADD A,E + LD B,A + BIT 7,(IX+9) + JR Z,$+6 + RLCA + RLCA + RLCA + RLCA + LD C,A + LD A,(HL) + AND (IX+9) + CP C + RET Z + LD A,B + JP EPex + +; Событие - обычные клавиши +EPkeys: ld a,(hl) ;+1 what + bit 7,(ix+1) ; sel or nosel + ret nz ; объект уже выделен + cp 9 ; Tab + jr z,SetPalBox ; выделить объект + inc hl + ld a,(hl) ;+2 what скен-код + cp (ix+10) ; hot-буква + ret nz +SetPalBox: + call MoveObj ; объект в начало таблицы + call ResDialInv ; Reset previos invert + ld ix,DialTab+5 ; таблица объектов + ld e,(ix+2) ; Xo + inc e + ld d,(ix+4) ; Y + ld a,(ix+6) ; Xi + sub e + ld c,a ; ширина выделения + call SetDialInv +EPexit: ld hl,what ; поле события + ld (hl),evNothing + ret + + + +;------------------------------------------------- +; Сбросить курсор палитры +;------------------------------------------------- +ResPalCurs: + PUSH IY + PUSH IX + PUSH HL + PUSH AF + PUSH IX + POP IY + LD IX,DialData ; таблица осн. диал. окна + LD L,(IY+12) ; hl=адрес начального цвета + LD H,(IY+13) + LD A,(HL) ; нач. цвет + AND (IY+9) ; маска из описателя + BIT 7,(IY+9) + JR Z,$+6 + RRCA + RRCA + RRCA + RRCA + LD L,A ; цвет + LD B,-1 + INC B + SUB (IY+7) + JR NC,$-4 + ADD A,(IY+7) + LD C,A + ADD A,A ;1+1=2 + ADD A,C ;2+1=3 гориз. шаг + inc a + LD C,A + LD A,B + ADD A,A ;1+1=2 верт. шаг + INC A + LD B,A + PUSH BC + LD A,(IY+2) + SUB (IX+0) + INC A + ADD A,C + LD C,A + LD A,(IY+4) + SUB (IX+1) + INC A + ADD A,B + LD B,A + CALL GetPutA + IN A,(SLOT3) + PUSH AF + LD A,(page_dial_screen) + OUT (SLOT3),A + LD A,"█" ; символ затирания + LD (DE),A + INC DE + LD A,L + LD (DE),A ; цвет + POP AF + OUT (SLOT3),A + POP BC + LD A,C + ADD A,(IY+2) + INC A + LD E,A + LD A,B + ADD A,(IY+4) + INC A + LD D,A + LD A,D + CP 31 + JR NC,RPalCr + LD A,E + CP 80 + JR NC,RPalCr + LD C,84h ; уст. курсор + PUSH HL + RST 08h + POP DE ; e=атрибут + LD A,"█" ; символ затирания + LD BC,0181h ; один символ с атрибутом + RST 08h +RPalCr: POP AF + POP HL + POP IX + POP IY + RET + + +;------------------------------------------------- +; Выделить курсор палитры +;------------------------------------------------- +SetPalCurs: + PUSH IY + PUSH IX + PUSH HL + PUSH IX + POP IY + LD IX,DialData ; таблица осн. диал. окна + LD L,(IY+12) ; адрес тек. цвета + LD H,(IY+13) + LD A,(HL) + AND (IY+9) + BIT 7,(IY+9) + JR Z,$+6 + RRCA + RRCA + RRCA + RRCA + LD B,-1 + INC B + SUB (IY+7) + JR NC,$-4 + ADD A,(IY+7) + LD C,A + ADD A,A ;1+1=2 + ADD A,C ;2+1=3 гориз. шаг + inc a + LD C,A + LD A,B + ADD A,A ;1+1=2 верт. шаг + INC A + LD B,A + PUSH BC + LD A,(IY+2) + SUB (IX+0) + INC A + ADD A,C + LD C,A + LD A,(IY+4) + SUB (IX+1) + INC A + ADD A,B + LD B,A + CALL GetPutA + IN A,(SLOT3) + PUSH AF + LD A,(page_dial_screen) + OUT (SLOT3),A + LD A,"*" ; курсор палитры + LD (DE),A + INC DE + LD A,(color_array+24) ; цвет диал. окна + LD (DE),A + POP AF + OUT (SLOT3),A + POP BC + LD A,C + ADD A,(IY+2) + INC A + LD E,A + LD A,B + ADD A,(IY+4) + INC A + LD D,A + LD A,D + CP 31 + JR NC,SPalCr + LD A,E + CP 80 + JR NC,SPalCr + LD C,84h ; уст. курсор + RST 08h + LD A,(color_array+24) ; цвет диал. окна + LD E,A + LD A,"*" ; курсор палитры + LD BC,0181h ; 1 символ с атрибутом + RST 08h +SPalCr: POP HL + POP IX + POP IY + RET + + + +;----------------------------------------------------------- +; Выделить заголовок объектов ~List Box~, ~Pallete Box~ +;----------------------------------------------------------- +PLstBoxI: + ld e,(ix+2) ; Xo + inc e + ld d,(ix+4) ; Y + ld a,(ix+6) ; Xi + sub e + ld c,a ; ширина выделения + call SetDialInv ; выделить заголовок + jp StLstBoxI ; указатель ListBox-а + + + + + + + +;----------------------------------------------------------- +; Обработчик событий объекта ~Resident1~ +;----------------------------------------------------------- +EResident1: + LD HL,what ; поле событий + LD A,(HL) + INC HL + CP evCommand + JR NZ,ERes1 + LD A,(HL) ;+1 + DEC HL + CP cmSelect + RET NZ + LD (HL),evNothing + RET + ; +ERes1: CP evMessage + RET NZ + LD A,(HL) ;+1 what + CP msNewElem + RET NZ + LD (HL),msNewList + INC HL + PUSH HL + LD L,(HL) ;+2 what номер списка (1..6) + LD H,0 + ADD HL,HL ;1+1=2 + ADD HL,HL ;2+2=4 + LD DE,ItemTab ; таблица + ADD HL,DE + LD E,(HL) ; de=ItemList1..6 + INC HL + LD D,(HL) + INC HL + LD C,(HL) ; bc=ColList1..6 + INC HL + LD B,(HL) + POP HL + LD (HL),E + INC HL + LD (HL),D + LD (AdrCol+1),BC ; тек. адрес в массиве цветов + RET + + +;------------------------------------------------- +; Обработчик событий объекта ~Resident1~ +;------------------------------------------------- +EResident2: + LD HL,what + LD A,(HL) + INC HL + CP evCommand + JR NZ,ERes2 + LD A,(HL) + DEC HL + CP cmSelect + RET NZ + LD (HL),evNothing + RET + ; +ERes2: CP evMessage + RET NZ + LD A,(HL) + CP msNewElem + RET NZ + LD (HL),msNewColor + INC HL + LD C,(HL) ; номер списка 1..6 + LD B,0 + EX DE,HL +AdrCol: LD HL,0 ; тек. адрес в массиве цветов + ADD HL,BC ;1+1=2 + ;ADD HL,BC;? ;2+1=3 убрать + EX DE,HL + LD (HL),E + INC HL + LD (HL),D + RET diff --git a/OBJS/PROCESS.ASM b/OBJS/PROCESS.ASM new file mode 100755 index 0000000..0b75a8a --- /dev/null +++ b/OBJS/PROCESS.ASM @@ -0,0 +1,262 @@ +;----------------------------------------------------------- +; Прорисовка объекта ~Process Line~. +; При макс. числе меньшем, чем ширина линейки процесса, +; погрешность большая (не закрашивается вся линейка). +; +; Object ~Process Line~ +; Input: HL-label +; Format mouse table: +; +0 - Object ~Process line~ +; +1 - Xo position object +; +2 - Xi position object +; +3 - Y position object +; +4 - поз. печати +; +5,6 - кол-во единиц на 1 деление процесса +; +7,8 - ячейка, где тек. число единиц +; +9,10 - подпрограмма процесса +;----------------------------------------------------------- +; db ProcesLine +; dw 0504h ; Y,X полож. +; db 72 ; длина линейки +; dw FileBytes ; адрес ячейки с MAX числом +; dw CurrBytes ; адрес ячейки с тек. числом +;ConCall:dw 0 ; адрес подпрограммы процесса +;----------------------------------------------------------- +;FileBytes: +; dw 0,0 ; размер файла +;CurrBytes: +; dw 0,0 ; тек. смещение в файле +;----------------------------------------------------------- +PProcess: + ld (iy+1),a ;+0 object + ld a,(hl) ; X pos + inc hl + ld c,a + add a,(ix+0) ; Pos X from begin screen + ld (iy+2),a ;+1 Xo + ld a,(hl) ; Y pos + inc hl + ld b,a + add a,(ix+1) ; Pos Y from begin screen + ld (iy+4),a ;+3 Yo + ld a,(hl) + inc hl + add a,(iy+2) + ld (iy+3),a + ld (iy+5),0 ; поз. вывода + ld e,(hl) ; где макс. + inc hl + ld d,(hl) + inc hl + push ix + push hl + push bc + ex de,hl + ld e,(hl) ; HL,IX - max. единиц + inc hl + ld d,(hl) + inc hl + push de + pop ix ; мл. разряд + ld a,(hl) + inc hl + ld h,(hl) ; ст. рязряд + ld l,a + ld a,(iy+3) + sub (iy+2) + ld c,a ; кол-во делений процесса (ширина линейки) + ld b,0 + call Divis32 + db 0DDh + ld a,l + ld (iy+6),a ; +6,+7 коэффициент + db 0DDh + ld a,h + ld (iy+7),a + pop bc + pop hl + pop ix + ld a,(hl) + inc hl + ld (iy+8),a + ld a,(hl) + inc hl + ld (iy+9),a + ld a,(hl) + inc hl + ld (iy+10),a + ld a,(hl) + inc hl + ld (iy+11),a + call GetPutA + ex de,hl + ld a,(color_array+52) ; 30h цвет линейки процесса + ld c,a + ld a,(iy+3) + sub (iy+2) + ld b,a + ld (hl),"░" + inc hl + ld (hl),c + inc hl + djnz $-5 + ex de,hl + ld de,12 + ld (IY+0),e + add iy,de + ret + + + + + +;----------------------------------------------------------- +; +; Обработчик событий объектов ~Process Line~ +; +;----------------------------------------------------------- +; п/п процесса должна возвращать "Carry", если +; процесс закончен. +EProcess: + push ix + ld de,EProcNx ; адрес выхода + push de + ld l,(ix+10) ; Подпрограмма + ld h,(ix+11) ; процесса + jp (hl) + ; +EProcNx:pop ix + push af + push ix + ld l,(ix+8) ; тек. положение + ld h,(ix+9) + ld c,(ix+6) ; bc=коэффициент + ld b,(ix+7) + ld e,(hl) ; hl,ix = cur. единиц + inc hl + ld d,(hl) + inc hl + push de + pop ix + ld a,(hl) ; ст. разряд + inc hl + ld h,(hl) + ld l,a + call Divis32 ; hl,ix / bc + db 0DDh + ld a,l + pop ix + ld b,a + ld a,(ix+3) + sub (ix+2) + ld c,a + cp b + ld a,b + jr nc,$+3 + ld a,c + sub (ix+5) ; пред. позиция вывода + jp z,ProcEx1 + ld b,a ; разница между положениями + ld c,(ix+5) + add a,c + ld (ix+5),a ; запом. тек. положение + ld a,(ix+2) ; Xo + add a,c ; тек. положение + ld e,a + ld d,(ix+4) ; Yo + push de + push bc + bit 7,(ix+3) ; Xi + jr nz,ProcExt + bit 7,e + jr z,proc1 + ld a,e + neg + sub b + neg + jr z,ProcExt + jp m,ProcExt + ld b,a + ld e,0 +proc1: ld a,e + cp 80 + jr nc,ProcExt + add a,b + cp 80 + jr c,proc2 + ld a,80 + sub e + ld b,a +proc2: ld a,d + cp 31 + jr nc,ProcExt + push ix + push bc + ld c,84h ; уст. курсор + rst 08h + pop bc ; b=число символов + ld a,"█" + ld c,82h + rst 08h + pop ix +ProcExt:pop hl ; h=число единиц + pop bc ; позиция на экране + push ix + in a,(SLOT3) + push af + ld a,(page_dial_screen) ; стр. буфера + out (SLOT3),a + ld ix,DialData ; таблица осн. диал. окна + ld a,c + sub (ix+0) + ld c,a + ld a,b + sub (ix+1) + ld b,a + call GetPutA + ld b,h + ld a,"█" + ld (de),a + inc de + inc de + djnz $-3 + pop af + out (SLOT3),a + pop ix +ProcEx1:pop af ; флаг от п/п процесса + ret nc ; процесс не закончился + ld hl,what ; поле событий + ld (hl),evCommand + inc hl + ld (hl),cmOkey + ret + + + + +;------------------------------------------------- +; Процедура деления (32bit) +; вход: hl,de / bc +; выход: de=целое, hl=остаток +;------------------------------------------------- +Divis32:ld a,b + or c + ret z + ex de,hl + ld hl,0 + ld a,32 +div32b1:add ix,ix + ex de,hl + adc hl,hl + ex de,hl + adc hl,hl + sbc hl,bc + jr nc,div32b2 + add hl,bc + dec a + jr nz,div32b1 + ret +div32b2:inc ix + dec a + jr nz,div32b1 + ret diff --git a/OBJS/RADIO.ASM b/OBJS/RADIO.ASM new file mode 100755 index 0000000..3e12ab1 --- /dev/null +++ b/OBJS/RADIO.ASM @@ -0,0 +1,789 @@ +; Включает объекты ~Radio Button~ и ~Check Box~ +; + + + + + +;===================================================================== +; Прорисовка объекта "Radio Button" +; object ~Claster radio buttons~ (имеет фокус) +; Input: HL-описатель объекта +; Format table: +; +0 - номер объекта ~Radio Button" +; +1 - Xo левое полож. объекта +; +2 - Xi правое полож. объекта +; +3 - Yo левое полож. объекта +; +4 - Yi правое полож. объекта +; +5 - Xi правое полож. имени +; from: +0 - Y полож. radio-кнопки +; +1 - скен-код hot-буквы +; +2 - триг. ячейка +; +3,4 - адрес ячейки +; 80h - конец таблицы объекта +;--------------------------------------------------------------------- +; db ClsRadioBut ; номер объекта +; dw 0202h,0112h ; Yo,Xo,lenY,lenX (с "() ") +; db "&Viewer command",0 ; имя элемента +; db 2Dh ; скен-код hot-буквы +; dw Mode1 ; ячейка памяти +; db "&Editor command",0 ; имя элемента +; db 12h ; скен-код hot-буквы +; dw Mode2 ; ячейка памяти +; db 0 ; конец кластера +;===================================================================== +PutClsRadioBut: + push iy + inc iy + ld (iy+0),a ; номер объекта + ld a,(hl) ; X pos + inc hl + ld c,a + ld (ix+4),a ; Save X pos + add a,(ix+0) ; Pos X from begin screen + ld (iy+1),a ;+1 Xo + ld a,(hl) ; Y pos + inc hl + ld b,a + ld (ix+5),a ; Save Y pos + add a,(ix+1) ; Pos Y from begin screen + ld (iy+3),a ;+3 Yo + call GetPutA + ld a,(hl) + inc hl + ld (ix+6),a + add a,(iy+1) + ld (iy+2),a ; Xi pos + ld a,(hl) + inc hl + add a,(iy+3) + ld (iy+4),a + ld a,(ix+6) + add a,(iy+1) + ld (iy+5),a ; Xi pos name + ld bc,6 ; next element claster + add iy,bc + ; Next element +ClChkLp:ld c,(ix+4) ; pos element + ld b,(ix+5) + call GetPutA + ld b,0 + ex de,hl + ld (hl),"(" + inc hl + inc hl + inc b + push hl + inc hl + inc hl + inc b + ld (hl),")" + inc hl + inc hl + inc b + inc hl + inc hl + inc b + ; имя элемента объекта + ld a,(color_array+24) ; цвет диал. окна + ld c,a + ld a,(de) +ClChkL1:inc de + cp "&" + jr nz,ClChkN0 + ld a,(color_array+25) ; цвет hot-буквы диал. окна + ld c,a + ld a,(de) + inc de + ld (hl),a + inc hl + ld a,(hl) + and 0F0h + or c + ld (hl),a + inc hl + ld a,(color_array+24) ; цвет диал. окна + ld c,a + inc b + ld a,(de) + inc de +ClChkN0:ld (hl),a + inc hl + ld (hl),c + inc hl + inc b + ld a,(de) + or a + jr nz,ClChkL1 + inc de + ld a,(ix+5) ; Current Y pos + add a,(ix+1) ; from begin screen + ld (iy+0),a + inc iy + ex de,hl + ld a,(hl) + inc hl + ld (iy+0),a ; скен-код hot-буквы + inc iy + ld c,(hl) + inc hl + ld b,(hl) + inc hl + ld a,(bc) + ld (iy+0),a ; ячейка + inc iy + ld (iy+0),c ; bc=адрес ячейки + inc iy + ld (iy+0),b + inc iy + pop bc + or a + ld a," " + jr z,$+4 + ld a,"" + ld (bc),a + inc (ix+5) + ld a,(hl) + or a + jp nz,ClChkLp + ld (iy+0),80h ; End tab claster + inc iy + inc hl + ; сохр. размер таблицы в Таблице объектов + push iy + exx + pop hl + pop de + or a + sbc hl,de + ld a,l + ld (de),a + exx + ld a,1 + ld (SavElem+1),a ; первый элемент + ret + + + +;===================================================================== +; Прорисовка объекта "Check Box" +; object ~Claster check buttons~ (имеет фокус) +; Input: HL-описатель объекта +; Format table: +; +0 - номер объекта "CheckBox" +; +1 - Xo левое полож. объекта +; +2 - Xi правое полож. объекта +; +3 - Yo левое полож. объекта +; +4 - Yi правое полож. объекта +; +5 - Xi правое полож. имени объекта +; from: +0 - Y полож. чек-бокса +; +1 - скен-код hot-буквы +; +2 - триг. ячейка +; +3,4 - адрес ячейки +; 80h - конец таблицы объекта +;--------------------------------------------------------------------- +; db ClsCheckBox ; номер объекта +; dw 0202h,0225h ; Yo,Xo,lenY,lenX (с "[x] ") +; db "&Clear r/o attribute",0 ; имя элемента +; db 2Ch ; скен-код hot-буквы +; dw cSystem1 ; адрес ячейки +; db "Clear &attribute",0 ; имя элемента +; db 1Dh ; скен-код hot-буквы +; dw cSystem2 ; адрес ячейки +; db 0 ; конец кластера +;===================================================================== +PutClsCheckBox: + PUSH IY + INC IY + LD (IY+0),A ; номер объекта + LD A,(HL) ; Xo pos + INC HL + LD C,A + LD (IX+4),A ; Save X pos ## + ADD A,(IX+0) ; Pos X from begin screen + LD (IY+1),A ;+1 Xo + LD A,(HL) ; Yo pos + INC HL + LD B,A + LD (IX+5),A ; Save Yo pos + ADD A,(IX+1) ; Pos Yo from begin screen + LD (IY+3),A ;+3 Yo + CALL GetPutA + LD A,(HL) ; X Len + INC HL + LD (IX+6),A ; ширина объекта + ; + ADD A,(IY+1) ;+1 Xo левая позиция объекта + LD (IY+2),A ;+2 Xi pos + LD A,(HL) ; Y Len + INC HL + ADD A,(IY+3) ;+3 Yo pos object + LD (IY+4),A ;+4 Yi pos object + LD A,(IX+6) + ADD A,(IY+1) + LD (IY+5),A ; Xi pos name + LD BC,6 ; next element claster + ADD IY,BC + ; Next element +ClRadLp:LD C,(IX+4) ; pos element + LD B,(IX+5) + CALL GetPutA + LD B,0 + EX DE,HL + LD (HL),"[" + INC HL + INC HL + INC B + PUSH HL + INC HL + INC HL + INC B + LD (HL),"]" + INC HL + INC HL + INC B + INC HL + INC HL + INC B + ; имя элемента объекта + LD A,(color_array+24) ; цвет диал. окна + LD C,A + LD A,(DE) +ClRadL1:INC DE + CP "&" + JR NZ,ClRadN0 + LD A,(color_array+25) ; цвет hot-буквы диал. окна + LD C,A + LD A,(DE) + INC DE + LD (HL),A + INC HL + LD A,(HL) + AND 0F0h + OR C + LD (HL),A + INC HL + LD A,(color_array+24) ; цвет диал. окна + LD C,A + INC B + LD A,(DE) + INC DE +ClRadN0:LD (HL),A + INC HL + LD (HL),C + INC HL + INC B + LD A,(DE) + OR A + JR NZ,ClRadL1 + INC DE + LD A,(IX+5) ; Current Y pos + ADD A,(IX+1) ; from begin screen + LD (IY+0),A + INC IY + EX DE,HL + ld a,(hl) + ld (iy+0),a ; скен-код hot-буквы + inc hl + inc iy + LD C,(HL) + INC HL + LD B,(HL) + INC HL + LD A,(BC) + LD (IY+0),A ; ячейка + INC IY + LD (IY+0),C ; bc=адрес ячейки + INC IY + LD (IY+0),B + INC IY + POP BC + OR A + LD A," " + JR Z,$+4 + LD A,"x" + LD (BC),A + INC (IX+5) + LD A,(HL) + OR A + JP NZ,ClRadLp + LD (IY+0),80h ; End tab claster + INC IY + INC HL + ; сохр. размер таблицы в Таблице объектов + push iy + exx + pop hl + pop de + or a + sbc hl,de ; длина таблицы "Check Box" + ld a,l + ld (de),a ; DialTab+5 + exx + ld a,1 + ld (SavElem+1),a ; первый элемент + ret + + +;----------------------------------------------------------- +; Начальный фокус на объект "Check Box" или "Radio Button" +;----------------------------------------------------------- +ClastI: ld de,color_array+24 ; 70h цвет диал. окон + ld (set_dial_tmp_inv+1),de ; не "выделять" цветом чек-боксы + ld e,(ix+2) ; Xo + inc e + ld d,(ix+4) ; Y + ld a,(ix+6) ; Xi name + sub e + ld c,a + call SetDialInv + ld hl,color_array+26 + ld (set_dial_tmp_inv+1),hl ; восст. ячейку + push ix + pop hl + ld de,7 + add hl,de + ld a,(ix+7) ; Y полож. 1-го элемента кластера + ld (hl),a ; Y pos check button + jp SetClasInv ; выделить элемент объекта + + + +;------------------------------------------------- +; Узнать состояние ячейки кластера +;------------------------------------------------- +GetClsData: + push ix + pop hl + ld bc,7 + add hl,bc ; Begin claster elements +GetDtLp:inc hl ; Y pos + inc hl ; скен-код hot-буквы + ld a,(hl) ; ячейка + inc hl + ld e,(hl) ; de=дрес ячейки + inc hl + ld d,(hl) + inc hl + ld (de),a + bit 7,(hl) ; 7bit-End claster + jr z,GetDtLp + ret + + + + + +;===================================================================== +; +; Обработчик событий объектов "Check Box" и "Radio Button" +; +;===================================================================== +EvClasterBut: + ld hl,what + ld a,(hl) + inc hl + cp evMouseFr + jr z,ECmouse ; Mouse fire + cp evKeyboard + jr z,ECkeys ; Key press + cp evCombKey + jp z,ECcombK ; Key press + ret + +; Событие - Мышка +ECmouse:LD E,(HL) ; X pos + INC HL + LD D,(HL) ; Y pos + LD A,E + BIT 7,(IX+2) + JR NZ,$+6 + CP (IX+2) ; Xo left pos + RET C ; < + BIT 7,(IX+3) + RET NZ + CP (IX+3) ; Xi right pos + RET NC ; > + LD A,D + CP (IX+4) ; Yo left pos + RET C ; < + CP (IX+5) ; Yi right pos + RET NC ; > + xor a + LD (ECnext+1),a + DEC A + LD (SaveA1+1),a ; Begin element claster + PUSH IX + POP HL + INC HL + inc hl + ld bc,5 ; len element claster + LD E,B ; number element + LD A,D +EClsLp1:ADD HL,BC + BIT 7,(HL) + JP NZ,SelClas ; Elem not found + INC E + CP (HL) ; Compare with Y pos elem + JR NZ,EClsLp1 + JR CSelNxt + +; Событие - обычная клавиша +ECkeys: xor a + ld (ECnext+1),a + dec a + ld (SaveA1+1),a ; Begin element claster + ld a,(hl) ;+1 what + cp 20h ; пробел + jr z,ECspace + bit 7,(ix+1) + jr nz,ECkeyN ; объект уже выделен + cp 9 ; Tab + jp z,SelCls0 ; If tab then select my +ECkeyN: inc hl + ld a,(hl) ;+2 what скен-код + push ix + pop hl + inc hl + inc hl + ld bc,5 ; Len elements + ld e,b +ECkeyLp:add hl,bc + bit 7,(hl) + ret nz + inc e + inc hl + cp (hl) ; hot-key element + dec hl + jr nz,ECkeyLp +CSelNxt:bit 7,(ix+1) + jp nz,CSelect ; объект уже выделен + jp SelCls1 + +; Обработка пробела +ECspace:BIT 7,(IX+1) + RET Z ; not select + LD A,(SavElem+1) + OR A + JR NZ,ECspc1 + INC A + LD (SavElem+1),A +ECspc1: LD (ECnext+1),A + PUSH IX + POP HL + INC HL + inc hl + ld de,5 + LD B,A + ADD HL,DE ; find elem.label + DJNZ $-1 + JP ECnext ; change + +; Курсорные клавиши +ECcombK:bit 7,(ix+1) + jr nz,ECcombn ; объект уже выделен + ld b,(hl) ;+1 what + inc hl + ld a,(hl) ;+2 what + cp 56h ; курсор вправо + jp z,SelCls0 + push ix + ld e,(ix+0) ; размер таблицы "Input Line" + ld d,0 + add ix,de + bit 7,(ix+0) + pop ix + ret z ; еще не конец объектов + cp 54h ; курсор влево + jp z,SelCls0 + ld a,b + and 00111111b ; биты Ctrl, Alt + ret nz + ld a,(hl) ;+2 what + cp 15+80h ; Tab скен-код+80h + ret nz + jp SelCls0 ; If tab then select my + ; +ECcombn:xor a + ld (ECnext+1),a ; Flag change buttons + inc hl + ld a,(hl) ;+2 what + cp 58h ; вверх + jr z,ECup + cp 54h ; влево + jr z,ECup + cp 52h ; вниз + jr z,ECdown + cp 56h ; вправо + ret nz +; курсор вниз +ECdown: PUSH IX + POP HL + INC HL + inc hl + ld e,l + ld d,h + ld bc,5 + LD A,(SavElem+1) + OR A + JR NZ,$+3 + INC A + INC A ; increment element + LD (SavElem+1),A +ECcmlp: ADD HL,BC ; find label + BIT 7,(HL) + CALL NZ,EndClst ; table is over + DEC A + JR NZ,ECcmlp + CALL ResClasInv ; Res inver elem + JP Pcurs ; next invert + +; Get begin table elem +EndClst:EX DE,HL + ADD HL,BC ; table is begin + LD A,1 + LD (SavElem+1),A ; first elem. + RET + +; Курсор вверх +ECup: PUSH IX + POP HL + INC HL + inc hl + ld de,5 + LD A,(SavElem+1) + OR A + JR NZ,$+3 + INC A + DEC A ; decrement cur.elem. + CALL Z,BegClst + LD (SavElem+1),A + LD B,A + ADD HL,DE ; find label + DJNZ $-1 + CALL ResClasInv ; Res inver elem + JR Pcurs ; next invert + +; Get end table elem +BegClst:PUSH HL + SUB A + DEC A + INC A + ADD HL,DE ; find nember end element + BIT 7,(HL) + JR Z,$-4 + POP HL + RET ; A=end element + +; selected claster +SelClas:BIT 7,(IX+1) + JR NZ,SaveA1 ; NZ-is select +SelCls0:ld e,0 +SelCls1:LD A,E + LD (SaveA1+1),A + call MoveObj + call ResDialInv ; Res orevios invert + LD IX,DialTab+5 +SaveA1: LD A,0 + INC A + JR Z,EClexit ; Element not found + DEC A + LD (SavElem+1),A + LD (ECnext+1),A + JR CButton ; Change buttons + +; Событие - Мышка (в выбранном кластере) +CSelect:LD A,1 + LD (ECnext+1),A + LD A,(SavElem+1) + CP E + JR Z,ECnext + LD A,E + LD (SavElem+1),A + CALL ResClasInv ; Res inver elem +CButton:PUSH IX + POP HL + INC HL + inc hl + ld de,5 +SavElem:LD A,0 + OR A + JR NZ,$+3 + INC A + LD B,A + ADD HL,DE + DJNZ $-1 +Pcurs: CALL SetClasInv ; Set inver elem +ECnext: ld a,0 + or a + call nz,ChangeB +EClexit:ld hl,what ; Event claster exit + ld (hl),evNothing + jp get_fire + + + +;--------------------------------------------------------------------- +; Изменение элементов CheckBox-а или Radio-кнопок +; +; вход: HL-Address claster element label +;--------------------------------------------------------------------- +ChangeB:LD A,(IX+1) + RES 7,A + CP ClsCheckBox + JP Z,ChangeR ; изменить CheckBox + ; Изменить Radio-кнопку + LD E,L + LD D,H + PUSH IX + POP HL + LD BC,7 + ADD HL,BC + PUSH HL ; Save cur.elem +ChangL1:INC HL ; Begin elements claster + INC HL + ;INC HL + LD (HL),B ; (Ceil)=0 + INC HL + INC HL + INC HL + BIT 7,(HL) + JR Z,ChangL1 + EX DE,HL ; HL=Current element claster + INC B + INC HL + INC HL + INC HL + LD (HL),B ; Cur.elem=1 + INC HL + INC HL + INC HL + POP HL ; Reset begin elem table + IN A,(SLOT3) + PUSH AF + LD A,(page_dial_screen) + OUT (SLOT3),A +ChangL2:LD D,(HL) ; Y pos + INC HL + INC HL + ;INC HL ;? + LD A,(HL) ; Address ceil + INC HL + INC HL + INC HL + LD E,(IX+2) ; X полож. "" + INC E + PUSH IX + PUSH DE + LD IX,DialData + EX AF,AF' + LD A,E + SUB (IX+0) + LD C,A + LD A,D + SUB (IX+1) + LD B,A + CALL GetPutA + EX AF,AF' + LD C,A + OR A + LD A," " + JR Z,$+4 + LD A,"" + LD (DE),A + POP DE + POP IX + LD A,D + CP 31 + JR NC,cl1 + BIT 7,E + JR NZ,cl1 + LD A,E + CP 80 + JR NC,cl1 + PUSH HL + LD A,C + PUSH AF + LD C,84h ; Set position print + RST 08h + POP AF + OR A + LD A," " + JR Z,$+4 + LD A,"" + LD BC,0182h + RST 08h ; Print on/off + POP HL +cl1: BIT 7,(HL) + JR Z,ChangL2 + CALL ResILCr ; Res cursor + CALL PILCurs ; Set cursor + EI + POP AF + OUT (SLOT3),A + RET + +;------------------------------------------------- +; Изменение элемента CheckBox-а +;------------------------------------------------- +ChangeR: + IN A,(SLOT3) + PUSH AF + LD A,(page_dial_screen) + OUT (SLOT3),A + LD D,(HL) ; Y pos + INC HL + INC HL + LD A,(HL) ; ячейка + XOR 1 + LD (HL),A + INC HL + INC HL + INC HL + LD E,(IX+2) ; X полож. "x" + INC E + PUSH IX + PUSH DE + LD IX,DialData + EX AF,AF' + LD A,E + SUB (IX+0) + LD C,A + LD A,D + SUB (IX+1) + LD B,A + CALL GetPutA + EX AF,AF' + LD C,A + OR A + LD A," " + JR Z,$+4 + LD A,"x" + LD (DE),A + POP DE + POP IX + LD A,D + CP 31 + JR NC,cl2 + BIT 7,E + JR NZ,cl2 + LD A,E + CP 80 + JR NC,cl2 + LD A,C + PUSH AF + LD C,84h ; Set position print + RST 08h + POP AF + OR A + LD A," " + JR Z,$+4 + LD A,"x" + LD BC,0182h + RST 08h ; Print +cl2: CALL ResILCr + CALL PILCurs + EI + POP AF + OUT (SLOT3),A + RET diff --git a/OBJS/UMENU.ASM b/OBJS/UMENU.ASM new file mode 100755 index 0000000..b24e3b0 --- /dev/null +++ b/OBJS/UMENU.ASM @@ -0,0 +1,614 @@ +; #C000+#2800=#E800 +; Буферы User-данных +array_user1 equ 0E800h ; 26*2 массив указ. на ком-строки +array_user2 equ array_user1+(26*2) ; 72*56 описатель пунктов меню + ; + 1 байт под конец описателя +array_user3 equ array_user2+(72*26)+1 ; 71*26 массив ком-строк + +; остаток банки после всего массива #0944 байт. + + + + + + +;----------------------------------------------------------- +; Вызов Меню Пользователя +;----------------------------------------------------------- +user_menu: + ld a,(enable_mnu_file) ; флаг наличия mnu-файла + or a + ret z ; нет + ld hl,user_table ; описатель меню (mod1) + call put_user_menu ; отрисовка меню + call get_fire ; защита от "залипания" бутонов + call event_user_menu ; обработчик событий меню + ; + ld hl,what + ld a,(hl) + cp evCommand + ret nz + ld (hl),evRunComLine ; событие "отработать ком-строку" + jp get_fire + + + + + +;----------------------------------------------------------- +; Прорисовка меню пользователя. +; Положение меню определяется шириной и числом пунктов. +; Таблица меню: +; Положение окна меню: +; +0 - Xo левый край +; +1 - Xi правый край +; +2 - Yo левый угол +; +3 - Yi правый угол +; +4 - Положение пункта меню: +; +0 - Xo левое +; +1 - Xi правое +; +2 - Y полож. +; +3 - hot-буква +;----------------------------------------------------------- +; вход: hl=описатель меню +;----------------------------------------------------------- +put_user_menu: + ld a,1 + ld (CurMBox),a ; номер пункта меню + push iy + ld iy,BoxTabl ; Generes MenuBox mouse table + ld ix,BoxData + ld a,(page_sys_screen) ; стр. user-данных + out (SLOT3),a + ld e,(hl) + inc hl + ld d,(hl) + inc hl + ld (usermenu_title+1),de ; адрес заголовка окна + ld a,(hl) ; адрес описателя тек. меню + ld (ix+0),a ; сохр. адрес описателя + inc hl + ld h,(hl) + ld (ix+1),h ; + ld l,a + call GetLenB1 ; get in DE len Y,X MenuBox + ; X центровка меню + ld a,80 ; ширина окна + sub e + srl a ; /2 + ld (iy+0),a ; Xo полож. окна меню + ld b,a + inc a + ld (ix+2),a ; Xo полож. пункта меню + ld a,e ; ширина окна (без тени) + sub 2 + ld (ix+5),a ; ширина окна без рамки + ld a,e + add a,b ; + Xo полож. окна меню + ld (iy+1),a ; X правый край окна меню + dec a + ld (ix+3),a ; Xi правый край пункта меню + ; Y центровка меню + ld a,30 ; высота окна + sub d + srl a ; /2 + ld (iy+2),a ; Yo полож. окна меню + ld (ix+4),a ; Temp Y posit for element box + ld b,a + ld a,d ; высота окна (без тени) + add a,b ; Yi (+ Y полож. окна меню) + ld (iy+3),a + call SaveBox ; сохр. экран под будущим окном + in a,(SLOT3) + push af + ld a,(page_dial_screen) ; Page buffer + out (SLOT3),a + ; начало вставки окна с тенью в буфер + ld hl,LC000+MaxDialWin + ld bc,4 + add iy,bc ; адрес описателя меню + exx + ld hl,LC000 + ld a,(ix+5) ; ширина окна + inc a + inc a + add a,a + ld e,a + ld d,0 + add hl,de + exx + ld a,(color_array+15) ; цвет верт. меню + ld c,a + ; центровка заголовка + push hl + ld de,(usermenu_title+1) ; адрес заголовка окна + ld a,(de) ; длина заголовка + ld b,a + ld a,(ix+5) ; ширина окна + sub b + srl a ; /2 + add a,a ; учесть атрибуты (результат всегда четный) + ld e,a + ld d,0 + add hl,de + ld (usermenu_addr+1),hl ; адрес вставки + pop hl + ; рамка окна + ld (hl),"╔" ; левый верх. угол + inc hl + ld (hl),c ; цвет + inc hl + ld b,(ix+5) ; ширина окна + ld a,"═" + ld (hl),a + inc hl + ld (hl),c + inc hl + djnz $-4 + ld (hl),"╗" ; правый верх. угол + inc hl + ld (hl),c + inc hl + ; + push hl +usermenu_title: + ld de,0 ; адрес титла окна +usermenu_addr: + ld hl,0 ; адрес вставки + ld a,(de) + ld b,a ; длина строки + inc de + ld (hl)," " + inc hl + inc hl + ld a,(de) + ld (hl),a + inc hl + inc hl ; атрибут + inc de + djnz $-5 + ld (hl)," " + pop hl + ; + ld b,3 + call copy_cell + exx + ld a,(hl) + inc hl + add hl,de + exx + ld (hl),a + inc hl + ld e,(ix+0) ;; de=адрес списка пунктов + ld d,(ix+1) +; цикл вывода пунктов меню +usermenu_loop: + inc (ix+4) ; увеличить Y-полож. пункта меню + call get_user_byte ; взять байт из стр. user-данных + cp -2 ; разделитель + jr nz,usermenu1__ + ; вставить разделитель пунктов + inc de + ld (hl),"╟" + inc hl + ld (hl),c + inc hl + ld b,(ix+5) ; ширина пункта + ld a,"─" + ld (hl),a + inc hl + ld (hl),c + inc hl + djnz $-4 + ld (hl),"╢" + jr usermenu3__ +usermenu1__: + cp -1 ; конец описателя ? + jp z,usermenu4__ ; да + ld a,(ix+2) + ld (iy+0),a ;+0 Xo coord + inc iy + ld a,(ix+3) + ld (iy+0),a ;+1 Xi coords + inc iy + ld a,(ix+4) + ld (iy+0),a ;+2 Y coords + inc iy + ld (hl),"║" + inc hl + ld (hl),c + inc hl + ld b,2 ; 2 пробела в начале пункта + ld (hl)," " + inc hl + ld (hl),c + inc hl + djnz $-5 + inc b ; b=1 + call get_user_byte ; взять байт из стр. user-данных +usermenu2__: + inc de + cp "&" + call z,Bhotkey2__ ; вставить hot-букву + ld (hl),a ; Put name element + inc hl + ld (hl),c + inc hl + inc b + call get_user_byte ; взять байт из стр. user-данных + or a ; конец имени ? + jr nz,usermenu2__ + inc de ; de=ячейка скен-кода пункта + call get_user_byte ; взять байт из стр. user-данных + ld (iy+0),a ;+3 скен-код hot-клавиши + inc iy + inc de + ld a,(ix+5) ; ширина тек. пункта + dec a + sub b + ld b,a + ld (hl)," " ; заполнить остаток пункта + inc hl + ld (hl),c + inc hl + djnz $-5 + ld (hl),"║" +usermenu3__: + inc hl + ld (hl),c + inc hl + exx + ld a,(hl) + inc hl + inc hl + exx + ld (hl),a + inc hl + ld (hl),color_shadow ; цвет тени + inc hl + exx + ld a,(hl) + inc hl + inc hl + add hl,de + exx + ld (hl),a + inc hl + ld (hl),color_shadow ; цвет тени + inc hl + jp usermenu_loop ; назад в цикл + ; +usermenu4__: + ld (iy+0),80h ; конец таблицы пунктов + ld (hl),"╚" + inc hl + ld (hl),c + inc hl + ld b,(ix+5) + ld a,"═" + ld (hl),a + inc hl + ld (hl),c + inc hl + djnz $-4 + ld (hl),"╝" + inc hl + ld (hl),c + inc hl + ; вставить 2 тени угла "┘" + ld b,2 + call print_shadow + ; вставить нижнюю тень + ld b,4 + call copy_cell ; скопир. ячейки + ld b,(ix+5) ; Full Len box + inc b + inc b + call print_shadow + pop af + out (SLOT3),a + call PutBox + pop iy + jp USetBoxI ; Set box invert + + + +;------------------------------------------------- +; Установить цвет hot-буквы пункта user-меню +;------------------------------------------------- +Bhotkey2__: + call get_user_byte ; взять байт из стр. user-данных + ld (hl),a ; hot-букву в буфер + inc hl + inc de + push de + ld a,(color_array+17) ; цвет hot-буквы меню + and 0Fh + ld e,a + ld a,(color_array+15) ; цвет верт. меню + and 0F0h + or e + ld (hl),a ; атрибут + pop de + inc hl + call get_user_byte ; взять байт из стр. user-данных + inc de + inc b + ret + + + +;----------------------------------------------------------- +; Вычислить ширину текущего окна верт. меню +; +; вход: hl=описатель меню +; выход: de=высота/ширина окна +;---------------------------------------------------------- +GetLenB1: + ld de,0207h ; Y/X размеры + ld b,e + dec b +GetL1: ld a,(hl) + inc hl + cp -1 ; конец описателя ? + ret z + cp -2 ; разделитель пунктов ? + jr z,AddLn +GetL2: inc b +GetL3: ld a,(hl) + inc hl + cp "&" ; hot-буква + jr z,GetL3 + or a ; конец названия пункта ? + jr nz,GetL2 ; нет + inc hl ; пройти скен-код + ld a,b + cp e + jr c,AddLn + ld e,b +AddLn: inc d + ld b,6 ; b=e-1 + jr GetL1 + + + +; Взять байт из страницы user-данных +; вход: de=адрес данных +get_user_byte: + in a,(SLOT3) + push af + ld a,(page_sys_screen) ; стр. user-данных + out (SLOT3),a + ld a,(de) + ex af,af' + pop af + out (SLOT3),a ; восст. стр. + ex af,af' + ret + + + + +;----------------------------------------------------------- +; +; Обработчик событий Меню Пользователя +; +;----------------------------------------------------------- +event_user_menu: + call handle_event ; читаем событие + ld hl,what + ld de,event_user_menu + push de + ld a,(hl) ;+0 узнать событие + inc hl + cp evMouseFr ; нажаты бутоны мышки + jp z,user_menu_mouse + cp evKeyboard ; нажаты обычные клавиши + jr z,user_menu_keys + cp evCombKey ; нажаты курс. клавиши и служ. + jr z,user_menu_ckeys + ret + ; +user_menu_exit: + call CloseBx ; закрыть меню + pop de ; восст. баланс стека + ld hl,what + ld (hl),evNothing ; "нет событий" + ret + +;------------------------------------------------- +; Обычные клавиши +;------------------------------------------------- +user_menu_keys: + ld a,(hl) ;+1 код клавиши + cp 1Bh ; Esc + jr z,user_menu_exit + cp 0Dh ; Enter + jr nz,user_menu_keys1 + ld a,(CurMBox) + ld b,a + ld ix,BoxTabl ; поиск пункта меню + ld de,4 + add ix,de + djnz $-2 + jp UBxEnt + ; +user_menu_keys1: + inc hl + ld a,(hl) ;+2 скен-код клавиши + ld ix,BoxTabl ; рабочая таблица меню + ld bc,4 + ld h,b +user_menu_keys2: + inc h + add ix,bc + bit 7,(ix+0) + ret nz ; конец таблицы пунктов + cp (ix+3) ; скен-код hot-клавиши + jr nz,user_menu_keys2 + jp UBxHotEx + +;------------------------------------------------- +; Курсорные клавиши и F10 +;------------------------------------------------- +user_menu_ckeys: + inc hl + ld a,(hl) ;+2 what + cp 44h ; F10 + jr z,user_menu_exit + cp 58h ; вверх + jr z,UMBup + cp 52h ; вниз + jr z,UMBdown + cp 54h ; влево + jr z,UMBhome + cp 56h ; вправо + jr z,UMBend + cp 59h ; PageUp + jr z,UMBhome + cp 53h ; PageDown + jr z,UMBend + cp 57h ; Home + jr z,UMBhome + cp 51h ; End + jr z,UMBend + ret + +; Курсор вверх +UMBup: ld a,(CurMBox) + dec a + jr nz,UMBupNxt + ld ix,BoxTabl ; рабочая таблица меню + ld bc,4 + ld a,b + dec a +UMBupLp:inc a ; поиск последнего элемента + add ix,bc + bit 7,(ix+0) + jr z,UMBupLp +UMBupNxt: + ld (CurMBox),a + ld b,a + ld ix,BoxTabl ; рабочая таблица меню + ld de,4 + add ix,de + djnz $-2 + push ix + call ResBoxI + call USetBoxI + pop ix + ret + +; Курсор вниз +UMBdown:ld a,(CurMBox) + inc a + ld ix,BoxTabl ; рабочая таблица меню + ld bc,4 + ld h,b ; тест на последний элемент +UMBdnLp:inc h + add ix,bc + bit 7,(ix+0) + jr z,UMBdnLp + cp h + jr nz,$+4 +; Home в начало списка +UMBhome:ld a,1 + jr UMBupNxt + +; End в конец списка +UMBend: ld a,(CurMBox) + ld h,a + ld ix,BoxTabl ; рабочая таблица меню + ld bc,4 + ld a,b + dec a +UMBendLp: + inc a ; поиск последнего элемента + add ix,bc + bit 7,(ix+0) + jr z,UMBendLp + cp h + jr nz,UMBupNxt + ret + +;------------------------------------------------- +; События мышки +;------------------------------------------------- +user_menu_mouse: + ld e,(hl) ;+1 X coord + inc hl + ld d,(hl) ;+2 Y coord + ; проверка на коорд. мышки и окна + ld ix,BoxTabl ; рабочая таблица + ld a,e + cp (ix+0) + jp c,user_menu_exit ; < Xo + cp (ix+1) + jp nc,user_menu_exit ; > Xi + ld a,d + cp (ix+2) + jp c,user_menu_exit ; < Yo + cp (ix+3) + jp nc,user_menu_exit ; > Yi + ld bc,4 + ld h,b +usermenu_mouse_loop: + inc h + add ix,bc + bit 7,(ix+0) ; конец описателя меню ? + ret nz ; да + ld a,d + cp (ix+2) + jr nz,usermenu_mouse_loop + ld a,e ; поиск пункта меню + cp (ix+0) + jr c,usermenu_mouse_loop ; < Xo + cp (ix+1) + jr nc,usermenu_mouse_loop ; > Xi +UBxHotEx: + ld a,(CurMBox) + cp h + jr z,UBxEnt ; уст. пункт меню + ld a,h + ld (CurMBox),a + push af + call ResBoxI + call USetBoxI + pop af + halt + halt + halt + halt + ; выполн. пункта по или мышке +UBxEnt: dec a + ld hl,what + ld (hl),evCommand ; уст. событие "команда" + ; скопир. ком-строку в буфер + add a,a + ld e,a + ld d,0 + ld a,(page_sys_screen);; ; стр. user-данных + out (SLOT3),a;; + ld hl,array_user1 ; таблица указателей на ком-строки + add hl,de + ld e,(hl) + inc hl + ld d,(hl) + ex de,hl ; hl=откуда + ld de,work_buffer+127;255 ; куда + call copy_string ; скопир. строку (с нулем) + ; закрыть меню + call CloseBx + pop de + ret ; выйти из меню + + +;------------------------------------------------- +; Инвертирование пункта меню +;------------------------------------------------- +USetBoxI: + ld c,0 + ld a,(CurMBox) + dec a + add a,a ;1+1=2 + jp SetBoxI1 diff --git a/SHELL.ASM b/SHELL.ASM new file mode 100755 index 0000000..02eca80 --- /dev/null +++ b/SHELL.ASM @@ -0,0 +1,2417 @@ +true equ 1 +false equ 0 + +; Число файлов на колонку +files_per_colon equ 25 + +; Форматы панелей +form_full equ 00000001b ; 0-bit full +form_med equ 00000010b ; 1-bit medium +form_brief equ 00000100b ; 2-bit brief +form_info equ 00001000b ; 3-bit info +form_qview equ 00010000b ; 4-bit qview +;form_tree equ 00100000b ; 5-bit tree +form_trd equ 01000000b ; 6-bit trd/scl формат +;form_ equ 10000000b ; 7-bit + + + + + + + ; Стек уже стоит на @stack + + call read_ini_file ; прочитать ini-файл (если есть) + ; вкл. в #0000 драйверы клавы, мышки, объекты + di + ld a,(page_module0) + out (SLOT0),a + ; настроить опц. ячейки, диски и пути панелей + call init_option_cells ; берет данные из work_buffer + call set_colors ; настроить цвета оболочки + ; выкл. вывод часов + ld hl,enable_clock ; флаг + ld a,(hl) + ld (clock__+1),a ; сохр. + ld (hl),false ; сбр. + ei + + ;ld a,form_info + ;ld (format_mode),a + + call make_user_menu ; создать Меню Пользователя + +; холодный вход (все, кроме дос-команд) +cold_entry: + ; уст. конфигурацию Sprinter-2 (вкл. аксель) + ld c,0F1h + rst 08h + ; цвет бордюра + xor a + out (0FEh),a + ; уст. внутр. палитру + ld a,1 ; номер экрана + ld bc,03A6h ; CGA-палитра + rst 08h + + call init_list_types_drives ; иниц. список типов дисков системы + call get_total_free_space ; своб. место на 2 дисках панелей + +; теплый вход (для дос-команд) +warm_entry: + ; сохр. полож. курсора сист. экрана + ld c,8Eh + rst 08h + ld (sys_cursor_coords+1),de + ; уст. текст. режим экрана + ld a,3 ; 80x32x16 цветов + ld bc,0150h ; b=1 экран + rst 10h + ; сохр. сист. экран + ld c,0B2h + ld a,(page_sys_screen) ; стр. буфера окна + call screen__ + ld a,0C0h + out (89h),a ; закрыть спек. экран + + ; инит. драйвер клавы + xor a + rst 20h + ; очистить буфер клавы + ld a,1 + rst 20h + ; иниц. обработчик событий + call InitEvent + + ld a,(present_doscmnd) ; признак отработки дос-команд + or a + jr z,entry1 ; не дос-команда + db 3Eh ; ld a,.. +number_command: db 0 ; порядк. номер дос-команды + cp 14 ; "rename" + jr c,entry2 + ; 23..14 номера команд, изменяющих список диска +entry1: + ; Заполнить банки списками файлов акт. панель + call save_pos_list ; сохр. прежнее полож. указателя и списка + call read_new_folder ; новый список каталога + размер папки + call sorting ; раздельный список указателей + сорт. списка + call set_newpos_list ; уст. полож. указателя и списка + ; пасс. панель + call change_panel ; сменить панель + call read_new_folder + call sorting + call change_panel + +entry2: xor a + ld (present_doscmnd),a ; сбр. признак дос-команд + ld (number_command),a ; сбр. номер команды + ld (this_cd),a ; сбр. признак "cd","chdir" команд + + + call PutComLine ; нач. вывод пути в ком-строке + call print_keybar ; начальный вывод key-бара + + call A20FC ; вывести аст. панель + call change_panel ; сменить панель + call A20FC ; вывести пасс. панель + call change_panel + + call print_status ; статусная строка панели + call show_pointer ; начальный вывод указателя + call init_mouse ; иниц. и показать мышку + +clock__: ld a,false + ld (enable_clock),a ; восст. флаг + + +; главный цикл +main_loop: ld hl,main_loop ; точка возврата + push hl + ; + ld hl,what ; поле событий + ld a,(hl) ; событие + cp evRunComLine ; событие "отработать ком-строку" + jp z,parsing_command_line ; launch.asm + ; + halt + ld a,3 ; тест нажатия клавиш + rst 20h + ld a,b + and 11110000b ; Ctrl,Alt,Shift ? + jp nz,change_keybar ; сменить вид key-бара и отраб. опцию + call dinam_qview_panel ; отраб. при вкл. qview-панели + jp nz,change_keybar ; сменить вид key-бара и отраб. опцию + call handle_event ; читаем событие + ld a,(what) ;+0 список событий + cp evNothing + ret z + cp evMouseFr + jp z,buttons_press ; бутоны нажаты + cp evKeyboard + jp z,normal_char ; обычные клавиши + cp evCombKey + ret nz + ld a,d + cp 58h ; курсор вверх + jp z,up + cp 52h ; курсор вниз + jp z,down + cp 54h ; курсор влево + jp z,left + cp 56h ; курсор вправо + jp z,right + cp 53h ; PageDown + jp z,page_down + cp 59h ; PageUp + jp z,page_up + cp 57h ; Home + jp z,home_list + cp 51h ; End + jp z,end_list + ld a,d + cp 3Bh ; F1 + ;jp z, + cp 3Ch ; F2 + jp z,user_menu + cp 3Dh ; F3 + jp z,file_viewer + cp 3Eh ; F4 + ;jp z, + cp 3Fh ; F5 + jp z,copy + cp 40h ; F6 + jp z,rename + cp 41h ; F7 + jp z,make_folder + cp 42h ; F8 + jp z,delete + cp 43h ; F9 + jp z,main_menu + cp 44h ; F10 + jr z,quit + ld a,(format_mode) ; формат акт. панели + and form_info+form_qview ; info, qview + ret nz + ld a,d + cp 50h ; Ins + jp z,mark + cp 4Fh ; Del + ;jp z, + ret + +quit: db 3Eh ; ld a,.. +confirm_quit: db true ; флаг "подтверждение выхода" + or a + jr z,quit__ + ; открыть окно "Quit" + ld hl,win_dial_quit ; описатель окна + call DialogW + cp evCommand ; событие "команда" + ret nz + ld a,(hl) ;+1 what + cp cmOkey ; "Yes" + ret nz +quit__: ld b,0 ; Ok возвр. код + pop hl ; восст. баланс стека + jp exit ; выход в ДОС + + + + + +;----------------------------------------------------------- +; обычные клавиши +;----------------------------------------------------------- +normal_char: ld a,e + cp 1Bh ; Esc временный просмотр экрана + jp z,view_screen + cp 9 ; Tab смена акт. панели + jp z,tab + cp 0Dh ; Enter + jp z,Press_Enter + cp " " + ret c + ; ввод символов в ком-строку + ld hl,(YXpos+1) ; начало поля ввода ком-строки + ld (CursorPos),hl ; полож. курсора на экране +ent_to_cline: call ComLineI ; вкл. курсор + jp EvComLine1 ; вход в ком-строку + +; войти в ком-строку (альт. вход) +alt_enter_to_comline: + ld hl,what ; список событий + ld (hl),evNothing ; не отраб. повторно + jr ent_to_cline + + + + + +;------------------------------------------------- +; Временный просмотр сист. экрана (Esc) +;------------------------------------------------- +view_screen: call test_show_panels ; тест на режим вкл. панелей + ret z ; выкл. + db 3Eh ; ld a,.. +flag_esc: db true ; флаг врем. просмотра экрана по Esc + or a + ret z + ; выкл. вывод часов + ld hl,enable_clock ; восст. флаг + ld a,(hl) + push af + ld (hl),false + ; сохр. полный экран менеджера + ld c,0B2h + ld a,(page_sys_screen) ; страница буфера + call screen2__ + ; восст. полный системный экран + ld c,0B3h + ld a,(page_sys_screen) ; страница буфера + call screen__ +view_scr_loop__: + ; ждем нажатия мышки + call get_mouse_info ; чтение состояния мышки + jr z,view_scr_loop1__ ; кнопки не нажаты + call get_fire ; ждем, пока нажаты кнопки + jr view_scr__ + ; +view_scr_loop1__: + ; ждем нажатия клавиши + ld a,2 + rst 20h + jr z,view_scr_loop__ + ld a,1 ; очистить буфер клавы + rst 20h +view_scr__: + ; восст. полный экран менеджера + ld c,0B3h + ld a,(page_sys_screen) ; страница буфера + call screen2__ + pop af + ld (enable_clock),a ; восст. флаг + ret + + + + + + + +; сравнить hl с de +cmphlde: ld a,l + sub e + ld a,h + sbc a,d + ret + +; загрузить de +L0020: ld e,(hl) + inc hl + ld d,(hl) + inc hl + ret + +; (hl) -> (ix) +; b-счетчик +A0E90: ld a,(hl) + ld (ix+0),a + inc hl + inc ix + djnz $-7 + ret + +; Копирование строки до нуля. Нуль копируется тоже. +; (hl) -> (de) +copy_string: ld a,(hl) + ldi + or a + jr nz,$-4 + ret + + +;------------------------------------------------- +; Сравнение строки с учетом регистра. +; (образец должен заканчиваться нулем) +; вход: de - string1 +; hl - string2 (образец) +; выход: "z" - string1 = string2 +; "c" - string1 < string2 +; иначе - string1 > string2 +;------------------------------------------------- +compare_strings:ld a,(de) + cp (hl) + ret nz + inc hl + inc de + ld a,(hl) + or a + jr nz,$-7 ; образец не закончен + ld a,(de) + cp (hl) + ret + + +;------------------------------------------------- +; Умножение BC*DE=HLBC +;------------------------------------------------- +mul_bcde: ld hl,0 + ld a,17 + rr b + rr c + dec a + ret z + jr nc,$+3 + add hl,de + rr h + rr l + jr $-13 + + +; Вывод HL в hex-формате +; ix=буфер +; hl=число +hex16: ld a,h + call hex8 + ld a,l +; Вывод "a" в hex-формате +; ix=буфер +; a=число +hex8: push af + rrca + rrca + rrca + rrca + call $+4 + pop af + and 0Fh + add a,90h + daa + adc a,40h + daa + ld (ix+0),a + inc ix + ret + + + +; Тест режима отображения панелей +; ------------------------------- +; out: Z - выкл. панели +; NZ - вкл. панели +test_show_panels: + db 3Eh ; ld a,.. +enable_panels: db true ; флаг отображения панелей + or a + ret + + + + + + +;----------------------------------- +; курсор влево +;----------------------------------- +left: call test_show_panels ; тест на режим вкл. панелей + ret z ; выкл. -> перемещение в ком-строке + ld a,(format_mode) ; формат акт. панели + cp form_info ; info + ret z + cp form_qview ; qview + ret z; + ;jp z, ; если файл, то навигация по нему + ld hl,(all_files) ; число файлов и папок + ld a,l + or h + ret z + call dinqview_set_flag ; уст. флаг "отработать dinamqview" + ld hl,(cur_pointer) ; тек. позиция указателя + ld a,l + or h + jr nz,A0CE6_ ; указатель не в начале списка + ld de,(offset_list) ; смещ. списка + adc hl,de ; adc нужен для уст."z" + jr nz,_0CEE ; список смещен + ret ; стоим в начале списка +A0CE6_: ld de,files_per_colon ; 25 файлов на колонку + sbc hl,de + jp nc,A0E12_ ; обновить полож. указателя + ; дошли до левого края списка +A0CE8: ld hl,0 ; указатель в начало писка + jp A0E12_ ; обновить полож. указателя + +;----------------------------------- +; на страницу вверх +;----------------------------------- +page_up: call test_show_panels ; тест на режим вкл. панелей + jr nz,$+8 + call history_begin ; в начало истории + jp alt_enter_to_comline ; фокус на ком-строку + ; + ld a,(format_mode) ; формат акт. панели + cp form_info ; info + ret z + cp form_qview ; qview + ret z; + ;jp z, ; если файл, то навигация по нему + ld hl,(all_files) ; число файлов и папок + ld a,l + or h + ret z + ld hl,(cur_pointer) + ld bc,(offset_list) ; смещ. списка + adc hl,bc ; "adc" нужен для "z" + ret z ; указатель в начале списка + call dinqview_set_flag ; уст. флаг "отработать dinamqview" + ld a,c + or b + jr z,A0CE8 ; указатель не в начале списка + ; список смещен + call clear_pointer + ld hl,0 ; сбр. полож. указателя + ld (cur_pointer),hl + ld hl,(offset_list) ; смещ. списка +_0CEE: ld de,files_per_colon ; 25/50/75 размер страницы + and a + sbc hl,de + jr nc,$+5 +A0CF0: ld hl,0 + ld (offset_list),hl + jp A0D78 ; обновить весь список панели + + +;----------------------------------- +; курсор вправо +;----------------------------------- +right: call test_show_panels ; тест на режим вкл. панелей + ret z ; выкл. -> перемещение в ком-строке + ld a,(format_mode) ; формат акт. панели + cp form_info ; info + ret z + cp form_qview ; qview + ret z; + ;jp z, ; если файл, то навигация по нему + ld hl,(all_files) ; число файлов и папок + ld a,l + or h + ret z + ld hl,(cur_pointer) ; тек. позиция указателя +_0D01: ld de,files_per_colon-1 ; размер страницы - 1 + call cmphlde ; сравнить hl с de + jr z,A0D1D ; указатель в конце списка панели + call dinqview_set_flag ; уст. флаг "отработать dinamqview" + ; + ld de,files_per_colon ; 25 файлов на колонку + add hl,de +_0D08: ld de,files_per_colon ; 25/50/75 размер страницы + call cmphlde ; сравнить hl с de + jr c,$+5 + ; дошли до правого края списка +_0D0D: ld hl,files_per_colon-1 ; размер страницы - 1 + inc hl + ld de,(all_files) ; файлов и папок + call cmphlde ; cp (hl) сравнить hl с de + dec hl + jp c,A0E12_ ; обновить полож. указателя + ex de,hl ; hl=all_files (файлов+папки) + dec hl + jp A0E12_ ; обновить полож. указателя + +;----------------------------------- +; на страницу вниз +;----------------------------------- +page_down: call test_show_panels ; тест на режим вкл. панелей + jr nz,$+8 + call history_last ; в конец истории + jp alt_enter_to_comline ; фокус на ком-строку + ; + ld a,(format_mode) ; формат акт. панели + cp form_info ; info + ret z + cp form_qview ; qview + ret z; + ;jp z, ; если файл, то навигация по нему + ld de,(all_files) ; число файлов и папок + ld a,e + or d + ret z + call dinqview_set_flag ; уст. флаг "отработать dinamqview" + ld hl,(_0D01+1) ; размер страницы - 1 + call cmphlde ; сравнить hl с de + jr c,A0D1D + ; число файлов меньше, чем + ; умещается в списке панели + ld hl,(cur_pointer) ; указатель на конец списка панели + dec de + call cmphlde ; сравнить hl с de + ret z ; указатель в конце списка + ex de,hl ; hl = all_files-1 + jp A0E12_ ; обновить полож. указателя + ; +A0D1D: ld c,l + ld b,h + ; тест на конец всего списка + ld hl,(cur_pointer) ; тек. позиция указателя + ld de,(offset_list) ; смещ. списка + inc hl + add hl,de + ld de,(all_files) + call cmphlde ; сравнить hl с de + ret z ; конец файлов +_0D1F: ld hl,files_per_colon ; 25/50/75 размер страницы + ld de,(offset_list) ; смещ. списка + add hl,de + ld de,(all_files) ; число файлов и папок + call cmphlde ; сравнить hl с de + ld l,c + ld h,b + jp z,A0E12_ ; указатель в пределах послед. страницы списка + push hl + call clear_pointer + pop hl + ld (cur_pointer),hl + ld bc,(all_files) ; число файлов и папок + ld hl,(offset_list) ; смещ. списка +_0D2C: ld de,files_per_colon ; 25/50/75 размер страницы + add hl,de + ld (offset_list),hl + dec de + add hl,de + and a + sbc hl,bc + jp c,A0F09 ; обновить весь список панели + ex de,hl + ld hl,(offset_list) ; смещ. списка + sbc hl,de + dec hl + ld (offset_list),hl + jp A0F09 ; обновить весь список панели + + +;----------------------------------- +; курсор вверх +;----------------------------------- +up: call test_show_panels ; тест на режим вкл. панелей + jr nz,$+8 +up1: call history_prev ; пред. строка истории + jp alt_enter_to_comline ; фокус на ком-строку + ld a,(format_mode) ; формат акт. панели + bit 3,a ; info + ret nz + bit 4,a ; qview + ret nz; + ;jp z, ; если файл, то навигация по нему + ld hl,(all_files) ; число файлов и папок + ld a,l + or h + ret z + ld hl,(cur_pointer) ; тек. позиция указателя + ld de,(offset_list) ; смещ. списка + adc hl,de ; adc нужен для "z" + ret z ; стоим в начале списка + call dinqview_set_flag ; уст. флаг "отработать dinamqview" + and a + sbc hl,de ; минус offset_list + jr nz,A0D94_ + ex de,hl ; hl=offset_list + dec hl + ld (offset_list),hl + ; цикл скроллинга всего списка панели +A0D78: ld hl,0 + call A0E15_ ; вывод указателя в новом полож. +A0D7A: ld hl,(cur_pointer) ; тек. позиция указателя + inc hl + ld (cur_pointer),hl +_0D7D: ld de,files_per_colon ; 25/50/75 размер страницы + call cmphlde ; сравнить hl с de + jr z,A0D80 + call A2203 ; вывод строки списка + jr A0D7A + ; +A0D80: ld hl,0 + ld (cur_pointer),hl ; новое полож. + ret + ; +A0D94_: ld hl,(cur_pointer) + dec hl ; --cur_pointer + jp A0E12_ ; обновить полож. указателя + + +;----------------------------------- +; курсор вниз +;----------------------------------- +down: call test_show_panels ; тест на режим вкл. панелей + jr nz,$+8 +down1: call history_next ; след. строка истории + jp alt_enter_to_comline ; фокус на ком-строку + ld a,(format_mode) ; формат акт. панели + bit 3,a ; info + ret nz + bit 4,a ; qview + ret nz; + ;jp nz, ; если файл, то навигация по нему + ld hl,(all_files) ; число файлов и папок + ld a,l + or h + ret z + call dinqview_set_flag ; уст. флаг "отработать dinamqview" + ld hl,(cur_pointer) ; тек. позиция указателя +_0EC7: ld de,files_per_colon-1 ; размер страницы - 1 + call cmphlde ; сравнить hl с de + jp nz,A0E0A ; сместить указатель вниз + ; дошли до конца списка панели + ld de,(offset_list) ; смещ. списка + inc hl + add hl,de + ld de,(all_files) + call cmphlde ; сравнить hl с de + ret z ; конец файлов + ld hl,(offset_list) ; смещ. списка + inc hl + ld (offset_list),hl +A0F09: ld hl,files_per_colon-1 ; размер страницы - 1 + call A0E15_ ; вывод указателя в новом полож. + ; цикл скроллинга всего списка панели +A0F0A: ld hl,(cur_pointer) ; тек. позиция указателя + dec hl + ld (cur_pointer),hl + inc hl + ld a,l + or h + jr z,A0F0C ; дошли до конца списка файлов + call A2203 ; вывод строки списка + jr A0F0A + ; +A0F0C: ld hl,(A0F09+1) + ld (cur_pointer),hl ; новое полож. + ret + + +; переместить указатель вниз +A0E0A: ld de,(all_files) + inc hl ; ++cur_pointer + call cmphlde ; сравнить hl с de + ret z ; конец файлов +A0E12_: push hl + call clear_pointer ; стереть указатель + pop hl +A0E15_: ld (cur_pointer),hl ; новое полож. + jp show_pointer ; вывести указатель + + +;----------------------------------- +; в начало списка +;----------------------------------- +home_list: call test_show_panels ; тест на режим вкл. панелей + ret z ; выкл. -> перемещение в ком-строке + ld a,(format_mode) ; формат акт. панели + cp form_info ; info + ret z + cp form_qview ; qview + ret z; + ;jp z, ; если файл, то навигация по нему + ld hl,(all_files) ; число файлов и папок + ld a,l + or h + ret z + ld hl,(cur_pointer) ; тек. полож. указателя + ld de,(offset_list) ; смещ. списка + xor a + adc hl,de ; adc нужен для "z" + ret z ; стоим в начале списка + ld l,a + ld h,a ; hl=0 + call dinqview_set_flag ; уст. флаг "отработать dinamqview" + call cmphlde ; список смещен ? + jr z,A0E12_ ; нет, обновить только полож. указателя + call clear_pointer + jp A0CF0 + + +;----------------------------------- +; в конец списка +;----------------------------------- +end_list: call test_show_panels ; тест на режим вкл. панелей + ret z ; выкл. -> перемещение в ком-строке + ld a,(format_mode) ; формат акт. панели + cp form_info ; info + ret z + cp form_qview ; qview + ret z; + ;jp z, ; если файл, то навигация по нему + ld hl,(all_files) ; число файлов и папок + ld a,l + or h + ret z + call dinqview_set_flag ; уст. флаг "отработать dinamqview" + ld c,l ; bc=all_files + ld b,h + ld hl,(cur_pointer) + ld de,(offset_list) ; смещ. списка + add hl,de + inc hl + ld a,l + sub c + ld a,h + sbc a,b + ret z ; указатель в конце списка + ld de,(_0D01+1) ; размер страницы - 1 + ld l,c ; hl=all_files + ld h,b + call cmphlde + jr nc,lst4__ + ; число файлов меньше списка панели +lst3__: dec hl + jp A0E12_ ; обновить полож. указателя + ; +lst4__: ld bc,-1 ; счетчик + dec hl ; --all_files + inc bc + call cmphlde ; hl и "размер страницы - 1" + jr nc,$-5 + ld hl,(offset_list) ; смещ. списка + and a + sbc hl,bc + jr c,lst6__ + ; указатель в пределах послед. страницы списка + ex de,hl + jr lst3__ + ; +lst6__: push bc + push de + call clear_pointer + pop de + pop bc + dec bc + ld (offset_list),bc + inc de + ld (cur_pointer),de + jp A0F09 ; обновить список панели + + + +;----------------------------------- +; Ins, отметка файлов +;----------------------------------- +mark: call test_show_panels ; тест на режим вкл. панелей + ret z ; выкл. + ld hl,(all_files) ; число файлов и папок + ld a,l + or h + ret z + call A0E13 ; ставит/снимает отметку файлов + ld hl,(cur_pointer) ; тек. позиция указателя +_0DA4: ld de,files_per_colon-1 ; размер страницы - 1 + call cmphlde ; сравнить hl с de + ex af,af' + db 3Eh ; ld a,.. +enable_down_mark: + db true ; флаг "смещать курсор при выделении" + or a + ret z + ex af,af' + jp nz,A0E0A ; переместить указатель вниз + ; нижняя строка страницы + ld de,(offset_list) ; смещ. списка + inc hl + add hl,de + ld de,(all_files) ; число файлов и папок + call cmphlde ; сравнить hl с de + jp z,show_pointer ; последний файл списка (список больше страницы) +A0DB7: ld hl,(offset_list) ; смещ. списка + inc hl + ld (offset_list),hl +A0DE9: ld hl,(cur_pointer) ; тек. позиция указателя + dec hl + ld a,l + or h + jr z,_0E04 + ld (cur_pointer),hl + call A2203 ; для смещ. списка вниз + jr A0DE9 + ; +_0E04: ld hl,files_per_colon-1 ; 25/50/75 размер страницы (после,"размер страницы - 1") + jp A0E15_ ; вывод указателя в новом полож. + + +; Ставит/снимает отметку файлов и выводит +; информ. строку выдел. файлов +A0E13: ; уст. режим клавы "вставка" + ld hl,D0642 ; флаги клавы + set 1,(hl) ; уст. 1-й бит (вставка) + ; + call get_record ; узнать адрес тек. записи в папке + ld a,(format_mode) ; тек. фомат панели + and form_trd ; spec + jp nz,mark_spec_record + ld a,(de) ;+11 смещ. до байта атрибутов + and 10h ; папка ? + jr z,A0E15 ; нет + ld a,(hl) + cp "." ; ".." + ret z + db 3Eh ; ld a,.. +mark_folders: db true ; флаг отметки папок + or a + ret z ; не отмечать +A0E15: inc de + ld bc,28 ; смещ. до размера файла + add hl,bc + ld a,(de) ; +12 ячейка маркировки файла + xor 80h ; инверт. флаг + ld (de),a + push hl + push af + call show_pointer ; вывод указателя + pop af + pop hl + call L0020 ; de <= low-размер файла + ld c,(hl) ; bc=ст. разряда размера + inc hl + ld b,(hl) +A0E49: ld hl,(low_size) ; мл. разряд размера выдел. файлов + rlca ; a=байт отметки + jr nc,A0E77 ; отметка снята, вычесть размер файла + add hl,de ; de=мл.разряд размера + ld (low_size),hl ; мл.разряд размера выдел. файлов + ld hl,(high_size) ; ст.разряд + adc hl,bc + ld (high_size),hl + ld hl,(mark_files) ; число выдел. файлов + inc hl ; увел. число выдел. файлов + ld (mark_files),hl +A0E63: ld hl,(__markline) ; описатель строки "xxx.. bytes in xx files" + inc hl + inc hl + inc hl + ld (A0E70_+1),hl ;+3 от начала описателя + inc hl + inc hl + push hl + pop ix ;+5 ix=mark_string+1 + ; вставить объем файлов + ld hl,put_comma ; уст. флаг вывода запятой + inc (hl) + exx + ld hl,(high_size) + exx + ld hl,(low_size) + ld b,0 ; без ведущих пробелов + call dec32 ; объем выдел. файлов + ld hl,put_comma ; флаг разделения разрядов + dec (hl) ; сбр. флаг + ; вставить строку " bytes in " + ld hl,mark_string1__ + ld b,10 ; длина строки + call A0E90 ; скопировать строку + ; вставить число выдел. файлов + ld hl,(mark_files) ; число выдел. файлов + ld e,l + ld d,h + call dec16 ; число без ведущ. пробелов + ; вставить строку " files" + ld b,5 ; длина строки " files" - 1 + and a + ld hl,1 + sbc hl,de ; de=число mark-файлов + jr nc,A0E6D_ + inc b +A0E6D_: ld hl,mark_string2__ + call A0E90 ; скопировать строку + push ix + pop hl + xor a + ld (hl)," " ; концевой пробел + inc hl + ld (hl),a ; конец описателя + dec hl + ; узнать длину строки +A0E70_: ld de,0 ;+3 сохр. mark_string-1 + sbc hl,de + ld c,l + ; центрировать строку + srl l ; длина строки / 2 + ld a,20 ; половина ширины панели + sub l + ld (de),a ; X полож. строки + ld hl,-3 + add hl,de ; hl=начало описателя + ld a,(hl) ; старая длина строки + ld (hl),c ; новая длина строки + inc c + cp c ; новая < старой ? + push hl + call nc,clear_footer_line ; да, очистить строку + pop hl + ; вывод готовой строки + jp draw_text ; позиц. вывод строки + ; +; вычесть размер файла +A0E77: sbc hl,de + ld (low_size),hl ; мл. разряд размера выдел. файлов + ld hl,(high_size) + sbc hl,bc + ld (high_size),hl ; ст. разряд + ld hl,(mark_files) ; число выдел. файлов + dec hl + ld (mark_files),hl + ld a,l + or h + jp nz,A0E63 +; 0 отмеченых файлов, стереть инф. строку +clear_footer_line: + ld hl,footer_med + ld a,(format_mode) ; формат панели + bit 1,a ; medium + jp nz,draw_text ; позиц. вывод строки + ld hl,footer_brief + bit 2,a ; brief + jp nz,draw_text + ld hl,footer_spec + bit 6,a ; spec + jp nz,draw_text + ld hl,footer_full ; full + jp draw_text + +; Ставит/снимает отметку спек-файлов +mark_spec_record: + ld a,(hl) ;+0 1-я буква имени + xor 80h + ld (hl),a + ld bc,11 ;+11 + add hl,bc ; перейти на размер файла + push hl + push af + call show_pointer ; вывод указателя + pop af + pop hl + call L0020 ; de=мл. разряд размера файла + ld bc,0 ; bc=ст. разряд размера файла + jp A0E49 + + + + + + + +;--------------------------------------------------------------------- +; Вывод всей информации в панели +;--------------------------------------------------------------------- +A20FC: ld a,(disk) ; номер диска + add a,"A" + ld hl,(char_disk) ; адрес буквы диска акт. панели + ld (hl),a + call width_path ; путь из path-буфера в буфер пути панели + call test_show_panels ; тест на режим вкл. панелей + ret z ; выкл. + call draw_half_frame ; боковые стороны и пред-нижняя линия рамки + call A208F ; настр. список панели + middle-линия + call A21AA ; вывод пути и суммарной инфы + ld a,(format_mode) ; формат панели + and form_info+form_qview + ret nz + ; + ld hl,(__title) ; заголовок панели + call draw_text ; A2551 позиц. вывод строки + call show_sort_letter ; вывод буквы сортировки + ld hl,(all_files) ; число файлов и папок + ld a,l + or h + ret z + ; вывод списка файлов + ld hl,(cur_pointer) ; сохр. тек. позицию указателя + push hl + ld hl,0 ; начать вывод с начала + ld (cur_pointer),hl + ; цикл вывода всего списка +A2151: call A2203 ; вывод строки списка + ld hl,(cur_pointer) ; тек. позиция указателя + inc hl + ld (cur_pointer),hl +_2159: ld de,files_per_colon ; 25/50/75 размер страницы + call cmphlde ; сравнить hl с de + jr z,A2164 + ld de,(all_files) + call cmphlde ; дошли до конца файлов ? + jr nz,A2151 ; нет +A2164: pop hl + ld (cur_pointer),hl ; восст. тек. позицию указателя + call print_status ; статусная строка внизу панели + ; вывод строки "xxx.. bytes in xx files" + ld hl,(mark_files) ; число выдел. файлов + ld a,l + or h + ret z + ld a,(format_mode) ; формат акт. панели + and form_info+form_qview + ret nz + ; full/med/brief/spec формат + ld hl,(__markline) ; строка "xxx.. bytes in xx files" + jp draw_text ; позиц. вывод строки + + + + + + +; Настроить список панели и вывести up и middle-строки +A208F: call A20E5 ; получить адрес описат. тек. формата (full/medium/brief/..) + ld (__title),de ; адрес описателя титла панели +A2097_: ld e,(hl) ; полож. верт. линии + inc hl + ld a,(hl) + or a + jr z,set_const ; конец, e="файлов на панель" + inc hl + push hl + ld d,a ; de=адрес middle-строки + ex de,hl + call draw_text ; вывод строки + pop hl + jr A2097_ + ; настроить константы списка панели +set_const: ld l,e ; 25/50/75 число файлов на панель + ld h,0 + ld (_2159+1),hl + ld (_0D7D+1),hl + ld (_0CEE+1),hl + ld (_0D08+1),hl + ld (_0D1F+1),hl + ld (_0D2C+1),hl + dec hl + ld (A0F09+1),hl + ld (_0EC7+1),hl + ld (_0D01+1),hl + ld (_0D0D+1),hl + ld (_0DA4+1),hl + ld (_0E04+1),hl ; было в 1-й половине + ret + + +; получить адрес описателя, согласно текущему +; формату (full/medium/brief + spec) +A20E5: ld a,(format_mode) ; тек. формат панели + ld e,a + ld hl,deskr_right ; описат. форматов вывода правой панели + ld a,(cur_panel) ; 0/#80 левая/правая панель + rlca + jr c,$+5 ; правая + ld hl,deskr_left ; описат. форматов вывода левой панели + call A15E5 ; получить описатель тек. формата (full/medium/brief) + ld e,(hl) ; de=адрес титла панели + inc hl + ld d,(hl) + inc hl + ret + + +; Получить адрес описателя тек. формата +; in: e=тек.формат (full/medium/brief + spec) +; hl=адрес описателя форматов панели +; out: hl=адрес описателя +A15E5: ld a,1 + bit 1,e ; medium + jr nz,A15E9__ + inc a + bit 2,e ; brief + jr nz,A15E9__ + inc a + bit 3,e ; info + jr nz,A15E9__ + inc a + bit 4,e ; qview + jr nz,A15E9__ + inc a ; индекс spec-описателя + bit 6,e ; trd + jr nz,A15E9__ + xor a ; индекс full-описателя +A15E9__: add a,a + add a,l + ld l,a + jr nc,$+3 + inc h + ld a,(hl) + inc hl + ld h,(hl) + ld l,a ; hl=адрес описателя + ret + + + + +;----------------------------------------------------------- +; Вывод пути вверху панели и строки суммарной информации +;----------------------------------------------------------- +A21AA: db 3Eh ; ld a,.. +A21AB: db false ; флаг работы обмена панелей + or a + ld a,0 + ld (A21AB),a ; сбр. флаг + jr nz,A21B0 ; работает обмен панелей + ld a,(format_mode) + bit 3,a ; info + jr z,A21AE + call set_info_actpanel + jr A21B0 + ; +A21AE: bit 4,a ; qview + jr z,A21B0 + call set_qview_actpanel + ret c ; был вывод содерж. файла + ; +A21B0: call print_up_path ; вывод пути + ret c ; info, qview форматы +; "╚══ размер_файлов_папки (число_файлов) ══ своб._объем_диска ══╝" +show_summary_info: + db 3Eh ; ld a,.. +flag_summary_info: + db false ; флаг вывода строки суммарной инфы + or a + ret z ; не выводить + ld hl,put_comma ; уст. флаг вывода запятой + inc (hl) + ld ix,summary_string+1 ; " 0,000,000,000 (0000) ═ ... " + ; общ. размер файлов списка + exx + ld hl,(files_size+2) ; ст.разряд + exx + ld hl,(files_size) ; мл.разряд + ld b,0 ; без ведущих пробелов + call dec32 ; объем выдел. файлов + ld hl,put_comma ; флаг разделения разрядов + dec (hl) ; сбр. флаг + ld (ix+0)," " + inc ix + ld (ix+0),"(" + inc ix + and a + ; число файлов в списке + ld hl,(all_files) ; число файлов и папок в списке + ld bc,(all_folders) ; число папок в списке + sbc hl,bc + call dec16 ; без ведущ. пробелов + ld hl,put_comma ; уст. флаг вывода запятой + inc (hl) + ld (ix+0),")" + inc ix + ld (ix+0)," " + inc ix + ld (ix+0),"═" + inc ix + ld (ix+0)," " + inc ix + ; своб. место на диске (уже вычислено) + exx + ld hl,(free_space_disk+2) ; ст.разряд + exx + ld hl,(free_space_disk) ; мл.разряд + ld b,0 ; без ведущих пробелов + call dec32 ; объем выдел. файлов + ld hl,put_comma ; флаг разделения разрядов + dec (hl) ; сбр. флаг + push ix + pop hl + xor a + ld (hl)," " ; концевой пробел + inc hl + ld (hl),a ; конец описателя + dec hl + ; узнать длину строки + ld de,summary_string-1 ; ячейка X-полож. + sbc hl,de + ld c,l + ; центрировать строку + srl l ; длина строки / 2 + ld a,20 ; половина ширины панели + sub l + ld (de),a ; X полож. строки + ld hl,deskr_summary ; описатель + ld a,(hl) ; старая длина строки + ld (hl),c ; новая длина строки + inc c + cp c ; новая < старой ? + call nc,clear_both_line ; да, очистить строку + ; вывод готовой строки + jp draw_text ; позиц. вывод строки + +clear_both_line:push hl + ld hl,botline ; описатель "╚═══════════════╝" + call draw_text ; позиц. вывод строки + pop hl + ret + + + +;----------------------------------------------------------- +; Вывод пути вверху акт. панели +; выход: CF - для info, qview форматов +;----------------------------------------------------------- +print_up_path: ld a,(format_mode) ; формат акт. панели + ld h,a + and form_info+form_qview ; info, qview форматы + jr nz,prn_up_path ; вывести титл + ld a,h + ; очистить строку пути + ld hl,up_med + bit 1,a ; medium + jr nz,upath_ + ld hl,up_brief + bit 2,a ; brief + jr nz,upath_ + ld hl,up_spec + bit 6,a ; spec + jr nz,upath_ + ld hl,up_full ; full +upath_: call draw_text ; позиц. вывод строки + ; вывод пути +prn_up_path: ld hl,format_mode ; формат акт. панели + ld a,(D48B1) ; флаг инверсии path-строки акт. панели + or a + ld a,(color_array+4) ; 30h цвет "Selected title" + jr nz,$+5 + ld a,(color_array+2) ; 1Bh цвет "Normal text" + bit 3,(hl) ; info + jr nz,upath2_ + bit 4,(hl) ; qview + jr nz,upath5_ + ; вывод пути + ld hl,(__path) ; адрес описателя пути акт. панели + inc hl + ld (hl),a ; цвет строки + dec hl + call draw_text ; позиц. вывод строки + xor a ; сбр. CF + ret + +; Вывод заполненного info-описателя +upath2_: ld (info_color1__),a ; цвет + ld hl,up_info ; описатель "╔══════════╗" + call draw_text + ld hl,title_info ; info-описатель + call draw_text + ld a,(format_mode) + and form_trd + ret z + ; вывод доп. описателя для спек-имиджа + ld hl,title_info_trd +upath4_: call draw_text + scf + ret + +; Вывод qview-описателя +upath5_: ld (qview_color1__),a ; цвет +; ld a,(type_title_qview) ; 0/1 флаг типа qview-описателя +; or a +; jr nz,upath7_ + call draw_half_frame ; очистить панель + ld hl,up_info ; описатель "╔══════════╗" + call draw_text + ; +upath6_: ld hl,qview_folder_panel ; описатель для папок + ld a,(type_title_qview) ; 0/1 флаг типа qview-описателя + or a + jr z,upath4_ + ld hl,title_qview ; вывести выдел. титл для файла + jr upath4_ + +;upath7_: ld hl,title_qview ; вывести выдел. титл для файла +; jr upath4_ + + + + + + + +; Вывести указатель +show_pointer: call test_show_panels ; тест на режим вкл. панелей + ret z + ld a,(format_mode) ; формат тек. панели + and form_info+form_qview + ret nz + ld hl,(all_files) ; число файлов и папок + ld a,l + or h + ret z + ld (pointer_flag),a ; уст. флаг вывода указателя + call A2203 ; вывод строки списка + xor a + ld (pointer_flag),a ; сбр. флаг + jp print_status1 ; статусная строка внизу панели + + +; Стереть указатель +clear_pointer: call test_show_panels ; тест на режим вкл. панелей + ret z + ld a,(format_mode) ; формат акт. панели + and form_info+form_qview + ret nz + ld hl,(all_files) ; число файлов и папок + ld a,l + or h + ret z + jp A2203 ; вывод строки списка + + + + +;===================================================================== +; Вывод 32-х битных чисел в буфер, в десятичном формате +;===================================================================== +; in: hl' = ст. разряд +; hl = мл. разряд +; ix = буфер +; c = 30h/20h - ведущ. символ +; b = 1/0 - вставлять/нет ведущий нуль/пробел +;--------------------------------------------------------------------- +; Флаг put_comma = true/false - вставлять/нет разделитель разрядов. +; +; Для формата с "M" - сбросить флаг put_comma и уст. режим "вставлять +; ведущие пробелы". Если флаг put_comma установлен, то более 7 знаков +; будет появляться только для значений от 1,000 M и выше. +;--------------------------------------------------------------------- +dec32: ld de,0CA00h + exx + ld de,3B9Ah ; 1.000.000.000 + exx + ld a,(put_mega) + or a + jr z,dec1_ + ld (ix+0)," " + inc ix +dec1_: ld iy,tmp1__ + res 7,(iy+0) + call GetLenN32 + call nz,print_comma + ld de,0E100h + exx + ld de,05F5h ; 100.000.000 + exx + call GetLenN32 + ld de,9680h + exx + ld de,98h ; 10.000.000 + exx + call GetLenN32 + call nz,mega_postfix ; "M" постфикс числа + ; + ld a,(put_mega) + or a + jr z,dec2_ + dec ix + dec ix + dec ix + dec ix +dec2_: ld de,4240h + exx + ld de,0Fh ; 1.000.000 + exx + call GetLenN32 + call nz,print_comma + ld de,86A0h + exx + ld de,1 ; 100.000 + exx + call GetLenN32 +dec5: ld de,10000 + exx + ld de,0 ; 10.000 + exx + call GetLenN32 +dec4: ld de,1000 ; 1.000 + call GetLenN16 + call nz,print_comma +dec3: ld de,100 ; 100 + call GetLenN16 +dec2: ld de,10 ; 10 + call GetLenN16 + ld a,l + add a,"0" + jr GetLenN163 + +tmp1__: db 0 + +GetLenN32: ld a,2Fh + and a +GetLenN321: inc a + sbc hl,de + exx + sbc hl,de + exx + jp nc,GetLenN321 + add hl,de + exx + adc hl,de + exx + jr GetLenN160 + ; +GetLenN16: ld a,2Fh + and a +GetLenN161: inc a + sbc hl,de + jp nc,GetLenN161 + add hl,de +GetLenN160: cp "0" + jr z,GetLenN162 + set 7,(iy+0) +GetLenN162: bit 7,(iy+0) + jr nz,GetLenN163 + dec b + inc b + ret z ; без ведущих пробелов/нулей + xor a ; уст. "Z" + ld a,c ; 20h/30h +GetLenN163: ld (ix+0),a ; сохр. в буфере + inc ix + ret + +; "M" постфикс числа +mega_postfix: db 3Eh ; ld a,.. +put_mega: db 0 ; false/true + or a + ret z + ld de,4240h + exx + ld de,0Fh ; 1.000.000 + exx + call GetLenN32 ; вывод мл. разряда + ld (ix+0)," " + inc ix + ld (ix+0),"M" + inc ix + pop de ; сместить стек + ret ; выйти из п/п dec32 + +print_comma: db 3Eh ; ld a,.. +put_comma: db 0 ; false/true + or a + ret z + ld (ix+0),"," + inc ix + ret + + +; Вывод чисел 0...65535 без ведущ. нуля +; in: hl=число +; ix=буфер +dec16: push de + xor a + exx + ld l,a ; ст. разряд + ld h,a + exx + ld b,a ; не вставлять ведущ. символ + ld iy,tmp1__ + res 7,(iy+0) + call dec5 + pop de + ret + + +; Вывод чисел 0...65535 с ведущим пробелом +; in: de=число +; ix=буфер +dec16s: push hl + xor a + exx + ld l,a ; ст. разряд + ld h,a + exx + ex de,hl + ld bc,0120h ; ведущие пробелы + ld iy,tmp1__ + res 7,(iy+0) + call dec5 + pop hl + ret + + +; Вывод чисел 0..999 с ведущ. пробелом +; in: a=число +; ix=буфер +dec9: push hl + ld l,a + ld h,0 + ld bc,0120h ; вставлять ведущ. нуль + ld iy,tmp1__ + res 7,(iy+0) + call dec3 + pop hl + ret + + +; Вывод чисел 0..99 с ведущ. нулем +; in: a=число +; ix=буфер +dec8: push de + ld l,a + ld h,0 + ld bc,0130h ; вставлять ведущ. нуль + ld iy,tmp1__ + res 7,(iy+0) + call dec2 + pop de + ret + + + + + + + + + +;----------------------------------------------------------- +; Получить адрес тек. записи списка акт. панели +; Не портить рег.BC!. +;----------------------------------------------------------- +; out: hl=начало записи +; de=ячейка атрибутов файла (+11) +; a=атрибут файла +get_record: ld hl,(cur_pointer) ; тек. позиция указателя + ld de,(offset_list) ; смещ. списка + add hl,de +get_record1: ld a,(cash_left_dir) ; банка списка акт. панели + out (SLOT3),a + ld de,(directory) ; начало списка адресов записей + add hl,hl ; 1+1=2 + add hl,de ; hl=начало записи + ld a,(hl) ; разадресация + inc hl + ld h,(hl) + ld l,a + ld a,(format_mode) + bit 6,a ; спек-формат панели ? + jr nz,get_spec_attrib ; да + ex de,hl + ld hl,11 ; смещ. ячейки атрибутов + add hl,de + ex de,hl + ld a,(de) ;+11 атрибут записи + ret + ; +spec_attrib: db 0 + ; +get_spec_attrib:ld de,spec_attrib ; ячейка атрибутов + ld a,(de) + ret + + + + + + + +; разделитель колонок +separator: db 3Eh ; ld a,.. +separ__: db "│" + ld (ix+0),a + inc ix + ret + + +; вставка пробелов +; in: b=счетчик +spaces: ld a," " + ld (ix+0),a + inc ix + djnz $-5 + ret + + + + + + + +;--------------------------------------------------------------------- +; Выводит строку списка файлов +;--------------------------------------------------------------------- +A2203: ld c,19 ; ширина medium-колонки + ld a,(format_mode) + ld e,a ; сохр. формат панели + bit 1,a ; medium + jr nz,A2217_ + ld c,13 + bit 2,a ; brief + jr nz,A2217_ + ; full,spec + ld c,39 ; ширина колонки +A2217_: ld a,c + dec a + ld (string_len),a ; длина строки + ld b,1 ; смещ. левой стороны колонки + ld a,(cur_pointer) ; тек. позиция указателя +A221C_: sub files_per_colon ; 25 файлов на колонку + jr c,A2229_ + ld d,a ; сохр. "a" + ld a,b + add a,c ; + ширина колонки + ld b,a ; X полож. + ld a,d ; восст. "a" + jr A221C_ + ; +A2229_: add a,files_per_colon+2 ; 27 файлов на колонку + 2 + ld (string_line),a ; Y полож. курсора + ld a,b ; колонка + ; коррект. длины указателя в medium-формате + bit 1,e ; medium ? + jr z,A2230_ + cp 20 ; правая половина левой панели ? + jr z,A222E_ ; да + cp 60 ; правая половина правой панели ? + jr nz,A2230_ ; нет +A222E_: ld hl,string_len + inc (hl) ; ++длина указателя + ; +A2230_: ld (string_colon),a ; X полож. курсора + ld b,e ; сохр. формат панели + call get_record ; адрес тек. записи в папке + ld (print_status2__),a ;+11 атрибут файла + ld (print_status1__),hl ; начало записи + bit 6,b ; spec-запись ? + jr z,A2235_ ; нет + ld e,l + ld d,h + dec de ; de=адр. 1-й буквы имени - 1 +A2235_: push bc + push de + call fill_string ; заполнить строку по формату + pop de + pop bc + call hilight_types ; вх: b=формат панели + ; c=индекс цвета + ;jp print_string +;----------------------------------------------------------- +; Вывод строки списка +;----------------------------------------------------------- +; вход: c = индекс цвета, pointer_flag = 00/01 - выводить текст/указатель +; +;print_string: + db 21h ; ld hl,.. +string_line: db 1 ; номер строки на экране (0..31) + db 0 + ld de,0301h ; с 0-й строки (для символов) + add hl,hl ; 1+1=2 + add hl,hl ; 2+2=4 + add hl,de + ld de,string_of_list ; адрес строки + in a,(89h) + ld (pnt3__+1),a ; сохр. порт + in a,(SLOT0) + ld (pnt4__+1),a ; сохр. порт + ld a,(panel_left+1) ; начало панели + ld b,a + di + ld a,50h ; видео-страница + out (SLOT0),a + db 3Eh ; ld a,.. +string_colon: db 0 ; номер колонки + add a,81h ; +0 (смещ. слева) + add a,b ; + начало панели + out (89h),a + ld (pnt1__+1),a + ; вывод текста + ld d,d ; уст. размер блока + db 3Eh ; ld a,.. +string_len: db 1 ; длина строки + ld b,b ; выкл. аксель + ld l,l ; копировать блок + ld a,(de) + ld b,b ; выкл. аксель + ld a,a ; копирование блока (верт. линии) + ld (hl),a + ld b,b ; выкл. аксель + inc hl ; перейти на атрибут + ; вывод атрибута + ld iy,color_array + ld a,(iy+0) ; цвет указателя + ld d,(iy+1) ; цвет выдел. указателя + ld b,0 + add iy,bc + ld b,a ; сохр. цвет норм. указателя + ld e,(iy+0) ; ячейка цвета по индексу + db 3Eh ; ld a,.. +pointer_flag: db 0 ; 0/1 цвет по индексу/указатель + or a + jr z,pnt__ ; не указатель + ld e,d ; цвет выдел. указателя + ld a,c + cp index_markfile ; 3 индекс ячейки "цвет выдел. файла" + jr z,pnt__ + ld e,b ; цвет норм. указателя + ; +pnt__: ld a,(string_len) ; длина строки + ld b,a +pnt1__: ld c,81h ; сохр. номер колонки +pnt2__: ld a,c + out (89h),a + ld (hl),e ; атрибут + inc c + djnz pnt2__ +pnt3__: ld a,0 + out (89h),a ; восст. порт +pnt4__: ld a,0 + out (SLOT0),a ; восст. порт + ei + ret + + +; буфер строки списка панели +string_of_list: db " " + ; ╔═══════════════╤═══════╤════════╤═════╗ + ;db Filenamm Ext 0005940│21.06.04│18:50 + + + + + + + + + + + + + + + + + + +;--------------------------------------------------------------------- +; Структура левой панели (27 байт) +;--------------------------------------------------------------------- +panel_left: db 0 ; Y полож. панели + db 0 ; X полож. панели +cur_panel: db 0 ; 00h признак левой панели +;  идет перекачка +disk: db 'A'-'A' ; номер тек. диска (0=A,1=B) +format_mode: db form_full ; full/med/brief/spec/info/qview +panel_size: db 40 ; ширина панели + db 27 ; высота панели - 3 +char_disk: dw disk_left ; буква диска +__buff: dw buff_left ; буфер пути (абс.путь) +__title: dw title_full ; описатель заголовка "Имя Объем Дата Время" +__markline: dw markline_left ; описатель строки "xxx.. bytes in xx files" +cash_left_dir: db -1 ; номер страницы каталога +directory: dw left_pointers ; массив указателей на папки + dw left_pointers ; массив указателей на файлы +all_folders: dw 0 ; число папок в списке +files_size: dw 0 ; мл. разряд общ. размера файлов + dw 0 ; ст. разряд +all_files: dw 321 ;21 число файлов + папок в тек. папке +__path: dw path_left ; описатель path-строки панели +__mask: dw mask_left_fname ; "*.*" маска имён файлов левой панели +free_space_disk:dw 0 ; мл. разряд своб. места на диске + dw 0 ; ст. разряд +total_space_disk: + dw 0 ; мл. разряд всего места на диске + dw 0 ; ст. разряд + ; +low_size: dw 0 ; мл. разряд размера выдел. файлов +high_size: dw 0 ; ст. разряд + ; +cur_pointer: dw 0 ; тек. позиция указателя в панели +offset_list: dw 0 ; смещение списка + ; +mark_files: dw 0 ; число выдел. файлов +sort_type: db "n" ; n/x/d/s/u тип сортировки списка + db 0 ; 00/01 / сортировка + ; +info_: db 0 ; триггер info-панели +form_under_info:db form_med ; сохр. формат под info-панели +D48B1: db true ; флаг инверсии path-строки + ; +qview_: db 0 ; триггер qview-панели +form_under_qview: + db form_med ; сохр. формат под qview-панели + +len_struct equ $ - panel_left ; размер структуры + + + +;--------------------------------------------------------------------- +; Структура правой панели +;--------------------------------------------------------------------- +panel_right: db 0 ; Y полож. панели + db 40 ; X полож. панели +cur_panel1: db 80h ; 80h признак правой панели +disk1: db 'D'-'A' ; номер тек. диска (0=A,1=B) +format_mode1: db form_full ; full/med/brief/spec/info/qview + db 40 ; ширина панели + db 27 ; высота панели - 3 + dw disk_right ; буква диска +__buff1: dw buff_right ; буфер пути + dw title_brief ; описатель заголовка "Имя Имя Имя" + dw markline_right ; описатель строки "xxx.. bytes in xx files" +cash_right_dir: db -1 ; номер страницы каталога +directory1: dw right_pointers ; массив указателей на папки + dw right_pointers ; массив указателей на файлы + dw 0 ; число папок в списке +files_size1: dw 0 ; мл. разряд общ. размера файлов папки + dw 0 ; ст. разряд +all_files1: dw 21 +__path1: dw path_right ; описатель пути пассивной панели +__mask1: dw mask_right_fname ; "*.*" маска имён файлов правой панели +free_space_disk1: + dw 0 ; мл. разряд своб. места на диске + dw 0 ; ст. разряд +total_space_disk1: + dw 0 ; мл. разряд всего места на диске + dw 0 ; ст. разряд + ; + dw 0 ; low_size мл. разряд выдел. файлов + dw 0 ; high_size ст. разряд +cur_pointer1: dw 0 +offset_list1: dw 0 + ; + dw 0 ; число выдел. файлов +sort_type1: db "x" ; n/x/d/s/u тип сортировки списка + db 0 ; 00/01 / сортировка + ; +info1_: db 0 ; триггер info-панели +form_under_info1: + db form_med ; сохр. формат под info-панели +D48B2: db false ; флаг инверсии path-строки +qview1_: db 0 ; триггер qview-панели +form_under_qview1: + db form_med ; сохр. формат под qview-панели + + + + + + + +index_markfile equ 3 ; смещ. цвета отмеч. файлов + +;----------------------------------------------------------- +; Массив цветов ФМ по-умолчанию (значения не изменяются) +; (ячейки местами не менять, исп. смещения к ячейкам!) +;----------------------------------------------------------- +default_colors: +; < Panel > +part1: db color_pointer ;+0 3Fh Normal cursor + db color_markpoint ;+1 3Eh Selected cursor + db color_panel ;+2 1Bh Normal text + db color_markfile ;+3 1Eh Selected text + db color_seltitle ;+4 30h Selected title + db color_title ;+5 1Eh Column title + db color_markline ;+6 3Eh Selected info + db color_highlighted_info ;+7 1Eh Highlighted info (info/qview панели) + db color_info_names ;+8 1Fh Info names (info/qview панели) + db 0 ;+9 резерв + db 0 ;+10 резерв + db 0 ;+11 резерв +col_lst1 equ $ - part1 +; < Horizontal Menu > +part2: db color_hmenu ;+12 30h Normal text + db color_hmenu_pointer ;+13 0Fh Highlighted text + db color_hmenu_hotkey ;+14 0Eh Hot-key +col_lst2 equ $ - part2 +; < Menu > +part3: db color_vmenu ;+15 3Fh Normal text + db color_vmenu_pointer ;+16 0Fh Highlighted text + db color_vmenu_hotkey ;+17 0Eh Hot-key + db 0 ;+18 резерв + db 0 ;+19 резерв +col_lst3 equ $ - part3 +; < Key Bar > (ячейки не разделять) +part4: db kb_f ;+20 30h пункты key-бара + db kb_b ;+21 0Eh hot-числа key-бара +col_lst4 equ $ - part4 +; < Command Line > +part5: db color_comline ;+22 07h командная строка + db 0 ;+23 резерв +col_lst5 equ $ - part5 +; < Dialog > +part6: db color_dial_win ;+24 70h Normal text + db color_dial_hotkey ;+25 0Eh Hot-keys + db color_sel_dial_title ;+26 30h Selected title (объекта) + db color_info_win ;+27 1Fh info-окна + db color_warn_win ;+28 4Fh warning/errors окна + db color_listbox ;+29 17h ListBox + db color_list_point ;+30 2Fh указатель ListBox-а + db color_list_hpoint ;+31 1Eh после указателя + db color_vscrl_bar ;+32 13h скролл-бар ListBox-а + db color_inputline ;+33 30h строка ввода + db color_selbuttons ;+34 30h Selected buttons + db color_selbuttons_err ;+35 70h Sel.buttons Warning/Errors + db 0 ;+36 резерв + db 0 ;+37 резерв + db 0 ;+38 резерв +col_lst6 equ $ - part6 +; < Viewer > +part7: db color_viewer ;+39 1Bh Normal text + db color_viewer_seltext ;+40 30h Selected text + db color_viewer_status ;+41 30h Status line + db color_viewer_scrl_arrow ;+42 1Eh Scrolling arrows +col_lst7 equ $ - part7 +; < Editor > +part8: db color_editor ;+43 1Bh Normal text + db color_edit_seltext ;+44 30h Selected text + db color_edit_status ;+45 30h Status line +col_lst8 equ $ - part8 +; < Help > +part9: db color_help ;+46 30h Normal text + db color_help_seltext ;+47 3Eh Highlighted text + db color_help_title ;+48 3Fh Title + db color_help_scrl_bar ;+49 30h Scrollbar + db 0 ;+50 резерв + db 0 ;+51 резерв +col_lst9 equ $ - part9 +; < Miscelions > +part10: db color_process_line ;+52 30h линейка процесса + db color_clock ;+53 30h часов в панелях + db 0 ;+54 резерв + db 0 ;+55 резерв + db 0 ;+56 резерв + db 0 ;+57 резерв + db 0 ;+58 резерв + db 0 ;+59 резерв +col_lst10 equ $ - part10 +; < Files Highlighting > + db color_folder ;+60 1Fh папки + db color_exe ;+61 1Ah exe-шники + db color_archive ;+62 1Dh архивы + db color_ro ;+63 17h файлы "r/o","system" + db color_hidden ;+64 13h скрытые файлы + db color_spec ;+65 1Ch спек-файлы (trd,scl) + +len_color_array equ $ - default_colors ; размер массива + +;------------------------------------------------- +; Рабочий массив цветов менеджера +;------------------------------------------------- +color_array: ds len_color_array + + + + + + + + +;------------------------------------------------- +; Установить полный формат акт. панели +;------------------------------------------------- +set_format_full:ld c,form_full ; full +set_format: call test_show_panels ; тест на режим вкл. панелей + ret z ; выкл. + ld hl,format_mode ; тек. формат акт. панели + ld a,(hl) + and form_trd ; выделить 6-й бит спек-формата + or c + cp (hl) ; новый = старому ? + ret z ; да + ld c,a + ld a,(format_mode1) ; формат пасс. панели + and form_info+form_qview ; info, qview + jr nz,set_form1 ; да + ld a,c + ld (form_under_info),a ; уст. формат панели под "Ctrl+L" + ld (form_under_qview),a ; уст. формат панели под "Ctrl+Q" + xor a + ld (info_),a ; сбр. триггер info-режима + ld (qview_),a ; сбр. триггер qview-режима +set_form1: ld (hl),c ; format_mode = новый формат + ld hl,0 + ld (cur_pointer),hl ; тек. полож. указателя + ld (offset_list),hl ; смещ. списка + call A20FC ; заново вывести список + jp enter_done1 ; тест на info/qview форматы др. панели + + +;------------------------------------------------- +; Установить средний формат акт. панели +;------------------------------------------------- +set_format_medium: + ld c,form_med + jr set_format + +;------------------------------------------------- +; Установить краткий формат акт. панели +;------------------------------------------------- +set_format_brief: + ld c,form_brief + jr set_format + + + + + + + + +;------------------------------------------------- +; Tab переход на другую панель +;------------------------------------------------- +tab: call test_show_panels ; тест на режим вкл. панелей + ret z ; выкл. + ld hl,D48B1 ; флаг инверсии + ld (hl),false ; сбр. инверсию path-строки + push hl + call clear_pointer ; убрать указатель + call prn_up_path ; вывод пути тек. панели без инверсии + call change_panel ; сменить акт. панель + pop hl + ld (hl),true ; инверсия path-строки + call prn_up_path ; вывод пути тек. панели с инверсией +tab1: call print_compath ; вывод пути в ком-строке + jp show_pointer ; вывести указатель + ;===== +; ld a,(format_mode) ; формат акт. панели +; and form_qview +; ret z ; не qview-формат +; ld a,(type_title_qview) ; флаг 00/01 - папка/файл +; or a +; ret z +; ; перейти в гляделку +; ld a,(page_viewer) ; стр. вьюера +; out (SLOT1),a +; ; настроить полож. дампа +; ld hl,panel_left ; полож. акт. панели +; ld d,(hl) ; Y полож. панели +; inc hl +; ld e,(hl) ; X полож. панели +; inc d +; inc e +; ld (coord),de ; полож. курсора +; ld (winpos),de ; полож. окна +; ; войти в гляделку +; ld iy,AAF04 +; ld hl,AB317 ; ascii-окно +; ld a,(cur_mode_dump) ; 0/1 флаг тек. окна (ascii/hex) +; or a +; jr z,$+5 +; ld hl,ABB1C ; hex-окно +; ld bc,f8__ ; точка выхода +; push bc +; jp (hl) + + +;f8__: ld a,(page_module1) +; out (SLOT1),a ; восст. стр. фм +; ret + + + + + +;------------------------------------------------- +; Ctrl+U обмен панелей +;------------------------------------------------- +swap_panels: call test_show_panels ; тест на режим вкл. панелей + ret z ; выкл. + ld (A21AB),a ; уст. флаг работы обмена панелей + in a,(SLOT3) + push af + ld hl,enable_clock ; флаг вывода часов + ld a,(hl) + push af + ld (hl),false ; выкл. вывод часов + call hidden_clock ; затереть часы + di + ; сохр. левую панель (до ком. строки) в буфер + ld ix,0C000h+1400h ; буфер за экраном менеджера + ld de,0000h ; Y/X полож. окна + ld hl,1E28h ; высота/ширина экрана + ld a,(page_sys_screen) ; стр. буфера + ld b,a + xor a ; идентиф. глоб. окна + ld c,0B2h ; экран в буфер + rst 08h + ; сохр. правую панель в буфер + ld ix,0C000h+1400h+0960h ; буфер + ld de,0028h ; Y/X полож. окна + ld hl,1E28h ; высота/ширина экрана + ld a,(page_sys_screen) ; стр. буфера + ld b,a + xor a ; идентиф. глоб. окна + ld c,0B2h ; экран в буфер + rst 08h + ; скопир. на левую правую панель + ld ix,0C000h+1400h+0960h ; буфер правой панели + ld de,0000h ; Y/X полож. окна + ld hl,1E28h ; высота/ширина экрана + ld a,(page_sys_screen) ; стр. буфера + ld b,a + xor a ; идентиф. глоб. окна + ld c,0B3h ; из буфера на экран + rst 08h + ; скопир. на правую левую панель + ld ix,0C000h+1400h ; буфер левой панели + ld de,0028h ; Y/X полож. окна + ld hl,1E28h ; высота/ширина экрана + ld a,(page_sys_screen) ; стр. буфера + ld b,a + xor a ; идентиф. глоб. окна + ld c,0B3h ; из буфера на экран + rst 08h + pop af + ld (enable_clock),a ; восст. флаг + ei + ; обменять X полож. панелей + ld hl,panel_left+1 + ld de,panel_right+1 + ld c,(hl) + ld a,(de) + ld (hl),a + ld a,c + ld (de),a + inc hl + inc de + ; обменять ячейки "cur_panel" + ld c,(hl) + ld a,(de) + ld (hl),a + ld a,c + ld (de),a + pop af + out (SLOT3),a + ret + + + +; смена активной панели (обмен служ. ячеек панелей) +change_panel: ld hl,panel_left ; обмен (hl) и (de) + ld de,panel_right + ld b,len_struct ; размер структуры панели + ld c,(hl) + ld a,(de) + ld (hl),a + ld a,c + ld (de),a + inc hl + inc de + djnz $-7 + call A20E5 ; получить адрес описат. тек. формата (full/medium/brief) + ld e,(hl) + inc hl + ld a,(hl) + inc hl + or a + jr nz,$-5 + jp set_const ; настроить константы + + + + + + +;-------------------------------------------------------------- +; Установить сист. диск и путь от акт. панели +; выход: CF - при ошибке (a=0FFh - нет диска, a=0 - нет пути) +;-------------------------------------------------------------- +set_path_from_activ_panel: + ; уст. диск от акт. панели + ld a,(disk) + ld c,1 + rst 10h + ld a,-1 + ret c + ; уст. путь от акт. панели + ld hl,(__buff) + ld c,1Dh + rst 10h + ret nc + ld a,0 + ret + +;------------------------------------------------- +; Установить диск и путь для акт. панели +;------------------------------------------------- +set_path_to_activ_panel: + ; уст. диск для акт. панели + ld c,2 + rst 10h + ret c + ld (disk),a + ; уст. путь для акт. панели + ld hl,(__buff) + ld c,1Eh + rst 10h + ret + + + + + + + +;------------------------------------------------- +; Вывод буквы режима сортировки +;------------------------------------------------- +show_sort_letter: + db 3Eh ; ld a,.. +sort_char_flag: db true ; флаг вывода буквы режима сортировки + or a + ret z + ld hl,(sort_type) + ld a,"" + add a,h + ld h,a ; / сортировка + ld (sort_char__),hl + ld hl,sort_char ; описатель буквы + jr draw_text ; позиц. вывод строки + + +;------------------------------------------------- +; Позиц. вывод текста (в акт. панели) +;------------------------------------------------- +; вход: hl=описатель строки +draw_text: ld a,(hl) + or a + ret z ; стоп-байт + ld (tdraw1__),a ; длина строки + ex af,af' + inc hl + ld a,(hl) + ld (tdraw3__+1),a ; цвет + inc hl + ld e,(hl) ; строка + inc hl + ld d,(hl) ; колонка + inc hl + ex de,hl ; hl=colon/line, de=адрес строки + call draw_txt_print + ex de,hl + jr draw_text + ; + ; h=номер колонки + ; a'=длина строки + ; de=адрес строки + ; настроить ячейки tdraw1__, tdraw3__+1 +draw_txt_print: ld bc,0301h ; с 0-й строки (для символов) + ld a,(panel_left+1) ; начало акт. панели + add a,h +draw_txt_print1:; + ld (tdraw__),a ; колонка + ld h,0 + add hl,hl ; 1+1=2 + add hl,hl ; 2+2=4 + add hl,bc + in a,(89h) + ld (tdraw4__+1),a ; сохр. порт + in a,(SLOT0) + ld (tdraw5__+1),a ; сохр. порт + di + ld a,50h ; видео-страница + out (SLOT0),a + db 3Eh ; ld a,.. +tdraw__: db 0 ; колонка (0..79) + add a,81h ; +0 (смещ. слева) + out (89h),a + ld c,a + ; вывод текста + ld d,d ; уст. размер блока + db 3Eh ; ld a,.. +tdraw1__: db 1 ; длина строки + ld b,b ; выкл. аксель + ld l,l ; копировать блок + ld a,(de) + ld b,b ; выкл. аксель + ld a,a ; копирование блока (верт. линии) + ld (hl),a + ld b,b ; выкл. аксель + inc hl ; перейти на атрибут + ; вывод атрибута + ex af,af' + ld b,a ; длина строки + ld a,c +tdraw2__: out (89h),a +tdraw3__: ld (hl),0 ; атрибут + inc a + inc de + djnz tdraw2__ +tdraw4__: ld a,0 + out (89h),a ; восст. порт +tdraw5__: ld a,0 + out (SLOT0),a ; восст. порт + ei + ret + + + + +;----------------------------------------------------------- +; Вывод боковых сторон и пред-нижней линии рамки панели +; (с очисткой места) +;----------------------------------------------------------- +draw_half_frame:ld hl,0301h+4 ; с 1-й строки + ld a,(panel_size+1) + ld b,a ; 27 число строк + jr $+7 +draw_half_frame1: + ld hl,0301h+(4*2) ; со 2-й строки + ld b,26 ; число строк + in a,(89h) + ld (fdraw3__+1),a ; сохр. порт + in a,(SLOT0) + ld (fdraw4__+1),a ; сохр. порт + ld a,(color_array+2) ; 1Bh color_panel + ld (fdraw1__+1),a ; атрибут + ld a,(panel_left+1) ; колонка (начало панели) + add a,81h ; +0 (смещ. слева) + ld c,a + ld a,(format_mode) ; формат панели + ; вывод средней части + ld de,midline2 ; линия "║ │ ║" medium + bit 1,a ; medium + jr nz,fdraw__ + ld de,midline3 ; линия "║ │ │ ║" brief + bit 2,a ; brief + jr nz,fdraw__ + ld de,midline4 ; линия "║ ║"" + bit 3,a ; info + jr nz,fdraw__ + bit 4,a ; qview + jr nz,fdraw__ + ld de,midline1 ; линия "║ │ │ │ ║" full + bit 6,a ; spec + jr z,fdraw__ + ld de,midline_spec ; линия "║ │ │ │ │ │ ║" full-spec +fdraw__: di + ld a,50h ; видео-страница + out (SLOT0),a +fdraw2__: call fdraw_axel + djnz fdraw2__ + ; вывод пред-нижней линии + ld de,midline4 ; линия "║ ║"" + call fdraw_axel +fdraw3__: ld a,0 + out (89h),a ; восст. порт +fdraw4__: ld a,0 + out (SLOT0),a ; восст. порт + ei + ret + +fdraw_axel: ld a,c + out (89h),a + ld d,d ; уст. размер блока + ld a,40 ; длина строки + ld b,b ; выкл. аксель + ld l,l ; копировать блок + ld a,(de) + ld b,b ; выкл. аксель + ld a,a ; копирование блока (верт. линии) + ld (hl),a + ld b,b ; выкл. аксель + inc l ; перейти на атрибут + ; вывод атрибута + push bc + ld b,40 ; длина строки + ld a,c +fdraw0__: out (89h),a +fdraw1__: ld (hl),color_panel ; 1Bh атрибут + inc a + djnz fdraw0__ + pop bc + inc l + inc l + inc l + ret diff --git a/SPEC/FUNCS.ASM b/SPEC/FUNCS.ASM new file mode 100755 index 0000000..b4c833e --- /dev/null +++ b/SPEC/FUNCS.ASM @@ -0,0 +1,159 @@ +;===================================================================== +; Разбор номеров спек-функций +; вход: c=номер функции +; выход: a=номер банки процедуры (структуры) менеджера +; hl=адрес процедуры менеджера +; CF - при ошибке (неверный номер функции) +;===================================================================== +spec_funcs: + push hl + ld l,c ; номер команды + ld h,SPEC_FUNC / 256 ; 256 мл. байт адресов + ld c,(hl) + inc h ; 256 ст. байт адресов + ld h,(hl) + ld l,c ; готовый адрес + ex (sp),hl ; в стек и + ret ; перейти на него + + +; заглушка +empty__:scf ; неверный номер функции + ret + + + ds 100h - $ ; выровнить на границу 0100h + +; Таблица адресов функций +; мл. байты адресов +SPEC_FUNC: + db empty__%256, empty__%256, empty__%256, empty__%256 ; 00..03 + db empty__%256, empty__%256, empty__%256, empty__%256 ; 04..07 + db empty__%256, empty__%256, empty__%256, empty__%256 ; 08..0B + db empty__%256, empty__%256, empty__%256, empty__%256 ; 0C..0F + db empty__%256, empty__%256, empty__%256, empty__%256 ; 10..13 + db empty__%256, empty__%256, empty__%256, empty__%256 ; 14..17 + db empty__%256, empty__%256, empty__%256, empty__%256 ; 18..1B + db empty__%256, empty__%256, empty__%256, empty__%256 ; 1C..1F + db empty__%256, empty__%256, empty__%256, empty__%256 ; 20..23 + db empty__%256, empty__%256, empty__%256, empty__%256 ; 24..27 + db empty__%256, empty__%256, empty__%256, empty__%256 ; 28..2B + db empty__%256, empty__%256, empty__%256, empty__%256 ; 2C..2F + db empty__%256, empty__%256, empty__%256, empty__%256 ; 30..33 + db empty__%256, empty__%256, empty__%256, empty__%256 ; 34..37 + db empty__%256, empty__%256, empty__%256, empty__%256 ; 38..3B + db empty__%256, empty__%256, empty__%256, empty__%256 ; 3C..3F + db empty__%256, empty__%256, empty__%256, empty__%256 ; 40..43 + db empty__%256, empty__%256, empty__%256, empty__%256 ; 44..47 + db empty__%256, empty__%256, empty__%256, empty__%256 ; 48..4B + db empty__%256, empty__%256, empty__%256, empty__%256 ; 4C..4F + db empty__%256, empty__%256, empty__%256, empty__%256 ; 50..53 + db empty__%256, empty__%256, empty__%256, empty__%256 ; 54..57 + db empty__%256, empty__%256, empty__%256, empty__%256 ; 58..5B + db empty__%256, empty__%256, empty__%256, empty__%256 ; 5C..5F + db empty__%256, empty__%256, empty__%256, empty__%256 ; 60..63 + db empty__%256, empty__%256, empty__%256, empty__%256 ; 64..67 + db empty__%256, empty__%256, empty__%256, empty__%256 ; 68..6B + db empty__%256, empty__%256, empty__%256, empty__%256 ; 6C..6F + db empty__%256, empty__%256, empty__%256, empty__%256 ; 70..73 + db empty__%256, empty__%256, empty__%256, empty__%256 ; 74..77 + db empty__%256, empty__%256, empty__%256, empty__%256 ; 78..7B + db empty__%256, empty__%256, empty__%256, empty__%256 ; 7C..7F + db empty__%256, empty__%256, empty__%256, empty__%256 ; 80..83 + db empty__%256, empty__%256, empty__%256, empty__%256 ; 84..87 + db empty__%256, empty__%256, empty__%256, empty__%256 ; 88..8B + db empty__%256, empty__%256, empty__%256, empty__%256 ; 8C..8F + db empty__%256, empty__%256, empty__%256, empty__%256 ; 90..93 + db empty__%256, empty__%256, empty__%256, empty__%256 ; 94..97 + db empty__%256, empty__%256, empty__%256, empty__%256 ; 98..9B + db empty__%256, empty__%256, empty__%256, empty__%256 ; 9C..9F + db empty__%256, empty__%256, empty__%256, empty__%256 ; A0..A3 + db empty__%256, empty__%256, empty__%256, empty__%256 ; A4..A7 + db empty__%256, empty__%256, empty__%256, empty__%256 ; A8..AB + db empty__%256, empty__%256, empty__%256, empty__%256 ; AC..AF + db empty__%256, empty__%256, empty__%256, empty__%256 ; B0..B3 + db empty__%256, empty__%256, empty__%256, empty__%256 ; B4..B7 + db empty__%256, empty__%256, empty__%256, empty__%256 ; B8..BB + db empty__%256, empty__%256, empty__%256, empty__%256 ; BC..BF + db empty__%256, empty__%256, empty__%256, empty__%256 ; C0..C3 + db empty__%256, empty__%256, empty__%256, empty__%256 ; C4..C7 + db empty__%256, empty__%256, empty__%256, empty__%256 ; C8..CB + db empty__%256, empty__%256, empty__%256, empty__%256 ; CC..CF + db empty__%256, empty__%256, empty__%256, empty__%256 ; D0..D3 + db empty__%256, empty__%256, empty__%256, empty__%256 ; D4..D7 + db empty__%256, empty__%256, empty__%256, empty__%256 ; D8..DB + db empty__%256, empty__%256, empty__%256, empty__%256 ; DC..DF + db empty__%256, empty__%256, empty__%256, empty__%256 ; E0..E3 + db empty__%256, empty__%256, empty__%256, empty__%256 ; E4..E7 + db empty__%256, empty__%256, empty__%256, empty__%256 ; E8..EB + db empty__%256, empty__%256, empty__%256, empty__%256 ; EC..EF + db empty__%256, empty__%256, empty__%256, empty__%256 ; F0..F3 + db empty__%256, empty__%256, empty__%256, empty__%256 ; F4..F7 + db empty__%256, empty__%256, empty__%256, empty__%256 ; F8..FB + db empty__%256, empty__%256, empty__%256, empty__%256 ; FC..FF + ; +;0300h ст. байты адресов + db empty__/256, empty__/256, empty__/256, empty__/256 ; 00..03 + db empty__/256, empty__/256, empty__/256, empty__/256 ; 04..07 + db empty__/256, empty__/256, empty__/256, empty__/256 ; 08..0B + db empty__/256, empty__/256, empty__/256, empty__/256 ; 0C..0F + db empty__/256, empty__/256, empty__/256, empty__/256 ; 10..13 + db empty__/256, empty__/256, empty__/256, empty__/256 ; 14..17 + db empty__/256, empty__/256, empty__/256, empty__/256 ; 18..1B + db empty__/256, empty__/256, empty__/256, empty__/256 ; 1C..1F + db empty__/256, empty__/256, empty__/256, empty__/256 ; 20..23 + db empty__/256, empty__/256, empty__/256, empty__/256 ; 24..27 + db empty__/256, empty__/256, empty__/256, empty__/256 ; 28..2B + db empty__/256, empty__/256, empty__/256, empty__/256 ; 2C..2F + db empty__/256, empty__/256, empty__/256, empty__/256 ; 30..33 + db empty__/256, empty__/256, empty__/256, empty__/256 ; 34..37 + db empty__/256, empty__/256, empty__/256, empty__/256 ; 38..3B + db empty__/256, empty__/256, empty__/256, empty__/256 ; 3C..3F + db empty__/256, empty__/256, empty__/256, empty__/256 ; 40..43 + db empty__/256, empty__/256, empty__/256, empty__/256 ; 44..47 + db empty__/256, empty__/256, empty__/256, empty__/256 ; 48..4B + db empty__/256, empty__/256, empty__/256, empty__/256 ; 4C..4F + db empty__/256, empty__/256, empty__/256, empty__/256 ; 50..53 + db empty__/256, empty__/256, empty__/256, empty__/256 ; 54..57 + db empty__/256, empty__/256, empty__/256, empty__/256 ; 58..5B + db empty__/256, empty__/256, empty__/256, empty__/256 ; 5C..5F + db empty__/256, empty__/256, empty__/256, empty__/256 ; 60..63 + db empty__/256, empty__/256, empty__/256, empty__/256 ; 64..67 + db empty__/256, empty__/256, empty__/256, empty__/256 ; 68..6B + db empty__/256, empty__/256, empty__/256, empty__/256 ; 6C..6F + db empty__/256, empty__/256, empty__/256, empty__/256 ; 70..73 + db empty__/256, empty__/256, empty__/256, empty__/256 ; 74..77 + db empty__/256, empty__/256, empty__/256, empty__/256 ; 78..7B + db empty__/256, empty__/256, empty__/256, empty__/256 ; 7C..7F + db empty__/256, empty__/256, empty__/256, empty__/256 ; 80..83 + db empty__/256, empty__/256, empty__/256, empty__/256 ; 84..87 + db empty__/256, empty__/256, empty__/256, empty__/256 ; 88..8B + db empty__/256, empty__/256, empty__/256, empty__/256 ; 8C..8F + db empty__/256, empty__/256, empty__/256, empty__/256 ; 90..93 + db empty__/256, empty__/256, empty__/256, empty__/256 ; 94..97 + db empty__/256, empty__/256, empty__/256, empty__/256 ; 98..9B + db empty__/256, empty__/256, empty__/256, empty__/256 ; 9C..9F + db empty__/256, empty__/256, empty__/256, empty__/256 ; A0..A3 + db empty__/256, empty__/256, empty__/256, empty__/256 ; A4..A7 + db empty__/256, empty__/256, empty__/256, empty__/256 ; A8..AB + db empty__/256, empty__/256, empty__/256, empty__/256 ; AC..AF + db empty__/256, empty__/256, empty__/256, empty__/256 ; B0..B3 + db empty__/256, empty__/256, empty__/256, empty__/256 ; B4..B7 + db empty__/256, empty__/256, empty__/256, empty__/256 ; B8..BB + db empty__/256, empty__/256, empty__/256, empty__/256 ; BC..BF + db empty__/256, empty__/256, empty__/256, empty__/256 ; C0..C3 + db empty__/256, empty__/256, empty__/256, empty__/256 ; C4..C7 + db empty__/256, empty__/256, empty__/256, empty__/256 ; C8..CB + db empty__/256, empty__/256, empty__/256, empty__/256 ; CC..CF + db empty__/256, empty__/256, empty__/256, empty__/256 ; D0..D3 + db empty__/256, empty__/256, empty__/256, empty__/256 ; D4..D7 + db empty__/256, empty__/256, empty__/256, empty__/256 ; D8..DB + db empty__/256, empty__/256, empty__/256, empty__/256 ; DC..DF + db empty__/256, empty__/256, empty__/256, empty__/256 ; E0..E3 + db empty__/256, empty__/256, empty__/256, empty__/256 ; E4..E7 + db empty__/256, empty__/256, empty__/256, empty__/256 ; E8..EB + db empty__/256, empty__/256, empty__/256, empty__/256 ; EC..EF + db empty__/256, empty__/256, empty__/256, empty__/256 ; F0..F3 + db empty__/256, empty__/256, empty__/256, empty__/256 ; F4..F7 + db empty__/256, empty__/256, empty__/256, empty__/256 ; F8..FB + db empty__/256, empty__/256, empty__/256, empty__/256 ; FC..FF diff --git a/SPEC/VECT.ASM b/SPEC/VECT.ASM new file mode 100755 index 0000000..cc46bcf --- /dev/null +++ b/SPEC/VECT.ASM @@ -0,0 +1,111 @@ + ; rst 00h + jp $+3 + db -1 + db -1 + db -1 + db -1 + db -1 + ; RST 08h. BIOS calls + push af + ld a,0 ; вкл. ПЗУ Биоса в 0-е окно + out (7Ch),a + pop af + ret + db 0C9h + ; RST 10h. DOS calls + jp alt10 ; fm.asm + db -1 + db -1 + db -1 + db -1 + db -1 + ; RST 18h + jp alt18 ; fm.asm + db -1 + db -1 + db -1 + db -1 + db -1 + ; rst 20h + jp $+3 + db -1 + db -1 + db -1 + db -1 + db -1 + ; rst 28h +rst28: push af + ld a,0 ; сохр. page_module0 + out (82h),a + pop af + jr spec_interrupt + ; rst 30h + jp $+3 + db -1 + db -1 + db -1 + db -1 + db -1 + ; + ; RST 38h. Main Interrupt + jp $+3 + di + push iy + push ix + push hl + push de + push bc + push af + ex af,af' + exx + push hl + push de + push bc + push af + ;call show_clock ; отображение часов + ;di + ds 4; + pop af + pop bc + pop de + pop hl + exx + ex af,af' + pop af + pop bc + pop de + pop hl + pop ix + pop iy + ei + reti + + db -1,-1,-1,-1,-1 ; на границу 0064h + +;0064h + retn + db 0 ; 0066h (от немаск. прерывания в IM0) + db 0 + db 0 + jp $-5 + +;================ Конец блока Векторов рестартов ===================== + + + + +;------------------------------------------------- +; Вызов обработчика #28 рестарта. +; Использовать свой стек. +;------------------------------------------------- +spec_interrupt: + ld (spc_stk+1),sp + ld sp,spec_stack + call spec_funcs ; отработка функции +spc_stk:ld sp,0 + jp rst28 ; вкл. 0-ю стр. фм + + + + ds 64 +spec_stack: ; стек банки diff --git a/Shared_Includes b/Shared_Includes new file mode 160000 index 0000000..a9f5915 --- /dev/null +++ b/Shared_Includes @@ -0,0 +1 @@ +Subproject commit a9f5915a3275f5ffbafa0994bb97c5846aab826c diff --git a/VERSION.INC b/VERSION.INC new file mode 100755 index 0000000..1c2128f --- /dev/null +++ b/VERSION.INC @@ -0,0 +1,3 @@ +; Версия менеджера +major_version equ 0 ; ст. цифра +minor_version equ 8 ; мл. цифра diff --git a/fix.! b/fix.! new file mode 100755 index 0000000..3fc6c8f --- /dev/null +++ b/fix.! @@ -0,0 +1 @@ +При смене диска не обновляется своб. место диска в суммарной строке. diff --git a/readme.txt b/readme.txt new file mode 100755 index 0000000..1856d7e --- /dev/null +++ b/readme.txt @@ -0,0 +1,13 @@ +Для компиляции FM.EXE запустить батник "make.bat". +При необходимости, в батниках (load.bat, make.bat) поправить +путь к "asmplus.exe". + + +Сорцы поправлены для сборки в ASMPlus. + + +- Убран (закомментарен) весь код, относящийся к выводу содержимого файла + в панель (Ctrl+Q). +- Прикручена вставка путей левой и правой панелей соотв. по Ctrl+[, Ctrl+]. +- Прикручено простое и групповое удаление файлов/папок. +- Прикручено переименование файла/папки. diff --git a/screens/screen01.gif b/screens/screen01.gif new file mode 100755 index 0000000000000000000000000000000000000000..f2ffb04de419b4e0d500d29ee013a750cf8e4cbc GIT binary patch literal 18172 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

lcjsFX1OI9D){!cJM7 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 W?&Vz$J# literal 0 HcmV?d00001 diff --git a/screens/screen04.gif b/screens/screen04.gif new file mode 100755 index 0000000000000000000000000000000000000000..caa22396953fc45328ee40b1e9623a7719e9e4e2 GIT binary patch literal 21890 zcmY(q1xy|7^9FjLNO6ig#ogVZxVyW%yIYG(ad&rjin|tf=O737qUW~X?|*Z1-)!DI zJ3BLZ=9$@Sve}iCmf+?w4uUj-d;$QVAfcc>prAs&Lw&qKL4JSxfU2&ne*1WPgM9l6 zfC2!P0RT@xx)%W0gvq}E@bp9|1_OX#02&wo00YQeA@Q03atr@_cAFu9O#rlixET`l z5CA{}{9E41D4&6V5Hx__f2V&pi2r~FU}r0$kt#fbjpB0h`r; zLkIvG*1rH86u>0_@DuPaj}xFA8gP^VK>LfqfCDf91P1&B1N`jM0nk7|0zamoCjfIA z2fhjr(h2a}{2MI=07PH{-2Nh?F_cfh|0DM^9e@c0;PU^YA8`*b1p+YtN4g;$5Df$@ zK>W1_03ZR^0Khw-FAxB@zXt&Sk0_Wm1su@_URVHodV-rzz`!Fg+CNbMU>rdBC1Bwv z!1F(*0B8Up;UDX2FaQFKiS0I+{O z{)h7c07L*l>2LDCWuO8~|7nQ%7u)@3`QJv}4>)B1Kh4?y_U-6jjeP(>b|~P97J&9& zA{@Zy|1_-n|1K;~bByvx3kV7U`27u_4gwrqVE(U317H9x7!dMT za&QFTAD@40{w^G52*C0GiQ8iU5L^L-$o?%|6O8%@J`Mt-`GEl#^u9;O*Jx-8f88UV z#7qT`G5;G5vCSUfiy)f9KcdU^z4&Oya*F?&u@ATcLV(f!5e(d;t_L0+qy5L>)8A|V znUrNY&@}hkiz<)f=lX7z~FbmC2TBC>)N)VYAu9xhWWp|0)_q zAl+CzohL<$_YoU>`o)@C!0{wW$wbn$d)umG!!j_9{; zw7XLNkjS}~?rc90#XE!<*STK9TsT= z2k96*nEr%djm$}hNnE4&CQdo7>?qF4bC~6Xrd=40`=fo$Pkr69P~7?P)H2F^|Icy$ zcZ+n?IOGehqjWt;Z>xfz^C?I6wz+A!#ts&q7NW*@98}4}<7s-9nls*1sn5Y3)>0v8 ztEZKfrQmx|QG<16MNxDJJDpxqV`M^|^fvsNXcyWwd4>0UWQJHts`-ACn?|!z!yv1U zZS9g^WuiOtwpWeeCr+Ev+ExjPiVz7_E9;ORxU7q2ApBx(N`Bl#^{=uhDaYpdkr&49 z;BE1Xu21N;nepNK6D94dK5F&q)|ZqwLp{ppm%ZB_!x=d&8Saj{79^e&qjS&E&Laq; z(KmyL(qlGp+d$}|LYP^sZ4<78>MYX^o@HfQ`avB#4KeKZrdBH3ESGs)wyk?B2}iev zg#$c{hb1Wpxt5mN$~VW~gCVh)%h>Yr55LXIkTBAGayjXyyjl=wj!ZAS5j0mmCYv7B;O$=Mb zK29|C5YuBkm5m!2t}*oxTUY}5O;XWotCk2)V?(UR;Q@;7swB~jaJ+v5}MKj2~RcV$9)TDwKQt~#6aaLuO1mx#KNVbXz zd6kCbd07%#0qO~v?Zm(`C<-Q9o(V%nr0@>JNc_q43G>W^q&`0jLUrv)>yN}xezPOy zoaYHCj|7goZqw)7@?m?6yNs3YZJtSKd50)havSnv^epcghsN8ia=5au@@wEB(bk2Z z!jYCjU>vz12e`BYf^u|oI9XEzgzOhzOO{cuF#{rubod%_Q3@NhV3p+5$a86^hYC5~ z7uTZKZYs_MX{G3wp&}os3K8*jnFyPoMXpfga`>4FY1!AsorpB@EHBDFw{8g>9I;By z>%UUb7SgQ6PKYE=7sd85m{b^!R6RRo7>QgfXyi{cV%OCfYm?IukSay$K=suxtfgix z6e>5kV--3sNw!0DyuRy+Uv<>7iifNe@-kIhm+h?2Oe+n*GLnPK=hdMtHl~A7l5NWz zMFH;gWr;F80Ey6$#+g%&Y0ds|Vu%sH@6V&g)Ay}fdm zZf9+)TaA1U$VgUacP6#1pn*Y15?gQUn?%Prd+l{L9nMMAgWH(AgGZID-UNqd7dHRV zRgbUUPF!2}!o}rUpKt$trl<4yyOH-Wg5hmvTFkwpsF3z$>)Au z2lX`9YMM*LRpEd~>^#gzC3cj|VPRhO{Qh$;@igx#GLO2LV}d>6@VGf7UDi?*f)ixT zSmV#KcV$gvM+&d267;4x*%WU_1HtV*+7@^}Hr^^ZOsiBYKCq&v5iQksdC<(Vow|6_5v(6#QfUF8OeICQv^=?BJsdjU^Q`l(FO(+pA z*Mn}WZ&Y{-<+cyCY16hEu)G0JrS5HYTNb9Tx?7MC?Ps;!BCbrjyO39U!Cme)vPCZr zqL(*meHg$`VBB$-Rb&w8Ewv$j)d!|4&&}AcIJ^?(^)URydl9Knf%0$_oW@eB= z)5W{C9m~-uUu%~-nR&zk>*N0C^-lBHZ_VxKdCtGbHSLMuNR9I)-2Ly+KBa+_N1qoH zh>Xja2tiz$FUuJQ?lp#lr?Au!+QnxN4P6KjPE4OSzcByo*x35&hAp>QLTDs!tJjZh zz&#Qv$A-s*(`tnKxf5NGuK>lr$20DA8}93K_vF?sWQLy}d+!0_0$)!y+Z~H1^ugdO z=jMTd-+F`XLm`v>ZAu;A5slDmhwSkN0zz7Ii>`elieQVIx&Q=D-Sslpp9k-@_icNo z*U7=$=Zs$8`wYY9wFAPJCC`t%;chDxU+|*RqZc@-g5vO};@f1O2WNsMRzU10@Ac)l zwXrnHx4pXDO?#oP4RXcTkA?T=bZp;uuAo`2ASmh}*apAUGQSos-;OfN4i~H6kKR%e z0dLFVzgGAnAkA)99EeUFH!Xv4y@KyO11miPt1UfhsVv{HeZeb1bJ(G2RH0DHL9nZ+ zoMYbEPeFLA-u$daaU)iw+%}h~mIB;X8>!!S8tsK}zMn5+lZ1vmj(SWzxVydg^%j8%TvBdDvw%TSKbp4<*ze$C+ zKZc2|+PYBs1!(!vdil|}2Qg_y{9KKK{}Yk@6ajY<5oHzj%hGWN_IvKCWj=SLAa&H* zNF--#bZU9HLPWGGj+3=!RKIIfD2{g(PH3H0*aCO#M_E+kSOg4Cbo7Zskz_FXn8U3{ z^j9nUJr~PLthnhBV2Zl{bZAws{OVAo|r_uaD(P1J^l~gN{#KIF# zQ<3zCD%sF7QU5sE0X9X%J5jVEfZRGoQ94;0H$^uxg*!5_{DjZ6ASTK(B+@bvBoSp^ z5pzS0A*k)7@tGS!DGgdV4T2fft0T=PGVR-58cIT%&>vqE+ypq7wBRQ*RPCRBA{eET zh5_k5Ra6-^;i(pI@j-u7_{S5nv@vc>(>!QU^J&sOY0?XDGlhdQ5eqW6BjU1F6Su{T zj?3*k#xfe=GOTzqCL=;RwKFWOQ^(uA;?^>9rL%)1HOqN2{k1a-r8C9)GvOg}aJ1rl z`#nc!tai1s+9dU;yfQN2oYLX4hrpi75~qo>u9*|kfS|SPNo!QUwY0O2w9<^Uvq;pd zwd`@4yaeuq@6XY@Po551>CN*2U%aDXy?=JK1pp?(;K!YydCeA2iK*JN#!s>W|77*A zWo1a`%J8JNL1u!a^X_pAui^57B6H8jbDtyg$TLw-BMUD&^6;pcZQIjxsN+6QaK>{w zF2My8tU7an;&@~%5^)MDMWR&Gop!A=a6zf~l^G%2NiHyj6EuZWYlT{wg}*xr8EA7Z z#xpBva`->9e{}e!aK~_++Gl8430CF|oJ4~na^%xi+6BY7C6YWPKWs{9WKd6~3uAc8wL#@`73Iu$Rs0h+1JKSx-02G*6&8h& zL%dnUDrYLu-Su}1r?c<3qIKa6FSGwm0IwHlO2UEQRT3ECHpc}QBhUH zrFus=WfQ!11t)oYowZ{=rO0bmEx2`(6UFkKb)HcL@3gso6Ph|aDV}UqOcOP`KDBVK zC9O7joj$eSqpbc&lo8`NUV`F=LEd5#PZKUJio*aVzPHY3p{ z$m$04tfZ(**BfQH6TZaIW+as++7$SEBn`wg#^! z1=nW3QR%pmY+Ti98Qr3P)@n!>?{C`{m=)q~n=35c>U~yVE87xb+fonLZe7)0GoMNs z-DYswUTvI|=^Ovij>#!)CnTF6)KJ+7mk{ciE9SxfvNv;%VH=$0Xd`{JPU2Q5s6Vb6@CmqXawHy=;^mN_ipOY7KwX1C_ z=WU{Xyq0~J@@)a*_iU8^$d2~cPyYe7>H*sNpRD-1PM8(q=PT0XldgDXgL>vh0uVC8 z?sNliI%+*7x;HjrwyJ6>q`X%m`WVyu=1(FfyCM+NQBnANTDVK`)5)608x~J3L?aq@ z%&gKLok4#ZMAzepZHqs3*Nxz}O^HWTt%fl91?5d9Vq`}&m80@Rcw@;GJ$RIkj(sm! zulfZu0GSxq4+ zvWe@H`rZlds+g!O3P0}}s2JEp=-T$}Q}-M9)a$DM)7?(@lQn(t+qntZd1;?)Tq(hr z8K~<%Ge3^M>?eI=ZPx%aecNxTessUd=7`aj2-J4F;rTONiKzzi&1kCZuG)%;>r%(G z^s%$gKS+`qQ*~P`5QMWff*?-fzaaJi%H#dc{Q%U1eAHe)ywl-*^5t}Gurm@qTjzvm z_I@TCIm_reO@eK2}zQ*o7Zu{Qn z({j??Yo)iA&9K}SvJCECNZjCKu3k0#Gca}5S7kpu=QWtNxh%R_+L<11wAmxAS4=Fo z5ev75XV>sTzv4!_&MQC9zlB{U5IP2o^^8+N|Xlo~!48^6N>Azv=yVqc7)D95#>r4+o`}vKZ%!E>6>sL94uzjPffP zwI`VVbaCisEC~lTu^rUNC9ZELE|h28wO^VUPvPWGBOSKO0`YBh zkxitaD@yo=u!+p}_f@^7pQ+QmSU7>8ZX55O9eBK!93&=*onvZ0rrAQOQql)nLr!!< z(3C>eQDv?+e62q5-TO>^J#XzM-lJaUmYK~K5_a)m^&E!aR=4~J7GrV$^nr&xJ%u6x z0U51k{KL~W=vkpeL+6q0>cI%Ufd#J?x$BR0T_)dVQN%fLH#S(fdM^R*`Df{+ki&DH z%<^wpO^qwu>@T!aH&5e4f0FDL{GH3gL4V+1b9FPzyFrD`vsdi8dH3>b2DKwyIJ=LP zTLy>~z9+9mFmL&I6WJUuZzeBOffwbyx6^TFJh;Nx;0Me2$0)L;4YM@7`G|K?p~q3DB}v%$LaJ2>!rR2dP1D*c%LIs-J1p>O0Qg<7u30 zHS(AbBwPK?7jF5CUTYrhbfMSgv_TZpwdA1R;di4W{^~*|or?*3wRoybr!W+xs6uY1 zb$yur!@hR!w2KU>UV)G0-<~+$Y#05ACeJY_Yr(v*KEI&y4B&V*9Pm0 zPL0#;dEMq2jPN9n&8V>#a7RS7eM=@EMpxxnjr^r?@*KU(@ECrZZ{o6k(l<{bw|nYr zxgqqua$7)ZD@%W8G|#YCb+!E+JPOYSfF-E!dHF1MEd+sX=F|#}|6Pgx6Uj#1Hw30b zrqa(`^k*W-Lftk4O~T|X!hdAMlshpr?Z#OV4ZnZs{m_z|6UF1fm>a<-S#*{pQoMH_ zB*2eqkRmI}WRW5WR%`4h$s%u%q((4vk%7$PXO(40YGxIo>FU0aW)37!9iyE@bnTk{ zeSa&*Y5jUD-#CULQMe1_`g;=$#o<=PhmNE?{RuY*U0Di0 z=l*vSQO#nNIGcLHLVd0rgPJlle2SVf%GdlwMy?09A&o&-wds?5(MzVCN40bQ%lV}0 zU(^&i)|8+_UzAlLvR@diYO4BJ>iKf!9{HA8B_3;5HD*f-c5Ijn?ZBwlX>J~3*;IiE zc0E>37Y5fBJ=7*>%yqT8oF{Fo3Jy$wbheRgat z9JXnqI2>|c;MP-RH0FA{bRgY3&OB9$s8&JGN7SW}PIy&I%?_eNhWU1nIX&O`6nrY* z%g};$qduE&HNT;HcZXHIjiBR6?iW5b>)aFrHX9#s5wPtbMzm39{HHif`a%Mbw!I?_ zPB5eP`!L1x#=eqZ$05*bT~0pSlaJn}2zz1tG6yc2kNIY`Mt4Zx{rjr^FUd`Aj<_0& z>>Zjm3k(<0UYJ@l-7T0`-6r`|T;mq|tt!{ay-PU<2#QA@OV{I(j;%=PaJkEgd;|T5 z!OycjaCD4&qns3Tuc{IhxeXJJMtV+uAeR4*II+ek-RrOt81lPg(;PV+)`5 z+xfhsOYf~Nb*|^chk2nJUYb#-!-Fh>t8I-gH@QT%)sYOb?~Gu7V3WThRYnGYG&YRJ zglKrf?Q+<5;RG~?Cu`31esm%JK^^Nslt9%tfz$&*V)uUqA%_4vBlgovXw@?&49avc zKW@uL$4KJ2cH#9Q(nJY>P>D?1a&fM$+;rimGFCfm@hEw%f;95C32_7(l-?yhr|D;j zSHUTMi*0SVai~_MeOl@N-0%-CFt*~6A1J3Vy)fgG|t-n`Yv#3)#pI;0vuUk z2-mcMAxxHVI7#z;xQrP)O7@JkNqiOXLda-#3CD){v}GJ!)@Dp8dyBM~95h?DJE(M^ zM|#?=(lz@qnUHVxblUS$!e+Pnm?N-5!S%>B>wU3=|9wp%NTp(@3Iz`g|04RiRu_(WITsZ1>wPNZDsB89GYdIL4`gB_w5S;h z?BpEsb8<`K6HGm`C7&-)758|$0(mQJNBDt6urCX&0@7vNB^B~CHmW&^<&|T2q?=(f zv(=X~v6phDPXRE}7s(t}Mf6y|Lp-<);4w-UvaKZ!be76wI7qN^KoU$*E1B!+bBz=`h*IWS#MU4i&3j3UurbLxo%sgC>Giw`QH1%L>i4D#O(3=J-n$jj64{Ej99op!Ky%3TPBe`@ zhcYVdKZkShJx_3F1eH3;Wb)m$L6tE^*ew;)Wvcoc>o*4K^&P)zjLtF*dL^3MS|02@ zWsmho!sgn=?_|>|_0E z`&DJfRk^)t!cB*XeC{24#@3L_!ZKy=6p3DGh@Ph2AgV$Z(LW*EkHpko>Re|c1UGzHR&{4m%*)9dSEZJr`xAYS{ZCPZ^U_T9|0uY zjJz(LL-FXIN}svTg~+;_;GgZ^5Tqye)+SE-4BHr9vJL1h+p1ke&2{&9EP5d|gyo%Y zZ(lCAo!p#Qx-*>HgL#uPmfXptbqvewC9OpdGIaWXo#_?5s5|Cf>wa3FHJ#k3qGQ-r zi5GCR18r=JO~G}81A$j0Ws9p1jNHXHkxp`Sn>CK_Z2~PcPN))ZxhRV5!;@={VTzl( zt;JrwtVrJihza)Ln0Uq{4V;sA@DGqyyqtLgZo|s-=uK7E0&yx*u);P?>A*aV)2}+w zBOdEeGMpOTu@?^5oZm>7iY0w(PB@{L_RMjMPXOPg7*ujn1ugeWT@keS1|LtPgkGaI z|l>7ilMRG`uw$~NR|&XC`34$W*+?xCHZ@)ulkRZNcJNH|;B(sn>W z7UUnHH)n_jbFHajU4D`!!J13;teqUujcV3wP_OmwP4gTtRCr0KLh>TleWhI<{qQ9t z>|#eqTdHINX(DB*10SnL|Csan6xyEbltCZc@#!K&JNg}}I$tqg`I>4(t19Qc49sG6 z^YQUPn6ci6WaR~iHbNG&eIn1pMkj?%WNDTmh81JpB5CNyAs+fh=;qo&$HqRq zn$6%+&_#yY#4~W%)B=p=N&mz5Crad=w6AY)041wOrK<9Dpl&^%!@!1&bdwcvv49nU z9cbDN<}fSS+aP`oMWqxI`~uaPA3YGBKA=$b4fDGQZS^;X^FhJ;foOzOX0v>fZeeIP zQ7us+mced8*`WfT2)cFQ894l!!LBh?B4;?Eq^b_r=jNGD-58q#3i#p!(IOa7!diEY z90e`+XG4SpLN7Mr(g>oT==dLP+eURWGJ-QiCpu7?`4u)hzHELmE&dXY*ZKR7zjs3L z7oLDsR}Z@0$YM0F!9we}O0V&!Hn-?s?nODyNu93f152;P#;=?^bT#p>oxF>9p5!7~ zRTy7HN6fyDnwpJjR7zs4jpB`uN*9d!4vnIb4`m#5DMGcQCQ5KDN(MJecHW7-iAqK4 za)UD``Mt$T0`4V4Hrpeny7}D3Fz3dS;H4AZBvtXof6|V}4oM~JjmJVsN574|(MiQu zk408XQzuIY+l(i+3wa)lrjbj>#iZDp@rD&A=AfmPh!LOTa#tmF=Is?b$zq$GO0%dn zCCZJL6-yuM43)g1wj~X1oQb5UO*Aw!!IGj^x$%g9nP}RS4jN!-&d#aHZaiodDJJhH z<;SZ-;0r|?XwZ?ob!NUhkZ|X#Y&(?6c4Obzkgyy4wOv&W+!q*uA4O-AlsL=X%#y3H z!x%Sf)0mXQhoEpbV=ObBD7_;EeH+A+OLb@OE>w|iBj+B8Axt%D`n)Kojy|nLAO_YQ zlD~AF_*zBMT`eH>UHo=ZzHwr5&!i|0LrCwgZkb=KN4ifkNnW6FvR+N@GMjQAYIb)> zhLwHj!laLouDAQGj=-*k$}OMRuO7%Rn$N2UU)i85nhWnX{b`DX07^#iRN*Q{x`FgJ z^#0V>ZV^Jg!4-PqciM(NITk!NMM5t88Ajc+#uED zp9xmGK1qT>sTc(~yIxGfSv@yp!>kh8q&ZOW+{+Zl`=auenOGQN#zpl+ZMS@<+8ooH zGIGrv*L)?8y2{sYVnpsLDDNzfQ?>L(N^}p(kq3(S9BioSe39K_xhmavbTi-@o4Lbc zaW;xdP4*d@;YqBjVfBM)(7ei!D48tUXhmqciFB2t+|)X~su!!wEP2&B+357t#0tW+ zpuj}`d9m=c(jp?a)4hb0xSA0ey`Z>co15CI91m#=l8S#PfCD{ZaXge>Ey{1mk4-t( zPBxT$0X;|E-j7R7ekt8-DWiE>Yf4IAK)n!3BaK{5SAHz*Zb@T$+=E|3TVBH_dNQDE zLeF2LBSu3O#Z*m$bzX1;9CIzvV0)ifGeh;UZ~NvZUlcO=qol7DUkw~2-ooiSYRjOt zEH-~RKN(!pazww}dpH@yP+srzYfDwwk51i@oFs;W6T`n+0kg?XSB-dx@OSqV^TZT( z4)0R)?+JE!xq0oALiUxWsfF&fBKORz7*(8$RYmJn+bVUZSo|BrStwm$Tnfe=`XX3f z;e9h+VOyQrSoz(d_3Pp_Mvm%(?%AEt`Agd&3M33}Yt3*%rK(}w>ZQ4tWTl(CjXKO( z=ueFdvGXEin`eo$Ql0Yl{($EH*+T2esOQ-Y^{jv?_$z+N^j@AZSGv?Ao_JhK<~7g z55C2ye%H|l3$MPtXt=o#6d}G%Jv!`Taj4Bt^yoc3X`L$sc;`5Pey?|5ts%nbryN(!pm-fqH z*#?#+T3WyKae9{2b99~=G_fgHC#N;C)RsS|@(@32xFDI}hZzwtnz-f|W5?|UdK**L z8dJpW#K>!s5otQu?-}`8<|xHqKpmJT-uPgzILk-{nRHD32{V?32gP;&+2`+a zF$$uJHu^J5+t9;AOEu{(1gE|dRtNSmlzxNwB>8TSvJ5>NvKFfY)7#fu+c!1+b4#bk z?>oH@rw4?`KaWoG7(r>Zz3CPS86!iPoXc6Q25}Tt#Unep%ZG;`#dA!XPmBhan55i< z20JO@?>qy~pT4Lb6?&8&qOLEnJqS85>gB>1VM(w<5FNL0oOLlCy`R)+xf7%8#*Uwskcswu7>tE#fG8uoO7gnu z@<2M6eR1UUwpI=4OR`l5%wpC95)B|Z@*$Y!Xph$5f-UTTpw(Ig=74(pg6r~vKG$Zy z_AtrLVLiZpEsWx1hU>J4802AcmP&E{XmY_=I+D9FDrmClaA6^6b`)lN+&Uy}U`oxo zxVWep9%Lqfb%D-O@m#t&MM>j;(cV#{HT2XO|eB1HCi#G%Qp;VyH?|K_`C}QOY^ZtyXng*t*{%( z3t$$>MSOsH@shd8_Vk?F5URl*4B^pNNm-dqv9Kf5R)eEC2uEmZm(8EYx1V&y&UPGn zs%s=R?Y4J2R@2a$1C%U?YLQZy=uRJL=l8>$-)lUzXte`1u zu#4R6eU(gJlqqf#i^N(H)5J3ggsSvWe*Ft#Z|>u&)@F!m^pdwM*(Va{8M&U~1x zPZ5E}1kM1%vvd*XOm9!Gz;p0eoJ;_N{e+DBSCp4 z@^rS3kt1?^pFMQedAtEP&N$1$uCGYCx(4Qo6QjCo7DvRroz3X;tlWw%tsgI5u%Re_ z^~Y%0(s9gPU>?;~z&r=_y67+Fje3GmtX=0=K6(Q$57Tb@>~Zce?d~rg`B%<<)wl|2 zy7SL&1m}teYwA8JT1{BFBSU?LgoH(-x4Qm1@E!IOvmK6+k!S=mE*b%|Fv&;^9+%5` z#9ZO%Pg2Q5_Rna=eM#612ITpTz{z9=x&brog<|<+YOc#op88|CG&b!C3?H_#*<#LU zEHR%XGNo*xP)LDFSD;e0syP~F6dRRlu69Y7dIu)?aESGiApNO_v2N%W=vs=`N5<_g z!ModwsyRF5K7%5#gni`_ok=F_QviXj7v14d$dihP-%_nfc^n&6Du3$r@oza?w#)1W zX3O7}Ov@$snuR-UH54N`ggl&=n{DoQM||2qhJA>wiy7R*co- zn9E9#G}^@SktA7ygXgs0UH-DnwN>&?wKpJeET6w^T$IB(sy71b;KzN8*jVG(^_|-Z z;7YgUj+JS%Ic^#3@KRH(I?cORjxU(4?Q-?lc0LD(!*`i(;?0>uyc}i_Y1>rO(d?+( z((Qq>Hx_c`HJkP~R021j~ynRmqr zJ_gnXa(#G|?KIwZ#MgZcLzW9oHOFdyoJ~!9hznfO)aqkT{+@)<;9=-za(&{>oo)qo z97WcKMrUp3K|KhAY8>6x+4Qeit+21mkzC-j33nOG2M`*sf8;`gnl;&h{V zVvKa6q@sGz&~6Uu;M9=Z#yBIOkpPUX1|vwEf(Q-`R`epoke6fZP7`+0EJj3`T91rA zR~e2*rPp%!*h^?dqb)l@jq*$==`-CbCssd_QOQ@>s`IY9(k5}#_n*byktPzLbTEB& zK@GLwUm}yG>^KltNfgQ^#hdjShqQ4@w5vKS6Rx1Kdv;11<4dDDwVY7pj80wzqXDVe zD#j@)=acK*v}wECW%brs({l8HjQGHb!*P|QECNc}VC^XtlBSeNvm-Xq(@8sM)%3YT zHMTT$d2xGJr8V+Zjs{!>*#s3mVpR*KCF(K13`LW#x>P-fDWlF7U)1C}ixx3X6@0N+ zNYL4jSWe+8zW<1gs4iaYVwUcEzOgWosZLktUSkfJPh^-8vlPC9okNsPR)Blk`540; z4osQJq@d4T57A`H%xKEm#weFoFOuw5XJV6o%^Y5b;>@NU_m&YQ|L!p%S$$~#Q`L8W zKU=jk3wbF{f|ZsKGqWSmLOT2!mrOJ;LpfuH!L4Od-}w@YJSXlxu=3RgtZ)!H5F7X4 ztXsXW{Yz%?BvL^nM70uP7$j07hZ$o$Wb+1-s%|rooJD#DGSaXlh0!_sPKQXN_o<0@ zgcYgL*!>KmH%+UVvo>Br3}hs!r4jU?Zb4iqA3g+BN%{K)bD86kO%FM+H>hlhV&I&}T^v1t9_ z_#;k@u}hyiN-_$>U*~nkt#wZS6y;~nsIIBje^i;4SmR$Ifl0gB5{KOm9KP`Meff>! z5ZS$+V*hb3yLLgF7KSg5;P-CR!O|mX?_S{Gel@v{2Cv-o=6>ZP3#JupXPm3mpl75L zqTM*-W#OiraRA@rQ6_t^gwvHc#iCToBRxqQKUG)2WsRxkYaGY>f2R_>qiJrP(Xh(B zNJ&^rXZmV-Wviren52(s9+j}zgOhW~E}Jn|(|Df5e|eK}bw6!ntTk=@Xq9gGY{6aD zRH#G9mi~GQbW7}*wD`D1S@Ba4JYJjm4&6+4ASWm0yY|~;#x)PW!;&9XXKtL_t>od& zQjSVzp{3ZZjPT-1I*?nzzSOn&>BY1R63z5VkE2(Gbk_e?wMMu{IcfTkMMU(81Iulp zLSDeqD5-i-p_rovhW_*uh_~P?7J;O`{2XgiF=J2ab$XcmIhZ$^vj6Lmd64~uT2fe7 z*e43@o1qi&FBxnl0m`1QI+Yh3&{^BzB{WHQ4CEE!DYlBhHbKMV_DoiHYx!FH>M}j^ zYg+qKWXjvbFA5svFn-@a#uct~<@i-Pe>fgmx!T%X6URxHhZ!8`4W2y>dYm8EG%(Kk zx<;4#65iTG_&Y9Dwhb_vR=4_ITU?!8I|`nZW=K|M#&mP<1wvLf$IY(>wHa4X4rWf{ zVtE&>Yu%D%JG!78oR*g`w#MzN?QR$%uazbpmS*tfiJ2B`Yp9+oH~ggC>ry+y@i&HU za!$Wi+s81R>ARnDu4_JCILDv3r|GgEX#S8r@MbgYX9fRR$T+GD==a%Qetzo9T&nU| z(A}M3GHCyHzkC#HxjQdZIdBom59DI(ZO}AGv&T+ySDYP#Uco-6_^~_i@wzv+(R$x! z_$(7!b^ z@QCfQ5N9$#J-O#~1a0bOV=v&9>DgnH1A#g#tIl zI(7x>>+@$`A?MhJrIh>b?bmAfbg1}J!2NVi}k)XrVxC?hz7#V@SJUwn4q(Tvev zjLPQni=0VG(Z>STn{ zlI~GW51YUIvhirOOwCCQ%n%7I(h1_eVnh+VE{#2OY+1?Yf8{O2vNj+JAvi+H=z%aG z{}4xVAtn7lI|61Uf0ZOSO&Y?)>;q;xzhl&LDB(ZgD`RTYGG_EqsC!W$)$$lA6co~M zB87`DKF~uqZ>dcEfWp4rA+U%%UX4>>*tt&G**#pEGLAB#P``IG95h~j9$vDzn4K3e zwRA6xfF>4+BsO`UViedql`}4P*B#F}2wnpx?|SD=00}u9azJpa`~k}|@7sIL+57! zldhWkoAI^m%%qsYI-4rNsfmmr^9|&St)m9@Yr(4*N+qJ66dYVT6Wv`Lh!Evr-58KX zEt8`uvwIwv_LEE09-y`sk**&ql;$eJrt75FD%_ z@1h>4x~$0U8{J)xOB$QXh3Q`>Xl1w)>$g%Y$7=m)A$P0Jldn8%yV-+WCe@Fem(-Zl zB`xrM$59C?rZ)Kc$z?zF0Rt*dmre%!75XC;+Juw=W*#B{y5~L>5O8G9s`4VQV@kQ- zIKGQ1acJYPjuv8qk!fVRUP>xxmP1~|`cjJTlZkwERKT$p=WpV?U5dVJ;i6ISg|!R? zmx`Oj(v9}mS+KyN=g3KdLcW#U)`d#Xhsqw!(w(;qBc#kUipnm)(vz_S%wU#w4(|wI z>9lN|+)agFx<+hqgiDLt2sep0lMv3K+X#1Tf@I)No2$u4g*j4km|YN%YJ9|?{{50f zcEB0(@JW;RBidtYyhf> z1(V)}()w}#6EA@R@PN)lTlxh&M-Mr#-(cbvK{7m@+AFe_@M1z;o37n|@>Thi(k9=Z z709)X++3r_5|U#$KeJe3xOG9%| zKtZb^sG;FIOs=9rp4LP5e0q?7YhI99ESy@Ab{oI+BUO9GI)YIxSHo)K(9Dk0YEzCp zl^4a-x{%5zS1ZJ32Y01h=kN)RA`C0{n#cO(r%hGu;V)@y@luiyB5HTMt>ieG`UoN= z6N=>=bEngi+aIW>Yegl(Y?%+7Vjsm&zCUdA)rCfy#==!W|V-+xC)ljn0Z{ZZhr= zjpis65xA7V)^$IxqiPe2UySQx!WPh-2|MGoHWKPqq-!-y;;z$?y zB4xiasbWXyBQCA0ex5{W)pX-g|1K<>`KZP`vh%n+UzVw9CB5)YteMWVUktH#wV|4= zwOr>do)9UiN}yN?yKwwo;NQI#u&om)Lm7-!-hPv84O1ItQzNIbUtw%Jt58D-S=x_x zxu;-NXklN&LUj88K57=Rzv@WcDzsk-qh=>HqA#(vm?{6rsQt!B&HAx_w>T}o^@Uuf zbg&j?)Pv$=zeZYMff#8~z;O9|9G5k_o++H-1dg4orPf8&pT3SMDb#K&V zB(9w#9vu}D0bIkSo5LxWhjmI1LH52}lMJD1<*^oW>55HVK^POi1gM|0jx!9{OmyzT zQPdb^ChWlkGAOfipkw2$1j|)EYgBsoUlj!`{}CrFAib8SWj0{Z6XsLr?cVg`L zrs9;VbbW^ft~um&5SgZ1@~`b1scd&Si>j&WNUgldas2vV+&E)jb9r57aP`qh69Rt& z>kD@~!=~3Q8Ga4Q*|D1MgO1nAdWnno` zTc>2v7fBhgZ)|OGZk@|&MS2P$V<)3SM&D?6UwJfZVlT?eFsyU@^wRjd^()hgY~2Uz zF=YKbQCUt+`Mc5a=eDc0Mh5EWixp0XwGS5ZFAYa9w_80mmo{wdgm=tTuFOn#ZmbM- z7_MI|!EAg_2s}&-%;@&~Y|XytWn0lTAEeC@iX4gBW-&*(|Q6gxw`Z+{?Z8 zcY7IzzlM;xPk`>fORR^;O~2C!onV3=`84>mtR& zRVCXQ>n>`XEwFj9Ic3hv9BVBWJ+Ytx{3!9% zBmia;40M%@F8axKPet6qLB){B_dLzZ_7&Zmcju0`>(SQNHA%GNi|#Ye;CYZzdCC|POPo`lSo}ox4E4EX`2$Ic2j6*PcfOU_hmzNv)?@0yYHW`t+gk4OjGu_`*($7Hy`_?z(4oLgC&PQ zy1J+FhU4^|!+Dgq`nFnlSs5j`qI47QHOt?37dP@6x4X;}yb{lMvkrPM$GHYBILkCR zxu-mYAAAzqcfHH?Ay;pxW<6flJkPoNGsAn-LzKlr?0t$X#F8wtd#R$=xKyt!ET?8g zjwS)l{Vmu1k6*ac8#Al>xipLXu4DVBOOvMSv#OUp)Mq-TGk(qs{+=syB<5zj-r_twE?V%(3(Oo{}_qpW{KIV_So*%wACBEjn?bv31ye~fJSALPx z{xugq$^Sh<1^(&>h@xMl<(hOud+^7;bg|5`@l!NB7wG5%ROplbFLpY1r8Hw+sA_7z z6q`ElxAx|Szpm4)dmk~xHDc;!FvNTA%A>xpTUh#3@r}PoF=5?pzp@Xi=j#AGQ>jbm_^aGI^?m*-`%~%&AO~YLr@4 zYD}jDohtN-_3Bow5Tl0V`t@bklV6t(jcJnVMy*^q%1ybJtku4Kj|LW8H0@x+hiw){ zyqNLdxNosOb{jEjUA1Q|Cq7Ggv)`wWC3A)>H?!!rrD?8p3-vBst8G7;u8i4k*2%D| z=GM!Y_hH4ofgk-HocK@2VdvJq{hF>`i>PhGUOiN4ZHlu!*1hihx%B9-aZ}f59d%*t z&>4yauX#D&(144_2RdAS{hIXc=NGNpbN}0{PvdT{-BRl;Jk$D9Z7#C{yllXp6!h=F z1t)wkGwdAHDMI%WBv8K(mjhA65Jv>@xDz|$3Ba;qYf-57Qr!RS#QpA44nr5eyK%)1 zr=yI<266O`Js~;duf!wqJ2Ji`l?)C=3fcNkJRqY)?>-sdo035a@sjMq8oOdr!s8}; zvP>{ptWvq0io}w~CPfqzPTu646EQPAQb|1Zz{`uJ@y=tjBtBj84y8QP+mkad3003z z&8mx(v`Hz&(Ir0<)iY3`B-M0EBkjzu&QJ{-mDIrSJatJARqf5xR*6a#R^VQpbv{;Y zEj7#aa=jDRUInWa*cU+^)>mU){T11uWL*|jWt}w++GsW0Raj~f#P(TjgSB>AZVLo= zTX6~VmfTpsJvT#jrG1lK2-AI6NO{>Smfj)n6*OOc?cM+PL4Uskc&26rCb8go4_1@c zgRd30VQvX#I9_=l);8jTE4FxIb}tqg1)}#XCndP2MW>!keRV^T*e< z8g~yJw{r5#%ehjug5&Sxf5Y3+m)4c7)5Xq!vST1y5STXwI?zr2s~zqnXuHbgu7a71UkE!F zzXui&EEj}eko0#u;9-u0E@adR%hsY9IxcJ?6yN|sSi{6+Pkb*_SPUsxL-ZNxbF^t- zm^O&L3n~nGOw`=2kf=iz@-U100${GbIIEGZjB)1~&)VvCvH~@(P<^+`LloXh=}7<3XD)P`VB#J0N(j(`cBzLl++zP$mnh{K@pVm2 zA{RXu)ga|`se{Yn*Tk91Sbh|wWThqn!GctBwlRZHWEw=_T0GETG(>G(p78i5zoX7I zdRq-2PTwlM3T>2XW<4uIjq20-!L)p3w37Acs#nEEc4ZlC?2A-bLhvotMVD1)V6}MF zOb(T_k3=h05yn**2T_pcGQgA?B=R3^^M|ln?kbTwTfl-=2mm==JoC@mwq?AV- zF1V)+R_TKaMObp_cfW|;nsAA_-Gp`%l^ph3Jy}^|{C1d|I9qXti~3>Uia5ru}# zJ7O2B*uyp+CXZ_zB@hRfkS#tWkVR}{RpMBv4E;12sOym?hd8|mz zF_&)%RCZT;5#QOrPZ%dsEz6c-l+Ze9lk# z?1Rqybk>&k4ifwsQ*U0qz5L=Kq`tU+#@YBf@%J`Ox_d3;M$Be3wtGY?Xm*!>?N&bH z$z8oN8Bg^9?{bhUjtWrw42f=_&Vb$`qjYb}crW@SF7n(CkiyOa;SaJ9FMlxV?lucK zG6^G4kMRGv&+h;*0P)43F75%VZt21YKfDg_a!UhQ@Xv^c{ZP+*E)cLLh_#Aq{zfpd z_HT@!YpMj$1hokTHBbfN$_JUwwYq5d_D`>FkpARMdc;fg;D-s@OZw=}?50EX%;U7) zs|*_tH~J0=KhFofP5hRS3(s!ip0Ks>X8=*~yin`7%&dtdko~r>0x<~q8gE+M&S;cQ z2F=j8j%ezF=elBR4)aOu29UU-=MWjl@%9H3(=QN_&oOH5VvgmC>7-!s<1&mpHZH;_k5gQ60`X|w8cyLD zZW;g6tr?xM+@LWU!)+R=vD>Wi8nZ1MwXxc`u^Xf98^N*J#Bm&xtsKp<*w8T@gKZtz zvDe)39dj)n<+0Z2u^xGB;PBBK|7{-~t{?r8-R?0UBhAMMGTsLAAlYo+6jB-ivLV3@ zMPh9tDY7Ch@**)ZBfUi9Q{E@-F}J zGB5RVFZr@B{qipXGcW~nFbT6T4f8M&Gcgr&F&VQl9rH0EGcx1S04S3((Xuiv(<(93 z05r2QwGuNs(=#P=G)c2GP4hHSGc^~}GBcAaIrB4L698BQBHi@${Ws^2v(>AdZH;51I+qBG4)dswNOP>Q%SW{12t4p^-fiFRT=eE zU3E`eHCE+xR%sPd)ACkjbt`ohPi^&9f0b5)HCBh!Rf~01j}=vuwN(F?Ra7^%SMBsF z3!nh9GEV_uSFhDlyK-8&6)UZEQmyh^qjf8}wOp@KTnUv}!ID}%)mpO^UGo%F$+cXk zHCw$ES}Ao~yOmc>6<$YGE9tdf!!=#cwN|wfTj{i5^>tsXl}`)SVI7t$>2+Z5^-?MJ zT?h76^))LQHeVmsSKl>WEtX+3He*>eWFJ*x*%bf;7GqIXUa$3I=QJ!^7G6!3S-(a-u5B6g5bz@nUT6Z>SgEnS?7F#)XWm}eM?e%4ec2{2&SFy5X>vd9Px*Ce3AbH=)^M%XYq3^Z$Chb%7Gy^? zVilKjKbCJZS85s8XXjOGJGW#_7j!R`TI*I^8x~#97H&^AXIGYXE4E>8cWNP5YB%?3 zYu9x{)_3hzPzkqizm{?LHg*4%cqdnFiB@5gmvZ$sczG6iJ$87pmUlh2a{0AtFE@2> z_Fh$%bd&aCW!7Yow|CL^aox6gB#xM$f{dfV295BPIU7>H3fd*@ekw-sEU+*nN>0dq)?3r`Uxj7>3Drh~@WsQP_jUIE7VLdYKoD4_9tY zm4?d~d}CN}!IEp{`jr(?f8F+fNc#1{0jDz@j_qdSxm}a3^ijCJ>1zC-$H<8ViYw6fu z6F7GR*@%}IgQ<9wiFj)U)r4ydTZ@>pR;;^MVOu!`JVq_`lhwIk`sEDYgdDt+Mxp)qaV4Dcets| zTCWw_koCH+0lI9(x|IDGjk}nGT^gHN8L6w8u$`D~lh~d&`IcukU<-S%;TNvsT9&(2 zf6+O$lXX?tOHcC{;bfIS9&9e8+^gIePx@l zXB&_~xOAV_sBQbUW0{b@H-M{~x2?C8ExWJ{o3~kacYiy#o4b?ux>IQzoxc)a6&Nhl zJGR-oy@h*vL-%Co`Mu$Lc)Rkx(c3Ha8^2BZzMnOs)zxoP_PqUDzT3N5KUKjwHCesd zr%OA%`7FOY#!nJiRt-DwM8)jb(9K*rY!V_G?)%#e@7kYhJ!u1=(C6&bsJW?lI z!(*Jl0i47g7sglI#-Y{49hJw;8^>!L$S+*SIb6nboW_S-$VXhsOPt7c)yF;DzJok0 T`@6RDd&a38%h9sR0|Ed$mvt5Q literal 0 HcmV?d00001 diff --git a/screens/screen05.gif b/screens/screen05.gif new file mode 100755 index 0000000000000000000000000000000000000000..016789aeb1e6953d4f23385e010dbdc5db7772a9 GIT binary patch literal 13775 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

2-y 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 literal 0 HcmV?d00001 diff --git a/screens/screen07.gif b/screens/screen07.gif new file mode 100755 index 0000000000000000000000000000000000000000..c6a8059017b7bf0bf0c3503651b14b569f54c634 GIT binary patch literal 27701 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 literal 0 HcmV?d00001 diff --git a/screens/screen08.gif b/screens/screen08.gif new file mode 100755 index 0000000000000000000000000000000000000000..a277ab5a3b3e02f535af6c3aeb4e6abae920be47 GIT binary patch literal 26717 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 literal 0 HcmV?d00001