; E32.ASM - Copyright (C) 1993, 1994 Douglas Herr ; all rights reserved ; ; This is the main E32 source file ; include model.inc public main32 extrn getcmd:near, mload:near, keyifwaiting:near extrn strchr:near, cursoron:near, qfname:near extrn insert:near extrn tprintce:near extrn ucursoron:near extrn htext:near extrn showfkey:near extrn display_screen:near extrn topline:near, showpos:near extrn get_screen_data:near extrn insert_key:near extrn readfile:near extrn isalpha:near, isdigit:near extrn undo:near, print:near, mark:near, cut:near extrn paste:near, save:near, del_eol:near, del_l:near, udel_l:near extrn new:near, screen_rows:near, ffeed:near, copy:near, dosshell:near extrn upcase:near, load:near, screen_columns:near, locase:near, search:near extrn home:near, up:near, pgup:near, left:near, right:near extrn endd:near, down:near, pgdn:near, cursoron:near, del_char:near extrn del_eol:near, bottom:near, top:near, goto:near extrn window_mode:near, switch:near, swapmode:near, search_again:near extrn pushpos:near, poppos:near, replace:near, merge:near, setup:near extrn yesno_message:near extrn working:near extrn swap_files:near ;extrn breakrelease:near public x0 includelib ..\asm32cw.lib include dataseg.inc breakflag db 0 public breakflag public cursor, top_of_screen, filesel, filesiz, buffersiz public cur_posn, file_row, filename, first_row, mouse_on public normal, inverse, warning, key_status, insert_mode public columns, rows, dirty_bits, left_margin public screen_addr, screen_data_size, screen2_data public save_column, count_bytes, count_start, save_row public undo_buffer, undo_length public push_mode, push_offset public int24h_msg, verify_msg, extended_key, no_file_name public mark_mode, mark_start, mark_end, mark_home, nul public file_data_ptr, file_data_len, number_of_files public display_mode extrn window_row:byte extrn swapmode_prompt:byte programmer db 0Dh,0Ah,0Dh,0Ah,' E32.EXE version 1.32',0Dh,0Ah db ' Copyright (C) 1995 Douglas Herr',0Dh,0Ah,'$' exit_mess db ' Quit E32 (Y/N)?',0 verify_mess db ' Lose changes (Y/N)?',0 no_file_name db '<no file name>',0 ; default colors used by GET_SCREEN_DATA public default_normal default_normal db 17h default_inverse db 70h default_warning db 0Ch columns dw 0 rows dw 0 screen_addr dd ? normal db 23 inverse db 70h warning db 0Ch screen_data_size equ $-columns mouse_on db 0 key_status db 0FFh insert_mode db ? undo_buffer dd ? undo_length dd 0 paste_buffer dd 0 ; near pointer to paste buffer valid_keys db 59,60,61,62,63 db 64,65,66,67,68 db 104,105,106,107,108 db 109,110,111,112,113 db 71,72,73,75,77 db 79,80,81,82,83 db 115,116,117,118,132 db 99,100,101,102,103 db 84,97,98,93,90 nul dw 0,0 dispatch_table dd quit, offset undo, offset print, offset mark dd offset cut, offset paste, offset save dd offset del_eol, offset del_l, offset udel_l dd new, screen_rows, ffeed, copy, dosshell dd upcase, load, screen_columns, locase, search dd home, up, pgup, left, right dd endd, down, pgdn, cursoron, del_char dd word_left, word_right, del_eol, bottom, top dd window_mode,switch, swapmode, goto, search_again dd setup, pushpos, poppos, replace, merge drive_error db 'Drive not ready: retry? (Y/N)',0 verify_msg db 'Lose changes?',0 int24h_msg dd offset @curseg:drive_error dd critical_exit sptr dd 0 ; storage for stack ptr at read_next_key sseg dw 0 file_data_ptr dd filename filename dd 0FFFFFFFFh ; pointer to current filename filesel dw 0FFFFh ; selector of file buffer filesiz dd 0 ; size of file buffersiz dd 0 ; size of file buffer cursor dd 0 top_of_screen dd 0 left_margin dw 0 file_row dd 1 push_offset dd 0 push_mode db 0 ; push status save_column db 0 save_row db 0 dirty_bits db 0 cur_posn dw 0100h mark_mode db 0 mark_start dd 0 mark_end dd 0 mark_home dd 0 count_rows db 0 count_start dd 0 count_bytes dd 0 first_row db 1 ; leave space at top for filename, etc display_mode db 0 ; assumes ASCII file file_data_len equ $-filename number_of_files equ 4 file2data label byte dd 0FFFFFFFFh ; pointer to current filename dw 0FFFFh ; selector of file buffer dd 0 ; size of file dd ? ; size of file buffer dd ? dd ? dw 0 dd 1 ; file_row dd 0 db 0 ; push status db ? db 0 db ? dw 0100h db 0 dd 0 dd 0 dd 0 db 0 dd 0 dd 0 db 1 ; leave space at top for filename, etc db 0 file3data label byte dd 0FFFFFFFFh ; pointer to current filename dw 0FFFFh ; selector of file buffer dd 0 ; size of file dd ? ; size of file buffer dd ? dd ? dw 0 dd 1 ; file_row dd 0 db 0 ; push status db ? db 0 db ? dw 0100h db 0 dd 0 dd 0 dd 0 db 0 dd 0 dd 0 db 1 ; leave space at top for filename, etc db 0 file4data label byte dd 0FFFFFFFFh ; pointer to current filename dw 0FFFFh ; selector of file buffer dd 0 ; size of file dd ? ; size of file buffer dd ? dd ? dw 0 dd 1 ; file_row dd 0 db 0 ; push status db ? db 0 db ? dw 0100h db 0 dd 0 dd 0 dd 0 db 0 dd 0 dd 0 db 1 ; leave space at top for filename, etc db 0 screen2_data label dword @curseg ends include codeseg.inc get_cmd_line: push ebp xor ebp,ebp ; initialize first file buffer xor ebx,ebx call swap_files ; get files on command line, last first mov ecx,number_of_files get0: push ecx mov ebx,ecx dec ebx ; offset format push ebx ; save parameter number mov eax,ebx ; copy to EAX for GETCMD call getcmd jecxz short get1 ; skip if no parameter call qfname mov edi,filename push ds pop es cld rep movsb mov al,cl stosb mov edx,filename call readfile inc ebp jnc short get1 dec ebp mov edx,filename mov byte ptr [edx],0 get1: pop ebx call swap_files pop ecx loop get0 cmp bp,2 jbe get2 mov byte ptr swapmode_prompt,'4' get2: pop ebp ret ; ; program starts here ; main32: ; lock program code and data mov bx,cs sys GetSelDet32 mov esi,edx mov ebx,ecx sys LockMem32 xor eax,eax mov cursor,eax mov top_of_screen,eax or dirty_bits,00100000b call get_screen_data cli mov sseg,ss mov sptr,esp sti ; set INT 24h address mov cx,cs lea edx,int24h mov bl,24h sys SetVect ; turn insert key toggle on mov ax,1 call insert ; get command line input call get_cmd_line ; create undo buffer mov ebx,128 sys GetMemNear mov undo_buffer,esi jmp short read_next_key critical_exit: cli mov ss,sseg mov esp,sptr sti read_next_key: call showpos mov fs,filesel cmp mark_mode,0 ; is the mark state on? je short mark_off ; if not, skip this or dirty_bits,4 ; refresh the current row mov dx,cur_posn cmp save_row,dh ; are we on the same row? je short same_row ; yup, redo the row only or dirty_bits,1 ; refresh the whole screen and dirty_bits,(NOT 4) ; cancel refresh row request same_row: mov eax,cursor ; get cursor position mov ebx,mark_home ; get the anchor mark position cmp eax,ebx ; moving backward in file? ja short s1 ; no: update mark_end & mark_start xchg eax,ebx ; switch start and end position s1: mov mark_end,eax ; store start and end marks mov mark_start,ebx mark_off: mov dx,cur_posn mov save_row,dh call cursoron test dirty_bits,4 or 1 ; need screen update? jz short check_shift_keys call display_screen check_shift_keys: call capslock shr mouse_on+1,1 jnc short s2 jmp read_next_key s2: call keyifwaiting jnc short process_key call topline jmp check_shift_keys process_key: ; turn mouse cursor off if it is on shr mouse_on,1 jnc short key0 push eax mov ax,2 int 33h pop eax key0: shr ah,1 jnc short normal_key call extended_key jc short exit jmp read_next_key normal_key: cmp al,08h ; backspace? jne short normal1 cmp cursor,0 ; start of file? je read_next_key ; yup, no backspace call left call del_char jmp read_next_key normal1: call insert_key jmp read_next_key x0: exit: lea edx,programmer mov ah,9 int 21h mov ax,4C00h int 21h subroutines proc near ; ; process extended key code ; extended_key: lea ebx,valid_keys call strchr jc short bad_key push ds pop es shl ax,2 ; make the code an offset movzx ebx,ax ; put offset in EBX jmp dispatch_table[ebx] bad_key: clc ret ; ; check status of CAPSLOCK, SHIFT, CTRL, ALT keys ; capslock: mov ax,0200h int 16h ; get key toggle status byte mov ah,al and ah,80h ; isolate INSERT status mov insert_mode,ah cmp key_status,al ; compare with previous and update mov key_status,al ; ZF = 1 if no changes jnz showfkey ; update prompt line if changed ret ; ; move cursor one word right ; word_right: ; ; move to end of current word ; exit when non-AlphaNum character found ; word_end_right: push fs pop es mov esi,cursor cmp esi,filesiz jae short wer9 movzx ax,byte ptr es:[esi] call isalphanumber jc short wer9 call right jmp word_end_right wer9: ; ; skip spaces if starting from a space character ; strip_space_right: push fs pop es mov esi,cursor cmp esi,filesiz jae short ssr9 movzx ax,byte ptr es:[esi] call isalphanumber jnc short ssr9 ; exit if Digit call right ; go to previous character jmp strip_space_right ssr9: clc ret ; ; move cursor one word left ; word_left: ; ; skip spaces if starting from a space character ; strip_space_left: push fs pop es mov esi,cursor test esi,esi jz short ssl9 ; done if at start of file movzx ax,byte ptr es:[esi-1] call isalphanumber jnc short ssl9 ; exit if Digit call left ; go to previous character jmp strip_space_left ssl9: ; ; go to start of current word ; scan off alpha and digit characters ; moving left ; word_start_left: push fs pop es mov esi,cursor test esi,esi jz short wsl9 ; done if at start of file movzx ax,byte ptr es:[esi-1] call isalphanumber jc short wsl9 ; continue if digit call left jmp word_start_left wsl9: clc ret isalphanumber: call isalpha jc isdigit ret ; ; INT 24h management ; int24h: sti ; Enable interrupts pushf ; Push flags pushad push ds push es mov ax,_NEAR mov ds,ax mov es,ax mov esi,int24h_msg mov ah,warning call yesno_message cmp al,'Y' je short int24exit jmp int24h_msg+4 int24exit: call working pop es pop ds popad popf ; Pop flags mov al,1 iretd ; Interrupt return ; ; exit E32, checking for unsaved changes ; quit: push dword ptr window_row mov window_row,1 mov key_status,0FFh ; force redo of F-key prompts ; check hidden file data areas for unsaved files q0: mov ecx,number_of_files q1: push ecx mov ebx,ecx dec ebx jnz short q1a ; skip if not last file mov ebx,number_of_files ; else retrieve initial file dec ebx q1a: call swap_files ; get file data test dirty_bits,10000000b ; continue if not changed jz short q2 call display_screen mov ah,warning mov esi,offset verify_mess call yesno_message cmp al,'Y' ; is the answer YES? je short q2 ; yup, check next file pop ecx jmp short dont_exit q2: pop ecx loop q1 lea esi,exit_mess ; prompt for 'EXIT' mov ah,inverse call yesno_message cmp al,'Y' ; is the answer YES? jne short dont_exit cmp columns,90 ; in RamFont mode? jne short exit100 call htext exit100: pop dword ptr window_row ; clear last row mov dh,byte ptr rows xor dl,dl call ucursoron inc dh lea esi,nul mov ah,normal call tprintce stc ; exit flag ret dont_exit: pop dword ptr window_row clc ; no exit flag ret ; ; PRINT_MSG ; print message at [ESI] on last row of screen ; public print_msg print_msg: mov ah,inverse mov dh,byte ptr rows inc dh xor dl,dl call tprintce ret subroutines endp @curseg ends end