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