dtinfo subtree dtinfo
[oweals/cde.git] / cde / programs / dtinfo / dtinfo / src / Basic / NodeViewInfo.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) 1996 FUJITSU LIMITED      */
24 /*      All Rights Reserved                     */
25
26 /*
27  * $XConsortium: NodeViewInfo.C /main/17 1996/11/18 15:50:15 mustafa $
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 <limits.h>
54 #include <wchar.h>
55
56 #define C_NodeViewInfo
57 #define L_Basic
58
59 #define C_xList
60 #define L_Support
61
62 #define C_PixmapGraphic
63 #define L_Graphics
64
65 #define C_GraphicsMgr
66 #define C_MessageMgr
67 #define C_NodeMgr
68 #define C_NodeParser
69 #define L_Managers
70
71 #include "Prelude.h"
72
73 #include <DtI/LinkMgrP.h>
74
75 #undef self
76 #include <DtI/DisplayAreaP.h>
77 #include <DtI/FontI.h>
78 #include <DtI/FontAttrI.h>
79 #include <DtI/RegionI.h>
80
81 #include "OnlineRender/SegClientData.hh"
82
83 #include "UAS/DtSR/Util_Classes/DictIter.hh"
84
85 // /////////////////////////////////////////////////////////////////
86 // class constructor
87 // /////////////////////////////////////////////////////////////////
88
89 NodeViewInfo::NodeViewInfo (UAS_Pointer<UAS_Common> &node_ptr, _DtCvTopicInfo *topic)
90 : f_node_ptr (node_ptr),
91   f_topic(topic),
92   f_current_hit(NULL),
93   f_def_key(""),
94   f_def_val((unsigned long)-1),
95   f_color_dict(f_def_key, f_def_val)
96 {
97 #ifdef DEBUG
98   printf( "make NodeViewInfo %p\n\n", this );
99 #endif
100 }
101
102
103 /*
104    Recursively clean up our segment structures
105 */
106 static void
107 cleanup(_DtCvSegment *segment)
108 {
109   if (segment)
110     {
111       switch (segment->type & _DtCvPRIMARY_MASK)
112         {
113         case _DtCvCONTAINER:
114           if (segment->handle.container.id)
115             free (segment->handle.container.id);
116           cleanup (segment->handle.container.seg_list);
117           break;
118         case _DtCvSTRING:
119             if (segment->handle.string.string)
120                 delete (char*)(segment->handle.string.string);
121           if (segment->client_use) {
122             delete (SegClientData*)segment->client_use;
123             segment->client_use = NULL;
124           }
125           break;
126         case _DtCvTABLE:
127           {
128             _DtCvTable *table = &segment->handle.table ;
129             if (table->col_w)
130               {
131                 for (int i = 0 ; i < table->num_cols; i++)
132                   delete table->col_w[i] ;
133                 delete table->col_w ;
134
135               }
136             delete table->col_justify ;
137             delete table->justify_chars ;
138             char **ids = table->cell_ids ;
139             while (*ids)
140               delete *ids++ ;
141             delete table->cell_ids ;
142             _DtCvSegment **cells = table->cells ;
143             while (*cells)
144               cleanup(*cells++);
145             delete table->cells ;
146           }
147           break ;
148         case _DtCvMARKER:
149           delete segment->handle.marker ;
150           break;
151         case _DtCvREGION:
152           {
153             _DtHelpDARegion     *pReg = (_DtHelpDARegion*) segment->handle.region.info ;
154             DtHelpGraphicStruct *pGS  = (DtHelpGraphicStruct *) pReg->handle;
155             delete pGS ;
156             delete pReg ;
157             if (segment->client_use) {
158               // Note: ((SegClientData*)segment->client_use)->GraphicHandle()
159               //       is deleted separately through f_pixmap_list
160               delete (SegClientData*)segment->client_use;
161               segment->client_use = NULL;
162             }
163           }
164           break ;
165         }
166       cleanup(segment->next_seg);
167
168       delete segment;
169     }
170 }
171
172 // /////////////////////////////////////////////////////////////////
173 // class destructor
174 // /////////////////////////////////////////////////////////////////
175
176 NodeViewInfo::~NodeViewInfo()
177 {
178   _DtLinkDbDestroy(f_topic->link_data); // kill the link database
179
180   cleanup(f_topic->seg_list);   // kill the segments and their items
181
182   f_topic->seg_list = 0 ;
183   delete f_topic ;              // sayonara
184
185   if (f_pixmap_list != NULL)
186   {             // explicitly cleanup graphics in f_pixmap_list
187     List_Iterator<UAS_Pointer<Graphic> > gli (f_pixmap_list) ;
188     while (gli)
189     {
190 #ifdef DEBUG
191       printf( "delete UAS_Pointer<Graphic> gli.item() = %p\n",
192                 (void*)gli.item() );
193 #endif
194       f_pixmap_list.remove(gli) ;
195     }
196   }
197 #ifdef DEBUG
198   printf( "kill NodeViewInfo %p\n\n", this );
199 #endif
200 }
201
202 void
203 NodeViewInfo::add_graphic(UAS_Pointer<Graphic> &pg)
204 {
205   f_pixmap_list.append(pg);
206
207 #ifdef DEBUG
208   printf( "NodeViewInfo: add UAS_Pointer<Graphic> %p\n", (void*)pg );
209   if (f_pixmap_list != NULL)
210   {
211       List_Iterator<UAS_Pointer<Graphic> > gli (f_pixmap_list) ;
212       printf( "graphics list is now: " );
213       while (gli)
214       {
215         printf( " %p ", (void*)gli.item() );
216         gli++;
217       }
218       printf( "\n" );
219   }
220 #endif
221 }
222
223 static unsigned int
224 DtCvStrLen(_DtCvSegment* seg)
225 {
226     if (seg == NULL || (seg->type & _DtCvPRIMARY_MASK) != _DtCvSTRING)
227         return 0;
228
229     unsigned int len = 0;
230
231     if (seg->type & _DtCvWIDE_CHAR) {
232         wchar_t* seg_str = (wchar_t*)seg->handle.string.string;
233         for (; *seg_str; seg_str++, len++);
234     }
235     else {
236         char* seg_str = (char*)seg->handle.string.string;
237         for (; *seg_str; seg_str++, len++);
238     }
239
240     return len;
241 }
242
243 static unsigned int
244 DtCvStrVccToIndex(_DtCvSegment* seg, unsigned int vcc)
245 {
246     if (seg == NULL || (seg->type & _DtCvPRIMARY_MASK) != _DtCvSTRING
247                     || seg->client_use == NULL)
248         return (unsigned int)-1;
249
250     unsigned int index = 0;
251
252     unsigned int rel_vcc;
253     if ((rel_vcc = vcc - ((SegClientData*)seg->client_use)->vcc()) < 0)
254         return (unsigned int)-1;
255
256     if (seg->type & _DtCvWIDE_CHAR) {
257         wchar_t* seg_str = (wchar_t*)seg->handle.string.string;
258         for (; *seg_str && rel_vcc > 0; seg_str++, index++) {
259             if (*seg_str != ' ' && *seg_str != '\t' && *seg_str != '\n')
260                 rel_vcc--;
261         }
262         if (*seg_str == 0 && rel_vcc > 0)
263             index = (unsigned int)-1;
264         else {
265             for (; *seg_str; seg_str++, index++) {
266                 if (*seg_str != ' ' && *seg_str != '\t' && *seg_str != '\n')
267                     break;
268             }
269         }
270     }
271     else {
272         unsigned char* seg_str = (unsigned char*)seg->handle.string.string;
273         for (; *seg_str && rel_vcc > 0; seg_str++, index++) {
274             if (*seg_str != ' ' && *seg_str != '\t' &&
275                                    *seg_str != '\n' && *seg_str != 0xA0)
276                 rel_vcc--;
277         }
278         if (*seg_str == 0 && rel_vcc > 0)
279             index = (unsigned int)-1;
280         else {
281             for (; *seg_str; seg_str++, index++) {
282                 if (*seg_str != ' ' && *seg_str != '\t' &&
283                                        *seg_str != '\n' && *seg_str != 0xA0)
284                     break;
285             }
286         }
287     }
288
289     return index;
290 }
291
292 static unsigned int
293 DtCvStrVcLenSync(_DtCvSegment* seg)
294 {
295     if (seg == NULL || (seg->type & _DtCvPRIMARY_MASK) != _DtCvSTRING
296                     || seg->client_use == NULL)
297         return (unsigned int)-1;
298
299     unsigned int vclen = 0;
300
301     if (seg->type & _DtCvWIDE_CHAR) {
302         wchar_t* seg_str = (wchar_t*)seg->handle.string.string;
303         for (; *seg_str; seg_str++) {
304             if (*seg_str != ' ' && *seg_str != '\t' && *seg_str != '\n')
305                 vclen++;
306         }
307     }
308     else {
309         unsigned char* seg_str = (unsigned char*)seg->handle.string.string;
310         for (; *seg_str; seg_str++) {
311             if (*seg_str != ' ' && *seg_str != '\t' &&
312                                    *seg_str != '\n' && *seg_str != 0xA0)
313                 vclen++;
314         }
315     }
316
317     // synchronization
318     ((SegClientData*)seg->client_use)->vclen() = vclen;
319
320     return vclen;
321 }
322
323 static unsigned int
324 DtCvStrVcLen(_DtCvSegment* seg)
325 {
326     if (seg == NULL || (seg->type & _DtCvPRIMARY_MASK) != _DtCvSTRING)
327         return 0;
328
329     return ((SegClientData*)seg->client_use)->vclen();
330 }
331
332 static unsigned int
333 DtCvStrVcc(_DtCvSegment* seg)
334 {
335     if (seg == NULL || (seg->type & _DtCvPRIMARY_MASK) != _DtCvSTRING
336                     || seg->client_use == NULL)
337         return (unsigned int)-1;
338
339     return ((SegClientData*)seg->client_use)->vcc();
340 }
341
342 static void
343 DtCvStrVcc(_DtCvSegment* seg, unsigned int vcc)
344 {
345     if (seg == NULL || (seg->type & _DtCvPRIMARY_MASK) != _DtCvSTRING
346                     || seg->client_use == NULL)
347         return;
348
349     ((SegClientData*)seg->client_use)->vcc() = vcc;
350 }
351
352 // Chop a segment into two separate segments.
353 // nc is the number of characters of the first segment.
354
355 _DtCvSegment*
356 chop_segment(_DtCvSegment* seg, unsigned int nc)
357 {
358     if (seg == NULL || (seg->type & _DtCvPRIMARY_MASK) != _DtCvSTRING)
359         return NULL;
360
361     if (nc == 0)
362         return NULL;
363
364     unsigned int seg_nc = DtCvStrLen(seg);
365
366     if (nc == seg_nc) {
367         assert( nc > 0 );
368         return seg;
369     }
370
371     unsigned long widec = seg->type & _DtCvWIDE_CHAR;
372
373     void* nseg_str;
374     if (widec) {
375         wchar_t* src  = (wchar_t*)seg->handle.string.string + nc;
376         wchar_t* dest = new wchar_t[seg_nc - nc + 1];
377         for (int i = 0; i < seg_nc - nc; i++)
378             dest[i] = src[i];
379         dest[seg_nc - nc] = '\0';
380         nseg_str = (void*)dest;
381
382         wchar_t* seg_str = (wchar_t*)seg->handle.string.string;
383         seg_str[nc] = '\0'; // chop seg string
384     }
385     else {
386         char* src  = (char*)seg->handle.string.string + nc;
387         char* dest = new char[seg_nc - nc + 1];
388         for (int i = 0; i < seg_nc - nc; i++)
389             dest[i] = src[i];
390         dest[seg_nc - nc] = '\0';
391         nseg_str = (void*)dest;
392
393         unsigned char* seg_str = (unsigned char*)seg->handle.string.string;
394         seg_str[nc] = '\0'; // chop seg string
395     }
396     DtCvStrVcLenSync(seg);
397
398     unsigned int seg_vcc   = DtCvStrVcc(seg);
399     unsigned int seg_vclen = DtCvStrVcLen(seg);
400
401 #ifdef SYMBOL_HIGHLIGHT
402     _DtCvSegment* symseg = new _DtCvSegment(*seg);
403     symseg->next_seg  = seg->next_seg;
404     symseg->next_disp = seg->next_disp;
405     seg ->next_seg  = symseg;
406     seg ->next_disp = symseg;
407
408     symseg->handle.string.string = new char[2];
409     *(unsigned char*) symseg->handle.string.string      = 0xA4;
410     *((unsigned char*)symseg->handle.string.string + 1) = 0x00;
411     symseg->client_use   = NULL;
412     symseg->internal_use = NULL;
413     symseg->type |=  _DtCvAPP_FLAG1;
414     symseg->type &= ~_DtCvWIDE_CHAR;
415
416     if (symseg->type & _DtCvNEW_LINE) // take _DtCvNEW_LINE over
417         seg->type &= ~_DtCvNEW_LINE;
418
419     symseg->type &=
420                 ~(_DtCvSEARCH_FLAG | _DtCvSEARCH_BEGIN | _DtCvSEARCH_END);
421
422     seg = symseg;
423 #endif
424
425     _DtCvSegment* nseg = new _DtCvSegment(*seg);
426     nseg->next_seg  = seg->next_seg;
427     nseg->next_disp = seg->next_disp;
428     seg ->next_seg  = nseg;
429     seg ->next_disp = nseg;
430
431     if (nseg->type & _DtCvNEW_LINE) // take _DtCvNEW_LINE over
432         seg->type &= ~_DtCvNEW_LINE;
433
434     if (widec)
435         nseg->type |= _DtCvWIDE_CHAR;
436
437     nseg->type &= ~_DtCvAPP_FLAG1;
438
439     nseg->type &= ~(_DtCvSEARCH_FLAG | _DtCvSEARCH_BEGIN | _DtCvSEARCH_END);
440
441     nseg->internal_use = NULL;
442
443     nseg->handle.string.string = nseg_str;
444
445     // set client_use properly
446     nseg->client_use = (_DtCvPointer)new SegClientData(_DtCvSTRING);
447     DtCvStrVcc(nseg, seg_vcc + seg_vclen);
448     DtCvStrVcLenSync(nseg);
449
450     return nseg;
451 }
452
453 // FUNCTION highlight_search_hit
454 // INPUT
455 //   vcc : vcc of the segment to be highlighted
456 //   len : character length of the segment to be highlighted
457 //
458 // RETURN
459 //   the segment to be highlighted
460
461 _DtCvSegment*
462 highlight_search_hit(_DtCvSegment* seg, unsigned int vcc, unsigned int len)
463 {
464     if (seg == NULL || (seg->type & _DtCvPRIMARY_MASK) != _DtCvSTRING)
465         return NULL;
466
467     if (len <= 0)
468         return NULL;
469
470     unsigned int seg_vcc = DtCvStrVcc(seg);
471     unsigned int seg_nc  = DtCvStrLen(seg);
472
473     if (vcc < seg_vcc) // vcc falls short
474         return NULL;
475
476     unsigned long widec = seg->type & _DtCvWIDE_CHAR;
477
478     // translate rel_vcc (vccs) into nseg_nc (characters)
479     unsigned int nseg_nc = DtCvStrVccToIndex(seg, vcc);
480     if (nseg_nc == (unsigned int)-1) // vcc is beyond segment
481         return NULL;
482
483 #ifdef DEBUG
484     fprintf(stderr, "(DEBUG) vcc=%d, index=%d, clen=%d\n", vcc, nseg_nc, len);
485 #endif
486
487     if (len == 0)
488         return NULL;
489     else if (seg_vcc == vcc && seg_nc == len)
490         return seg;
491
492     if (len > seg_nc - nseg_nc) { // len goes beyond this segment
493         if (seg->next_seg == NULL) {
494             len = seg_nc - nseg_nc;
495         }
496         else {
497             _DtCvSegment* sibling = seg->next_seg;
498             unsigned long type = sibling->type & _DtCvPRIMARY_MASK;
499             if (type != _DtCvSTRING || sibling->client_use == NULL ||
500                 DtCvStrVcc(sibling) == (unsigned int)-1 ||
501                 (seg->type & _DtCvWIDE_CHAR) != (sibling->type & _DtCvWIDE_CHAR)) {
502                 len = seg_nc - nseg_nc;
503             }
504             else { // let's merge segments
505                 seg->next_seg  = sibling->next_seg;
506                 seg->next_disp = sibling->next_disp;
507                 sibling->next_seg = NULL;
508                 sibling->next_disp = NULL;
509                 
510                 if (widec) {
511                     wchar_t* src = (wchar_t*)sibling->handle.string.string;
512                     wchar_t* dst = (wchar_t*)seg->handle.string.string;
513                     int len = wcslen(dst) + wcslen(src);
514                     seg->handle.string.string = (void*)
515                         realloc(seg->handle.string.string,
516                                         sizeof(wchar_t) * (len + 1));
517                     dst = (wchar_t*)seg->handle.string.string;
518                     wcscat(dst, src);
519                 }
520                 else {
521                     char* src = (char*)sibling->handle.string.string;
522                     char* dst = (char*)seg->handle.string.string;
523                     int len = strlen(dst) + strlen(dst);
524                     seg->handle.string.string = (void*)
525                         realloc(seg->handle.string.string, len + 1);
526                     dst = (char*)seg->handle.string.string;
527                     strcat(dst, src);
528                 }
529                 DtCvStrVcLenSync(seg);
530
531                 if (sibling->handle.string.string)
532                     free (sibling->handle.string.string);
533                 if (sibling->client_use) {
534                     delete (SegClientData*)sibling->client_use;
535                     sibling->client_use = NULL;
536                 }
537
538                 // NOTE: sibling is kept (i.e. not deleted)
539                 // this fact may cause problems in next highlight_search_hit
540
541                 return highlight_search_hit(seg, vcc, len);
542             }
543         }
544     }
545
546     if (nseg_nc) {
547 #ifdef DEBUG    
548         if (widec) {
549             char buf[MB_LEN_MAX + 1];
550             wchar_t* debug_p = (wchar_t*)seg->handle.string.string + nseg_nc;
551             int n = wctomb(buf, *debug_p);
552             assert( n >= 0 );
553             *(buf + n) = '\0';
554             fprintf(stderr, "(DEBUG) initial=%s\n", buf);
555         }
556         else {
557             char* debug_p = (char*)seg->handle.string.string + nseg_nc;
558             fprintf(stderr, "(DEBUG) initial=%c\n", *debug_p);
559         }
560 #endif
561         if ((seg = chop_segment(seg, nseg_nc)) == NULL)
562             return NULL;
563     }
564
565     if (len != seg_nc - nseg_nc)
566         chop_segment(seg, len);
567
568     return seg;
569 }
570
571 static _DtCvSegment *
572 traverse_for_vcc(_DtCvSegment* seg, unsigned int vcc)
573 {
574     if (seg == NULL)
575         return NULL;
576
577     unsigned long seg_ptype = seg->type & _DtCvPRIMARY_MASK;
578
579     if (seg_ptype == _DtCvSTRING && seg->client_use) {
580
581         assert( DtCvStrVcc(seg) <= vcc );
582
583         if (DtCvStrVcc(seg) != (unsigned int)-1) { // check for validity
584             if (vcc < DtCvStrVcc(seg) + DtCvStrVcLen(seg)) // found
585                 return seg;
586         }
587     }
588
589     _DtCvSegment* therein = NULL;
590
591     if (seg_ptype == _DtCvCONTAINER) { // traverse subordinates
592         _DtCvSegment* subordinates;
593         if ((subordinates = seg->handle.container.seg_list) != NULL)
594             therein = traverse_for_vcc(subordinates, vcc);
595     }
596     else if (seg_ptype == _DtCvTABLE) {
597         _DtCvSegment** cell = seg->handle.table.cells;
598         for (; *cell; cell++) {
599             if (therein = traverse_for_vcc(*cell, vcc))
600                 break;
601         }
602     }
603     if (therein)
604         return therein;
605
606     // traverse siblings
607     _DtCvSegment* siblings;
608     if ((siblings = seg->next_seg) != NULL)
609         therein = traverse_for_vcc(siblings, vcc);
610
611     return therein;
612 }
613
614 _DtCvSegment*
615 NodeViewInfo::top_container()
616 {
617     if (f_topic == NULL)
618         return NULL;
619
620     // retrieve the top container
621     _DtCvSegment* root_seg;
622     if ((root_seg = f_topic->seg_list) == NULL)
623         return NULL;
624     assert( (root_seg->type & _DtCvPRIMARY_MASK) == _DtCvCONTAINER );
625
626     return root_seg;
627 }
628
629 void
630 clear_search_hits_traverse(_DtCvSegment* seg)
631 {
632     if (seg == NULL)
633         return;
634
635     unsigned long seg_ptype = seg->type & _DtCvPRIMARY_MASK;
636
637     if (seg_ptype == _DtCvSTRING && seg->client_use) {
638         if (seg->type & _DtCvSEARCH_FLAG)
639             seg->type &=
640                 ~(_DtCvSEARCH_FLAG | _DtCvSEARCH_BEGIN | _DtCvSEARCH_END |
641                   _DtCvAPP_FLAG2);
642     }
643
644     if (seg_ptype == _DtCvCONTAINER) { // traverse subordinates
645         _DtCvSegment* subordinates;
646         if ((subordinates = seg->handle.container.seg_list) != NULL)
647             clear_search_hits_traverse(subordinates);
648     }
649     else if (seg_ptype == _DtCvTABLE) {
650         _DtCvSegment** cell = seg->handle.table.cells;
651         for (; *cell; cell++)
652             clear_search_hits_traverse(*cell);
653     }
654
655     // traverse siblings
656     _DtCvSegment* siblings;
657     if ((siblings = seg->next_seg) != NULL)
658         clear_search_hits_traverse(siblings);
659
660     return;
661 }
662
663 void
664 NodeViewInfo::clear_search_hits()
665 {
666     // retrieve the top container
667     _DtCvSegment* root_seg;
668     if ((root_seg = top_container()) == NULL)
669         return;
670
671     clear_search_hits_traverse(root_seg);
672
673     f_hits.clearAndDestroy();
674     f_current_hit = NULL;
675 }
676
677 void
678 NodeViewInfo::set_search_hits(UAS_Pointer<UAS_List<UAS_TextRun> >& hits)
679 {
680     if (f_current_hit) { // clear search hits previously displayed
681         clear_search_hits();
682     }
683
684     // retrieve the top container
685     _DtCvSegment* root_seg;
686     if ((root_seg = top_container()) == NULL)
687         return;
688
689     unsigned int idx;
690
691     for (idx = 0; idx < hits->length(); idx++) { // for each TextRun
692
693         UAS_Pointer<UAS_TextRun>& hit = hits->item(idx);
694
695         _DtCvSegment* seg;
696
697         if ((seg = traverse_for_vcc(root_seg, hit->offset())) == NULL) {
698 #ifdef DEBUG
699             fprintf(stderr, "(DEBUG) traverse_for_vcc failed, offset=%d\n",
700                                                                 hit->offset());
701 #endif
702             continue;
703         }
704 #ifdef DEBUG
705         else
706             fprintf(stderr, "(DEBUG) traverse_for_vcc succeeded, offset=%d\n",
707                                                                 hit->offset());
708 #endif
709
710         assert( (seg->type & _DtCvPRIMARY_MASK) == _DtCvSTRING );
711
712         if (seg = highlight_search_hit(seg, hit->offset(), hit->length())) {
713 #ifdef DEBUG
714             fprintf(stderr, "(DEBUG) highlight_search_hit succeeded, "
715                                                 "offset=%d\n", hit->offset());
716 #endif
717             seg->type |=
718                         _DtCvSEARCH_FLAG | _DtCvSEARCH_BEGIN | _DtCvSEARCH_END;
719
720             sr_DtCvSegment* sr_seg = new sr_DtCvSegment(seg);
721
722             if (idx == 0) {
723                 seg->type |= _DtCvAPP_FLAG2;
724                 f_current_hit = sr_seg;
725             }
726             f_hits.append(sr_seg);
727         }
728 #ifdef DEBUG
729         else
730             fprintf(stderr, "(DEBUG) highlight_search_hit failed, offset=%d\n",
731                                                                 hit->offset());
732 #endif
733     }
734 }
735
736 // returns 0 if upon success. returns -1 if it traversal was not changed.
737
738 NodeViewInfo::trav_status_t
739 NodeViewInfo::adjust_current_search_hit(trav_dir_t dir)
740 {
741     trav_status_t status = SUCCESS;
742
743     CC_TPtrDlistIterator<sr_DtCvSegment> iter(f_hits);
744
745     for (++iter; *iter.key() != *f_current_hit;)
746         ++iter;
747
748     if (dir == PREV) {
749         if (*iter.key() != *f_hits.first())
750             --iter;
751     }
752     else {
753         assert( dir == NEXT );
754         if (*iter.key() != *f_hits.last())
755             ++iter;
756     }
757
758     if (*f_current_hit != *iter.key()) {
759         f_current_hit->hitseg->type &= ~_DtCvAPP_FLAG2;
760
761         f_current_hit = iter.key();
762         f_current_hit->hitseg->type |=  _DtCvAPP_FLAG2;
763
764         if (dir == PREV) {
765             if (*f_current_hit == *f_hits.first())
766                 status = REACH_LIMIT;
767         }
768         else
769             if (*f_current_hit == *f_hits.last())
770                 status = REACH_LIMIT;
771     }
772     else
773         status = NOT_MOVED;
774
775     return status;
776 }
777
778 int
779 NodeViewInfo::hit_entries() const
780 {
781     return f_hits.entries();
782 }
783
784 int
785 NodeViewInfo::search_hit_idx()
786 {
787     int i;
788
789     CC_TPtrDlistIterator<sr_DtCvSegment> iter(f_hits);
790
791     for (i = 0, ++iter; *iter.key() != *f_current_hit; i++)
792         ++iter;
793
794     return i;
795 }
796
797 void
798 NodeViewInfo::comp_pixel_values_traverse(_DtCvSegment* seg, Display* dpy,
799                                          Colormap &cmap)
800 {
801     if (seg == NULL)
802         return;
803
804     unsigned long seg_ptype = seg->type & _DtCvPRIMARY_MASK;
805
806     if (seg_ptype == _DtCvSTRING && seg->client_use) {
807         XColor screen, exact;
808         SegClientData* pSCD = (SegClientData*)seg->client_use;
809         assert( pSCD->type() == _DtCvSTRING );
810
811         if (pSCD->bg_color() && pSCD->bg_pixel() == (unsigned long)-1) {
812             UAS_String bg_color = pSCD->bg_color();
813             unsigned long& bg_pixel = f_color_dict[bg_color];
814             if (bg_pixel == (unsigned long)-1) {
815                 if (XAllocNamedColor(dpy, cmap, pSCD->bg_color(),
816                                                         &screen, &exact))
817                     pSCD->bg_pixel(bg_pixel = screen.pixel);
818             }
819             else
820                 pSCD->bg_pixel(bg_pixel);
821         }
822
823         if (pSCD->fg_color() && pSCD->fg_pixel() == (unsigned long)-1) {
824             UAS_String fg_color = pSCD->fg_color();
825             unsigned long& fg_pixel = f_color_dict[fg_color];
826             if (fg_pixel == (unsigned long)-1) {
827                 if (XAllocNamedColor(dpy, cmap, pSCD->fg_color(),
828                                                         &screen, &exact))
829                     pSCD->fg_pixel(fg_pixel = screen.pixel);
830             }
831             else
832                 pSCD->fg_pixel(fg_pixel);
833         }
834     }
835
836     if (seg_ptype == _DtCvCONTAINER) { // traverse subordinates
837         _DtCvSegment* subordinates;
838         if ((subordinates = seg->handle.container.seg_list) != NULL)
839             comp_pixel_values_traverse(subordinates, dpy, cmap);
840     }
841
842     // traverse siblings
843     _DtCvSegment* siblings;
844     if ((siblings = seg->next_seg) != NULL)
845         comp_pixel_values_traverse(siblings, dpy, cmap);
846
847     return;
848 }
849
850 void
851 NodeViewInfo::comp_pixel_values(Display* dpy, Colormap &cmap)
852 {
853     // retrieve the top container
854     _DtCvSegment* root_seg;
855     if ((root_seg = top_container()) == NULL)
856         return;
857
858     comp_pixel_values_traverse(root_seg, dpy, cmap);
859
860 #ifdef CM_DEBUG
861     DictIter<UAS_String, unsigned long> dictiter;
862     for (dictiter = f_color_dict.first(); dictiter() ; dictiter++) {
863         fprintf(stderr, "(DEBUG) color=\"%s\", pixel=0x%lx\n",
864                                 (char*)dictiter.key(), dictiter.value());
865     }
866 #endif
867
868     return;
869 }
870
871 _DtCvSegment*
872 NodeViewInfo::get_segment(unsigned int vcc)
873 {
874   return traverse_for_vcc(top_container(), vcc);
875 }
876
877 unsigned int
878 NodeViewInfo::segment_to_vcc(_DtCvSegment* seg)
879 {
880   return DtCvStrVcc(seg);
881 }
882