home *** CD-ROM | disk | FTP | other *** search
- /*
- * In the dte editor, version 5.1, the end of file was marked with '\0'.
- * I have decided to use ^Z to mark the begin and end of files instead of '\0'.
- * That way, null characters are allowed as normal text characters. ^Z is used
- * to mark the end of strings in buffers instead of '\0'. The standard C
- * string library functions should not be used when dealing with text buffers.
- *
- * The often used string routines have been rewritten in assembly. When using
- * 16 bit processors, accessing memory by WORDs on WORD boundaries is twice
- * as fast as accessing memory by BYTEs. If a memory pointer is even then it
- * is WORD aligned. If a memory pointer is odd, do the first BYTE and then
- * the rest of the string is WORD aligned on an even boundary.
- *
- * Two routines were written to adjust the string pointers whenever they
- * approach the end of a segment. With these two routines, the code may
- * be compiled without the huge memory model. Another assembly routine was
- * written to compare physical memory locations. For example, all of these
- * pointers point to same physical memory address:
- *
- * 59a1:9122 == 58a1:a122 == 62a1:0122 = physical address 404,274
- *
- * An efficient way to compare far pointers is to convert them to either
- * unsigned long or long integers. Either one will do - their is no such
- * thing a negative physical memory address. A long int goes from
- * -2 billion to 2 billion, which leaves plenty of room to describe a physical
- * address, using a long, where the max is 1 MEG. I used unsigned long. When
- * adding or subtracting from the physical address of a pointer, we should
- * never, ever get a negative physical address. This is the concept behind the
- * function ptoul, which is short for pointer to unsigned long.
- *
- * With these functions written in assembly, this editor is fairly fast. I
- * feel the need for speed.
- *
- * New editor name: tde, the Thomson-Davis Editor.
- * Author: Frank Davis
- * Date: June 5, 1991
- *
- * This modification of Douglas Thomson's code is released into the
- * public domain, Frank Davis. You may distribute it freely.
- */
-
- #include "tdestr.h"
- #include "common.h"
- #include "tdefunc.h"
-
- /*
- * Name: cpf - check_pointer_forward
- * Purpose: To adjust a pointer if it is nearing end of a segment (within 16k)
- * Date: June 5, 1991
- * Passed: s: string pointer
- * Notes: To avoid a bunch of code generated for pointer arithmetic when using
- * the huge memory model, this routine adjusts a pointer when it
- * approaches the end of a segment.
- */
- text_ptr cpf( text_ptr s )
- {
- _asm {
- mov ax, WORD PTR s ; get offset of s
- mov dx, WORD PTR s+2 ; get segment of s
- cmp ax, 0xc000 ; are we within 16k of top of segment?
- jb get_out ; no, get out
- sub ax, 0x8000 ; yes, subtract 32k from offset
- add dx, 0x0800 ; add 0x0800 paragraphs to segment == 32k
- get_out:
- }
- }
-
- /*
- * Name: cpb - check_pointer_backward
- * Purpose: To adjust a pointer if it is nearing beginning of a segment (16k)
- * Date: June 5, 1991
- * Passed: s: string pointer
- * Notes: To avoid a bunch of code generated for pointer arithmetic when using
- * the huge memory model, this routine adjusts a pointer when it
- * approaches the beginning of a segment. Don't check NULL pointer.
- */
- text_ptr cpb( text_ptr s )
- {
- _asm {
- mov ax, WORD PTR s ; get offset of s
- mov dx, WORD PTR s+2 ; get segment of s
- cmp ax, 0 ; is offset of s == NULL?
- jne not_null ; no, check pointer
- cmp dx, 0 ; is segment of s == NULL?
- je get_out ; yes, don't check NULL pointer
- not_null:
- cmp ax, 0x4000 ; are we within 16k of beginning of segment?
- jae get_out ; no, get out
- add ax, 0x8000 ; yes, add 32k to offset
- sub dx, 0x0800 ; sub 0x0800 paragraphs from segment == 32k
- get_out:
- }
- }
-
- /*
- * Name: ptoul - pointer to unsigned long
- * Purpose: convert a far pointer to unsigned long integer
- * Date: June 5, 1991
- * Passed: s: string pointer
- * Notes: combine the offset and segment like so:
- * offset 0000
- * segment + 0000
- * =======
- * 00000
- * result is returned in dx:ax
- */
- unsigned long ptoul( text_ptr s )
- {
- _asm {
- mov ax, WORD PTR s ; ax = offset of s
- mov dx, WORD PTR s+2 ; dx = segment of s
- mov bx, dx ; put copy of segment in bx
- mov cl, 12 ; cl = decimal 12 - shift hi word 3 digits
- shr dx, cl ; convert to 'real segment'
- mov cl, 4 ; cl = 4 - shift hi word 1 digit
- shl bx, cl ; shift bx - line up on paragraph
- add ax, bx ; add low part of segment to offset
- adc dx, 0 ; if carry, bump to next 'real' segment
- }
- }
-
-
- /*
- * Name: nptop - normalize pointer to paragraph
- * Purpose: make the offset of a pointer no larger than a paragraph (16 bytes)
- * Date: June 5, 1991
- * Passed: s: string pointer
- * Notes: move all but the paragraph from the offset of the pointer to the
- * segment. The offset will be no larger than 16 bytes. Why? because
- * we can add up to 0xFFF0 reliably to a pointer in small, compact or
- * large model and not worry about segment wrap.
- *
- * offset abcx
- * segment 0000
- * =======
- * offset 000x
- * segment 0abc
- * result is returned in dx:ax
- */
- text_ptr nptop( text_ptr s )
- {
- _asm {
- mov ax, WORD PTR s ; ax = offset of s
- mov dx, WORD PTR s+2 ; dx = segment of s
- mov bx, ax ; put copy of offset in bx
- mov cl, 4 ; cl = 4 - shift lo word 1 digit
- shr bx, cl ; shift bx - line up on paragraph
- add dx, bx ; add hi part of offset to segment
- and ax, 0x000f ; mask out three digits in offset
- }
- }
-
- /*
- * Name: addltop - add long to pointer
- * Purpose: add long integer to a pointer
- * Date: June 5, 1991
- * Passed: l: long
- * p: text pointer
- * Returns: pointer + long integer
- * Notes: A long integer takes two WORDs. A far pointer takes two WORDs.
- * A long integer cannot be added directly to a far pointer.
- * This diagram may help explain better than I can write.
- *
- * far pointer 0000 offset
- * 0xxx segment
- * +
- * long integer 00000000 -throw away those three
- * ====== digits on long integer,
- * 0000 offset they have no effect
- * new far pointer 0xxx segment
- *
- * msw = Most Significant WORD
- * lsw = Least Significant WORD
- *
- * When working with the long integer, we don't need to worry about
- * the three x's on segment of the pointer. Add or subtract the lsw
- * of the long integer to/from the offset. If there is a carry,
- * it only affects the left most digit of the msw of the pointer.
- */
- text_ptr addltop( long l, text_ptr p )
- {
-
- if (l >= 0) {
- _asm {
- mov ax, WORD PTR p ; ax = offset of p
- mov dx, WORD PTR p+2 ; dx = segment of p
- mov bx, WORD PTR l+2 ; msw of l in bx
- add ax, WORD PTR l ; add lsw of p and lsw of l
- adc bx, 0 ; if carry, pointer in another segment
- mov cl, 12 ; cl = 12 - shift off 3 digits
- shl bx, cl ; only handle 1st part of msw of l
- add dx, bx ; add msw of p and msw of l
- }
- } else {
- l = -l; /* convert l to positive and subtract from pointer p */
- _asm {
- mov ax, WORD PTR p ; ax = offset of p
- mov dx, WORD PTR p+2 ; dx = segment of p
- mov bx, WORD PTR l+2 ; msw of l in bx
- mov cl, 12 ; cl = 12 - shift off 3 digits
- sub ax, WORD PTR l ; subtract low part of pointer
- adc bx, 0 ; if we borrowed then add it back to bx
- shl bx, cl ; only handle 1st digit of msw of l
- sub dx, bx ; subtract msw from segment of p
- }
- }
- }
-
-
- /*
- * Name: find_CONTROL_Z - assembler version, see commented C at end
- * Purpose: To determine the length of a line up to ^Z
- * Date: June 5, 1991
- * Passed: s: the line to be measured
- * Notes: DOS carried over ^Z to mark the end of files from CP/M. Since
- * it is the only character not allowed in regular text files. ^Z
- * can be used, instead of '\0', to mark the end of strings. All
- * ASCII characters, except ^Z, may be included in a text file.
- * However, none of the C string library functions should be used
- * when working with text. The string library functions can be used
- * on responses solicited from the user.
- * Returns: the length of the line
- */
- int find_CONTROL_Z( text_ptr s )
- {
- s = cpf( s );
- _asm {
- mov dx, ds ; keep ds in dx, MUST save data segment
- push si ; put copy of si on stack
-
- xor cx, cx ; cx = 0
- mov si, WORD PTR s ; put offset of s in si
- mov ax, WORD PTR s+2 ; get segment of s
- mov ds, ax ; else, segment in ds
- cmp si, 0 ; is offset of s == NULL?
- jne not_null ; no, find length
- cmp ax, 0 ; is segment of s == NULL?
- je get_out ; yes, line length = 0
- not_null:
- mov bl, CONTROL_Z ; keep Control Z in bl - eos marker
- mov ax, si ; pointer is ok, check for word align
- shr ax, 1 ; if [si] is odd, lsb is 1 - rotate to carry
- jnc top ; see if string is WORD aligned
- lodsb ; no, get a BYTE - now WORD aligned
- cmp al, bl ; is ds:[si] == ^Z?
- je get_out ; yes, have length, cx = 0
- inc cx ; increment length variable
- ALIGN 2
- top:
- lodsw ; string is WORD aligned
- cmp al, bl ; is lo BYTE == ^Z?
- je get_out ; yes, we have length
- inc cx ; no, increment counter
- cmp ah, bl ; now test higher BYTE, is it ^Z?
- je get_out ; yes, we have length
- inc cx ; no, increment length
- jmp SHORT top ; look at next two characters
- get_out:
- mov ax, cx ; put length in ax - as defined by Microsoft
- mov ds, dx ; get back data segment from dx
- pop si ; get back si from stack
- }
-
- /*
- int len = 0;
-
- while (*s != ^Z) {
- ++len;
- ++s;
- }
- return len;
- */
- }
-
-
- /*
- * Name: linelen - assembler version, see commented C at end of routine
- * Purpose: To determine the length of a line, up to either a \n or a
- * ^Z, whichever comes first.
- * Date: June 5, 1991
- * Passed: s: the line to be measured
- * Notes: Demonstrates 'lodsb' and 'lodsw'. Memory operations are most
- * efficient when working with WORDs. See if first BYTE in
- * string is WORD aligned. If it is then work with WORDs else
- * get the first BYTE and rest of string will be WORD aligned.
- * The 'mov' instruction could have been used, but 'lobsb' and
- * 'lodsw' automatically increment the memory pointer.
- * Returns: the length of the line
- */
- int linelen( text_ptr s )
- {
- s = cpf( s );
- _asm {
- mov dx, ds ; keep ds in dx, MUST save data segment
- push si ; save si on stack
-
- xor cx, cx ; cx = 0
- mov si, WORD PTR s ; put offset of s in si
- mov ax, WORD PTR s+2 ; get segment of s
- mov ds, ax ; else, segment in ds
- cmp si, 0 ; is offset of s == NULL?
- jne not_null ; no, find length
- cmp ax, 0 ; is segment of s == NULL?
- je get_out ; yes, line length = 0
- not_null:
- mov bl, '\n' ; keep new line character in bl
- mov bh, CONTROL_Z ; keep Control Z in bh - DOS eof marker
- mov ax, si ; pointer is ok, check for word align
- shr ax, 1 ; if [si] is odd, lsb is 1 - rotate to carry
- jnc top ; see if string is WORD aligned
- lodsb ; no, get a BYTE - now WORD aligned
- cmp al, bl ; is BYTE == '\n'?
- je get_out ; yes, have length, cx = 0
- cmp al, bh ; is ds:[si] == ^Z?
- je get_out ; yes, have length, cx = 0
- inc cx ; increment length variable
- ALIGN 2
- top:
- lodsw ; string is WORD aligned
- cmp al, bl ; test lower BYTE, is it '\n'
- je get_out ; yes, we have length
- cmp al, bh ; no, test for ^Z
- je get_out ; yes, we have length
- inc cx ; no, increment counter
- cmp ah, bl ; now test higher BYTE, is it '\n'
- je get_out ; yes, we have length
- cmp ah, bh ; is it ^Z
- je get_out ; yes, we have length
- inc cx ; no, increment length
- jmp SHORT top ; look at next two characters
- ALIGN 2
- get_out:
- mov ax, cx ; put length in ax - as defined by Microsoft
- mov ds, dx ; get back data segment from dx
- pop si ; get back si from stack
- }
-
- /*
- int len = 0;
-
- while (*s && *s != '\n') {
- ++len;
- ++s;
- }
- return len;
- */
- }
-
-
- /************* prelinelen is not used, but left in for reference **********/
- /*
- * Name: prelinelen
- * Purpose: To determine the length of a line, from the current position
- * backwards to either a \n or a ^Z, whichever comes first.
- * Date: June 5, 1991
- * Passed: s: the line to be measured
- * Returns: the length of the line up to the current position
- * Notes: It is assumed there will be a "terminating" ^Z before the
- * start of the first line.
- */
- /*
- int prelinelen( text_ptr s )
- {
- s = cpb( s );
- _asm {
- push di ; put copy of di on stack
-
- xor ax, ax ; ax = 0, keep string length in ax
- mov di, WORD PTR s ; get offset of string
- mov dx, WORD PTR s+2 ; get segment of string
- mov es, dx ; put segment in es
- cmp di, 0 ; is offset of string == NULL?
- jne not_null ; no, do string stuff
- cmp dx, 0 ; is, segment of string == NULL?
- je get_out ; yes, don't do NULL string
- not_null:
- dec di ; look at previous character
- ALWORD: dec di ; get ready to check for WORD align
- mov bl, '\n' ; keep '\n' in bl
- mov bh, CONTROL_Z ; keep ^Z in bh
- mov dx, di ; pointer is ok, check for WORD align
- shr dx, 1 ; if [di] is odd, lsb is 1 - rotate to carry
- jnc top ; string is WORD aligned
- inc di ; fix the second decrement - see ALWORD
- mov dl, BYTE PTR es:[di] ; get a BYTE - put in DL
- cmp dl, bl ; is it '\n'
- je get_out ; yes, get out - count = 0
- cmp dl, bh ; is it ^Z
- je get_out ; yes, get out - count = 0
- inc ax ; increment length counter
- dec di ; pointer was BYTE aligned, dec pointer
- dec di ; pointer is now WORD aligned
- ALIGN 2
- top:
- mov dx, WORD PTR es:[di] ; load WORD - hi BYTE is next
- cmp dh, bl ; is hi BYTE (next char) '\n'?
- je get_out ; yes, get out - count already in ax
- cmp dh, bh ; is hi BYTE (next char) ^Z?
- je get_out ; yes, get out - count already in ax
- inc ax ; increment character counter
- cmp dl, bl ; now check lo BYTE, is it '\n'?
- je get_out ; yes, get out - count is in ax
- cmp dl, bh ; is lo BYTE ^Z?
- je get_out ; yes, get out - count is in ax
- inc ax ; increment character counter
- dec di ; decrement pointer
- dec di ; align pointer on WORD
- jmp SHORT top ; test next 2 characters
- get_out:
- pop di ; get back di from stack
- }
- int len = 0;
-
- while (*--s != CONTROL_Z && *s != '\n')
- ++len;
- return len;
- }
- */
- /************************** prelinelen is not used ************************/
-
-
- /*
- * Name: find_next
- * Purpose: To find the first character in the next line after the starting
- * point.
- * Date: June 5, 1991
- * Passed: s: the starting point
- * Returns: the first character in the next line
- * Notes: This function goes faster if machine works with WORDs. See if
- * first BYTE in string is WORD aligned. If it is not, get first
- * BYTE in string then the rest of string is WORD aligned.
- * Code added at end to adjust segment:offset if needed.
- */
- text_ptr find_next( text_ptr s )
- {
- _asm {
- push ds ; save ds on stack
- push si ; save si on stack
-
- mov si, WORD PTR s ; load offset of s
- mov ax, WORD PTR s+2 ; load segment of s
- mov ds, ax
- cmp si, 0 ; is offset of string == NULL?
- jne not_null ; no, do string stuff
- cmp ax, 0 ; is segment of string == NULL?
- je return_null ; yes, return NULL if string is NULL
- not_null:
- mov bl, '\n' ; keep '\n' in bl
- mov bh, CONTROL_Z ; keep ^Z in bh
- mov ax, si ; move offset of si to ax
- shr ax, 1 ; shift right into carry flag
- jnc top ; is string WORD aligned?
- lodsb ; no, get a BYTE
- cmp al, bl ; is it '\n'?
- je next_even ; yes, si already incremented by lodsb
- cmp al, bh ; is it ^Z?
- je return_null ; yes, return NULL
- ALIGN 2
- top:
- lodsw ; string is WORD aligned, get two BYTEs
- cmp al, bl ; is next BYTE == '\n'?
- je next_odd ; yes, since si inc for WORD (lodsw) - dec di
- cmp al, bh ; is next BYTE == ^Z?
- je return_null ; yes, return NULL
- cmp ah, bl ; is next BYTE in AH == '\n'?
- je next_even ; yes, si is OK - return pointer to next BYTE
- cmp ah, bh ; is next BYTE in AH == ^Z?
- je return_null ; yes, return NULL
- jmp SHORT top ; look at next WORD
- ALIGN 2
- return_null:
- xor ax, ax ; clear ax - offset = NULL
- xor dx, dx ; clear dx - segment = NULL
- jmp SHORT get_out ; return text_ptr in dx:ax - see Microsoft
- ALIGN 2
- next_odd:
- dec si ; 'lodsw' went one BYTE too far - so dec si
- next_even:
- mov ax, si ; ds:si now points to next line, load ax
- mov dx, ds ; load dx with segment of next BYTE
- cmp ax, 0xc000 ; are we within 16k of segment?
- jb get_out ; no, get out
- sub ax, 0x8000 ; yes, subtract 32k from offset
- add dx, 0x0800 ; add 0x0800 paragraphs to segment
- get_out:
- pop si ; get back si from stack
- pop ds ; get back ds from stack
- }
- /*
- while (*s && *s != '\n' && *s != CONTROL_Z)
- ++s;
- if (*s)
- return ++s;
- else
- return NULL;
- */
- }
-
-
- /*
- * Name: find_prev
- * Purpose: To find the start of the line before the current line.
- * Date: June 5, 1991
- * Passed: current: the current line
- * Returns: the start if the previous line
- * Notes: current must be at the start of the current line to begin with.
- * There must be a ^Z preceding the first line.
- * This function goes faster if machine works with WORDs. See if
- * first BYTE in string is WORD aligned. If it is not, get first
- * BYTE in string then the rest of string is WORD aligned.
- * The test for '\n' will pass a lot more than the test for
- * ^Z. Set up the WORD align stuff first.
- * Since we are searching, by WORDs, backwards, the hi BYTE is the
- * prev BYTE and the al BYTE is two prev BYTEs (make sense?).
- * Code added at end to adjust segment:offset if needed.
- */
- text_ptr find_prev( text_ptr current )
- {
- _asm {
- push di ; save di on stack
-
- mov di, WORD PTR current ; load offset of current
- DECR1: dec di ; decrement it
- mov ax, WORD PTR current+2 ; load segment of current
- mov es, ax
- cmp di, 0 ; is offset of string == NULL?
- jne not_null ; no, do string stuff
- cmp ax, 0 ; is segment of string == NULL?
- je return_null ; yes, return NULL if string NULL
- not_null:
- mov bl, '\n' ; keep '\n' in bl
- mov bh, CONTROL_Z ; keep ^Z in bh
- mov ax, di ; put copy of offset in ax
- shr ax, 1 ; shift right thru carry flag
- jnc on_boundary ; if no carry, string is WORD aligned
- ;
- ; if we were to dec the pointer twice, it would be WORD aligned with the
- ; '--current' BYTE in the AH register. if ^Z test fails, might as well
- ; test the BYTE in the AL register.
- ;
- DECR2: dec di ; dec offset one more so it is WORD aligned
- mov ax, WORD PTR es:[di] ; might as well load WORD
- cmp ah, bh ; is prev BYTE ^Z?
- je return_null ; yes, return NULL
- ;
- ; now we are in the for loop - see commented C code at bottom.
- ; 'on_boundary' is not part of the for loop so jump past it if needed.
- ;
- cmp al, bl ; is prev BYTE '\n'?
- je inc_pointer ; yes, increment the pointer and return
- cmp al, bh ; is it ^Z?
- je inc_pointer ; yes, increment the pointer and return
- jmp SHORT for_loop ;no, pointer is now WORD aligned - do for loop
- ALIGN 2
- ;
- ; the string ended on an odd boundary and the DECR1 has now aligned the
- ; string on a WORD. if we load a WORD, the '--current' BYTE would be in the
- ; AL register.
- ;
- on_boundary:
- mov ax, WORD PTR es:[di] ; load --current, aligned on WORD
- cmp al, bh ; is --current ^Z?
- je return_null ; yes, return NULL
- ;
- ; now we are in the for loop and string is guaranteed WORD aligned.
- ; IMPORTANT: there are 2 cases if the test for '\n' or ^Z pass.
- ; 1) AH passed, so di must be increment twice for '++current'
- ; 2) AL passed, inc di once for '++current'
- ;
- ALIGN 2
- for_loop:
- dec di ; decrement di twice so it will be
- dec di ; WORD aligned
- mov ax, WORD PTR es:[di] ; string is WORD aligned
- cmp ah, bl ; is --current '\n'?
- je next_even ; yes, increment di twice to return ++current
- cmp ah, bh ; is --current ^Z?
- je next_even ; yes, increment di twice to return ++current
- cmp al, bl ; look at low part of WORD, is it '\n'?
- je inc_pointer ; yes, increment di once to return ++current
- cmp al, bh ; is low part of WORD ^Z?
- je inc_pointer ; yes, increment di once to return ++current
- jmp SHORT for_loop ; get next WORD
- ALIGN 2
- return_null:
- xor ax, ax ; clear ax - offset = NULL
- xor dx, dx ; clear dx - segment = NULL
- jmp SHORT get_out ; return text_ptr in dx:ax - see Microsoft
- ALIGN 2
- next_even:
- inc di ; di is a WORD too far - inc di
- inc_pointer:
- inc di ; ++current
- mov ax, di ; put offset in ax
- mov dx, es ; put segment in dx, return dx:ax - Microsoft
- cmp ax, 0x4000 ; are we within 16k of segment?
- jae get_out ; no, get out
- add ax, 0x8000 ; yes, add 32k to offset
- sub dx, 0x0800 ; sub 0x0800 paragraphs to segment
- get_out:
- pop di ; get back di from stack
- }
-
- /*
- if (*--current == ^Z)
- return NULL;
- for (;;) {
- if (*--current == '\n' || *current == ^Z)
- return ++current;
- }
- */
- }
-
- /*
- * Name: update_line
- * Purpose: Display the current line in window
- * Date: June 5, 1991
- * Passed: window: information allowing access to the current window
- * Returns: none
- * Notes: Show string starting at column zero and if needed blank rest
- * of line. Put max_col in cx and count down. When we run into
- * '\n', cx contains number of columns to blank out. Use the
- * fast 'rep stosw' to clear the end of line.
- */
- void update_line( windows *window )
- {
- text_ptr text; /* current character of orig begin considered */
- char far *screen_ptr;
- int off;
- int attr;
- int line;
- int col;
- int bc, ec;
- int normal, block;
- int max_col;
- int block_line;
- int len;
- int c;
- long rline;
- file_infos *file;
-
- file = window->file_info;
- max_col = g_display.ncols;
- line = window->cline;
- normal = g_display.text_color;
- block = g_display.block_color;
- /* 160 = 80 chars + 80 attr for each line */
- screen_ptr = g_display.display_address;
- off = line * 160;
- text = cpf( window->cursor );
- if (g_status.copied && ptoul( text ) == ptoul( g_status.buff_line ))
- text = g_status.line_buff;
- bc = window->bcol;
- if (bc > 0) {
- if ((col = linelen( text )) < bc)
- bc = col;
- text += bc;
- }
- rline = window->rline;
- if (file->block_type && rline >= file->block_br && rline <= file->block_er)
- block_line = TRUE;
- else
- block_line = FALSE;
- if (block_line == TRUE && file->block_type == BOX) {
- len = linelen( text );
- bc = file->block_bc - window->bcol;
- ec = file->block_ec - window->bcol;
-
- _asm {
- push ds ; MUST save ds - push it on stack
- push si ; save si on stack
- push di ; save di on stack
- ;
- ; set up local register variables
- ;
- mov ax, WORD PTR bc ; get beginning column
- mov bl, al ; keep it in bl
- mov ax, WORD PTR ec ; get ending column
- mov bh, al ; keep it in bh
- mov ax, WORD PTR normal ; get normal attribute
- mov dl, al ; keep it in dl
- mov ax, WORD PTR block ; get block attribute
- mov dh, al ; keep it in dh
- mov ax, WORD PTR max_col ; get max number columns on screen
- mov ch, al ; keep it in ch
- xor cl, cl ; col = 0, keep col in cl
- ;
- ; load screen and text pointer
- ;
- mov di, WORD PTR screen_ptr ; load offset of screen ptr
- add di, WORD PTR off ; add offset of line
- mov ax, WORD PTR screen_ptr+2 ; load segment of screen ptr
- mov es, ax
- mov si, WORD PTR text ; load offset of text ptr
- mov ax, WORD PTR text+2 ; load segment of text ptr
- mov ds, ax ; move segment of text in ds
- cmp si, 0 ; is offset of text ptr == NULL?
- jne not_null ; no, output string
- cmp ax, 0 ; is segment of text ptr == NULL?
- je block_eol ; yes, clear end of line
- not_null:
- ALIGN 2
- top:
- cmp cl, ch ; is col == max_col 0?
- je getout ; yes, thru with line
- lodsb ; get next char in string
- cmp al, CONTROL_Z ; is it ^Z?
- je block_eol ; yes, must check block past ^Z
- cmp al, '\n' ; is it '\n'?
- je block_eol ; yes, must check block past '\n'
- mov ah, dl ; assume normal attribute
- cmp cl, bl ; is col < bc? (less than beginning col)
- jl ch_out1 ; yes, show char and normal attribute
- cmp cl, bh ; is col > ec? (greater than ending col)
- jg ch_out1 ; yes, show char and normal attribute
- mov ah, dh ; must be in a block - show block attribute
- ch_out1:
- stosw ; else show char on screen
- inc cl ; ++col
- jmp SHORT top ; get another character
- ALIGN 2
- block_eol:
- mov al, ' ' ; clear rest of line w/ spaces
- b1:
- mov ah, dl ; assume normal attribute
- cmp cl, bl ; is col < bc? (less than beginning col)
- jl ch_out2 ; yes, show char and normal attribute
- cmp cl, bh ; is col > ec? (greater than ending col)
- jg ch_out2 ; yes, show char and normal attribute
- mov ah, dh ; must be in a block - show block attribute
- ch_out2:
- stosw ; write blank and attribute to screen
- inc cl ; ++col
- cmp cl, ch ; is col == max_col?
- jl b1 ; while less output block
- getout:
- pop di
- pop si
- pop ds
- }
- /*
- for (col=0; col < max_col; col++) {
- attr = normal;
- if (col >= bc && col <= ec)
- attr = block;
- if (col < len)
- c = text[col];
- else
- c = ' ';
- update_char( c, col, line, attr );
- }
- */
- } else {
- if (block_line)
- attr = block;
- else
- attr = normal;
- _asm {
- mov dx, ds ; MUST save ds - keep it in dx
- push di ; save di on stack
- push si ; save si on stack
-
- mov bx, WORD PTR attr ; keep attribute in bl
- mov bh, '\n' ; keep '\n' in bh
- mov cx, WORD PTR max_col ; keep max_col in cx
- mov di, WORD PTR screen_ptr ; load offset of screen ptr
- add di, WORD PTR off ; add offset of line
- mov ax, WORD PTR screen_ptr+2 ; load segment of screen ptr
- mov es, ax
- mov si, WORD PTR text ; load offset of text ptr
- mov ax, WORD PTR text+2 ; load segment of text ptr
- mov ds, ax ; move segment of text in ds
- cmp si, 0 ; is offset of pointer == NULL?
- jne nnot_null ; no, output string
- cmp ax, 0 ; is segment of pointer == NULL?
- je clreol ; yes, then clear rest of line
- nnot_null:
- mov ah, bl ; get attribute
- ALIGN 2
- topp:
- or cx, cx ; col == 0 ?
- je getoutt ; yes, thru with line
- lodsb ; get next char in string
- cmp al, CONTROL_Z ; is it ^Z
- je clreol ; yes, clear end of line
- cmp al, bh ; is it '\n'
- je clreol ; yes, clear end of line
- stosw ; else show char on screen
- dec cx ; --col, count down from max_column
- jmp SHORT topp ; get another character
- ALIGN 2
- clreol:
- mov ah, bl ; get attribute
- mov al, ' ' ; clear eol with ' '
- rep stosw ; count is in cx - set rest of line to ' '
- getoutt:
- pop si
- pop di
- mov ds, dx
- }
- }
- /*
- if (orig != NULL) {
- text = orig;
- screen_ptr = g_display.display_address + line * 160 + col * 2;
- for (; *text != '\n' && *text != ^Z && col < max_col; text++, col++) {
- *screen_ptr++ = *text;
- *screen_ptr++ = attr;
- }
- }
- if (col < max_col)
- eol_clear( col, line, attr );
- */
- }
-
-
- /*
- * Name: update_char
- * Purpose: display one character in window
- * Date: June 5, 1991
- * Passed: window: information allowing access to the current window
- * c: character to output to screen
- * col: col to display character
- * line: line number to display character
- * Returns: none
- */
- void update_char( windows *window, int c, int col, int line )
- {
- char far *screen_ptr;
- int off;
- int attr;
- long rline;
- file_infos *file;
-
- file = window->file_info;
- rline = window->rline;
- attr = g_display.text_color;
- if (file->block_type) {
- if (rline >= file->block_br && rline <= file->block_er) {
- if (file->block_type == LINE)
- attr = g_display.block_color;
- else if (window->rcol>=file->block_bc && window->rcol<=file->block_ec)
- attr = g_display.block_color;
- }
- }
- screen_ptr = g_display.display_address;
- off = line * 160 + col * 2;
-
- _asm {
- mov dx, di ; save di in dx
-
- mov di, WORD PTR screen_ptr ; load offset of screen ptr
- add di, WORD PTR off ; add offset of line:col
- mov ax, WORD PTR screen_ptr+2 ; load segment of screen ptr
- mov es, ax
- mov bx, WORD PTR attr ; get attribute
- mov ah, bl ; put in ah
- mov bx, WORD PTR c ; get character
- mov al, bl ; put in al
- stosw ; show char on screen
-
- mov di, dx ; get back di from dx
- }
-
- /*
- screen_ptr = g_display.display_address + line * 160 + col * 2;
- *screen_ptr++ = c;
- *screen_ptr = attr;
- */
- }
-
-
- /*
- * Name: c_output
- * Purpose: To make as few changes as possible to cause the current line
- * to be what it should be.
- * Date: June 5, 1991
- * Passed: c: character to output to screen
- * col: col to display character
- * line: line number to display character
- * attr: attribute of character
- * Returns: none
- */
- void c_output( int c, int col, int line, int attr )
- {
- char far *screen_ptr;
- int off;
-
- screen_ptr = g_display.display_address;
- off = line * 160 + col * 2;
-
- _asm {
- mov dx, di ; save di in dx
-
- mov di, WORD PTR screen_ptr ; load offset of screen ptr
- add di, WORD PTR off ; add offset of line:col
- mov ax, WORD PTR screen_ptr+2 ; load segment of screen ptr
- mov es, ax
- mov bx, WORD PTR attr ; get attribute
- mov ah, bl ; put in ah
- mov bx, WORD PTR c ; get character
- mov al, bl ; put in al
- stosw ; show char on screen
-
- mov di, dx ; get back di from dx
- }
-
- /*
- screen_ptr = g_display.display_address + line * 160 + col * 2;
- *screen_ptr++ = c;
- *screen_ptr = attr;
- */
- }
-
-
- /*
- * Name: s_output
- * Purpose: To output character string at the cursor position, advancing
- * the cursor by the length of the string.
- * Date: June 5, 1991
- * Passed: s: string to output
- * Notes: This function is used to output most strings not part of file text.
- */
- void s_output( char far *s, int line, int col, int attr )
- {
- char far *screen_ptr;
- int off;
- int max_col;
-
- max_col = g_display.ncols;
- screen_ptr = g_display.display_address;
- off = line * 160 + col * 2;
-
- _asm {
- push ds ; save ds on stack
- push di ; save di on stack
- push si ; save si on stack
-
- mov bx, WORD PTR attr ; keep attribute in bx
- mov cx, WORD PTR col ; put cols in cx
- mov dx, WORD PTR max_col ; keep max_col in dx
- mov di, WORD PTR screen_ptr ; load offset of screen ptr
- add di, WORD PTR off ; add offset of line:col
- mov ax, WORD PTR screen_ptr+2 ; load segment of screen ptr
- mov es, ax
- mov si, WORD PTR s ; load offset of string ptr
- or si, si ; is it == NULL?
- je getout ; yes, no output needed
- mov ax, WORD PTR s+2 ; load segment of string ptr
- or ax, ax ; is pointer == NULL?
- je getout ; yes, no output needed
- mov ds, ax ; load segment of text in ds
- mov ah, bl ; put attribute in AH
- top:
- cmp cx, dx ; col < max_cols?
- jge getout ; no, thru with line
- lodsb ; get next char in string - put in al
- or al, al ; is it '\0'
- je getout ; yes, end of string
- cmp al, '\n' ; is it '\n'?
- je getout ; yes, end of string
- stosw ; else show attr + char on screen (ah + al)
- inc cx ; col++
- jmp SHORT top ; get another character
- getout:
- pop si ; get back si
- pop di ; get back di
- pop ds ; get back ds
- }
-
- /*
- screen_ptr = g_display.display_address + line * 160 + col * 2;
- max_col = g_display.ncols;
- while (*s && col < max) {
- *screen_ptr++ = *s++;
- *screen_ptr++ = attr;
- }
- */
- }
-
-
- /*
- * Name: eol_clear
- * Purpose: To clear the current line from the cursor to the end of the
- * line to normal spaces.
- * Date: June 5, 1991
- * Notes: Basic assembly - comments should be enough explanation.
- */
- void eol_clear( int col, int line, int attr )
- {
- int max_col;
- char far *screen_ptr;
- int off;
-
- max_col = g_display.ncols;
- screen_ptr = g_display.display_address;
- off = line * 160 + col * 2;
-
- _asm {
- push di ; save di on stack
-
- mov bx, WORD PTR attr ; keep attribute in bx
- mov dx, WORD PTR col ; put cols in dx
- mov cx, WORD PTR max_col ; put max_col in cx
- cmp dx, cx ; max_cols < cols?
- jge getout ; no, thru with line
- sub cx, dx ; number of column to clear
- mov di, WORD PTR screen_ptr ; load offset of screen ptr
- add di, WORD PTR off ; add offset of line:col
- mov ax, WORD PTR screen_ptr+2 ; load segment of screen ptr
- mov es, ax
- mov ah, bl ; get attribute in ah
- mov al, ' ' ; store ' ' in al
- rep stosw ; clear to end of line
- getout:
- pop di ; get back di from stack
- }
-
- /*
- for (; col < g_display.ncols; col++) {
- *p++ = ' ';
- *p++ = attr;
- }
- */
- }