/* odlbox.c * =========================================================================== * * PUBLIC DOMAIN NOTICE * National Center for Biotechnology Information (NCBI) * * This software/database is a "United States Government Work" under the * terms of the United States Copyright Act. It was written as part of * the author's official duties as a United States Government employee and * thus cannot be copyrighted. This software/database is freely available * to the public for use. The National Library of Medicine and the U.S. * Government do not place any restriction on its use or reproduction. * We would, however, appreciate having the NCBI and the author cited in * any work or product based on this material * * Although all reasonable efforts have been taken to ensure the accuracy * and reliability of the software and data, the NLM and the U.S. * Government do not and cannot warrant the performance or results that * may be obtained by using this software or data. The NLM and the U.S. * Government disclaim all warranties, express or implied, including * warranties of performance, merchantability or fitness for any particular * purpose. * * =========================================================================== * * File Name: odlbox.c * * Author: Patrick Durand * * Version Creation Date: 5/3/99 * * $Revision: 6.4 $ * * File Description: * * Modifications: * -------------------------------------------------------------------------- * $Log: odlbox.c,v $ * Revision 6.4 2008/04/29 13:43:50 kans * fixes for warnings caught by mingw cross-compiler * * Revision 6.3 1999/06/07 15:41:31 durand * add LOG line to keep track of the history * * * * ========================================================================== */ #include #include #include typedef struct rect4 {/*a new rect type for very big listbox*/ Int4 left; Int4 top; Int4 right; Int4 bottom; } RecT4, PNTR Rect4Ptr; typedef struct lbvscroll {/*vertical Scroll Bar data*/ Int4 ScrollMax; /*Size of the vertical Scroll Bar*/ /*also equal number of data lines displayed within the listbox*/ Int4 ScrollPos; /*Current position within the vertical Scroll Bar*/ Int4 ScrollPage; /*Page decal of the vertical Scroll Bar*/ Int4 nTotLines; /*total number of line*/ Int2 cxClient; /*size of the client lbox window*/ Int2 cyClient; RecT rcP; } LBVScroll, PNTR LBVScrollPtr; typedef struct lbentrydata {/*data attached to each list box entry*/ Pointer pUserData; /*a 'stuff' provided by the user*/ RecT4 rc; /*the position of the entry*/ Boolean Selected; /*TRUE: item is selected*/ } LBEntryData, PNTR LBEntryDataPtr; typedef struct mainlbdata { /*list box main data*/ WindoW Parent; /*parent of the list box*/ Int4 nEntry; /*number of entry in this list box*/ Int4 CurEntry;/*current selected entry (zero-based)*/ LBEntryDataPtr CurEntryData; ValNodePtr LBData; /*private list box data ; LBData->data.ptrvalue is of LBEntryDataPtr type*/ LBVScroll vscroll;/*Vertical scrollbar data*/ OwnerDrawLboxFunc MsgFunc;/*Message Loop provided by the user*/ FonT f; /*user Font*/ Int2 cxChar; Int2 cyChar; /*internal use only*/ ValNodePtr LBDataTmp; Int4 decal; } MainLBData, PNTR MainLBDataPtr; /******************************************************************************* Function : LBCleanupDataProc() Purpose : List Box personnal CleanupExtraProc Callback Parameters : g; handle of the dialog box data; to erase Return value : none *******************************************************************************/ static void LBCleanupDataProc (GraphiC g, VoidPtr data) { MainLBDataPtr lbdata; ValNodePtr vnp; lbdata=(MainLBDataPtr)data; if (lbdata==NULL) return; /*delete list of user data*/ if (lbdata->nEntry>0){ for(vnp=lbdata->LBData ; vnp!=NULL ; vnp=vnp->next){ if (vnp->data.ptrvalue) MemFree(vnp->data.ptrvalue); } ValNodeFree(lbdata->LBData); } MemFree (lbdata); } /******************************************************************************* Function : LB_calc_RCdraw() Purpose : compute the RC of an entry to be drawn Parameters : rc_entry; absolute position of an entry decal; y decal to place rc_entry within the listbox panel Return value : position of the entry within the listbox panel *******************************************************************************/ static RecT LB_calc_RCdraw(RecT4 rc_entry,Int4 decal) { RecT rc; rc.top=(Int2)(rc_entry.top-decal); rc.bottom=(Int2)(rc_entry.bottom-decal); rc.left=(Int2)rc_entry.left; rc.right=(Int2)rc_entry.right; return(rc); } /***************************************************************************** Function: LB_ChangSel() Purpose: manage ChangSelection Parameters: p; panel handle (currently unused) lbdata; list box data block CurEntry,CurEntryData; new item selected Return value: none *****************************************************************************/ static void LB_ChangSel(WindoW p,MainLBDataPtr lbdata,Int4 CurEntry, LBEntryDataPtr CurEntryData,Boolean SendSelectMessage) { MIData mid; Int4 decal=lbdata->vscroll.ScrollPos*stdLineHeight; WindoW temport; temport=SavePort(p); Select(p); mid.rcP=lbdata->vscroll.rcP; mid.f=lbdata->f; mid.cxChar=lbdata->cxChar; mid.cyChar=lbdata->cyChar; mid.Parent=lbdata->Parent; InsetRect(&mid.rcP,2,4); ClipRect(&mid.rcP); /*deselect previous entry, if needed*/ if (lbdata->CurEntry!=(Int4)-1){ /*mid.rcP=lbdata->vscroll.rcP;*/ mid.Data=lbdata->CurEntryData->pUserData; mid.rcItem=LB_calc_RCdraw(lbdata->CurEntryData->rc,decal); mid.Selected=FALSE; lbdata->CurEntryData->Selected=FALSE; /*send message to draw an entry*/ (*lbdata->MsgFunc)((WindoW)p,ODLB_DrawItem,(Pointer)&mid); } /*select the new entry*/ lbdata->CurEntry=CurEntry; lbdata->CurEntryData=CurEntryData; /*mid.rcP=lbdata->vscroll.rcP;*/ mid.Data=CurEntryData->pUserData; mid.rcItem=LB_calc_RCdraw(CurEntryData->rc,decal); mid.Selected=TRUE; CurEntryData->Selected=TRUE; /*send message to draw an entry; then send a SelectItem msg*/ (*lbdata->MsgFunc)((WindoW)p,ODLB_DrawItem,(Pointer)&mid); if (SendSelectMessage){ (*lbdata->MsgFunc)((WindoW)p,ODLB_SelectItem,(Pointer)&mid); } ResetClip(); RestorePort(temport); } /***************************************************************************** Function: LB_OnClick() Purpose: manage Mouse-Click Parameters: p; list-box handle pt; new mouse position Return value: none *****************************************************************************/ static void LB_OnClick(PaneL p, PoinT pt) { Int4 limit,decal=0,i=1; ValNodePtr vnp; LBEntryDataPtr lbdp; RecT rc; MainLBDataPtr lbdata; Boolean bFind=FALSE; /*get some usefull data...*/ lbdata = (MainLBDataPtr) GetObjectExtra (p); if (lbdata==NULL) return; decal=lbdata->vscroll.ScrollPos*stdLineHeight; limit=(Int4)lbdata->vscroll.rcP.top+decal; /*find the first entry located at the top of the listbox*/ for(vnp=lbdata->LBData ; vnp != NULL ; vnp=vnp->next){ if (vnp->data.ptrvalue){ lbdp=(LBEntryDataPtr)vnp->data.ptrvalue; if (lbdp->rc.bottom>limit){ rc=LB_calc_RCdraw(lbdp->rc,decal); if (PtInRect(pt,&rc)){ bFind=TRUE; break; } } i++; } } /*if item found in the listbox*/ if (bFind){ LB_ChangSel((WindoW)p, lbdata,i,lbdp,TRUE); } } /***************************************************************************** Function: UDV_ReleaseProc() Purpose: manage Mouse-Release Parameters: p; panel handle (currently unused) pt; new position Return value: none *****************************************************************************/ static void LB_OnRelease(PaneL p, PoinT pt) { } /******************************************************************************* Function : LB_DrawEmpty() Purpose : draw a emplty window Parameters : rectangle to fill Return value : none *******************************************************************************/ static void LB_DrawEmpty(RecT rc) { White(); PaintRect(&rc); Black(); } /******************************************************************************* Function : LB_calc_decalRC() Purpose : compute the y decal for LB entry RecT correct positionning on the listbox panel Parameters : lbdata; list of entries ScrollPos; actual position of the Vscroll bar vnp; first entry to draw in the panel rcP; rc de la listbox Return value : y decal value (pixel unit) *******************************************************************************/ static Int4 LB_calc_decalRC(ValNodePtr lbdata,Int4 ScrollPos, ValNodePtr PNTR vnp,RecT rcP) { Int4 decal,limit; LBEntryDataPtr lbdp; decal=ScrollPos*stdLineHeight; limit=(Int4)rcP.top+decal; /*find the first entry located at the top of the listbox*/ for(*vnp=lbdata ; *vnp != NULL ; *vnp=(*vnp)->next){ if ((*vnp)->data.ptrvalue){ lbdp=(LBEntryDataPtr)(*vnp)->data.ptrvalue; if (lbdp->rc.bottom>limit){ break; } } } return(decal); } /******************************************************************************* Function : LB_onDraw() Purpose : draw the panel of the listbox ; if fact, call the User OnDraw function Parameters : handle of the panel Return value : none *******************************************************************************/ static void LB_onDraw(PaneL p) { Int4 decal=0; ValNodePtr vnp,vnp2; LBEntryDataPtr lbdp; RecT rc,rcP; MainLBDataPtr lbdata; MIData mid; WindoW temport; /*get some usefull data...*/ lbdata = (MainLBDataPtr) GetObjectExtra (p); if (lbdata==NULL) return; temport=SavePort(ParentWindow(p)); Select (p); /*restrict panel drawing area: 'add' little margins*/ ObjectRect(p,&rcP); InsetRect(&rcP,2,4); ClipRect(&rcP); if (lbdata->LBData==NULL) { LB_DrawEmpty(rcP); ResetClip(); return; } decal=LB_calc_decalRC(lbdata->LBData,lbdata->vscroll.ScrollPos,&vnp,rcP); if (vnp==NULL){ LB_DrawEmpty(rcP); ResetClip(); return; } mid.rcP=lbdata->vscroll.rcP; mid.f=lbdata->f; mid.cxChar=lbdata->cxChar; mid.cyChar=lbdata->cyChar; mid.Parent=lbdata->Parent; for(vnp2=vnp ; vnp2 != NULL ; vnp2=vnp2->next){ if (vnp2->data.ptrvalue){ lbdp=(LBEntryDataPtr)vnp2->data.ptrvalue; rc=LB_calc_RCdraw(lbdp->rc,decal); /*send message to draw an entry*/ mid.rcItem=rc; mid.Data=lbdp->pUserData; mid.Selected=lbdp->Selected; (*lbdata->MsgFunc)((WindoW)p,ODLB_DrawItem,(Pointer)&mid); /*end ?*/ if (rc.bottom >= rcP.bottom) break; } } ResetClip(); RestorePort(temport); } /******************************************************************************* Function : LB_onVScroll() Purpose : Owner Draw list box Vertical Scroll Bar Callback Parameters : sb; handle of the scroll s; pane; newval; new value of the thumb oldval; old value of the thumb Return value : none *******************************************************************************/ static void LB_onVScroll (BaR sb, SlatE s, Int4 newval, Int4 oldval) { RecT rcP; WindoW temport; Int4 n; Boolean IsGoUp=FALSE; MainLBDataPtr lbdata; /*get some usefull data...*/ lbdata = (MainLBDataPtr) GetObjectExtra (s); if (lbdata==NULL) return; lbdata->vscroll.ScrollPos=newval; temport=SavePort((WindoW)s); Select(s); ObjectRect((PaneL)s,&rcP); InsetRect(&rcP,2,4); ClipRect(&rcP); if (oldval>newval){ n=oldval-newval; IsGoUp=TRUE; } else { n=newval-oldval; IsGoUp=FALSE; } if (nvscroll.ScrollPage){/*Line UP/Down*/ /*move and redraw*/ ScrollRect (&rcP, 0, (Int2)((oldval-newval)*stdLineHeight)); } else{/*Page Up/Down*/ /*redraw*/ /*rcP.left=0; rcP.top=0;*/ InvalRect(&rcP); } ResetClip(); RestorePort(temport); /*Update ();*/ } /******************************************************************************* Function : OwnerDrawLbox_VScrlUpdatePage() Purpose : compute PageUp & Down (VScroll) Parameters : PageUpDn; initialize here cyClient; height of UnDviewer panel Return value : none *******************************************************************************/ static void OwnerDrawLbox_VScrlUpdatePage(Int4Ptr PageUpDn, Int2 cyClient) { *PageUpDn=(Int4)(cyClient/stdLineHeight); } /******************************************************************************* Function : OwnerDrawLbox_VScrlUpdate() Purpose : update the UnDviewer VScroll bar Parameters : p; handel of the UnDviewer panel bInit; TRUE only when the UnDviewer is created (soft. start up) CurPos ; new position Return value : none *******************************************************************************/ static void OwnerDrawLbox_VScrlUpdate(PaneL p, Boolean bInit,Int4 CurPos) { MainLBDataPtr lbdata; BaR vsb; if (p==NULL) return; /*get some usefull data...*/ lbdata = (MainLBDataPtr) GetObjectExtra (p); if (lbdata==NULL) return; /*current scroll status*/ vsb = GetSlateVScrollBar ((SlatE) p); if (bInit) CurPos=0; /*given curpos (lineNumber) retrieve letter number*/ /*compute new values*/ OwnerDrawLbox_VScrlUpdatePage(&(lbdata->vscroll.ScrollPage), lbdata->vscroll.cyClient); if (lbdata->vscroll.nTotLines>lbdata->vscroll.ScrollPage){ lbdata->vscroll.ScrollMax=lbdata->vscroll.nTotLines- lbdata->vscroll.ScrollPage; } else{ lbdata->vscroll.ScrollMax=0; lbdata->vscroll.ScrollPos=0; lbdata->vscroll.ScrollPage=0; } if (CurPos<0) CurPos=0; if (CurPos>=lbdata->vscroll.ScrollMax) lbdata->vscroll.ScrollPos=lbdata->vscroll.ScrollMax; else lbdata->vscroll.ScrollPos=CurPos; /*update scroll*/ CorrectBarMax(vsb,lbdata->vscroll.ScrollMax); CorrectBarValue(vsb,lbdata->vscroll.ScrollPos); CorrectBarPage(vsb,lbdata->vscroll.ScrollPage, lbdata->vscroll.ScrollPage); } /******************************************************************************* Function : OwnerDrawLbox_ResetLBContent() Purpose : delete actual data of the list box Parameters : lbox; handle of the list box Return value : none *******************************************************************************/ NLM_EXTERN void OwnerDrawLbox_ResetLBContent(WindoW lbox) { MainLBDataPtr lbdata; ValNodePtr vnp; WindoW temport; BaR vsb; lbdata=(MainLBDataPtr)GetObjectExtra (lbox); if (lbdata==NULL) return; /*delete list of user data*/ if (lbdata->nEntry>0){ for(vnp=lbdata->LBData ; vnp!=NULL ; vnp=vnp->next){ if (vnp->data.ptrvalue) MemFree(vnp->data.ptrvalue); } ValNodeFree(lbdata->LBData); lbdata->LBData=NULL; } /*init lbox internal data*/ lbdata->nEntry=0; lbdata->CurEntry=-1; lbdata->CurEntryData=NULL; lbdata->vscroll.ScrollMax=0; lbdata->vscroll.ScrollPos=0; lbdata->vscroll.ScrollPage=0; lbdata->vscroll.nTotLines=0; lbdata->LBDataTmp=NULL; lbdata->decal=0; /*reinit scrollbar and redraw an empty listbox*/ vsb = GetSlateVScrollBar ((SlatE)lbox); CorrectBarMax(vsb,0); CorrectBarValue(vsb,0); CorrectBarPage(vsb,0,0); temport=SavePort(lbox); Select(lbox); InvalRect(&lbdata->vscroll.rcP); RestorePort(temport); } /******************************************************************************* Function : OwnerDrawLbox_GetCurData() Purpose : retrieve the current data of the selected item in an owner draw listbox Parameters : lbox; handle of the list box Return value : current item data *******************************************************************************/ NLM_EXTERN Pointer OwnerDrawLbox_GetCurData(WindoW lbox) { MainLBDataPtr lbdata; /*retrieve lbox data*/ lbdata = (MainLBDataPtr) GetObjectExtra (lbox); if (lbdata == NULL) return(NULL);/*oups*/ return(lbdata->CurEntryData->pUserData); } /******************************************************************************* Function : OwnerDrawLbox_GetData() Purpose : retrieve the current data of the selected item in an owner draw listbox Parameters : lbox; handle of the list box item; data to retrieve (one based value) Return value : current item data *******************************************************************************/ NLM_EXTERN Pointer OwnerDrawLbox_GetData(WindoW lbox,Int4 item) { MainLBDataPtr lbdata; ValNodePtr vnp; Int4 i=1; Boolean bFound=FALSE; /*retrieve lbox data*/ lbdata = (MainLBDataPtr) GetObjectExtra (lbox); if (lbdata == NULL) return(NULL);/*oups*/ /*scan list of user data*/ if (lbdata->nEntry>0){ for(vnp=lbdata->LBData ; vnp!=NULL ; vnp=vnp->next){ if (i==item) { bFound=TRUE; break; } i++; } } if (!bFound) return(NULL); return((Pointer)vnp->data.ptrvalue); } /******************************************************************************* Function : OwnerDrawLbox_GetNentry() Purpose : retrieve the number of entries of aa owner draw listbox Parameters : lbox; handle of the list box Return value : current item data *******************************************************************************/ NLM_EXTERN Int4 OwnerDrawLbox_GetNentry(WindoW lbox) { MainLBDataPtr lbdata; /*retrieve lbox data*/ lbdata = (MainLBDataPtr) GetObjectExtra (lbox); if (lbdata == NULL) return(0);/*oups*/ return(lbdata->nEntry); } /******************************************************************************* Function : OwnerDrawLbox_GetCurSel() Purpose : retrieve the current selected item in an owner draw listbox Parameters : lbox; handle of the list box Return value : current item selected in the list box (Zero-based value) *******************************************************************************/ NLM_EXTERN Int4 OwnerDrawLbox_GetCurSel(WindoW lbox) { MainLBDataPtr lbdata; /*retrieve lbox data*/ lbdata = (MainLBDataPtr) GetObjectExtra (lbox); if (lbdata == NULL) return((Int4)-1);/*oups*/ return(lbdata->CurEntry); } /******************************************************************************* Function : OwnerDrawLbox_SelectItem() Purpose : select an item in an owner draw listbox Parameters : lbox; handle of the list box item; item to select (One-based value) Return value : none *******************************************************************************/ NLM_EXTERN void OwnerDrawLbox_SelectItem(WindoW lbox,Int4 item) { MainLBDataPtr lbdata; ValNodePtr vnp; Int4 i=1,decal,NewPos; Boolean bFound=FALSE; LBEntryDataPtr lbdp; RecT rc; /*retrieve lbox data*/ lbdata = (MainLBDataPtr) GetObjectExtra (lbox); if (lbdata == NULL) return;/*oups*/ /*scan list of user data*/ if (lbdata->nEntry>0){ for(vnp=lbdata->LBData ; vnp!=NULL ; vnp=vnp->next){ if (i==item) { bFound=TRUE; break; } i++; } } if (!bFound) return; lbdp=(LBEntryDataPtr)vnp->data.ptrvalue; /*scroll*/ decal=lbdata->vscroll.ScrollPos*stdLineHeight; rc=LB_calc_RCdraw(lbdp->rc,decal); if (!RectInRect(&rc,&lbdata->vscroll.rcP)){ WindoW temport; NewPos=(lbdp->rc.top-lbdata->vscroll.rcP.top)/stdLineHeight; OwnerDrawLbox_VScrlUpdate((PaneL)lbox,FALSE,NewPos); temport=SavePort(lbox); Select(lbox); InvalRect(&lbdata->vscroll.rcP); RestorePort(temport); } LB_ChangSel(lbox,lbdata,item,lbdp,FALSE); } /******************************************************************************* Function : OwnerDrawLbox_AddItem() Purpose : add a user item to an owner draw listbox Parameters : lbox; handle of the list box item; data to add to the list Return value : TRUE if success, FALSE if any errors *******************************************************************************/ NLM_EXTERN Boolean OwnerDrawLbox_AddItem(WindoW lbox,Pointer item) { MainLBDataPtr lbdata; LBEntryDataPtr lbdp; MIData mid; /*retrieve lbox data*/ lbdata = (MainLBDataPtr) GetObjectExtra (lbox); if (lbdata == NULL) return(FALSE);/*oups*/ /*ask the user for the item size*/ MemSet(&mid.rcItem,0,sizeof(RecT)); mid.Data=item; mid.rcP=lbdata->vscroll.rcP; mid.Selected=FALSE; mid.f=lbdata->f; mid.cxChar=lbdata->cxChar; mid.cyChar=lbdata->cyChar; mid.Parent=lbdata->Parent; if (!(*lbdata->MsgFunc)(lbox,ODLB_MeasureItem,(Pointer)&mid)) { /*if message isn't managed by the user, compute a default size*/ mid.rcItem.left=lbdata->vscroll.rcP.left; mid.rcItem.top=0; mid.rcItem.right=lbdata->vscroll.rcP.right; mid.rcItem.bottom=stdLineHeight; } /*create new data block for the user data*/ lbdp=(LBEntryDataPtr)MemNew(sizeof(LBEntryData)); if (lbdp==NULL) return(FALSE);/*oups II, the return*/ MemSet(lbdp,0,sizeof(LBEntryData)); lbdp->pUserData=item; /*add the item to the ValNodeList*/ if (lbdata->nEntry==0){ lbdata->LBData=ValNodeAddPointer(NULL,0,(VoidPtr)lbdp); if (lbdata->LBData==NULL) { MemFree(lbdp); return(FALSE);/*oups III, the ultimate adventure*/ } lbdata->LBDataTmp=lbdata->LBData; /*position of the new element*/ lbdp->rc.left=(Int4)mid.rcItem.left; lbdp->rc.right=(Int4)mid.rcItem.right; lbdp->rc.top=(Int4)(mid.rcItem.top+lbdata->vscroll.rcP.top); lbdp->rc.bottom=(Int4)(lbdp->rc.top+mid.rcItem.bottom); } else{ lbdata->LBDataTmp=ValNodeAddPointer(&lbdata->LBDataTmp,0,(VoidPtr)lbdp); if (!lbdata->LBDataTmp){ MemFree(lbdp); return(FALSE); /*oups IV, the resurrection*/ } /*compute correct pos for the new item*/ lbdp->rc.left=(Int4)mid.rcItem.left; lbdp->rc.right=(Int4)mid.rcItem.right; lbdp->rc.top=(Int4)(mid.rcItem.top+lbdata->decal); lbdp->rc.bottom=(Int4)(lbdp->rc.top+mid.rcItem.bottom); } /*decal in the list box*/ lbdata->decal=lbdp->rc.bottom+1; /*ok*/ lbdata->nEntry++; /*update the scroll, but do not move it; stay on pos 0*/ lbdata->vscroll.nTotLines=lbdata->decal/stdLineHeight+1; OwnerDrawLbox_VScrlUpdate((PaneL)lbox,TRUE,0); /*ask the user to draw, only if needed*/ /* if (lbdp->rc.bottom<=(Int4)lbdata->vscroll.rcP.bottom){ mid.rcItem.top=(Int2)lbdp->rc.top; mid.rcItem.bottom=(Int2)lbdp->rc.bottom; mid.Data=item; mid.rcP=lbdata->vscroll.rcP; mid.f=lbdata->f; mid.cxChar=lbdata->cxChar; mid.cyChar=lbdata->cyChar; (*lbdata->MsgFunc)(lbox,ODLB_DrawItem,(Pointer)&mid); }*/ return(TRUE); } /******************************************************************************* Function : OwnerDrawLbox_MoveWindow() Purpose : move/resize an owner draw listbox Parameters : lbox ; do you think it's what ? x ; pos on x y ; pos on y cx ; width of the ListBox cy ; height of the ListBox Return value : - *******************************************************************************/ NLM_EXTERN void OwnerDrawLbox_MoveWindow(WindoW lbox, Int2 x,Int2 y, Int2 cx,Int2 cy) { MainLBDataPtr lbdata; LBEntryDataPtr lbdp; MIData mid; ValNodePtr vnp; RecT rcP; Int4 oldDecal,oldCurPos = 0; Boolean bFirst=TRUE,bFirst2=FALSE; /*retrieve lbox data*/ lbdata = (MainLBDataPtr) GetObjectExtra (lbox); if (lbdata == NULL) return; /*compute new listbox size*/ Select(lbox); rcP.left=x; rcP.top=y; rcP.right=x+cx; rcP.bottom=y+cy; lbdata->vscroll.rcP=rcP; lbdata->vscroll.rcP.right-=3*lbdata->cxChar; lbdata->vscroll.rcP.top+=1; lbdata->vscroll.cxClient=cx; lbdata->vscroll.cyClient=cy; mid.rcP=lbdata->vscroll.rcP; mid.f=lbdata->f; mid.cxChar=lbdata->cxChar; mid.cyChar=lbdata->cyChar; mid.Parent=lbdata->Parent; oldDecal=lbdata->vscroll.ScrollPos*stdLineHeight; lbdata->decal=lbdata->vscroll.rcP.top; /*resize all the items*/ for(vnp=lbdata->LBData ; vnp!=NULL ; vnp=vnp->next){ lbdp=(LBEntryDataPtr)vnp->data.ptrvalue; if (lbdp){ if (bFirst){/*retrieve the first displayed item of the list*/ if ((lbdp->rc.top-lbdata->vscroll.rcP.top)>=oldDecal){ bFirst2=TRUE; bFirst=FALSE; } } mid.Data=lbdp->pUserData; if (!(*lbdata->MsgFunc)(lbox,ODLB_MeasureItem,(Pointer)&mid)) { /*if message isn't managed by the user, compute a default size*/ mid.rcItem.left=lbdata->vscroll.rcP.left; mid.rcItem.top=0; mid.rcItem.right=lbdata->vscroll.rcP.right; mid.rcItem.bottom=stdLineHeight; } /*compute correct pos for the new item*/ lbdp->rc.left=(Int4)mid.rcItem.left; lbdp->rc.right=(Int4)mid.rcItem.right; lbdp->rc.top=(Int4)(mid.rcItem.top+lbdata->decal); lbdp->rc.bottom=(Int4)(lbdp->rc.top+mid.rcItem.bottom); if (bFirst2){/*compute oldCurPos*/ oldCurPos=(lbdp->rc.top-lbdata->vscroll.rcP.top)/stdLineHeight; bFirst2=FALSE; } /*decal in the list box*/ lbdata->decal=lbdp->rc.bottom+1; } } /*update the scroll*/ lbdata->vscroll.nTotLines=lbdata->decal/stdLineHeight+1; OwnerDrawLbox_VScrlUpdate((PaneL)lbox,FALSE,oldCurPos); /*move/resize and redraw window*/ SetPosition(lbox, &rcP); AdjustPrnt(lbox, &rcP, FALSE); } /******************************************************************************* Function : OwnerDrawLbox_Create() Purpose : Create an owner draw listbox Parameters : Parent ; handle of the parent window for the listbox x ; pos on x y ; pos on y cx ; width of the ListBox cy ; height of the ListBox MsgFunc ; Message loop of the ListBox Return value : WindoW if success, NULL if any errors *******************************************************************************/ NLM_EXTERN WindoW OwnerDrawLbox_Create(WindoW Parent, Int2 x,Int2 y, Int2 cx,Int2 cy, OwnerDrawLboxFunc MsgFunc,FonT f, Int2 cxChar,Int2 cyChar) { MainLBDataPtr lbdata; PaneL p; RecT rcP; /*create the listbox as an AutonomousPanel4*/ p=AutonomousPanel4(Parent,10,10,LB_onDraw, LB_onVScroll,NULL,0,NULL,NULL); /*create mouse action for the listbox*/ SetPanelClick(p,LB_OnClick,NULL,NULL,LB_OnRelease); if (p==NULL) return(NULL);/*isn't it !*/ /*use x,y,cx,cy provided by the user*/ Select(p); rcP.left=x; rcP.top=y; rcP.right=x+cx; rcP.bottom=y+cy; SetPosition(p, &rcP); AdjustPrnt(p, &rcP, FALSE); /*Allocate the data structure and attach it to the list box*/ lbdata=(MainLBDataPtr)MemNew(sizeof(MainLBData)); if (lbdata==NULL) { Remove(p); return(NULL); } MemSet(lbdata,0,sizeof(MainLBData)); lbdata->CurEntry=-1; lbdata->Parent=Parent; lbdata->MsgFunc=(OwnerDrawLboxFunc)MsgFunc; lbdata->vscroll.cxClient=cx; lbdata->vscroll.cyClient=cy; rcP.top+=1; rcP.right-=3*cxChar; lbdata->vscroll.rcP=rcP; lbdata->f=f; lbdata->cxChar=cxChar; lbdata->cyChar=cyChar; SetObjectExtra (p, (Pointer) lbdata, LBCleanupDataProc); /*yes !*/ return((WindoW)p); }