/* $Id: ddvclick.c,v 1.66 2006/07/13 17:11:42 bollin Exp $ * =========================================================================== * * 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: ddvclick.c * * Author: Patrick Durand * * Version Creation Date: 09/20/99 * * $Revision: 1.66 $ * * File Description: mouse management code for DeuxD-Viewer (DDV) * * Modifications: * -------------------------------------------------------------------------- * $Log: ddvclick.c,v $ * Revision 1.66 2006/07/13 17:11:42 bollin * use Uint4 instead of Uint2 for itemID values * * Revision 1.65 2000/07/25 20:30:23 hurwitz * bug fixes: panel update when file is closed, double-click launches UDV from DDE, seqName agrees in status line and left col * * Revision 1.64 2000/07/24 22:00:08 hurwitz * fixed bug that 1/2 characters were displayed sometimes * * Revision 1.63 2000/07/20 22:25:57 hurwitz * bug fix. mouse-mode query working again * * Revision 1.62 2000/07/14 22:24:55 lewisg * fix scroll, click, visual c++ build bugs. add command line arg parse to ddv * * Revision 1.61 2000/07/12 22:22:41 hurwitz * added delete block to DDV * * Revision 1.60 2000/07/12 21:18:13 hurwitz * fixed display problems with select rectangle * * Revision 1.59 2000/07/12 15:38:08 hurwitz * made rectangle select much faster. it's almost working. * * Revision 1.58 2000/07/05 19:23:13 lewisg * add two panes to ddv, update msvc project files * * Revision 1.57 2000/07/05 18:42:16 hurwitz * added split block function to DDV * * Revision 1.56 2000/06/30 22:31:51 hurwitz * added merge block function for DDV * * Revision 1.55 2000/06/28 19:41:31 hurwitz * auto vertical scroll working for rectangle selection * * Revision 1.54 2000/06/27 20:46:38 hurwitz * fixed bugs with select rectangle, added select row option * * Revision 1.53 2000/06/26 19:32:17 hurwitz * can select a rectangle instead of a single row, auto horizontal scroll works but not vertical scroll yet * * Revision 1.52 2000/06/22 20:56:52 hurwitz * assorted bug fixes * * Revision 1.51 2000/06/21 21:20:56 hurwitz * a couple bug fixes * * Revision 1.50 2000/06/20 19:35:11 hurwitz * use indexed seqAlign when necessary, make multiple when redrawing * * Revision 1.49 2000/06/16 18:40:02 lewisg * send mouseup message when drag ends off of sequence * * Revision 1.48 2000/06/15 20:26:05 hurwitz * added left/right/center justify for DDE * * Revision 1.47 2000/06/13 18:23:54 hurwitz * made ViewMgr_MakeMultiple routine, call this on each launch of DDE rather than launch of DDV * * Revision 1.46 2000/06/12 23:02:40 hurwitz * enable launch of DDE from Cn3D, swith from DDV_ComputeRuler to DDE_ReMakeRuler, get rid of styles option for DDE * * Revision 1.45 2000/06/06 20:09:22 lewisg * fix double redraw bug * * Revision 1.44 2000/05/31 23:07:26 hurwitz * made NoGaps a runtime parameter, fixed bug with vertical scroll of show/hide list, save edits query is not performed if nothing to save * * Revision 1.43 2000/05/25 21:40:42 hurwitz * rows hidden in DDV are hidden in DDE, can save edits when rows are hidden in DDE * * Revision 1.42 2000/05/24 21:42:59 hurwitz * getting hide/show rows to work with DDV and DDE together * * Revision 1.41 2000/05/19 13:48:31 hurwitz * made a version of DDE that doesn't allow aligned gaps, changed wording for adding new rows * * Revision 1.40 2000/05/16 19:43:01 hurwitz * grey out create block, delete block, undo, and redo as needed * * Revision 1.39 2000/05/08 22:48:33 hurwitz * on launch of DDE, merge nodes that are same MsaTxtDisp alignment and gap * * Revision 1.38 2000/05/05 20:24:13 hurwitz * some bug fixes, also redraw proper block in DDE after a save operation that causes a merge of 2 blocks * * Revision 1.37 2000/05/04 22:43:38 hurwitz * don't launch DDE on top of DDV, change some wording, redraw DDE after save to AlnMgr * * Revision 1.36 2000/05/02 19:50:38 hurwitz * fixed some bugs with launching DDE from DDV, added new alnMgr fn for positioning DDE on proper column * * Revision 1.35 2000/04/27 17:01:44 hurwitz * small fixes to shift row and shift boundary * * Revision 1.34 2000/04/26 21:54:27 hurwitz * added save function to tell AlnMgr about edits made in DDE * * Revision 1.33 2000/04/21 23:00:51 hurwitz * can launch DDE from DDV * * Revision 1.32 2000/04/13 18:57:03 hurwitz * for DDE: many bug fixes, also get rid of columns that are all unaligned gaps * * Revision 1.31 2000/04/10 20:58:42 hurwitz * added GUI controls for DeleteBlock in DDE * * Revision 1.30 2000/04/07 16:21:08 hurwitz * made delete block faster, added delete block to edit menu * * Revision 1.29 2000/04/05 20:52:35 hurwitz * added GUI control for shifting left and right alignment boundaries * * Revision 1.28 2000/04/04 22:18:43 lewisg * add defline to ddv, fix seq import bugs, set boundbox * * Revision 1.27 2000/04/03 22:26:31 hurwitz * can now shift a row with click and drag * * Revision 1.26 2000/03/30 23:35:22 hurwitz * fixed a bug involving scrolling while moving a row * * Revision 1.25 2000/03/29 20:02:48 hurwitz * keep track of master during move row operations * * Revision 1.24 2000/03/28 21:03:14 hurwitz * added gui control to re-order rows * * Revision 1.23 2000/03/27 18:07:48 hurwitz * page up and page down working, give panel focus on launch * * Revision 1.22 2000/03/25 00:22:09 hurwitz * put DDE_StackPtr in DDV_Main, add to stack inside DDE api's, added insert char, delete char, home and end keyboard control * * Revision 1.21 2000/03/01 22:49:41 lewisg * import bioseq, neatlyindex, get rid of dead code * * Revision 1.20 2000/03/01 20:23:39 durand * update select/deselect code to allow DDV sending correct message to Cn3D * * Revision 1.19 2000/02/15 22:40:57 lewisg * add ability to launch udv so that it colors by row, fixes to colormgr, track rows from viewmgr, fix visual c projects * * Revision 1.18 2000/02/07 18:57:58 durand * fixed a selection problem * * Revision 1.17 2000/02/04 16:05:40 durand * add click action to select a row * * Revision 1.16 2000/02/02 14:44:29 durand * added function to create data structure for block editor, fixed some bugs * * Revision 1.15 2000/01/12 15:49:42 durand * add About dlg box and fix a bug in selection * * Revision 1.14 2000/01/10 15:09:45 durand * Use Entrez instead of ID1 * * Revision 1.13 2000/01/05 21:11:13 durand * update mouse click actions and DrawSequence function for a better use from ddv and cn3d * * Revision 1.12 1999/12/07 21:40:13 durand * add mouse modes menu and caret facility for the editor * * Revision 1.11 1999/12/06 16:19:19 durand * add GoTo facility to DDV * * Revision 1.10 1999/12/03 23:17:22 lewisg * Patrick's new global update msg, argument passing when launching ddv, experimental editing * * Revision 1.9 1999/11/29 15:26:25 durand * designed a new GUI to fix problems under MacOS, Linux and SGI * * Revision 1.8 1999/11/18 00:21:42 lewisg * draw speedups and selection on mouseup * * Revision 1.7 1999/11/17 22:44:01 durand * speed up the selection manager for large SeqAlign * * Revision 1.6 1999/11/03 21:29:48 durand * add CTRL and SHFT keys for mouse selection. redesign the loader functions of DDV to properly register the message callbacks * * Revision 1.5 1999/10/29 14:15:39 durand * add simple mouse selection functions * * Revision 1.4 1999/10/22 14:19:05 durand * add new code for mouse selection * * Revision 1.3 1999/10/21 13:12:43 durand * update selection system * * Revision 1.2 1999/10/12 15:01:28 lewisg * resolve confict with internal/ddv * * Revision 1.1 1999/09/30 14:10:24 durand * add ddv to toolkit * * Revision 1.2 1999/09/22 20:41:17 durand * add mouse-click and drag functions * * Revision 1.1 1999/09/21 14:19:59 durand * add basic mouse management functions * * * * ========================================================================== */ #include #include #include #include #include #include #include #include #include #include #include #include #include /*static MonitorPtr mon=NULL;*/ static Boolean OnAlignmentBoundary(PoinT pt, PaneL p, DdvMainPtr dmp, Int4* pBlockIndex, Boolean* pLeftBoundary, Int4* pCol, Int4* pHPos); static Boolean GetBlockAndAlignment(PoinT pt, PaneL p, DdvMainPtr dmp, Int4* pBlockIndex, Boolean* pIsUnAligned, Int4* pCol, Int4* pOffset, Int4* pWidth, RecT* rcP); static Boolean GetBlockAndAlignmentForCol(DdvMainPtr dmp, Int4 Col, Int4* pBlockIndex, Boolean* pIsUnAligned, Int4* pOffset, Int4* pWidth); static RecT DrawOutline(PaneL p, Int4 Line_num_start, Int4 Disp_coord_start, Int4 Line_num_stop, Int4 Disp_coord_stop, Boolean Draw); static RecT DrawOutlineGivenScroll(PaneL p, Int4 Line_num_start, Int4 Disp_coord_start, Int4 Line_num_stop, Int4 Disp_coord_stop, Int4 VScroll, Int4 HScroll, Boolean Draw); static void EraseOutline(PaneL p); static Boolean RectanglesAreSame(RecT rc1, RecT rc2); static void DDV_SelectRegion(DdvMainPtr dmp, PoinT pt, RecT rc, Int4 row_start, Int4 row_stop, Int4 col_start, Int4 col_stop); NLM_EXTERN Int4 DDV_GetHPixelPosGivenColNumberAndScroll(DdvMainPtr dmp, RecT rc, Int4 Col, Int4 ScrollPos) { /***************************************************************************** * return number of pixels right to (0-based) Col. *****************************************************************************/ Int4 NumPixels; InsetRect(&rc,4,4); DDV_AdjustDrawingRect(&rc,&(dmp->GrData.udv_font),dmp); NumPixels = (Col+1-ScrollPos) * dmp->GrData.udv_font.ColWidth; NumPixels += dmp->GrData.udv_panel.cxName + dmp->GrData.udv_scale.cxLeftScale; NumPixels += rc.left; return(NumPixels); } NLM_EXTERN Int4 DDV_GetHPixelPosGivenColNumber(DdvMainPtr dmp, RecT rc, Int4 Col) { /***************************************************************************** * return number of pixels right to (0-based) Col for current ScrollPos. *****************************************************************************/ return(DDV_GetHPixelPosGivenColNumberAndScroll(dmp, rc, Col, dmp->GrData.udv_hscrl.ScrollPos)); } NLM_EXTERN Int4 DDV_GetVPixelPosGivenRowNumberAndScroll(DdvMainPtr dmp, RecT rc, Int4 Row, Int4 ScrollPos) { /***************************************************************************** * return number of pixels down to (0-based) Row. *****************************************************************************/ Int4 NumPixels; InsetRect(&rc,4,4); DDV_AdjustDrawingRect(&rc,&(dmp->GrData.udv_font), dmp); NumPixels = (Row+1-ScrollPos) * dmp->GrData.udv_font.LineHeight; /* next line is copied from DDV_GetRowGivenMousePos */ NumPixels += 3*dmp->GrData.udv_panel.cyScale/2; NumPixels += rc.top; return(NumPixels); } NLM_EXTERN Int4 DDV_GetVPixelPosGivenRowNumber(DdvMainPtr dmp, RecT rc, Int4 Row) { /***************************************************************************** * return number of pixels down to (0-based) Row for current scrollPos. *****************************************************************************/ return(DDV_GetVPixelPosGivenRowNumberAndScroll(dmp, rc, Row, dmp->GrData.udv_vscrl.ScrollPos)); } NLM_EXTERN void DDV_GetVPixelPosOfEmptySpace(DdvMainPtr dmp, RecT rc, Int4* pTop, Int4* pBot) { /***************************************************************************** * return Top: number of pixels down to top of empty space. * return Bot: number of pixels down to bot of empty space. *****************************************************************************/ InsetRect(&rc,4,4); *pTop = rc.top; *pBot = rc.top + dmp->GrData.udv_panel.cyScale/2; return; } NLM_EXTERN Int4 DDV_GetColNumberGivenMousePos(DdvMainPtr dmp, RecT rc, PoinT pt) { /***************************************************************************** * return the display coordinate at this mouse position. *****************************************************************************/ Int4 mouse_col; InsetRect(&rc,4,4); DDV_AdjustDrawingRect(&rc,&(dmp->GrData.udv_font),dmp); rc.left+=dmp->GrData.udv_panel.cxName + dmp->GrData.udv_scale.cxLeftScale; mouse_col=(pt.x-rc.left)/dmp->GrData.udv_font.ColWidth+ dmp->GrData.udv_hscrl.ScrollPos; return(mouse_col); } /***************************************************************************** Function: DDV_GetRowGivenMousePos() Purpose: given some graphical info, this function returns line_num, the row number (absolute value) and the ParaGLine_Num (i.e. sequence/row number; this value must be use to get data from TableHead). Return value: line_num (-1 if not found ; otherwise a one-based value) *****************************************************************************/ static Int4 DDV_GetRowGivenMousePos(DdvMainPtr dmp, RecT * rcP, PoinT * pt, Int4Ptr ParaGLine_Num) { Int4 Line_num=(Int4)-1,mouse_row,i,n; ParaGPtr pgp; /*size of the Panel; see also DDV_DrawPanelContent_H()*/ InsetRect(rcP,4,4); DDV_AdjustDrawingRect(rcP,&(dmp->GrData.udv_font),dmp); rcP->left+=dmp->GrData.udv_panel.cxName+dmp->GrData.udv_scale.cxLeftScale; rcP->top+=3*dmp->GrData.udv_panel.cyScale/2; /*mouse position*/ mouse_row=(pt->y-rcP->top)/dmp->GrData.udv_font.LineHeight+ dmp->GrData.udv_vscrl.ScrollPos; /*use the first ParaG of each sequence and mouse_row to find row (==sequence) number*/ for(i=0;iMSA_d.pgp_l.nBsp;i++){ pgp=(ParaGPtr)(dmp->MSA_d.pgp_l.TableHead[i]->data.ptrvalue); if (pgp->ScaleStyle==SCALE_POS_NONE) n=0; else n=1; /*within each ParaG, the seq. in on line 0 or 1 (if ruler)*/ if (mouse_row>=pgp->StartLine && mouse_row<=(pgp->StartLine+n)){ Line_num=mouse_row+1; *ParaGLine_Num=i+1; break; } } return(Line_num); } /***************************************************************************** Function: DDV_GetClosetSeqLocGivenBspPos() Purpose: given a position in the Bioseq, this function return the closest selected region on that bioseq. Parameters: sip, eID, iID; bsioseq identifiers bsp_pos; current position on that bioseq old_pos; returns old_pos of a selection (used only if bModify is TRUE) bModify; if TRUE, create a modified slp Note : sip can be null ONLY if bModify if FALSE. Return value: see Purpose. *****************************************************************************/ static SeqLocPtr DDV_GetClosetSeqLocGivenBspPos(SeqIdPtr sip, Uint2 eID, Uint2 iID, Int4 bsp_pos, Int4Ptr old_pos, Boolean bModify) { SelStructPtr ssp; SeqLocPtr slp=NULL; ValNodePtr vnp_bsp,vnp; Int4 diff,old_diff,diff_l,diff_r,bsp_start,bsp_stop; Uint1 strand; ssp=ObjMgrGetSelected(); if (ssp==NULL) return(NULL); vnp_bsp=DDV_GetSelectedRegions(ssp,eID,iID); if (vnp_bsp==NULL) return(NULL); vnp=vnp_bsp; *old_pos=(Int4)-1; old_diff=(Int4)INT4_MAX; while(vnp){ bsp_start=SeqLocStart((SeqLocPtr)vnp->data.ptrvalue); bsp_stop=SeqLocStop((SeqLocPtr)vnp->data.ptrvalue); strand=SeqLocStrand((SeqLocPtr)vnp->data.ptrvalue); if (bsp_posbsp_stop){/*right of a selected region ?*/ diff=bsp_pos-bsp_stop; if (diffnext; } ValNodeFree(vnp_bsp); return(slp); } /***************************************************************************** Function: DDV_IsFullBspAlreadySel() Purpose: check if a row is already selected. Parameters: bsp_eID,bsp_iID; bsp identifiers bsp_start,bsp_stop; full sequence Return value: TRUE if the sequence is already fully selected *****************************************************************************/ static Boolean DDV_IsFullBspAlreadySel(Uint2 bsp_eID,Uint2 bsp_iID,Int4 bsp_start, Int4 bsp_stop) { SelStructPtr ssp; ValNodePtr vnp_bsp,vnp; Int4 sel_bsp_start,sel_bsp_stop; ssp=ObjMgrGetSelected(); if (ssp==NULL) return(FALSE); vnp_bsp=DDV_GetSelectedRegions(ssp,bsp_eID,bsp_iID); if (vnp_bsp==NULL) return(FALSE); vnp=vnp_bsp; while(vnp){ sel_bsp_start=SeqLocStart((SeqLocPtr)vnp->data.ptrvalue); sel_bsp_stop=SeqLocStop((SeqLocPtr)vnp->data.ptrvalue); if (bsp_start==sel_bsp_start && bsp_stop==sel_bsp_stop) return(TRUE); vnp=vnp->next; } return(FALSE); } static Uint1 DDV_GetRegionInParaG(ParaGPtr pgp, Int4 Line_num) { /***************************************************************************** * get region within ParaG *****************************************************************************/ Int4 mouse_row, diff; mouse_row = Line_num-1; if (pgp->ScaleStyle==SCALE_POS_NONE) diff=0; else diff=1; if (mouse_row==(pgp->StartLine+diff)){ return(PGP_REGION_SEQ); } else if (mouse_row > (pgp->StartLine+ diff) && mouse_row <= (pgp->StartLine+ pgp->nLines-1)){ return(PGP_REGION_FEAT); } return(PGP_REGION_NOWHERE); } static void DDV_GetRowAndColGivenPtAndScroll(DdvMainPtr dmp, RecT rc, PoinT pt, Int4 HScroll, Int4 VScroll, Int4Ptr Disp_coord, Int4Ptr Line_num) { /***************************************************************************** * get row and column where the mouse is clicked. Provide scroll positions. *****************************************************************************/ Int4 mouse_row, mouse_col; InsetRect(&rc,4,4); DDV_AdjustDrawingRect(&rc, &(dmp->GrData.udv_font), dmp); rc.left += dmp->GrData.udv_panel.cxName + dmp->GrData.udv_scale.cxLeftScale; rc.top += 3*dmp->GrData.udv_panel.cyScale/2; mouse_row = (pt.y - rc.top)/dmp->GrData.udv_font.LineHeight + VScroll; mouse_col = (pt.x - rc.left)/dmp->GrData.udv_font.ColWidth + HScroll; *Line_num=mouse_row+1; *Disp_coord=mouse_col; } static void DDV_GetRowAndColGivenPt(DdvMainPtr dmp, RecT rc, PoinT pt, Int4Ptr Disp_coord, Int4Ptr Line_num) { /*********************************************************************************** * get row and column where the mouse is clicked. Assume current scroll positions. ***********************************************************************************/ DDV_GetRowAndColGivenPtAndScroll(dmp, rc, pt, dmp->GrData.udv_hscrl.ScrollPos, dmp->GrData.udv_vscrl.ScrollPos, Disp_coord, Line_num); } static Int4 DDV_GetParaGLineNumGivenLineNum(DdvMainPtr dmp, Int4 Line_num) { /***************************************************************************** * get the ParaGLine_Num for Line_num. *****************************************************************************/ Int4 i, row; ParaGPtr pgp; row = Line_num-1; for (i=0; iMSA_d.pgp_l.nBsp; i++) { pgp = (ParaGPtr)(dmp->MSA_d.pgp_l.TableHead[i]->data.ptrvalue); if (row>=pgp->StartLine && row<=(pgp->StartLine + pgp->nLines-1)) { return(i+1); } } return(-1); } static Int4 DDV_GetSeqAlignCoordGivenCol(DdvMainPtr dmp, Int4 Disp_coord) { /***************************************************************************** * get the SeqAlignCoord for Disp_coord. *****************************************************************************/ ValNodePtr vnp; DDVRulerDescrPtr drdp; Int4 diff; vnp=dmp->MSA_d.pgp_l.RulerDescr; while(vnp){ drdp=(DDVRulerDescrPtr)vnp->data.ptrvalue; if (!drdp->bUnAligned){ diff = Disp_coord - drdp->disp_start; if (Disp_coord>=drdp->disp_start && Disp_coord<=drdp->disp_stop){ return(drdp->align_start + diff); } } vnp=vnp->next; } return(-1); } static ParaGPtr DDV_GetPGPGivenRowAndCol(DdvMainPtr dmp, Int4 Line_num, Int4 Disp_coord) { /***************************************************************************** * get the ParaG ptr that contains (Line_num, Disp_coord) *****************************************************************************/ ParaGPtr pgp=NULL; ValNodePtr vnp; vnp=dmp->MSA_d.pgp_l.TableHead[Line_num-1]; while(vnp){ pgp=(ParaGPtr)vnp->data.ptrvalue; if (Disp_coord>=pgp->StartLetter && Disp_coord<=pgp->StopLetter){ return(pgp); } vnp=vnp->next; } return(pgp); } static Boolean DDV_GetCoordsGivenAClickAndScrollPos(DdvMainPtr dmp, RecT * rcP, PoinT * pt, Int4 HScroll, Int4 VScroll, Int4Ptr bsp_coord, Int4Ptr SeqAlign_coord, Int4Ptr Disp_coord, Int4Ptr Line_num, Int4Ptr ParaGLine_Num, Uint1Ptr uWhere, ParaGPtr PNTR cur_pgp) /***************************************************************************** * variation on DDV_GetCoordsGivenAClick. * pass: VScroll and HScroll -- the positions of the vertical and * horizontal scroll bars. *****************************************************************************/ { ValNodePtr vnp; ParaGPtr pgp,TheParaG; /*MsaTxtDispPtr mtdp;*/ DDVRulerDescrPtr drdp; Int4 mouse_row,mouse_col,i,diff; Boolean bFound; *ParaGLine_Num = -1; /*size of the Panel; see also DDV_DrawPanelContent_H()*/ InsetRect(rcP,4,4); DDV_AdjustDrawingRect(rcP,&(dmp->GrData.udv_font),dmp); rcP->left+=dmp->GrData.udv_panel.cxName+dmp->GrData.udv_scale.cxLeftScale; rcP->top+=3*dmp->GrData.udv_panel.cyScale/2; /*mouse position*/ mouse_row=(pt->y-rcP->top)/dmp->GrData.udv_font.LineHeight+VScroll; mouse_col=(pt->x-rcP->left)/dmp->GrData.udv_font.ColWidth+HScroll; bFound=FALSE; for(i=0;iMSA_d.pgp_l.nBsp;i++){ /*use the first ParaG of each sequence and mouse_row to find row (==sequence) number; then go though the ParaG list of that sequence to find The ParaG, using mouse_col*/ pgp=(ParaGPtr)(dmp->MSA_d.pgp_l.TableHead[i]->data.ptrvalue); if (mouse_row>=pgp->StartLine && mouse_row<=(pgp->StartLine+pgp->nLines-1)){ vnp=dmp->MSA_d.pgp_l.TableHead[i]; *ParaGLine_Num = i + 1; while(vnp){ pgp=(ParaGPtr)vnp->data.ptrvalue; if (mouse_col>=pgp->StartLetter && mouse_col<=pgp->StopLetter){ bFound=TRUE; TheParaG=pgp; break; } vnp=vnp->next; } if (bFound) break; } } /*ok : the mouse is inside a ParaG*/ if (bFound){ *cur_pgp=TheParaG; /*where is the mouse in the ParaG ?*/ *uWhere=PGP_REGION_NOWHERE; if (TheParaG->ScaleStyle==SCALE_POS_NONE) diff=0; else diff=1; if (mouse_row==(TheParaG->StartLine+diff)){ *uWhere=PGP_REGION_SEQ; } else if (mouse_row>(TheParaG->StartLine+diff) && mouse_row<=(pgp->StartLine+pgp->nLines-1)){ *uWhere=PGP_REGION_FEAT; } /*a. get Disp Coord*/ *Line_num=mouse_row+1;/*base 1 value*/ *Disp_coord=mouse_col; /*on the Sequence ? Then, get the coords. (BSP, DISP, SEQALIGN)*/ /*PGP_REGION_FEAT is not yet implemented... ;-) */ if (*uWhere==PGP_REGION_SEQ){ /*b. get BSP coord*/ *bsp_coord=DDV_GetBspCoordGivenDispCoord(TheParaG,mouse_col); /*c. get SeqAlign Coord*/ vnp=dmp->MSA_d.pgp_l.RulerDescr; while(vnp){ drdp=(DDVRulerDescrPtr)vnp->data.ptrvalue; if (!drdp->bUnAligned){ diff=mouse_col-drdp->disp_start; if (mouse_col>=drdp->disp_start && mouse_col<=drdp->disp_stop){ *SeqAlign_coord=drdp->align_start+diff; break; } } else{ *SeqAlign_coord=(Int4)-1; } vnp=vnp->next; } } } return(bFound); } /***************************************************************************** Function: DDV_GetCoordsGivenAClick() Purpose: given some graphical info, this function returns bsp_coord, SeqAlign_coord, Disp_coord. Future implementation : will also return eID, iID, idx of a feature (if the nice user clicks on a feature). Parameters: dmp; panel main data block rcP; panel size pt; mouse position bsp_coord, SeqAlign_coord, Disp_coord,Line_num; return values uWhere; where the mouse is in a ParaG Note : all but Line_num are zero-based values. Line_num is a one-based value. Return value: TRUE if the user clicks within a ParaG (see also bsp_coord, SeqAlign_coord, Disp_coord, uWhere). NOTE : if the function returns FALSE then bsp_coord, SeqAlign_coord, Line_num, Disp_coord and uWhere are undefined ! *****************************************************************************/ static Boolean DDV_GetCoordsGivenAClick(DdvMainPtr dmp, RecT * rcP, PoinT * pt, Int4Ptr bsp_coord, Int4Ptr SeqAlign_coord, Int4Ptr Disp_coord, Int4Ptr Line_num, Int4Ptr ParaGLine_Num, Uint1Ptr uWhere, ParaGPtr PNTR cur_pgp) { /* return coordinates for the current scroll position */ return(DDV_GetCoordsGivenAClickAndScrollPos(dmp, rcP, pt, dmp->GrData.udv_hscrl.ScrollPos, dmp->GrData.udv_vscrl.ScrollPos, bsp_coord, SeqAlign_coord, Disp_coord, Line_num, ParaGLine_Num, uWhere, cur_pgp)); } /***************************************************************************** Function: DDV_AutoHScroll() Purpose: used from drag/hold mouse to auto-scroll the panel horizontally when the mouse reaches the left/right borders of the panel Return value: none *****************************************************************************/ static void DDV_AutoHScroll(DdvMainPtr dmp,Int4 Disp_coord) { Int4 from_col,to_col,from_row,to_row,old_pos; BaR hsb; DDV_GetCurrentDispRange(dmp->hWndDDV,&(dmp->GrData),dmp->MSA_d.pgp_l.LengthAli, &from_col,&to_col,&from_row,&to_row); hsb = GetSlateHScrollBar ((SlatE) dmp->hWndDDV); old_pos=GetBarValue(hsb); if (Disp_coord>=to_col){/*scroll to the right*/ SetValue(hsb,old_pos+1); } else if (Disp_coord<=from_col){ SetValue(hsb,old_pos-1); } } /***************************************************************************** Function: DDV_AutoVScroll() Purpose: used from drag/hold mouse to auto-scroll the panel vertically when the mouse reaches the top/bottom borders of the panel Return value: none *****************************************************************************/ static void DDV_AutoVScroll(DdvMainPtr dmp,Int4 Line_num) { Int4 from_col,to_col,from_row,to_row,old_pos; BaR vsb; DDV_GetCurrentDispRange(dmp->hWndDDV,&(dmp->GrData),dmp->MSA_d.pgp_l.LengthAli, &from_col,&to_col,&from_row,&to_row); vsb = GetSlateVScrollBar ((SlatE) dmp->hWndDDV); old_pos=GetBarValue(vsb); if (Line_num>=(to_row-1)){/*scroll down*/ SetValue(vsb,old_pos+1); } else if (Line_num<=(from_row+1)){/*scroll up*/ SetValue(vsb,old_pos-1); } } /***************************************************************************** Function: DDV_DispSelRangeInStatus() Purpose: display position while selection is in progress. (mouse mode : selection) Return value: none *****************************************************************************/ static void DDV_DispSelRangeInStatus(PrompT InfoPanel,Int4 bsp_start, Int4 bsp_stop, Int4 line_num,CharPtr szSeqName) { Char szText[250]; sprintf(szText,"Selection : %s, [%i]:[%i..%i]",szSeqName,line_num, bsp_start,bsp_stop); SetTitle(InfoPanel,szText); } /***************************************************************************** Function: DDV_DispPositionInStatus() Purpose: display position (mouse mode : query). Return value: none *****************************************************************************/ NLM_EXTERN void DDV_DispPositionInStatus(PrompT InfoPanel,Int4 bsp_pos, Int4 line_num,CharPtr szSeqName) { Char szText[250]; sprintf(szText,"Position : %s, [%i]:[%i]",szSeqName,line_num,bsp_pos); SetTitle(InfoPanel,szText); } static void DDV_DispStatus(DdvMainPtr dmp, Int4 Line_num_stop, Int4 Disp_coord_start, Int4 Disp_coord_stop) { /***************************************************************************** Function: DDV_DispStatus() Purpose: display position while selection is in progress. (mouse mode : selection) Return value: none *****************************************************************************/ DdvMainWinPtr mWin_d; Int4 ParaGLine_num, bsp_start, bsp_stop; ParaGPtr pgp; char szAccess[21]; mWin_d = (DdvMainWinPtr) GetObjectExtra(dmp->hParent); if (mWin_d != NULL) { ParaGLine_num = DDV_GetParaGLineNumGivenLineNum(dmp, Line_num_stop); if (ParaGLine_num != -1) { DDV_GetSeqNameGivenRow(dmp->MSA_d.pgp_l.TableHead, ParaGLine_num, szAccess); pgp = DDV_GetPGPGivenRowAndCol(dmp, Line_num_stop, Disp_coord_stop); bsp_stop = DDV_GetBspCoordGivenDispCoord(pgp, Disp_coord_stop); if (dmp->MouseMode == DDV_MOUSEMODE_SELECT || dmp->MouseMode == DDV_MOUSEMODE_SELECT_ONE_ROW) { pgp = DDV_GetPGPGivenRowAndCol(dmp, Line_num_stop, Disp_coord_start); bsp_start = DDV_GetBspCoordGivenDispCoord(pgp, Disp_coord_start); DDV_DispSelRangeInStatus(mWin_d->InfoPanel, bsp_start+1, bsp_stop+1, ParaGLine_num, szAccess); } else { DDV_DispPositionInStatus(mWin_d->InfoPanel, bsp_stop+1, ParaGLine_num, szAccess); } } } } /***************************************************************************** Function: DDV_GetSeqNameGivenRow() Purpose: get a sequence number, given a list of ParaG and a row number Note: row_num is a one-based value; this value must be in the range 0 to nBsp. (I don't check that here, so be carefull when calling this function) Return value: - *****************************************************************************/ NLM_EXTERN void DDV_GetSeqNameGivenRow(ValNodePtr * ParaG_List, Int4 row_num, CharPtr szSeqName) { SeqIdPtr sip; ParaGPtr pgp; BioseqPtr bsp; pgp=(ParaGPtr)(ParaG_List[row_num-1]->data.ptrvalue); /*get a name*/ bsp = BioseqLockById(pgp->sip); if(bsp) { /* get name but not gi */ sip = SeqIdFindBestAccession(bsp->id); BioseqUnlock(bsp); } if (!sip) sip = SeqIdFindBest(pgp->sip, 0); SeqIdWrite(sip, szSeqName,PRINTID_TEXTID_ACCESSION, 20); } /***************************************************************************** Function: DDV_SendBSPSelectMsg_OLD() Purpose: send a message to select a range of letters on a bioseq. Return value: none *****************************************************************************/ static void DDV_SendBSPSelectMsg_OLD(DdvMainPtr dmp,Int4 bsp_coord,Int4 SeqAlign_coord, Int4 first_Disp_coord, Int4 Disp_coord,Int4 Line_num,Int4 ParaGLine_Num, ParaGPtr cur_pgp,PoinT * pt, Boolean Display) { Int4 first_bsp_coord, bsp_pos; Uint1 direction;/*use to tell ObjMgr the direction of the mouse (left,right)*/ SeqLocPtr slp;/*to send an AlsoSelectMsg*/ Uint2 bsp_eID; Uint4 bsp_iID; Boolean bDeselectAll=TRUE; DdvMainWinPtr dmwp; /*analyse the bsp coords*/ if (bsp_coord==(Int4)-1){/*this is a gap*/ dmp->ms.oldPos=dmp->ms.newPos=*pt; dmp->ms.old_row=Line_num; dmp->ms.old_col=Disp_coord; dmp->ms.old_pgp=cur_pgp; return; } /*get the very first click (from DDV_ClickProc)*/ first_bsp_coord= DDV_GetBspCoordGivenDispCoord(dmp->ms.first_pgps[Line_num-1], dmp->ms.first_cols[Line_num-1]); if (first_bsp_coord==(Int4)-1){/*the first time the user clicked, it was on a gap*/ /*if we are in this scope, that means we have a bsp coord*/ first_bsp_coord=bsp_coord; dmp->ms.first_cols[Line_num-1]=Disp_coord; dmp->ms.first_pgps[Line_num-1]=cur_pgp; } bsp_pos=bsp_coord; if (ctrlKey || shftKey) bDeselectAll=FALSE; /*the mouse is moving to the left or to the right ?*/ /*don't forget to check the strand... ;-) */ if (AlnMgrGetNthStrand(dmp->MSA_d.pgp_l.sap, ParaGLine_Num)==Seq_strand_plus){ if (dmp->ms.oldPos.xx) direction=Seq_strand_plus; else direction=Seq_strand_minus; } else{ if (dmp->ms.oldPos.x>pt->x) direction=Seq_strand_minus; else direction=Seq_strand_plus; } /*'from' (first_bsp_coord) always less than 'to' (bsp_coord)*/ if (first_bsp_coord>bsp_coord) swap(&first_bsp_coord,&bsp_coord); /*save the new position*/ dmp->ms.oldPos=dmp->ms.newPos=*pt; dmp->ms.old_row=Line_num; dmp->ms.old_col=Disp_coord; dmp->ms.old_pgp=cur_pgp; /*now, we can send the Select message*/ /* first_pgp, old_pgp & cur_pgp have the same sip... they are on a same row; I can use one of them*/ slp = SeqLocIntNew (first_bsp_coord, bsp_coord, direction, cur_pgp->sip); UDV_DecodeIdxFeat (dmp->MSA_d.pgp_l.entitiesTbl[ParaGLine_Num-1],&bsp_eID,&bsp_iID); if (bsp_eID!=0 && bsp_iID!=0 && slp){ /*update InfoPanel*/ dmwp=(DdvMainWinPtr)GetObjectExtra(dmp->hParent); if (dmwp){ Char szAccess[21]; DDV_GetSeqNameGivenRow(dmp->MSA_d.pgp_l.TableHead, ParaGLine_Num, szAccess); switch(dmp->MouseMode){ case DDV_MOUSEMODE_SELECT: case DDV_MOUSEMODE_SELECT_ONE_ROW: if (Display) { DDV_DispSelRangeInStatus(dmwp->InfoPanel,first_bsp_coord+1, bsp_coord+1,ParaGLine_Num,szAccess);/*+1 : switch to one-based value*/ } break; case DDV_MOUSEMODE_QUERY: case DDV_MOUSEMODE_EDIT: DDV_DispPositionInStatus(dmwp->InfoPanel, bsp_pos+1,ParaGLine_Num,szAccess);/*+1 : switch to one-based value*/ break; } } /*send the message*/ if (dmp->MouseMode==DDV_MOUSEMODE_SELECT || dmp->MouseMode==DDV_MOUSEMODE_SELECT_ONE_ROW){ ObjMgrAlsoSelect (bsp_eID, bsp_iID, OBJ_BIOSEQ,OM_REGION_SEQLOC, slp); } } else { if (slp) SeqLocFree(slp); } } /***************************************************************************** Function: DDV_SendBSPSelectMsg() Purpose: send a message to select a range of letters on a bioseq. I've rewritten this. Hope I did it right. Dave H. Return value: none *****************************************************************************/ static void DDV_SendBSPSelectMsg(DdvMainPtr dmp, Int4 col_start, Int4 col_stop, Int4 row, Boolean Display) { Int4 bsp_coord_start, bsp_coord_stop, ParaGLine_Num, col; Uint1 direction;/*used to tell ObjMgr the direction of the mouse (left,right)*/ SeqLocPtr slp;/*to send an AlsoSelectMsg*/ Uint2 bsp_eID; Uint4 bsp_iID; Boolean bDeselectAll=TRUE; ParaGPtr pgp; DdvMainWinPtr dmwp; if (col_start > col_stop) swap(&col_start, &col_stop); /* calculate bsp_coord_start */ for (col=col_start; col<=col_stop; col++) { pgp = DDV_GetPGPGivenRowAndCol(dmp, row, col); bsp_coord_start = DDV_GetBspCoordGivenDispCoord(pgp, col); if (bsp_coord_start != -1) break; } /* calculate bsp_coord_stop */ for (col=col_stop; col>=col_start; col--) { pgp = DDV_GetPGPGivenRowAndCol(dmp, row, col); bsp_coord_stop = DDV_GetBspCoordGivenDispCoord(pgp, col); if (bsp_coord_stop != -1) break; } ParaGLine_Num = DDV_GetParaGLineNumGivenLineNum(dmp, row); if (ctrlKey || shftKey) bDeselectAll=FALSE; /*the mouse is moving to the left or to the right ?*/ /*don't forget to check the strand... ;-) */ if (AlnMgrGetNthStrand(dmp->MSA_d.pgp_l.sap, ParaGLine_Num)==Seq_strand_plus) { direction=Seq_strand_plus; } else { direction=Seq_strand_minus; } /*now, we can send the Select message*/ /* first_pgp, old_pgp & cur_pgp have the same sip... they are on a same row; I can use one of them*/ slp = SeqLocIntNew (bsp_coord_start, bsp_coord_stop, direction, pgp->sip); UDV_DecodeIdxFeat (dmp->MSA_d.pgp_l.entitiesTbl[ParaGLine_Num-1],&bsp_eID,&bsp_iID); if (bsp_eID!=0 && bsp_iID!=0 && slp){ /*update InfoPanel*/ dmwp=(DdvMainWinPtr)GetObjectExtra(dmp->hParent); if (dmwp){ Char szAccess[21]; DDV_GetSeqNameGivenRow(dmp->MSA_d.pgp_l.TableHead, ParaGLine_Num, szAccess); switch(dmp->MouseMode){ case DDV_MOUSEMODE_SELECT: case DDV_MOUSEMODE_SELECT_ONE_ROW: if (Display) { DDV_DispSelRangeInStatus(dmwp->InfoPanel, bsp_coord_start+1, bsp_coord_stop+1, ParaGLine_Num, szAccess); /*+1 : switch to one-based value*/ } break; case DDV_MOUSEMODE_QUERY: case DDV_MOUSEMODE_EDIT: DDV_DispPositionInStatus(dmwp->InfoPanel, bsp_coord_stop+1, ParaGLine_Num, szAccess);/*+1 : switch to one-based value*/ break; } } /*send the message*/ if (dmp->MouseMode==DDV_MOUSEMODE_SELECT || dmp->MouseMode==DDV_MOUSEMODE_SELECT_ONE_ROW){ ObjMgrAlsoSelect (bsp_eID, bsp_iID, OBJ_BIOSEQ, OM_REGION_SEQLOC, slp); } } else { if (slp) SeqLocFree(slp); } } /***************************************************************************** Functions: DDV_ClickProcUpper() and DDV_ClickProcLower() Purpose: mouse click funcions attached to the upper and lower panels in 2-panel mode. They switch focus between the upper and lower panels, then call the main DDV_ClickProc. Parameters: p; panel handle (currently unused) pt; new mouse position Return value: none *****************************************************************************/ NLM_EXTERN void DDV_ClickProcUpper(PaneL p, PoinT pt) { DdvMainWinPtr mWin_d; WindoW hWinMain; Boolean tempClick; hWinMain=(WindoW)ParentWindow(p); if (hWinMain==NULL) return; mWin_d = (DdvMainWinPtr) GetObjectExtra (hWinMain); if (mWin_d==NULL) return; mWin_d->hWndDDV = mWin_d->hUpperPanel; DDV_SetMenuFocus(hWinMain); mWin_d->InfoPanel = mWin_d->UpperInfoPanel; tempClick = Nlm_dblClick; /* keep vibrant from resetting double click */ SetTitle(mWin_d->InfoPanel,"Ready !"); SetTitle(mWin_d->LowerInfoPanel,""); Nlm_dblClick = tempClick; DDV_ClickProc(p, pt); } NLM_EXTERN void DDV_ClickProcLower(PaneL p, PoinT pt) { DdvMainWinPtr mWin_d; WindoW hWinMain; Boolean tempClick; hWinMain=(WindoW)ParentWindow(p); if (hWinMain==NULL) return; mWin_d = (DdvMainWinPtr) GetObjectExtra (hWinMain); if (mWin_d==NULL) return; mWin_d->hWndDDV = mWin_d->hLowerPanel; DDV_SetMenuFocus(hWinMain); mWin_d->InfoPanel = mWin_d->LowerInfoPanel; tempClick = Nlm_dblClick; /* keep vibrant from resetting double click */ SetTitle(mWin_d->InfoPanel,"Ready !"); SetTitle(mWin_d->UpperInfoPanel,""); Nlm_dblClick = tempClick; DDV_ClickProc(p, pt); } /***************************************************************************** Function: DDV_ClickProc() Purpose: manage Mouse-Click; this function is designed for the autonomous viewer to manage the InfoPanel and the Features List Dialog Box DON'T USE FOR EXTERNAL SOFTWARE... Parameters: p; panel handle (currently unused) pt; new mouse position Return value: none *****************************************************************************/ NLM_EXTERN void DDV_ClickProc(PaneL p, PoinT pt) { DdvMainPtr dmp; DdvMainWinPtr mWin_d; RecT rcP, rcP2; Int4 bsp_coord, SeqAlign_coord, Disp_coord, Line_num,bsp_start,bsp_stop, old_pos, ParaGLine_Num, VPos, HPos; Int4 from_row, to_row, from_col, to_col; Uint1 uWhere; ParaGPtr cur_pgp=NULL; SeqLocPtr slp; Uint2 bsp_eID; Uint4 bsp_iID; Boolean bDeselectAll=TRUE,bIsAlreadyFullSel; Int4 BlockIndex, Col, NumBlocks; Boolean LeftBoundary, IsUnAligned; DdvMainWinPtr dmwp; BioseqPtr bsp; Char buf[81], szAccess[21]; ParaGPtr pgp; Int4 i, NumRows, ColCnt, Offset, Width; MsaParaGPopListPtr mpplp; SeqAlignPtr sap; DDE_StackPtr dsp; Boolean IsEditable, *pNoGaps, NoGaps, FoundIt; /*get the panel data*/ dmp = (DdvMainPtr) GetObjectExtra(p); if (dmp==NULL) return; mWin_d = (DdvMainWinPtr) GetObjectExtra(dmp->hParent); if (mWin_d == NULL) return; ObjectRect(p,&rcP); if (ctrlKey || shftKey) bDeselectAll=FALSE; /* handle the case when a block is being deleted in DDV */ if (dmp->MouseMode == DDV_MOUSEMODE_DELETEBLOCK) { /* get block index, etc */ if (GetBlockAndAlignment(pt, p, dmp, &BlockIndex, &IsUnAligned, &Col, &Offset, &Width, &rcP)) { /* if block is aligned */ if (!IsUnAligned) { /* create display for single block */ sap = ViewMgr_GetBeginIndexed(dmp->MSA_d.pgp_l.sap); dmp->MSA_d.pgp_l.viewed_sap = dmp->MSA_d.pgp_l.sap; mpplp = DDE_CreateDisplay(sap, BlockIndex, IsUnAligned, &NumBlocks); dsp = DDE_NewStack(mpplp); /* record which block is being edited, etc */ dsp->LaunchBlock = BlockIndex; dsp->NumBlocks = NumBlocks; dsp->IsUnAligned = IsUnAligned; DDE_MergeNodesLists(dsp->pEdit); /* delete block, tell AlnMgr to save edits, redraw DDV */ DDE_DeleteBlock(dsp, 0, FALSE); dmp->dsp = dsp; DDV_SaveEdits(dmp, TRUE); /* free stack */ dsp = DDE_FreeStack(dsp); dmp->dsp = dsp; } } ArrowCursor(); dmp->MouseMode = dmp->SavedMouseMode; } /* handle the click when splitting 2 blocks */ if (dmp->MouseMode == DDV_MOUSEMODE_SPLITBLOCK) { FoundIt = FALSE; /* adjust x position so vertical bar jumps when mouse is on center of char */ pt.x -= dmp->GrData.udv_font.ColWidth/2; /* if user clicked on an aligned block */ if (GetBlockAndAlignment(pt, p, dmp, &BlockIndex, &IsUnAligned, &Col, &Offset, &Width, &rcP)) { /* save col where vertical bar was last drawn */ dmp->SaveCol = Col; /* draw vertical bar after this column */ HPos = DDV_GetHPixelPosGivenColNumber(dmp, rcP, Col); UDV_draw_vertical_bar(rcP, HPos, FALSE); dmp->ms.Action_type = MS_ACTION_SPLIT_BLOCK; FoundIt = TRUE; } if (!FoundIt) { ArrowCursor(); } dmp->MouseMode = dmp->SavedMouseMode; } /* handle the 1st click when merging 2 blocks */ /* for the 1st click just need to record the block */ else if (dmp->MouseMode == DDV_MOUSEMODE_MERGEBLOCKS1) { FoundIt = FALSE; /* if mouse is in a valid place, get BlockIndex and alignment status */ if (GetBlockAndAlignment(pt, p, dmp, &BlockIndex, &IsUnAligned, &Col, &Offset, &Width, &rcP)) { if (!IsUnAligned) { dmp->BlockIndex = BlockIndex; dmp->MouseMode = DDV_MOUSEMODE_MERGEBLOCKS2; FoundIt = TRUE; } } if (!FoundIt) { dmp->MouseMode = dmp->SavedMouseMode; ArrowCursor(); } } /* handle the 2nd click when merging 2 blocks */ else if (dmp->MouseMode == DDV_MOUSEMODE_MERGEBLOCKS2) { /* if mouse is in a valid place, get BlockIndex and alignment status */ if (GetBlockAndAlignment(pt, p, dmp, &BlockIndex, &IsUnAligned, &Col, &Offset, &Width, &rcP)) { /* if 2 blocks are next to each other and both aligned */ if ((!IsUnAligned) && (ABS(BlockIndex - dmp->BlockIndex) == 1)) { /* create a stack for the block on the right */ BlockIndex = MAX(BlockIndex, dmp->BlockIndex); sap = ViewMgr_GetBeginIndexed(dmp->MSA_d.pgp_l.sap); dmp->MSA_d.pgp_l.viewed_sap = dmp->MSA_d.pgp_l.sap; mpplp = DDE_CreateDisplay(sap, BlockIndex, IsUnAligned, &NumBlocks); dsp = DDE_NewStack(mpplp); /* record which block is being edited, etc */ dsp->LaunchBlock = BlockIndex; dsp->NumBlocks = NumBlocks; dsp->IsUnAligned = IsUnAligned; DDE_MergeNodesLists(dsp->pEdit); /* if block on right is flush left */ if (DDE_FirstColumnIsAligned(dsp->pEdit)) { /* delete block on right. count number of cols that were in block. */ ColCnt = DDE_DeleteBlock(dsp, 0, FALSE); /* tell AlnMgr to save edits, don't redraw yet */ dmp->dsp = dsp; DDV_SaveEdits(dmp, FALSE); /* free stack for block on right. create stack for block on left */ DDE_FreeStack(dsp); sap = ViewMgr_GetBeginIndexed(dmp->MSA_d.pgp_l.sap); dmp->MSA_d.pgp_l.viewed_sap = dmp->MSA_d.pgp_l.sap; mpplp = DDE_CreateDisplay(sap, BlockIndex-1, IsUnAligned, &NumBlocks); dsp = DDE_NewStack(mpplp); /* record which block is being edited, etc */ dsp->LaunchBlock = BlockIndex-1; dsp->NumBlocks = NumBlocks; dsp->IsUnAligned = IsUnAligned; DDE_MergeNodesLists(dsp->pEdit); DDE_Verify(dsp->pEdit); /* shift right boundary of left block by number cols in right block */ DDE_ShiftRightBoundary(dsp, 0, ColCnt, FALSE); /* tell AlnMgr to save edits, now redraw */ dmp->dsp = dsp; DDV_SaveEdits(dmp, TRUE); } /* free remaining stack */ dsp = DDE_FreeStack(dsp); dmp->dsp = dsp; } } dmp->MouseMode = dmp->SavedMouseMode; ArrowCursor(); } /* handle the case when we're launching the editor on a block */ else if (dmp->MouseMode == DDV_MOUSEMODE_LAUNCHEDITOR) { /* if mouse is in a valid place, get BlockIndex and alignment status */ if (GetBlockAndAlignment(pt, p, dmp, &BlockIndex, &IsUnAligned, &Col, &Offset, &Width, &rcP)) { /* don't allow editing when there are gaps and no gaps are allowed */ pNoGaps = (Boolean*) GetAppProperty("dde_nogaps"); if (pNoGaps == NULL) NoGaps = TRUE; else NoGaps = *pNoGaps; IsEditable = AlnMgrIsEditable(dmp->MSA_d.pgp_l.sap); if (!(IsEditable == AM_EDITGAPS && NoGaps) && IsEditable) { ViewMgr_MakeMultiple(dmp->MSA_d.pgp_l.sap); } else { Message(MSG_OK, "%s", "Unable to convert this alignment\n into an editable form."); dmp->MouseMode = dmp->SavedMouseMode; ArrowCursor(); return; } /* get pointer to original seqAlign */ sap = ViewMgr_GetBeginIndexed(dmp->MSA_d.pgp_l.sap); /* create display for editor */ mpplp = DDE_CreateDisplay(sap, BlockIndex, IsUnAligned, &NumBlocks); mpplp->viewed_sap = dmp->MSA_d.pgp_l.sap; /* create the stack used by editor */ dsp = DDE_NewStack(mpplp); DDE_MergeNodesLists(dsp->pEdit); /* record which block is being edited, etc */ dsp->LaunchBlock = BlockIndex; dsp->NumBlocks = NumBlocks; dsp->IsUnAligned = IsUnAligned; /* hide the rows in DDE that are hidden in DDV */ NumRows = dsp->pEdit->TotalNumRows; for (i=0; iMSA_d.pgp_l.sap, i+1) == -1) { DDE_HideRow(dsp, i, FALSE); } } DDE_Add(dsp); dsp->SomethingToSave = FALSE; /* launch the editor as a slave */ SetAppProperty("ddeinterndata",(void*)dsp); GatherProcLaunch(OMPROC_EDIT, FALSE, dmp->MSA_d.entityID, dmp->MSA_d.itemID, OBJ_SEQALIGN, 0, 0, OBJ_SEQALIGN, 0); RemoveAppProperty("ddeinterndata"); } dmp->MouseMode = dmp->SavedMouseMode; ArrowCursor(); } /* handle the case when we're creating an aligned block */ else if (dmp->MouseMode == DDV_MOUSEMODE_CREATEBLOCK) { ObjectRect(p, &rcP); InsetRect(&rcP,4,4); DDV_AdjustDrawingRect(&rcP,&(dmp->GrData.udv_font),dmp); rcP.left += dmp->GrData.udv_panel.cxName + dmp->GrData.udv_scale.cxLeftScale; /* if the point is in a valid spot */ if (PtInRect(pt, &rcP)) { ObjectRect(p, &rcP); Col = DDV_GetColNumberGivenMousePos(dmp, rcP, pt); /* and the column's legal */ if ((Col >= 0) && (Col < dmp->MSA_d.pgp_l.LengthAli)) { /* and there is no aligned block already */ if (DDE_GetNumBlocks(dmp->dsp->pEdit) == 0) { /* save start col */ dmp->dsp->FromCol = Col; /* save col where vertical bar was last drawn */ dmp->dsp->SaveCol = Col; /* draw vertical bar before and after this column */ HPos = DDV_GetHPixelPosGivenColNumber(dmp, rcP, dmp->dsp->SaveCol); UDV_draw_vertical_bar(rcP, HPos, TRUE); HPos -= dmp->GrData.udv_font.ColWidth; UDV_draw_vertical_bar(rcP, HPos, TRUE); dmp->ms.Action_type = MS_ACTION_CREATE_BLOCK; } else { dmp->MouseMode = dmp->SavedMouseMode; ArrowCursor(); } } else { dmp->MouseMode = dmp->SavedMouseMode; ArrowCursor(); } } else { dmp->MouseMode = dmp->SavedMouseMode; ArrowCursor(); } } /*the mouse is located in a ParaG ?*/ /*if YES : the user is selecting either sequence letter(s) or a feature*/ else if ((pt.x>(rcP.left+dmp->GrData.udv_panel.cxName+ dmp->GrData.udv_scale.cxLeftScale)) && (pt.y>(rcP.top+dmp->GrData.udv_panel.cyScale))) { /*get the ParaG list and look for the ParaG where the mouse is located*/ /*note : only implemented for DDV_DISP_HORZ type of display...*/ if (dmp->MSA_d.pgp_l.DisplayType==DDV_DISP_HORZ){ if (DDV_GetCoordsGivenAClick(dmp,&rcP,&pt, &bsp_coord,&SeqAlign_coord,&Disp_coord,&Line_num, &ParaGLine_Num,&uWhere,&cur_pgp)){ if (uWhere==PGP_REGION_SEQ){ if (bDeselectAll && (dmp->MouseMode==DDV_MOUSEMODE_SELECT || dmp->MouseMode==DDV_MOUSEMODE_SELECT_ONE_ROW)) ObjMgrDeSelectAll (); if (shftKey && bsp_coord!=(Int4)-1){ UDV_DecodeIdxFeat (dmp->MSA_d.pgp_l.entitiesTbl[ParaGLine_Num-1], &bsp_eID,&bsp_iID); if (bsp_eID!=0 && bsp_iID!=0){ slp=DDV_GetClosetSeqLocGivenBspPos(cur_pgp->sip,bsp_eID, bsp_iID, bsp_coord, &old_pos, TRUE); if (slp){ if (dmp->MouseMode==DDV_MOUSEMODE_SELECT || dmp->MouseMode==DDV_MOUSEMODE_SELECT_ONE_ROW) ObjMgrAlsoSelect (bsp_eID, bsp_iID, OBJ_BIOSEQ,OM_REGION_SEQLOC, slp); if (old_pos!=(Int4)-1) Disp_coord=old_pos; } } dmp->ms.oldPos=pt; dmp->ms.Action_type=MS_ACTION_SELECT_SEQ; return; } /* display info about residues that's clicked */ if (ParaGLine_Num != -1) { DDV_GetSeqNameGivenRow(dmp->MSA_d.pgp_l.TableHead, ParaGLine_Num, szAccess); DDV_DispPositionInStatus(mWin_d->InfoPanel, bsp_coord+1, ParaGLine_Num, szAccess); } /*save the positions */ dmp->ms.oldPos=pt; dmp->ms.newPos=pt; dmp->ms.Action_type=MS_ACTION_SELECT_SEQ; dmp->ms.old_row=Line_num; dmp->ms.old_col=Disp_coord; dmp->ms.old_pgp=cur_pgp; dmp->ms.first_row=Line_num; dmp->ms.first_col=Disp_coord; dmp->ms.last_row=Line_num; dmp->ms.last_col=Disp_coord; /* show outline of highlighted area */ CopyMode(); DrawOutline(p, Line_num, Disp_coord, Line_num, Disp_coord, TRUE); if (dmp->ms.first_cols == NULL) { NumRows = dmp->MSA_d.pgp_l.nBsp; dmp->ms.first_cols = MemNew(NumRows * sizeof(Int4)); dmp->ms.first_pgps = MemNew(NumRows * sizeof(ParaGPtr)); } dmp->ms.first_cols[Line_num-1]=Disp_coord; dmp->ms.first_pgps[Line_num-1]=cur_pgp; dmp->ms.first_point=pt; dmp->ms.first_HScroll=dmp->GrData.udv_hscrl.ScrollPos; dmp->ms.first_VScroll=dmp->GrData.udv_vscrl.ScrollPos; dmp->ms.old_HScroll = dmp->GrData.udv_hscrl.ScrollPos; dmp->ms.old_VScroll = dmp->GrData.udv_vscrl.ScrollPos; /*update caret pos, if needed only*/ if (dmp->MouseMode==DDV_MOUSEMODE_EDIT){ dmp->dci.old_row=dmp->dci.new_row; dmp->dci.old_col=dmp->dci.new_col; } /* if we're in the editor and mousemode is query */ /* click and drag on sequence will cause the whole row to shift */ if (dmp->bEditor) { if (dmp->MouseMode == DDV_MOUSEMODE_QUERY) { /* make sure column is legit */ DDV_GetCurrentDispRange(dmp->hWndDDV,&(dmp->GrData), dmp->MSA_d.pgp_l.LengthAli,&from_col,&to_col,&from_row,&to_row); /* Don't shift row if clicking on first or last column of */ /* display because then the screen scrolls */ if (((Disp_coord>from_col) && (Disp_coord<=to_col)) || (Disp_coord==0)) { /* draw a double rectangle around the selected char */ /* to mark the from spot */ ObjectRect(p, &rcP); VPos = DDV_GetVPixelPosGivenRowNumber(dmp, rcP, Line_num-1); /* 1-based */ HPos = DDV_GetHPixelPosGivenColNumber(dmp, rcP, Disp_coord); /* 0-based */ rcP2.left = HPos - dmp->GrData.udv_font.ColWidth; rcP2.right = HPos; rcP2.top = VPos - dmp->GrData.udv_font.LineHeight; rcP2.bottom = VPos; UDV_draw_rectangle(rcP2, FALSE); InsetRect(&rcP2, 1, 1); UDV_draw_rectangle(rcP2, FALSE); CrossCursor(); dmp->dsp->FromCol = Disp_coord; dmp->dsp->FromRow = Line_num-1; dmp->dsp->SaveCol = Disp_coord; dmp->dsp->SaveRow = Line_num-1; dmp->ms.Action_type = MS_ACTION_SHIFT_ROW; } } } /*select a single letter*/ if (dmp->MouseMode == DDV_MOUSEMODE_SELECT || dmp->MouseMode == DDV_MOUSEMODE_SELECT_ONE_ROW) { /* DDV_SendBSPSelectMsg(dmp, bsp_coord, SeqAlign_coord, Disp_coord, Line_num, ParaGLine_Num, cur_pgp, &pt, TRUE); */ } } } } } /*the mouse is located within the Name list region (left of ParaG) ?*/ else if (pt.x>=dmp->GrData.udv_panel.cxName-1 && pt.x<=dmp->GrData.udv_panel.cxName+3){ rcP.left=5*dmp->GrData.udv_font.cxChar; /*min value*/ rcP.right=2*PANEL_NAME_WIDTH*dmp->GrData.udv_font.cxChar;/*max val*/ pt.x=dmp->GrData.udv_panel.cxName; dmp->ms.oldPos=pt; dmp->ms.newPos=pt; dmp->ms.rcClip=rcP; dmp->ms.Action_type=MS_ACTION_RESIZE_WIN; InvertMode(); UDV_draw_double_cursor(dmp->ms.rcClip, dmp->ms.oldPos); CrossCursor(); } /*the mouse is located on a sequence name ?*/ else if (pt.xGrData.udv_panel.cxName && pt.y>(rcP.top+dmp->GrData.udv_panel.cyScale)){ Line_num=DDV_GetRowGivenMousePos(dmp, &rcP, &pt,&ParaGLine_Num); if (Line_num!=(Int4)-1){ UDV_DecodeIdxFeat (dmp->MSA_d.pgp_l.entitiesTbl[ParaGLine_Num-1], &bsp_eID,&bsp_iID); if (dblClick /*&& !dmp->bEditor*/){/*load the sequence viewer on that sequence*/ { SAM_ViewGlobal vg; MemSet(&vg, 0, sizeof(SAM_ViewGlobal)); vg.pCGlobal = dmp->Globals.colorp; vg.Row = Line_num; if(!dmp->bEditor) vg.MasterViewer = SAMVIEWDDV; else vg.MasterViewer = SAMVIEWDDE; SetAppProperty(SAM_ViewString, &vg); GatherSpecificProcLaunch(0, "OneD-Viewer", OMPROC_VIEW, FALSE, bsp_eID, bsp_iID, OBJ_BIOSEQ); RemoveAppProperty(SAM_ViewString); } } else{ if (dmp->bEditor){ WindoW temport; dmp->deri.curEditRow=ParaGLine_Num-1; rcP.left=0; rcP.right=rcP.left+dmp->GrData.udv_panel.cxName; temport=SavePort(ParentWindow(p)); Select(p); InvalRect(&rcP); Update(); RestorePort(temport); /* record the row that's moving */ dmp->dsp->FromRow = Line_num - 1; /* keep track of where the underline is */ dmp->dsp->SaveRow = Line_num - 1; dmp->ms.Action_type = MS_ACTION_MOVE_ROW; /* make a rectangle of the sequence names region */ ObjectRect(p,&rcP); rcP2.left = rcP.left; rcP2.right = rcP.left + dmp->GrData.udv_panel.cxName - 10; rcP2.top = rcP.top; rcP2.bottom = rcP.bottom; /* draw the underline */ VPos = DDV_GetVPixelPosGivenRowNumber(dmp, rcP2, Line_num-1); UDV_draw_horizontal_line(rcP2, VPos); CrossCursor(); } else /* not editor */ { dmwp=(DdvMainWinPtr)GetObjectExtra(dmp->hParent); if(dmwp) { pgp=(ParaGPtr)(dmp->MSA_d.pgp_l.TableHead[Line_num-1]->data.ptrvalue); bsp=BioseqLockById(pgp->sip); CreateDefLine(NULL,bsp,buf,80,0,NULL,NULL); BioseqUnlock(bsp); SetTitle(dmwp->InfoPanel,buf); } } } } } /*the mouse is located just on the left of a sequence ? If true, select the full sequence*/ else if ((pt.x>=dmp->GrData.udv_panel.cxName+3) /*after the name of the sequence ?*/ && (pt.x<=dmp->GrData.udv_panel.cxName+3+dmp->GrData.udv_scale.cxLeftScale+ dmp->GrData.udv_font.cxChar) /*before the sequence ?*/ && (dmp->MouseMode==DDV_MOUSEMODE_SELECT || dmp->MouseMode==DDV_MOUSEMODE_SELECT_ONE_ROW)/*valid only if selection mode*/ ){ if (pt.y>(rcP.top+dmp->GrData.udv_panel.cyScale)){ /*get the ParaG list and look for the ParaG where the mouse is located*/ /*note : only implemented for DDV_DISP_HORZ type of display...*/ if (dmp->MSA_d.pgp_l.DisplayType==DDV_DISP_HORZ){ Line_num=DDV_GetRowGivenMousePos(dmp, &rcP, &pt,&ParaGLine_Num); if (Line_num!=(Int4)-1){ /*get min,max coord. of BSP*/ UDV_GetBspRangeinPGPList(dmp->MSA_d.pgp_l.TableHead[ParaGLine_Num-1], &bsp_start,&bsp_stop); if (bsp_start!=INT4_MAX && bsp_stop!=INT4_MIN){ /*now, we can send the Select message*/ /* first_pgp, old_pgp & cur_pgp have the same sip... they are on a same row; I can use one of them*/ cur_pgp=(ParaGPtr)(dmp->MSA_d.pgp_l.TableHead[ParaGLine_Num-1]->data.ptrvalue); slp = SeqLocIntNew (bsp_start, bsp_stop, Seq_strand_plus, cur_pgp->sip); UDV_DecodeIdxFeat (dmp->MSA_d.pgp_l.entitiesTbl[ParaGLine_Num-1], &bsp_eID,&bsp_iID); if (bsp_eID!=0 && bsp_iID!=0 && slp){ bIsAlreadyFullSel=DDV_IsFullBspAlreadySel(bsp_eID,bsp_iID, bsp_start,bsp_stop); if (!bIsAlreadyFullSel){ if (!bDeselectAll){ ObjMgrAlsoSelect (bsp_eID, bsp_iID, OBJ_BIOSEQ,OM_REGION_SEQLOC, slp); } else{ ObjMgrDeSelectAll (); ObjMgrSelect (bsp_eID, bsp_iID, OBJ_BIOSEQ,OM_REGION_SEQLOC, slp); } } else{ if (bDeselectAll) ObjMgrDeSelectAll (); ObjMgrDeSelect (bsp_eID, bsp_iID, OBJ_BIOSEQ,OM_REGION_SEQLOC, slp); } } } dmp->ms.Action_type=MS_ACTION_SELECT_FULL_SEQ; } } } } /* if the mouse is located on one of the vertical bars, on top, that */ /* mark an alignment boundary */ else if (OnAlignmentBoundary(pt, p, dmp, &BlockIndex, &LeftBoundary, &Col, &HPos)) { /* record the boundary and block that are being moved */ dmp->dsp->FromCol = Col; dmp->dsp->BlockIndex = BlockIndex; dmp->dsp->LeftBoundary = LeftBoundary; /* record the column of the last drawn vertical bar */ dmp->dsp->SaveCol = Col; dmp->ms.Action_type = MS_ACTION_SHIFT_BOUNDARY; /* draw a dotted outline of the vertical bar */ ObjectRect(p, &rcP); UDV_draw_vertical_bar(rcP, HPos, TRUE); CrossCursor(); } else{/*click outside "special" regions : deselect everything*/ if (dmp->MouseMode==DDV_MOUSEMODE_SELECT || dmp->MouseMode==DDV_MOUSEMODE_SELECT_ONE_ROW) ObjMgrDeSelectAll (); /*this line if for cn3d only*/ ObjMgrSendMsg(OM_MSG_MOUSEUP, dmp->MSA_d.entityID, dmp->MSA_d.itemID, OBJ_SEQALIGN); } if (dmp->bEditor) { DDV_GreyOut(mWin_d, DDE_AtStartOfStack(dmp->dsp), DDE_AtEndOfStack(dmp->dsp)); } } static Boolean GetBlockAndAlignmentForCol(DdvMainPtr dmp, Int4 Col, Int4* pBlockIndex, Boolean* pIsUnAligned, Int4* pOffset, Int4* pWidth) { /***************************************************************************** * get the BlockIndex and Alignment status for Col. *****************************************************************************/ /* if Col is legal */ if ((Col >= 0) && (Col < dmp->MSA_d.pgp_l.LengthAli)) { /* get the block or unaligned-region index */ if (DDE_IsColValid(&(dmp->MSA_d.pgp_l), Col, pBlockIndex, pIsUnAligned, pOffset, pWidth)) { return(TRUE); } } *pBlockIndex = -1; *pIsUnAligned = TRUE; return(FALSE); } static Boolean GetBlockAndAlignment(PoinT pt, PaneL p, DdvMainPtr dmp, Int4* pBlockIndex, Boolean* pIsUnAligned, Int4* pCol, Int4* pOffset, Int4* pWidth, RecT* rcP) { /***************************************************************************** * get the BlockIndex and Alignment status for point pt. *****************************************************************************/ ObjectRect(p, rcP); InsetRect(rcP,4,4); DDV_AdjustDrawingRect(rcP, &(dmp->GrData.udv_font), dmp); rcP->left += dmp->GrData.udv_panel.cxName + dmp->GrData.udv_scale.cxLeftScale; /* if the point is in a valid spot */ if (PtInRect(pt, rcP)) { ObjectRect(p, rcP); *pCol = DDV_GetColNumberGivenMousePos(dmp, *rcP, pt); /* and the column's legal */ if ((*pCol >= 0) && (*pCol < dmp->MSA_d.pgp_l.LengthAli)) { /* get the block or unaligned-region index */ if (DDE_IsColValid(&(dmp->MSA_d.pgp_l), *pCol, pBlockIndex, pIsUnAligned, pOffset, pWidth)) { return(TRUE); } } } *pCol=-1; *pBlockIndex = -1; *pIsUnAligned = TRUE; return(FALSE); } static Boolean RectanglesAreSame(RecT rc1, RecT rc2) { /***************************************************************************** * return TRUE if 2 rectangles are identical. *****************************************************************************/ if (rc1.left != rc2.left) return(FALSE); if (rc1.right != rc2.right) return(FALSE); if (rc1.top != rc2.top) return(FALSE); if (rc1.bottom != rc2.bottom) return(FALSE); return(TRUE); } static void EraseOutline(PaneL p) { /***************************************************************************** * erase the old outline of the region selected for highlighting. *****************************************************************************/ DdvMainPtr dmp; BaR hsb, vsb; Int4 HScroll, VScroll; dmp = (DdvMainPtr) GetObjectExtra(p); if (dmp==NULL) return; hsb = GetSlateHScrollBar((SlatE) dmp->hWndDDV); vsb = GetSlateVScrollBar((SlatE) dmp->hWndDDV); /* save current scroll positions, set scroll positions to saved scroll positions */ HScroll = dmp->GrData.udv_hscrl.ScrollPos; VScroll = dmp->GrData.udv_vscrl.ScrollPos; SetValue(hsb, dmp->ms.old_HScroll); SetValue(vsb, dmp->ms.old_VScroll); /* erase the old rectangle */ InvertMode(); UDV_draw_rectangle(dmp->ms.outline, FALSE); /* restore scroll positions */ SetValue(hsb, HScroll); SetValue(vsb, VScroll); } static RecT DrawOutline(PaneL p, Int4 Line_num_start, Int4 Disp_coord_start, Int4 Line_num_stop, Int4 Disp_coord_stop, Boolean Draw) { /***************************************************************************** * use current scroll postions. *****************************************************************************/ RecT rcP2; DdvMainPtr dmp; rcP2.left = rcP2.right = rcP2.top = rcP2.bottom = 0; dmp = (DdvMainPtr) GetObjectExtra(p); if (dmp==NULL) return(rcP2); return(DrawOutlineGivenScroll(p, Line_num_start, Disp_coord_start, Line_num_stop, Disp_coord_stop, dmp->GrData.udv_vscrl.ScrollPos, dmp->GrData.udv_hscrl.ScrollPos, Draw)); } static RecT DrawOutlineGivenScroll(PaneL p, Int4 Line_num_start, Int4 Disp_coord_start, Int4 Line_num_stop, Int4 Disp_coord_stop, Int4 VScroll, Int4 HScroll, Boolean Draw) { /***************************************************************************** * draw the outline of the region being selected for highlighting. * Line_num_stop and Disp_coord_stop are for the current mouse position. * Line_num_start and Disp_coord_start are for the first click position. * if Draw is FALSE, just return the rectangle and don't draw it. * Line_num's are 1-based. Disp_coord's are 0-based. * treat VScroll and HScroll as the current scroll positions. * return rectangle that's drawn. *****************************************************************************/ RecT rcP, rcP2; DdvMainPtr dmp; Int4 Line_num_stop_save, Disp_coord_stop_save; rcP2.left = rcP2.right = rcP2.top = rcP2.bottom = 0; Line_num_stop_save = Line_num_stop; Disp_coord_stop_save = Disp_coord_stop; dmp = (DdvMainPtr) GetObjectExtra(p); if (dmp==NULL) return(rcP2); if (Line_num_start > Line_num_stop) { swap(&Line_num_start, &Line_num_stop); } if (Disp_coord_start > Disp_coord_stop) { swap(&Disp_coord_start, &Disp_coord_stop); } if (Line_num_start < 1) Line_num_start=1; if (Line_num_stop > dmp->MSA_d.pgp_l.nBsp) Line_num_stop=dmp->MSA_d.pgp_l.nBsp; if (Disp_coord_start < 0) Disp_coord_start=0; if (Disp_coord_stop >= dmp->MSA_d.pgp_l.LengthAli) Disp_coord_stop=dmp->MSA_d.pgp_l.LengthAli; if (dmp->MouseMode==DDV_MOUSEMODE_SELECT || dmp->MouseMode==DDV_MOUSEMODE_SELECT_ONE_ROW) { /* calculate new rectangle */ ObjectRect(p, &rcP); rcP2.top = DDV_GetVPixelPosGivenRowNumber(dmp, rcP, Line_num_start-1); rcP2.bottom = DDV_GetVPixelPosGivenRowNumber(dmp, rcP, Line_num_stop-1); rcP2.left = DDV_GetHPixelPosGivenColNumber(dmp, rcP, Disp_coord_start); rcP2.right = DDV_GetHPixelPosGivenColNumber(dmp, rcP, Disp_coord_stop); rcP2.top -= dmp->GrData.udv_font.LineHeight; rcP2.left -= dmp->GrData.udv_font.ColWidth; if (Draw) { /* make clip region */ InsetRect(&rcP,4,4); DDV_AdjustDrawingRect(&rcP,&(dmp->GrData.udv_font),dmp); rcP.left+=dmp->GrData.udv_panel.cxName+dmp->GrData.udv_scale.cxLeftScale; rcP.top+=3*dmp->GrData.udv_panel.cyScale/2; rcP.bottom+=2; /* so bottom of rectangle not cut */ ClipRect(&rcP); /* draw new rectangle */ UDV_draw_rectangle(rcP2, FALSE); ResetClip(); /* save row and col for current mouse pos */ dmp->ms.last_row = Line_num_stop_save; dmp->ms.last_col = Disp_coord_stop_save; } } return(rcP2); } static Boolean OnAlignmentBoundary(PoinT pt, PaneL p, DdvMainPtr dmp, Int4* pBlockIndex, Boolean* pLeftBoundary, Int4* pCol, Int4* pHPos) { /***************************************************************************** * check if point pt is on one of the vertical bars that mark * alignment boundaries. return TRUE if it is. * whether it's TRUE or not, ... * return BlockIndex indicating which aligned block, * return LeftBoundary = TRUE if p is on a left boundary, * return LeftBoundary = FALSE if p is on a right boundary. * return Col; the display coordinate for the alignment boundary. * return HPos; the horizontal pixel position of the boundary. *****************************************************************************/ RecT rcP, rcBanner; Int4 TopVPos, BotVPos, LeftHPos, RightHPos; Int4 i, NumBlocks; /* this only works in the editor */ if (!dmp->bEditor) return(FALSE); /* make rectangle for banner across top. make it extra wide */ ObjectRect(p, &rcP); DDV_GetVPixelPosOfEmptySpace(dmp, rcP, &TopVPos, &BotVPos); rcBanner = rcP; rcBanner.left += dmp->GrData.udv_panel.cxName + dmp->GrData.udv_scale.cxLeftScale; rcBanner.top = TopVPos-4; rcBanner.bottom = BotVPos+8; rcBanner.left -= 4; /* for each aligned block */ NumBlocks = DDE_GetNumBlocks(dmp->dsp->pEdit); for (i=0; idsp->pEdit, i); LeftHPos = DDV_GetHPixelPosGivenColNumber(dmp, rcP, *pCol); LeftHPos -= dmp->GrData.udv_font.ColWidth; if ((pt.x >= LeftHPos-5) && (pt.x <= LeftHPos+5)) { *pBlockIndex = i; *pLeftBoundary = TRUE; *pHPos = LeftHPos; if (PtInRect(pt, &rcBanner)) return(TRUE); return(FALSE); } /* check if the pt is reasonably close to the right vertical bar */ *pCol = DDE_GetAlignStop(dmp->dsp->pEdit, i); RightHPos = DDV_GetHPixelPosGivenColNumber(dmp, rcP, *pCol); if ((pt.x >= RightHPos-5) && (pt.x <= RightHPos+5)) { *pBlockIndex = i; *pLeftBoundary = FALSE; *pHPos = RightHPos; if (PtInRect(pt, &rcBanner)) return(TRUE); return(FALSE); } } return(FALSE); } /***************************************************************************** Function: DDV_DragProc() Purpose: manage Mouse-Drag Parameters: p; panel handle (currently unused) pt; new position Return value: none *****************************************************************************/ NLM_EXTERN void DDV_DragProc(PaneL p, PoinT pt) { DdvMainPtr dmp; RecT rcP, rcP2; ParaGPtr cur_pgp=NULL; Int4 Jump; Int4 Line_num, ParaGLine_num;/*to get the coordinates*/ Int4 VPos, SavedVPos, from_col, to_col, from_row, to_row, old_VPos; Int4 HPos, SavedHPos, Col; Int4 Disp_coord_stop; Int4 Line_num_stop, BlockIndex, Offset, Width; BaR vsb; Boolean IsUnAligned; static Boolean LineToErase=TRUE; /*get the panel data*/ dmp = (DdvMainPtr) GetObjectExtra(p); if (dmp==NULL) return; /*what is happening ?*/ switch(dmp->ms.Action_type){ case MS_ACTION_SELECT_SEQ:/*selection on a sequence*/ if (shftKey) break; ObjectRect(p,&rcP); /*get the ParaG list and look for the ParaG where the mouse is located*/ /*note : only implemented for DDV_DISP_HORZ type of display...*/ if (dmp->MSA_d.pgp_l.DisplayType==DDV_DISP_HORZ) { /* get line num and col for current mouse position */ DDV_GetRowAndColGivenPt(dmp, rcP, pt, &Disp_coord_stop, &Line_num_stop); /* force single row selection when needed */ if (dmp->MouseMode == DDV_MOUSEMODE_SELECT_ONE_ROW) Line_num_stop = dmp->ms.first_row; /* erase the old rectangle */ InvertMode(); DrawOutline(p, dmp->ms.first_row, dmp->ms.first_col, dmp->ms.last_row, dmp->ms.last_col, TRUE); /* get display info */ DDV_GetCurrentDispRange(dmp->hWndDDV,&(dmp->GrData), dmp->MSA_d.pgp_l.LengthAli,&from_col,&to_col,&from_row,&to_row); /* draw the new rectangle */ CopyMode(); DrawOutline(p, dmp->ms.first_row, dmp->ms.first_col, Line_num_stop, Disp_coord_stop, TRUE); /* display info about residues that mouse is over */ DDV_DispStatus(dmp, Line_num_stop, dmp->ms.first_col, Disp_coord_stop); } break; case MS_ACTION_RESIZE_WIN:/*the user moves the 3D line located between name area and SeqAlign area*/ InvertMode(); UDV_draw_double_cursor(dmp->ms.rcClip, dmp->ms.oldPos); dmp->ms.newPos=pt; UDV_draw_double_cursor(dmp->ms.rcClip, dmp->ms.newPos); dmp->ms.oldPos=dmp->ms.newPos; Update(); break; case MS_ACTION_SELECT_FULL_SEQ: break; case MS_ACTION_MOVE_ROW: ObjectRect(p,&rcP); rcP2.left = rcP.left; rcP2.right = rcP.left + dmp->GrData.udv_panel.cxName - 10; rcP2.top = rcP.top; rcP2.bottom = rcP.bottom; Line_num=DDV_GetRowGivenMousePos(dmp, &rcP, &pt,&ParaGLine_num); DDV_GetCurrentDispRange(dmp->hWndDDV,&(dmp->GrData), dmp->MSA_d.pgp_l.LengthAli,&from_col,&to_col,&from_row,&to_row); vsb = GetSlateVScrollBar ((SlatE)dmp->hWndDDV); old_VPos = GetBarValue(vsb); if ((Line_num != -1) && (Line_num-1 >= from_row) && (Line_num-1 <= to_row)) { /* scroll vertically */ Jump = ABS((Line_num-1) - dmp->dsp->SaveRow); if (Line_num >= to_row) { SetValue(vsb, old_VPos + Jump); } if (Line_num <= from_row+1) { SetValue(vsb, old_VPos - Jump); } /* get new line number, erase last underline, draw new one */ SavedVPos = DDV_GetVPixelPosGivenRowNumber(dmp, rcP2, dmp->dsp->SaveRow); if ((Line_num-1) <= dmp->dsp->FromRow) { /* move before new row */ VPos = DDV_GetVPixelPosGivenRowNumber(dmp, rcP2, Line_num-2); dmp->dsp->SaveRow = Line_num-2; } else { /* move after new row */ VPos = DDV_GetVPixelPosGivenRowNumber(dmp, rcP2, Line_num-1); dmp->dsp->SaveRow = Line_num-1; } if (LineToErase) { InvertMode(); UDV_draw_horizontal_line(rcP2, SavedVPos); } LineToErase = TRUE; UDV_draw_horizontal_line(rcP2, VPos); } else { /* just one time, xor the horizontal line to turn it off */ if (LineToErase) { InvertMode(); SavedVPos = DDV_GetVPixelPosGivenRowNumber(dmp, rcP2, dmp->dsp->SaveRow); UDV_draw_horizontal_line(rcP2, SavedVPos); LineToErase = FALSE; } } break; case MS_ACTION_SHIFT_ROW: ObjectRect(p,&rcP); Col = DDV_GetColNumberGivenMousePos(dmp, rcP, pt); DDV_GetCurrentDispRange(dmp->hWndDDV,&(dmp->GrData), dmp->MSA_d.pgp_l.LengthAli,&from_col,&to_col,&from_row,&to_row); /* if we're still in a legal area */ if ((Col>=from_col) && (Col<=to_col) && PtInRect(pt, &rcP)) { /* if a new box needs to be drawn */ if (dmp->dsp->SaveCol != Col) { ObjectRect(p,&rcP); SavedVPos = DDV_GetVPixelPosGivenRowNumber(dmp, rcP, dmp->dsp->SaveRow); SavedHPos = DDV_GetHPixelPosGivenColNumber(dmp, rcP, dmp->dsp->SaveCol); /* erase old box */ rcP2.left = SavedHPos - dmp->GrData.udv_font.ColWidth; rcP2.right = SavedHPos; rcP2.top = SavedVPos - dmp->GrData.udv_font.LineHeight; rcP2.bottom = SavedVPos; InvertMode(); UDV_draw_rectangle(rcP2, FALSE); /* draw new box */ dmp->dsp->SaveCol = Col; HPos = DDV_GetHPixelPosGivenColNumber(dmp, rcP, Col); rcP2.left = HPos - dmp->GrData.udv_font.ColWidth; rcP2.right = HPos; rcP2.top = SavedVPos - dmp->GrData.udv_font.LineHeight; rcP2.bottom = SavedVPos; UDV_draw_rectangle(rcP2, FALSE); } } break; case MS_ACTION_SHIFT_BOUNDARY: /* if we're still in a legit area */ ObjectRect(p, &rcP); InsetRect(&rcP,4,4); DDV_AdjustDrawingRect(&rcP,&(dmp->GrData.udv_font),dmp); rcP.left += dmp->GrData.udv_panel.cxName + dmp->GrData.udv_scale.cxLeftScale; if (PtInRect(pt, &rcP)) { ObjectRect(p, &rcP); /* get column of new vertical bar */ Col = DDV_GetColNumberGivenMousePos(dmp, rcP, pt); /* if column has changed since vertical bar was last drawn */ if (Col != dmp->dsp->SaveCol) { /* and the column's legal */ if ((Col >= 0) && (Col < dmp->MSA_d.pgp_l.LengthAli)) { /* get horizontal pixel position of old column */ HPos = DDV_GetHPixelPosGivenColNumber(dmp, rcP, dmp->dsp->SaveCol); /* adjust for drawing bar preceeding left boundary */ if (dmp->dsp->LeftBoundary) HPos -= dmp->GrData.udv_font.ColWidth; /* erase old vertical bar */ InvertMode(); UDV_draw_vertical_bar(rcP, HPos, TRUE); /* get horizontal pixel position of new column */ HPos = DDV_GetHPixelPosGivenColNumber(dmp, rcP, Col); /* adjust for drawing bar preceeding left boundary */ if (dmp->dsp->LeftBoundary) HPos -= dmp->GrData.udv_font.ColWidth; /* draw the new vertical bar */ UDV_draw_vertical_bar(rcP, HPos, TRUE); /* save the column */ dmp->dsp->SaveCol = Col; } } } break; case MS_ACTION_CREATE_BLOCK: ObjectRect(p, &rcP); InsetRect(&rcP,4,4); DDV_AdjustDrawingRect(&rcP,&(dmp->GrData.udv_font),dmp); rcP.left += dmp->GrData.udv_panel.cxName + dmp->GrData.udv_scale.cxLeftScale; /* if we're still in a legit area */ if (PtInRect(pt, &rcP)) { ObjectRect(p, &rcP); Col = DDV_GetColNumberGivenMousePos(dmp, rcP, pt); /* and the column has changed since vertical bar was last drawn */ if (Col != dmp->dsp->SaveCol) { /* and the column's legal */ if ((Col >= 0) && (Col < dmp->MSA_d.pgp_l.LengthAli)) { if (Col >= dmp->dsp->FromCol) { /* get horizontal pixel position of old column */ HPos = DDV_GetHPixelPosGivenColNumber(dmp, rcP, dmp->dsp->SaveCol); /* erase old vertical bar */ InvertMode(); UDV_draw_vertical_bar(rcP, HPos, TRUE); /* get horizontal pixel position of new column */ HPos = DDV_GetHPixelPosGivenColNumber(dmp, rcP, Col); /* draw the new vertical bar */ UDV_draw_vertical_bar(rcP, HPos, TRUE); /* save the column */ dmp->dsp->SaveCol = Col; } } } } break; case MS_ACTION_SPLIT_BLOCK: /* adjust x position so vertical bar jumps when mouse is on center of char */ pt.x -= dmp->GrData.udv_font.ColWidth/2; /* get block, col, etc for new mouse position */ if (GetBlockAndAlignment(pt, p, dmp, &BlockIndex, &IsUnAligned, &Col, &Offset, &Width, &rcP)) { /* if mouse col changed */ if (Col != dmp->SaveCol) { /* get horizontal pixel position of old column */ HPos = DDV_GetHPixelPosGivenColNumber(dmp, rcP, dmp->SaveCol); /* erase old vertical bar */ InvertMode(); UDV_draw_vertical_bar(rcP, HPos, FALSE); /* get horizontal pixel position of new column */ HPos = DDV_GetHPixelPosGivenColNumber(dmp, rcP, Col); /* draw the new vertical bar */ UDV_draw_vertical_bar(rcP, HPos, FALSE); /* save the column */ dmp->SaveCol = Col; } } } } /***************************************************************************** Function: DDV_ReleaseProc() Purpose: manage Mouse-Release Parameters: p; panel handle (currently unused) pt; new position Return value: none *****************************************************************************/ NLM_EXTERN void DDV_ReleaseProc(PaneL p, PoinT pt) { WindoW temport; DdvMainPtr dmp; DdvMainWinPtr dmwp; DDVUpdateMSGPtr dump; RecT rcP, rcP2; ParaGPtr cur_pgp=NULL; Int4 bsp_coord, SeqAlign_coord; Int4 Disp_coord, Line_num,ParaGLine_Num;/*to get the coordinates*/ Uint1 uWhere; /*where the use clicked (seq, feat, name,...)*/ Uint2 bsp_eID; Uint4 bsp_iID; Int4 VPos, Shift, SavedVPos, SavedHPos, BlockIndex, NumBlocks; Boolean IsUnAligned; MsaParaGPopListPtr mpplp; SeqAlignPtr sap; DDE_StackPtr dsp; Int4 Offset, Width; BaR hsb; RecT rc; /*get the panel data*/ dmp = (DdvMainPtr) GetObjectExtra(p); if (dmp==NULL) return; switch(dmp->ms.Action_type){ case MS_ACTION_SELECT_FULL_SEQ: ObjectRect(p,&rcP); Line_num=DDV_GetRowGivenMousePos(dmp,&rcP,&pt,&ParaGLine_Num); if (Line_num!=(Int4)-1){ UDV_DecodeIdxFeat (dmp->MSA_d.pgp_l.entitiesTbl[ParaGLine_Num-1], &bsp_eID,&bsp_iID); ObjMgrSendMsg(OM_MSG_MOUSEUP, bsp_eID, bsp_iID, OBJ_BIOSEQ); } break; case MS_ACTION_SELECT_SEQ: /* erase outline */ InvertMode(); rc = DrawOutline(p, dmp->ms.first_row, dmp->ms.first_col, dmp->ms.last_row, dmp->ms.last_col, TRUE); CopyMode(); DDV_SelectRegion(dmp, pt, rc, dmp->ms.first_row, dmp->ms.last_row, dmp->ms.first_col, dmp->ms.last_col); ObjectRect(p,&rcP); pt.y=dmp->ms.oldPos.y; if (dmp->MSA_d.pgp_l.DisplayType==DDV_DISP_HORZ){ if (DDV_GetCoordsGivenAClick(dmp,&rcP,&pt, &bsp_coord,&SeqAlign_coord,&Disp_coord,&Line_num, &ParaGLine_Num,&uWhere,&cur_pgp)){ if (uWhere==PGP_REGION_SEQ){ UDV_DecodeIdxFeat (dmp->MSA_d.pgp_l.entitiesTbl[ParaGLine_Num-1], &bsp_eID,&bsp_iID); ObjMgrSendMsg(OM_MSG_MOUSEUP, bsp_eID, bsp_iID, OBJ_BIOSEQ); /*send a OM_MSG_UPDATE message to move the caret (if needed)*/ if (dmp->MouseMode==DDV_MOUSEMODE_EDIT){ dump=(DDVUpdateMSGPtr)MemNew(sizeof(DDVUpdateMSG)); if (dump){ dmp->dci.new_row=Line_num; dmp->dci.new_col=Disp_coord; dump->type=UPDATE_TYPE_CARETPOS; dump->data=NULL; ObjMgrSendProcMsg(OM_MSG_UPDATE, bsp_eID, bsp_iID, OBJ_BIOSEQ, 0,0,(Pointer)dump); MemFree(dump); } } } } else { /* send mouse up anyway */ if(ParaGLine_Num > 0) { UDV_DecodeIdxFeat (dmp->MSA_d.pgp_l.entitiesTbl[ParaGLine_Num-1], &bsp_eID,&bsp_iID); ObjMgrSendMsg(OM_MSG_MOUSEUP, bsp_eID, bsp_iID, OBJ_BIOSEQ); } } } break; case MS_ACTION_RESIZE_WIN: temport=SavePort((WindoW)p); Select(p); InvertMode(); UDV_draw_double_cursor(dmp->ms.rcClip, dmp->ms.oldPos); /*redraw panel with new 'cxName' value*/ if (PtInRect(dmp->ms.newPos,&dmp->ms.rcClip)){ RecT rc; ObjectRect(p,&rc); rc.left=0;/*for obscure reasons, not == 0*/ rc.top=0; dmp->GrData.udv_panel.cxName=dmp->ms.newPos.x; DDV_Resize_DDV(p,FALSE); /*DDV_SetupWin (p,FALSE,NULL); */ InvalRect(&rc); } RestorePort(temport); break; case MS_ACTION_MOVE_ROW: ObjectRect(p, &rcP); /* if the mouse is released in sequence name section */ if (pt.xGrData.udv_panel.cxName && pt.y>(rcP.top+dmp->GrData.udv_panel.cyScale)){ /* get the line number where the mouse is released */ Line_num=DDV_GetRowGivenMousePos(dmp, &rcP, &pt,&ParaGLine_Num); if (Line_num != -1) { /* if the line number is valid */ if (dmp->dsp->FromRow != Line_num-1) { /* move the saved row to this line number */ DDE_MoveRow(dmp->dsp, dmp->dsp->FromRow, Line_num-1, TRUE); dmp->deri.curEditRow = Line_num-1; DDV_ReDraw(dmp); } /* otherwise */ else { /* since screen's not redrawn, turn off the last drawn horizontal line */ ObjectRect(p, &rcP); rcP2.left = rcP.left; rcP2.right = rcP.left + dmp->GrData.udv_panel.cxName - 10; rcP2.top = rcP.top; rcP2.bottom = rcP.bottom; VPos = DDV_GetVPixelPosGivenRowNumber(dmp, rcP2, dmp->dsp->SaveRow); InvertMode(); UDV_draw_horizontal_line(rcP2, VPos); } } } ArrowCursor(); break; case MS_ACTION_SHIFT_ROW: /* shift row by diff between original col position and last position */ Shift = dmp->dsp->SaveCol - dmp->dsp->FromCol; if (DDE_ShiftRow(dmp->dsp, dmp->dsp->SaveRow, Shift, TRUE, TRUE)) { DDV_ReDraw(dmp); } else { /* if no shift was done, erase the boxes */ ObjectRect(p,&rcP); SavedVPos = DDV_GetVPixelPosGivenRowNumber(dmp, rcP, dmp->dsp->SaveRow); SavedHPos = DDV_GetHPixelPosGivenColNumber(dmp, rcP, dmp->dsp->SaveCol); rcP2.left = SavedHPos - dmp->GrData.udv_font.ColWidth; rcP2.right = SavedHPos; rcP2.top = SavedVPos - dmp->GrData.udv_font.LineHeight; rcP2.bottom = SavedVPos; InsetRect(&rcP2, -2, -2); InvalRect(&rcP2); } ArrowCursor(); break; case MS_ACTION_SHIFT_BOUNDARY: /* shift boundary by diff between original col position and last position */ Shift = dmp->dsp->SaveCol - dmp->dsp->FromCol; if (dmp->dsp->LeftBoundary) { DDE_ShiftLeftBoundary(dmp->dsp, dmp->dsp->BlockIndex, Shift, TRUE); DDV_ReDraw(dmp); } else { DDE_ShiftRightBoundary(dmp->dsp, dmp->dsp->BlockIndex, Shift, TRUE); DDV_ReDraw(dmp); } ArrowCursor(); break; case MS_ACTION_CREATE_BLOCK: DDE_CreateBlock(dmp->dsp, dmp->dsp->FromCol, dmp->dsp->SaveCol, TRUE); dmp->MouseMode = dmp->SavedMouseMode; DDV_ReDraw(dmp); ArrowCursor(); break; case MS_ACTION_SPLIT_BLOCK: /* get block and alignment for last saved col */ /* also get offset into block and width of block */ GetBlockAndAlignmentForCol(dmp, dmp->SaveCol, &BlockIndex, &IsUnAligned, &Offset, &Width); /* if col is in aligned region */ if (!IsUnAligned && (Offset < (Width-1))) { /* create a stack for the block */ sap = ViewMgr_GetBeginIndexed(dmp->MSA_d.pgp_l.sap); dmp->MSA_d.pgp_l.viewed_sap = dmp->MSA_d.pgp_l.sap; mpplp = DDE_CreateDisplay(sap, BlockIndex, FALSE, &NumBlocks); dsp = DDE_NewStack(mpplp); DDE_MergeNodesLists(dsp->pEdit); /* record which block is being edited, etc */ dsp->LaunchBlock = BlockIndex; dsp->NumBlocks = NumBlocks; dsp->IsUnAligned = IsUnAligned; /* shift right boundary of block left, to the split line */ DDE_ShiftRightBoundary(dsp, 0, -(Width-(Offset+1)), FALSE); /* tell AlnMgr to save edits, don't redraw yet */ dmp->dsp = dsp; DDV_SaveEdits(dmp, FALSE); /* free stack for block. create stack for unaligned region to right of block */ DDE_FreeStack(dsp); sap = ViewMgr_GetBeginIndexed(dmp->MSA_d.pgp_l.sap); dmp->MSA_d.pgp_l.viewed_sap = dmp->MSA_d.pgp_l.sap; mpplp = DDE_CreateDisplay(sap, BlockIndex+1, TRUE, &NumBlocks); dsp = DDE_NewStack(mpplp); DDE_MergeNodesLists(dsp->pEdit); /* create new block of part that was just unaligned */ DDE_CreateBlock(dsp, 0, (Width-(Offset+1)-1), FALSE); /* tell AlnMgr to save edits, now redraw */ dmp->dsp = dsp; DDV_SaveEdits(dmp, TRUE); /* free remaining stack */ dsp = DDE_FreeStack(dsp); dmp->dsp = dsp; dmp->MouseMode = dmp->SavedMouseMode; } /* get rid of vertical bar */ else { hsb = GetSlateHScrollBar((SlatE) dmp->hWndDDV); DDV_ReDrawAtCol(dmp, GetBarValue(hsb), FALSE); } } ClearUDV_mouse_select(&(dmp->ms)); dmp->ms.Action_type=MS_ACTION_FEAT_NOTHING; /*update InfoPanel*/ dmwp=(DdvMainWinPtr)GetObjectExtra(dmp->hParent); if (dmp->bEditor) { DDV_GreyOut(dmwp, DDE_AtStartOfStack(dmp->dsp), DDE_AtEndOfStack(dmp->dsp)); } if (dmwp && dmp->MouseMode!=DDV_MOUSEMODE_EDIT) SetTitle(dmwp->InfoPanel,"Ready !"); if (dmp->MouseMode != DDV_MOUSEMODE_MERGEBLOCKS2) ArrowCursor(); } /***************************************************************************** Function: DDV_HoldProc() Purpose: manage Mouse-Hold Parameters: p; panel handle (currently unused) pt; new position Return value: none *****************************************************************************/ NLM_EXTERN void DDV_HoldProc(PaneL p, PoinT pt) { DdvMainPtr dmp; RecT rcP; ParaGPtr cur_pgp=NULL; Int4 Disp_coord_stop; Int4 Line_num_stop; Int4 from_col, to_col, from_row, to_row; Boolean Scroll=FALSE; /*get the panel data*/ dmp = (DdvMainPtr) GetObjectExtra(p); if (dmp==NULL) return; /*what is happening ?*/ switch(dmp->ms.Action_type){ case MS_ACTION_SELECT_SEQ: if (shftKey) break; ObjectRect(p,&rcP); /*get the ParaG list and look for the ParaG where the mouse is located*/ /*note : only implemented for DDV_DISP_HORZ type of display...*/ if (dmp->MSA_d.pgp_l.DisplayType==DDV_DISP_HORZ) { /* get line num and col for current mouse position */ DDV_GetRowAndColGivenPt(dmp, rcP, pt, &Disp_coord_stop, &Line_num_stop); /* force single row selection when needed */ if (dmp->MouseMode == DDV_MOUSEMODE_SELECT_ONE_ROW) Line_num_stop = dmp->ms.first_row; /* erase the old rectangle */ InvertMode(); DrawOutline(p, dmp->ms.first_row, dmp->ms.first_col, dmp->ms.last_row, dmp->ms.last_col, TRUE); /* get display info */ DDV_GetCurrentDispRange(dmp->hWndDDV,&(dmp->GrData), dmp->MSA_d.pgp_l.LengthAli,&from_col,&to_col,&from_row,&to_row); /* draw the new rectangle after scrolling */ DDV_AutoHScroll(dmp, Disp_coord_stop); DDV_AutoVScroll(dmp, Line_num_stop); CopyMode(); DrawOutline(p, dmp->ms.first_row, dmp->ms.first_col, Line_num_stop, Disp_coord_stop, TRUE); /* display info about residues that mouse is over */ DDV_DispStatus(dmp, Line_num_stop, dmp->ms.first_col, Disp_coord_stop); } break; case MS_ACTION_RESIZE_WIN: case MS_ACTION_SELECT_FULL_SEQ: break; }/*end switch()*/ } /***************************************************************************** Function: DDV_MoveCaretLR() Purpose: move the caret to the right or to the left Parameters: Return value: none *****************************************************************************/ static void DDV_MoveCaretLR(DdvMainPtr dmp,Int4 decal_Hscroll, Boolean bMoveRight,BaR hsb,Int4 old_Hpos,Int4 from_col,Int4 to_col) { DDVUpdateMSGPtr dump; Uint2 bsp_eID; Uint4 bsp_iID; Int4 shift, new_from_col, new_to_col; dump=(DDVUpdateMSGPtr)MemNew(sizeof(DDVUpdateMSG)); if (dump){ /*get bsp IDs*/ UDV_DecodeIdxFeat(dmp->MSA_d.pgp_l.entitiesTbl[dmp->dci.new_row-1], &bsp_eID,&bsp_iID); /*save old position*/ dmp->dci.old_col=dmp->dci.new_col; dmp->dci.old_row=dmp->dci.new_row; /*update the position*/ if (bMoveRight) dmp->dci.new_col+=decal_Hscroll; else dmp->dci.new_col-=decal_Hscroll; if (dmp->dci.new_col<0){ dmp->dci.new_col=0; Beep(); return; } if (dmp->dci.new_col>dmp->MSA_d.pgp_l.LengthAli-1){ dmp->dci.new_col=dmp->MSA_d.pgp_l.LengthAli-1; Beep(); return; } /*auto-scroll the panel if needed*/ if (dmp->dci.new_col<=from_col){ shift = (to_col-from_col)/2; new_from_col = from_col - shift; new_to_col = to_col - shift; if ((dmp->dci.new_col >= new_from_col) && (dmp->dci.new_col <= new_to_col)) { /* shift left by 1/2 the window width */ SetValue(hsb,old_Hpos-shift); } else { /* shifting by more than 1/2 the window width */ SetValue(hsb, dmp->dci.new_col); } } if (dmp->dci.new_col>=to_col){ shift = (to_col-from_col)/2; new_from_col = from_col + shift; new_to_col = to_col + shift; if ((dmp->dci.new_col >= new_from_col) && (dmp->dci.new_col <= new_to_col)) { /* shift right by 1/2 the window width */ SetValue(hsb,old_Hpos+shift); } else { /* shifting by more than 1/2 the window width */ SetValue(hsb, dmp->dci.new_col); } } /*if ok, move the caret*/ dump->type=UPDATE_TYPE_CARETPOS; dump->data=NULL; ObjMgrSendProcMsg(OM_MSG_UPDATE, bsp_eID, bsp_iID, OBJ_BIOSEQ, 0,0,(Pointer)dump); MemFree(dump); } } /***************************************************************************** Function: DDV_MoveCaretUD() Purpose: move the caret up or down Parameters: Return value: none *****************************************************************************/ static void DDV_MoveCaretUD(DdvMainPtr dmp,Int4 decal_Vscroll, Boolean bMoveDown,BaR vsb,Int4 old_Vpos,Int4 from_row,Int4 to_row) { DDVUpdateMSGPtr dump; Uint2 bsp_eID; Uint4 bsp_iID; Int4 shift; dump=(DDVUpdateMSGPtr)MemNew(sizeof(DDVUpdateMSG)); if (dump){ /*get bsp IDs*/ UDV_DecodeIdxFeat(dmp->MSA_d.pgp_l.entitiesTbl[dmp->dci.new_row-1], &bsp_eID,&bsp_iID); /*save old position*/ dmp->dci.old_row=dmp->dci.new_row; dmp->dci.old_col=dmp->dci.new_col; /*update the position*/ if (bMoveDown) dmp->dci.new_row+=decal_Vscroll; else dmp->dci.new_row-=decal_Vscroll; if (dmp->dci.new_row<1){ dmp->dci.new_row=1; SetValue(vsb, 0); Beep(); goto send_msg; } if (dmp->dci.new_row>dmp->MSA_d.pgp_l.nBsp){ dmp->dci.new_row=dmp->MSA_d.pgp_l.nBsp; SetValue(vsb, dmp->MSA_d.pgp_l.nBsp); Beep(); goto send_msg; } /*auto-scroll the panel if needed*/ if (ABS(decal_Vscroll) == 1) { if (dmp->dci.new_row<=from_row){ shift = (to_row-from_row)/2; SetValue(vsb, old_Vpos-shift); } if (dmp->dci.new_row>=to_row-1){ shift = (to_row-from_row)/2; SetValue(vsb, old_Vpos+shift); } } else { if (bMoveDown) { SetValue(vsb, old_Vpos+decal_Vscroll); } else { SetValue(vsb, old_Vpos-decal_Vscroll); } } /*if ok, move the caret*/ send_msg: dump->type=UPDATE_TYPE_CARETPOS; dump->data=NULL; ObjMgrSendProcMsg(OM_MSG_UPDATE, bsp_eID, bsp_iID, OBJ_BIOSEQ, 0,0,(Pointer)dump); MemFree(dump); } } /***************************************************************************** Function: DDV_KeyboardProc() Purpose: manage keyboard actions Parameters: s; panel handle (DDV panel) ch; key Return value: none *****************************************************************************/ NLM_EXTERN void DDV_KeyboardProc (SlatE s, Char ch) { DdvMainWinPtr dmwp; /*main window*/ DdvMainPtr dmp; /*DDV panel associated data*/ BaR hsb,vsb; /*DDV' scroll bars*/ Int4 old_Hpos,old_Vpos,/*scrolls positions*/ decal_Hscroll,decal_Vscroll,/*used to scroll DDV's panel*/ from_col,to_col,from_row,to_row,/*display size*/ bsp_pos, height; if ( (int) ch == 0 ) return; /*get the panel data*/ dmp = (DdvMainPtr) GetObjectExtra(s); if (dmp==NULL) return; dmwp = (DdvMainWinPtr) GetObjectExtra(dmp->hParent); if (dmwp == NULL) return; /*get scroll handles and data*/ hsb = GetSlateHScrollBar ((SlatE) dmp->hWndDDV); old_Hpos=GetBarValue(hsb); vsb = GetSlateVScrollBar ((SlatE) dmp->hWndDDV); old_Vpos=GetBarValue(vsb); /*get the display size*/ DDV_GetCurrentDispRange(dmp->hWndDDV,&(dmp->GrData), dmp->MSA_d.pgp_l.LengthAli,&from_col,&to_col,&from_row,&to_row); /*if pressed, scroll panel by one 'panel' size*/ if (ctrlKey) { decal_Hscroll=to_col-from_col; decal_Vscroll=to_row-from_row; } else{ decal_Hscroll=1; decal_Vscroll=1; } /*switch to one-bsed value because dmp->dci values are one-based values*/ from_row++;to_row++; switch ((int) TO_UPPER(ch)){ case NLM_PREV: /* page-up -- scoll page up one page height */ height = (to_row-from_row) - 1; if (dmp->MouseMode==DDV_MOUSEMODE_EDIT) { DDV_MoveCaretUD(dmp, height, FALSE, vsb, old_Vpos, from_row, to_row); } else { SetValue(vsb, old_Vpos - height); } break; case NLM_NEXT: /* page-down -- scoll page down one page height */ height = (to_row-from_row) - 1; if (dmp->MouseMode==DDV_MOUSEMODE_EDIT) { DDV_MoveCaretUD(dmp, height, TRUE, vsb, old_Vpos, from_row, to_row); } else { SetValue(vsb, old_Vpos + height); } break; case NLM_HOME: /* for home key, move cursor to start of row */ if (dmp->MouseMode==DDV_MOUSEMODE_EDIT){ /* move caret left by current col pos */ DDV_MoveCaretLR(dmp, dmp->dci.new_col, FALSE, hsb, old_Hpos, from_col, to_col); } else { SetValue(hsb, 0); } break; case NLM_END: /* for end key, move cursor to end of row */ if (dmp->MouseMode==DDV_MOUSEMODE_EDIT){ /* move caret right by diff between last col and current col */ DDV_MoveCaretLR(dmp, ((dmp->MSA_d.pgp_l.LengthAli-1) - dmp->dci.new_col), TRUE, hsb, old_Hpos, from_col, to_col); } else { SetValue(hsb, dmp->MSA_d.pgp_l.LengthAli-1); } break; case 0x1a: /* for ctrl-z, undo the last edit */ if (DDE_Prev(dmp->dsp)) { DDV_ReDraw(dmp); } break; case 0x19: /* for ctrl-y, redo the last undone edit */ if (DDE_Next(dmp->dsp)) { DDV_ReDraw(dmp); } break; case NLM_DEL: /* delete key pressed -- remove a gap and leave carat in place */ if (dmp->MouseMode==DDV_MOUSEMODE_EDIT){ if (DDE_RemoveGap(dmp->dsp, dmp->dci.new_row-1, dmp->dci.new_col+1, TRUE)) { DDV_ReDraw(dmp); } } break; case 0x08: /* backspace key pressed -- remove gap to the left and move carat left */ if (dmp->MouseMode==DDV_MOUSEMODE_EDIT){ if (DDE_RemoveGap(dmp->dsp, dmp->dci.new_row-1, dmp->dci.new_col, TRUE)) { DDV_ReDraw(dmp); } } case NLM_LEFT: /*move the caret ?*/ if (dmp->MouseMode==DDV_MOUSEMODE_EDIT){ decal_Hscroll=1;/*doesn't accept ctrlKey motions*/ DDV_MoveCaretLR(dmp,decal_Hscroll,FALSE,hsb,old_Hpos, from_col,to_col); } /*scroll the panel*/ else{ SetValue(hsb,old_Hpos-decal_Hscroll); } break; case 0x20: /* space bar pressed -- insert a gap and move carat to the right */ if (dmp->MouseMode==DDV_MOUSEMODE_EDIT){ if (DDE_InsertGap(dmp->dsp, dmp->dci.new_row-1, dmp->dci.new_col+1, TRUE)) { DDV_ReDraw(dmp); } } case NLM_RIGHT: /*move the caret ?*/ if (dmp->MouseMode==DDV_MOUSEMODE_EDIT){ decal_Hscroll=1;/*doesn't accept ctrlKey motions*/ DDV_MoveCaretLR(dmp,decal_Hscroll,TRUE,hsb,old_Hpos, from_col,to_col); } /*scroll the panel*/ else { SetValue(hsb,old_Hpos+decal_Hscroll); } break; case NLM_UP: /*move the caret ?*/ if (dmp->MouseMode==DDV_MOUSEMODE_EDIT){ decal_Vscroll=1;/*doesn't accept ctrlKey motions*/ DDV_MoveCaretUD(dmp,decal_Vscroll,FALSE,vsb,old_Vpos, from_row,to_row); } /*scroll the panel*/ else{ SetValue(vsb,old_Vpos-decal_Vscroll); } break; case NLM_DOWN: /*move the caret ?*/ if (dmp->MouseMode==DDV_MOUSEMODE_EDIT){ decal_Vscroll=1;/*doesn't accept ctrlKey motions*/ DDV_MoveCaretUD(dmp,decal_Vscroll,TRUE,vsb,old_Vpos, from_row,to_row); } /*scroll the panel*/ else{ SetValue(vsb,old_Vpos+decal_Vscroll); } break; default: Beep (); break; } if (dmp->bEditor) { DDV_GreyOut(dmwp, DDE_AtStartOfStack(dmp->dsp), DDE_AtEndOfStack(dmp->dsp)); } /*update InfoPanel with position*/ if (dmwp && dmp->MouseMode==DDV_MOUSEMODE_EDIT){ Char szAccess[21]; DDV_GetSeqNameGivenRow(dmp->MSA_d.pgp_l.TableHead, dmp->dci.new_row, szAccess); bsp_pos=DDV_GetBspCoordGivenPgpList( dmp->MSA_d.pgp_l.TableHead[dmp->dci.new_row-1], dmp->dci.new_col); if (bsp_pos!=(Int4)-1){ DDV_DispPositionInStatus(dmwp->InfoPanel, bsp_pos+1,dmp->dci.new_row,szAccess); /*+1 : switch to one-based value*/ } } } NLM_EXTERN void DDV_ReDrawAtCol(DdvMainPtr dmp, Int4 Col, Boolean DDE) { /*------------------------------------------ * resize, redraw. *------------------------------------------*/ DdvMainWinPtr dmwp; WindoW temport; RecT rcP; BaR hsb; Int4 NumBlocks; if (DDE) { MemCopy(&(dmp->MSA_d.pgp_l), dmp->dsp->pEdit->pPopList, sizeof(MsaParaGPopList)); } DDV_InitColour_When_Start(dmp->MSA_d.pgp_l.sap, &(dmp->MSA_d.pgp_l),&(dmp->Globals.colorp), FALSE); /* recalculate window size */ DDV_WhatSize(dmp); /* adjust horizontal scroll bar */ hsb = GetSlateHScrollBar((SlatE) dmp->hWndDDV); DDV_UpdateHScrollVal(dmp->hWndDDV, FALSE, GetBarValue(hsb)); dmwp=(DdvMainWinPtr)GetObjectExtra(dmp->hParent); temport=SavePort(dmwp->hWndDDV); Select(dmwp->hWndDDV); ObjectRect(dmwp->hWndDDV, &rcP); InvalRect(&rcP); if (Col >= 0) { SetValue(hsb, Col); } Update(); RestorePort(temport); if (DDE) { /* decide about greying out undo and redo functions */ DDV_GreyOut(dmwp, DDE_AtStartOfStack(dmp->dsp), DDE_AtEndOfStack(dmp->dsp)); /* decide about greying out left/right/center functions */ NumBlocks = DDE_GetNumBlocks(dmp->dsp->pEdit); if (NumBlocks == 0) { Enable(dmwp->MainMenu.Justify); } else { Disable(dmwp->MainMenu.Justify); } } return; } NLM_EXTERN void DDV_ReDraw(DdvMainPtr dmp) { /*------------------------------------------ * resize, redraw. *------------------------------------------*/ /* give an illegal column so the column's not set */ /* specify that this redraw is for DDE */ DDV_ReDrawAtCol(dmp, -1, TRUE); } static void DDV_SelectRegion(DdvMainPtr dmp, PoinT pt, RecT rc, Int4 row_start, Int4 row_stop, Int4 col_start, Int4 col_stop) { /*---------------------------------------------------------------------------- * select from row_start to row_stop between columns col_start and col_stop. * rows are 1-based, cols are 0-based. why? go figure. * *----------------------------------------------------------------------------*/ Int4 row; Uint1 uWhere; ParaGPtr pgp; if (row_start > row_stop) swap(&row_start, &row_stop); if (row_start < 1) row_start=1; if (row_stop > dmp->MSA_d.pgp_l.nBsp) row_stop=dmp->MSA_d.pgp_l.nBsp; for (row=row_start; row<=row_stop; row++) { /* send message to select all intervening columns on this row */ pgp = DDV_GetPGPGivenRowAndCol(dmp, row, col_stop); uWhere = DDV_GetRegionInParaG(pgp, row); if (uWhere == PGP_REGION_SEQ) { DDV_SendBSPSelectMsg(dmp, col_start, col_stop, row, TRUE); } } /* redraw section that's been highlighted */ /* InsetRect(&rc, -4, -4); InvalRect(&rc); Update(); */ }