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.

357 lines
9.8 KiB

  1. /*****************************************************************/
  2. /** Microsoft Windows for Workgroups **/
  3. /** Copyright (C) Microsoft Corp., 1991-1992 **/
  4. /*****************************************************************/
  5. /*
  6. strload.cxx
  7. NLS/DBCS-aware string class: LoadString methods
  8. This file contains the implementation of the LoadString methods
  9. for the NLS_STR class. It is separate so that clients of NLS_STR who
  10. do not use this operator need not link to it.
  11. FILE HISTORY:
  12. rustanl 01/31/91 Created
  13. beng 02/07/91 Uses lmui.hxx
  14. gregj 03/10/92 Added caching to speed up PM ext
  15. gregj 04/22/93 #ifdef'd out caching to save space
  16. */
  17. #include "npcommon.h"
  18. extern "C"
  19. {
  20. #include <netlib.h>
  21. }
  22. #if defined(DEBUG)
  23. static const CHAR szFileName[] = __FILE__;
  24. #define _FILENAME_DEFINED_ONCE szFileName
  25. #endif
  26. #include <npassert.h>
  27. #include <npstring.h>
  28. #include <shlwapi.h>
  29. #define ARRAYSIZE(a) (sizeof(a)/sizeof(a[0]))
  30. // we define this before we include mluisupp.h so we get code
  31. // instead of just prototypes
  32. #define MLUI_INIT
  33. #include <mluisupp.h>
  34. #ifdef RESOURCE_STRING_CACHING
  35. /*************************************************************************
  36. NAME: RESOURCE_CACHE
  37. SYNOPSIS: Caches a loaded resource string
  38. INTERFACE: RESOURCE_CACHE()
  39. Construct from an existing NLS_STR. Automatically
  40. links itself into its list.
  41. FindResourceCache() [friend function]
  42. Finds an ID in the list. If not found, returns NULL,
  43. else automatically promotes itself to the head of the
  44. list.
  45. AddResourceCache() [friend function]
  46. Set()
  47. Sets the cached message ID and string.
  48. all NLS_STR methods
  49. PARENT: NLS_STR
  50. USES:
  51. CAVEATS:
  52. NOTES:
  53. HISTORY:
  54. gregj 03/10/92 Created
  55. **************************************************************************/
  56. class RESOURCE_CACHE : public NLS_STR
  57. {
  58. friend const RESOURCE_CACHE *FindResourceCache( USHORT idMsg, RESOURCE_CACHE **ppLast,
  59. RESOURCE_CACHE **ppTrail );
  60. friend void AddResourceCache( USHORT idMsg, const NLS_STR *nls, RESOURCE_CACHE *pLast,
  61. RESOURCE_CACHE *pTrail );
  62. protected:
  63. USHORT _idMsg;
  64. RESOURCE_CACHE *_pFwd;
  65. static RESOURCE_CACHE *_pList;
  66. static INT _cItems;
  67. void Promote();
  68. public:
  69. RESOURCE_CACHE( USHORT idMsg, const NLS_STR &nls );
  70. ~RESOURCE_CACHE();
  71. RESOURCE_CACHE & operator=( const NLS_STR & nlsSource )
  72. { return (RESOURCE_CACHE&) NLS_STR::operator=( nlsSource ); }
  73. void Set( USHORT idMsg, const NLS_STR &nls );
  74. };
  75. RESOURCE_CACHE *RESOURCE_CACHE::_pList = NULL;
  76. INT RESOURCE_CACHE::_cItems = 0;
  77. #define RESCACHE_MAX 8 /* max number of strings to cache */
  78. RESOURCE_CACHE::RESOURCE_CACHE( USHORT idMsg, const NLS_STR &nls )
  79. : NLS_STR( MAX_RES_STR_LEN + 1 ),
  80. _idMsg( idMsg ),
  81. _pFwd( NULL )
  82. {
  83. if (QueryError() != WN_SUCCESS)
  84. return;
  85. *this = nls; /* copy contents */
  86. _pFwd = _pList;
  87. _pList = this; /* make this the new list head */
  88. _cItems++; /* and count this one */
  89. }
  90. RESOURCE_CACHE::~RESOURCE_CACHE()
  91. {
  92. RESOURCE_CACHE *pThis, *pTrail;
  93. for (pThis = _pList, pTrail = NULL;
  94. pThis != this && pThis != NULL;
  95. pTrail = pThis, pThis = pThis->_pFwd)
  96. ;
  97. if (pThis == NULL)
  98. return;
  99. if (pTrail == NULL)
  100. _pList = _pFwd;
  101. else
  102. pTrail->_pFwd = _pFwd;
  103. _cItems--;
  104. }
  105. void RESOURCE_CACHE::Promote()
  106. {
  107. RESOURCE_CACHE *pThis, *pTrail;
  108. for (pThis = _pList, pTrail = NULL;
  109. pThis != this && pThis != NULL;
  110. pTrail = pThis, pThis = pThis->_pFwd)
  111. ;
  112. if (pThis == NULL) /* item not found??? */
  113. _cItems++; /* try to keep count accurate */
  114. else if (pTrail == NULL)
  115. return; /* already at list head, no change */
  116. else
  117. pTrail->_pFwd = _pFwd; /* remove item from list */
  118. _pFwd = _pList;
  119. _pList = this; /* make this the new list head */
  120. }
  121. const RESOURCE_CACHE *FindResourceCache( USHORT idMsg, RESOURCE_CACHE **ppLast,
  122. RESOURCE_CACHE **ppTrail )
  123. {
  124. RESOURCE_CACHE *pThis, *pTrail;
  125. if (RESOURCE_CACHE::_pList == NULL) { /* empty list? */
  126. *ppLast = NULL;
  127. *ppTrail = NULL;
  128. return NULL;
  129. }
  130. for (pThis = RESOURCE_CACHE::_pList;
  131. pThis->_pFwd != NULL && pThis->_idMsg != idMsg;
  132. pTrail = pThis, pThis = pThis->_pFwd)
  133. ;
  134. if (pThis->_idMsg != idMsg) { /* item not found? */
  135. *ppLast = pThis; /* return ptr to last item */
  136. *ppTrail = pTrail; /* and to its predecessor */
  137. return NULL;
  138. }
  139. pThis->Promote(); /* item found, promote it */
  140. return pThis; /* and return it */
  141. }
  142. void AddResourceCache( USHORT idMsg, const NLS_STR *nls, RESOURCE_CACHE *pLast,
  143. RESOURCE_CACHE *pTrail )
  144. {
  145. if (RESOURCE_CACHE::_cItems < RESCACHE_MAX) { /* cache not full, make a new entry */
  146. RESOURCE_CACHE *pNew = new RESOURCE_CACHE( idMsg, *nls );
  147. /* automatically adds itself to the list */
  148. }
  149. else {
  150. if (pTrail != NULL) { /* if not already first item */
  151. pTrail->_pFwd = pLast->_pFwd; /* unlink from list */
  152. pLast->_pFwd = RESOURCE_CACHE::_pList; /* and move to front */
  153. RESOURCE_CACHE::_pList = pLast;
  154. }
  155. pLast->Set( idMsg, *nls ); /* set new contents */
  156. }
  157. }
  158. void RESOURCE_CACHE::Set( USHORT idMsg, const NLS_STR &nls )
  159. {
  160. *this = nls;
  161. _idMsg = idMsg;
  162. }
  163. #endif /* RESOURCE_STRING_CACHING */
  164. /*******************************************************************
  165. NAME: NLS_STR::LoadString
  166. SYNOPSIS: Loads a string from a resource file.
  167. ENTRY:
  168. EXIT: Returns an error value, which is WN_SUCCESS on success.
  169. NOTES: Requires that owner alloc strings must have an allocated
  170. size enough to fit strings of length MAX_RES_STR_LEN.
  171. This is requires even if the programmer thinks the string
  172. to be loaded is very small. The reason is that after the
  173. string has been localized, the string length bound is not
  174. known. Hence, the programmer always needs to allocate
  175. MAX_RES_STR_LEN + 1 bytes, which is guaranteed to be
  176. enough.
  177. HISTORY:
  178. rustanl 01/31/91 Created
  179. beng 07/23/91 Allow on erroneous string
  180. gregj 04/22/93 #ifdef'd out caching to save space
  181. ********************************************************************/
  182. USHORT NLS_STR::LoadString( USHORT usMsgID )
  183. {
  184. if (QueryError())
  185. return (USHORT) QueryError();
  186. // Impose requirement on owner alloc'd strings (see function header).
  187. UIASSERT( !IsOwnerAlloc() ||
  188. ( QueryAllocSize() >= MAX_RES_STR_LEN + 1 ));
  189. if ( ! IsOwnerAlloc())
  190. {
  191. // Resize the buffer to be big enough to hold any message.
  192. // If the buffer is already this big, realloc will do nothing.
  193. if ( ! realloc( MAX_RES_STR_LEN + 1 ))
  194. {
  195. return WN_OUT_OF_MEMORY;
  196. }
  197. }
  198. // At this point, we have a buffer which is big enough.
  199. UIASSERT( QueryAllocSize() >= MAX_RES_STR_LEN );
  200. #ifdef RESOURCE_STRING_CACHING
  201. RESOURCE_CACHE *pLast, *pTrail;
  202. const RESOURCE_CACHE *prc = FindResourceCache( usMsgID, &pLast, &pTrail );
  203. if (prc != NULL) {
  204. *this = *prc; /* copy contents */
  205. return WN_SUCCESS; /* all done */
  206. }
  207. #endif /* RESOURCE_STRING_CACHING */
  208. int cbCopied = MLLoadStringA(usMsgID, (LPSTR)QueryPch(),
  209. QueryAllocSize());
  210. if ( cbCopied == 0 )
  211. {
  212. return WN_BAD_VALUE;
  213. }
  214. _cchLen = cbCopied;
  215. IncVers();
  216. #ifdef RESOURCE_STRING_CACHING
  217. AddResourceCache( usMsgID, this, pLast, pTrail );
  218. #endif /* RESOURCE_STRING_CACHING */
  219. return WN_SUCCESS;
  220. }
  221. /*******************************************************************
  222. NAME: NLS_STR::LoadString
  223. SYNOPSIS: Loads a string from a resource file, and then inserts
  224. some parameters into it.
  225. ENTRY:
  226. EXIT: Returns an error value, which is WN_SUCCESS on success.
  227. NOTES: This method is provides a simple way to call the above
  228. LoadString and InsertParams consecutively.
  229. HISTORY:
  230. rustanl 01/31/91 Created
  231. ********************************************************************/
  232. USHORT NLS_STR::LoadString( USHORT usMsgID,
  233. const NLS_STR * apnlsParamStrings[] )
  234. {
  235. USHORT usErr = LoadString( usMsgID );
  236. if ( usErr == WN_SUCCESS )
  237. {
  238. usErr = InsertParams( apnlsParamStrings );
  239. }
  240. return usErr;
  241. }
  242. #ifdef EXTENDED_STRINGS
  243. /*******************************************************************
  244. NAME: RESOURCE_STR::RESOURCE_STR
  245. SYNOPSIS: Constructs a nls-string from a resource ID.
  246. ENTRY: idResource
  247. EXIT: Successful construct, or else ReportError
  248. NOTES: This string may not be owner-alloc! For owner-alloc,
  249. cons up a new one and copy this into it.
  250. HISTORY:
  251. beng 07/23/91 Created
  252. ********************************************************************/
  253. RESOURCE_STR::RESOURCE_STR( UINT idResource )
  254. : NLS_STR()
  255. {
  256. UIASSERT(!IsOwnerAlloc());
  257. USHORT usErr = LoadString(idResource);
  258. if (usErr)
  259. ReportError(usErr);
  260. }
  261. #endif