; ---------------------------------------------------------------------------
; S t r i n g   c h e c k e r
;
; Функция, возвращающая тип символа в строке _независимо_от_языка_ 
; (русский/английский) для 866cp.
;
; Возвращаемые значения:
; 00 - error
; 01 - ни один из следующих
; 02 - цифра
; 03 - заглавная буква
; 04 - строчная буква
;
; Заменяет собой функции Clipper IsDigit(szLine), IsAlpha(szLine), 
;                                IsLower(szLine), IsUpper(szLine)
;
; int WhatIs (char szLine, int iNum) 
;
; char szLine - строка 
; int  iNum   - номер проверяемого символа в строке. Если не указан - то первый
;
; (с) WhiteUnicorn, 31.01.2000, Freeware, WhiteUnicorn@mail.ru
; ---------------------------------------------------------------------------
 
include	extenda.inc

CLpublic <WhatIs>

;DGROUP	group MyDataSeg		; Вроде как тут легко можно обойтись и без этого,
;MyDataSeg	segment '_DATA'		; но на всякий случай просто комментарю...

;	Мессаги для еррор-блока:
;	szAsmLine	db  0dh, 0ah, 'Print from Asm$'
;	szPcount0	db  0dh, 0ah, 'Pcount = 0$'
;	szStrVoid	db  0dh, 0ah, 'szLine is NULL$'
	
;	iLine_len	dw  ?			; Длина переданной строки
;	WhatFunc	db  00h		; Какая функция вызвана
;	InputBuffer	db  0ffh dup (?)	; Сюда затаскиваем исходную строку,
;	ResBuffer	db  0ffh dup (?)	; а тут соберется результирующая

;MyDataSeg	ends

; ---------------------------------------------------------------------------
; F u n c t i o n 
; int WhatIs (char szLine, int iNum)
; Определяем тип указанного (или первого, если не указан :) символа
;
; ---------------------------------------------------------------------------

CLfunc int WhatIs <char szLine, int iNum>

 CLcode
;	int	03h				; Это для отладчика подарок :)

;	assume	ds:DGROUP, es:DGROUP
	
	xor	dx,dx				; Если что-то не сработает, то так ноль и останется

 TestParam:					; Проверяем количество входных параметров
	cmp	PCOUNT,01h
	jnb	TestLine
;	lea	dx,szPcount0
	jmp	Exit

 TestLine:					; и их качество :)
	TESTNUL	szLine
	jnz	StartWork
;	lea	dx,szStrVoid
	jmp	Exit	

 StartWork:
 	push	ds				; Иначе будет очень плохо...
	lds	si, szLine
	mov	cx, word ptr ds:[si-02h]; Тут должна лежать длина строки (с учетом 0 символа)
	cmp	PCOUNT,02h			; Если номер не задан, то берем первый символ
	jb	Working
	mov	bx,iNum
	cmp	bx,cx				; Проверяем, не вылазим ли мы за пределы строки
	jnb	Exit
	add	si,bx				; Передвигаем указатель на нужный символ
	sub	si,1				; А это потому, что в Clipper массивы начинаются с 1 :)

 Working:
	lodsb					; Грузим символ и проверяем его
	call	CheckSymbol

; ErrorMes:
;	mov	ah,09h
;	int	21h


 Exit:
	pop	ds				; И восстанавливаем обратно

CLret dx

; ---------------------------------------------------------------------------
; E n d   o f   b a s e   f u n с t i o n s
; ---------------------------------------------------------------------------

WORKFUNCS

; ---------------------------------------------------------------------------
; S u b r o u t i n e
; Проверяем символ в al, результат оказывается в dx
; ---------------------------------------------------------------------------

CheckSymbol proc near

	mov	dx,01h	; "ни один из" - если не поменяется в процессе проверки

	cmp	al,030h	; 1
	jnb	Next_39h
	ret
 Next_39h:
	cmp	al,039h	; 9
	ja	Next_41h
	mov	dx,02h	; Digit
	ret

 Next_41h:
	cmp	al,041h	; A lat
	jnb	Next_5ah
	ret
 Next_5ah:
	cmp	al,05ah	; Z lat
	ja	Next_61h
	mov	dx,03h	; UpperAlpha
	ret

 Next_61h:
	cmp	al,061h	; a lat
	jnb	Next_7ah
	ret	
 Next_7ah:
	cmp	al,07ah	; z lat
	ja	Next_80h
	mov	dx,04h	; LowerAlpha
	ret

 Next_80h:
	cmp	al,080h	; А cyr
	jnb	Next_9fh
	ret
 Next_9fh:
	cmp	al,09fh	; Я cyr
	ja	Next_afh
	mov	dx,03h	; UpperAlpha
	ret

 Next_afh:
	cmp	al,0afh	; а cyr
	ja	Next_e0h
	mov	dx,04h	; LowerAlpha
	ret

 Next_e0h:
	cmp	al,0e0h
	jnb	Next_efh
	ret
 Next_efh:
	cmp	al,0efh
	ja	Last_ret
	mov	dx,04h	; LowerAlpha
 Last_ret:
	ret

CheckSymbol	endp


ENDWORK
END