/*++ Copyright (c) 1988-1999 Microsoft Corporation Module Name: string.c Abstract: String processing support --*/ #include "cmd.h" /*** * * This file contains routines for finding the last character and the * penultimate (next to last) character of a string. And finally, a routine * (prevc) to return a pointer to the previous character given a pointer * to an entire string and a pointer to a character within the string. * * John Tupper, Microsoft */ // // DbcsLeadCharTable contains 256 BOOL entries. Each entry signifies // whether the character used to look-up the table is a DBCS lead byte. // This table needs to be updated whenever Cmd's codepage is changed. // Dbcsleadchar is accessed by the is_dbcsleadchar macro defined in Cmd.h. // BOOLEAN DbcsLeadCharTable[ 256 ]; // // AnyDbcsLeadChars is an optimization. It tells us of there are any DBCS // lead chars currently defined in DbcsLeadCharTable. If it is FALSE, then // we don't have to use DBCS aware string functions. // extern CPINFO CurrentCPInfo; extern UINT CurrentCP; BOOLEAN AnyDbcsLeadChars = FALSE; VOID InitializeDbcsLeadCharTable( ) { UINT i, k; if (! GetCPInfo((CurrentCP=GetConsoleOutputCP()), &CurrentCPInfo )) { // // GetCPInfo failed. What should we do ? // #ifdef FE_SB LCID lcid = GetThreadLocale(); if (PRIMARYLANGID(LANGIDFROMLCID(lcid)) == LANG_JAPANESE) { CurrentCPInfo.LeadByte[0] = 0x81; CurrentCPInfo.LeadByte[1] = 0x9f; CurrentCPInfo.LeadByte[2] = 0xe0; CurrentCPInfo.LeadByte[3] = 0xfc; CurrentCPInfo.LeadByte[4] = 0; CurrentCPInfo.LeadByte[5] = 0; } else if (PRIMARYLANGID(LANGIDFROMLCID(lcid)) == LANG_CHINESE) { if (SUBLANGID(LANGIDFROMLCID(lcid)) == SUBLANG_CHINESE_SIMPLIFIED) CurrentCPInfo.LeadByte[0] = 0x81; /* 0xa1 */ else CurrentCPInfo.LeadByte[0] = 0x81; CurrentCPInfo.LeadByte[1] = 0xfe; CurrentCPInfo.LeadByte[2] = 0; CurrentCPInfo.LeadByte[3] = 0; } else if (PRIMARYLANGID(LANGIDFROMLCID(lcid)) == LANG_KOREAN) { CurrentCPInfo.LeadByte[0] = 0x81; CurrentCPInfo.LeadByte[1] = 0xfe; CurrentCPInfo.LeadByte[2] = 0; CurrentCPInfo.LeadByte[3] = 0; } else { CurrentCPInfo.LeadByte[0] = 0; CurrentCPInfo.LeadByte[1] = 0; } #else CurrentCPInfo.LeadByte[0] = 0; CurrentCPInfo.LeadByte[1] = 0; #endif } memset( DbcsLeadCharTable, 0, 256 * sizeof (BOOLEAN) ); for (k=0 ; CurrentCPInfo.LeadByte[k] && CurrentCPInfo.LeadByte[k+1]; k+=2) { for (i=CurrentCPInfo.LeadByte[k] ; i<=CurrentCPInfo.LeadByte[k+1] ; i++) DbcsLeadCharTable[i] = TRUE; } if ( CurrentCPInfo.LeadByte[0] && CurrentCPInfo.LeadByte[1] ) AnyDbcsLeadChars = TRUE; else AnyDbcsLeadChars = FALSE; } /*** * mystrchr(string, c) - search a string for a character * * mystrchr will search through string and return a pointer to the first * occurance of the character c. This version of mystrchr knows about * double byte characters. Note that c must be a single byte character. * */ TCHAR * mystrchr(TCHAR const *string, TCHAR c) { /* handle null seperatly to make main loop easier to code */ if (string == NULL) return(NULL); return _tcschr( string, c ); } /*** * mystrrchr(string, c) - search a string for a character * * mystrchr will search through string and return a pointer to the last * occurance of the character c. This version of mystrrchr knows about * double byte characters. Note that c must be a single byte character. * */ TCHAR * mystrrchr(TCHAR const *string, TCHAR c) { /* handle null seperatly to make main loop easier to code */ if ((TCHAR *)string == NULL) return(NULL); return _tcsrchr( string, c ); } /*** * mystrcspn (str1, str2) will find the first character of str1 that is also * in str2. * Return value: * if a match is found return the position in str1 where the matching * character was found (the first position is 0). * If nomatch is found, return the position of the trailing null. */ size_t mystrcspn(str1, str2) TCHAR const *str1; TCHAR const *str2; { TCHAR c; int position = 0; if ((str1 == NULL) || (str2 == NULL)) return (0); /* Since str2 may not contain any double byte characters, when we see a double byte character in str1, we just skip it. Otherwise, use mystrchr to see if we have a match */ while (c = *str1++) { if (mystrchr(str2, c)) break; position++; } return(position); } /*** * lastc - return a pointer to the last character of the argument string * not including the trailing null. If a pointer to a zero length string * is passed, a pointer to the original string is returned. */ TCHAR *lastc(str) TCHAR *str; { TCHAR *last = str; while(*str) last = str++; return(last); } /*** * * penulc returns a pointer to the penultimate (next to last) character * of the argument string not including the trailing null. * If a pointer to a zero or one length string is passed, a pointer to * the orignial string is returned. */ TCHAR *penulc(str) TCHAR *str; { TCHAR *last = str; TCHAR *penul = str; while(*str) { penul = last; last = str; str++; } return(penul); } /*** * * prevc(str1, str2) assumes that str2 points to a character within * str1. prevc will return a pointer to the previous character (right * before str2). If str2 points outside of str1, NULL is returned. */ TCHAR *prevc(str1, str2) TCHAR *str1, *str2; { TCHAR *prev = str1; while (str1 != str2) { if (!*str1) return(NULL); prev = str1; str1++; } return(prev); }