fixed mishandling of MBCS chars

git-svn-id: https://svn.code.sf.net/p/nsis/code/NSIS/trunk@3441 212acab6-be3b-0410-9dea-997c60f758d6
This commit is contained in:
kichik 2004-01-31 19:54:45 +00:00
parent 3b65a9cb07
commit ebd0852b60
4 changed files with 193 additions and 145 deletions

View file

@ -54,6 +54,16 @@ char *WINAPI STRDUP(const char *c)
return lstrcpy(t,c); return lstrcpy(t,c);
} }
// Turn a pair of chars into a word
// Turn four chars into a dword
#ifdef __BIG_ENDIAN__ // Not very likely, but, still...
#define CHAR2_TO_WORD(a,b) (((WORD)(b))|((a)<<8))
#define CHAR4_TO_DWORD(a,b,c,d) (((DWORD)CHAR2_TO_WORD(c,d))|(CHAR2_TO_WORD(a,b)<<16))
#else
#define CHAR2_TO_WORD(a,b) (((WORD)(a))|((b)<<8))
#define CHAR4_TO_DWORD(a,b,c,d) (((DWORD)CHAR2_TO_WORD(a,b))|(CHAR2_TO_WORD(c,d)<<16))
#endif
// Field types // Field types
// NB - the order of this list is important - see below // NB - the order of this list is important - see below
@ -120,6 +130,9 @@ int WINAPI LookupTokens(TableEntry*, char*);
void WINAPI ConvertNewLines(char *str); void WINAPI ConvertNewLines(char *str);
// all allocated buffers must be first in the struct
// when adding more allocated buffers to FieldType, don't forget to change this define
#define FIELD_BUFFERS 6
struct FieldType { struct FieldType {
char *pszText; char *pszText;
char *pszState; char *pszState;
@ -128,12 +141,12 @@ struct FieldType {
char *pszListItems; char *pszListItems;
char *pszFilter; char *pszFilter;
int nType; char *pszValidateText;
RECT rect;
int nMinLength; int nMinLength;
int nMaxLength; int nMaxLength;
char *pszValidateText;
int nType;
RECT rect;
int nFlags; int nFlags;
@ -313,28 +326,30 @@ bool WINAPI SaveSettings(void) {
pszBuffer[nLength+1]='"'; pszBuffer[nLength+1]='"';
pszBuffer[nLength+2]='\0'; pszBuffer[nLength+2]='\0';
if ( pField->nType == FIELD_TEXT && (pField->nFlags & FLAG_MULTILINE) ) if (pField->nType == FIELD_TEXT && (pField->nFlags & FLAG_MULTILINE))
{ {
char *pszBuf2 = (char*)MALLOC(nBufLen*2); // double the size, consider the worst case, all chars are \r\n char *pszBuf2 = (char*)MALLOC(nBufLen*2); // double the size, consider the worst case, all chars are \r\n
char *p1, *p2; char *p1, *p2;
for (p1=pszBuffer,p2=pszBuf2; *p1; p1++, p2++) { for (p1 = pszBuffer, p2 = pszBuf2; *p1; p1 = CharNext(p1), p2 = CharNext(p2))
{
switch (*p1) { switch (*p1) {
case '\t': case '\t':
*p2++ = '\\'; *(LPWORD)p2 = CHAR2_TO_WORD('\\', 't');
*p2 = 't'; p2++;
break; break;
case '\n': case '\n':
*p2++ = '\\'; *(LPWORD)p2 = CHAR2_TO_WORD('\\', 'n');
*p2 = 'n'; p2++;
break; break;
case '\r': case '\r':
*p2++ = '\\'; *(LPWORD)p2 = CHAR2_TO_WORD('\\', 'r');
*p2 = 'r'; p2++;
break; break;
case '\\': case '\\':
*p2++ = '\\'; *p2++ = '\\';
default: default:
*p2=*p1; lstrcpyn(p2, p1, CharNext(p1) - p1 + 1);
break;
} }
} }
*p2 = 0; *p2 = 0;
@ -361,46 +376,48 @@ bool WINAPI SaveSettings(void) {
#define BROWSE_WIDTH 15 #define BROWSE_WIDTH 15
static char szResult[BUFFER_SIZE]; static char szResult[BUFFER_SIZE];
char *pszAppName;
DWORD WINAPI myGetProfileString(LPCTSTR lpAppName, LPCTSTR lpKeyName) DWORD WINAPI myGetProfileString(LPCTSTR lpKeyName)
{ {
*szResult = '\0'; *szResult = '\0';
return GetPrivateProfileString(lpAppName, lpKeyName, "", szResult, BUFFER_SIZE, pszFilename); return GetPrivateProfileString(pszAppName, lpKeyName, "", szResult, BUFFER_SIZE, pszFilename);
} }
char * WINAPI myGetProfileStringDup(LPCTSTR lpAppName, LPCTSTR lpKeyName) char * WINAPI myGetProfileStringDup(LPCTSTR lpKeyName)
{ {
int nSize = myGetProfileString(lpAppName, lpKeyName); int nSize = myGetProfileString(lpKeyName);
if ( nSize ) if (nSize)
return strdup(szResult); return strdup(szResult);
else else
return NULL; return NULL;
} }
UINT WINAPI myGetProfileInt(LPCTSTR lpAppName, LPCTSTR lpKeyName, INT nDefault) UINT WINAPI myGetProfileInt(LPCTSTR lpKeyName, INT nDefault)
{ {
return GetPrivateProfileInt(lpAppName, lpKeyName, nDefault, pszFilename); return GetPrivateProfileInt(pszAppName, lpKeyName, nDefault, pszFilename);
} }
int WINAPI ReadSettings(void) { int WINAPI ReadSettings(void) {
static char szField[25]; static char szField[25];
int nIdx, nCtrlIdx; int nIdx, nCtrlIdx;
pszTitle = myGetProfileStringDup("Settings", "Title"); pszAppName = "Settings";
pszCancelButtonText = myGetProfileStringDup("Settings", "CancelButtonText"); pszTitle = myGetProfileStringDup("Title");
pszNextButtonText = myGetProfileStringDup("Settings", "NextButtonText"); pszCancelButtonText = myGetProfileStringDup("CancelButtonText");
pszBackButtonText = myGetProfileStringDup("Settings", "BackButtonText"); pszNextButtonText = myGetProfileStringDup("NextButtonText");
pszBackButtonText = myGetProfileStringDup("BackButtonText");
nNumFields = myGetProfileInt("Settings", "NumFields", 0); nNumFields = myGetProfileInt("NumFields", 0);
nRectId = myGetProfileInt("Settings", "Rect", DEFAULT_RECT); nRectId = myGetProfileInt("Rect", DEFAULT_RECT);
bBackEnabled = myGetProfileInt("Settings", "BackEnabled", -1); bBackEnabled = myGetProfileInt("BackEnabled", -1);
// by ORTIM: 13-August-2002 // by ORTIM: 13-August-2002
bCancelEnabled = myGetProfileInt("Settings", "CancelEnabled", -1); bCancelEnabled = myGetProfileInt("CancelEnabled", -1);
bCancelShow = myGetProfileInt("Settings", "CancelShow", -1); bCancelShow = myGetProfileInt("CancelShow", -1);
bRTL = myGetProfileInt("Settings", "RTL", 0); bRTL = myGetProfileInt("RTL", 0);
if (nNumFields > 0) { if (nNumFields > 0) {
// make this twice as large for the worst case that every control is a browse button. // make this twice as large for the worst case that every control is a browse button.
@ -464,25 +481,26 @@ int WINAPI ReadSettings(void) {
FieldType *pField = pFields + nIdx; FieldType *pField = pFields + nIdx;
wsprintf(szField, "Field %d", nCtrlIdx + 1); wsprintf(szField, "Field %d", nCtrlIdx + 1);
pszAppName = szField;
// Get the control type // Get the control type
myGetProfileString(szField, "TYPE"); myGetProfileString("TYPE");
pField->nType = LookupToken(TypeTable, szResult); pField->nType = LookupToken(TypeTable, szResult);
if (pField->nType == FIELD_INVALID) if (pField->nType == FIELD_INVALID)
continue; continue;
// Lookup flags associated with the control type // Lookup flags associated with the control type
pField->nFlags = LookupToken(FlagTable, szResult); pField->nFlags = LookupToken(FlagTable, szResult);
myGetProfileString(szField, "Flags"); myGetProfileString("Flags");
pField->nFlags |= LookupTokens(FlagTable, szResult); pField->nFlags |= LookupTokens(FlagTable, szResult);
// pszState must not be NULL! // pszState must not be NULL!
myGetProfileString(szField, "State"); myGetProfileString("State");
pField->pszState = strdup(szResult); pField->pszState = strdup(szResult);
// ListBox items list // ListBox items list
{ {
int nResult = myGetProfileString(szField, "ListItems"); int nResult = myGetProfileString("ListItems");
if (nResult) { if (nResult) {
// add an extra | character to the end to simplify the loop where we add the items. // add an extra | character to the end to simplify the loop where we add the items.
pField->pszListItems = (char*)MALLOC(nResult + 2); pField->pszListItems = (char*)MALLOC(nResult + 2);
@ -493,15 +511,15 @@ int WINAPI ReadSettings(void) {
} }
// Label Text - convert newline // Label Text - convert newline
pField->pszText = myGetProfileStringDup(szField, "TEXT"); pField->pszText = myGetProfileStringDup("TEXT");
if (pField->nType == FIELD_LABEL) if (pField->nType == FIELD_LABEL)
ConvertNewLines(pField->pszText); ConvertNewLines(pField->pszText);
// Dir request - root folder // Dir request - root folder
pField->pszRoot = myGetProfileStringDup(szField, "ROOT"); pField->pszRoot = myGetProfileStringDup("ROOT");
// ValidateText - convert newline // ValidateText - convert newline
pField->pszValidateText = myGetProfileStringDup(szField, "ValidateText"); pField->pszValidateText = myGetProfileStringDup("ValidateText");
ConvertNewLines(pField->pszValidateText); ConvertNewLines(pField->pszValidateText);
{ {
@ -512,22 +530,25 @@ int WINAPI ReadSettings(void) {
pField->pszFilter = (char*)MALLOC(nResult + 2); pField->pszFilter = (char*)MALLOC(nResult + 2);
strcpy(pField->pszFilter, szResult); strcpy(pField->pszFilter, szResult);
char *pszPos = pField->pszFilter; char *pszPos = pField->pszFilter;
while (*pszPos) { while (*pszPos)
if (*pszPos == '|') *pszPos = '\0'; {
pszPos++; if (*pszPos == '|')
*pszPos++ = 0;
else
pszPos = CharNext(pszPos);
} }
} }
} }
pField->rect.left = myGetProfileInt(szField, "LEFT", 0); pField->rect.left = myGetProfileInt("LEFT", 0);
pField->rect.top = myGetProfileInt(szField, "TOP", 0); pField->rect.top = myGetProfileInt("TOP", 0);
pField->rect.right = myGetProfileInt(szField, "RIGHT", 0); pField->rect.right = myGetProfileInt("RIGHT", 0);
pField->rect.bottom = myGetProfileInt(szField, "BOTTOM", 0); pField->rect.bottom = myGetProfileInt("BOTTOM", 0);
pField->nMinLength = myGetProfileInt(szField, "MinLen", 0); pField->nMinLength = myGetProfileInt("MinLen", 0);
pField->nMaxLength = myGetProfileInt(szField, "MaxLen", 0); pField->nMaxLength = myGetProfileInt("MaxLen", 0);
// Text color for LINK control, default is pure blue // Text color for LINK control, default is pure blue
pField->hImage = (HANDLE)myGetProfileInt(szField, "TxtColor", RGB(0,0,255)); pField->hImage = (HANDLE)myGetProfileInt("TxtColor", RGB(0,0,255));
pField->nControlID = 1200 + nIdx; pField->nControlID = 1200 + nIdx;
if (pField->nType == FIELD_FILEREQUEST || pField->nType == FIELD_DIRREQUEST) if (pField->nType == FIELD_FILEREQUEST || pField->nType == FIELD_DIRREQUEST)
@ -1141,42 +1162,38 @@ int WINAPI createCfgDlg()
} }
char *pszStart, *pszEnd, *pszList; char *pszStart, *pszEnd, *pszList;
pszStart = pszEnd = pszList = STRDUP(pField->pszListItems); pszStart = pszEnd = pszList = STRDUP(pField->pszListItems);
while ((*pszEnd) && (*pszStart)) { // pszListItems has a trailing pipe
while (*pszEnd) {
if (*pszEnd == '|') { if (*pszEnd == '|') {
*pszEnd = '\0'; *pszEnd = '\0';
if (pszEnd > pszStart) { if (*pszStart)
mySendMessage(hwCtrl, nAddMsg, 0, (LPARAM)pszStart); mySendMessage(hwCtrl, nAddMsg, 0, (LPARAM) pszStart);
} pszStart = ++pszEnd;
// jump to the next item, skip any redundant | characters
do { pszEnd++; } while (*pszEnd == '|');
pszStart = pszEnd;
} }
else else
pszEnd++; pszEnd = CharNext(pszEnd);
} }
FREE(pszList); FREE(pszList);
if (pField->pszState) { if (pField->pszState) {
if (pField->nFlags & (LBS_MULTIPLESEL|LBS_EXTENDEDSEL) && nFindMsg == LB_FINDSTRINGEXACT) { if (pField->nFlags & (LBS_MULTIPLESEL|LBS_EXTENDEDSEL) && nFindMsg == LB_FINDSTRINGEXACT) {
mySendMessage(hwCtrl, LB_SETSEL, FALSE, -1); mySendMessage(hwCtrl, LB_SETSEL, FALSE, -1);
pszStart = pszEnd = pField->pszState; pszStart = pszEnd = pField->pszState;
while (*pszStart) { for (;;) {
char cLast = *pszEnd; char c = *pszEnd;
if (*pszEnd == '|') *pszEnd = '\0'; if (c == '|' || c == '\0') {
if (!*pszEnd) { *pszEnd = '\0';
if (pszEnd > pszStart) { if (*pszStart)
int nItem = mySendMessage(hwCtrl, nFindMsg, -1, (LPARAM)pszStart); {
if (nItem != CB_ERR) { // CB_ERR == LB_ERR == -1 int nItem = mySendMessage(hwCtrl, LB_FINDSTRINGEXACT, -1, (LPARAM)pszStart);
if (nItem != LB_ERR)
mySendMessage(hwCtrl, LB_SETSEL, TRUE, nItem); mySendMessage(hwCtrl, LB_SETSEL, TRUE, nItem);
}
} }
if (cLast) { if (!c)
do { break;
pszEnd++; pszStart = ++pszEnd;
} while (*pszEnd == '|');
}
pszStart = pszEnd;
} }
pszEnd++; else
pszEnd = CharNext(pszEnd);
} }
} }
else { else {
@ -1289,11 +1306,11 @@ void WINAPI showCfgDlg()
int i = nNumFields; int i = nNumFields;
while (i--) { while (i--) {
FieldType *pField = pFields + i; FieldType *pField = pFields + i;
FREE(pField->pszText);
FREE(pField->pszState); int j = FIELD_BUFFERS;
FREE(pField->pszListItems); while (j--)
FREE(pField->pszFilter); FREE(((char **) pField)[j]);
FREE(pField->pszRoot);
if (pField->nType == FIELD_BITMAP) { if (pField->nType == FIELD_BITMAP) {
DeleteObject(pField->hImage); DeleteObject(pField->hImage);
} }
@ -1352,8 +1369,6 @@ extern "C" void __declspec(dllexport) show(HWND hwndParent, int string_size,
extern "C" BOOL WINAPI DllMain(HANDLE hInst, ULONG ul_reason_for_call, LPVOID lpReserved) extern "C" BOOL WINAPI DllMain(HANDLE hInst, ULONG ul_reason_for_call, LPVOID lpReserved)
{ {
m_hInstance=(HINSTANCE) hInst; m_hInstance=(HINSTANCE) hInst;
if (ul_reason_for_call == DLL_THREAD_DETACH || ul_reason_for_call == DLL_PROCESS_DETACH)
DestroyWindow(hConfigWindow);
return TRUE; return TRUE;
} }
@ -1372,48 +1387,60 @@ int WINAPI LookupTokens(TableEntry* psTable_, char* pszTokens_)
char *pszStart = pszTokens_; char *pszStart = pszTokens_;
char *pszEnd = pszTokens_; char *pszEnd = pszTokens_;
for (;;) { for (;;) {
if (*pszEnd == '\0') { char c = *pszEnd;
n |= LookupToken(psTable_, pszStart); if (c == '|' || c == '\0') {
break;
}
if (*pszEnd == '|') {
*pszEnd = '\0'; *pszEnd = '\0';
n |= LookupToken(psTable_, pszStart); n |= LookupToken(psTable_, pszStart);
*pszEnd = '|'; *pszEnd = c;
pszStart = pszEnd + 1; if (!c)
break;
pszStart = ++pszEnd;
} }
pszEnd++; else
pszEnd = CharNext(pszEnd);
} }
return n; return n;
} }
void WINAPI ConvertNewLines(char *str) { void WINAPI ConvertNewLines(char *str) {
char *p1, *p2; char *p1, *p2, *p3;
if (!str) return;
for (p1=p2=str; *p1; p1++, p2++) { if (!str)
if (*p1 == '\\') { return;
switch (p1[1]) {
case 't': p1 = p2 = str;
*p2 = '\t';
break; while (*p1)
case 'n': {
*p2 = '\n'; switch (*(LPWORD)p1)
break; {
case 'r': case CHAR2_TO_WORD('\\', 't'):
*p2 = '\r'; *p2 = '\t';
break; p1 += 2;
case '\\': p2++;
*p2 = '\\'; break;
break; case CHAR2_TO_WORD('\\', 'n'):
default: *p2 = '\n';
p1--; p1 += 2;
p2--; p2++;
break; break;
} case CHAR2_TO_WORD('\\', 'r'):
p1++; *p2 = '\r';
p1 += 2;
p2++;
break;
case CHAR2_TO_WORD('\\', '\\'):
*p2 = '\\';
p1 += 2;
p2++;
break;
default:
p3 = CharNext(p1);
while (p1 < p3)
*p2++ = *p1++;
break;
} }
else *p2 = *p1;
} }
*p2 = 0; *p2 = 0;
} }

View file

@ -38,7 +38,7 @@ unsigned int g_to;
void ExecScript(BOOL log); void ExecScript(BOOL log);
void LogMessage(const char *pStr); void LogMessage(const char *pStr);
char *my_strstr(const char *string, const char *strCharSet); char *my_strstr(char *a, char *b);
unsigned int my_atoi(char *s); unsigned int my_atoi(char *s);
void __declspec(dllexport) Exec(HWND hwndParent, int string_size, char *variables, stack_t **stacktop) { void __declspec(dllexport) Exec(HWND hwndParent, int string_size, char *variables, stack_t **stacktop) {
@ -94,14 +94,25 @@ void ExecScript(int log) {
nComSpecSize = GetModuleFileName(g_hInst, meDLLPath, MAX_PATH); nComSpecSize = GetModuleFileName(g_hInst, meDLLPath, MAX_PATH);
p = meDLLPath + nComSpecSize - 1; p = meDLLPath + nComSpecSize - 1;
g_exec = (char *)GlobalAlloc(GPTR, sizeof(char)*g_stringsize+nComSpecSize+1); g_exec = (char *)GlobalAlloc(GPTR, sizeof(char)*g_stringsize+nComSpecSize+1);
while ( *p && *p != '\\' ) do
p--; {
if ( p ) if (*p == '\\')
*p = 0; break;
p = CharPrev(meDLLPath, p);
}
while (p > meDLLPath);
if (p == meDLLPath)
{
// bad path
lstrcpy(szRet, "error");
goto done;
}
*p = 0;
GetTempFileName(meDLLPath, "ns", 0, g_exec); GetTempFileName(meDLLPath, "ns", 0, g_exec);
*p = '\\'; *p = '\\';
if ( CopyFile(meDLLPath, g_exec, FALSE) ) if (CopyFile(meDLLPath, g_exec, FALSE))
{ {
HANDLE hFile, hMapping; HANDLE hFile, hMapping;
LPBYTE pMapView; LPBYTE pMapView;
@ -109,7 +120,7 @@ void ExecScript(int log) {
hFile = CreateFile(g_exec, GENERIC_READ|GENERIC_WRITE, 0, NULL, OPEN_EXISTING,0, 0); hFile = CreateFile(g_exec, GENERIC_READ|GENERIC_WRITE, 0, NULL, OPEN_EXISTING,0, 0);
hMapping = CreateFileMapping(hFile, NULL, PAGE_READWRITE, 0, 0, NULL); hMapping = CreateFileMapping(hFile, NULL, PAGE_READWRITE, 0, 0, NULL);
pMapView = MapViewOfFile(hMapping, FILE_MAP_WRITE, 0, 0, 0); pMapView = MapViewOfFile(hMapping, FILE_MAP_WRITE, 0, 0, 0);
if ( pMapView ) if (pMapView)
{ {
pNTHeaders = (PIMAGE_NT_HEADERS)(pMapView + ((PIMAGE_DOS_HEADER)pMapView)->e_lfanew); pNTHeaders = (PIMAGE_NT_HEADERS)(pMapView + ((PIMAGE_DOS_HEADER)pMapView)->e_lfanew);
pNTHeaders->FileHeader.Characteristics = IMAGE_FILE_32BIT_MACHINE | IMAGE_FILE_LOCAL_SYMS_STRIPPED | pNTHeaders->FileHeader.Characteristics = IMAGE_FILE_32BIT_MACHINE | IMAGE_FILE_LOCAL_SYMS_STRIPPED |
@ -129,12 +140,12 @@ void ExecScript(int log) {
*pExec = ' '; *pExec = ' ';
pExec++; pExec++;
popstring(pExec); popstring(pExec);
if ( my_strstr(pExec, "/TIMEOUT=") ) { if (my_strstr(pExec, "/TIMEOUT=")) {
char *szTimeout = pExec + 9; char *szTimeout = pExec + 9;
g_to = my_atoi(szTimeout); g_to = my_atoi(szTimeout);
popstring(pExec); popstring(pExec);
} }
if (!g_exec[0] ) if (!g_exec[0])
{ {
lstrcpy(szRet, "error"); lstrcpy(szRet, "error");
goto done; goto done;
@ -216,30 +227,39 @@ void ExecScript(int log) {
if (!(log & 2)) { if (!(log & 2)) {
while (p = my_strstr(p, "\t")) { while (p = my_strstr(p, "\t")) {
int len = lstrlen(p); if ((int)(p - szUnusedBuf) > (int)(GlobalSize(hUnusedBuf) - TAB_REPLACE_SIZE - 1))
char *c_out=(char*)p+TAB_REPLACE_SIZE+len; {
char *c_in=(char *)p+len; *p++ = ' ';
while (len-- > 0) {
*c_out--=*c_in--;
} }
else
{
int len = lstrlen(p);
char *c_out=(char*)p+TAB_REPLACE_SIZE+len;
char *c_in=(char *)p+len;
while (len-- > 0) {
*c_out--=*c_in--;
}
lstrcpy(p, TAB_REPLACE); lstrcpy(p, TAB_REPLACE);
p += TAB_REPLACE_SIZE; p += TAB_REPLACE_SIZE;
*p = ' '; *p = ' ';
}
} }
p = szUnusedBuf; // get the old left overs p = szUnusedBuf; // get the old left overs
for (p2 = p; *p2; p2++) { for (p2 = p; *p2;) {
if (*p2 == '\r') { if (*p2 == '\r') {
*p2 = 0; *p2++ = 0;
continue; continue;
} }
if (*p2 == '\n') { if (*p2 == '\n') {
*p2 = 0; *p2 = 0;
while (!*p && p != p2) p++; while (!*p && p != p2) p++;
LogMessage(p); LogMessage(p);
p = p2 + 1; p = ++p2;
continue;
} }
p2 = CharNext(p2);
} }
// If data was taken out from the unused buffer, move p contents to the start of szUnusedBuf // If data was taken out from the unused buffer, move p contents to the start of szUnusedBuf
@ -299,21 +319,22 @@ void LogMessage(const char *pStr) {
ListView_EnsureVisible(g_hwndList, item.iItem, 0); ListView_EnsureVisible(g_hwndList, item.iItem, 0);
} }
char *my_strstr(char *a, char *b)
char *my_strstr(const char *string, const char *strCharSet) { {
char *s1, *s2; int l = lstrlen(b);
size_t chklen; while (lstrlen(a) >= l)
size_t i; {
if (lstrlen(string) < lstrlen(strCharSet)) return 0; char c = a[l];
if (!*strCharSet) return (char*)string; a[l] = 0;
chklen=lstrlen(string)-lstrlen(strCharSet); if (!lstrcmpi(a, b))
for (i = 0; i <= chklen; i++) { {
s1=&((char*)string)[i]; a[l] = c;
s2=(char*)strCharSet; return a;
while (*s1++ == *s2++) }
if (!*s2) return &((char*)string)[i]; a[l] = c;
a = CharNext(a);
} }
return 0; return NULL;
} }
unsigned int my_atoi(char *s) { unsigned int my_atoi(char *s) {

Binary file not shown.

Binary file not shown.