1 /*   odlbox.c
2 * ===========================================================================
3 *
4 *                            PUBLIC DOMAIN NOTICE
5 *            National Center for Biotechnology Information (NCBI)
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 do not place any restriction on its use or reproduction.
13 *  We would, however, appreciate having the NCBI and the author cited in
14 *  any work or product based on this material
15 *
16 *  Although all reasonable efforts have been taken to ensure the accuracy
17 *  and reliability of the software and data, the NLM and the U.S.
18 *  Government do not and cannot warrant the performance or results that
19 *  may be obtained by using this software or data. The NLM and the U.S.
20 *  Government disclaim all warranties, express or implied, including
21 *  warranties of performance, merchantability or fitness for any particular
22 *  purpose.
23 *
24 * ===========================================================================
25 *
26 * File Name:  odlbox.c
27 *
28 * Author:  Patrick Durand
29 *
30 * Version Creation Date:   5/3/99
31 *
32 * $Revision: 6.4 $
33 *
34 * File Description:
35 *
36 * Modifications:
37 * --------------------------------------------------------------------------
38 * $Log: odlbox.c,v $
39 * Revision 6.4  2008/04/29 13:43:50  kans
40 * fixes for warnings caught by mingw cross-compiler
41 *
42 * Revision 6.3  1999/06/07 15:41:31  durand
43 * add LOG line to keep track of the history
44 *
45 *
46 *
47 * ==========================================================================
48 */
49 
50 #include <ncbi.h>
51 #include <vibrant.h>
52 
53 #include <odlbox.h>
54 
55 typedef  struct  rect4 {/*a new rect type for very big listbox*/
56 	Int4  left;
57 	Int4  top;
58 	Int4  right;
59 	Int4  bottom;
60 	} RecT4, PNTR Rect4Ptr;
61 
62 typedef struct lbvscroll {/*vertical Scroll Bar data*/
63 	Int4 ScrollMax;		/*Size of the vertical Scroll Bar*/
64 						/*also equal number of data lines displayed within
65 						the listbox*/
66 	Int4 ScrollPos;		/*Current position within the vertical Scroll Bar*/
67 	Int4 ScrollPage;	/*Page decal of the vertical Scroll Bar*/
68 	Int4 nTotLines;		/*total number of line*/
69 	Int2 cxClient;		/*size of the client lbox window*/
70 	Int2 cyClient;
71 	RecT rcP;
72 	} LBVScroll, PNTR LBVScrollPtr;
73 
74 typedef struct lbentrydata {/*data attached to each list box entry*/
75 	Pointer		pUserData;	/*a 'stuff' provided by the user*/
76 	RecT4		rc;			/*the position of the entry*/
77 	Boolean 	Selected;	/*TRUE: item is selected*/
78 	} LBEntryData, PNTR LBEntryDataPtr;
79 
80 typedef struct mainlbdata {	/*list box main data*/
81 	WindoW 				Parent;	/*parent of the list box*/
82 	Int4				nEntry;	/*number of entry in this list box*/
83 	Int4				CurEntry;/*current selected entry (zero-based)*/
84 	LBEntryDataPtr		CurEntryData;
85 	ValNodePtr			LBData;	/*private list box data ;
86 								LBData->data.ptrvalue is of LBEntryDataPtr type*/
87 	LBVScroll			vscroll;/*Vertical scrollbar data*/
88 	OwnerDrawLboxFunc	MsgFunc;/*Message Loop provided by the user*/
89 	FonT 				f;		/*user Font*/
90 	Int2				cxChar;
91 	Int2				cyChar;
92 		/*internal use only*/
93 	ValNodePtr			LBDataTmp;
94 	Int4				decal;
95 	} MainLBData, PNTR MainLBDataPtr;
96 
97 /*******************************************************************************
98 
99   Function : LBCleanupDataProc()
100 
101   Purpose : List Box personnal CleanupExtraProc Callback
102 
103   Parameters : g; handle of the dialog box
104   				data; to erase
105 
106   Return value : none
107 
108 *******************************************************************************/
LBCleanupDataProc(GraphiC g,VoidPtr data)109 static void LBCleanupDataProc (GraphiC g, VoidPtr data)
110 {
111 MainLBDataPtr 	lbdata;
112 ValNodePtr		vnp;
113 
114 	lbdata=(MainLBDataPtr)data;
115 	if (lbdata==NULL) return;
116 
117 	/*delete list of user data*/
118 	if (lbdata->nEntry>0){
119 		for(vnp=lbdata->LBData ; vnp!=NULL ; vnp=vnp->next){
120 			if (vnp->data.ptrvalue) MemFree(vnp->data.ptrvalue);
121 		}
122 		ValNodeFree(lbdata->LBData);
123 	}
124 
125 	MemFree (lbdata);
126 }
127 
128 /*******************************************************************************
129 
130   Function : LB_calc_RCdraw()
131 
132   Purpose : compute the RC of an entry to be drawn
133 
134   Parameters :	rc_entry; absolute position of an entry
135   				decal; y decal to place rc_entry within the listbox panel
136 
137   Return value : position of the entry within the listbox panel
138 
139 *******************************************************************************/
LB_calc_RCdraw(RecT4 rc_entry,Int4 decal)140 static RecT LB_calc_RCdraw(RecT4 rc_entry,Int4 decal)
141 {
142 RecT rc;
143 
144 	rc.top=(Int2)(rc_entry.top-decal);
145 	rc.bottom=(Int2)(rc_entry.bottom-decal);
146 	rc.left=(Int2)rc_entry.left;
147 	rc.right=(Int2)rc_entry.right;
148 
149 	return(rc);
150 }
151 
152 /*****************************************************************************
153 
154 Function: LB_ChangSel()
155 
156 Purpose: manage ChangSelection
157 
158 Parameters:	p; panel handle (currently unused)
159 			lbdata; list box data block
160 			CurEntry,CurEntryData; new item selected
161 
162 Return value: none
163 
164 *****************************************************************************/
LB_ChangSel(WindoW p,MainLBDataPtr lbdata,Int4 CurEntry,LBEntryDataPtr CurEntryData,Boolean SendSelectMessage)165 static void LB_ChangSel(WindoW p,MainLBDataPtr lbdata,Int4 CurEntry,
166 		LBEntryDataPtr CurEntryData,Boolean SendSelectMessage)
167 {
168 MIData	mid;
169 Int4	decal=lbdata->vscroll.ScrollPos*stdLineHeight;
170 WindoW	temport;
171 
172 	temport=SavePort(p);
173 	Select(p);
174 	mid.rcP=lbdata->vscroll.rcP;
175 	mid.f=lbdata->f;
176 	mid.cxChar=lbdata->cxChar;
177 	mid.cyChar=lbdata->cyChar;
178 	mid.Parent=lbdata->Parent;
179 	InsetRect(&mid.rcP,2,4);
180 	ClipRect(&mid.rcP);
181 	/*deselect previous entry, if needed*/
182 	if (lbdata->CurEntry!=(Int4)-1){
183 		/*mid.rcP=lbdata->vscroll.rcP;*/
184 		mid.Data=lbdata->CurEntryData->pUserData;
185 		mid.rcItem=LB_calc_RCdraw(lbdata->CurEntryData->rc,decal);
186 		mid.Selected=FALSE;
187 		lbdata->CurEntryData->Selected=FALSE;
188 		/*send message to draw an entry*/
189 		(*lbdata->MsgFunc)((WindoW)p,ODLB_DrawItem,(Pointer)&mid);
190 	}
191 	/*select the new entry*/
192 	lbdata->CurEntry=CurEntry;
193 	lbdata->CurEntryData=CurEntryData;
194 	/*mid.rcP=lbdata->vscroll.rcP;*/
195 	mid.Data=CurEntryData->pUserData;
196 	mid.rcItem=LB_calc_RCdraw(CurEntryData->rc,decal);
197 	mid.Selected=TRUE;
198 	CurEntryData->Selected=TRUE;
199 	/*send message to draw an entry; then send a SelectItem msg*/
200 	(*lbdata->MsgFunc)((WindoW)p,ODLB_DrawItem,(Pointer)&mid);
201 	if (SendSelectMessage){
202 		(*lbdata->MsgFunc)((WindoW)p,ODLB_SelectItem,(Pointer)&mid);
203 	}
204 	ResetClip();
205 	RestorePort(temport);
206 }
207 
208 /*****************************************************************************
209 
210 Function: LB_OnClick()
211 
212 Purpose: manage Mouse-Click
213 
214 Parameters:	p; list-box handle
215 			pt; new mouse position
216 
217 Return value: none
218 
219 *****************************************************************************/
LB_OnClick(PaneL p,PoinT pt)220 static void LB_OnClick(PaneL p, PoinT pt)
221 {
222 Int4 			limit,decal=0,i=1;
223 ValNodePtr 		vnp;
224 LBEntryDataPtr 	lbdp;
225 RecT 			rc;
226 MainLBDataPtr	lbdata;
227 Boolean 		bFind=FALSE;
228 
229 	/*get some usefull data...*/
230 	lbdata = (MainLBDataPtr) GetObjectExtra (p);
231 	if (lbdata==NULL) return;
232 
233 	decal=lbdata->vscroll.ScrollPos*stdLineHeight;
234 	limit=(Int4)lbdata->vscroll.rcP.top+decal;
235 	/*find the first entry located at the top of the listbox*/
236 	for(vnp=lbdata->LBData ; vnp != NULL ; vnp=vnp->next){
237 		if (vnp->data.ptrvalue){
238 			lbdp=(LBEntryDataPtr)vnp->data.ptrvalue;
239 			if (lbdp->rc.bottom>limit){
240 				rc=LB_calc_RCdraw(lbdp->rc,decal);
241 				if (PtInRect(pt,&rc)){
242 					bFind=TRUE;
243 					break;
244 				}
245 			}
246 			i++;
247 		}
248 	}
249 
250 	/*if item found in the listbox*/
251 	if (bFind){
252 		LB_ChangSel((WindoW)p, lbdata,i,lbdp,TRUE);
253 	}
254 }
255 
256 /*****************************************************************************
257 
258 Function: UDV_ReleaseProc()
259 
260 Purpose: manage Mouse-Release
261 
262 Parameters:	p; panel handle (currently unused)
263 			pt; new position
264 
265 Return value: none
266 
267 *****************************************************************************/
LB_OnRelease(PaneL p,PoinT pt)268 static void LB_OnRelease(PaneL p, PoinT pt)
269 {
270 }
271 
272 /*******************************************************************************
273 
274   Function : LB_DrawEmpty()
275 
276   Purpose : draw a emplty window
277 
278   Parameters :	rectangle to fill
279 
280   Return value : none
281 
282 *******************************************************************************/
LB_DrawEmpty(RecT rc)283 static void  LB_DrawEmpty(RecT rc)
284 {
285 	White();
286 	PaintRect(&rc);
287 	Black();
288 }
289 
290 /*******************************************************************************
291 
292   Function : LB_calc_decalRC()
293 
294   Purpose : compute the y decal for LB entry RecT correct positionning on
295   		the listbox panel
296 
297   Parameters :	lbdata; list of entries
298   				ScrollPos; actual position of the Vscroll bar
299 				vnp; first entry to draw in the panel
300 				rcP; rc de la listbox
301 
302   Return value : y decal value (pixel unit)
303 
304 *******************************************************************************/
LB_calc_decalRC(ValNodePtr lbdata,Int4 ScrollPos,ValNodePtr PNTR vnp,RecT rcP)305 static Int4  LB_calc_decalRC(ValNodePtr lbdata,Int4 ScrollPos,
306 		ValNodePtr PNTR vnp,RecT rcP)
307 {
308 Int4 			decal,limit;
309 LBEntryDataPtr 	lbdp;
310 
311 	decal=ScrollPos*stdLineHeight;
312 	limit=(Int4)rcP.top+decal;
313 	/*find the first entry located at the top of the listbox*/
314 	for(*vnp=lbdata ; *vnp != NULL ; *vnp=(*vnp)->next){
315 		if ((*vnp)->data.ptrvalue){
316 			lbdp=(LBEntryDataPtr)(*vnp)->data.ptrvalue;
317 			if (lbdp->rc.bottom>limit){
318 					break;
319 			}
320 		}
321 	}
322 
323 	return(decal);
324 }
325 
326 
327 /*******************************************************************************
328 
329   Function : LB_onDraw()
330 
331   Purpose :  draw the panel of the listbox ; if fact, call the User OnDraw
332   		function
333 
334   Parameters :	handle of the panel
335 
336   Return value : none
337 
338 *******************************************************************************/
LB_onDraw(PaneL p)339 static void LB_onDraw(PaneL p)
340 {
341 Int4 			decal=0;
342 ValNodePtr 		vnp,vnp2;
343 LBEntryDataPtr 	lbdp;
344 RecT 			rc,rcP;
345 MainLBDataPtr	lbdata;
346 MIData			mid;
347 WindoW temport;
348 
349 	/*get some usefull data...*/
350 	lbdata = (MainLBDataPtr) GetObjectExtra (p);
351 	if (lbdata==NULL) return;
352 
353 	temport=SavePort(ParentWindow(p));
354 
355 	Select (p);
356 
357 	/*restrict panel drawing area: 'add' little margins*/
358 	ObjectRect(p,&rcP);
359 	InsetRect(&rcP,2,4);
360 	ClipRect(&rcP);
361 
362 
363 	if (lbdata->LBData==NULL) {
364 		LB_DrawEmpty(rcP);
365 		ResetClip();
366 		return;
367 	}
368 
369 
370 	decal=LB_calc_decalRC(lbdata->LBData,lbdata->vscroll.ScrollPos,&vnp,rcP);
371 
372 	if (vnp==NULL){
373 		LB_DrawEmpty(rcP);
374 		ResetClip();
375 		return;
376 	}
377 
378 	mid.rcP=lbdata->vscroll.rcP;
379 	mid.f=lbdata->f;
380 	mid.cxChar=lbdata->cxChar;
381 	mid.cyChar=lbdata->cyChar;
382 	mid.Parent=lbdata->Parent;
383 
384 	for(vnp2=vnp ; vnp2 != NULL ; vnp2=vnp2->next){
385 		if (vnp2->data.ptrvalue){
386 			lbdp=(LBEntryDataPtr)vnp2->data.ptrvalue;
387 
388 			rc=LB_calc_RCdraw(lbdp->rc,decal);
389 
390 			/*send message to draw an entry*/
391 			mid.rcItem=rc;
392 			mid.Data=lbdp->pUserData;
393 			mid.Selected=lbdp->Selected;
394 			(*lbdata->MsgFunc)((WindoW)p,ODLB_DrawItem,(Pointer)&mid);
395 			/*end ?*/
396 			if (rc.bottom >= rcP.bottom) break;
397 		}
398 	}
399 
400 	ResetClip();
401 	RestorePort(temport);
402 }
403 
404 /*******************************************************************************
405 
406   Function : LB_onVScroll()
407 
408   Purpose : Owner Draw list box Vertical Scroll Bar Callback
409 
410   Parameters : sb; handle of the scroll
411   				s; pane;
412 				newval; new value of the thumb
413 				oldval; old value of the thumb
414 
415   Return value : none
416 
417 *******************************************************************************/
LB_onVScroll(BaR sb,SlatE s,Int4 newval,Int4 oldval)418 static void LB_onVScroll (BaR sb, SlatE s, Int4 newval,
419 			Int4 oldval)
420 {
421 RecT 				rcP;
422 WindoW 				temport;
423 Int4 				n;
424 Boolean 			IsGoUp=FALSE;
425 MainLBDataPtr		lbdata;
426 
427 	/*get some usefull data...*/
428 	lbdata = (MainLBDataPtr) GetObjectExtra (s);
429 	if (lbdata==NULL) return;
430 
431 	lbdata->vscroll.ScrollPos=newval;
432 
433 	temport=SavePort((WindoW)s);
434 	Select(s);
435 	ObjectRect((PaneL)s,&rcP);
436 	InsetRect(&rcP,2,4);
437 	ClipRect(&rcP);
438 
439 	if (oldval>newval){
440 		n=oldval-newval;
441 		IsGoUp=TRUE;
442 	}
443 	else {
444 		n=newval-oldval;
445 		IsGoUp=FALSE;
446 	}
447 
448 	if (n<lbdata->vscroll.ScrollPage){/*Line UP/Down*/
449 		/*move and redraw*/
450 		ScrollRect (&rcP, 0, (Int2)((oldval-newval)*stdLineHeight));
451 	}
452 	else{/*Page Up/Down*/
453 		/*redraw*/
454 		/*rcP.left=0;
455 		rcP.top=0;*/
456 		InvalRect(&rcP);
457 	}
458 	ResetClip();
459 	RestorePort(temport);
460 	/*Update ();*/
461 }
462 
463 /*******************************************************************************
464 
465   Function : OwnerDrawLbox_VScrlUpdatePage()
466 
467   Purpose : compute PageUp & Down (VScroll)
468 
469   Parameters : PageUpDn; initialize here
470   				cyClient; height of UnDviewer panel
471 
472   Return value : none
473 
474 *******************************************************************************/
OwnerDrawLbox_VScrlUpdatePage(Int4Ptr PageUpDn,Int2 cyClient)475 static void  OwnerDrawLbox_VScrlUpdatePage(Int4Ptr PageUpDn,
476 				Int2 cyClient)
477 {
478 	*PageUpDn=(Int4)(cyClient/stdLineHeight);
479 }
480 
481 /*******************************************************************************
482 
483   Function : OwnerDrawLbox_VScrlUpdate()
484 
485   Purpose : update the UnDviewer VScroll bar
486 
487   Parameters : p; handel of the UnDviewer panel
488   				bInit; TRUE only when the UnDviewer is created (soft. start up)
489   				CurPos ; new position
490 
491   Return value : none
492 
493 *******************************************************************************/
OwnerDrawLbox_VScrlUpdate(PaneL p,Boolean bInit,Int4 CurPos)494 static void  OwnerDrawLbox_VScrlUpdate(PaneL p,
495 		Boolean bInit,Int4 CurPos)
496 {
497 MainLBDataPtr	lbdata;
498 BaR 			vsb;
499 
500 	if (p==NULL) return;
501 
502 	/*get some usefull data...*/
503 	lbdata = (MainLBDataPtr) GetObjectExtra (p);
504 	if (lbdata==NULL) return;
505 
506 	/*current scroll status*/
507 	vsb = GetSlateVScrollBar ((SlatE) p);
508 
509 	if (bInit) CurPos=0;
510 
511 	/*given curpos (lineNumber) retrieve letter number*/
512 	/*compute new values*/
513 	OwnerDrawLbox_VScrlUpdatePage(&(lbdata->vscroll.ScrollPage),
514 				lbdata->vscroll.cyClient);
515 
516 	if (lbdata->vscroll.nTotLines>lbdata->vscroll.ScrollPage){
517 		lbdata->vscroll.ScrollMax=lbdata->vscroll.nTotLines-
518 							lbdata->vscroll.ScrollPage;
519 	}
520 	else{
521 		lbdata->vscroll.ScrollMax=0;
522 		lbdata->vscroll.ScrollPos=0;
523 		lbdata->vscroll.ScrollPage=0;
524 	}
525 
526 	if (CurPos<0) CurPos=0;
527 
528 	if (CurPos>=lbdata->vscroll.ScrollMax)
529 		lbdata->vscroll.ScrollPos=lbdata->vscroll.ScrollMax;
530 	else lbdata->vscroll.ScrollPos=CurPos;
531 
532 	/*update scroll*/
533 	CorrectBarMax(vsb,lbdata->vscroll.ScrollMax);
534 	CorrectBarValue(vsb,lbdata->vscroll.ScrollPos);
535 	CorrectBarPage(vsb,lbdata->vscroll.ScrollPage,
536 			lbdata->vscroll.ScrollPage);
537 }
538 
539 
540 /*******************************************************************************
541 
542   Function : OwnerDrawLbox_ResetLBContent()
543 
544   Purpose : delete actual data of the list box
545 
546   Parameters : 	lbox; handle of the list box
547 
548   Return value : none
549 
550 *******************************************************************************/
OwnerDrawLbox_ResetLBContent(WindoW lbox)551 NLM_EXTERN void  OwnerDrawLbox_ResetLBContent(WindoW lbox)
552 {
553 MainLBDataPtr 	lbdata;
554 ValNodePtr		vnp;
555 WindoW			temport;
556 BaR				vsb;
557 
558 	lbdata=(MainLBDataPtr)GetObjectExtra (lbox);
559 	if (lbdata==NULL) return;
560 
561 	/*delete list of user data*/
562 	if (lbdata->nEntry>0){
563 		for(vnp=lbdata->LBData ; vnp!=NULL ; vnp=vnp->next){
564 			if (vnp->data.ptrvalue) MemFree(vnp->data.ptrvalue);
565 		}
566 		ValNodeFree(lbdata->LBData);
567 		lbdata->LBData=NULL;
568 	}
569 	/*init lbox internal data*/
570 	lbdata->nEntry=0;
571 	lbdata->CurEntry=-1;
572 	lbdata->CurEntryData=NULL;
573 	lbdata->vscroll.ScrollMax=0;
574 	lbdata->vscroll.ScrollPos=0;
575 	lbdata->vscroll.ScrollPage=0;
576 	lbdata->vscroll.nTotLines=0;
577 	lbdata->LBDataTmp=NULL;
578 	lbdata->decal=0;
579 
580 	/*reinit scrollbar and redraw an empty listbox*/
581 	vsb = GetSlateVScrollBar ((SlatE)lbox);
582 	CorrectBarMax(vsb,0);
583 	CorrectBarValue(vsb,0);
584 	CorrectBarPage(vsb,0,0);
585 	temport=SavePort(lbox);
586 	Select(lbox);
587 	InvalRect(&lbdata->vscroll.rcP);
588 	RestorePort(temport);
589 }
590 
591 /*******************************************************************************
592 
593   Function : OwnerDrawLbox_GetCurData()
594 
595   Purpose : retrieve the current data of the selected item in an owner
596   			draw listbox
597 
598   Parameters : 	lbox; handle of the list box
599 
600   Return value : current item data
601 
602 *******************************************************************************/
OwnerDrawLbox_GetCurData(WindoW lbox)603 NLM_EXTERN Pointer  OwnerDrawLbox_GetCurData(WindoW lbox)
604 {
605 MainLBDataPtr	lbdata;
606 
607 	/*retrieve lbox data*/
608 	lbdata = (MainLBDataPtr) GetObjectExtra (lbox);
609 	if (lbdata == NULL) return(NULL);/*oups*/
610 
611 	return(lbdata->CurEntryData->pUserData);
612 }
613 
614 /*******************************************************************************
615 
616   Function : OwnerDrawLbox_GetData()
617 
618   Purpose : retrieve the current data of the selected item in an owner
619   			draw listbox
620 
621   Parameters : 	lbox; handle of the list box
622   				item; data to retrieve (one based value)
623 
624   Return value : current item data
625 
626 *******************************************************************************/
OwnerDrawLbox_GetData(WindoW lbox,Int4 item)627 NLM_EXTERN Pointer  OwnerDrawLbox_GetData(WindoW lbox,Int4 item)
628 {
629 MainLBDataPtr	lbdata;
630 ValNodePtr		vnp;
631 Int4			i=1;
632 Boolean bFound=FALSE;
633 
634 	/*retrieve lbox data*/
635 	lbdata = (MainLBDataPtr) GetObjectExtra (lbox);
636 	if (lbdata == NULL) return(NULL);/*oups*/
637 
638 	/*scan list of user data*/
639 	if (lbdata->nEntry>0){
640 		for(vnp=lbdata->LBData ; vnp!=NULL ; vnp=vnp->next){
641 			if (i==item) {
642 				bFound=TRUE;
643 				break;
644 			}
645 			i++;
646 		}
647 	}
648 
649 	if (!bFound) return(NULL);
650 
651 	return((Pointer)vnp->data.ptrvalue);
652 }
653 
654 /*******************************************************************************
655 
656   Function : OwnerDrawLbox_GetNentry()
657 
658   Purpose : retrieve the number of entries of aa owner draw listbox
659 
660   Parameters : 	lbox; handle of the list box
661 
662   Return value : current item data
663 
664 *******************************************************************************/
OwnerDrawLbox_GetNentry(WindoW lbox)665 NLM_EXTERN Int4  OwnerDrawLbox_GetNentry(WindoW lbox)
666 {
667 MainLBDataPtr	lbdata;
668 
669 	/*retrieve lbox data*/
670 	lbdata = (MainLBDataPtr) GetObjectExtra (lbox);
671 	if (lbdata == NULL) return(0);/*oups*/
672 
673 	return(lbdata->nEntry);
674 }
675 
676 /*******************************************************************************
677 
678   Function : OwnerDrawLbox_GetCurSel()
679 
680   Purpose : retrieve the current selected item in an owner draw listbox
681 
682   Parameters : 	lbox; handle of the list box
683 
684   Return value : current item selected in the list box (Zero-based value)
685 
686 *******************************************************************************/
OwnerDrawLbox_GetCurSel(WindoW lbox)687 NLM_EXTERN Int4  OwnerDrawLbox_GetCurSel(WindoW lbox)
688 {
689 MainLBDataPtr	lbdata;
690 
691 	/*retrieve lbox data*/
692 	lbdata = (MainLBDataPtr) GetObjectExtra (lbox);
693 	if (lbdata == NULL) return((Int4)-1);/*oups*/
694 
695 	return(lbdata->CurEntry);
696 }
697 
698 /*******************************************************************************
699 
700   Function : OwnerDrawLbox_SelectItem()
701 
702   Purpose : select an item in an owner draw listbox
703 
704   Parameters : 	lbox; handle of the list box
705   				item; item to select (One-based value)
706 
707   Return value : none
708 
709 *******************************************************************************/
OwnerDrawLbox_SelectItem(WindoW lbox,Int4 item)710 NLM_EXTERN void  OwnerDrawLbox_SelectItem(WindoW lbox,Int4 item)
711 {
712 MainLBDataPtr	lbdata;
713 ValNodePtr		vnp;
714 Int4			i=1,decal,NewPos;
715 Boolean			bFound=FALSE;
716 LBEntryDataPtr  lbdp;
717 RecT			rc;
718 
719 	/*retrieve lbox data*/
720 	lbdata = (MainLBDataPtr) GetObjectExtra (lbox);
721 	if (lbdata == NULL) return;/*oups*/
722 
723 	/*scan list of user data*/
724 	if (lbdata->nEntry>0){
725 		for(vnp=lbdata->LBData ; vnp!=NULL ; vnp=vnp->next){
726 			if (i==item) {
727 				bFound=TRUE;
728 				break;
729 			}
730 			i++;
731 		}
732 	}
733 
734 	if (!bFound) return;
735 	lbdp=(LBEntryDataPtr)vnp->data.ptrvalue;
736 	/*scroll*/
737 	decal=lbdata->vscroll.ScrollPos*stdLineHeight;
738 	rc=LB_calc_RCdraw(lbdp->rc,decal);
739 	if (!RectInRect(&rc,&lbdata->vscroll.rcP)){
740 		WindoW temport;
741 		NewPos=(lbdp->rc.top-lbdata->vscroll.rcP.top)/stdLineHeight;
742 		OwnerDrawLbox_VScrlUpdate((PaneL)lbox,FALSE,NewPos);
743 		temport=SavePort(lbox);
744 		Select(lbox);
745 		InvalRect(&lbdata->vscroll.rcP);
746 		RestorePort(temport);
747 	}
748 	LB_ChangSel(lbox,lbdata,item,lbdp,FALSE);
749 }
750 
751 /*******************************************************************************
752 
753   Function : OwnerDrawLbox_AddItem()
754 
755   Purpose : add a user item to an owner draw listbox
756 
757   Parameters : 	lbox; handle of the list box
758   				item; data to add to the list
759 
760   Return value : TRUE if success, FALSE if any errors
761 
762 *******************************************************************************/
OwnerDrawLbox_AddItem(WindoW lbox,Pointer item)763 NLM_EXTERN Boolean  OwnerDrawLbox_AddItem(WindoW lbox,Pointer item)
764 {
765 MainLBDataPtr	lbdata;
766 LBEntryDataPtr	lbdp;
767 MIData			mid;
768 
769 	/*retrieve lbox data*/
770 	lbdata = (MainLBDataPtr) GetObjectExtra (lbox);
771 	if (lbdata == NULL) return(FALSE);/*oups*/
772 
773 	/*ask the user for the item size*/
774 	MemSet(&mid.rcItem,0,sizeof(RecT));
775 	mid.Data=item;
776 	mid.rcP=lbdata->vscroll.rcP;
777 	mid.Selected=FALSE;
778 	mid.f=lbdata->f;
779 	mid.cxChar=lbdata->cxChar;
780 	mid.cyChar=lbdata->cyChar;
781 	mid.Parent=lbdata->Parent;
782 	if (!(*lbdata->MsgFunc)(lbox,ODLB_MeasureItem,(Pointer)&mid)) {
783 		/*if message isn't managed by the user, compute a default size*/
784 		mid.rcItem.left=lbdata->vscroll.rcP.left;
785 		mid.rcItem.top=0;
786 		mid.rcItem.right=lbdata->vscroll.rcP.right;
787 		mid.rcItem.bottom=stdLineHeight;
788 	}
789 
790 	/*create new data block for the user data*/
791 	lbdp=(LBEntryDataPtr)MemNew(sizeof(LBEntryData));
792 	if (lbdp==NULL) return(FALSE);/*oups II, the return*/
793 	MemSet(lbdp,0,sizeof(LBEntryData));
794 	lbdp->pUserData=item;
795 
796 	/*add the item to the ValNodeList*/
797 	if (lbdata->nEntry==0){
798 		lbdata->LBData=ValNodeAddPointer(NULL,0,(VoidPtr)lbdp);
799 		if (lbdata->LBData==NULL) {
800 			MemFree(lbdp);
801 			return(FALSE);/*oups III, the ultimate adventure*/
802 		}
803 		lbdata->LBDataTmp=lbdata->LBData;
804 		/*position of the new element*/
805 		lbdp->rc.left=(Int4)mid.rcItem.left;
806 		lbdp->rc.right=(Int4)mid.rcItem.right;
807 		lbdp->rc.top=(Int4)(mid.rcItem.top+lbdata->vscroll.rcP.top);
808 		lbdp->rc.bottom=(Int4)(lbdp->rc.top+mid.rcItem.bottom);
809 	}
810 	else{
811 		lbdata->LBDataTmp=ValNodeAddPointer(&lbdata->LBDataTmp,0,(VoidPtr)lbdp);
812 		if (!lbdata->LBDataTmp){
813 			MemFree(lbdp);
814 			return(FALSE); /*oups IV, the resurrection*/
815 		}
816 		/*compute correct pos for the new item*/
817 		lbdp->rc.left=(Int4)mid.rcItem.left;
818 		lbdp->rc.right=(Int4)mid.rcItem.right;
819 		lbdp->rc.top=(Int4)(mid.rcItem.top+lbdata->decal);
820 		lbdp->rc.bottom=(Int4)(lbdp->rc.top+mid.rcItem.bottom);
821 	}
822 	/*decal in the list box*/
823 	lbdata->decal=lbdp->rc.bottom+1;
824 
825 	/*ok*/
826 	lbdata->nEntry++;
827 
828 	/*update the scroll, but do not move it; stay on pos 0*/
829 	lbdata->vscroll.nTotLines=lbdata->decal/stdLineHeight+1;
830 	OwnerDrawLbox_VScrlUpdate((PaneL)lbox,TRUE,0);
831 
832 	/*ask the user to draw, only if needed*/
833 /*	if (lbdp->rc.bottom<=(Int4)lbdata->vscroll.rcP.bottom){
834 		mid.rcItem.top=(Int2)lbdp->rc.top;
835 		mid.rcItem.bottom=(Int2)lbdp->rc.bottom;
836 		mid.Data=item;
837 		mid.rcP=lbdata->vscroll.rcP;
838 		mid.f=lbdata->f;
839 		mid.cxChar=lbdata->cxChar;
840 		mid.cyChar=lbdata->cyChar;
841 		(*lbdata->MsgFunc)(lbox,ODLB_DrawItem,(Pointer)&mid);
842 	}*/
843 
844 	return(TRUE);
845 }
846 
847 /*******************************************************************************
848 
849   Function : OwnerDrawLbox_MoveWindow()
850 
851   Purpose : move/resize an owner draw listbox
852 
853   Parameters : 	lbox ; do you think it's what ?
854   				x ; pos on x
855 				y ; pos on y
856 				cx ; width of the ListBox
857 				cy ; height of the ListBox
858 
859   Return value : -
860 
861 *******************************************************************************/
OwnerDrawLbox_MoveWindow(WindoW lbox,Int2 x,Int2 y,Int2 cx,Int2 cy)862 NLM_EXTERN void  OwnerDrawLbox_MoveWindow(WindoW lbox,
863 	Int2 x,Int2 y, Int2 cx,Int2 cy)
864 {
865 MainLBDataPtr	lbdata;
866 LBEntryDataPtr	lbdp;
867 MIData			mid;
868 ValNodePtr		vnp;
869 RecT			rcP;
870 
871 Int4			oldDecal,oldCurPos = 0;
872 Boolean			bFirst=TRUE,bFirst2=FALSE;
873 
874 	/*retrieve lbox data*/
875 	lbdata = (MainLBDataPtr) GetObjectExtra (lbox);
876 	if (lbdata == NULL) return;
877 
878 	/*compute new listbox size*/
879 	Select(lbox);
880 	rcP.left=x;
881 	rcP.top=y;
882 	rcP.right=x+cx;
883 	rcP.bottom=y+cy;
884 	lbdata->vscroll.rcP=rcP;
885 	lbdata->vscroll.rcP.right-=3*lbdata->cxChar;
886 	lbdata->vscroll.rcP.top+=1;
887 	lbdata->vscroll.cxClient=cx;
888 	lbdata->vscroll.cyClient=cy;
889 	mid.rcP=lbdata->vscroll.rcP;
890 	mid.f=lbdata->f;
891 	mid.cxChar=lbdata->cxChar;
892 	mid.cyChar=lbdata->cyChar;
893 	mid.Parent=lbdata->Parent;
894 	oldDecal=lbdata->vscroll.ScrollPos*stdLineHeight;
895 	lbdata->decal=lbdata->vscroll.rcP.top;
896 	/*resize all the items*/
897 	for(vnp=lbdata->LBData ; vnp!=NULL ; vnp=vnp->next){
898 		lbdp=(LBEntryDataPtr)vnp->data.ptrvalue;
899 		if (lbdp){
900 			if (bFirst){/*retrieve the first displayed item of the list*/
901 				if ((lbdp->rc.top-lbdata->vscroll.rcP.top)>=oldDecal){
902 					bFirst2=TRUE;
903 					bFirst=FALSE;
904 				}
905 			}
906 			mid.Data=lbdp->pUserData;
907 			if (!(*lbdata->MsgFunc)(lbox,ODLB_MeasureItem,(Pointer)&mid)) {
908 				/*if message isn't managed by the user, compute a default size*/
909 				mid.rcItem.left=lbdata->vscroll.rcP.left;
910 				mid.rcItem.top=0;
911 				mid.rcItem.right=lbdata->vscroll.rcP.right;
912 				mid.rcItem.bottom=stdLineHeight;
913 			}
914 			/*compute correct pos for the new item*/
915 			lbdp->rc.left=(Int4)mid.rcItem.left;
916 			lbdp->rc.right=(Int4)mid.rcItem.right;
917 			lbdp->rc.top=(Int4)(mid.rcItem.top+lbdata->decal);
918 			lbdp->rc.bottom=(Int4)(lbdp->rc.top+mid.rcItem.bottom);
919 			if (bFirst2){/*compute oldCurPos*/
920 				oldCurPos=(lbdp->rc.top-lbdata->vscroll.rcP.top)/stdLineHeight;
921 				bFirst2=FALSE;
922 			}
923 			/*decal in the list box*/
924 			lbdata->decal=lbdp->rc.bottom+1;
925 		}
926 	}
927 
928 	/*update the scroll*/
929 	lbdata->vscroll.nTotLines=lbdata->decal/stdLineHeight+1;
930 	OwnerDrawLbox_VScrlUpdate((PaneL)lbox,FALSE,oldCurPos);
931 
932 	/*move/resize and redraw window*/
933 	SetPosition(lbox, &rcP);
934 	AdjustPrnt(lbox, &rcP, FALSE);
935 }
936 
937 /*******************************************************************************
938 
939   Function : OwnerDrawLbox_Create()
940 
941   Purpose : Create an owner draw listbox
942 
943   Parameters : 	Parent ; handle of the parent window for the listbox
944   				x ; pos on x
945 				y ; pos on y
946 				cx ; width of the ListBox
947 				cy ; height of the ListBox
948 				MsgFunc ; Message loop of the ListBox
949 
950   Return value : WindoW if success, NULL if any errors
951 
952 *******************************************************************************/
OwnerDrawLbox_Create(WindoW Parent,Int2 x,Int2 y,Int2 cx,Int2 cy,OwnerDrawLboxFunc MsgFunc,FonT f,Int2 cxChar,Int2 cyChar)953 NLM_EXTERN WindoW  OwnerDrawLbox_Create(WindoW Parent,
954 	Int2 x,Int2 y, Int2 cx,Int2 cy, OwnerDrawLboxFunc MsgFunc,FonT f,
955 	Int2 cxChar,Int2 cyChar)
956 {
957 MainLBDataPtr	lbdata;
958 PaneL			p;
959 RecT			rcP;
960 
961 	/*create the listbox as an AutonomousPanel4*/
962 	p=AutonomousPanel4(Parent,10,10,LB_onDraw,
963 			LB_onVScroll,NULL,0,NULL,NULL);
964 	/*create mouse action for the listbox*/
965 	SetPanelClick(p,LB_OnClick,NULL,NULL,LB_OnRelease);
966 
967 	if (p==NULL) return(NULL);/*isn't it !*/
968 
969 	/*use x,y,cx,cy provided by the user*/
970 	Select(p);
971 	rcP.left=x;
972 	rcP.top=y;
973 	rcP.right=x+cx;
974 	rcP.bottom=y+cy;
975 	SetPosition(p, &rcP);
976 	AdjustPrnt(p, &rcP, FALSE);
977 
978 	/*Allocate the data structure and attach it to the list box*/
979 	lbdata=(MainLBDataPtr)MemNew(sizeof(MainLBData));
980 	if (lbdata==NULL) {
981 		Remove(p);
982 		return(NULL);
983 	}
984 	MemSet(lbdata,0,sizeof(MainLBData));
985 	lbdata->CurEntry=-1;
986 	lbdata->Parent=Parent;
987 	lbdata->MsgFunc=(OwnerDrawLboxFunc)MsgFunc;
988 	lbdata->vscroll.cxClient=cx;
989 	lbdata->vscroll.cyClient=cy;
990 	rcP.top+=1;
991 	rcP.right-=3*cxChar;
992 	lbdata->vscroll.rcP=rcP;
993 	lbdata->f=f;
994 	lbdata->cxChar=cxChar;
995 	lbdata->cyChar=cyChar;
996 	SetObjectExtra (p, (Pointer) lbdata, LBCleanupDataProc);
997 
998 	/*yes !*/
999 	return((WindoW)p);
1000 }
1001 
1002