;	SCCSID = @(#)casemap.asm	6.1 90/11/17
;	SCCSID = @(#)casemap.asm	6.2 90/06/15
; ****************************************************************************
; *									     *
; *			  IBM/Microsoft Confidential			     *
; *									     *
; *		    Copyright (c) IBM Corporation  1987, 1990		     *
; *		    Copyright (c) Microsoft Corp.  1987, 1990		     *
; *			      All Rights Reserved			     *
; *									     *
; ****************************************************************************

;***  Change History
;***   noto  11/18/93  Define which segment for Page Tuning DLL   ***
;***								  ***




SUBTTL Casemap Routine
PAGE
;/******* START OF SPECIFICATION ********************************/
;/*								*/
;/* SUBROUTINE	NAME: CASEMAP1					*/
;/*								*/
;/* DESCRIPTIVE NAME: CASEMAP1					*/
;/*								*/
;/* FUNCTION: Map the specified user's string buffer to upper   */
;/*	      case based on CDIB's ucase table or cached table. */
;/*								*/
;/* NOTES: ASM routine for performance increase performance	*/
;/*								*/
;/*								*/
;/* ENTRY POINT: CASEMAP1					*/
;/*   LINKAGE:							*/
;/*								*/
;/* INPUT:							*/
;/*		 ctrl_len  - length of casemap table		*/
;/*		 table_off - table addr in CDIB casemap table	*/
;/*		 table_off2 - table addr in CDIB DBCS table	*/
;/*		 length - length of user's buffer               */
;/*		 buffer - user's buffer address                 */
;/*								*/
;/*								*/
;/*		 +----------+					*/
;/*	   bp+18 | length   | <-- ctrl_len			*/
;/*		 +----------+					*/
;/*	   bp+16 | Segment  | <-- table_off			*/
;/*		 +----------+					*/
;/*	   bp+14 | Offset   |					*/
;/*		 +----------+					*/
;/*	   bp+12 | Segment  | <-- table_off2			*/
;/*		 +----------+					*/
;/*	   bp+10 | Offset   |					*/
;/*		 +----------+					*/
;/*	   bp+8  | length   | <-- length of user buffer 	*/
;/*		 +----------+					*/
;/*	   bp+6  | Segment  | <-- buffer			*/
;/*		 +----------+					*/
;/*	   bp+4  | Offset   |					*/
;/*		 +==========+					*/
;/*	   bp+2  | ip	    |					*/
;/*		 +----------+					*/
;/*	   bp	 | bp	    |					*/
;/*		 +----------+					*/
;/*		 | ds	    | save ds register			*/
;/*		 +----------+					*/
;/*								*/
;/* EXIT-NORMAL:						*/
;/*		 NO_ERROR return code				*/
;/*								*/
;/* EXIT-ERROR: 						*/
;/*		 NO_ERROR return code				*/
;/*								*/
;/* EFFECTS:							*/
;/*								*/
;/*								*/
;/* INTERNAL REFERENCES:					*/
;/*	   ROUTINES:						*/
;/*	     NONE						*/
;/*								*/
;/* EXTERNAL REFERENCES:					*/
;/*	   ROUTINES:						*/
;/*		 None						*/
;/*								*/
;/*								*/
;/************ END OF SOURCE FILE SPECIFICATIONS ****************/

 PAGE
.xlist
;include nls.inc
INCL_DOSSEMAPHORES EQU	1
INCLUDE BSEDOS.INC
include dc1segs.inc						; DCR 704
.list

; DGROUP  group   _DATA 					; DCR 704
CODE   segment
CODE   ends
SHRDATA   segment
SHRDATA   ends
DATA16	segment
DATA16	ends
DATA16E segment
	EXTRN _ENDDATA16 : BYTE 				 ; DCR 704
;_ENDDATA16	 LABEL	 BYTE					 ; DCR 704
DATA16E ends
DATA16	 segment
top_idata	equ	$

public	_iNLS_Sem
_iNLS_Sem	label		dword
		 dd	 _iCache_sem  ; Semaphore for allocated table
				      ; access
public	_iCache_sem
_iCache_sem	label		dword
		 dd	 0000H

public	_FSRam_Sem
_FSRam_Sem	DOSFSRSEM <14,0,0,0,0,0> ;intialize to zero

public	_iSize
_iSize		dw	OFFSET _ENDDATA16	; Total length of instance data


public	_ICACHE_TABLE
_iCACHE_TABLE	label		byte
		 db	 30	dup(0)	; Cached Tables

DATA16	 ends


CODE16C_TUNE1	SEGMENT DWORD USE16 PUBLIC 'CODE'
CODE16C_TUNE1	ENDS



CODE16C_TUNE1	SEGMENT
	assume	cs:CODE16C_TUNE1

public	CASEMAP1
CASEMAP1	PROC	NEAR

;	int	3
	push	bp
	mov	bp,sp
	push	ds
	push	es
	push	di
	push	si
	mov	es,word ptr [bp+12]	; es:[di] points to
	mov	di,word ptr [bp+10]	; DBCS Table
	xor	dx,dx			; dx = 0
	mov	ax,word ptr es:[di]	; ax = 1 st byte in DBCS Table

dbcs_zeros:				;
	cmp	ax,0			; if cx = 0
	je	casemap_loop		; casemap for non-DBCS string
	inc	dx			; Increment DBCS Table entry counter
	add	di,2			; increment to next DBCS Table entry
	mov	ax,word ptr es:[di]	; ax = next DBCS Table entry
	jmp	dbcs_zeros		; continue loop

casemap_loop:				; casemap routine
	mov	ah,byte ptr [bp+18]	; ah = ctrl_len
	mov	al,255			; al = 255
	sub	al,ah			; al = 255 - ctrl_len
	inc	al			; al = al + 1 , char_range

	mov	cx,word ptr [bp+8]	; cx = length of user's buffer
	cmp	cx,0			; No buffer !?
	je	end_casemap		; go to end casemap
	mov	ds,word ptr [bp+6]	; ds = sel of buffer
	mov	si,word ptr [bp+4]	; ds:[si] points to user's buffer

	xor	bh,bh			; clear bh

get_char:
	mov	bl,byte ptr ds:[si]	; bl is a char in user's buff

	cmp	dx,0			; If not dbcs string skip
	je	casemap_process 	; dbcs mapper
	push	cx			; save cx
	mov	cx,dx			; cx = number of DBCS ranges
dbcs_mapper:
	mov	di,word ptr [bp+10]	; es:[di] = DBCS Table lower range
dbcs_check:
	cmp	bl,es:[di]		; if bl < lower rage
	jb	next_range1		; go to next range
	inc	di			; increment di es:[di] = upper range
	cmp	bl,es:[di]		; if bl > upper range
	ja	next_range2		; go to next range
	inc	si			; inrement si to advance the pointer
	pop	cx			; cx = restore length of user's buffer
	cmp	cx,1			;
	je	end_casemap		;
	dec	cx			;
	jmp	next_char		; go to process next character

next_range1:
	inc	di			; skip the uppler range of thie entry

next_range2:				; Get next DBCS range
	dec	cx			; decrement cx
	inc	di			; increment di es:[di] = next lower
					; range in DBCS Table
	cmp	cx,0			; If end of Table
	jg	dbcs_check		; no, continue to check
	pop	cx			; cx = restore length of user's buffer
					;
casemap_process:			;
	cmp	bl,al			; if char >= char_range
	jae	use_table		; go to use casemap table

	cmp	bl,'a'                  ; if char < 'a'
	jb	next_char		; go to process next char
	cmp	bl,'z'                  ; if char > 'z'
	ja	next_char		; go to process next char
	sub	byte ptr ds:[si],'a'-'A'  ; compute the upper case char
	jmp	next_char		; go to process next char

use_table:				;
	sub	bl,al			; compute the mapping location
					; in the casemap table
	mov	di,word ptr [bp+14]	; es:[di] = Casemap Table
	mov	bl,es:[bx][di]		; al = mapping char in casemap table
					;
	mov	ds:[si],bl		; copy the mapping char into user's
					; buffer

next_char:
	inc	si			; increment the pointer to user's buff
	dec	cx			; decrement the length counter
	cmp	cx,0			; if no more char, return
	jnz	get_char		; else get char from user's buufer

end_casemap:
	xor	ax,ax
	assume	ds:SHRDATA
	pop	si
	pop	di
	pop	es
	pop	ds
	pop	bp
	ret	16			; Return to the caller
CASEMAP1  endp
CODE16C_TUNE1	ends
	end
;**************************************************************************
