Convert uses of XKeycodeToKeysym (deprecated) to XkbKeycodeToKeysym
[oweals/cde.git] / cde / programs / dtinfo / dtinfo / src / UAS / MMDB / MMDB_Factory.C
1 /*
2  * CDE - Common Desktop Environment
3  *
4  * Copyright (c) 1993-2012, The Open Group. All rights reserved.
5  *
6  * These libraries and programs are free software; you can
7  * redistribute them and/or modify them under the terms of the GNU
8  * Lesser General Public License as published by the Free Software
9  * Foundation; either version 2 of the License, or (at your option)
10  * any later version.
11  *
12  * These libraries and programs are distributed in the hope that
13  * they will be useful, but WITHOUT ANY WARRANTY; without even the
14  * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
15  * PURPOSE. See the GNU Lesser General Public License for more
16  * details.
17  *
18  * You should have received a copy of the GNU Lesser General Public
19  * License along with these libraries and programs; if not, write
20  * to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
21
22  */
23 // $TOG: MMDB_Factory.C /main/15 1998/04/17 11:42:43 mgreess $
24 # include <sstream>
25 using namespace std;
26 # include "UAS_Exceptions.hh"
27 # include "MMDB_Factory.hh"
28 # include "UAS_Exceptions.hh"
29 # include "MMDB_EmbeddedObject.hh"
30 # include "MMDB_Library.hh"
31 # include "MMDB_BookCase.hh"
32 # include "MMDB_Section.hh"
33 # include "UAS_Collection.hh"
34
35 #include "Managers/CatMgr.hh"
36 #include "Registration.hh"
37
38 OLIAS_DB *MMDB_Factory::fOLIASDB = 0;
39
40 static MMDB_Factory  the_mmdb_factory; // instantiation
41
42 MMDB_Factory::MMDB_Factory ()
43 {
44     UAS_Factory::register_factory("mmdb", this);
45 }
46
47 MMDB_Factory::~MMDB_Factory ()
48 {
49     finalizeFactory ();
50     UAS_Factory::unregister_factory("mmdb");
51 }
52
53 OLIAS_DB &
54 MMDB_Factory::olias_db () {
55     if (fOLIASDB == 0) {
56         fOLIASDB = new OLIAS_DB ();
57     }
58     return *fOLIASDB;
59 }
60
61 MMDB *
62 MMDB_Factory::createMMDB (const UAS_String &infoLibPath) {
63     MMDB *rval = 0;
64     //
65     //  The MMDB leaks memory if we try to create an infolib
66     //  with a bogus path. This routine is called often with
67     //  infoLibPath == "", so we'll trap that case now
68     //
69     if (infoLibPath.length()) {
70         if (!olias_db().validInfoLibPath(infoLibPath)) {
71             UAS_ErrorMsg badPath;
72             char buf[BUFSIZ];
73             (void) snprintf (buf, sizeof(buf), CATGETS(Set_UAS_MMDB, 2,
74                                         "Invalid Infolib path: %s"),
75                                         (char *) infoLibPath);
76             badPath.fErrorMsg = buf;
77             UAS_Common::send_message (badPath);
78             return rval;
79         }
80         mtry {
81             rval = new MMDB (infoLibPath);
82             fMMDBList.append (rval);
83         } mcatch_any() {
84 #if 0
85             char buf[BUFSIZ];
86             (void) snprintf (buf, sizeof(buf), CATGETS(Set_UAS_MMDB, 3,
87                                         "Ignoring invalid Infolib path: %s"),
88                                         (char *) infoLibPath);
89             UAS_ErrorMsg theError;
90             theError.fErrorMsg = buf;
91             UAS_Common::send_message (theError);
92 #endif
93             rval = 0;
94         } end_try;
95     }
96     return rval;
97 }
98
99 // check to make sure duplicate infolibs are not added.
100 // for a duplicate infolib, just return a pointer to
101 // the already-existing infolib.
102 // (Duplicate infolib means infolibs with the same lid (uid))
103 MMDB *
104 MMDB_Factory::getMMDB (const UAS_String &infoLibPath) {
105     int i;
106     UAS_String uid(fOLIASDB->getInfoLibUid((char*)infoLibPath));
107     for (i = 0; i < fMMDBList.numItems(); i ++) {
108         if (uid == fMMDBList[i]->infoLibUid())
109             return fMMDBList[i];
110     }
111     for (i  = 0; i < fDeadMMDBList.numItems(); i ++) {
112         if (uid == fDeadMMDBList[i]->infoLibUid())
113             return fDeadMMDBList[i];
114     }
115     return createMMDB (infoLibPath);
116 }
117
118 void
119 MMDB_Factory::resolveLocator (const UAS_String &loc,
120                               MMDB *&returnMMDB,
121                               info_base *&returnInfoBase) {
122     returnMMDB = 0;
123     returnInfoBase = 0;
124     for (int i = 0; i < fMMDBList.numItems(); i ++) {
125         if ((returnInfoBase = fMMDBList[i]->infolib()->
126                 getInfobaseByComponent(loc, info_lib::LOC))) {
127             returnMMDB = fMMDBList[i];
128             return;
129         }
130     }
131 }
132
133 MMDB *
134 MMDB_Factory::getMMDBFromObject (UAS_Pointer<UAS_Common> theDoc) {
135     if (theDoc->implementation_type() != "mmdb")
136         return 0;
137     switch (theDoc->type()) {
138         case UAS_LIBRARY: {
139             MMDB_Library *l = (MMDB_Library *) ((UAS_Common *) theDoc);
140             return &(l->mmdb());
141         }
142         case UAS_BOOKCASE: {
143             MMDB_BookCase *c = (MMDB_BookCase *) ((UAS_Common *) theDoc);
144             return &(c->mmdb());
145         }
146         case UAS_BOOK:
147         case UAS_SECTION: {
148             MMDB_Section *s =  (MMDB_Section *) ((UAS_Common *) theDoc);
149             return &(s->mmdb());
150         }
151         default:
152             return 0;
153     }
154 }
155
156 UAS_Pointer<UAS_Common>
157 MMDB_Factory::create_object (const UAS_String &locator) {
158     MMDB_URL curURL;
159     curURL.locator (locator);
160     MMDB *theMMDB = getMMDB (curURL.fInfoLib);
161     info_base *theInfoBase = 0;
162     if (theMMDB == 0) {
163         if (curURL.fLocator != "") {
164             resolveLocator (curURL.fLocator, theMMDB, theInfoBase);
165             if (theMMDB == 0) {
166                 throw (CASTEXCEPT Exception());
167             } else {
168                 UAS_Pointer<UAS_Common> rval =
169                     new MMDB_Section (*theMMDB, curURL.fLocator);
170                 if (curURL.fType == "collection")
171                     return new UAS_Collection (rval);
172                 return rval;
173             }
174         }
175     }
176
177     if (theMMDB && curURL.fLocator != "") {
178         UAS_Pointer<UAS_Common> rval =
179                 new MMDB_Section (*theMMDB, curURL.fLocator);
180         if (curURL.fType == "collection")
181             return new UAS_Collection (rval);
182         return rval;
183     } else if (theMMDB && curURL.fInfoBase != "") {
184         return new UAS_Collection(new MMDB_BookCase(*theMMDB,curURL.fInfoBase));
185     } else if (theMMDB && curURL.fInfoLib != "") {
186         return new UAS_Collection (new MMDB_Library(*theMMDB));
187     } else {
188         throw (CASTEXCEPT Exception());
189     }
190 }
191
192 UAS_Pointer<UAS_Common>
193 MMDB_Factory::create_relative_object (const UAS_String &locator,
194                                UAS_Pointer<UAS_Common> theDoc) {
195
196     //
197     //  First, try to get the object by using the current
198     //  MMDB information library.
199     //
200     MMDB *theMMDB = getMMDBFromObject (theDoc);
201     if (theMMDB) {
202         info_base *ib = theMMDB->infolib()->
203             getInfobaseByComponent(locator, info_lib::LOC);
204         if (ib) {
205             // need to pass precise id to the constructor
206             return new MMDB_Section (*theMMDB, locator);
207         }
208     }
209
210     //
211     //  Couldn't find it in theDoc's infolib. Try all the infolibs
212     //  we know about.
213     //
214     for (int i = 0; i < fMMDBList.numItems(); i ++) {
215         info_base *ib = fMMDBList[i]->infolib()->
216                 getInfobaseByComponent(locator, info_lib::LOC);
217         if (ib) {
218             // need to pass precise id to the constructor
219             return new MMDB_Section(*(fMMDBList[i]), locator);
220         }
221     }
222
223     return UAS_Pointer<UAS_Common>(NULL);
224 }
225
226 UAS_Pointer<UAS_EmbeddedObject>
227 MMDB_Factory::create_embedded_object (const UAS_String &locator) {
228     for (int i = 0; i < fMMDBList.numItems(); i ++) {
229         info_base *ib = fMMDBList[i]->infolib()->
230                 getInfobaseByComponent(locator, info_lib::GRA);
231         if (ib) {
232             return new MMDB_EmbeddedObject (*fMMDBList[i], ib, locator);
233         }
234     }
235     throw (CASTEXCEPT Exception());
236 }
237
238 UAS_Pointer<UAS_EmbeddedObject>
239 MMDB_Factory::create_relative_embedded_object (const UAS_String &locator,
240                                UAS_Pointer<UAS_Common> theDoc) {
241     //
242     //  First try resolving to theDoc's infolib
243     //
244     MMDB *theMMDB = getMMDBFromObject (theDoc);
245     if (theMMDB) {
246         info_base *ib = theMMDB->infolib()->
247                 getInfobaseByComponent(locator, info_lib::GRA);
248         if (ib) {
249             return new MMDB_EmbeddedObject (*theMMDB, ib, locator);
250         }
251     }
252
253     //
254     //  Cross-infolib link. Iterate through the list of infolibs.
255     //
256     for (int i = 0; i < fMMDBList.numItems(); i ++) {
257         info_base *ib = fMMDBList[i]->infolib()->
258                 getInfobaseByComponent(locator, info_lib::GRA);
259         if (ib) {
260             return new MMDB_EmbeddedObject (*(fMMDBList[i]), ib, locator);
261         }
262     }
263     throw (CASTEXCEPT Exception());
264 }
265
266 void
267 MMDB_Factory::initializeFactory (UAS_List<UAS_String>& libs) {
268     //
269     //  Take DTINFO_INFOLIB_PATH and split out the colon-separated
270     //  paths. Create an MMDB object for each path and, if creation
271     //  was successful, add it to our list of infolibs. Send messages
272     //  for each invalid 
273     //
274     //char *libenv = getenv ("DTINFO_INFOLIB_PATH");
275     //if (!libenv) {
276         //return;
277     //}
278     //UAS_String libstr (libenv);
279     //UAS_List<UAS_String> fields = libstr.splitFields (':');
280     //for (int i = 0; i < fields.length(); i ++) {
281         //(void) getMMDB (*(UAS_String*)fields[i]);
282     //}
283     for (unsigned int i = 0; i < libs.length(); i ++) {
284         //  If this call doesn't create a new MMDB, it sends
285         //  an error message to the application.
286         (void) getMMDB (*(UAS_String*)libs[i]);
287     }
288 }
289
290 void
291 MMDB_Factory::finalizeFactory () {
292     while (fMMDBList.numItems() > 0) {
293         MMDB *dead = fMMDBList[0];
294         fMMDBList.remove(dead);
295         delete dead;
296     }
297     while (fDeadMMDBList.numItems() > 0) {
298         MMDB *deaddead = fDeadMMDBList[0];
299         fDeadMMDBList.remove(deaddead);
300         delete deaddead;
301     }
302     delete fOLIASDB;
303     fOLIASDB = 0;
304 }
305
306 UAS_List<UAS_String>
307 MMDB_Factory::rootLocators () {
308     //
309     // CHANGE THIS TO BE UAS_ObjList...
310     //
311     UAS_List<UAS_String> rval;
312     for (int i = 0; i < fMMDBList.numItems(); i ++) {
313         MMDB_URL cur;
314         cur.fType = "collection";
315         cur.fInfoLib = fMMDBList[i]->infoLibPath();
316         rval.insert_item (new UAS_String (cur.locator()));
317     }
318     return rval;
319 }
320
321 void
322 MMDB_Factory::destroy_root_object (UAS_Pointer<UAS_Common> theRoot) {
323     if (theRoot->implementation_type() != "mmdb" ||
324         theRoot->type() != UAS_LIBRARY)
325         throw(CASTEXCEPT Exception());
326     MMDB_Library *theLib = (MMDB_Library *) (UAS_Common *) theRoot;
327     MMDB *deadMMDB = &(theLib->mmdb());
328     int i;
329     for (i = 0; i < fMMDBList.numItems(); i ++)
330         if (fMMDBList[i] == deadMMDB)
331             break;
332     if (i >= fMMDBList.numItems())
333         throw(CASTEXCEPT Exception());
334
335     // remove deadMMDB before sending msg because the user
336     // can possibly inquire mmdb list on the thread.
337     fMMDBList.remove (deadMMDB);
338
339     //  Give the user a chance to blow away all objects associated
340     //  with this library.
341     //
342     UAS_LibraryDestroyedMsg theMsg (theRoot);
343     UAS_Common::send_message (theMsg);
344
345     //  Do the final damage.
346     delete deadMMDB;
347 }
348
349 UAS_String
350 MMDB_Factory::genInfolibName () {
351     static int counter = 0;
352     char buf[BUFSIZ];
353     (void) snprintf (buf, sizeof(buf),
354                 CATGETS(Set_UAS_MMDB, 4, "DtMmdb Library %d"), ++counter);
355     return UAS_String (buf);
356 }
357
358 ///////////////////////////////////////////////////////////////////////////////
359 ///////////////////////////////////////////////////////////////////////////////
360 //
361 //  MMDB_URL
362 //
363 ///////////////////////////////////////////////////////////////////////////////
364 ///////////////////////////////////////////////////////////////////////////////
365
366 MMDB_URL::MMDB_URL () {
367 }
368
369 UAS_String
370 MMDB_URL::locator () {
371     UAS_String rval = "mmdb:";
372     int hasStuff = 0;
373     if (fInfoLib != "") {
374         rval = rval + "INFOLIB=" + fInfoLib;
375         hasStuff ++;
376     }
377     if (fInfoBase != "") {
378         if (hasStuff)
379             rval = rval + "&";
380         rval = rval + "BOOKCASE=" + fInfoBase;
381         hasStuff ++;
382     }
383     if (fLocator != "") {
384         if (hasStuff)
385             rval = rval + "&";
386         rval = rval + "LOCATOR=" + fLocator;
387         hasStuff ++;
388     }
389     if (fType == "") {
390         fType = "collection"; // default value
391     }
392     if (hasStuff)
393         rval = rval + "&";
394     rval = rval + "TYPE=" + fType;
395     hasStuff ++;
396
397     return rval;
398 }
399
400 void
401 MMDB_URL::installPair (const UAS_String &key, const UAS_String &value) {
402     if (key == "INFOLIB") {
403         fInfoLib = value;
404     } else if (key == "BOOKCASE") {
405         fInfoBase = value;
406     } else if (key == "TYPE") {
407         fType = value;
408     } else if (key == "LOCATOR") {
409         fLocator = value;
410     }
411 }
412
413 void
414 MMDB_URL::locator (const UAS_String &in) {
415     UAS_String access, rest;
416     in.split (':', access, rest);
417     UAS_List<UAS_String> pairs = rest.splitFields ('&');
418     for (unsigned int i = 0; i < pairs.length(); i ++) {
419         UAS_String key, value;
420         pairs[i]->split ('=', key, value);
421         installPair (key, value);
422     }
423 }
424