Initial commit.
[pdfium.git] / fpdfsdk / src / javascript / global.cpp
1 // Copyright 2014 PDFium Authors. All rights reserved.\r
2 // Use of this source code is governed by a BSD-style license that can be\r
3 // found in the LICENSE file.\r
4  \r
5 // Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com\r
6 \r
7 #include "../../include/javascript/JavaScript.h"\r
8 #include "../../include/javascript/IJavaScript.h"\r
9 #include "../../include/javascript/JS_Define.h"\r
10 #include "../../include/javascript/JS_Object.h"\r
11 #include "../../include/javascript/JS_Value.h"\r
12 #include "../../include/javascript/JS_GlobalData.h"\r
13 #include "../../include/javascript/global.h"\r
14 #include "../../include/javascript/JS_EventHandler.h"\r
15 #include "../../include/javascript/JS_Context.h"\r
16 \r
17 /* ---------------------------- global ---------------------------- */\r
18 \r
19 BEGIN_JS_STATIC_CONST(CJS_Global)\r
20 END_JS_STATIC_CONST()\r
21 \r
22 BEGIN_JS_STATIC_PROP(CJS_Global)\r
23 END_JS_STATIC_PROP()\r
24 \r
25 BEGIN_JS_STATIC_METHOD(CJS_Global)\r
26         JS_STATIC_METHOD_ENTRY(setPersistent, 2)\r
27 END_JS_STATIC_METHOD()\r
28 \r
29 IMPLEMENT_SPECIAL_JS_CLASS(CJS_Global, global_alternate, global);\r
30 \r
31 FX_BOOL CJS_Global::InitInstance(IFXJS_Context* cc)\r
32 {\r
33         CJS_Context* pContext = (CJS_Context*)cc;\r
34         ASSERT(pContext != NULL);\r
35 \r
36         global_alternate* pGlobal = (global_alternate*)GetEmbedObject();\r
37         ASSERT(pGlobal != NULL);\r
38         \r
39         pGlobal->Initial(pContext->GetReaderApp());\r
40         \r
41         return TRUE;\r
42 };\r
43 \r
44 global_alternate::global_alternate(CJS_Object* pJSObject)\r
45         : CJS_EmbedObj(pJSObject),\r
46         m_pApp(NULL)\r
47 {\r
48 }\r
49 \r
50 global_alternate::~global_alternate(void)\r
51 {\r
52         ASSERT(m_pApp != NULL);\r
53 \r
54 //      CommitGlobalPersisitentVariables();\r
55         DestroyGlobalPersisitentVariables();\r
56 \r
57         CJS_RuntimeFactory* pFactory = m_pApp->m_pJSRuntimeFactory;\r
58         ASSERT(pFactory);\r
59 \r
60         pFactory->ReleaseGlobalData();\r
61 }\r
62   \r
63 void global_alternate::Initial(CPDFDoc_Environment* pApp)\r
64 {\r
65         m_pApp = pApp;\r
66 \r
67         CJS_RuntimeFactory* pFactory = pApp->m_pJSRuntimeFactory;\r
68         ASSERT(pFactory);\r
69         m_pGlobalData = pFactory->NewGlobalData(pApp);\r
70         UpdateGlobalPersistentVariables();\r
71 }\r
72 \r
73 FX_BOOL global_alternate::QueryProperty(FX_LPCWSTR propname)\r
74 {\r
75         return CFX_WideString(propname) != L"setPersistent";\r
76 }\r
77 \r
78 FX_BOOL global_alternate::DelProperty(IFXJS_Context* cc, FX_LPCWSTR propname, JS_ErrorString& sError)\r
79 {\r
80         js_global_data* pData = NULL;\r
81         CFX_ByteString sPropName = CFX_ByteString::FromUnicode(propname);\r
82 \r
83         if (m_mapGlobal.Lookup(sPropName, (FX_LPVOID&)pData))\r
84         {\r
85                 pData->bDeleted = TRUE;\r
86                 return TRUE;\r
87         }\r
88 \r
89         return FALSE;\r
90 }\r
91 \r
92 FX_BOOL global_alternate::DoProperty(IFXJS_Context* cc, FX_LPCWSTR propname, CJS_PropValue& vp, JS_ErrorString& sError)\r
93 {\r
94         if (vp.IsSetting())\r
95         {\r
96                 CFX_ByteString sPropName = CFX_ByteString::FromUnicode(propname);\r
97                 switch (vp.GetType())\r
98                 {\r
99                 case VT_number:\r
100                         {\r
101                                 double dData;\r
102                                 vp >> dData;\r
103                                 return SetGlobalVariables(sPropName, JS_GLOBALDATA_TYPE_NUMBER, dData, false, "", v8::Handle<v8::Object>(), FALSE);\r
104                         }\r
105                 case VT_boolean:\r
106                         {\r
107                                 bool bData;\r
108                                 vp >> bData;\r
109                                 return SetGlobalVariables(sPropName, JS_GLOBALDATA_TYPE_BOOLEAN, 0, (bool)vp, "", v8::Handle<v8::Object>(), FALSE);\r
110                         }\r
111                 case VT_string:\r
112                         {\r
113                                 CFX_ByteString sData;\r
114                                 vp >> sData;\r
115                                 return SetGlobalVariables(sPropName, JS_GLOBALDATA_TYPE_STRING, 0, false, sData, v8::Handle<v8::Object>(), FALSE);\r
116                         }\r
117                 case VT_object:\r
118                         {\r
119                                 JSObject pData = (JSObject)vp;\r
120                                 return SetGlobalVariables(sPropName, JS_GLOBALDATA_TYPE_OBJECT, 0, false, "", pData, FALSE);\r
121 //                              else\r
122 //                              {\r
123 //                                      if (vp.IsArrayObject())\r
124 //                                      {\r
125 //                                              CJS_Array array;\r
126 //                                              vp.ConvertToArray(array);\r
127 //                                              return SetGlobalVariables(sPropName, JS_GLOBALDATA_TYPE_OBJECT, 0, false, "", \r
128 //                                                      (Dobject*)(Darray*)array, FALSE);\r
129 //                                      }\r
130 //                                      else\r
131 //                                              return FALSE;\r
132 //                              }\r
133                         }\r
134                 case VT_null:\r
135                         {\r
136                                 return SetGlobalVariables(sPropName, JS_GLOBALDATA_TYPE_NULL, 0, false, "", v8::Handle<v8::Object>(), FALSE);\r
137                         }\r
138                 case VT_undefined:\r
139                         {\r
140                                 DelProperty(cc, propname, sError);\r
141                                 return TRUE;\r
142                         }\r
143                 default:\r
144                         return FALSE;\r
145                 }\r
146         }\r
147         else\r
148         {\r
149                 js_global_data* pData = NULL;\r
150                 CFX_ByteString sPropName = CFX_ByteString::FromUnicode(propname);\r
151 \r
152                 if (m_mapGlobal.Lookup(sPropName, (FX_LPVOID&)pData))\r
153                 {\r
154                         if (pData)\r
155                         {\r
156                                 if (!pData->bDeleted)\r
157                                 {\r
158                                         switch (pData->nType)\r
159                                         {\r
160                                         case JS_GLOBALDATA_TYPE_NUMBER:\r
161                                                 vp << pData->dData;\r
162                                                 break;\r
163                                         case JS_GLOBALDATA_TYPE_BOOLEAN:\r
164                                                 vp << pData->bData;\r
165                                                 break;\r
166                                         case JS_GLOBALDATA_TYPE_STRING:\r
167                                                 vp << pData->sData;\r
168                                                 break;\r
169                                         case JS_GLOBALDATA_TYPE_OBJECT:\r
170                                                 {\r
171                                                         v8::Handle<v8::Object> obj = v8::Local<v8::Object>::New(vp.GetIsolate(),pData->pData);\r
172                                                         vp << obj;\r
173                                                         break;\r
174                                                 }\r
175                                         case JS_GLOBALDATA_TYPE_NULL:\r
176                                                 vp.SetNull();\r
177                                                 break;\r
178                                         default:\r
179                                                 return FALSE;\r
180                                         }\r
181                                         return TRUE;\r
182                                 }\r
183                                 else\r
184                                 {\r
185                                         return TRUE;\r
186                                 }\r
187                         }\r
188                         else\r
189                         {\r
190                                 vp.SetNull();\r
191                                 return TRUE;\r
192                         }\r
193                 }\r
194                 else\r
195                 {\r
196                         vp.SetNull();\r
197                         return TRUE;\r
198                 }\r
199         }\r
200 \r
201         return FALSE;\r
202 }\r
203 \r
204 FX_BOOL global_alternate::setPersistent(OBJ_METHOD_PARAMS)\r
205 {\r
206         if (params.size() != 2)\r
207         {\r
208                 //sError = JSGetStringFromID(IDS_STRING_JSPARAMERROR);  \r
209                 return FALSE;\r
210         }\r
211 \r
212         CFX_ByteString sName = params[0];\r
213 \r
214         js_global_data* pData = NULL;\r
215         if (m_mapGlobal.Lookup(sName, (FX_LPVOID&)pData))\r
216         {\r
217                 if (pData && !pData->bDeleted)\r
218                 {\r
219                         pData->bPersistent = (bool)params[1];\r
220                         return TRUE;\r
221                 }\r
222         }\r
223 \r
224         //sError = JSGetStringFromID(IDS_JSPARAM_INCORRECT);    \r
225         return FALSE;\r
226 }\r
227 \r
228 void global_alternate::UpdateGlobalPersistentVariables()\r
229 {\r
230         ASSERT(m_pGlobalData != NULL);\r
231 \r
232         for (int i=0,sz=m_pGlobalData->GetSize(); i<sz; i++)\r
233         {\r
234                 CJS_GlobalData_Element* pData = m_pGlobalData->GetAt(i);\r
235                 ASSERT(pData != NULL);\r
236 \r
237                 switch (pData->data.nType)\r
238                 {\r
239                 case JS_GLOBALDATA_TYPE_NUMBER:\r
240                         this->SetGlobalVariables(pData->data.sKey, JS_GLOBALDATA_TYPE_NUMBER, pData->data.dData, false, "", v8::Handle<v8::Object>(), pData->bPersistent == 1);\r
241                         JS_PutObjectNumber(NULL,(JSFXObject)(*m_pJSObject),\r
242                                 pData->data.sKey.UTF8Decode(), pData->data.dData);\r
243                         break;\r
244                 case JS_GLOBALDATA_TYPE_BOOLEAN:\r
245                         this->SetGlobalVariables(pData->data.sKey, JS_GLOBALDATA_TYPE_BOOLEAN, 0, (bool)(pData->data.bData == 1), "", v8::Handle<v8::Object>(), pData->bPersistent == 1);\r
246                         JS_PutObjectBoolean(NULL,(JSFXObject)(*m_pJSObject),\r
247                                 pData->data.sKey.UTF8Decode(), (bool)(pData->data.bData == 1));\r
248                         break;\r
249                 case JS_GLOBALDATA_TYPE_STRING:\r
250                         this->SetGlobalVariables(pData->data.sKey, JS_GLOBALDATA_TYPE_STRING, 0, false, pData->data.sData, v8::Handle<v8::Object>(), pData->bPersistent == 1);\r
251                         JS_PutObjectString(NULL,(JSFXObject)(*m_pJSObject),\r
252                                 pData->data.sKey.UTF8Decode(), \r
253                                 pData->data.sData.UTF8Decode());\r
254                         break;\r
255                 case JS_GLOBALDATA_TYPE_OBJECT:\r
256                         {\r
257                                 IJS_Runtime* pRuntime = JS_GetRuntime((JSFXObject)(*m_pJSObject));\r
258                                 v8::Handle<v8::Object> pObj = JS_NewFxDynamicObj(pRuntime, NULL, -1);\r
259 \r
260                                 PutObjectProperty(pObj, &pData->data);\r
261 \r
262                                 this->SetGlobalVariables(pData->data.sKey, JS_GLOBALDATA_TYPE_OBJECT, 0, false, "", \r
263                                         (JSObject)pObj, pData->bPersistent == 1);\r
264                                 JS_PutObjectObject(NULL,(JSFXObject)(*m_pJSObject),\r
265                                         pData->data.sKey.UTF8Decode(), (JSObject)pObj);\r
266                         }\r
267                         break;\r
268                 case JS_GLOBALDATA_TYPE_NULL:\r
269                         this->SetGlobalVariables(pData->data.sKey, JS_GLOBALDATA_TYPE_NULL, 0, false, "", v8::Handle<v8::Object>(), pData->bPersistent == 1);\r
270                         JS_PutObjectNull(NULL,(JSFXObject)(*m_pJSObject),\r
271                                 pData->data.sKey.UTF8Decode());\r
272                         break;\r
273                 }\r
274         }\r
275 }\r
276 \r
277 void global_alternate::CommitGlobalPersisitentVariables()\r
278 {\r
279         ASSERT(m_pGlobalData != NULL);\r
280 \r
281         FX_POSITION      pos = m_mapGlobal.GetStartPosition();\r
282         while (pos)\r
283         {\r
284                 CFX_ByteString name; \r
285                 js_global_data* pData = NULL;\r
286                 m_mapGlobal.GetNextAssoc(pos, name, (FX_LPVOID&)pData);\r
287                 \r
288                 if (pData)\r
289                 {\r
290                         if (pData->bDeleted)\r
291                         {\r
292                                 m_pGlobalData->DeleteGlobalVariable(name);\r
293                         }\r
294                         else\r
295                         {\r
296                                 switch (pData->nType)\r
297                                 {\r
298                                 case JS_GLOBALDATA_TYPE_NUMBER:\r
299                                         m_pGlobalData->SetGlobalVariableNumber(name, pData->dData);\r
300                                         m_pGlobalData->SetGlobalVariablePersistent(name, pData->bPersistent);\r
301                                         break;\r
302                                 case JS_GLOBALDATA_TYPE_BOOLEAN:\r
303                                         m_pGlobalData->SetGlobalVariableBoolean(name, pData->bData);\r
304                                         m_pGlobalData->SetGlobalVariablePersistent(name, pData->bPersistent);\r
305                                         break;\r
306                                 case JS_GLOBALDATA_TYPE_STRING:\r
307                                         m_pGlobalData->SetGlobalVariableString(name, pData->sData);\r
308                                         m_pGlobalData->SetGlobalVariablePersistent(name, pData->bPersistent);\r
309                                         break;\r
310                                 case JS_GLOBALDATA_TYPE_OBJECT:\r
311                                         //if (pData->pData)\r
312                                         {\r
313                                                 CJS_GlobalVariableArray array;\r
314                                                 v8::Handle<v8::Object> obj = v8::Local<v8::Object>::New(GetJSObject()->GetIsolate(),pData->pData);\r
315                                                 ObjectToArray(obj, array);\r
316                                                 m_pGlobalData->SetGlobalVariableObject(name, array);\r
317                                                 m_pGlobalData->SetGlobalVariablePersistent(name, pData->bPersistent);\r
318                                         }\r
319                                         break;\r
320                                 case JS_GLOBALDATA_TYPE_NULL:\r
321                                         m_pGlobalData->SetGlobalVariableNull(name);\r
322                                         m_pGlobalData->SetGlobalVariablePersistent(name, pData->bPersistent);\r
323                                         break;\r
324                                 }\r
325                         }\r
326                 }\r
327         }\r
328 }\r
329 \r
330 void global_alternate::ObjectToArray(v8::Handle<v8::Object> pObj, CJS_GlobalVariableArray& array)\r
331 {\r
332         v8::Handle<v8::Array> pKeyList = JS_GetObjectElementNames(pObj);\r
333         int     nObjElements = pKeyList->Length();\r
334 \r
335         v8::Local<v8::Context> context = pObj->CreationContext();\r
336         v8::Isolate* isolate = context->GetIsolate();\r
337 \r
338         for (int i=0; i<nObjElements; i++)\r
339         {\r
340                 \r
341                 CFX_WideString ws = JS_ToString(JS_GetArrayElemnet(pKeyList, i));\r
342                 CFX_ByteString sKey = ws.UTF8Encode();\r
343 \r
344                 v8::Handle<v8::Value> v = JS_GetObjectElement(isolate, pObj, (const wchar_t*)(FX_LPCWSTR)ws);\r
345                 FXJSVALUETYPE vt = GET_VALUE_TYPE(v);\r
346                 switch (vt)\r
347                 {\r
348                 case VT_number:\r
349                         {\r
350                                 CJS_KeyValue* pObjElement = new CJS_KeyValue;\r
351                                 pObjElement->nType = JS_GLOBALDATA_TYPE_NUMBER;\r
352                                 pObjElement->sKey = sKey;\r
353                                 pObjElement->dData = JS_ToNumber(v);\r
354                                 array.Add(pObjElement);\r
355                         }\r
356                         break;\r
357                 case VT_boolean:\r
358                         {\r
359                                 CJS_KeyValue* pObjElement = new CJS_KeyValue;\r
360                                 pObjElement->nType = JS_GLOBALDATA_TYPE_BOOLEAN;\r
361                                 pObjElement->sKey = sKey;\r
362                                 pObjElement->dData = JS_ToBoolean(v);\r
363                                 array.Add(pObjElement);\r
364                         }\r
365                         break;\r
366                 case VT_string:\r
367                         {\r
368                                 CFX_ByteString sValue = CJS_Value(isolate, v, VT_string);\r
369                                 CJS_KeyValue* pObjElement = new CJS_KeyValue;\r
370                                 pObjElement->nType = JS_GLOBALDATA_TYPE_STRING;\r
371                                 pObjElement->sKey = sKey;\r
372                                 pObjElement->sData = sValue;\r
373                                 array.Add(pObjElement);\r
374                         }\r
375                         break;\r
376                 case VT_object:\r
377                         {\r
378                                 CJS_KeyValue* pObjElement = new CJS_KeyValue;\r
379                                 pObjElement->nType = JS_GLOBALDATA_TYPE_OBJECT;\r
380                                 pObjElement->sKey = sKey;\r
381                                 ObjectToArray(JS_ToObject(v), pObjElement->objData);\r
382                                 array.Add(pObjElement);\r
383                         }\r
384                         break;\r
385                 case VT_null:\r
386                         {\r
387                                 CJS_KeyValue* pObjElement = new CJS_KeyValue;\r
388                                 pObjElement->nType = JS_GLOBALDATA_TYPE_NULL;\r
389                                 pObjElement->sKey = sKey;\r
390                                 array.Add(pObjElement);\r
391                         }\r
392                         break;\r
393                 default:\r
394                         break;\r
395                 }\r
396         }\r
397 }\r
398 \r
399 void global_alternate::PutObjectProperty(v8::Handle<v8::Object> pObj, CJS_KeyValue* pData)\r
400 {\r
401         ASSERT(pData != NULL);\r
402 \r
403         for (int i=0,sz=pData->objData.Count(); i<sz; i++)\r
404         {\r
405                 CJS_KeyValue* pObjData = pData->objData.GetAt(i);\r
406                 ASSERT(pObjData != NULL);\r
407 \r
408                 switch (pObjData->nType)\r
409                 {\r
410                 case JS_GLOBALDATA_TYPE_NUMBER:\r
411                         JS_PutObjectNumber(NULL,(JSObject)pObj, pObjData->sKey.UTF8Decode(), pObjData->dData);\r
412                         break;\r
413                 case JS_GLOBALDATA_TYPE_BOOLEAN:\r
414                         JS_PutObjectBoolean(NULL,(JSObject)pObj, pObjData->sKey.UTF8Decode(), (bool)(pObjData->bData == 1));\r
415                         break;\r
416                 case JS_GLOBALDATA_TYPE_STRING:\r
417                         JS_PutObjectString(NULL,(JSObject)pObj, pObjData->sKey.UTF8Decode(), pObjData->sData.UTF8Decode());\r
418                         break;\r
419                 case JS_GLOBALDATA_TYPE_OBJECT:\r
420                         {\r
421                                 IJS_Runtime* pRuntime = JS_GetRuntime((JSFXObject)(*m_pJSObject));\r
422                                 v8::Handle<v8::Object> pNewObj = JS_NewFxDynamicObj(pRuntime, NULL, -1);\r
423                                 PutObjectProperty(pNewObj, pObjData);\r
424                                 JS_PutObjectObject(NULL, (JSObject)pObj, pObjData->sKey.UTF8Decode(), (JSObject)pNewObj);\r
425                         }\r
426                         break;\r
427                 case JS_GLOBALDATA_TYPE_NULL:\r
428                         JS_PutObjectNull(NULL,(JSObject)pObj, pObjData->sKey.UTF8Decode());\r
429                         break;\r
430                 }\r
431         }\r
432 }\r
433 \r
434 void global_alternate::DestroyGlobalPersisitentVariables()\r
435 {\r
436         FX_POSITION      pos = m_mapGlobal.GetStartPosition();\r
437         while (pos)\r
438         {\r
439                 CFX_ByteString name; \r
440                 js_global_data* pData = NULL;\r
441                 m_mapGlobal.GetNextAssoc(pos, name, (FX_LPVOID&)pData);\r
442                 delete pData;\r
443         }\r
444 \r
445         m_mapGlobal.RemoveAll();\r
446 }\r
447 \r
448 \r
449 FX_BOOL global_alternate::SetGlobalVariables(FX_LPCSTR propname, int nType, \r
450                                 double dData, bool bData, const CFX_ByteString& sData, JSObject pData, bool bDefaultPersistent)\r
451 {\r
452         if (propname == NULL) return FALSE;\r
453 \r
454         js_global_data* pTemp = NULL;\r
455         m_mapGlobal.Lookup(propname, (FX_LPVOID&)pTemp);\r
456 \r
457         if (pTemp)\r
458         {\r
459                 if (pTemp->bDeleted || pTemp->nType != nType)\r
460                 {\r
461                         pTemp->dData = 0;\r
462                         pTemp->bData = 0;\r
463                         pTemp->sData = "";\r
464                         pTemp->nType = nType;\r
465                 }\r
466 \r
467                 pTemp->bDeleted = FALSE;\r
468 \r
469                 switch (nType)\r
470                 {\r
471                 case JS_GLOBALDATA_TYPE_NUMBER:\r
472                         {\r
473                                 pTemp->dData = dData;\r
474                         }\r
475                         break;\r
476                 case JS_GLOBALDATA_TYPE_BOOLEAN:\r
477                         {\r
478                                 pTemp->bData = bData;\r
479                         }\r
480                         break;\r
481                 case JS_GLOBALDATA_TYPE_STRING:\r
482                         {\r
483                                 pTemp->sData = sData;\r
484                         }\r
485                         break;\r
486                 case JS_GLOBALDATA_TYPE_OBJECT:\r
487                         {\r
488                                 pTemp->pData.Reset(JS_GetRuntime(pData), pData);\r
489                         }\r
490                         break;\r
491                 case JS_GLOBALDATA_TYPE_NULL:\r
492                         break;\r
493                 default:\r
494                         return FALSE;\r
495                 }       \r
496 \r
497                 return TRUE;\r
498         }\r
499 \r
500         js_global_data* pNewData = NULL;\r
501 \r
502         switch (nType)\r
503         {\r
504         case JS_GLOBALDATA_TYPE_NUMBER:\r
505                 {\r
506                         pNewData = new js_global_data;\r
507                         pNewData->nType = JS_GLOBALDATA_TYPE_NUMBER;\r
508                         pNewData->dData = dData;\r
509                         pNewData->bPersistent = bDefaultPersistent;\r
510                 }\r
511                 break;\r
512         case JS_GLOBALDATA_TYPE_BOOLEAN:\r
513                 {\r
514                         pNewData = new js_global_data;\r
515                         pNewData->nType = JS_GLOBALDATA_TYPE_BOOLEAN;\r
516                         pNewData->bData = bData;\r
517                         pNewData->bPersistent = bDefaultPersistent;\r
518                 }\r
519                 break;\r
520         case JS_GLOBALDATA_TYPE_STRING:\r
521                 {\r
522                         pNewData = new js_global_data;\r
523                         pNewData->nType = JS_GLOBALDATA_TYPE_STRING;\r
524                         pNewData->sData = sData;\r
525                         pNewData->bPersistent = bDefaultPersistent;\r
526                 }\r
527                 break;\r
528         case JS_GLOBALDATA_TYPE_OBJECT:\r
529                 {\r
530                         pNewData = new js_global_data;\r
531                         pNewData->nType = JS_GLOBALDATA_TYPE_OBJECT;\r
532                         pNewData->pData.Reset(JS_GetRuntime(pData), pData);\r
533                         pNewData->bPersistent = bDefaultPersistent;\r
534                 }\r
535                 break;\r
536         case JS_GLOBALDATA_TYPE_NULL:\r
537                 {\r
538                         pNewData = new js_global_data;\r
539                         pNewData->nType = JS_GLOBALDATA_TYPE_NULL;\r
540                         pNewData->bPersistent = bDefaultPersistent;\r
541                 }\r
542                 break;\r
543         default:\r
544                 return FALSE;\r
545         }       \r
546 \r
547         m_mapGlobal.SetAt(propname, (FX_LPVOID)pNewData);\r
548 \r
549         return TRUE;\r
550 }\r