0026244: Destructive results of simplification with DRAW command 'unifysamedom' after...
[occt.git] / src / Resource / Resource_Manager.cxx
CommitLineData
b311480e 1// Copyright (c) 1998-1999 Matra Datavision
973c2be1 2// Copyright (c) 1999-2014 OPEN CASCADE SAS
b311480e 3//
973c2be1 4// This file is part of Open CASCADE Technology software library.
b311480e 5//
d5f74e42 6// This library is free software; you can redistribute it and/or modify it under
7// the terms of the GNU Lesser General Public License version 2.1 as published
973c2be1 8// by the Free Software Foundation, with special exception defined in the file
9// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
10// distribution for complete text of the license and disclaimer of any warranty.
b311480e 11//
973c2be1 12// Alternatively, this file may be used under the terms of Open CASCADE
13// commercial license or contractual agreement.
b311480e 14
7fd59977 15
7fd59977 16#include <OSD_Directory.hxx>
42cf5bc1 17#include <OSD_File.hxx>
18#include <OSD_Path.hxx>
7fd59977 19#include <OSD_Protection.hxx>
42cf5bc1 20#include <Resource_DataMapIteratorOfDataMapOfAsciiStringAsciiString.hxx>
21#include <Resource_LexicalCompare.hxx>
22#include <Resource_Manager.hxx>
23#include <Resource_NoSuchResource.hxx>
24#include <Resource_Unicode.hxx>
7fd59977 25#include <Standard_ErrorHandler.hxx>
42cf5bc1 26#include <Standard_OutOfRange.hxx>
27#include <Standard_Type.hxx>
28#include <Standard_TypeMismatch.hxx>
29#include <TCollection_AsciiString.hxx>
7fd59977 30#include <TCollection_ExtendedString.hxx>
7fd59977 31#include <TColStd_Array1OfAsciiString.hxx>
32
e35db416 33#include <algorithm>
42cf5bc1 34#include <errno.h>
7fd59977 35#define END 0
36#define EMPTY 1
37#define COMMENT 2
b6d779d9 38#define RESOURCE 3
7fd59977 39#define ERROR -1
40
41static Standard_Integer WhatKindOfLine(OSD_File& aFile,
42 TCollection_AsciiString& aToken1,
43 TCollection_AsciiString& aToken2);
44
45static Standard_Integer GetLine(OSD_File& aFile,TCollection_AsciiString& aLine);
46
47static Standard_Boolean Debug;
48
49Resource_Manager::Resource_Manager(const Standard_CString aName,
50 TCollection_AsciiString& aDefaultsDirectory,
51 TCollection_AsciiString& anUserDefaultsDirectory,
52 const Standard_Boolean Verbose) : myName(aName), myVerbose(Verbose)
53{
54 if ( !aDefaultsDirectory.IsEmpty() ) {
b6d779d9 55 OSD_Path anOSDPath(aDefaultsDirectory);
56 anOSDPath.DownTrek(anOSDPath.Name());
57 anOSDPath.SetName(aName);
58 TCollection_AsciiString aPath;
59 anOSDPath.SystemName(aPath);
60 Load(aPath,myRefMap);
7fd59977 61 }
62 else
63 if (myVerbose)
64 cout << "Resource Manager Warning: aDefaultsDirectory is empty." << endl;
65
66 if ( !anUserDefaultsDirectory.IsEmpty() ) {
b6d779d9 67 OSD_Path anOSDPath(anUserDefaultsDirectory);
68 anOSDPath.DownTrek(anOSDPath.Name());
69 anOSDPath.SetName(aName);
70 TCollection_AsciiString aPath;
71 anOSDPath.SystemName(aPath);
72 Load(aPath,myRefMap);
7fd59977 73 }
74 else
75 if (myVerbose)
76 cout << "Resource Manager Warning: anUserDefaultsDirectory is empty." << endl;
77}
78
79Resource_Manager::Resource_Manager(const Standard_CString aName,
80 const Standard_Boolean Verbose) : myName(aName), myVerbose(Verbose)
81{
82 Debug = (getenv("ResourceDebug") != NULL) ;
83
7fd59977 84 TCollection_AsciiString Directory ;
7fd59977 85
86 if ( getenv ("CSF_ResourceVerbose") != NULL )
87 myVerbose = Standard_True;
88
b6d779d9 89 TCollection_AsciiString aPath,aUserPath;
90 GetResourcePath(aPath,aName,Standard_False);
91 GetResourcePath(aUserPath,aName,Standard_True);
7fd59977 92
b6d779d9 93 if (!aPath.IsEmpty())
94 Load(aPath,myRefMap);
95 else if (myVerbose)
96 cout << "Resource Manager Warning: Environment variable \"CSF_" << aName << "Defaults\" not set." << endl;
97
98 if (!aUserPath.IsEmpty())
99 Load(aUserPath,myRefMap);
100 else if (myVerbose)
101 cout << "Resource Manager Warning: Environment variable \"CSF_" << aName << "UserDefaults\" not set." << endl;
7fd59977 102}
103
b6d779d9 104void Resource_Manager::Load(TCollection_AsciiString& aPath,
105 Resource_DataMapOfAsciiStringAsciiString& aMap)
7fd59977 106{
b6d779d9 107 Standard_Integer Kind;
7fd59977 108 TCollection_AsciiString Token1, Token2;
109 TCollection_AsciiString Directory, Name;
110 TCollection_AsciiString FileName;
b6d779d9 111 OSD_File File = OSD_Path(aPath);
7fd59977 112 File.Open(OSD_ReadOnly,OSD_Protection());
113 if (File.Failed()) {
114 if (myVerbose)
115 cout << "Resource Manager Warning: Cannot read file \"" << FileName
116 << "\". File not found or permission denied." << endl;
117 return;
118 }
119 Standard_Integer LineNumber = 1;
120 while ((Kind = WhatKindOfLine(File, Token1, Token2)) != END) {
121 switch (Kind) {
122 case COMMENT :
123 case EMPTY :
124 break ;
7fd59977 125 case RESOURCE :
126 if (!aMap.Bind(Token1,Token2))
127 aMap(Token1) = Token2;
128 break;
129 case ERROR :
130 if (myVerbose)
131 cout << "Resource Manager: Syntax error at line "
132 << LineNumber << " in file : " << FileName << endl;
133 break;
134 }
135 LineNumber++;
136 }
137 File.Close();
138 if (myVerbose)
139 cout << "Resource Manager: " << ((&aMap == &myUserMap) ? "User" : "Reference")
140 << " file \"" << FileName << "\" loaded" << endl;
141}
142
143static Standard_Integer WhatKindOfLine(OSD_File& aFile,
144 TCollection_AsciiString& aToken1,
145 TCollection_AsciiString& aToken2)
146{
147 TCollection_AsciiString WhiteSpace = " \t" ;
148 Standard_Integer Pos1,Pos2,Pos ;
149 TCollection_AsciiString Line ;
150
151 if (!GetLine(aFile,Line))
152 return END;
153
154 if (Line.Value(1) == '!')
155 return COMMENT;
156
7fd59977 157 Pos1 = Line.FirstLocationNotInSet(WhiteSpace, 1, Line.Length());
158 if (Line.Value(Pos1) == '\n')
159 return EMPTY;
160
161 Pos2 = Line.Location(1,':',Pos1,Line.Length());
162 if (!Pos2 || Pos1 == Pos2)
163 return ERROR;
164
165 for (Pos = Pos2-1; Line.Value(Pos) == '\t' || Line.Value(Pos) == ' ' ; Pos--);
166 aToken1 = Line.SubString(Pos1, Pos);
167
168 if (Debug)
169 cout << "Key = '" << aToken1 << flush ;
170
302f96fb 171 Pos = Line.FirstLocationNotInSet(WhiteSpace, Pos2+1, Line.Length());
172 if (Pos) {
7fd59977 173 if (Line.Value(Pos) == '\\')
174 switch(Line.Value(Pos+1)) {
175 case '\\' :
176 case ' ' :
177 case '\t' :
178 Pos++;
179 break;
180 }
181 }
182 if (Pos == Line.Length())
183 aToken2.Clear();
bcf50875 184 else {
185 Line.Remove(1,Pos-1);
186 Line.Remove(Line.Length());
187 aToken2 = Line;
188 }
7fd59977 189 if (Debug)
190 cout << "'\t Value = '" << aToken2 << "'" << endl << flush;
191 return RESOURCE;
192}
193
194// Retourne 0 (EOF) ou une ligne toujours terminee par <NL>.
195
196static Standard_Integer GetLine(OSD_File& aFile,TCollection_AsciiString& aLine)
197{
198 TCollection_AsciiString Buffer;
199 Standard_Integer BufSize = 10;
200 Standard_Integer Len;
201
202 aLine.Clear();
203 do {
204 aFile.ReadLine(Buffer,BufSize,Len);
205 aLine += Buffer;
eafb234b 206 if (aFile.IsAtEnd()) {
7fd59977 207 if (!aLine.Length()) return 0;
208 else aLine += "\n";
eafb234b 209 }
7fd59977 210 } while (aLine.Value(aLine.Length()) != '\n');
211
212 return 1;
213}
214
215//=======================================================================
216//function : Save
217//purpose : Sort and save the user resources in the user file.
218// Creates the file if it does not exist.
219//=======================================================================
220Standard_Boolean Resource_Manager::Save() const
221{
b6d779d9 222 TCollection_AsciiString anEnvVar("CSF_");
223 anEnvVar += myName;
224 anEnvVar += "UserDefaults";
7fd59977 225
b6d779d9 226 Standard_CString dir;
227 if ((dir = getenv (anEnvVar.ToCString())) == NULL) {
7fd59977 228 if (myVerbose)
229 cout << "Resource Manager Warning: environment variable \""
b6d779d9 230 << anEnvVar << "\" not set. Cannot save resources." << endl ;
7fd59977 231 return Standard_False;
232 }
b6d779d9 233
234 TCollection_AsciiString aFilePath(dir);
235 OSD_Path anOSDPath(aFilePath);
236 OSD_Directory Dir = anOSDPath;
7fd59977 237 Standard_Boolean Status = Standard_True;
238 if ( !Dir.Exists() ) {
239 {
240 try {
241 OCC_CATCH_SIGNALS
b6d779d9 242 Dir.Build(OSD_Protection(OSD_RX, OSD_RWX, OSD_RX, OSD_RX));
7fd59977 243 }
244 catch (Standard_Failure) {
b6d779d9 245 Status = Standard_False;
7fd59977 246 }
247 }
248 Status = Status && !Dir.Failed();
249 if (!Status) {
250 if (myVerbose)
b6d779d9 251 cout << "Resource Manager: Error opening or creating directory \"" << aFilePath
252 << "\". Permission denied. Cannot save resources." << endl;
7fd59977 253 return Standard_False;
254 }
255 }
256
b6d779d9 257 anOSDPath.DownTrek(anOSDPath.Name());
258 anOSDPath.SetName(myName);
259 anOSDPath.SystemName(aFilePath);
260
261 OSD_File File = anOSDPath;
7fd59977 262 OSD_Protection theProt;
263 Status = Standard_True;
264 {
265 try {
266 OCC_CATCH_SIGNALS
267 File.Build(OSD_ReadWrite, theProt);
268 }
269 catch (Standard_Failure) {
270 Status = Standard_False;
271 }
272 }
273 Status = Status && !File.Failed();
274 if (!Status) {
275 if (myVerbose)
b6d779d9 276 cout << "Resource Manager: Error opening or creating file \"" << aFilePath
7fd59977 277 << "\". Permission denied. Cannot save resources." << endl;
278 return Standard_False;
279 }
280
b6d779d9 281 const Standard_Integer NbKey = myUserMap.Extent();
282 if (NbKey)
283 {
284 TColStd_Array1OfAsciiString KeyArray(1,NbKey);
285 Resource_DataMapIteratorOfDataMapOfAsciiStringAsciiString Iter(myUserMap);
286
287 Standard_Integer Index;
288 for ( Index = 1; Iter.More(); Iter.Next())
289 KeyArray(Index++)= Iter.Key();
290
e35db416 291 std::sort (KeyArray.begin(), KeyArray.end());
b6d779d9 292
293 TCollection_AsciiString Line, Value;
294 for (Index = 1 ; Index <= NbKey ; Index++) {
295 Value = myUserMap(KeyArray(Index));
296 if (!Value.IsEmpty())
297 switch(Value.Value(1)) {
298 case '\\' :
299 case ' ' :
300 case '\t' :
301 Value.Insert(1,'\\');
302 break;
303 }
304 Line = KeyArray(Index) + ":\t" + Value + "\n";
305
306 if (Debug)
307 cout << "Line = '" << Line << "'" << endl;
308
309 File.Write(Line, Line.Length());
310 }
311 if (myVerbose)
312 cout << "Resource Manager: Resources saved in file " << aFilePath << endl;
7fd59977 313 }
7fd59977 314 File.Close();
315 return Standard_True;
316}
317
318//=======================================================================
319//function : Integer
320//purpose : Gets the value of an integer resource
321//=======================================================================
322
323Standard_Integer Resource_Manager::Integer(const Standard_CString aResourceName) const
324{
325 TCollection_AsciiString Result = Value(aResourceName) ;
326 if (!Result.IsIntegerValue()) {
327 TCollection_AsciiString n("Value of resource `");
328 n+= aResourceName;
329 n+= "` is not an integer";
330 Standard_TypeMismatch::Raise(n.ToCString());
331 }
332 return Result.IntegerValue();
333}
334
335//=======================================================================
336//function : Real
337//purpose : Gets the value of a real resource
338//=======================================================================
339
340Standard_Real Resource_Manager::Real(const Standard_CString aResourceName) const
341{
342 TCollection_AsciiString Result = Value(aResourceName) ;
343 if (!Result.IsRealValue()) {
344 TCollection_AsciiString n("Value of resource `");
345 n+= aResourceName;
346 n+= "` is not a real";
347 Standard_TypeMismatch::Raise(n.ToCString());
348 }
349 return Result.RealValue();
350}
351
352//=======================================================================
353//function : Value
354//purpose : Gets the value of a CString resource
355//=======================================================================
356
357Standard_CString Resource_Manager::Value(const Standard_CString aResource) const
358{
359 TCollection_AsciiString Resource(aResource);
360 if (myUserMap.IsBound(Resource))
361 return myUserMap(Resource).ToCString();
362 if (myRefMap.IsBound(Resource))
363 return myRefMap(Resource).ToCString();
364 Resource_NoSuchResource::Raise(aResource);
365 return ("");
366}
367
368//=======================================================================
369//function : ExtValue
370//purpose : Gets the value of a ExtString resource
371//=======================================================================
372
373Standard_ExtString Resource_Manager::ExtValue(const Standard_CString aResource)
374{
375 TCollection_AsciiString Resource(aResource);
376 if (myExtStrMap.IsBound(Resource))
377 return myExtStrMap(Resource).ToExtString();
378
379 TCollection_AsciiString Result = Value(aResource);
380 TCollection_ExtendedString ExtResult;
381
382 Resource_Unicode::ConvertFormatToUnicode(Result.ToCString(),ExtResult);
383
384 myExtStrMap.Bind(Resource, ExtResult);
385 return myExtStrMap(Resource).ToExtString();
386}
387
388//=======================================================================
389//function : SetResource
390//purpose : Sets the new value of an integer resource.
391// If the resource does not exist, it is created.
392//=======================================================================
393void Resource_Manager::SetResource(const Standard_CString aResourceName,
394 const Standard_Integer aValue)
395{
396 SetResource(aResourceName,TCollection_AsciiString(aValue).ToCString());
397}
398
399//=======================================================================
400//function : SetResource
401//purpose : Sets the new value of a real resource.
402// If the resource does not exist, it is created.
403//=======================================================================
404void Resource_Manager::SetResource(const Standard_CString aResourceName,
405 const Standard_Real aValue)
406{
407 SetResource(aResourceName,TCollection_AsciiString(aValue).ToCString());
408}
409
410//=======================================================================
411//function : SetResource
412//purpose : Sets the new value of ExtString resource.
413// If the resource does not exist, it is created.
414//=======================================================================
415void Resource_Manager::SetResource(const Standard_CString aResource,
416 const Standard_ExtString aValue)
417{
418 Standard_PCharacter pStr;
419 TCollection_AsciiString Resource = aResource;
420 TCollection_ExtendedString ExtValue = aValue;
421 TCollection_AsciiString FormatStr(ExtValue.Length()*3+10, ' ');
422
423 if (!myExtStrMap.Bind(Resource,ExtValue)) {
424 myExtStrMap(Resource) = ExtValue;
425 }
426 //
427 pStr=(Standard_PCharacter)FormatStr.ToCString();
428 //
429 Resource_Unicode::ConvertUnicodeToFormat(ExtValue,
430 pStr,//FormatStr.ToCString(),
431 FormatStr.Length()) ;
432 SetResource(aResource,FormatStr.ToCString());
433}
434
435//=======================================================================
436//function : SetResource
437//purpose : Sets the new value of an enum resource.
438// If the resource does not exist, it is created.
439//=======================================================================
440void Resource_Manager::SetResource(const Standard_CString aResource,
441 const Standard_CString aValue)
442{
443 TCollection_AsciiString Resource = aResource;
444 TCollection_AsciiString Value = aValue;
445 if (!myUserMap.Bind(Resource, Value))
446 myUserMap(Resource) = Value;
447}
448
449//=======================================================================
450//function : Find
451//purpose : Tells if a resource exits.
452//=======================================================================
453Standard_Boolean Resource_Manager::Find(const Standard_CString aResource) const
454{
455 TCollection_AsciiString Resource(aResource);
456 if (myUserMap.IsBound(Resource) || myRefMap.IsBound(Resource))
457 return Standard_True;
458 return Standard_False;
459}
b6d779d9 460
461//=======================================================================
462//function : GetResourcePath
463//purpose :
464//=======================================================================
465
466void Resource_Manager::GetResourcePath (TCollection_AsciiString& aPath, const Standard_CString aName, const Standard_Boolean isUserDefaults)
467{
468 aPath.Clear();
469
470 TCollection_AsciiString anEnvVar("CSF_");
471 anEnvVar += aName;
472 anEnvVar += isUserDefaults?"UserDefaults":"Defaults";
473
474 Standard_CString dir;
475 if ((dir = getenv (anEnvVar.ToCString())) == NULL)
476 return;
477
478 TCollection_AsciiString aResPath(dir);
479
480 OSD_Path anOSDPath(aResPath);
481 anOSDPath.DownTrek(anOSDPath.Name());
482 anOSDPath.SetName(aName);
483
484 anOSDPath.SystemName(aPath);
42cf5bc1 485}