Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

241 lines
5.7 KiB

  1. /*++
  2. Copyright (c) 1988-1999 Microsoft Corporation
  3. Module Name:
  4. string.c
  5. Abstract:
  6. String processing support
  7. --*/
  8. #include "cmd.h"
  9. /***
  10. *
  11. * This file contains routines for finding the last character and the
  12. * penultimate (next to last) character of a string. And finally, a routine
  13. * (prevc) to return a pointer to the previous character given a pointer
  14. * to an entire string and a pointer to a character within the string.
  15. *
  16. * John Tupper, Microsoft
  17. */
  18. //
  19. // DbcsLeadCharTable contains 256 BOOL entries. Each entry signifies
  20. // whether the character used to look-up the table is a DBCS lead byte.
  21. // This table needs to be updated whenever Cmd's codepage is changed.
  22. // Dbcsleadchar is accessed by the is_dbcsleadchar macro defined in Cmd.h.
  23. //
  24. BOOLEAN DbcsLeadCharTable[ 256 ];
  25. //
  26. // AnyDbcsLeadChars is an optimization. It tells us of there are any DBCS
  27. // lead chars currently defined in DbcsLeadCharTable. If it is FALSE, then
  28. // we don't have to use DBCS aware string functions.
  29. //
  30. extern CPINFO CurrentCPInfo;
  31. extern UINT CurrentCP;
  32. BOOLEAN AnyDbcsLeadChars = FALSE;
  33. VOID
  34. InitializeDbcsLeadCharTable(
  35. )
  36. {
  37. UINT i, k;
  38. if (! GetCPInfo((CurrentCP=GetConsoleOutputCP()), &CurrentCPInfo )) {
  39. //
  40. // GetCPInfo failed. What should we do ?
  41. //
  42. #ifdef FE_SB
  43. LCID lcid = GetThreadLocale();
  44. if (PRIMARYLANGID(LANGIDFROMLCID(lcid)) == LANG_JAPANESE) {
  45. CurrentCPInfo.LeadByte[0] = 0x81;
  46. CurrentCPInfo.LeadByte[1] = 0x9f;
  47. CurrentCPInfo.LeadByte[2] = 0xe0;
  48. CurrentCPInfo.LeadByte[3] = 0xfc;
  49. CurrentCPInfo.LeadByte[4] = 0;
  50. CurrentCPInfo.LeadByte[5] = 0;
  51. }
  52. else if (PRIMARYLANGID(LANGIDFROMLCID(lcid)) == LANG_CHINESE) {
  53. if (SUBLANGID(LANGIDFROMLCID(lcid)) == SUBLANG_CHINESE_SIMPLIFIED)
  54. CurrentCPInfo.LeadByte[0] = 0x81; /* 0xa1 */
  55. else
  56. CurrentCPInfo.LeadByte[0] = 0x81;
  57. CurrentCPInfo.LeadByte[1] = 0xfe;
  58. CurrentCPInfo.LeadByte[2] = 0;
  59. CurrentCPInfo.LeadByte[3] = 0;
  60. }
  61. else if (PRIMARYLANGID(LANGIDFROMLCID(lcid)) == LANG_KOREAN) {
  62. CurrentCPInfo.LeadByte[0] = 0x81;
  63. CurrentCPInfo.LeadByte[1] = 0xfe;
  64. CurrentCPInfo.LeadByte[2] = 0;
  65. CurrentCPInfo.LeadByte[3] = 0;
  66. }
  67. else {
  68. CurrentCPInfo.LeadByte[0] = 0;
  69. CurrentCPInfo.LeadByte[1] = 0;
  70. }
  71. #else
  72. CurrentCPInfo.LeadByte[0] = 0;
  73. CurrentCPInfo.LeadByte[1] = 0;
  74. #endif
  75. }
  76. memset( DbcsLeadCharTable, 0, 256 * sizeof (BOOLEAN) );
  77. for (k=0 ; CurrentCPInfo.LeadByte[k] && CurrentCPInfo.LeadByte[k+1]; k+=2) {
  78. for (i=CurrentCPInfo.LeadByte[k] ; i<=CurrentCPInfo.LeadByte[k+1] ; i++)
  79. DbcsLeadCharTable[i] = TRUE;
  80. }
  81. if ( CurrentCPInfo.LeadByte[0] && CurrentCPInfo.LeadByte[1] )
  82. AnyDbcsLeadChars = TRUE;
  83. else
  84. AnyDbcsLeadChars = FALSE;
  85. }
  86. /***
  87. * mystrchr(string, c) - search a string for a character
  88. *
  89. * mystrchr will search through string and return a pointer to the first
  90. * occurance of the character c. This version of mystrchr knows about
  91. * double byte characters. Note that c must be a single byte character.
  92. *
  93. */
  94. TCHAR *
  95. mystrchr(TCHAR const *string, TCHAR c)
  96. {
  97. /* handle null seperatly to make main loop easier to code */
  98. if (string == NULL)
  99. return(NULL);
  100. return _tcschr( string, c );
  101. }
  102. /***
  103. * mystrrchr(string, c) - search a string for a character
  104. *
  105. * mystrchr will search through string and return a pointer to the last
  106. * occurance of the character c. This version of mystrrchr knows about
  107. * double byte characters. Note that c must be a single byte character.
  108. *
  109. */
  110. TCHAR *
  111. mystrrchr(TCHAR const *string, TCHAR c)
  112. {
  113. /* handle null seperatly to make main loop easier to code */
  114. if ((TCHAR *)string == NULL)
  115. return(NULL);
  116. return _tcsrchr( string, c );
  117. }
  118. /***
  119. * mystrcspn (str1, str2) will find the first character of str1 that is also
  120. * in str2.
  121. * Return value:
  122. * if a match is found return the position in str1 where the matching
  123. * character was found (the first position is 0).
  124. * If nomatch is found, return the position of the trailing null.
  125. */
  126. size_t
  127. mystrcspn(str1, str2)
  128. TCHAR const *str1;
  129. TCHAR const *str2;
  130. {
  131. TCHAR c;
  132. int position = 0;
  133. if ((str1 == NULL) || (str2 == NULL))
  134. return (0);
  135. /* Since str2 may not contain any double byte characters,
  136. when we see a double byte character in str1, we just skip it.
  137. Otherwise, use mystrchr to see if we have a match */
  138. while (c = *str1++) {
  139. if (mystrchr(str2, c))
  140. break;
  141. position++;
  142. }
  143. return(position);
  144. }
  145. /***
  146. * lastc - return a pointer to the last character of the argument string
  147. * not including the trailing null. If a pointer to a zero length string
  148. * is passed, a pointer to the original string is returned.
  149. */
  150. TCHAR *lastc(str)
  151. TCHAR *str;
  152. {
  153. TCHAR *last = str;
  154. while(*str)
  155. last = str++;
  156. return(last);
  157. }
  158. /***
  159. *
  160. * penulc returns a pointer to the penultimate (next to last) character
  161. * of the argument string not including the trailing null.
  162. * If a pointer to a zero or one length string is passed, a pointer to
  163. * the orignial string is returned.
  164. */
  165. TCHAR *penulc(str)
  166. TCHAR *str;
  167. {
  168. TCHAR *last = str;
  169. TCHAR *penul = str;
  170. while(*str) {
  171. penul = last;
  172. last = str;
  173. str++;
  174. }
  175. return(penul);
  176. }
  177. /***
  178. *
  179. * prevc(str1, str2) assumes that str2 points to a character within
  180. * str1. prevc will return a pointer to the previous character (right
  181. * before str2). If str2 points outside of str1, NULL is returned.
  182. */
  183. TCHAR *prevc(str1, str2)
  184. TCHAR *str1, *str2;
  185. {
  186. TCHAR *prev = str1;
  187. while (str1 != str2) {
  188. if (!*str1)
  189. return(NULL);
  190. prev = str1;
  191. str1++;
  192. }
  193. return(prev);
  194. }