NCBI C Toolkit Cross Reference

C/vibrant/treeview.c


  1 /*  treeview.c
  2 * ===========================================================================
  3 *
  4 *                            PUBLIC DOMAIN NOTICE                          
  5 *               National Center for Biotechnology Information
  6 *                                                                          
  7 *  This software/database is a "United States Government Work" under the   
  8 *  terms of the United States Copyright Act.  It was written as part of    
  9 *  the author's official duties as a United States Government employee and 
 10 *  thus cannot be copyrighted.  This software/database is freely available 
 11 *  to the public for use. The National Library of Medicine and the U.S.    
 12 *  Government have not placed any restriction on its use or reproduction.  
 13 *                                                                          
 14 *  Although all reasonable efforts have been taken to ensure the accuracy  
 15 *  and reliability of the software and data, the NLM and the U.S.          
 16 *  Government do not and cannot warrant the performance or results that    
 17 *  may be obtained by using this software or data. The NLM and the U.S.    
 18 *  Government disclaim all warranties, express or implied, including       
 19 *  warranties of performance, merchantability or fitness for any particular
 20 *  purpose.                                                                
 21 *                                                                          
 22 *  Please cite the author in any work or product based on this material.   
 23 *
 24 * ===========================================================================
 25 *
 26 * File Name:  treeview.c
 27 *
 28 * Author:  Vladimir Soussov
 29 *   
 30 * File Description:  treeview functions
 31 *
 32 *
 33 * $Log: treeview.c,v $
 34 * Revision 1.14  2008/04/29 13:43:50  kans
 35 * fixes for warnings caught by mingw cross-compiler
 36 *
 37 * Revision 1.13  2001/03/28 14:05:47  beloslyu
 38 * fix the comments to C style
 39 *
 40 * Revision 1.12  2001/03/28 01:37:40  juran
 41 * *** empty log message ***
 42 *
 43 * Revision 1.11  2000/11/06 21:51:15  soussov
 44 * adds code to prevent infinite loop in getNodeCoordinates
 45 *
 46 * Revision 1.10  1999/08/12 18:31:10  soussov
 47 * fixed bug in allocNewSegm
 48 *
 49 * Revision 1.9  1999/08/11 14:19:42  soussov
 50 * fixed bug with Int4 -> Int2 conversion
 51 *
 52 * Revision 1.8  1998/07/02 18:24:33  vakatov
 53 * Cleaned the code & made it pass through the C++ compilation
 54 *
 55 * Revision 1.7  1998/04/08 16:51:49  soussov
 56 * typo in function name fixed
 57 *
 58 * Revision 1.6  1998/04/02 23:03:51  vakatov
 59 * PC-specific fixes
 60 *
 61 * Revision 1.5  1998/04/01 21:52:47  soussov
 62 * Prototype fixed
 63 *
 64 * Revision 1.4  1998/04/01 20:14:41  soussov
 65 * vibincld.h added
 66 *
 67 * Revision 1.3  1998/04/01 20:09:22  soussov
 68 * Some prototypes added
 69 *
 70 * Revision 1.2  1998/04/01 17:43:59  soussov
 71 * changed tp include <>
 72 *
 73 * Revision 1.1  1998/03/31 21:22:27  sirotkin
 74 * With Vladimir - moved from distrib/internal/taxonomy/tree
 75 *
 76 * Revision 6.1  1998/01/13 19:18:51  soussov
 77 * qsort for large sibling list added
 78 *
 79 * Revision 6.0  1997/08/25 18:29:53  madden
 80 * Revision changed to 6.0
 81 *
 82 * Revision 1.1  1997/05/30 16:16:21  soussov
 83 * Set of files for ncbitree library
 84 *
 85 * Revision 1.1  1997/05/29 20:44:31  soussov
 86 * Initial version of tree library
 87 *
 88 *
 89 */
 90 
 91 #include <treemgr.h>
 92 #include <treeview.h>
 93 
 94 #define TREE_X0 10
 95 #define TREE_Y0 10
 96 
 97 #define getTree4Cursor tree_getUserData
 98 
 99 #define port_MoveTo(p, a, b) sMoveTo((a) + (p)->panel_origin_X, (b) + (p)->panel_origin_Y)
100 #define port_LineTo(p, a, b) sLineTo((a) + (p)->panel_origin_X, (b) + (p)->panel_origin_Y)
101 
102 static void closeAllSubtrees(TreeCursorPtr cursor);
103 extern void Nlm_GetRect PROTO((Nlm_GraphiC a, Nlm_RectPtr r));
104 
105 static _tnSegmPtr getNewSegmBuff(void)
106 {
107     _tnSegmPtr ts= (_tnSegmPtr)MemNew(4096*sizeof(_tnSegm));
108 
109     if(ts) {
110         memset(ts, 0, 4096*sizeof(_tnSegm));
111         ts[4095].flags= LINK_TO_NEXT_BUFF;
112     }
113     return ts;
114 }
115 
116 static void sMoveTo(Int4 x, Int4 y)
117 {
118     if(x > 32000) x= 32000;
119     else if(x < -32000) x= -32000;
120     if(y > 32000) y= 32000;
121     else if(y < -32000) y= -32000;
122 
123     MoveTo((Int2)x, (Int2)y);
124 }
125 
126 static void sLineTo(Int4 x, Int4 y)
127 {
128     if(x > 32000) x= 32000;
129     else if(x < -32000) x= -32000;
130     if(y > 32000) y= 32000;
131     else if(y < -32000) y= -32000;
132 
133     LineTo((Int2)x, (Int2)y);
134 }
135 
136 static void port_PaintRect(_drawContextPtr port, RectPtr r)
137 {
138     r->left+= port->panel_origin_X;
139     r->right+= port->panel_origin_X;
140     r->top+= port->panel_origin_Y;
141     r->bottom+= port->panel_origin_Y;
142 
143     PaintRect(r);
144 }
145 
146 static void Rect2Box(_drawContextPtr p, RectPtr r, _boxPtr b)
147 {
148     b->xl= (r->left - p->panel_origin_X) + p->port_origin.x;
149     b->xr= (r->right - p->panel_origin_X) + p->port_origin.x;
150     b->yt= (r->top - p->panel_origin_Y) + p->port_origin.y;
151     b->yb= (r->bottom - p->panel_origin_Y) + p->port_origin.y;
152 }
153 
154 static void Box2Rect(_drawContextPtr p, _boxPtr b, RectPtr r)
155 {
156     r->left= p->panel_origin_X + (b->xl - p->port_origin.x);
157     r->right= p->panel_origin_X + (b->xr - p->port_origin.x);
158     r->top= p->panel_origin_Y + (b->yt - p->port_origin.y);
159     r->bottom= p->panel_origin_Y + (b->yb - p->port_origin.y);
160 }
161 
162 static CharPtr getNodeLabel(TreeCursorPtr cursor)
163 {
164     Uint2 size;
165     CharPtr label;
166 
167     label= (CharPtr) tree_getNode(cursor, TREE_NODE_FMT_LABEL, &size);
168     if(label != NULL) label[size]= '\0';
169     return label;
170 }
171 
172 static Int4 getNodeLength(TreeCursorPtr cursor)
173 {
174     Uint2 size;
175     Int4 length;
176 
177     length= (Int4)tree_getNode(cursor, TREE_NODE_FMT_DISTANCE, &size);
178     return (length <= 0)? 1 : length;
179 }
180 
181 static Int2 getIconId(TreeCursorPtr cursor)
182 {
183     Uint2 size;
184     Int4 a;
185     Int2 id;
186 
187     a= (Int4) tree_getNode(cursor, TREE_NODE_FMT_ICON, &size);
188     id= (Int2)a;
189 
190     return id;
191 }
192     
193 #ifdef XXX_UNUSED_STATIC_FUNC
194 static void addBox2Region(_boxPtr region, _boxPtr box)
195 {
196     if(box->xl < region->xl) region->xl= box->xl;
197     if(box->xr > region->xr) region->xr= box->xr;
198     if(box->yt < region->yt) region->yt= box->yt;
199     if(box->yb > region->yb) region->yb= box->yb;
200 }
201 #endif /* XXX_UNUSED_STATIC_FUNC */
202 
203 static Boolean BoxXRegion(_boxPtr region, _boxPtr box, _boxPtr res)
204 {
205     if((box->yt >= region->yb) || (box->yb <= region->yt)) return FALSE;
206     if((box->xl >= region->xr) || (box->xr <= region->xl)) return FALSE;
207 
208     if(res != NULL) {
209         res->xl= (box->xl > region->xl)? box->xl : region->xl;
210         res->xr= (box->xr < region->xr)? box->xr : region->xr;
211         res->yt= (box->yt > region->yt)? box->yt : region->yt;
212         res->yb= (box->yb < region->yb)? box->yb : region->yb;
213     }
214 
215     return TRUE;
216 }
217 
218 #ifdef XXX_UNUSED_STATIC_FUNC
219 static void moveBox(_boxPtr box, Int4 dx, Int4 dy)
220 {
221     
222     if(dx != 0) {
223         box->xl+= dx;
224         box->xr+= dx;
225     }
226     if(dy != 0) {
227         box->yt+= dy;
228         box->yb+= dy;
229     }
230 }
231 #endif /* XXX_UNUSED_STATIC_FUNC */
232 
233 #ifdef XXX_UNUSED_STATIC_FUNC
234 static void zoomBox(_boxPtr box, Int4 dx, Int4 dy)
235 {
236     if(dx != 0) {
237         box->xl-= dx;
238         box->xr+= dx;
239     }
240 
241     if(dy != 0) {
242         box->yt-= dy;
243         box->yb+= dy;
244     }
245 }
246 #endif /* XXX_UNUSED_STATIC_FUNC */
247 
248 static Boolean ptInBox(_boxPtr box, Int4 x, Int4 y)
249 {
250     return ((y >= box->yt) && (y <= box->yb) && (x >= box->xl) && (x <= box->xr));
251 }
252 
253 static void freeNodeSegm(TreeCursorPtr cursor)
254 {
255     _tnSegmPtr ts1;
256     _tnSegmPtr ts2;
257     TreeViewPtr tv;
258 
259     tv= (TreeViewPtr) getTree4Cursor(cursor);
260     ts1= (_tnSegmPtr)(cursor->node->sys_data);
261 
262     if(ts1 == NULL) return;
263 
264     if(ts1->viewer_id == tv->my_spy_id) {
265         cursor->node->sys_data= ts1->next;
266         ts2= ts1;
267     }
268     else {
269         for(ts2= ts1->next; ts2 != NULL; ts2= ts2->next) {
270             if(ts2->viewer_id == tv->my_spy_id) {
271                 ts1->next= ts2->next;
272                 break;
273             }
274             else {
275                 ts1= ts2;
276             }
277         }
278     }
279 
280     if(ts2 != NULL) {
281         ts2->flags= 0;
282     }
283 }
284 
285 static _tnSegmPtr allocNewSegm(TreeCursorPtr cursor)
286 {
287     _tnSegmPtr ts;
288     _tnSegmPtr tsn;
289     TreeViewPtr tv;
290     /* Int4 i, j; */
291 
292     /*find free room */
293     tv= (TreeViewPtr) getTree4Cursor(cursor);
294     ts= tv->segm_buff;
295 
296     while(ts) {
297         if(ts->flags == 0) {
298             ts->flags= RESERVED_SEGM;
299             ts->next= (_tnSegmPtr)cursor->node->sys_data;
300             cursor->node->sys_data= ts;
301             ts->viewer_id= tv->my_spy_id;
302             return ts;
303         }
304         if((ts->flags & LINK_TO_NEXT_BUFF) != 0) {
305             if(ts->next) {
306                 ts= ts->next;
307                 continue;
308             }
309             else break;
310         }
311         ++ts;
312     }
313 
314     if(ts == NULL) return NULL;
315     /* try to allocate more memory */
316     if((tsn= getNewSegmBuff()) == NULL) {
317         return NULL;
318     }
319     
320     tsn->flags= RESERVED_SEGM;
321     tsn->viewer_id= tv->my_spy_id;
322     ts->next= tsn;
323     cursor->node->sys_data= tsn;
324     
325     return tsn;
326 }
327     
328     
329 
330 static Int4 getIconWidth(_ImageListPtr ilp, Uint2 i_id)
331 {
332     Uint2 w= 0, h;
333 
334     if(ilp != NULL) {
335         ilst_size(ilp, i_id, &w, &h);
336     }
337     return (Int4)w;
338 }
339     
340 
341 static Int4 calcNodeWidth(TreeViewPtr tv, Int2 icon_id, Int4 length, CharPtr label)
342 {
343     return ((tv->length_scale >= 0)? (tv->length_scale * length) : (length/(-tv->length_scale))) +
344         (((tv->i_list != NULL) && (icon_id >= 0))? getIconWidth(tv->i_list, icon_id) : 0) +
345         (((label != NULL) && (*label != '\0'))? (StringWidth(label) + 4) : 0);
346 }
347 
348 static _tnSegmPtr getNodeViewerData(_tnSegmPtr tn, Uint1 v_id)
349 {
350     while(tn != NULL) {
351         if(tn->viewer_id == v_id) return tn;
352         tn= tn->next;
353     }
354     return NULL;
355 }
356 
357 static Boolean getBox4Cursor(TreeCursorPtr cursor, _boxPtr box)
358 {
359     _tnSegmPtr node_data;
360     TreeViewPtr tv;
361 
362     tv= (TreeViewPtr) getTree4Cursor(cursor);
363     if((node_data= getNodeViewerData((_tnSegmPtr)cursor->node->sys_data, tv->my_spy_id)) != NULL) {
364         box->xr+= node_data->w;
365         box->yb+= node_data->h;
366         return TRUE;
367     }
368 
369     return FALSE;
370 }
371 
372 static TreeNodeId getNextSibling(TreeCursorPtr cursor, TreeNodeId nxt_id)
373 {
374     Boolean r;
375     _tnSegmPtr node_data;
376     TreeViewPtr tv;
377 
378     tv= (TreeViewPtr)getTree4Cursor(cursor);
379 
380     if(nxt_id.idi == cursor->node_id.idi) {
381         nxt_id.idi= 0;
382         return nxt_id;
383     }
384 
385     if(nxt_id.idi != 0) {
386         tree_toNode(cursor, nxt_id);
387         if((node_data= getNodeViewerData((_tnSegmPtr)cursor->node->sys_data, tv->my_spy_id)) != NULL) {
388             return node_data->work;
389         }
390         else {
391             nxt_id.idi= 0;
392             return nxt_id;
393         }
394     }
395 
396     /* find the first one */
397 
398     if(tree_parent(cursor)) {
399 
400         for(r= tree_child(cursor); r; r= tree_sibling(cursor)) {
401             if((node_data= getNodeViewerData((_tnSegmPtr)cursor->node->sys_data, tv->my_spy_id)) != NULL) {
402                 if((node_data->flags & TREE_FIRST_NODE) != 0) return node_data->work;
403             }
404         }
405     }
406 
407     nxt_id.idi= 0;
408     return nxt_id;
409 }
410         
411 static void draw_line(_drawContextPtr port, Int4 x1, Int4 y1, Int4 x2, Int4 y2)
412 {
413     if(y1 == y2) {
414         /* horisontal line */
415         if(((y1 + port->pen_w) <= port->clip_box.yt) ||
416            ((y1 - port->pen_w) >= port->clip_box.yb)) return;
417 
418         if(x1 > x2) {
419             y2= x1;
420             x1= x2;
421             x2= y2;
422             y2= y1;
423         }
424 
425         if(((x2 + port->pen_w) <= port->clip_box.xl) ||
426            ((x1 - port->pen_w) >= port->clip_box.xr)) return;
427     }
428     else if(x1 == x2) {
429         /* vertical line */
430         if(((x1 + port->pen_w) <= port->clip_box.xl) ||
431            ((x1 - port->pen_w) >= port->clip_box.xr)) return;
432 
433         if(y1 > y2) {
434             x2= y1;
435             y1= y2;
436             y2= x2;
437             x2= x1;
438         }
439 
440         if(((y1 - port->pen_w) >= port->clip_box.yb) ||
441            ((y2 + port->pen_w) <= port->clip_box.yt)) return;
442     }
443 
444     /* adjust coordinates */
445     x1-= port->port_origin.x;
446     x2-= port->port_origin.x;
447     y1-= port->port_origin.y;
448     y2-= port->port_origin.y;
449 
450     port_MoveTo(port, x1, y1);
451     /* TODO add here the pen settings */
452     SetColor(port->line_color);
453     port_LineTo(port, x2, y2);
454 }
455 
456 #if 0   
457 static void erase_line(_drawContextPtr port, Int4 x1, Int4 y1, Int4 x2, Int4 y2)
458 {
459     if(y1 == y2) {
460         /* horisontal line */
461         if(((y1 + port->pen_w) <= port->clip_box.yt) ||
462            ((y1 - port->pen_w) >= port->clip_box.yb)) return;
463 
464         if(x1 > x2) {
465             y2= x1;
466             x1= x2;
467             x2= y2;
468             y2= y1;
469         }
470 
471         if(((x2 + port->pen_w) <= port->clip_box.xl) ||
472            ((x1 - port->pen_w) >= port->clip_box.xr)) return;
473     }
474     else if(x1 == x2) {
475         /* vertical line */
476         if(((x1 + port->pen_w) <= port->clip_box.xl) ||
477            ((x1 - port->pen_w) >= port->clip_box.xr)) return;
478 
479         if(y1 > y2) {
480             x2= y1;
481             y1= y2;
482             y2= x2;
483             x2= x1;
484         }
485 
486         if(((y1 - port->pen_w) >= port->clip_box.yb) ||
487            ((y2 + port->pen_w) <= port->clip_box.yt)) return;
488     }
489 
490     /* adjust coordinates */
491     x1-= port->port_origin.x;
492     x2-= port->port_origin.x;
493     y1-= port->port_origin.y;
494     y2-= port->port_origin.y;
495 
496     port_MoveTo(port, x1, y1);
497     /* TODO add here the pen settings */
498     Black();
499     EraseMode();
500     port_LineTo(port, x2, y2);
501     CopyMode();
502 }
503 #endif
504 
505 static void draw_plus(_drawContextPtr port, Int4 x, Int4 y)
506 {
507     RecT rect;
508     Int2 radius;
509 
510     radius= port->pen_w + 3;
511 
512     if(((y + radius) < port->clip_box.yt) ||
513        ((y - radius) > port->clip_box.yb) ||
514        ((x - radius) > port->clip_box.xr) ||
515        ((x + radius) < port->clip_box.xl)) return;
516 
517     x-= port->port_origin.x;
518     y-= port->port_origin.y;
519 
520     rect.right=  (Int2)(x + radius);
521     rect.left=   (Int2)(x - radius);
522     rect.top=    (Int2)(y - radius);
523     rect.bottom= (Int2)(y + radius);
524 
525     SetColor(port->plus_color);
526     Solid();
527     port_PaintRect(port, &rect);
528     SetColor(port->bg_color);
529     port_MoveTo(port, x, y - radius + 1);
530     port_LineTo(port, x, y + radius - 1);
531     port_MoveTo(port, x - radius + 1, y);
532     port_LineTo(port, x + radius - 1, y);
533 }
534     
535 static void draw_minus(_drawContextPtr port, Int4 x, Int4 y)
536 {
537     RecT rect;
538     Int2 radius;
539 
540     radius= port->pen_w + 3;
541 
542     if(((y + radius) < port->clip_box.yt) ||
543        ((y - radius) > port->clip_box.yb) ||
544        ((x - radius) > port->clip_box.xr) ||
545        ((x + radius) < port->clip_box.xl)) return;
546 
547     x-= port->port_origin.x;
548     y-= port->port_origin.y;
549 
550     rect.right=  (Int2)(x + radius);
551     rect.left=   (Int2)(x - radius);
552     rect.top=    (Int2)(y - radius);
553     rect.bottom= (Int2)(y + radius);
554 
555     SetColor(port->plus_color);
556     Solid();
557     port_PaintRect(port, &rect);
558     SetColor(port->bg_color);
559     port_MoveTo(port, x - radius + 1, y);
560     port_LineTo(port, x + radius - 1, y);
561 }
562 
563 static void draw_label(_drawContextPtr port, CharPtr label, Int4 x, Int4 y)
564 {
565     
566     if(x >= port->clip_box.xr) return;
567 
568     /* TODO insert here pen and font settings */
569     SetColor(port->text_color);
570 
571     y+= FontHeight()/2 - Descent();
572     x-= port->port_origin.x;
573     y-= port->port_origin.y;
574     port_MoveTo(port, x, y);
575     PaintChar(' ');
576     PaintString(label);
577 }
578     
579 static void draw_icon(_drawContextPtr port, _ImageListPtr il, Uint2 i_ind, Int4 x, Int4 y)
580 {
581     Uint2 w, h;
582 
583     if(!ilst_size(il, i_ind, &w, &h)) {
584         w= h= 0;
585     }
586 
587     x-= w/2 + 1;
588     y-= h/2 + 1;
589 
590     if((y > port->clip_box.yb) ||
591        ((y + h) < port->clip_box.yt) ||
592        (x > port->clip_box.xr) ||
593        ((x + w) < port->clip_box.xl)) return;
594 
595     x-= port->port_origin.x;
596     y-= port->port_origin.y;
597     ilst_draw(il, i_ind, x + port->panel_origin_X, y + port->panel_origin_Y);
598 }
599 
600 static void highLightBox(_drawContextPtr port, _boxPtr node_box, CharPtr label)
601 {
602     RecT r;
603     Int4 x, y;
604 
605     r.left= node_box->xl - port->port_origin.x;
606     r.right= node_box->xr - port->port_origin.x;
607     r.top= node_box->yt - port->port_origin.y;
608     r.bottom= node_box->yb - port->port_origin.y;
609 
610     InsetRect(&r, 1, 1);
611     r.right+= 1;
612     SetColor(port->sbg_color);
613     port_PaintRect(port, &r);
614     SetColor(port->sfg_color);
615 
616     x= node_box->xl;
617     y= ((node_box->yt + node_box->yb)/2) + FontHeight()/2 - Descent();
618     x-= port->port_origin.x;
619     y-= port->port_origin.y;
620     port_MoveTo(port, x, y);
621     PaintChar(' ');
622     if(label != NULL) PaintString(label);
623     /*InvertRect(&r);*/    
624 }
625 
626 static void unHighLightBox(_drawContextPtr port, _boxPtr node_box, CharPtr label)
627 {
628     RecT r;
629     Int4 x, y;
630 
631     r.left= node_box->xl - port->port_origin.x;
632     r.right= node_box->xr - port->port_origin.x;
633     r.top= node_box->yt - port->port_origin.y;
634     r.bottom= node_box->yb - port->port_origin.y;
635 
636     InsetRect(&r, 1, 1);
637     r.right+= 1;
638     SetColor(port->bg_color);
639     port_PaintRect(port, &r);
640     SetColor(port->text_color);
641 
642     x= node_box->xl;
643     y= ((node_box->yt + node_box->yb)/2) + FontHeight()/2 - Descent();
644     x-= port->port_origin.x;
645     y-= port->port_origin.y;
646     port_MoveTo(port, x, y);
647     PaintChar(' ');
648     if(label != NULL) PaintString(label);
649     /*InvertRect(&r);*/    
650 }
651 
652 /*******************************************
653  * set clip box on whole panel
654  */
655 static void setPort2Panel(_drawContextPtr my_port)
656 {
657     RecT r;
658 
659     ObjectRect(my_port->tree_panel, &r);
660 
661     /* convert it to panel coordinates */
662     Rect2Box(my_port, &r, &my_port->clip_box);
663 }
664 
665 static void drawVertical(TreeCursorPtr cursor, Int4 x0, Int4 y0)
666 {
667     if(tree_child(cursor)) {
668         TreeViewPtr tv= (TreeViewPtr) getTree4Cursor(cursor);
669         Int4 y1= y0;
670         Int4 dy= tv->row_height;
671         _tnSegmPtr tns;
672 
673         if(tv->cmpSiblings == NULL) {
674             /* we don't want to sort siblings */
675             do {
676                 y1+= dy;
677                 if((tns= getNodeViewerData((_tnSegmPtr)cursor->node->sys_data, tv->my_spy_id)) != NULL) {
678                     dy= tns->h;
679                 }
680                 else dy= 0;
681             }
682             while (tree_sibling(cursor));
683         }
684         else {/* siblings have to be sorted */
685             TreeNodeId id;
686 
687             for(id.idi= 0; (id= getNextSibling(cursor, id)).idi != 0;) {
688                 y1+= dy;
689                 if((tns= getNodeViewerData((_tnSegmPtr)cursor->node->sys_data, tv->my_spy_id)) != NULL) {
690                     dy= tns->h;
691                 }
692                 else dy= 0;
693             }
694         }
695 
696         tree_parent(cursor);
697         draw_line(&tv->draw_port, x0, y0, x0, y1);
698     }
699 }
700         
701 
702 static Int4 draw_node(TreeCursorPtr cursor, Int4 x0, Int4 y0)
703 {
704     TreeViewPtr tv;
705     _box my_box;
706     _box node_box;
707     Int4 ym, xm, xt, yd;
708     Int2 icon_id;
709     Int4 length;
710     CharPtr label;
711     Boolean need_select= FALSE;
712 
713     my_box.xl= my_box.xr= x0;
714     my_box.yt= my_box.yb= y0;
715     if(!getBox4Cursor(cursor, &my_box)) return x0;
716     tv= (TreeViewPtr) getTree4Cursor(cursor);
717     icon_id= (tv->i_list == NULL)? -1 : getIconId(cursor);
718     length= getNodeLength(cursor);
719     label= getNodeLabel(cursor);
720 
721     
722     node_box.xl= x0;
723     node_box.yt= y0;
724     node_box.yb= y0 + tv->row_height;
725     node_box.xr= x0 + calcNodeWidth(tv, icon_id, length, label);
726                 
727     /* calculate the mediane */
728     ym= y0 + tv->row_height/2;
729 
730     xm= x0 + 
731         ((tv->length_scale >= 0)? 
732          (tv->length_scale * length) : (length/(-tv->length_scale)));
733 
734     yd= my_box.yb - tv->row_height/2;
735 
736     if(BoxXRegion(&tv->draw_port.clip_box, &node_box, NULL)) {
737         /* we have visible part */
738 
739         /* check for selected node */
740         if(cursor->node_id.idi == tv->cr2->node_id.idi) {
741             need_select= TRUE;
742             tv->sel_x= x0;
743             tv->sel_y= y0;
744         }
745         
746         /* draw horisontal line */
747         draw_line(&tv->draw_port, x0, ym, xm, ym);
748 
749         /* draw vertical line */
750         if((yd - ym) > tv->row_height/2) {
751             drawVertical(cursor, xm, ym);
752             draw_minus(&tv->draw_port, x0, ym);
753         }
754         else if(tree_child(cursor)) {
755             draw_plus(&tv->draw_port, x0, ym);
756             tree_parent(cursor);
757         }
758             
759         if(icon_id >= 0) {
760             /* draw icon */
761             xt= xm + getIconWidth(tv->i_list, icon_id)/2;
762             draw_icon(&tv->draw_port, tv->i_list, icon_id, xm, ym);
763         }
764         else xt= xm;
765 
766         if(label != NULL) {
767             /* draw label */
768             if(need_select) {
769                 node_box.xl= xt;
770                 highLightBox(&tv->draw_port, &node_box, label);
771             }
772             else draw_label(&tv->draw_port, label, xt, ym);
773         }
774     }
775     else {
776         /* node itself invisible, but we can see it's children */
777         
778         /* draw vertical line */
779         drawVertical(cursor, xm, ym);
780         /*
781         if((yd - ym) > tv->row_height/2) {
782             draw_line(&tv->draw_port, xm, ym, xm, yd);
783         }
784         */
785     }
786     return xm;
787 }
788         
789 
790 static Boolean drawTree(TreeCursorPtr cursor, Int4 x0, Int4 y0)
791 {
792     _box my_box;
793     TreeViewPtr tv;
794 
795     my_box.xl= my_box.xr= x0;
796     my_box.yt= my_box.yb= y0;
797 
798     if(!getBox4Cursor(cursor, &my_box)) return FALSE; /* this node is invisible */
799     tv= (TreeViewPtr) getTree4Cursor(cursor);
800 
801     if(BoxXRegion(&tv->draw_port.clip_box, &my_box, NULL)) {
802         /* we have visible part */
803         x0= draw_node(cursor, x0, y0);
804         y0+= tv->row_height;
805         if(tree_child(cursor)) {
806 
807             if(tv->cmpSiblings == NULL) {
808                 /* we don't want to sort siblings */
809                 do {
810                     if(drawTree(cursor, x0, y0)) {
811                         my_box.xl= my_box.xr= x0;
812                         my_box.yt= my_box.yb= y0;
813                         getBox4Cursor(cursor, &my_box);
814                         y0= my_box.yb;
815                         if(y0 > tv->draw_port.clip_box.yb) break;
816                     }
817                 }
818                 while (tree_sibling(cursor));
819             }
820             else {/* siblings have to be sorted */
821                 TreeNodeId id;
822 
823                 for(id.idi= 0; (id= getNextSibling(cursor, id)).idi != 0;) {
824                     if(drawTree(cursor, x0, y0)) {
825                         my_box.xl= my_box.xr= x0;
826                         my_box.yt= my_box.yb= y0;
827                         getBox4Cursor(cursor, &my_box);
828                         y0= my_box.yb;
829                         if(y0 > tv->draw_port.clip_box.yb) break;
830                     }
831                 }
832             }
833 
834             tree_parent(cursor);
835         }
836     }
837     return TRUE;
838 }
839 
840 /*------------------------------------------------------
841  * Redraw tree fragment in current port
842  */
843 
844 static void redrawInPort(TreeViewPtr tv)
845 {
846     RecT r;
847 
848     Box2Rect(&tv->draw_port, &tv->draw_port.clip_box, &r);
849 
850     InsetRect(&r, 1, 1);
851     InvalRect(&r);
852     /*FrameRect(&r);*/
853     Update();
854 }
855 
856 static Boolean makeNodeVisible(TreeCursorPtr cursor)
857 {
858     TreeViewPtr tv;
859     _box my_box;
860     _tnSegmPtr tsp;
861 
862     tv= (TreeViewPtr)getTree4Cursor(cursor);
863     if(getNodeViewerData((_tnSegmPtr)cursor->node->sys_data, tv->my_spy_id) != NULL) return TRUE;
864 
865     /* we need to open node */
866     tsp= allocNewSegm(cursor);
867     if(tsp == NULL) {
868         return FALSE;
869     }
870     else {
871         Int2 icon_id;
872         Int4 length, xm, ym;
873         CharPtr label;
874         
875         icon_id= (tv->i_list == NULL)? -1 : getIconId(cursor);
876         length= getNodeLength(cursor);
877         label= getNodeLabel(cursor);
878 
879         tsp->h= tv->row_height;
880 
881         tsp->w= calcNodeWidth(tv, icon_id, length, label);
882 
883 
884         
885         if(tree_child(cursor)) {
886             
887             /* adjust with children's boxes if visable */
888             xm= ((tv->length_scale >= 0)? 
889                  (tv->length_scale * length) : (length/(-tv->length_scale)));
890     
891             ym= tv->row_height;
892             /* we don't need to sort siblings  here */
893             do {
894                 my_box.xl= my_box.xr= xm;
895                 my_box.yt= my_box.yb= ym;
896 
897                 if(getBox4Cursor(cursor, &my_box)) {
898                     ym= my_box.yb;
899                     if(tsp->w < my_box.xr) tsp->w= my_box.xr;
900                 }
901             }
902             while (tree_sibling(cursor));
903             
904             tsp->h= ym;
905             tree_parent(cursor);
906         }
907     }
908     return TRUE;
909 }       
910 
911 static void adjust_parentSize(TreeCursorPtr cursor)
912 {
913     TreeViewPtr tv;
914     _box my_box;
915     _tnSegmPtr tsp;
916     TreeNodeId nid= tree_getId(cursor);
917 
918     if(tree_parent(cursor)) {
919         tv= (TreeViewPtr) getTree4Cursor(cursor);
920         if((tsp= getNodeViewerData((_tnSegmPtr)cursor->node->sys_data, tv->my_spy_id)) != NULL) {
921             Int2 icon_id;
922             Int4 length, xm, ym;
923             CharPtr label;
924         
925             icon_id= (tv->i_list == NULL)? -1 : getIconId(cursor);
926             length= getNodeLength(cursor);
927             label= getNodeLabel(cursor);
928 
929             tsp->h= tv->row_height;
930 
931             tsp->w= calcNodeWidth(tv, icon_id, length, label);
932 
933 
934         
935             if(tree_child(cursor)) {
936             
937                 /* adjust with children's boxes if visable */
938                 xm= ((tv->length_scale >= 0)? 
939                      (tv->length_scale * length) : (length/(-tv->length_scale)));
940     
941                 ym= tv->row_height;
942                 /* we don't need to sort siblings  here */
943                 do {
944                     my_box.xl= my_box.xr= xm;
945                     my_box.yt= my_box.yb= ym;
946 
947                     if(getBox4Cursor(cursor, &my_box)) {
948                         ym= my_box.yb;
949                         if(tsp->w < my_box.xr) tsp->w= my_box.xr;
950                     }
951                 }
952                 while (tree_sibling(cursor));
953             
954                 tsp->h= ym;
955                 tree_parent(cursor);
956             }
957             adjust_parentSize(cursor);
958         }
959         tree_toNode(cursor, nid);
960     }
961 }
962 
963 static TreeCursorPtr sortCursor;
964 
965 typedef int (*QsortCmpFunc)(const void *, const void *);
966 
967 static int my_cmpSibl(TreeNodeId* a, TreeNodeId* b)
968 {
969     TreeViewPtr tv= (TreeViewPtr) getTree4Cursor(sortCursor);
970 
971     tree_toNode(sortCursor, *b);
972     tree_toNode(tv->cr3, *a);
973     return (*(tv->cmpSiblings))(tv->cr3, sortCursor);
974 }
975 
976 /* sort siblings */
977 static void sortSiblings(TreeCursorPtr cursor, Int2 n)
978 {
979     TreeViewPtr tv= (TreeViewPtr)getTree4Cursor(cursor);
980     _tnSegmPtr tns;
981     int i;
982     TreeNodeId nid, save_id= cursor->node_id;
983     TreeNodeId* aref;
984 
985     if(!tree_child(cursor)) return;
986 
987     /* create the array of pointers to viewer structure */
988     if(n < 2) {
989         /* we have just one child - nothing to sort */
990         if((tns= getNodeViewerData((_tnSegmPtr)cursor->node->sys_data, tv->my_spy_id)) != NULL) {
991             tns->work= cursor->node_id;
992             tns->flags|= TREE_FIRST_NODE;
993         }
994         tree_parent(cursor);
995         return;
996     }
997 
998     for(i= 0; i < n;) {
999         if((tns= getNodeViewerData((_tnSegmPtr)cursor->node->sys_data, tv->my_spy_id)) != NULL) {
1000             tns->work.idi= 0;
1001             tns->flags&= ~TREE_FIRST_NODE;
1002         }
1003         if(!tree_sibling(cursor)) break;
1004     }
1005 
1006     tree_parent(cursor);
1007     tree_child(cursor);
1008     if(tv->cr3 == NULL) {
1009         tv->cr3= tree_openCursor(tv->tree, tv, NULL);
1010     }
1011 
1012     /* sort it */
1013 #if 1
1014     if((n > 132) && ((aref= (TreeNodeId*)malloc(sizeof(TreeNodeId)*n)) != NULL)) {
1015         
1016         sortCursor= cursor;
1017 
1018         i= 0;
1019         do {
1020             if(i < n) aref[i++]= tree_getId(cursor);
1021         }
1022         while(tree_sibling(cursor));
1023         qsort((void*)aref, i, sizeof(TreeNodeId), (QsortCmpFunc)my_cmpSibl);
1024 
1025         tree_toNode(cursor, aref[0]);
1026         if((tns= getNodeViewerData((_tnSegmPtr)cursor->node->sys_data, tv->my_spy_id)) != NULL) {
1027             tns->flags|= TREE_FIRST_NODE;
1028         }
1029 
1030         for(n= 1; n < i; n++) {
1031             tree_toNode(cursor, aref[n-1]);
1032             if((tns= getNodeViewerData((_tnSegmPtr)cursor->node->sys_data, tv->my_spy_id)) != NULL) {
1033                 tns->work= aref[n];
1034             }
1035         }
1036 
1037         tree_toNode(cursor, aref[i-1]);
1038         if((tns= getNodeViewerData((_tnSegmPtr)cursor->node->sys_data, tv->my_spy_id)) != NULL) {
1039             tns->work= aref[i-1];
1040         }
1041         
1042         free(aref);
1043         tree_toNode(cursor, save_id);
1044         return;
1045     }
1046 
1047 #endif
1048     nid.idi= 0;
1049     for(i= 0; i < n; i++) {
1050         /* find the minimum */
1051         do {
1052             if(((tns= getNodeViewerData((_tnSegmPtr)cursor->node->sys_data, tv->my_spy_id)) != NULL) && 
1053                (tns->work.idi == 0)) break;
1054         }
1055         while(tree_sibling(cursor));
1056 
1057         tree_toNode(tv->cr3, tree_getId(cursor));
1058         while(tree_sibling(tv->cr3)) {
1059             if(((tns= getNodeViewerData((_tnSegmPtr)tv->cr3->node->sys_data, tv->my_spy_id)) != NULL) && 
1060                (tns->work.idi == 0) && ((*(tv->cmpSiblings))(tv->cr3, cursor) < 0)) {
1061 
1062                 tree_toNode(cursor, tree_getId(tv->cr3));
1063             }
1064         }
1065 
1066 
1067         if(((tns= getNodeViewerData((_tnSegmPtr)cursor->node->sys_data, tv->my_spy_id)) != NULL) && 
1068            (tns->work.idi == 0)) {
1069 
1070             tns->work= tree_getId(cursor);
1071             if(nid.idi == 0) {
1072                 tns->flags|= TREE_FIRST_NODE;
1073             }
1074             else {
1075                 tree_toNode(tv->cr3, nid);
1076                 tns= getNodeViewerData((_tnSegmPtr)tv->cr3->node->sys_data, tv->my_spy_id);
1077                 tns->work= tree_getId(cursor);
1078             }
1079             nid= tree_getId(cursor);
1080         }
1081 
1082         tree_parent(cursor);
1083         tree_child(cursor);
1084     }
1085     tree_toNode(cursor, save_id);
1086 }    
1087     
1088 /* open subtree */    
1089 static Boolean openSubtree(TreeCursorPtr cursor, Boolean do_callBack)
1090 {
1091     TreeViewPtr tv;
1092     _tnSegmPtr node_data;
1093     _box node_box;
1094     Int4 length, xm, ym;
1095     Int2 n= 0;
1096     TreeNodeId save_id= cursor->node_id;
1097 
1098 
1099     tv= (TreeViewPtr)getTree4Cursor(cursor);
1100     if((node_data= getNodeViewerData((_tnSegmPtr)cursor->node->sys_data, tv->my_spy_id)) == NULL) {
1101         return FALSE;
1102     }
1103 
1104     if(do_callBack && (tv->evntFunc != NULL)) {
1105         (*(tv->evntFunc))(cursor, TVIEW_ON_OPEN);
1106         Select(tv->draw_port.tree_panel);
1107         tree_toNode(cursor, save_id);
1108     }
1109 
1110     length= getNodeLength(cursor);
1111 
1112     node_data->h= tv->row_height;
1113 
1114     node_data->w= calcNodeWidth(tv, (tv->i_list == NULL)? -1 : getIconId(cursor), 
1115                                 length, getNodeLabel(cursor));
1116 
1117     xm= ((tv->length_scale >= 0)? 
1118          (tv->length_scale * length) : (length/(-tv->length_scale)));
1119     
1120     ym= tv->row_height;
1121 
1122     if(!tree_child(cursor)) return FALSE;
1123 
1124     /* we don't need to sort siblings */
1125     do {
1126         if(makeNodeVisible(cursor)) {
1127             node_box.xl= node_box.xr= xm;
1128             node_box.yt= node_box.yb= ym;
1129             if(getBox4Cursor(cursor, &node_box)) {
1130                 ym= node_box.yb;
1131                 if(node_data->w < node_box.xr) node_data->w= node_box.xr;
1132             }
1133             ++n;
1134         }
1135     }
1136     while (tree_sibling(cursor));
1137 
1138 
1139     node_data->h= ym;
1140 
1141     tree_parent(cursor);
1142 
1143     if(tv->cmpSiblings != NULL) {
1144         if(n > 100) WatchCursor();
1145         sortSiblings(cursor, n);
1146         if(n > 100) ArrowCursor();
1147     }
1148 
1149     adjust_parentSize(cursor);
1150 
1151     return TRUE;
1152 }
1153 
1154 static Boolean closeSubtree(TreeCursorPtr cursor, Boolean do_callBack)
1155 {
1156     TreeViewPtr tv;
1157     _tnSegmPtr tsp;
1158     Int2 icon_id;
1159     Int4 length;
1160     CharPtr label;
1161     TreeNodeId nid= cursor->node_id;
1162 
1163 
1164     tv= (TreeViewPtr) getTree4Cursor(cursor);
1165     if((tsp= getNodeViewerData((_tnSegmPtr)cursor->node->sys_data, tv->my_spy_id)) == NULL) {
1166         return FALSE;
1167     }
1168 
1169     if(do_callBack && (tv->evntFunc != NULL)) {
1170         (*(tv->evntFunc))(cursor, TVIEW_ON_CLOSE);
1171         Select(tv->draw_port.tree_panel);
1172         tree_toNode(cursor, nid);
1173     }
1174 
1175     /* check if selected node belongs to subtree to close */
1176     if(cursor->node_id.idi != tv->cr2->node_id.idi) {
1177         if(tree_isDescendant(cursor, tv->cr2)) {
1178             /* it is, so move select to cursor */
1179             tree_toNode(tv->cr2, cursor->node_id);
1180             tv->sel_y= -1024;
1181         }
1182     }
1183 
1184     icon_id= (tv->i_list == NULL)? -1 : getIconId(cursor);
1185     length= getNodeLength(cursor);
1186     label= getNodeLabel(cursor);
1187 
1188     tsp->h= tv->row_height;
1189 
1190     tsp->w= calcNodeWidth(tv, icon_id, length, label);
1191 
1192     if(tree_child(cursor)) {
1193         do {
1194             freeNodeSegm(cursor);
1195         }
1196         while (tree_sibling(cursor));
1197         tree_parent(cursor);
1198     }
1199 
1200     adjust_parentSize(cursor);
1201 
1202 
1203     return TRUE;
1204 }
1205 
1206 /*****************************************************************************
1207 *
1208 *   TreeVScrollProc (sb, viewer, newval, oldval)
1209 *
1210 *****************************************************************************/
1211 
1212 static void TreeVScrollProc (BaR sb, SlatE viewer, Int2 newval, Int2 oldval)
1213 
1214 {
1215     TreeViewPtr  tv;
1216     Int2         height;
1217     Int4         offsetY;
1218     Int2         pixels;
1219     RecT         r;
1220     Int2         visLines;
1221 
1222     if (viewer != NULL && oldval != newval) {
1223         if (Visible(viewer) && AllParentsVisible (viewer)) {
1224             GetPanelExtra((PaneL) viewer, &tv);
1225             ObjectRect(viewer, &r);
1226             InsetRect (&r, 1, 1);
1227             height = r.bottom - r.top;
1228             
1229             visLines = (height) / tv->row_height;
1230 
1231             Select (viewer);
1232             if((newval > oldval && newval - visLines + 1 <= oldval) ||
1233                (newval < oldval && newval + visLines - 1 >= oldval)) {
1234                 pixels = (newval - oldval) * tv->row_height;
1235                 if (ABS(pixels) < height) {
1236                     ScrollRect (&r, 0, -pixels);
1237                     if (pixels > 0) {
1238                         r.top = r.bottom - pixels;
1239                     } 
1240                     else {
1241                         r.bottom = r.top - pixels;
1242                     }
1243                     InsetRect (&r, -1, -1);
1244                     InvalRect (&r);
1245                 } 
1246                 else {
1247                     InsetRect (&r, -1, -1);
1248                     InvalRect (&r);
1249                 }
1250             } 
1251             else {
1252                 InsetRect (&r, -1, -1);
1253                 InvalRect (&r);
1254             }
1255 
1256             offsetY= tv->row_height * (Int4) (newval - oldval);
1257             tv->draw_port.port_origin.y+= offsetY;
1258 
1259             /* calculate clip box for given rect  */
1260             Rect2Box(&tv->draw_port, &r, &tv->draw_port.clip_box);
1261 
1262             Update ();
1263 
1264             setPort2Panel(&tv->draw_port); /* resize clip box to whole panel */
1265         }
1266     }
1267 }
1268 
1269 /*****************************************************************************
1270 *
1271 *   TreeHScrollProc (sb, viewer, newval, oldval)
1272 *
1273 *****************************************************************************/
1274 
1275 static void TreeHScrollProc (BaR sb, SlatE viewer, Int2 newval, Int2 oldval)
1276 
1277 {
1278     TreeViewPtr  tv;
1279     Int4       lineWidth;
1280     Int4       offsetX;
1281     Int2       pixels;
1282     RecT       r;
1283     Int2       visLines;
1284     Int2       width;
1285 
1286     if(viewer != NULL && oldval != newval) {
1287         if(Visible (viewer) && AllParentsVisible (viewer)) {
1288             GetPanelExtra ((PaneL)viewer, &tv);
1289             ObjectRect (viewer, &r);
1290             InsetRect (&r, 1, 1);
1291             width = r.right - r.left;
1292             lineWidth= tv->row_width;
1293             visLines = (width) / lineWidth;
1294 
1295             Select (viewer);
1296             if((newval > oldval && newval - visLines + 1 <= oldval) ||
1297                (newval < oldval && newval + visLines - 1 >= oldval)) {
1298                 pixels= (newval - oldval) * lineWidth;
1299                 if (ABS (pixels) < width) {
1300                     ScrollRect (&r, -pixels, 0);
1301                     if (pixels > 0) {
1302                         r.left = r.right - pixels;
1303                     } 
1304                     else {
1305                         r.right = r.left - pixels;
1306                     }
1307                     InsetRect (&r, -1, -1);
1308                     InvalRect (&r);
1309                 } 
1310                 else {
1311                     InsetRect (&r, -1, -1);
1312                     InvalRect (&r);
1313                 }
1314             }
1315             else {
1316                 InsetRect (&r, -1, -1);
1317                 InvalRect (&r);
1318             }
1319 
1320             offsetX = lineWidth * (Int4) (newval - oldval);
1321             tv->draw_port.port_origin.x+= offsetX;
1322 
1323             /* calculate clip box for given rect  */
1324             Rect2Box(&tv->draw_port, &r, &tv->draw_port.clip_box);
1325 
1326             Update ();
1327 
1328             setPort2Panel(&tv->draw_port); /* resize clip box to whole panel */
1329 
1330         }
1331     }
1332 }
1333     
1334 static void CorrectScrollbar(BaR sb, Int4 unitSize, Int4 tree_size, Int4 port_min,  Int4 port_max)
1335 {
1336 
1337     if (sb != NULL) {
1338         Int4 numUnits= ((tree_size < port_max)? port_max : tree_size)/unitSize;
1339         Int4 visUnits= (port_max - port_min + 1)/unitSize;
1340         Int2 max_val= (Int2)MAX((numUnits - visUnits), 0);
1341         Int2 val = (Int2) (port_min / unitSize);
1342 
1343         CorrectBarMax  (sb, max_val);
1344         CorrectBarValue(sb, val);
1345         CorrectBarPage (sb, (Int2)(visUnits - 1), (Int2)(visUnits - 1));
1346     }
1347 }
1348     
1349 static void DrawTreeProc(PaneL tree_panel)
1350 {
1351     TreeViewPtr  tv;
1352 
1353     if(tree_panel != NULL) {
1354         GetPanelExtra (tree_panel, &tv);
1355         if(tv->draw_port.bg_color_set == 0) {
1356             Uint4 def_col= GetColor();
1357             RecT r;
1358 
1359             GetPosition(tree_panel, &r);
1360             tv->draw_port.panel_origin_X= r.left;
1361             tv->draw_port.panel_origin_Y= r.top;
1362             if(tv->draw_port.line_color_set == 0) tv->draw_port.line_color= def_col;
1363             if(tv->draw_port.text_color_set == 0) tv->draw_port.text_color= def_col;
1364             if(tv->draw_port.plus_color_set == 0) tv->draw_port.plus_color= tv->draw_port.line_color;
1365             if(tv->draw_port.sbg_color_set  == 0) tv->draw_port.sbg_color= def_col;
1366 
1367             InvertColors();
1368             def_col= GetColor();
1369             tv->draw_port.bg_color_set= 1;
1370             tv->draw_port.bg_color= def_col;
1371             if(tv->draw_port.sfg_color_set  == 0) tv->draw_port.sfg_color= def_col;
1372             InvertColors();
1373 
1374             if(tv->draw_port.line_color == tv->draw_port.bg_color) {
1375                 Black();
1376                 tv->draw_port.line_color= tv->draw_port.text_color= tv->draw_port.sbg_color= GetColor();
1377                 White();
1378                 tv->draw_port.bg_color= tv->draw_port.sfg_color= GetColor();
1379             }
1380         }
1381         tree_toNode(tv->cr1, tv->my_root); /*tree_root(tv->cr1);*/
1382         drawTree(tv->cr1, TREE_X0, TREE_Y0);
1383     }
1384 }
1385 
1386 /*----------------------------------------------------------
1387  * find node with coordinate x, y
1388  */
1389 static Int2 find_node4xy(TreeCursorPtr cursor, Int4 my_x, Int4 my_y, Int4Ptr px, Int4Ptr py)
1390 {
1391     _box my_box;
1392     Int4 length;
1393     TreeViewPtr tv;
1394     Int2 res;
1395 
1396     my_box.xl= my_box.xr= my_x;
1397     my_box.yt= my_box.yb= my_y;
1398 
1399     if(!getBox4Cursor(cursor, &my_box)) return 0;
1400 
1401     my_box.xl-= 4;
1402     my_box.xr+= 4;
1403 
1404     if(!ptInBox(&my_box, *px, *py)) return 0;
1405 
1406     tv= (TreeViewPtr) getTree4Cursor(cursor);
1407 
1408     length= getNodeLength(cursor);
1409     my_x+= ((tv->length_scale >= 0)? 
1410             (tv->length_scale * length) : (length/(-tv->length_scale)));
1411 
1412     if(*py <= (my_y+= tv->row_height)) {
1413         /* we are on node itself */
1414         Int2 res= (*px < my_x)? 1 : 2;
1415         *px= my_box.xl + 4;
1416         *py= my_box.yt;
1417         return res;
1418     }
1419 
1420     if(*px < (my_x - 4)) return 0;
1421 
1422     /* we are on nodes children */
1423     if(tree_child(cursor)) {
1424 
1425         if(tv->cmpSiblings == NULL) {
1426             /* we don't want to sort siblings */
1427             do {
1428                 if((res= find_node4xy(cursor, my_x, my_y, px, py)) != 0) {
1429                     return res;
1430                 }
1431                 my_box.xl= my_box.xr= my_x;
1432                 my_box.yt= my_box.yb= my_y;
1433                 getBox4Cursor(cursor, &my_box);
1434                 my_y= my_box.yb;
1435             }
1436             while (tree_sibling(cursor));
1437         }
1438         else {/* siblings have to be sorted */
1439             TreeNodeId id;
1440 
1441             for(id.idi= 0; (id= getNextSibling(cursor, id)).idi != 0;) {
1442                 if((res= find_node4xy(cursor, my_x, my_y, px, py)) != 0) {
1443                     return res;
1444                 }
1445                 my_box.xl= my_box.xr= my_x;
1446                 my_box.yt= my_box.yb= my_y;
1447                 getBox4Cursor(cursor, &my_box);
1448                 my_y= my_box.yb;
1449             }
1450         }
1451 
1452         tree_parent(cursor);
1453     }
1454 
1455     return 0;
1456 }
1457         
1458 
1459 /*----------------------------------------------------------
1460  * this function set cursor (cr1) on selected node and return
1461  * the type of element selected
1462  */
1463 static Int2 find_Node4Point(TreeViewPtr tv, Int4Ptr x, Int4Ptr y)
1464 {
1465     tree_toNode(tv->cr1, tv->my_root); /*tree_root(tv->cr1);*/
1466     return find_node4xy(tv->cr1, TREE_X0, TREE_Y0, x, y);
1467 }
1468 
1469 static void node_open_close(TreeCursorPtr cursor, Int4 x, Int4 y)
1470 {
1471     TreeViewPtr tv= (TreeViewPtr) getTree4Cursor(cursor);
1472     _tnSegmPtr tns;
1473     Boolean need_resize;
1474     
1475     tns= getNodeViewerData((_tnSegmPtr)cursor->node->sys_data, tv->my_spy_id);
1476     if(tns == NULL) return;
1477 
1478     need_resize= (tns->h > tv->row_height)? closeSubtree(tv->cr1, TRUE) : openSubtree(tv->cr1, TRUE);
1479 
1480     if(need_resize) {
1481         tree_toNode(cursor, tv->my_root); /*tree_root(cursor);*/
1482         tns= getNodeViewerData((_tnSegmPtr)cursor->node->sys_data, tv->my_spy_id);
1483 
1484         setPort2Panel(&tv->draw_port);
1485         
1486         CorrectScrollbar(GetSlateHScrollBar((SlatE)(tv->draw_port.tree_panel)),
1487                          tv->row_width, tns->w + 16, tv->draw_port.clip_box.xl, tv->draw_port.clip_box.xr);
1488 
1489         CorrectScrollbar(GetSlateVScrollBar((SlatE)(tv->draw_port.tree_panel)),
1490                          tv->row_height, tns->h + 24, tv->draw_port.clip_box.yt, tv->draw_port.clip_box.yb);
1491 
1492         if(tv->sel_y > y) {
1493             /* selected node has been moved */
1494             tv->sel_y= -1024;
1495         }
1496 
1497         /* redraw all below y */
1498         tv->draw_port.clip_box.yt= y;
1499         redrawInPort(tv);
1500         setPort2Panel(&tv->draw_port);
1501     }
1502 }       
1503 
1504 static CharPtr calcBox4Select(TreeCursorPtr cursor, Int4 x0, Int4 y0, _boxPtr sel_box)
1505 {
1506     TreeViewPtr tv= (TreeViewPtr) getTree4Cursor(cursor);
1507     Int4 length= getNodeLength(cursor);
1508     Int2 icon_id= getIconId(cursor);
1509     CharPtr label= getNodeLabel(cursor);
1510 
1511     sel_box->xl= x0 + 
1512         ((tv->length_scale >= 0)? (tv->length_scale * length) : (length/(-tv->length_scale))) +
1513         (((tv->i_list != NULL) && (icon_id >= 0))? (getIconWidth(tv->i_list, icon_id)/2) : 0);
1514     sel_box->xr= x0 + calcNodeWidth(tv, icon_id, length, label);
1515     sel_box->yt= y0;
1516     sel_box->yb= y0 + tv->row_height;
1517     return label;
1518 }
1519         
1520 static void select_treeNode(TreeCursorPtr cursor, Int4 x, Int4 y)
1521 {
1522     TreeViewPtr tv= (TreeViewPtr) getTree4Cursor(cursor);
1523     _box my_box;
1524     CharPtr label;
1525     
1526     setPort2Panel(&tv->draw_port);
1527     Select(tv->draw_port.tree_panel);
1528 
1529 #if 0
1530     if(tv->evntFunc != NULL) {
1531         (*(tv->evntFunc))(cursor, TVIEW_ON_SELECT);
1532         Select(tv->draw_port.tree_panel);
1533     }
1534 #endif
1535 
1536 
1537     if(tv->sel_y >= 0) {
1538         /* we have selected node */
1539         
1540         /* check if selected node is in window */
1541         if((tv->sel_y < tv->draw_port.clip_box.yb) && 
1542            ((tv->sel_y + tv->row_height) > tv->draw_port.clip_box.yt)) {
1543             /* yes it is, we have to unselect it */
1544             label= calcBox4Select(tv->cr2, tv->sel_x, tv->sel_y, &my_box);
1545             unHighLightBox(&tv->draw_port, &my_box, label);
1546         }
1547     }
1548 
1549     /* select the new one */
1550     label= calcBox4Select(cursor, x, y, &my_box);
1551     highLightBox(&tv->draw_port, &my_box, label);
1552     tv->sel_x= x;
1553     tv->sel_y= y;
1554     tree_toNode(tv->cr2, tree_getId(cursor));
1555 }       
1556 
1557 /*****************************************************************************
1558 *
1559 *   ViewerClickProc (viewer, pt)
1560 *
1561 *****************************************************************************/
1562 
1563 static void ViewerClickProc (PaneL viewer, PoinT pt)
1564 
1565 {
1566     TreeViewPtr tv;
1567     Int4 x, y;
1568     TreeNodeId id;
1569 
1570     GetPanelExtra (viewer, &tv);
1571 
1572     x= (pt.x - tv->draw_port.panel_origin_X) + tv->draw_port.port_origin.x;
1573     y= (pt.y - tv->draw_port.panel_origin_Y) + tv->draw_port.port_origin.y;
1574         
1575     switch (find_Node4Point(tv, &x, &y)) {
1576     case 0: /* nothing selected */
1577         id.idi= 0;
1578         if(dblClick && (tv->dblClickFunc != NULL)) (*tv->dblClickFunc)(tv, id, FALSE);
1579         else if(shftKey && (tv->shiftClickFunc != NULL))
1580             (*tv->shiftClickFunc)(tv, id, FALSE);
1581         else if(ctrlKey && (tv->ctrlClickFunc != NULL))
1582             (*tv->ctrlClickFunc)(tv, id, FALSE);
1583         return;
1584     case 1:
1585         /* open/close subtree for this node */
1586         if(dblClick && (tv->dblClickFunc != NULL)) (*tv->dblClickFunc)(tv, tv->cr1->node_id, FALSE);
1587         else if(shftKey && (tv->shiftClickFunc != NULL))
1588             (*tv->shiftClickFunc)(tv, tv->cr1->node_id, FALSE);
1589         else if(ctrlKey && (tv->ctrlClickFunc != NULL))
1590             (*tv->ctrlClickFunc)(tv, tv->cr1->node_id, FALSE);
1591         else node_open_close(tv->cr1, x, y);
1592         return;
1593             
1594     case 2:
1595         /* select new node */
1596         if(dblClick && (tv->dblClickFunc != NULL)) (*tv->dblClickFunc)(tv, tv->cr1->node_id, TRUE);
1597         else if(shftKey && (tv->shiftClickFunc != NULL))
1598             (*tv->shiftClickFunc)(tv, tv->cr1->node_id, TRUE);
1599         else if(ctrlKey && (tv->ctrlClickFunc != NULL))
1600             (*tv->ctrlClickFunc)(tv, tv->cr1->node_id, TRUE);
1601         else select_treeNode(tv->cr1, x, y);
1602         return;
1603     }
1604 }
1605 
1606 #if 0
1607 static void ViewerHoldProc (PaneL viewer, PoinT pt)
1608 
1609 {
1610     TreeViewPtr tv;
1611     Int4 x, y;
1612 
1613 
1614     GetPanelExtra (viewer, &tv);
1615 
1616     if(tv->holdFunc == NULL) return;
1617 
1618     x= (pt.x - tv->draw_port.panel_origin_X) + tv->draw_port.port_origin.x;
1619     y= (pt.y - tv->draw_port.panel_origin_Y) + tv->draw_port.port_origin.y;
1620         
1621     switch (find_Node4Point(tv, &x, &y)) {
1622     case 0: /* nothing selected */
1623         (*tv->holdFunc)(tv, tv->cr2->node_id, FALSE);
1624         return;
1625     case 1:
1626         /* open/close subtree for this node */
1627         (*tv->holdFunc)(tv, tv->cr1->node_id, FALSE);
1628         return;
1629             
1630     case 2:
1631         /* select new node */
1632         (*tv->holdFunc)(tv, tv->cr1->node_id, TRUE);
1633         return;
1634     }
1635 }
1636 #endif
1637 
1638 /*
1639 typedef enum {
1640     TREE_CURSOR_MOVED = 0,
1641     TREE_NODE_UPDATE,
1642     TREE_NODE_UPD_DONE,
1643     TREE_NODEDATA_UPDATE,
1644     TREE_NODEDATA_UPD_DONE,
1645     TREE_NODE_DELETE,
1646     TREE_NODE_DEL_DONE,
1647     TREE_NODE_MOVE,
1648     TREE_NODE_MV_DONE,
1649     TREE_NODE_MERGE,
1650     TREE_NODE_MERGE_DONE,
1651     TREE_CHILDREN_MOVE,
1652     TREE_CHILDREN_MV_DONE,
1653     TREE_NODE_ADDED,
1654     TREE_SUBTREE_DELETE,
1655     TREE_SUBTREE_DEL_DONE
1656 } TreeEvent;
1657 */
1658 static void spy_proc(TreePtr tree, Int2 spy_id, TreeEvent event, 
1659                      TreeNodeId id1, TreeNodeId id2, VoidPtr node_data,
1660                      Int2 node_data_size)
1661 {
1662     static int tran_level= 0;
1663     static TreeEvent tran_stack[8];
1664     TreeViewPtr tv= (TreeViewPtr) tree_getSpyData(tree, spy_id);
1665     _tnSegmPtr tns;
1666     Boolean need_redraw= FALSE;
1667 
1668     switch(event) {
1669     case TREE_NODE_UPDATE: /* node will be updated */
1670         tree_toNode(tv->cr4, id1);
1671         if(getNodeViewerData((_tnSegmPtr)tv->cr4->node->sys_data, tv->my_spy_id) != NULL) {
1672             freeNodeSegm(tv->cr4);
1673             tran_stack[tran_level++]= TREE_NODE_UPDATE;
1674         }
1675         else {
1676             tran_stack[tran_level++]= TREE_CURSOR_MOVED;
1677         }
1678         break;
1679     case TREE_NODE_UPD_DONE: /* node was updated */
1680     case TREE_NODEDATA_UPD_DONE:
1681         if(tran_stack[--tran_level] == TREE_NODE_UPDATE) {
1682             if(tree_parent(tv->cr4)) {
1683                 openSubtree(tv->cr4, FALSE);
1684             }
1685             else {
1686                 makeNodeVisible(tv->cr4);
1687             }
1688             need_redraw= TRUE;
1689         }
1690         break;
1691 
1692     case TREE_NODEDATA_UPDATE: /* node will be updated */
1693         if(tran_stack[tran_level - 1] == TREE_NODE_UPDATE) {
1694             tran_stack[tran_level++]= TREE_CURSOR_MOVED;
1695         }
1696         else {
1697             tree_toNode(tv->cr4, id1);
1698             if(getNodeViewerData((_tnSegmPtr)tv->cr4->node->sys_data, tv->my_spy_id) != NULL) {
1699                 freeNodeSegm(tv->cr4);
1700                 tran_stack[tran_level++]= TREE_NODE_UPDATE;
1701             }
1702             else {
1703                 tran_stack[tran_level++]= TREE_CURSOR_MOVED;
1704             }
1705         }
1706         break;
1707 
1708     case TREE_NODE_DELETE: /* node will be deleted */
1709         tree_toNode(tv->cr4, id1);
1710         if(getNodeViewerData((_tnSegmPtr)tv->cr4->node->sys_data, tv->my_spy_id) != NULL) {
1711             freeNodeSegm(tv->cr4);
1712             tran_stack[tran_level++]= TREE_NODE_DELETE;
1713             tree_toNode(tv->cr4, id2);
1714             closeSubtree(tv->cr4, FALSE);
1715         }
1716         else {
1717             tran_stack[tran_level++]= TREE_CURSOR_MOVED;
1718         }
1719         tree_parent(tv->cr4);
1720         break;
1721 
1722     case TREE_SUBTREE_DEL_DONE:
1723     case TREE_NODE_DEL_DONE: /* node was deleted */
1724         tree_toNode(tv->cr4, id1);
1725         if(tran_stack[--tran_level] == TREE_NODE_DELETE) {
1726             openSubtree(tv->cr4, FALSE);
1727             need_redraw= TRUE;
1728         }
1729         break;
1730 
1731     case TREE_NODE_MOVE: /* node will be moved */
1732         tree_toNode(tv->cr4, id2);
1733         if(getNodeViewerData((_tnSegmPtr)tv->cr4->node->sys_data, tv->my_spy_id) != NULL) {
1734             /* node is visible */
1735             tree_parent(tv->cr4);
1736         }
1737         else {
1738             tree_toNode(tv->cr4, id1);
1739         }
1740         break;
1741 
1742     case TREE_NODE_MV_DONE: /* node has been moved */
1743         if(tv->cr4->node_id.idi != id1.idi) {
1744             need_redraw= openSubtree(tv->cr4, FALSE);
1745             tree_toNode(tv->cr4, id1);
1746         }
1747         need_redraw|= openSubtree(tv->cr4, FALSE);
1748         break;
1749 
1750     case TREE_CHILDREN_MOVE: /* children will be moved */
1751         tree_toNode(tv->cr4, id2);
1752         if(((tns= getNodeViewerData((_tnSegmPtr)tv->cr4->node->sys_data, tv->my_spy_id)) != NULL) &&
1753            (tns->h > tv->row_height)) {
1754             need_redraw= closeSubtree(tv->cr4, TRUE);
1755         }
1756         break;
1757 
1758     case TREE_CHILDREN_MV_DONE: /* children have been moved */
1759         tree_toNode(tv->cr4, id1);
1760         if((tns= getNodeViewerData((_tnSegmPtr)tv->cr4->node->sys_data, tv->my_spy_id)) == NULL) {
1761             /* this node is invisible */
1762             for(need_redraw= tree_child(tv->cr4); need_redraw; need_redraw= tree_sibling(tv->cr4)) {
1763                 if(getNodeViewerData((_tnSegmPtr)tv->cr4->node->sys_data, tv->my_spy_id) != NULL) {
1764                     freeNodeSegm(tv->cr4);
1765                 }
1766             }
1767         }
1768         else {
1769             closeSubtree(tv->cr4, FALSE);
1770             need_redraw= openSubtree(tv->cr4, TRUE);
1771         }
1772         break;
1773                 
1774     case TREE_SUBTREE_DELETE: /* subtree will be deleted */
1775         tree_toNode(tv->cr4, id1);
1776         if(getNodeViewerData((_tnSegmPtr)tv->cr4->node->sys_data, tv->my_spy_id) != NULL) {
1777             /* this node is visible */
1778             
1779             tran_stack[tran_level++]= TREE_NODE_DELETE;
1780         }
1781         else {
1782             tran_stack[tran_level++]= TREE_CURSOR_MOVED;
1783         }
1784         closeAllSubtrees(tv->cr4);
1785         tree_parent(tv->cr4);
1786         break;
1787         
1788     case TREE_NODE_MERGE: /* nodes will be merged */
1789         tree_toNode(tv->cr4, id2);
1790         if(getNodeViewerData((_tnSegmPtr)tv->cr4->node->sys_data, tv->my_spy_id) != NULL) {
1791             /* this node is visible */
1792             freeNodeSegm(tv->cr4);
1793         }
1794         break;
1795 
1796     case TREE_NODE_MERGE_DONE: /* nodes was merged */
1797         tree_toNode(tv->cr4, id2);
1798         openSubtree(tv->cr4, TRUE);
1799         tree_toNode(tv->cr4, id1);
1800         openSubtree(tv->cr4, TRUE);
1801         need_redraw= TRUE;
1802         break;
1803 
1804     case TREE_NODE_ADDED: /* new node was added */
1805         tree_toNode(tv->cr4, id1);
1806         need_redraw= openSubtree(tv->cr4, TRUE);
1807         break;
1808             
1809     case TREE_CURSOR_MOVED:
1810         break;  /* do nothing */
1811             
1812     case TREE_SHUTDOWN:
1813         break;
1814     }
1815     
1816 
1817 
1818     if(need_redraw) {
1819         tree_toNode(tv->cr4, tv->my_root); /*tree_root(tv->cr4);*/
1820         tns= getNodeViewerData((_tnSegmPtr)tv->cr4->node->sys_data, tv->my_spy_id);
1821 
1822         setPort2Panel(&tv->draw_port);
1823         
1824         CorrectScrollbar(GetSlateHScrollBar((SlatE)(tv->draw_port.tree_panel)),
1825                          tv->row_width, tns->w + 16, tv->draw_port.clip_box.xl, tv->draw_port.clip_box.xr);
1826 
1827         CorrectScrollbar(GetSlateVScrollBar((SlatE)(tv->draw_port.tree_panel)),
1828                          tv->row_height, tns->h + 24, tv->draw_port.clip_box.yt, tv->draw_port.clip_box.yb);
1829         tv->sel_y= -1024;
1830         tview_redraw(tv);
1831     }
1832 }
1833 
1834 static void close_proc(WindoW w)
1835 {
1836     TreeViewPtr tv= (TreeViewPtr) GetWindowExtra(w);
1837     
1838     tview_delete(tv, 0);
1839 }
1840 
1841 static void resize_proc(WindoW w)
1842 {
1843     TreeViewPtr tv= (TreeViewPtr) GetWindowExtra(w);
1844     RecT r;
1845     _tnSegmPtr tns;
1846 
1847     setPort2Panel(&tv->draw_port);
1848     Nlm_GetRect((GraphiC)w, &r);
1849     r.right-= r.left + 10;
1850     r.left= 10;
1851     r.bottom-= r.top + 10;
1852     r.top= 10;
1853     SetPosition(tv->draw_port.tree_panel, &r);
1854 
1855     tv->draw_port.panel_origin_X= r.left;
1856     tv->draw_port.panel_origin_Y= r.top;
1857 
1858     InsetRect(&r, 1, 1);
1859     tv->draw_port.clip_box.xr= tv->draw_port.clip_box.xl + (r.right - r.left - Nlm_vScrollBarWidth);
1860     tv->draw_port.clip_box.yb= tv->draw_port.clip_box.yt + (r.bottom - r.top - Nlm_hScrollBarHeight);
1861 
1862     /* we need to correct scroll bars here */
1863     tree_toNode(tv->cr1, tv->my_root); /*tree_root(tv->cr1);*/
1864     tns= getNodeViewerData((_tnSegmPtr)tv->cr1->node->sys_data, tv->my_spy_id);
1865 
1866     CorrectScrollbar(GetSlateHScrollBar((SlatE)(tv->draw_port.tree_panel)),
1867                      tv->row_width, tns->w + 16, tv->draw_port.clip_box.xl, tv->draw_port.clip_box.xr);
1868 
1869     CorrectScrollbar(GetSlateVScrollBar((SlatE)(tv->draw_port.tree_panel)),
1870                      tv->row_height, tns->h + 24, tv->draw_port.clip_box.yt, tv->draw_port.clip_box.yb);
1871 
1872     Select(tv->draw_port.tree_panel);
1873     InvalRect (&r);
1874     /*    Black();
1875     FrameRect(&r);*/
1876     Update();
1877 }
1878 
1879 void tview_resize(TreeViewPtr tv, RectPtr r)
1880 {
1881     _tnSegmPtr tns;
1882 
1883     SetPosition(tv->draw_port.tree_panel, r);
1884 
1885     tv->draw_port.panel_origin_X= r->left;
1886     tv->draw_port.panel_origin_Y= r->top;
1887 
1888     InsetRect(r, 1, 1);
1889     tv->draw_port.clip_box.xr= tv->draw_port.clip_box.xl + (r->right - r->left - Nlm_vScrollBarWidth);
1890     tv->draw_port.clip_box.yb= tv->draw_port.clip_box.yt + (r->bottom - r->top - Nlm_hScrollBarHeight);
1891 
1892     /* we need to correct scroll bars here */
1893     tree_toNode(tv->cr1, tv->my_root); /*tree_root(tv->cr1);*/
1894     tns= getNodeViewerData((_tnSegmPtr)tv->cr1->node->sys_data, tv->my_spy_id);
1895 
1896     CorrectScrollbar(GetSlateHScrollBar((SlatE)(tv->draw_port.tree_panel)),
1897                      tv->row_width, tns->w + 16, tv->draw_port.clip_box.xl, tv->draw_port.clip_box.xr);
1898 
1899     CorrectScrollbar(GetSlateVScrollBar((SlatE)(tv->draw_port.tree_panel)),
1900                      tv->row_height, tns->h + 24, tv->draw_port.clip_box.yt, tv->draw_port.clip_box.yb);
1901     Select(tv->draw_port.tree_panel);
1902     InvalRect (r);
1903     Update();
1904 }
1905 
1906 static void tv_cr2_callback(TreeCursorPtr cursor, TreeEvent event, TreeNodeId id)
1907 {
1908     if(event == TREE_CURSOR_MOVED) {
1909         TreeViewPtr tv= (TreeViewPtr) getTree4Cursor(cursor);
1910 
1911         if(tv->evntFunc != NULL) {
1912             (*(tv->evntFunc))(cursor, TVIEW_ON_SELECT);
1913             Select(tv->draw_port.tree_panel);
1914         }
1915     }
1916 }
1917 
1918 static void tv_cr5_callback(TreeCursorPtr cursor, TreeEvent event, TreeNodeId id)
1919 {
1920     if(event == TREE_CURSOR_MOVED) {
1921         TreeViewPtr tv= (TreeViewPtr) getTree4Cursor(cursor);
1922 
1923         tv->my_root= id;
1924         if(getNodeViewerData((_tnSegmPtr)cursor->node->sys_data, tv->my_spy_id) == NULL) {
1925             tree_parent(cursor);
1926         }
1927     }
1928 }
1929 
1930 
1931 TreeViewPtr tview_create(GrouP parent, Int2 width, Int2 height, 
1932                          TreePtr tree, _ImageListPtr il, Int2 l_scale, 
1933                          TreeNodeCmpFunc NodeCmp)
1934 {
1935     TreeViewPtr tv;
1936     /* int i; */
1937     _tnSegmPtr tns;
1938 
1939     if((tv= (TreeViewPtr) MemNew(sizeof(TreeView))) == NULL) return NULL;
1940 
1941     if((tv->segm_buff= getNewSegmBuff()) == NULL) {
1942         MemFree(tv);
1943         return NULL;
1944     }
1945 
1946 
1947     if(parent == NULL) {
1948         /* we need to create window for tree view */
1949         tv->draw_port.tree_window= DocumentWindow(-50, -33, -10, -10, "Tree View", close_proc, resize_proc);
1950         parent= tv->draw_port.tree_window;
1951         SetWindowExtra(tv->draw_port.tree_window, tv, NULL);
1952     }
1953     else tv->draw_port.tree_window= NULL;
1954 
1955     /* create panel */
1956     tv->draw_port.tree_panel= AutonomousPanel(parent, width, height, DrawTreeProc,
1957                                               TreeVScrollProc, TreeHScrollProc,
1958                                               sizeof(TreeViewPtr), NULL, NULL);
1959 
1960     if(tv->draw_port.tree_panel == NULL) {
1961         MemFree(tv->segm_buff);
1962         MemFree(tv);
1963         return NULL;
1964     }
1965 
1966     SetPanelClick (tv->draw_port.tree_panel, ViewerClickProc, NULL, NULL, NULL);
1967 
1968     SetPanelExtra(tv->draw_port.tree_panel, &tv);
1969 
1970     tv->i_list= il;
1971 
1972     /* populate tv structure */
1973     tv->tree= tree;
1974 
1975     tv->cr1= tree_openCursor(tree, tv, NULL);
1976     tv->cr2= tree_openCursor(tree, tv, tv_cr2_callback);
1977     tv->cr3= NULL;
1978     tv->cr4= tree_openCursor(tree, tv, NULL);
1979     
1980     tv->my_spy_id= tree_addSpy(tree, spy_proc, tv);
1981 
1982     /* draw port setup */
1983     tv->draw_port.panel_origin_X= tv->draw_port.panel_origin_Y= 0;
1984     tv->draw_port.port_origin.x= 0;
1985     tv->draw_port.port_origin.y= 0;
1986      
1987     /*Black();*/
1988     tv->draw_port.clip_box.xl= 0;
1989     tv->draw_port.clip_box.yt= 0;
1990     tv->draw_port.clip_box.xr= width;
1991     tv->draw_port.clip_box.yb= height;
1992     tv->draw_port.line_color= tv->draw_port.text_color= tv->draw_port.sbg_color= 0;
1993     tv->draw_port.line_color_set= tv->draw_port.text_color_set= tv->draw_port.sbg_color_set= 0;
1994     /* InvertColors(); */
1995     tv->draw_port.bg_color= tv->draw_port.sfg_color= 0;
1996     tv->draw_port.bg_color_set= tv->draw_port.sfg_color_set= 0;
1997     tv->draw_port.plus_color= 0;
1998     tv->draw_port.plus_color_set= 0;
1999     /*InvertColors();*/
2000 
2001     tv->draw_port.pen_w= 1;
2002 
2003     tv->row_height= FontHeight() + 2;
2004     /*tv->row_height+= tv->row_height/4;*/
2005     tv->row_width= CharWidth('w');
2006     if(tv->row_width < 4) tv->row_width= 4;
2007 
2008     tv->length_scale= (l_scale == 0)? 1 : l_scale;
2009 
2010     tv->sel_y= -1024;
2011 
2012     /* prepare root node for drawing */
2013     tns= allocNewSegm(tv->cr1);
2014     tns->w= calcNodeWidth(tv, getIconId(tv->cr1), getNodeLength(tv->cr1), getNodeLabel(tv->cr1));
2015     tns->h= tv->row_height;
2016 
2017     tv->cmpSiblings= NodeCmp;
2018     tv->dblClickFunc= NULL;
2019     tv->shiftClickFunc= NULL;
2020     tv->ctrlClickFunc= NULL;
2021 
2022     tv->cr5= tree_openCursor(tree, tv, tv_cr5_callback);
2023     
2024     tv->my_root= tv->cr5->node_id;
2025 
2026     openSubtree(tv->cr1, TRUE);
2027 
2028     if(tv->draw_port.tree_window != NULL) {
2029         RealizeWindow(tv->draw_port.tree_window);
2030         Show(tv->draw_port.tree_window);
2031     }
2032     return tv;
2033 }
2034 
2035 
2036 TreeViewPtr tview_createCustom(Int2 left, Int2 top, Int2 width, Int2 height,
2037                                CharPtr title, void (*menuCrtFunc)(WindoW),
2038                          TreePtr tree, _ImageListPtr il, Int2 l_scale, 
2039                          TreeNodeCmpFunc NodeCmp)
2040 {
2041     TreeViewPtr tv;
2042     /* int i; */
2043     _tnSegmPtr tns;
2044 
2045     if((tv= (TreeViewPtr) MemNew(sizeof(TreeView))) == NULL) return NULL;
2046 
2047     if((tv->segm_buff= getNewSegmBuff()) == NULL) {
2048         MemFree(tv);
2049         return NULL;
2050     }
2051 
2052 
2053     /* we need to create window for tree view */
2054     tv->draw_port.tree_window= DocumentWindow(left, top, -10, -10, title, close_proc, resize_proc);
2055     SetWindowExtra(tv->draw_port.tree_window, tv, NULL);
2056     
2057     if(menuCrtFunc != NULL) (*menuCrtFunc)(tv->draw_port.tree_window);
2058 
2059     /* create panel */
2060     tv->draw_port.tree_panel= AutonomousPanel(tv->draw_port.tree_window, width, height, DrawTreeProc,
2061                                               TreeVScrollProc, TreeHScrollProc,
2062                                               sizeof(TreeViewPtr), NULL, NULL);
2063 
2064     if(tv->draw_port.tree_panel == NULL) {
2065         MemFree(tv->segm_buff);
2066         MemFree(tv);
2067         return NULL;
2068     }
2069 
2070     SetPanelClick (tv->draw_port.tree_panel, ViewerClickProc, NULL, NULL, NULL);
2071 
2072     SetPanelExtra(tv->draw_port.tree_panel, &tv);
2073 
2074     tv->i_list= il;
2075 
2076     /* populate tv structure */
2077     tv->tree= tree;
2078 
2079     tv->cr1= tree_openCursor(tree, tv, NULL);
2080     tv->cr2= tree_openCursor(tree, tv, tv_cr2_callback);
2081     tv->cr3= NULL;
2082     tv->cr4= tree_openCursor(tree, tv, NULL);
2083 
2084     tv->my_spy_id= tree_addSpy(tree, spy_proc, tv);
2085 
2086     /* draw port setup */
2087     tv->draw_port.panel_origin_X= tv->draw_port.panel_origin_Y= 0;
2088     tv->draw_port.port_origin.x= 0;
2089     tv->draw_port.port_origin.y= 0;
2090      
2091     /*Black();*/
2092     tv->draw_port.clip_box.xl= 0;
2093     tv->draw_port.clip_box.yt= 0;
2094     tv->draw_port.clip_box.xr= width;
2095     tv->draw_port.clip_box.yb= height;
2096     tv->draw_port.line_color= tv->draw_port.text_color= tv->draw_port.sbg_color= 0;
2097     tv->draw_port.line_color_set= tv->draw_port.text_color_set= tv->draw_port.sbg_color_set= 0;
2098     /* InvertColors(); */
2099     tv->draw_port.bg_color= tv->draw_port.sfg_color= 0;
2100     tv->draw_port.bg_color_set= tv->draw_port.sfg_color_set= 0;
2101     tv->draw_port.plus_color= 0;
2102     tv->draw_port.plus_color_set= 0;
2103     /*InvertColors();*/
2104 
2105     tv->draw_port.pen_w= 1;
2106 
2107     tv->row_height= FontHeight() + 2;
2108     /*tv->row_height+= tv->row_height/4;*/
2109     tv->row_width= CharWidth('w');
2110     if(tv->row_width < 4) tv->row_width= 4;
2111 
2112     tv->length_scale= (l_scale == 0)? 1 : l_scale;
2113 
2114     tv->sel_y= -1024;
2115 
2116     /* prepare root node for drawing */
2117     tns= allocNewSegm(tv->cr1);
2118     tns->w= calcNodeWidth(tv, getIconId(tv->cr1), getNodeLength(tv->cr1), getNodeLabel(tv->cr1));
2119     tns->h= tv->row_height;
2120 
2121     tv->cmpSiblings= NodeCmp;
2122     tv->dblClickFunc= NULL;
2123     tv->shiftClickFunc= NULL;
2124     tv->ctrlClickFunc= NULL;
2125 
2126     tv->cr5= tree_openCursor(tree, tv, tv_cr5_callback);
2127     
2128     tv->my_root= tv->cr5->node_id;
2129 
2130     openSubtree(tv->cr1, TRUE);
2131 
2132     if(tv->draw_port.tree_window != NULL) {
2133         RealizeWindow(tv->draw_port.tree_window);
2134         Show(tv->draw_port.tree_window);
2135     }
2136     return tv;
2137 }
2138     
2139 Boolean tview_setTextColor(TreeViewPtr tv, Uint4 color)
2140 {
2141     if((color != tv->draw_port.bg_color) || (tv->draw_port.bg_color_set == 0)){
2142         tv->draw_port.text_color= color;
2143         tv->draw_port.text_color_set= 1;
2144         return TRUE;
2145     }
2146     
2147     return FALSE;
2148 }
2149 
2150 Boolean tview_setLineColor(TreeViewPtr tv, Uint4 color)
2151 {
2152     if((color != tv->draw_port.bg_color) || (tv->draw_port.bg_color_set == 0)) {
2153         tv->draw_port.line_color= color;
2154         tv->draw_port.line_color_set= 1;
2155         return TRUE;
2156     }
2157     
2158     return FALSE;
2159 }
2160 
2161 Boolean tview_setPlusColor(TreeViewPtr tv, Uint4 color)
2162 {
2163     if((color != tv->draw_port.bg_color) || (tv->draw_port.bg_color_set == 0)) {
2164         tv->draw_port.plus_color= color;
2165         tv->draw_port.plus_color_set= 1;
2166         return TRUE;
2167     }
2168     
2169     return FALSE;
2170 }
2171 
2172 Boolean tview_setSelBGColor(TreeViewPtr tv, Uint4 color)
2173 {
2174     tv->draw_port.sbg_color= color;
2175     tv->draw_port.sbg_color_set= 1;
2176     return TRUE;
2177 }
2178 
2179 Boolean tview_setSelFGColor(TreeViewPtr tv, Uint4 color)
2180 {
2181     tv->draw_port.sfg_color= color;
2182     tv->draw_port.sfg_color_set= 1;
2183     return TRUE;
2184 }
2185 
2186 Int2 tview_labelCmp(TreeCursorPtr c1, TreeCursorPtr c2)
2187 {
2188     static char l1[256], l2[256];
2189     Int2 res;
2190 
2191     StringNCpy(l1, getNodeLabel(c1), 255);
2192     StringNCpy(l2, getNodeLabel(c2), 255);
2193     res= StringCmp(l1, l2);
2194     return res;
2195 }
2196 
2197 Int2 tview_distanceCmp(TreeCursorPtr c1, TreeCursorPtr c2)
2198 {
2199     return (Int2)(getNodeLength(c1) - getNodeLength(c2));
2200 }
2201 
2202 static void resortNodes(TreeCursorPtr cursor)
2203 {
2204     TreeViewPtr tv= (TreeViewPtr) getTree4Cursor(cursor);
2205     _tnSegmPtr tns= getNodeViewerData((_tnSegmPtr)cursor->node->sys_data, tv->my_spy_id);
2206     TreeNodeId nid= tree_getId(cursor);
2207     Boolean res;
2208 
2209     if((tns == NULL) || (tns->h <= tv->row_height)) return;
2210 
2211     closeSubtree(cursor, FALSE);
2212     
2213     tree_toNode(cursor, nid);
2214 
2215     openSubtree(cursor, FALSE);
2216 
2217     tree_toNode(cursor, nid);
2218 
2219     for(res= tree_child(cursor); res; res= tree_sibling(cursor)) {
2220         resortNodes(cursor);
2221     }
2222 
2223     tree_toNode(cursor, nid);
2224 }
2225 
2226 TreeNodeCmpFunc tview_setNodeCmpFunc(TreeViewPtr tv, TreeNodeCmpFunc NodeCmp)
2227 {
2228     TreeNodeCmpFunc old;
2229     
2230     old= tv->cmpSiblings;
2231     tv->cmpSiblings= NodeCmp;
2232 
2233     if(NodeCmp != NULL) {
2234         TreeNodeId sid= tv->cr2->node_id;
2235 
2236         WatchCursor();
2237         tree_toNode(tv->cr1, tv->my_root); /*tree_root(tv->cr1);*/
2238         resortNodes(tv->cr1);
2239         tree_toNode(tv->cr2, sid);
2240         tview_showSelected(tv);
2241         ArrowCursor();
2242     }
2243 
2244     return old;
2245 }
2246 
2247 TreeViewEventFunc tview_setEventHandler(TreeViewPtr tv, TreeViewEventFunc HandlerFunc)
2248 {
2249     TreeViewEventFunc old;
2250     
2251     old= tv->evntFunc;
2252     tv->evntFunc= HandlerFunc;
2253 
2254     return old;
2255 }
2256 
2257 
2258 TreeViewClickFunc tview_setDblClickFunc(TreeViewPtr tv, TreeViewClickFunc dblClickProc)
2259 {
2260     TreeViewClickFunc old;
2261     
2262     old= tv->dblClickFunc;
2263     tv->dblClickFunc= dblClickProc;
2264 
2265     return old;
2266 }
2267 
2268 TreeViewClickFunc tview_setShiftClickFunc(TreeViewPtr tv, TreeViewClickFunc shiftClickProc)
2269 {
2270     TreeViewClickFunc old;
2271     
2272     old= tv->shiftClickFunc;
2273     tv->shiftClickFunc= shiftClickProc;
2274 
2275     return old;
2276 }
2277 
2278 TreeViewClickFunc tview_setCtrlClickFunc(TreeViewPtr tv, TreeViewClickFunc ctrlClickProc)
2279 {
2280     TreeViewClickFunc old;
2281     
2282     old= tv->ctrlClickFunc;
2283     tv->ctrlClickFunc= ctrlClickProc;
2284 
2285     return old;
2286 }
2287                 
2288 void tview_redraw(TreeViewPtr tv)
2289 {
2290 
2291     PaneL viewer= tv->draw_port.tree_panel;
2292     RecT r;
2293     _tnSegmPtr tns;
2294 
2295     if (Visible(viewer) && AllParentsVisible (viewer)) {
2296 
2297         Select(viewer);
2298         ObjectRect(viewer, &r);
2299         /*InsetRect(&r, 1, 1);*/
2300         setPort2Panel(&tv->draw_port);
2301         
2302         tree_toNode(tv->cr1, tv->my_root); /*tree_root(cursor);*/
2303         tns= getNodeViewerData((_tnSegmPtr)tv->cr1->node->sys_data, tv->my_spy_id);
2304 
2305         setPort2Panel(&tv->draw_port);
2306         
2307         CorrectScrollbar(GetSlateHScrollBar((SlatE)(tv->draw_port.tree_panel)),
2308                      tv->row_width, tns->w + 16, tv->draw_port.clip_box.xl, tv->draw_port.clip_box.xr);
2309 
2310         CorrectScrollbar(GetSlateVScrollBar((SlatE)(tv->draw_port.tree_panel)),
2311                      tv->row_height, tns->h + 24, tv->draw_port.clip_box.yt, tv->draw_port.clip_box.yb);
2312         Select(viewer);
2313         InvalRect(&r);
2314         Update();
2315     }
2316 }
2317 
2318 static Boolean ancestor(TreeCursorPtr cursor, TreeNodeId nid)
2319 {
2320     TreeNodeId pid= cursor->node_id;
2321     TreeNodeId gpid= cursor->node->parent;
2322 
2323     tree_toNode(cursor, nid);
2324     while(cursor->node_id.idi != gpid.idi) {
2325         if(cursor->node_id.idi == pid.idi) return TRUE;
2326         if(!tree_parent(cursor)) break;
2327     }
2328 
2329     tree_toNode(cursor, pid);
2330     return FALSE;
2331 }
2332     
2333 /*-------------------------------------------
2334  * function makes node tv->cr1 visible
2335  */
2336 static void getNodeCoordinates(TreeViewPtr tv, Int4Ptr node_x, Int4Ptr node_y)
2337 {
2338     _tnSegmPtr tns;
2339     Int4 x, y;
2340     _box my_box;
2341     /*Boolean need_cont;*/
2342     TreeNodeId nid= tv->cr1->node_id;
2343     TreeNodeId id;
2344     Int4 length;
2345 
2346     /* make node visible */
2347     tree_toNode(tv->cr1, tv->my_root); /*tree_root(tv->cr1);*/
2348     x= TREE_X0;
2349     y= TREE_Y0;
2350 
2351     if(tv->cr3 == NULL) {
2352         tv->cr3= tree_openCursor(tv->tree, tv, NULL);
2353     }
2354 
2355     while(tv->cr1->node_id.idi != nid.idi) {
2356 
2357         tns= getNodeViewerData((_tnSegmPtr)tv->cr1->node->sys_data, tv->my_spy_id);
2358         if(tns == NULL) break;
2359         if(tns->h <= tv->row_height) {
2360             openSubtree(tv->cr1, TRUE);
2361         }
2362         y+= tv->row_height;
2363         length= getNodeLength(tv->cr1);
2364         x+= ((tv->length_scale >= 0)? 
2365              (tv->length_scale * length) : (length/(-tv->length_scale)));
2366         
2367         if(tree_child(tv->cr1)) {
2368 
2369             if(tv->cmpSiblings == NULL) {
2370                 /* we don't want to sort siblings */
2371                 do {
2372                     if(ancestor(tv->cr1, nid)) break;
2373                     
2374                     my_box.xl= my_box.xr= x;
2375                     my_box.yt= my_box.yb= y;
2376                     getBox4Cursor(tv->cr1, &my_box);
2377                     y= my_box.yb;
2378                 }
2379                 while (tree_sibling(tv->cr1));
2380             }
2381             else {/* siblings have to be sorted */
2382 
2383                 for(id.idi= 0; (id= getNextSibling(tv->cr1, id)).idi != 0;) {
2384 
2385                     if(ancestor(tv->cr1, nid)) break;
2386 
2387                     my_box.xl= my_box.xr= x;
2388                     my_box.yt= my_box.yb= y;
2389                     getBox4Cursor(tv->cr1, &my_box);
2390                     y= my_box.yb;
2391                 }
2392             }
2393         }
2394         else {
2395             break;
2396         }
2397     }
2398 
2399     *node_x= x;
2400     *node_y= y;
2401     tree_toNode(tv->cr1, nid);
2402 }
2403 
2404         
2405 /*-------------------------------------------
2406  * Adjust scrolling to show selected node
2407  * SetBarValue(Nlm_BaR b, Nlm_Int4 val)
2408  * extern Nlm_Int4 Nlm_GetBarMax (Nlm_BaR b)
2409  */
2410 void tview_showSelected(TreeViewPtr tv)
2411 {
2412     Int4 bar_val= -1, s;
2413     BaR b;
2414     _box my_box;
2415     
2416 
2417     if(tv->draw_port.tree_window != NULL) Select(tv->draw_port.tree_window);
2418 
2419     setPort2Panel(&tv->draw_port);
2420     if(tv->sel_y < 0) {
2421 
2422         /* we have to calculate coordinates for selected node */
2423         tree_toNode(tv->cr1, tree_getId(tv->cr2));
2424         getNodeCoordinates(tv, &tv->sel_x, &tv->sel_y);
2425     }
2426 
2427     /* adjust vertical bar */
2428 
2429     b= GetSlateVScrollBar((SlatE)(tv->draw_port.tree_panel));
2430 
2431     if(tv->sel_y < tv->draw_port.clip_box.yt) {
2432         /* the node is above the screen */
2433         if(tv->sel_y == 0) {
2434             /* this is a root */
2435             bar_val= 0;
2436         }
2437         else {
2438             bar_val= tv->sel_y/tv->row_height - 1;
2439         }
2440     }
2441     else if(tv->sel_y >= tv->draw_port.clip_box.yb) {
2442         /* the node is below the screen */
2443         s= (tv->draw_port.clip_box.yb - tv->draw_port.clip_box.yt)/tv->row_height;
2444         bar_val= tv->sel_y/tv->row_height - s + 2;
2445         if(bar_val < 0) bar_val= 1;
2446         s= GetBarMax(b);
2447         if(bar_val > s) bar_val= s;
2448     }
2449 
2450     if(bar_val >= 0) {
2451         SetBarValue(b, bar_val);
2452     }
2453     
2454     /* adjust horisontal bar */
2455 
2456     b= GetSlateHScrollBar((SlatE)(tv->draw_port.tree_panel));
2457     bar_val= -1;
2458     s= GetBarMax(b);
2459 
2460     if(s == 0) return;
2461     calcBox4Select(tv->cr2, tv->sel_x, tv->sel_y, &my_box);
2462     if((my_box.xl >= tv->draw_port.clip_box.xl) && (my_box.xr < tv->draw_port.clip_box.xr)) {
2463         /* perfectly visible */
2464         return;
2465     }
2466     
2467     bar_val= tv->sel_x/tv->row_width - 1;
2468     if(bar_val < 0) bar_val= 0;
2469     if(bar_val > s) bar_val= s;
2470     
2471     if(bar_val >= 0) {
2472         SetBarValue(b, bar_val);
2473     }    
2474 
2475 }    
2476         
2477 Boolean tview_selectNode(TreeViewPtr tv, TreeNodeId id)
2478 {
2479     if(tree_toNode(tv->cr1, id)) {
2480         Int4 x, y;
2481 
2482         if(!tree_isDescendant(tv->cr5, tv->cr1)) {
2483             tview_moveRoot(tv, tree_getAncestor(tv->cr5, tv->cr1));
2484             tree_toNode(tv->cr1, id);
2485         }
2486         getNodeCoordinates(tv, &x, &y);
2487         select_treeNode(tv->cr1, x, y);
2488         tview_showSelected(tv);
2489         return TRUE;
2490     }
2491     return FALSE;
2492 }
2493         
2494 Boolean tview_openSubtree(TreeViewPtr tv, TreeNodeId id)
2495 {
2496     if(tree_toNode(tv->cr1, id)) {
2497         Int4 x, y;
2498 
2499         getNodeCoordinates(tv, &x, &y);
2500         openSubtree(tv->cr1, TRUE);
2501         return TRUE;
2502     }
2503     return FALSE;
2504 }
2505 
2506 Boolean tview_closeSubtree(TreeViewPtr tv, TreeNodeId id)
2507 {
2508     if(tree_toNode(tv->cr1, id)) {
2509 
2510         closeSubtree(tv->cr1, TRUE);
2511         return TRUE;
2512     }
2513     return FALSE;
2514 }
2515 
2516 void tview_hide(TreeViewPtr tv)
2517 {
2518     if(tv->draw_port.tree_window != NULL) Hide(tv->draw_port.tree_window);
2519     else Hide(tv->draw_port.tree_panel);
2520 }
2521 
2522 void tview_show(TreeViewPtr tv)
2523 {
2524     if(tv->draw_port.tree_window != NULL) Show(tv->draw_port.tree_window);
2525     else Show(tv->draw_port.tree_panel);
2526 }
2527 
2528 
2529 void tview_disable(TreeViewPtr tv)
2530 {
2531     Disable(tv->draw_port.tree_panel);
2532 }
2533 
2534 void tview_enable(TreeViewPtr tv)
2535 {
2536     Enable(tv->draw_port.tree_panel);
2537 }
2538 
2539 static void closeAllSubtrees(TreeCursorPtr cursor)
2540 {
2541     freeNodeSegm(cursor);
2542     if(tree_child(cursor)) {
2543         do {
2544             closeAllSubtrees(cursor);
2545         }
2546         while(tree_sibling(cursor));
2547         tree_parent(cursor);
2548     }
2549 }
2550         
2551         
2552 void tview_delete(TreeViewPtr tv, Boolean do_hide)
2553 {
2554     _tnSegmPtr ts;
2555     _tnSegmPtr tsn;
2556     /* close all subtrees */
2557     tree_root(tv->cr1);
2558     closeAllSubtrees(tv->cr1);
2559 
2560     tree_closeCursor(tv->cr1);
2561     tree_closeCursor(tv->cr2);
2562     tree_closeCursor(tv->cr3);
2563     tree_closeCursor(tv->cr4);
2564     tree_closeCursor(tv->cr5);
2565     tree_delSpy(tv->tree, tv->my_spy_id);
2566     if(tv->draw_port.tree_panel != NULL) {
2567         if(do_hide) Hide(tv->draw_port.tree_panel);
2568         Remove(tv->draw_port.tree_panel);
2569     }
2570     if(tv->draw_port.tree_window != NULL) {
2571         if(do_hide) Hide(tv->draw_port.tree_window);
2572         Remove(tv->draw_port.tree_window);
2573     }
2574 
2575     for(ts= tv->segm_buff; ts != NULL; ts= tsn) {
2576         tsn= ts[4095].next;
2577         MemFree(ts);
2578     }
2579     MemFree(tv);
2580 }
2581         
2582 Boolean tview_moveRoot(TreeViewPtr tv, TreeNodeId id)
2583 {
2584     _tnSegmPtr tns;
2585     BaR b;
2586 
2587     if(tree_toNode(tv->cr1, id)) {
2588         tns= getNodeViewerData((_tnSegmPtr)tv->cr1->node->sys_data, tv->my_spy_id);
2589         if(tns == NULL) {
2590             
2591             tns= allocNewSegm(tv->cr1);
2592             tns->w= calcNodeWidth(tv, getIconId(tv->cr1), getNodeLength(tv->cr1), getNodeLabel(tv->cr1));
2593             tns->h= tv->row_height;
2594         }
2595         tree_toNode(tv->cr5, id);
2596         if((tv->cr2->node_id.idi != id.idi) && (!tree_isDescendant(tv->cr5, tv->cr2))) {
2597             tree_toNode(tv->cr2, id);
2598         }
2599         openSubtree(tv->cr1, TRUE);
2600 
2601         tns= getNodeViewerData((_tnSegmPtr)tv->cr5->node->sys_data, tv->my_spy_id);
2602 
2603         setPort2Panel(&tv->draw_port);
2604         
2605         CorrectScrollbar(GetSlateHScrollBar((SlatE)(tv->draw_port.tree_panel)),
2606                          tv->row_width, tns->w + 16, tv->draw_port.clip_box.xl, tv->draw_port.clip_box.xr);
2607 
2608         CorrectScrollbar(GetSlateVScrollBar((SlatE)(tv->draw_port.tree_panel)),
2609                          tv->row_height, tns->h + 24, tv->draw_port.clip_box.yt, tv->draw_port.clip_box.yb);
2610 
2611         b= GetSlateVScrollBar((SlatE)(tv->draw_port.tree_panel));
2612         SetBarValue(b, 0);
2613         
2614         b= GetSlateHScrollBar((SlatE)(tv->draw_port.tree_panel));
2615         SetBarValue(b, 0);
2616 
2617         tv->sel_y= -1024;
2618         
2619         tview_redraw(tv);
2620         return TRUE;
2621     }
2622     return FALSE;
2623 }
2624 
2625 TreeNodeId tview_getSelected(TreeViewPtr tv)
2626 {
2627     return tv->cr2->node_id;
2628 }
2629 
2630 TreePtr tview_getTreePtr(TreeViewPtr tv)
2631 {
2632     return tv->tree;
2633 }
2634 
2635         
2636 
2637 
2638 

source navigation ]   [ diff markup ]   [ identifier search ]   [ freetext search ]   [ file search ]  

This page was automatically generated by the LXR engine.
Visit the LXR main site for more information.