dtinfo subtree dtinfo
[oweals/cde.git] / cde / programs / dtinfo / dtinfo / src / Agents / SearchScopeList.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 librararies and programs; if not, write
20  * to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
21  * Floor, Boston, MA 02110-1301 USA
22  */
23 /*      Copyright (c) 1994,1995,1996 FUJITSU LIMITED    */
24 /*      All Rights Reserved                             */
25
26 /*
27  * $XConsortium: SearchScopeList.C /main/15 1996/09/27 10:16:12 cde-hal $
28  *
29  * Copyright (c) 1993 HAL Computer Systems International, Ltd.
30  * All rights reserved.  Unpublished -- rights reserved under
31  * the Copyright Laws of the United States.  USE OF A COPYRIGHT
32  * NOTICE IS PRECAUTIONARY ONLY AND DOES NOT IMPLY PUBLICATION
33  * OR DISCLOSURE.
34  * 
35  * THIS SOFTWARE CONTAINS CONFIDENTIAL INFORMATION AND TRADE
36  * SECRETS OF HAL COMPUTER SYSTEMS INTERNATIONAL, LTD.  USE,
37  * DISCLOSURE, OR REPRODUCTION IS PROHIBITED WITHOUT THE
38  * PRIOR EXPRESS WRITTEN PERMISSION OF HAL COMPUTER SYSTEMS
39  * INTERNATIONAL, LTD.
40  * 
41  *                         RESTRICTED RIGHTS LEGEND
42  * Use, duplication, or disclosure by the Government is subject
43  * to the restrictions as set forth in subparagraph (c)(l)(ii)
44  * of the Rights in Technical Data and Computer Software clause
45  * at DFARS 252.227-7013.
46  *
47  *          HAL COMPUTER SYSTEMS INTERNATIONAL, LTD.
48  *                  1315 Dell Avenue
49  *                  Campbell, CA  95008
50  * 
51  */
52
53 #include "UAS.hh"
54 #include "Support/UtilityFunctions.hh"
55
56 #define C_Buffer
57 #define L_Basic
58
59 #define C_xList
60 #define L_Support
61
62 #define C_SearchScopeList
63 #define C_SearchScopeAgent
64 #define L_Agents
65
66 #define C_UserPreference
67 #define C_StringPref
68 #define L_Preferences
69
70 #define C_MessageMgr
71 #define C_SearchScopeMgr
72 #define C_EnvMgr
73 #define L_Managers
74
75 #include <Prelude.h>
76 #include <string.h>
77
78 #ifdef SVR4
79 #ifndef USL
80 #include <libintl.h>
81 #endif
82 #endif
83
84 #include <string.h>
85 #include <iostream>
86 using namespace std;
87
88 #include "Other/XmStringLocalized.hh"
89 #include "Managers/CatMgr.hh"
90
91 #include "Registration.hh"
92
93 // rtp - 4/24/95 : Added a very simple buffer class for use in
94 //                 this module. (Original code written by swm.)
95 SimpleBuffer::SimpleBuffer ()
96 : f_data(NULL),
97   f_data_len(0)
98 {
99 }
100
101 SimpleBuffer::~SimpleBuffer ()
102 {
103   delete [] f_data;
104   f_data = NULL;
105   f_data_len = 0;
106 }
107
108 void
109 SimpleBuffer::write (char *new_data)
110 {
111   int new_len = 0;
112
113   if (f_data)
114     new_len = strlen (f_data);
115   new_len += strlen (new_data);
116   // manual realloc
117   char *new_buf = new char [new_len + 1];
118   if (f_data)
119     (void) strcpy (new_buf, f_data);
120   else
121     *new_buf = 0;
122   delete [] f_data;
123   f_data = new_buf;
124   (void) strcat (f_data, new_data);
125 }
126
127 char *
128 SimpleBuffer::data ()
129 {
130   return f_data;
131 }
132
133 SearchScopeList::SearchScopeList (SearchScopeAgent *ssa)
134 : f_search_scope_agent (ssa)
135 {
136   f_buffer = new SimpleBuffer;
137 }
138
139 SearchScopeList::~SearchScopeList ()
140 {
141   delete f_buffer;
142 }
143
144 void
145 SearchScopeList::save()
146 {
147   List_Iterator<UAS_SearchScope *> i (this);
148   UAS_SearchScope *scope;
149   char scratch[256];
150   Buffer buffer, temp_buffer;
151
152   // for each search scope do
153   for (; i != 0; i++)
154   {
155     scope = i.item();
156     if (scope->deleted() || scope->read_only())
157       continue;
158
159     buffer.reset();
160
161     // Store the scope component mask.
162     sprintf (scratch, "%d;", scope->search_zones().zones());
163     buffer.write (scratch, sizeof (char), strlen (scratch));
164
165     // get the list of bookcases for the current scope
166     UAS_PtrList<UAS_BookcaseEntry> bcases = scope->bookcases();
167
168     // If there are no bookcases in the scope, there is a problem
169     // somewhere; skip to the next scope.
170     if (bcases.numItems() <= 0)
171       continue;
172
173     UAS_BookcaseEntry *bce;
174
175     if(env().debug())
176     {
177       cerr << endl;
178       cerr << "Save Scope: " << scope->name();
179     }
180
181     // loop for each bookcase in the search scope
182     for (int bc = 0; bc < bcases.numItems(); bc++)
183     {
184       bce = bcases[bc];
185
186       // write bookcase id and name to buffer
187       const char *name = bce->name();
188       const char *bid = bce->bid();
189       if (bc > 0)
190         sprintf (scratch, "&%s(%s)", bid, name);
191       else
192         sprintf (scratch, "%s(%s)", bid, name);
193       buffer.write(scratch, sizeof (char), strlen(scratch));
194
195       if(env().debug())
196         cerr << scratch;
197
198       // See if individual books are selected.
199       // Store the books by book number.
200       UAS_ObjList<int> booklist = bce->book_list();
201
202       // if there are no books--entire bookcase is selected
203       if (booklist.numItems() > 0)
204       {
205         for (int bk = 0; bk < booklist.numItems(); bk++)
206         {
207           sprintf (scratch, ",%d", booklist[bk]);
208           buffer.write(scratch, sizeof (char), strlen(scratch));
209         }
210         if(env().debug())
211           cerr << scratch << endl;
212       }
213     }
214     buffer.write ("\0", sizeof (char), 1);
215
216     // Get the right preference object.
217     sprintf (scratch, "Scope.%s", scope->name());
218     StringPref store (scratch);
219
220     // Update its value.
221     ON_DEBUG (printf ("WRITING: %s: %s\n", scratch, buffer.data()));
222     store.value (buffer.data());
223   }
224
225   // Now dump the name of each of the scopes.
226   buffer.reset();
227   const char *name;
228   for (i.reset(); i != 0; i++)
229   {
230     if (i.item()->read_only())
231       continue;
232     name = i.item()->name();
233     buffer.write (name, sizeof (char), strlen (name));
234     buffer.write (",", sizeof (char), 1);
235   }
236   // Backup and overwrite the trailing comma if there is one.
237   if (buffer.point() != buffer.data())
238     buffer.point (buffer.point() - sizeof (char));
239   buffer.write ("\0", sizeof (char), 1);
240
241   StringPref scopes ("Scopes");
242
243   //  buffer used to write out all scope names
244   SimpleBuffer output_buf;
245
246   //  if there's invalid scope names in f_buffer
247   //               to write out...
248   if (f_buffer->data())
249   {
250     //  copy the invalid names to output buffer
251     output_buf.write(f_buffer->data());
252     //  if buffer with valid names is "empty",
253     //  i.e., only contains '\0' (see code above)
254     if (buffer.length() == 1)
255     {
256       // overwrite the trailing comma at end of
257       // the invalid scope names
258       char *data = output_buf.data();
259       int   len = strlen(data);
260       data[len-1] = '\0';
261     }
262     // otherwise concatanate the valid names
263     else
264       output_buf.write((char *)buffer.data());
265   }
266   // otherwise just write out the valid names
267   else
268     output_buf.write((char *)buffer.data());
269
270   //  write out all scope names to the prefs file
271   scopes.value (output_buf.data());
272   ON_DEBUG (printf ("SCOPES: %s\n", output_buf.data()));
273
274   // Flush the changes to disk.
275   UserPreference::flush_preferences();
276 }
277
278 void
279 SearchScopeList::restore()
280 {
281   char scratch[1024];
282   char basename[256];
283   int  i;
284   UAS_SearchScope *s;
285
286   // get the list of bookcase names
287   UAS_List<UAS_Common> bcaseList = bookcaseList ();
288   UAS_List<UAS_Common> libs = f_search_scope_agent->list();
289
290   // create the set of standard scopes
291   UAS_PtrList<UAS_BookcaseEntry>  bcases;
292
293   //
294   // Create the scope for the Current Section
295   //
296   s = f_search_scope_agent->create_scope(
297         (char*)UAS_String(CATGETS(Set_Messages, 30, "Current Section")),
298         bcases, f_section, FALSE);
299   s->set_read_only();
300
301   //
302   // Create a scope for All Libraries
303   //
304   bcases = f_search_scope_agent->bookcase_list();
305   s = f_search_scope_agent->create_scope(
306         (char*)UAS_String(CATGETS(Set_SearchScopeAgent, 4, "All Libraries")),
307         bcases, f_all, FALSE);
308   s->set_read_only();
309   bcases.clear();
310
311   //
312   // Create a scope for each infolib
313   //
314   for (i = 0; i < libs.length(); i++) {
315       UAS_String libs_lid(libs[i]->lid());
316       s = f_search_scope_agent->create_infolib_scope(libs_lid);
317   }
318   
319   // create all named scopes in preferences file
320   create_named_scopes();
321   
322   // rtp - 4/24/95 : if invalid scopes found then warn the user
323   if (f_buffer->data())
324     search_scope_mgr().show_warning(True);
325   // do not show dialog at this point--toplevel shell has not
326   // yet been realized. Just set the flag so dialog can be
327   // shown later.
328   //   message_mgr().warning_dialog (
329   //    (char*)UAS_String(CATGETS(Set_Messages, 31,
330   //    "Ignoring invalid scopes in your profile.")));
331 }
332
333 // create all valid named scopes in preferences file
334 void
335 SearchScopeList::create_named_scopes()
336 {
337   char scratch[1024];
338   bool is_scope_valid;
339   UAS_PtrList<UAS_BookcaseEntry>  bookcase_list;
340   UAS_BookcaseEntry              *bce;
341
342   // get list of scope names from preference file
343   StringPref scopes ("Scopes");
344   UAS_String scope_list (scopes.value());
345   UAS_List<UAS_String> scope_names = scope_list.splitFields (',');
346
347   // reset invalid scope name buffer
348   if (f_buffer != NULL)
349   {
350     delete f_buffer;
351     f_buffer = new SimpleBuffer;
352   }
353
354   // retrieve scopes from preference file and validate each one
355   for (int sname = 0; sname < scope_names.length(); sname++)
356   {
357     is_scope_valid = True;
358
359     // Get the specified scope from preferences.
360     UAS_String ss = *(UAS_String*) scope_names[sname];
361     sprintf (scratch, "Scope.%s", (char*)ss);
362     StringPref scope (scratch);
363
364     // Grab the component mask.
365     unsigned int mask = 0;
366     int i;
367     sscanf (scope.value(), "%d%n", &mask, &i);
368     if (mask == 0)
369     {
370       // rtp - 4/24/95 : bad mask means invalid scope
371       is_scope_valid = FALSE;
372     }
373
374     // skip past component mask
375     const char *scope_ptr = scope.value() + i;
376     scope_ptr += 1;
377
378     // get list of bookcases
379     UAS_String scope_string(scope_ptr);
380     UAS_List<UAS_String>bookcases = scope_string.splitFields ('&');
381
382     if(env().debug())
383     {
384       cerr << endl;
385       cerr << "Restore Scope." << (char*)ss;
386       cerr << ": " << mask << ";";
387     }
388
389     // loop once for each bookcase in search scope. create a
390     // bookcase entry for each valid bookcase. if bookcase
391     // is invalid, invalidate the scope.
392     for (int bname = 0; bname < bookcases.length(); bname++)
393     {
394       UAS_String str = *(UAS_String*)bookcases[bname];
395       UAS_List<UAS_String>bc_list = str.splitFields (',');
396
397       bce = create_bcase_entry(bc_list);
398       if (bce == NULL)
399       {
400         is_scope_valid = False;
401         if(env().debug())
402           cerr << "  >>>>Scope is invalid" << endl;
403         break;
404       }
405
406       bookcase_list.append(bce);
407     }
408
409     // get scope name
410     UAS_String sn = *(UAS_String*)scope_names[sname];
411     if(is_scope_valid)
412     {
413       UAS_SearchScope *s = f_search_scope_agent->create_scope (
414                   sn, bookcase_list, mask, False);
415     }
416     else
417     {
418       // rtp - 4/24/95 : otherwise store its name for use later;
419       //                 see SearchScopeList::save routine above
420       sprintf(scratch, "%s%s", (char*)sn, ",");
421       f_buffer->write (scratch);
422     }
423     // reset list for next turn
424     bookcase_list.clear();
425   } // for (int sname = 0)
426 }
427
428 // Check to see if bookcase is valid on system. If bid is valid,
429 // return true, otherwise, return false.
430 UAS_Pointer<UAS_Common>
431 SearchScopeList::validate_bookcase(UAS_String &bid)
432 {
433   // validate bookcase id
434   UAS_List<UAS_Common> libs = f_search_scope_agent->list();
435
436   for (int i = 0; i < libs.length(); i++)
437   {
438     UAS_List<UAS_Common> kids = libs[i]->children();
439     for (int j = 0; j < kids.length(); j++)
440     {
441       if(kids[j]->bid() == bid)
442       {
443         return  kids[j];
444       }
445     }
446   }
447   return (UAS_Pointer<UAS_Common>)NULL;
448 }
449
450 // Create a bookcase_entry and return it.
451 // The input to this function is a bookcase list.
452 // The first element is a bookcase id. All subsequent elements
453 // are books:
454 //      BCID [book1 book2 book3 ...]
455 //
456 UAS_BookcaseEntry *
457 SearchScopeList::create_bcase_entry(UAS_List<UAS_String> &bc_list)
458 {
459   UAS_Pointer<UAS_Common> uas_bookcase;
460
461   // get BCID--the first element in list
462   UAS_String bs = *(UAS_String*)bc_list[0];
463   char buff[40];
464   sscanf((char*)bs,"%[^)(]", buff);
465   UAS_String bid = UAS_String(buff, strlen(buff));
466
467   // validate BCID
468   uas_bookcase = validate_bookcase(bid);
469   if (uas_bookcase == (UAS_Pointer<UAS_Common>)NULL)
470     return (UAS_BookcaseEntry*)NULL;
471
472   // create new bookcase entry object
473   UAS_BookcaseEntry *bce = new UAS_BookcaseEntry(uas_bookcase);
474
475   if(env().debug())
476     cerr << "," << (char*)uas_bookcase->bid();
477
478   // Check to see if entire bookcase is selected or are there
479   // individual books selected.
480   if (bc_list.length() > 1)
481   {
482     // individual books have been selected.
483     int book_num;
484     UAS_ObjList<int> booklist;
485
486     for (int book = 1; book < bc_list.length(); book++)
487     {
488       UAS_String abook = *(UAS_String*)bc_list[book];
489       if(sscanf ((char*)abook, "%d", &book_num) == 1)
490       {
491          booklist.append (book_num);
492       }
493     }
494     if(env().debug())
495     {
496       for (int bk=0; bk < booklist.numItems(); bk++)
497         cerr << "," << booklist[bk];
498       cerr << endl;
499     }
500     bce->set_book_list(booklist);
501   }
502
503   return bce;
504 }
505
506 // These routines are called from the SearchScopeAgent; They
507 // maintain a list of BitHandles that directly coorespond to
508 // the scopes maintained in the SearchScopeList (i.e., this).
509 // It's crucial that if a scope is modified in SearchScopeList
510 // (i.e., added, removed, etc.), it's corresponding BitHandle
511 // in f_handle_list is modified in lock-step. -rtp
512
513 // Note: the index is zero (0) based. -rtp
514 void
515 SearchScopeList::add_handle(BitHandle handle, int index)
516 {
517     // index of -1 means to append
518     if (index == -1) {
519         f_handle_list.append(handle);
520         return;
521     }
522
523     List_Iterator<BitHandle> h (f_handle_list);
524     for (int i = 0; i < index; i++, h++);
525     f_handle_list.insert_before (h, handle);
526 }
527
528 // Note: this routine must be called *before* the remove method
529 // is called for the scope (...otherwise it won't find scope in
530 // this, duh). -rtp
531 void
532 SearchScopeList::remove_handle(UAS_SearchScope *scope)
533 {
534     // first, find index into search scope list
535     List_Iterator<UAS_SearchScope *> s (this);
536     int i;
537     for (i = 0; s != 0 && s.item() != scope; s++, i++);
538     // if can't find scope in list then something is hosed
539     if (s == NULL)
540         return;
541     // next, find the bit handle located at this index in handle list
542     List_Iterator<BitHandle> h (f_handle_list);
543     for (int j = 0; j < i && h != 0; j++, h++);
544     // if this happens then something is hosed
545     if (h == NULL)
546         return;
547     // and finally, remove it
548     BitHandle bh = h.item();
549     f_handle_list.remove(bh);
550 }
551
552 // Routine to lookup BitHandle based on UAS_SearchScope *
553 BitHandle
554 SearchScopeList::lookup_handle(UAS_SearchScope *scope)
555 {
556   // first, find index into search scope list
557   List_Iterator<UAS_SearchScope *> s (this);
558
559   int i;
560   for (i = 0; s != 0 && s.item() != scope; s++, i++);
561   // if can't find scope in list then something is hosed
562   if (s == NULL)
563     return 0;
564
565   // next, find the bit handle located at this index in handle list
566   List_Iterator<BitHandle> h (f_handle_list);
567
568   for (int j = 0; j < i && h != 0; j++, h++);
569   // if this happens then something is hosed
570   if (h == NULL)
571     return 0;
572
573   // and finally, return handle
574   BitHandle bh = h.item();
575   return bh;
576 }