include	clib.inc
ifdef __TE__
include	dobj.inc
include	tinfo.inc
include	ctype.inc
include	string.inc

	public	tistyle

ST_COUNT	= 9

S_STYLE		STRUC
st_line		DW ?	; current line index
st_bpax		DW ?	; current line adress
st_bpdx		DW ?
st_boff		DW ?	; offset start of visible line
st_bend		DW ?	; end of visible line
st_wbuf		DW ?	; screen buffer (int *)
st_type		DB ?	; current type
st_attr		DB ?	; current attrib
st_slen		DW ?	; length of line
st_string	DW ?	; offset of first word
st_quote_start	DW ?	; first " or ' in line
st_quote_end	DW ?	; last " or ' in line
S_STYLE		ENDS

_DATA	SEGMENT

format_label 	label word
	dw	tidoattrib	; 1. A Attrib
	dw	tidocontrol	; 2. O Control
	dw	tidoquote	; 3. Q Quote
	dw	tidonumber	; 4. D Digit
	dw	tidochar	; 5. C Char
	dw	tidostring	; 6. S String
	dw	tidostart	; 7. B Begin
	dw	tidoword	; 8. W Word
	dw	tidonested	; 9. N Nested

_DATA	ENDS

_TEXT	SEGMENT

	assume	bp: ptr S_STYLE

tisetat PROC
	push	ax
	push	bx
	mov	ax,di
	dec	ax   		; = offset in text line
	cmp	ax,[bp].st_boff
	jb	tisetat_end
	cmp	ax,[bp].st_bend
	ja	tisetat_end
	sub	ax,[bp].st_boff
	add	ax,ax
	mov	bx,[bp].st_wbuf
	add	bx,ax   	; = offset in screen line (*int)
	mov	al,[bp].st_attr
	xchg	bx,bp
	mov	[bp+1],al	; set attrib for this char
	mov	bp,bx
    tisetat_end:
	pop	bx
	pop	ax
	ret
tisetat	ENDP

tisetlen PROC			; Set length of string in SI to BX
	push	si		; Increase SI if string[0] == '"'
	xor	ax,ax		; if string[0] == '"' AH = '"' on return
	mov	bx,ax
	lodsb
	cmp	al,'"'
	jne	tisetlen_noquote
	mov	ah,al
    tisetlen_loop:
	lodsb
    tisetlen_noquote:
	or	al,al
	jz	tisetlen_end
	cmp	al,'"'
	je	tisetlen_end
	inc	bx
	jmp	tisetlen_loop
    tisetlen_end:
	pop	si
	cmp	ah,'"'
	jne	tisetlen_ret
	inc	si
    tisetlen_ret:
	or	bx,bx
	ret
tisetlen ENDP

tistrchr PROC			; scan for next char
	lodsb
	or	al,al
	jz	tistrchr_end
    tistrchr_scan:
	repne	scasb
	je	tistrchr_equal
	or	cx,cx
	ret
    tistrchr_equal:
	or	al,al
    tistrchr_end:
	ret
tistrchr ENDP

ticmpi PROC			; scan for next char no case
	push	bx
	lodsb
	or	al,al
	jz	ticmpi_nul
	call	isupper
	mov	bl,al
	jz	ticmpi_get
	or	bl,20h
    ticmpi_get:
	mov	al,es:[di]
	inc	di
	call	isupper
	jz	ticmpi_cmp
	or	al,20h
    ticmpi_cmp:
	cmp	al,bl
    ticmpi_end:
	pop	bx
	ret
    ticmpi_nul:
	or	bl,1
	jmp	ticmpi_end
ticmpi ENDP

tistrchri PROC			; scan for next char no case
	push	bx
	lodsb
	or	al,al
	jz	tistrchri_end
	push	ax
	call	isupper
	mov	bl,al
	jz	tistrchri_scan
	or	bl,20h
    tistrchri_scan:
	mov	al,es:[di]
	inc	di
	call	isupper
	jz	tistrchri_case
	or	al,20h
    tistrchri_case:
	cmp	al,bl
	je	tistrchri_equal
	dec	cx
	jnz	tistrchri_scan
	pop	ax
	pop	bx
	ret
    tistrchri_equal:
	pop	ax
	or	al,al
    tistrchri_end:
	pop	bx
	ret
tistrchri ENDP

ticmpsbi PROC
	push	cx
	push	si
	push	di
	push	bx
	mov	cx,bx
    ticmpsbi_lup:
	lodsb
	mov	bl,es:[di]
	inc	di
	cmp	ah,al		; AH == '"' or 0
	je	ticmpsbi_equal
	dec	cx
	jz	ticmpsbi_end
	or	bl,20h
	or	al,20h
	cmp	al,bl
	je	ticmpsbi_lup
	xor	cx,cx
	jmp	ticmpsbi_end
    ticmpsbi_equal:
	inc	cx
    ticmpsbi_end:
	pop	bx
	pop	di
	pop	si
	pop	cx
	ret
ticmpsbi ENDP

ticmpsb PROC
	push	cx
	push	si
	push	di
	mov	cx,bx
	repe	cmpsb
	cmp	ah,[si-1]	; AH == '"' or 0
	je	ticmpsb_equal
	xor	cx,cx
	jmp	ticmpsb_end
    ticmpsb_equal:
	inc	cx
    ticmpsb_end:
	pop	di
	pop	si
	pop	cx
	ret
ticmpsb ENDP

tistrstr PROC
	mov	di,dx
	mov	cx,[bp].st_slen
tistrstr ENDP

tistrstrdi PROC
	call	tisetlen
	jz	tistrstr_fail
	lodsb
tistrstrdi ENDP

tistrnext PROC
	repne	scasb
	je	tistrnext_test
	test	cx,cx
	jz	tistrstr_fail
    tistrnext_test:
	test	cx,cx
	jnz	tistrnext_cmp
	mov	cx,bx
    tistrnext_cmp:
	call	ticmpsb
	jz	tistrnext
	call	isquote
	jnz	tistrstr_fail
	or	al,al
	ret
tistrnext ENDP

tigetquote PROC
	mov	al,es:[si]
	inc	si
	or	al,al
	jz	tigetquote_end
	cmp	al,"'"
	je	tigetquote_quote
	cmp	al,'"'
	jne	tigetquote
    tigetquote_quote:
	or	al,al
    tigetquote_end:
	ret
tigetquote ENDP

isquote PROC
	push	si
	push	ax
	mov	ax,di
	dec	ax
	cmp	ax,[bp].st_quote_end
	ja	isquote_00
	mov	si,[bp].st_quote_start
	cmp	si,di
	jae	isquote_00
    isquote_l1:
	call	tigetquote
	jz	isquote_00
	cmp	di,si
	jb	isquote_00
	mov	ah,al
    isquote_l2:
	call	tigetquote
	jz	isquote_01
	cmp	ah,al
	jne	isquote_l2
	cmp	di,si
	ja	isquote_l1
    isquote_01:
	or	si,si
	jmp	isquote_end
    isquote_00:
	xor	ax,ax
    isquote_end:
	pop	ax
	pop	si
	ret
isquote ENDP

; 01,attrib[,0,char],0,0

tidoattrib PROC
	mov	al,[si-1]
	mov	bx,ss:tinfo
	mov	[bx].ti_stat,al
	mov	al,[si]
	or	al,al
	jz	tidoattrib_end
	mov	[bx].ti_stch,al
    tidoattrib_end:
	ret
tidoattrib ENDP

; 05: <attrib>,<'chars'>,0,0

tidochar PROC
	mov	di,dx
	mov	cx,[bp].st_slen
	call	tistrchr
	jnz	tidochar_set
	or	al,al
	jnz	tidochar
	ret
    tidochar_scan:
	repne	scasb
	je	tidochar_set
	or	cx,cx
	jz	tidochar
    tidochar_set:
	call	isquote
	jnz	tidochar_scan
	call	tisetat
	jmp	tidochar_scan
tidochar ENDP

tistrstr_fail PROC
	xor	al,al
	ret
tistrstr_fail ENDP

; 03ATstring,0

tidostart PROC
	call	tistrstr
	jz	tidostart_end
    tidostart_set:
	call	tisetat
	mov	al,es:[di]
	inc	di
	or	al,al
	jnz	tidostart_set
    tidostart_end:
	lodsb
	or	al,al
	jnz	tidostart_end
	cmp	[si],al
	jne	tidostart
	ret
tidostart ENDP

; 04ATstring1,0,string2,0,0

tifind	PROC PASCAL string, line:WORD
	push	si
	push	di
	push	bx
	call	tisetlen
	jz	tifind_end
	dec	line
    tifind_line:
	mov	si,string
	mov	ax,line
	push	ds
	push	ss
	pop	ds
	call	tigetline
	pop	ds
	jz	tifind_end
	push	dx
	push	ax
	mov	di,ax
	call	strlen
	jz	tifind_next
	mov	cx,ax
	add	di,ax
	dec	di
    tifind_scan:
	lodsb
	or	al,al
	jz	tifind_next
	std
	repne	scasb
	cld
	jne	tifind_next
	add	di,2
	mov	ah,0
	call	ticmpsb
	jnz	tifind_found
	sub	di,2
	dec	si
	jmp	tifind_scan
    tifind_next:
	dec	line
	jmp	tifind_line
    tifind_end:
	pop	bx
	pop	di
	pop	si
	ret
    tifind_found:
	mov	ax,line
	mov	dx,di
	jmp	tifind_end
tifind	ENDP

tinested PROC
	mov	di,dx
	push	si
	push	di
	push	bx
	mov	ax,[bp].st_line
	or	ax,ax
	jz	tinested_end
	push	si			; find last start-string
	push	ax
	call	tifind
	jz	tinested_notfound
	mov	di,ax			; match line
	mov	bx,dx			; match offset
    tinested_endword:
	lodsb
	or	al,al
	jnz	tinested_endword
	cmp	[si],al			; second word ?
	je	tinested_found		; start, no end - ok
	push	si			; DI end-string
	push	[bp].st_line
	call	tifind
	jz	tinested_found		; start+end
	cmp	ax,di
	ja	tinested_notfound
	jb	tinested_found
	cmp	dx,bx
	ja	tinested_notfound
    tinested_found:			; open, find end..
	mov	bx,1
	jmp	tinested_popl
    tinested_notfound:
	xor	bx,bx
    tinested_popl:
	mov	ax,[bp].st_line		; back to this line
	push	ds
	push	ss
	pop	ds
	call	tigetline
	pop	ds
	mov	es,dx
	mov	dx,ax
	or	bx,bx
    tinested_end:
	pop	bx
	pop	di
	pop	si
	ret
tinested ENDP

stgetnextarg:
	lodsb
	or	al,al
	jnz	stgetnextarg
	ret

tidonested PROC
	call	tisetlen		; BX to length of first arg
	jz	tistrstr_fail
	call	tinested		; find start condition
	mov	cx,[bp].st_slen		; CX to length of line
	jz	tidonested_line
	call	stgetnextarg
	jmp	tidonested_seek
    tidonested_next:
	mov	si,[bp].st_string
	mov	cx,[bp].st_slen
	sub	cx,di
	jle	tidonested_end
	call	tistrstrdi
	jz	tidonested_end
	jmp	tidonested_first
    tidonested_line:
	mov	si,[bp].st_string
	call	tistrstr
	jz	tidonested_end
    tidonested_first:
	call	tisetat
	lodsb
	inc	di
	or	al,al
	jz	tidonested_seek
	assert	cx,0,jne,"nested"
	dec	cx
	jnz	tidonested_first
	call	tisetat
    tidonested_seek:
	or	cx,cx
	jz	tidonested_end
	lodsb
	or	al,al
	jz	tidonested_end
	push	si
	push	di
	call	tistrnext
	mov	cx,di
	pop	di
	pop	si
	jz	tidonested_null
	sub	cx,di
	jle	tidonested_end
    tidonested_pad:
	call	tisetat
	inc	di
	dec	cx
	jnz	tidonested_pad
	add	cx,bx
	jz	tidonested_end
	dec	di
    tidonested_endtag:
	inc	di
	call	tisetat
	dec	cx
	jnz	tidonested_endtag
    tidonested_end:
	cmp	di,[bp].st_slen
	jb	tidonested_next
	ret
    tidonested_null:
	dec	di
	mov	cx,[bp].st_slen
	sub	cx,di
	jg	tidonested_endtag
	jmp	tidonested_end
tidonested ENDP

; 02FBstring1,0,string2,0,..,0

tiistart PROC		; test if di is the first char in a word
	push	ax	; di is match + 1, di-2 is char in front
	mov	ax,di
	dec	ax
	cmp	ax,[bp].st_bpax
	je	tiistart_ok	; start of line
	assertf	jnb,"tiistart"
	mov	al,es:[di-2]
	cmp	al,'_'
	je	@F
	call	getctype
	jz	tiistart_end
	and	ah,_UPPER or _LOWER or _DIGIT
	jz	tiistart_ok
    @@:
	xor	al,al
	jmp	tiistart_end
    tiistart_ok:
	inc	ax
    tiistart_end:
	pop	ax
	ret
tiistart ENDP

tidoword PROC		; match on all equal words if not inside quote
	mov	di,dx
	mov	cx,[bp].st_slen
	call	tisetlen
	jz	tidoword_end
    tidoword_scan:
	call	tistrchri
	jnz	tidoword_set
    @@:
	or	al,al
	jz	@F
	lodsb
	jmp	@B
    @@:
	lodsb
	or	al,al
	jz	tidoword_end
	dec	si
	jmp	tidoword
    tidoword_find:
	dec	si
	jmp	tidoword_scan
    tidoword_set:
	call	ticmpsbi
	jz	tidoword_find
	push	si
	push	bx
	push	ax
	call	isquote
	jnz	tidoword_pop	; = inside quote
	call	tiistart
	jz	tidoword_pop
	mov	al,es:[bx+di-1]
	call	islabel
	jnz	tidoword_pop
    @@:
	call	tisetat
	inc	di
	dec	bx
	jnz	@B
	dec	di
    tidoword_pop:
	pop	ax
	pop	bx
	pop	si
	jmp	tidoword_find
    tidoword_end:
	ret
tidoword ENDP

tidocontrol PROC		; match on all control chars
	mov	di,[bp].st_boff
    tidocontrol_loop:
	mov	al,es:[di]
	inc	di
	or	al,al
	jz	tidocontrol_end
	call	getctype
	or	ah,ah
	jz	@F
	and	ah,_CONTROL
	jz	tidocontrol_next
	cmp	al,TITABCHAR
	je	tidocontrol_next
	cmp	al,9
	je	tidocontrol_next
	mov	bx,ss:tinfo
	test	[bx].ti_flag,_T_SHOWTABS
	jz	tidocontrol_next
    @@:
	call	tisetat
    tidocontrol_next:
	cmp	di,[bp].st_bend
	jb	tidocontrol_loop
    tidocontrol_end:
	ret
tidocontrol ENDP

tidostring PROC		; match on all equal strings if not inside quote
	mov	di,dx
	mov	cx,[bp].st_slen
	call	tisetlen
	jz	tidostring_end
	call	tistrchr
	jnz	tidostring_set
    tidostring_next:
	or	al,al
	jz	@F
	lodsb
	jmp	tidostring_next
    @@:
	lodsb
	or	al,al
	jz	tidostring_end
	dec	si
	jmp	tidostring
    tidostring_scan:
	repne	scasb
	or	cx,cx
	jz	tidostring_next
    tidostring_set:
	call	ticmpsb
	jz	tidostring_scan
	push	si
	push	bx
	call	isquote
	jnz	tidostring_pop	; = inside quote
    @@:
	call	tisetat
	inc	di
	dec	bx
	jnz	@B
	dec	di
    tidostring_pop:
	pop	bx
	pop	si
	jmp	tidostring_scan
    tidostring_end:
	ret
tidostring ENDP

tidoquote PROC		; match on '"' and "'", fail on "\"C\""
	mov	di,[bp].st_bpax
    tidoquote_loop:
	mov	al,es:[di]
	inc	di
	or	al,al
	jz	tidoquote_end
	call	isquote
	jz	@F
	call	tisetat
    @@:
	cmp	di,[bp].st_bend
	jb	tidoquote_loop
    tidoquote_end:
	ret
tidoquote ENDP

tidonumber PROC		; match on 0x 0123456789ABCDEF and Xh
	mov	di,[bp].st_boff
    tidonumber_loop:
	mov	al,es:[di]
	inc	di
	call	getctype
	jz	tidonumber_end
	test	ah,_DIGIT
	jz	tidonumber_next
	call	isquote
	jnz	tidonumber_next
	call	tiistart
	jz	tidonumber_next
	mov	si,di
	cmp	al,'0'
	jne	@F
	mov	al,es:[si]
	inc	si
	or	al,20h
	cmp	al,'x'
	je	@F
	dec	si
    @@:
	mov	al,es:[si]
	inc	si
	call	getctype
	jz	tidonumber_set
	test	ah,_HEX
	jnz	@B
	or	al,20h
	cmp	al,'h'
	jne	@F
	inc	si
	jmp	tidonumber_set
    @@:
	and	ah,_UPPER or _LOWER
	jnz	tidonumber_next
    tidonumber_set:
	sub	si,di
    @@:
	call	tisetat
	inc	di
	dec	si
	jnz	@B
    tidonumber_next:
	cmp	di,[bp].st_bend
	jb	tidonumber_loop
    tidonumber_end:
	ret
tidonumber ENDP

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

tisetquote PROC	; "s\"C\"e"
	push	si
	xor	ax,ax
	mov	[bp].st_quote_start,ax
	mov	[bp].st_quote_end,ax
	mov	si,[bp].st_bpax
	push	[bp].st_bpdx
	push	si
	call	strlen		; set ES:SI line
	mov	cx,ax		; CX to eol
	add	cx,si
    tisetquote_00:
	xor	ax,ax
	call	tigetquote
	jz	tisetquote_end
	mov	ah,al
	mov	bx,si
	dec	bx
	mov	[bp].st_quote_end,cx
    @@:
	call	tigetquote
	jz	tisetquote_eof
	cmp	ah,al
	jne	@B
	cmp	si,cx
	jbe	tisetquote_00
	mov     ax,bx
	cmp	ax,cx
	jnb	@F
	mov	ax,[bp].st_bpax
    @@:
	mov	[bp].st_quote_start,ax
	mov	bx,si
    @@:
	call	tigetquote
	jz	@F
	mov	bx,si
	jmp	@B
    @@:
	mov	ax,bx
	dec	ax
	mov	[bp].st_quote_end,ax
    tisetquote_end:
	pop	si
	ret
    tisetquote_eof:
	mov	ax,[bp].st_bpax
	mov	[bp].st_quote_start,ax
	jmp	tisetquote_end
tisetquote ENDP

tistyle PROC PASCAL
local	style:S_STYLE
	push	si
	push	di
	push	bp
	push	ds
	lea	bp,style
	mov	[bp].st_line,bx		; line id
	mov	[bp].st_bpax,ax		; pointer to line
	mov	[bp].st_bpdx,di
	mov	[bp].st_wbuf,dx		; output buffer (*int) (SS)
	mov     [bp].st_slen,cx		; length of line
	add	ax,[si].ti_boff		; start of line
	mov     [bp].st_boff,ax
	mov	dx,ax
	add	ax,cx
	add	dx,TIMAXSCRLINE
	cmp	ax,dx
	jb	@F
	mov	ax,dx
	dec	ax
    @@:
	mov	[bp].st_bend,ax		; end of line
	mov	si,tinfo
	lds	si,[si].ti_style	; DS:SI style
	call	tisetquote
    tistyle_loop:
	lodsw
	mov	[bp].st_attr,ah
	mov	[bp].st_type,al
	or	al,al
	je	tistyle_end
	mov	ah,0
	dec	ax
	cmp	al,ST_COUNT
	jnb	tistyle_end
	add	ax,ax
	mov	di,ax
	mov	[bp].st_string,si
	mov	dx,[bp].st_bpax
	push	si
	call	ss:format_label[di]
	pop	si
    @@:
	lodsb
	or	al,al
	jnz	@B
	lodsb
	or	al,al
	jnz	@B
	jmp	tistyle_loop
    tistyle_end:
	pop	ds
	pop	bp
	pop	di
	pop	si
	ret
tistyle ENDP

_TEXT	ENDS
endif
	END
