summaryrefslogtreecommitdiffstats
path: root/private/crt32/string/strlwr.c
blob: 24bc083683a12f63bbf6736c8c2e6c489400dde8 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
/***
*strlwr.c - routine to map upper-case characters in a string to lower-case
*
*	Copyright (c) 1985-1992, Microsoft Corporation. All rights reserved.
*
*Purpose:
*	Converts all the upper case characters in a string to lower case,
*	in place.
*
*Revision History:
*	05-31-89   JCR	C version created.
*	02-27-90   GJF	Fixed calling type, #include <cruntime.h>, fixed
*			copyright.
*	10-02-90   GJF	New-style function declarator.
*	01-18-91   GJF	ANSI naming.
*	09-18-91   ETC	Locale support under _INTL switch.
*	12-08-91   ETC	Updated nlsapi; added multithread.
*	08-19-92   KRS	Activated NLS support.
*	08-22-92   SRW	Allow INTL definition to be conditional for building ntcrt.lib
*	09-02-92   SRW	Get _INTL definition via ..\crt32.def
*       06-02-93   SRW  ignore _INTL if _NTSUBSET_ defined.
*
*******************************************************************************/

#include <cruntime.h>
#include <string.h>
#include <malloc.h>
#include <locale.h>
#include <setlocal.h>
#include <limits.h> // for INT_MAX
#include <os2dll.h>

/***
*char *_strlwr(string) - map upper-case characters in a string to lower-case
*
*Purpose:
*	_strlwr() converts upper-case characters in a null-terminated string
*	to their lower-case equivalents.  Conversion is done in place and
*	characters other than upper-case letters are not modified.
*
*	In the C locale, this function modifies only 7-bit ASCII characters
*	in the range 0x41 through 0x5A ('A' through 'Z').
*
*	If the locale is not the 'C' locale, MapString() is used to do
*	the work.  Assumes enough space in the string to hold result.
*
*Entry:
*	char *string - string to change to lower case
*
*Exit:
*	input string address
*
*Exceptions:
*	The original string is returned unchanged on any error.
*
*******************************************************************************/

char * _CALLTYPE1 _strlwr (
	char * string
	)
{
#if defined(_INTL) && !defined(_NTSUBSET_)
	char *cp;		/* traverses string for C locale conversion */
	wchar_t *wsrc = NULL;	/* wide version of string in original case */
	wchar_t *wdst = NULL;	/* wide version of string in alternate case */
	int srclen;		/* general purpose length of source string */
	int dstlen;		/* len of wdst string, wide chars, no null  */

	_mlock (_LC_CTYPE_LOCK);

	if ((_lc_handle[LC_CTYPE] == _CLOCALEHANDLE) &&
	    (_lc_codepage == _CLOCALECP))
	{
		_munlock (_LC_CTYPE_LOCK);

		for (cp=string; *cp; ++cp)
		{
			if ('A' <= *cp && *cp <= 'Z')
				*cp += 'a' - 'A';
		}
	
		return(string);
	} /* C locale */

	/* Algorithm for non-C locale: */
	/* Convert string to wide-character wsrc string */
	/* Map wrc string to wide-character wdst string in alternate case */
	/* Convert wdst string to char string and place in user buffer */

	/* Allocate maximum required space for wsrc */
	srclen = strlen(string) + 1;
	if ((wsrc = (wchar_t *) malloc(srclen*sizeof(wchar_t))) == NULL)
		goto error_cleanup;

	/* Convert string to wide-character wsrc string */
	if ((srclen=MultiByteToWideChar(_lc_codepage, MB_PRECOMPOSED, string,
		srclen, wsrc, srclen)) == 0)
		goto error_cleanup;

	/* Inquire size of wdst string */
	if ((dstlen=LCMapStringW (_lc_handle[LC_CTYPE], LCMAP_LOWERCASE, wsrc, 
		srclen, wdst, 0)) == 0)
		goto error_cleanup;

	/* Allocate space for wdst */
	if ((wdst = (wchar_t *) malloc(dstlen*sizeof(wchar_t))) == NULL)
		goto error_cleanup;

	/* Map wrc string to wide-character wdst string in alternate case */
	if (LCMapStringW(_lc_handle[LC_CTYPE], LCMAP_LOWERCASE, wsrc,
		srclen, wdst, dstlen) == 0)
		goto error_cleanup;

	/* Convert wdst string to char string and place in user buffer */
	srclen = INT_MAX; /* may overwrite length of user string */
	if (WideCharToMultiByte(_lc_codepage, WC_COMPOSITECHECK|WC_SEPCHARS,
	    wdst, dstlen, string, srclen, NULL, NULL) == 0)
		goto error_cleanup; /* can't recover here if fail */

error_cleanup:
	_munlock (_LC_CTYPE_LOCK);
	free (wsrc);
	free (wdst);
	return (string);

#else
	char * cp;

	for (cp=string; *cp; ++cp)
	{
		if ('A' <= *cp && *cp <= 'Z')
			*cp += 'a' - 'A';
	}

	return(string);
#endif /* _INTL */
}