1 /*  $Id: ddvclick.c,v 1.66 2006/07/13 17:11:42 bollin Exp $
2 * ===========================================================================
3 *
4 *                            PUBLIC DOMAIN NOTICE
5 *            National Center for Biotechnology Information (NCBI)
6 *
7 *  This software/database is a "United States Government Work" under the
8 *  terms of the United States Copyright Act.  It was written as part of
9 *  the author's official duties as a United States Government employee and
10 *  thus cannot be copyrighted.  This software/database is freely available
11 *  to the public for use. The National Library of Medicine and the U.S.
12 *  Government do not place any restriction on its use or reproduction.
13 *  We would, however, appreciate having the NCBI and the author cited in
14 *  any work or product based on this material
15 *
16 *  Although all reasonable efforts have been taken to ensure the accuracy
17 *  and reliability of the software and data, the NLM and the U.S.
18 *  Government do not and cannot warrant the performance or results that
19 *  may be obtained by using this software or data. The NLM and the U.S.
20 *  Government disclaim all warranties, express or implied, including
21 *  warranties of performance, merchantability or fitness for any particular
22 *  purpose.
23 *
24 * ===========================================================================
25 *
26 * File Name:  ddvclick.c
27 *
28 * Author:  Patrick Durand
29 *
30 * Version Creation Date:   09/20/99
31 *
32 * $Revision: 1.66 $
33 *
34 * File Description: mouse management code for DeuxD-Viewer (DDV)
35 *
36 * Modifications:
37 * --------------------------------------------------------------------------
38 * $Log: ddvclick.c,v $
39 * Revision 1.66  2006/07/13 17:11:42  bollin
40 * use Uint4 instead of Uint2 for itemID values
41 *
42 * Revision 1.65  2000/07/25 20:30:23  hurwitz
43 * bug fixes: panel update when file is closed, double-click launches UDV from DDE, seqName agrees in status line and left col
44 *
45 * Revision 1.64  2000/07/24 22:00:08  hurwitz
46 * fixed bug that 1/2 characters were displayed sometimes
47 *
48 * Revision 1.63  2000/07/20 22:25:57  hurwitz
49 * bug fix.  mouse-mode query working again
50 *
51 * Revision 1.62  2000/07/14 22:24:55  lewisg
52 * fix scroll, click, visual c++ build bugs.  add command line arg parse to ddv
53 *
54 * Revision 1.61  2000/07/12 22:22:41  hurwitz
55 * added delete block to DDV
56 *
57 * Revision 1.60  2000/07/12 21:18:13  hurwitz
58 * fixed display problems with select rectangle
59 *
60 * Revision 1.59  2000/07/12 15:38:08  hurwitz
61 * made rectangle select much faster.  it's almost working.
62 *
63 * Revision 1.58  2000/07/05 19:23:13  lewisg
64 * add two panes to ddv, update msvc project files
65 *
66 * Revision 1.57  2000/07/05 18:42:16  hurwitz
67 * added split block function to DDV
68 *
69 * Revision 1.56  2000/06/30 22:31:51  hurwitz
70 * added merge block function for DDV
71 *
72 * Revision 1.55  2000/06/28 19:41:31  hurwitz
73 * auto vertical scroll working for rectangle selection
74 *
75 * Revision 1.54  2000/06/27 20:46:38  hurwitz
76 * fixed bugs with select rectangle, added select row option
77 *
78 * Revision 1.53  2000/06/26 19:32:17  hurwitz
79 * can select a rectangle instead of a single row, auto horizontal scroll works but not vertical scroll yet
80 *
81 * Revision 1.52  2000/06/22 20:56:52  hurwitz
82 * assorted bug fixes
83 *
84 * Revision 1.51  2000/06/21 21:20:56  hurwitz
85 * a couple bug fixes
86 *
87 * Revision 1.50  2000/06/20 19:35:11  hurwitz
88 * use indexed seqAlign when necessary, make multiple when redrawing
89 *
90 * Revision 1.49  2000/06/16 18:40:02  lewisg
91 * send mouseup message when drag ends off of sequence
92 *
93 * Revision 1.48  2000/06/15 20:26:05  hurwitz
94 * added left/right/center justify for DDE
95 *
96 * Revision 1.47  2000/06/13 18:23:54  hurwitz
97 * made ViewMgr_MakeMultiple routine, call this on each launch of DDE rather than launch of DDV
98 *
99 * Revision 1.46  2000/06/12 23:02:40  hurwitz
100 * enable launch of DDE from Cn3D, swith from DDV_ComputeRuler to DDE_ReMakeRuler, get rid of styles option for DDE
101 *
102 * Revision 1.45  2000/06/06 20:09:22  lewisg
103 * fix double redraw bug
104 *
105 * Revision 1.44  2000/05/31 23:07:26  hurwitz
106 * made NoGaps a runtime parameter, fixed bug with vertical scroll of show/hide list, save edits query is not performed if nothing to save
107 *
108 * Revision 1.43  2000/05/25 21:40:42  hurwitz
109 * rows hidden in DDV are hidden in DDE, can save edits when rows are hidden in DDE
110 *
111 * Revision 1.42  2000/05/24 21:42:59  hurwitz
112 * getting hide/show rows to work with DDV and DDE together
113 *
114 * Revision 1.41  2000/05/19 13:48:31  hurwitz
115 * made a version of DDE that doesn't allow aligned gaps, changed wording for adding new rows
116 *
117 * Revision 1.40  2000/05/16 19:43:01  hurwitz
118 * grey out create block, delete block, undo, and redo as needed
119 *
120 * Revision 1.39  2000/05/08 22:48:33  hurwitz
121 * on launch of DDE, merge nodes that are same MsaTxtDisp alignment and gap
122 *
123 * Revision 1.38  2000/05/05 20:24:13  hurwitz
124 * some bug fixes, also redraw proper block in DDE after a save operation that causes a merge of 2 blocks
125 *
126 * Revision 1.37  2000/05/04 22:43:38  hurwitz
127 * don't launch DDE on top of DDV, change some wording, redraw DDE after save to AlnMgr
128 *
129 * Revision 1.36  2000/05/02 19:50:38  hurwitz
130 * fixed some bugs with launching DDE from DDV, added new alnMgr fn for positioning DDE on proper column
131 *
132 * Revision 1.35  2000/04/27 17:01:44  hurwitz
133 * small fixes to shift row and shift boundary
134 *
135 * Revision 1.34  2000/04/26 21:54:27  hurwitz
136 * added save function to tell AlnMgr about edits made in DDE
137 *
138 * Revision 1.33  2000/04/21 23:00:51  hurwitz
139 * can launch DDE from DDV
140 *
141 * Revision 1.32  2000/04/13 18:57:03  hurwitz
142 * for DDE: many bug fixes, also get rid of columns that are all unaligned gaps
143 *
144 * Revision 1.31  2000/04/10 20:58:42  hurwitz
145 * added GUI controls for DeleteBlock in DDE
146 *
147 * Revision 1.30  2000/04/07 16:21:08  hurwitz
148 * made delete block faster, added delete block to edit menu
149 *
150 * Revision 1.29  2000/04/05 20:52:35  hurwitz
151 * added GUI control for shifting left and right alignment boundaries
152 *
153 * Revision 1.28  2000/04/04 22:18:43  lewisg
154 * add defline to ddv, fix seq import bugs, set boundbox
155 *
156 * Revision 1.27  2000/04/03 22:26:31  hurwitz
157 * can now shift a row with click and drag
158 *
159 * Revision 1.26  2000/03/30 23:35:22  hurwitz
160 * fixed a bug involving scrolling while moving a row
161 *
162 * Revision 1.25  2000/03/29 20:02:48  hurwitz
163 * keep track of master during move row operations
164 *
165 * Revision 1.24  2000/03/28 21:03:14  hurwitz
166 * added gui control to re-order rows
167 *
168 * Revision 1.23  2000/03/27 18:07:48  hurwitz
169 * page up and page down working, give panel focus on launch
170 *
171 * Revision 1.22  2000/03/25 00:22:09  hurwitz
172 * put DDE_StackPtr in DDV_Main, add to stack inside DDE api's, added insert char, delete char, home and end keyboard control
173 *
174 * Revision 1.21  2000/03/01 22:49:41  lewisg
175 * import bioseq, neatlyindex, get rid of dead code
176 *
177 * Revision 1.20  2000/03/01 20:23:39  durand
178 * update select/deselect code to allow DDV sending correct message to Cn3D
179 *
180 * Revision 1.19  2000/02/15 22:40:57  lewisg
181 * add ability to launch udv so that it colors by row, fixes to colormgr, track rows from viewmgr, fix visual c projects
182 *
183 * Revision 1.18  2000/02/07 18:57:58  durand
184 *  fixed a selection problem
185 *
186 * Revision 1.17  2000/02/04 16:05:40  durand
187 * add click action to select a row
188 *
189 * Revision 1.16  2000/02/02 14:44:29  durand
190 * added function to create data structure for block editor, fixed some bugs
191 *
192 * Revision 1.15  2000/01/12 15:49:42  durand
193 * add About dlg box and fix a bug in selection
194 *
195 * Revision 1.14  2000/01/10 15:09:45  durand
196 * Use Entrez instead of ID1
197 *
198 * Revision 1.13  2000/01/05 21:11:13  durand
199 * update mouse click actions and DrawSequence function for a better use from ddv and cn3d
200 *
201 * Revision 1.12  1999/12/07 21:40:13  durand
202 * add mouse modes menu and caret facility for the editor
203 *
204 * Revision 1.11  1999/12/06 16:19:19  durand
205 * add GoTo facility to DDV
206 *
207 * Revision 1.10  1999/12/03 23:17:22  lewisg
208 * Patrick's new global update msg, argument passing when launching ddv, experimental editing
209 *
210 * Revision 1.9  1999/11/29 15:26:25  durand
211 * designed a new GUI to fix problems under MacOS, Linux and SGI
212 *
213 * Revision 1.8  1999/11/18 00:21:42  lewisg
214 * draw speedups and selection on mouseup
215 *
216 * Revision 1.7  1999/11/17 22:44:01  durand
217 * speed up the selection manager for large SeqAlign
218 *
219 * Revision 1.6  1999/11/03 21:29:48  durand
220 * add CTRL and SHFT keys for mouse selection. redesign the loader functions of DDV to properly register the message callbacks
221 *
222 * Revision 1.5  1999/10/29 14:15:39  durand
223 * add simple mouse selection functions
224 *
225 * Revision 1.4  1999/10/22 14:19:05  durand
226 * add new code for mouse selection
227 *
228 * Revision 1.3  1999/10/21 13:12:43  durand
229 * update selection system
230 *
231 * Revision 1.2  1999/10/12 15:01:28  lewisg
232 * resolve confict with internal/ddv
233 *
234 * Revision 1.1  1999/09/30 14:10:24  durand
235 * add ddv to toolkit
236 *
237 * Revision 1.2  1999/09/22 20:41:17  durand
238 * add mouse-click and drag functions
239 *
240 * Revision 1.1  1999/09/21 14:19:59  durand
241 * add basic mouse management functions
242 *
243 *
244 *
245 * ==========================================================================
246 */
247 
248 #include <ncbi.h>
249 #include <vibrant.h>
250 
251 #include <udviewer.h>
252 #include <ddvpanel.h>
253 #include <ddvclick.h>
254 #include <ddvgraph.h>
255 #include <alignmgr.h>
256 #include <sqnutils.h>
257 #include <seqmgr.h>
258 #include <pgppop.h>
259 #include <samutil.h>
260 #include <tofasta.h>
261 #include <viewmgr.h>
262 
263 /*static MonitorPtr  mon=NULL;*/
264 static Boolean OnAlignmentBoundary(PoinT pt, PaneL p, DdvMainPtr dmp,
265                                    Int4* pBlockIndex, Boolean* pLeftBoundary,
266                                    Int4* pCol, Int4* pHPos);
267 static Boolean GetBlockAndAlignment(PoinT pt, PaneL p, DdvMainPtr dmp,
268                                     Int4* pBlockIndex, Boolean* pIsUnAligned,
269                                     Int4* pCol, Int4* pOffset, Int4* pWidth, RecT* rcP);
270 static Boolean GetBlockAndAlignmentForCol(DdvMainPtr dmp, Int4 Col, Int4* pBlockIndex,
271                                           Boolean* pIsUnAligned, Int4* pOffset, Int4* pWidth);
272 static RecT DrawOutline(PaneL p, Int4 Line_num_start, Int4 Disp_coord_start,
273                         Int4 Line_num_stop, Int4 Disp_coord_stop, Boolean Draw);
274 static RecT DrawOutlineGivenScroll(PaneL p, Int4 Line_num_start, Int4 Disp_coord_start,
275                                    Int4 Line_num_stop, Int4 Disp_coord_stop,
276                                    Int4 VScroll, Int4 HScroll, Boolean Draw);
277 static void EraseOutline(PaneL p);
278 static Boolean RectanglesAreSame(RecT rc1, RecT rc2);
279 static void DDV_SelectRegion(DdvMainPtr dmp, PoinT pt, RecT rc,
280                              Int4 row_start, Int4 row_stop,
281                              Int4 col_start, Int4 col_stop);
282 
283 
DDV_GetHPixelPosGivenColNumberAndScroll(DdvMainPtr dmp,RecT rc,Int4 Col,Int4 ScrollPos)284 NLM_EXTERN Int4 DDV_GetHPixelPosGivenColNumberAndScroll(DdvMainPtr dmp, RecT rc,
285                                                         Int4 Col, Int4 ScrollPos) {
286 /*****************************************************************************
287 *  return number of pixels right to (0-based) Col.
288 *****************************************************************************/
289   Int4  NumPixels;
290 
291 	InsetRect(&rc,4,4);
292 	DDV_AdjustDrawingRect(&rc,&(dmp->GrData.udv_font),dmp);
293   NumPixels = (Col+1-ScrollPos) * dmp->GrData.udv_font.ColWidth;
294   NumPixels += dmp->GrData.udv_panel.cxName + dmp->GrData.udv_scale.cxLeftScale;
295   NumPixels += rc.left;
296   return(NumPixels);
297 }
298 
299 
DDV_GetHPixelPosGivenColNumber(DdvMainPtr dmp,RecT rc,Int4 Col)300 NLM_EXTERN Int4 DDV_GetHPixelPosGivenColNumber(DdvMainPtr dmp, RecT rc, Int4 Col) {
301 /*****************************************************************************
302 *  return number of pixels right to (0-based) Col for current ScrollPos.
303 *****************************************************************************/
304   return(DDV_GetHPixelPosGivenColNumberAndScroll(dmp, rc, Col, dmp->GrData.udv_hscrl.ScrollPos));
305 }
306 
307 
DDV_GetVPixelPosGivenRowNumberAndScroll(DdvMainPtr dmp,RecT rc,Int4 Row,Int4 ScrollPos)308 NLM_EXTERN Int4 DDV_GetVPixelPosGivenRowNumberAndScroll(DdvMainPtr dmp, RecT rc,
309                                                         Int4 Row, Int4 ScrollPos) {
310 /*****************************************************************************
311 *  return number of pixels down to (0-based) Row.
312 *****************************************************************************/
313   Int4  NumPixels;
314 
315 	InsetRect(&rc,4,4);
316 	DDV_AdjustDrawingRect(&rc,&(dmp->GrData.udv_font), dmp);
317   NumPixels = (Row+1-ScrollPos) * dmp->GrData.udv_font.LineHeight;
318   /* next line is copied from DDV_GetRowGivenMousePos */
319   NumPixels += 3*dmp->GrData.udv_panel.cyScale/2;
320   NumPixels += rc.top;
321   return(NumPixels);
322 }
323 
324 
DDV_GetVPixelPosGivenRowNumber(DdvMainPtr dmp,RecT rc,Int4 Row)325 NLM_EXTERN Int4 DDV_GetVPixelPosGivenRowNumber(DdvMainPtr dmp, RecT rc, Int4 Row) {
326 /*****************************************************************************
327 *  return number of pixels down to (0-based) Row for current scrollPos.
328 *****************************************************************************/
329   return(DDV_GetVPixelPosGivenRowNumberAndScroll(dmp, rc, Row, dmp->GrData.udv_vscrl.ScrollPos));
330 }
331 
332 
DDV_GetVPixelPosOfEmptySpace(DdvMainPtr dmp,RecT rc,Int4 * pTop,Int4 * pBot)333 NLM_EXTERN void DDV_GetVPixelPosOfEmptySpace(DdvMainPtr dmp, RecT rc, Int4* pTop, Int4* pBot) {
334 /*****************************************************************************
335 *  return Top:  number of pixels down to top of empty space.
336 *  return Bot:  number of pixels down to bot of empty space.
337 *****************************************************************************/
338 	InsetRect(&rc,4,4);
339   *pTop = rc.top;
340   *pBot = rc.top + dmp->GrData.udv_panel.cyScale/2;
341   return;
342 }
343 
344 
DDV_GetColNumberGivenMousePos(DdvMainPtr dmp,RecT rc,PoinT pt)345 NLM_EXTERN Int4 DDV_GetColNumberGivenMousePos(DdvMainPtr dmp, RecT rc, PoinT pt) {
346 /*****************************************************************************
347 *  return the display coordinate at this mouse position.
348 *****************************************************************************/
349   Int4  mouse_col;
350 
351 	InsetRect(&rc,4,4);
352 	DDV_AdjustDrawingRect(&rc,&(dmp->GrData.udv_font),dmp);
353 	rc.left+=dmp->GrData.udv_panel.cxName + dmp->GrData.udv_scale.cxLeftScale;
354 	mouse_col=(pt.x-rc.left)/dmp->GrData.udv_font.ColWidth+
355 		dmp->GrData.udv_hscrl.ScrollPos;
356   return(mouse_col);
357 }
358 
359 
360 /*****************************************************************************
361 
362 Function: DDV_GetRowGivenMousePos()
363 
364 Purpose: given some graphical info, this function returns line_num, the row
365 		number (absolute value) and the ParaGLine_Num (i.e. sequence/row
366 
367 		number; this value must be use to get data from TableHead).
368 
369 Return value: line_num (-1 if not found ; otherwise a one-based value)
370 
371 *****************************************************************************/
DDV_GetRowGivenMousePos(DdvMainPtr dmp,RecT * rcP,PoinT * pt,Int4Ptr ParaGLine_Num)372 static Int4 DDV_GetRowGivenMousePos(DdvMainPtr dmp, RecT * rcP, PoinT * pt,
373 
374 			Int4Ptr ParaGLine_Num)
375 {
376 Int4 Line_num=(Int4)-1,mouse_row,i,n;
377 ParaGPtr pgp;
378 
379 	/*size of the Panel; see also DDV_DrawPanelContent_H()*/
380 	InsetRect(rcP,4,4);
381 	DDV_AdjustDrawingRect(rcP,&(dmp->GrData.udv_font),dmp);
382 	rcP->left+=dmp->GrData.udv_panel.cxName+dmp->GrData.udv_scale.cxLeftScale;
383 	rcP->top+=3*dmp->GrData.udv_panel.cyScale/2;
384 
385 	/*mouse position*/
386 	mouse_row=(pt->y-rcP->top)/dmp->GrData.udv_font.LineHeight+
387 		dmp->GrData.udv_vscrl.ScrollPos;
388 
389 	/*use the first ParaG of each sequence and mouse_row to find
390 	row (==sequence) number*/
391 	for(i=0;i<dmp->MSA_d.pgp_l.nBsp;i++){
392 		pgp=(ParaGPtr)(dmp->MSA_d.pgp_l.TableHead[i]->data.ptrvalue);
393 		if (pgp->ScaleStyle==SCALE_POS_NONE) n=0;
394 		else n=1;
395 		/*within each ParaG, the seq. in on line 0 or 1 (if ruler)*/
396 		if (mouse_row>=pgp->StartLine && mouse_row<=(pgp->StartLine+n)){
397 			Line_num=mouse_row+1;
398 
399 			*ParaGLine_Num=i+1;
400 			break;
401 		}
402 	}
403 
404 	return(Line_num);
405 }
406 
407 /*****************************************************************************
408 
409 Function: DDV_GetClosetSeqLocGivenBspPos()
410 
411 Purpose: given a position in the Bioseq, this function return the closest
412          selected region on that bioseq.
413 
414 Parameters:	sip, eID, iID; bsioseq identifiers
415             bsp_pos; current position on that bioseq
416 			old_pos; returns old_pos of a selection (used only if bModify is TRUE)
417 			bModify; if TRUE, create a modified slp
418 
419 Note : sip can be null ONLY if bModify if FALSE.
420 
421 Return value: see Purpose.
422 
423 *****************************************************************************/
DDV_GetClosetSeqLocGivenBspPos(SeqIdPtr sip,Uint2 eID,Uint2 iID,Int4 bsp_pos,Int4Ptr old_pos,Boolean bModify)424 static SeqLocPtr DDV_GetClosetSeqLocGivenBspPos(SeqIdPtr sip, Uint2 eID,
425 		Uint2 iID, Int4 bsp_pos, Int4Ptr old_pos, Boolean bModify)
426 {
427 SelStructPtr ssp;
428 SeqLocPtr    slp=NULL;
429 ValNodePtr   vnp_bsp,vnp;
430 Int4         diff,old_diff,diff_l,diff_r,bsp_start,bsp_stop;
431 Uint1        strand;
432 
433 	ssp=ObjMgrGetSelected();
434 	if (ssp==NULL) return(NULL);
435 
436 	vnp_bsp=DDV_GetSelectedRegions(ssp,eID,iID);
437 	if (vnp_bsp==NULL) return(NULL);
438 	vnp=vnp_bsp;
439 	*old_pos=(Int4)-1;
440 	old_diff=(Int4)INT4_MAX;
441 
442 	while(vnp){
443 		bsp_start=SeqLocStart((SeqLocPtr)vnp->data.ptrvalue);
444 		bsp_stop=SeqLocStop((SeqLocPtr)vnp->data.ptrvalue);
445 		strand=SeqLocStrand((SeqLocPtr)vnp->data.ptrvalue);
446 		if (bsp_pos<bsp_start){/*left of a selected region ?*/
447 			diff=bsp_start-bsp_pos;
448 			if (diff<old_diff){
449 				if (slp) slp=SeqLocFree(slp);
450 				if (bModify){
451 					slp = SeqLocIntNew (bsp_pos, bsp_stop, strand/*Seq_strand_minus*/, sip);
452 					*old_pos=bsp_stop;
453 				}
454 				else{
455 					slp = SeqLocIntNew (bsp_start, bsp_stop, strand, sip);
456 					*old_pos=(Int4)-1;
457 				}
458 				old_diff=diff;
459 			}
460 		}
461 		else if (bsp_pos>bsp_stop){/*right of a selected region ?*/
462 			diff=bsp_pos-bsp_stop;
463 			if (diff<old_diff){
464 				if (slp) slp=SeqLocFree(slp);
465 				if (bModify){
466 					slp = SeqLocIntNew (bsp_start, bsp_pos, strand/*Seq_strand_plus*/, sip);
467 					*old_pos=bsp_start;
468 				}
469 				else{
470 					slp = SeqLocIntNew (bsp_start, bsp_stop, strand, sip);
471 					*old_pos=(Int4)-1;
472 				}
473 				old_diff=diff;
474 			}
475 		}
476 		else{/*inside a selected region ?*/
477 			if(bModify){
478 				diff_l=bsp_pos-bsp_start;
479 				diff_r=bsp_stop-bsp_pos;
480 				if (diff_l<diff_r){
481 					bsp_start=bsp_pos;
482 					*old_pos=bsp_stop;
483 					/*strand=Seq_strand_plus;*/
484 				}
485 				else{
486 					bsp_stop=bsp_pos;
487 					*old_pos=bsp_start;
488 					/*strand=Seq_strand_minus;*/
489 				}
490 				slp = SeqLocIntNew (bsp_start, bsp_stop, strand, sip);
491 				break;
492 			}
493 		}
494 		vnp=vnp->next;
495 	}
496 	ValNodeFree(vnp_bsp);
497 	return(slp);
498 }
499 
500 /*****************************************************************************
501 
502 Function: DDV_IsFullBspAlreadySel()
503 
504 Purpose: check if a row is already selected.
505 
506 Parameters:	bsp_eID,bsp_iID; bsp identifiers
507 			bsp_start,bsp_stop; full sequence
508 
509 Return value: TRUE if the sequence is already fully selected
510 
511 *****************************************************************************/
DDV_IsFullBspAlreadySel(Uint2 bsp_eID,Uint2 bsp_iID,Int4 bsp_start,Int4 bsp_stop)512 static Boolean DDV_IsFullBspAlreadySel(Uint2 bsp_eID,Uint2 bsp_iID,Int4 bsp_start,
513 		Int4 bsp_stop)
514 {
515 SelStructPtr ssp;
516 ValNodePtr   vnp_bsp,vnp;
517 Int4         sel_bsp_start,sel_bsp_stop;
518 
519 	ssp=ObjMgrGetSelected();
520 	if (ssp==NULL) return(FALSE);
521 
522 	vnp_bsp=DDV_GetSelectedRegions(ssp,bsp_eID,bsp_iID);
523 	if (vnp_bsp==NULL) return(FALSE);
524 	vnp=vnp_bsp;
525 
526 	while(vnp){
527 		sel_bsp_start=SeqLocStart((SeqLocPtr)vnp->data.ptrvalue);
528 		sel_bsp_stop=SeqLocStop((SeqLocPtr)vnp->data.ptrvalue);
529 		if (bsp_start==sel_bsp_start && bsp_stop==sel_bsp_stop)
530 			return(TRUE);
531 		vnp=vnp->next;
532 	}
533 	return(FALSE);
534 }
535 
536 
DDV_GetRegionInParaG(ParaGPtr pgp,Int4 Line_num)537 static Uint1 DDV_GetRegionInParaG(ParaGPtr pgp, Int4 Line_num) {
538 /*****************************************************************************
539 *  get region within ParaG
540 *****************************************************************************/
541   Int4  mouse_row, diff;
542 
543   mouse_row = Line_num-1;
544 
545   if (pgp->ScaleStyle==SCALE_POS_NONE)
546     diff=0;
547   else
548     diff=1;
549 
550   if (mouse_row==(pgp->StartLine+diff)){
551     return(PGP_REGION_SEQ);
552   }
553   else if (mouse_row >  (pgp->StartLine+ diff) &&
554            mouse_row <= (pgp->StartLine+ pgp->nLines-1)){
555     return(PGP_REGION_FEAT);
556   }
557   return(PGP_REGION_NOWHERE);
558 }
559 
560 
DDV_GetRowAndColGivenPtAndScroll(DdvMainPtr dmp,RecT rc,PoinT pt,Int4 HScroll,Int4 VScroll,Int4Ptr Disp_coord,Int4Ptr Line_num)561 static void DDV_GetRowAndColGivenPtAndScroll(DdvMainPtr dmp, RecT rc, PoinT pt,
562                                              Int4 HScroll, Int4 VScroll,
563                                              Int4Ptr Disp_coord, Int4Ptr Line_num) {
564 /*****************************************************************************
565 *  get row and column where the mouse is clicked.  Provide scroll positions.
566 *****************************************************************************/
567   Int4  mouse_row, mouse_col;
568 
569   InsetRect(&rc,4,4);
570   DDV_AdjustDrawingRect(&rc, &(dmp->GrData.udv_font), dmp);
571   rc.left += dmp->GrData.udv_panel.cxName + dmp->GrData.udv_scale.cxLeftScale;
572   rc.top += 3*dmp->GrData.udv_panel.cyScale/2;
573 
574   mouse_row = (pt.y - rc.top)/dmp->GrData.udv_font.LineHeight + VScroll;
575   mouse_col = (pt.x - rc.left)/dmp->GrData.udv_font.ColWidth + HScroll;
576 
577   *Line_num=mouse_row+1;
578   *Disp_coord=mouse_col;
579 }
580 
581 
DDV_GetRowAndColGivenPt(DdvMainPtr dmp,RecT rc,PoinT pt,Int4Ptr Disp_coord,Int4Ptr Line_num)582 static void DDV_GetRowAndColGivenPt(DdvMainPtr dmp, RecT rc, PoinT pt,
583                                     Int4Ptr Disp_coord, Int4Ptr Line_num) {
584 /***********************************************************************************
585 *  get row and column where the mouse is clicked.  Assume current scroll positions.
586 ***********************************************************************************/
587   DDV_GetRowAndColGivenPtAndScroll(dmp, rc, pt,
588       dmp->GrData.udv_hscrl.ScrollPos, dmp->GrData.udv_vscrl.ScrollPos,
589       Disp_coord, Line_num);
590 }
591 
592 
DDV_GetParaGLineNumGivenLineNum(DdvMainPtr dmp,Int4 Line_num)593 static Int4 DDV_GetParaGLineNumGivenLineNum(DdvMainPtr dmp, Int4 Line_num) {
594 /*****************************************************************************
595 *  get the ParaGLine_Num for Line_num.
596 *****************************************************************************/
597   Int4      i, row;
598   ParaGPtr  pgp;
599 
600   row = Line_num-1;
601   for (i=0; i<dmp->MSA_d.pgp_l.nBsp; i++) {
602     pgp = (ParaGPtr)(dmp->MSA_d.pgp_l.TableHead[i]->data.ptrvalue);
603     if (row>=pgp->StartLine && row<=(pgp->StartLine + pgp->nLines-1)) {
604       return(i+1);
605     }
606   }
607   return(-1);
608 }
609 
610 
DDV_GetSeqAlignCoordGivenCol(DdvMainPtr dmp,Int4 Disp_coord)611 static Int4 DDV_GetSeqAlignCoordGivenCol(DdvMainPtr dmp, Int4 Disp_coord) {
612 /*****************************************************************************
613 *  get the SeqAlignCoord for Disp_coord.
614 *****************************************************************************/
615   ValNodePtr        vnp;
616   DDVRulerDescrPtr  drdp;
617   Int4              diff;
618 
619   vnp=dmp->MSA_d.pgp_l.RulerDescr;
620   while(vnp){
621     drdp=(DDVRulerDescrPtr)vnp->data.ptrvalue;
622     if (!drdp->bUnAligned){
623       diff = Disp_coord - drdp->disp_start;
624       if (Disp_coord>=drdp->disp_start && Disp_coord<=drdp->disp_stop){
625         return(drdp->align_start + diff);
626       }
627     }
628     vnp=vnp->next;
629   }
630   return(-1);
631 }
632 
633 
DDV_GetPGPGivenRowAndCol(DdvMainPtr dmp,Int4 Line_num,Int4 Disp_coord)634 static ParaGPtr DDV_GetPGPGivenRowAndCol(DdvMainPtr dmp, Int4 Line_num, Int4 Disp_coord) {
635 /*****************************************************************************
636 *  get the ParaG ptr that contains (Line_num, Disp_coord)
637 *****************************************************************************/
638   ParaGPtr    pgp=NULL;
639   ValNodePtr  vnp;
640 
641   vnp=dmp->MSA_d.pgp_l.TableHead[Line_num-1];
642   while(vnp){
643     pgp=(ParaGPtr)vnp->data.ptrvalue;
644     if (Disp_coord>=pgp->StartLetter && Disp_coord<=pgp->StopLetter){
645       return(pgp);
646     }
647     vnp=vnp->next;
648   }
649   return(pgp);
650 }
651 
652 
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)653 static Boolean DDV_GetCoordsGivenAClickAndScrollPos(DdvMainPtr dmp, RecT * rcP, PoinT * pt,
654     Int4 HScroll, Int4 VScroll,
655 		Int4Ptr bsp_coord, Int4Ptr SeqAlign_coord, Int4Ptr Disp_coord,
656 		Int4Ptr Line_num, Int4Ptr ParaGLine_Num, Uint1Ptr uWhere,
657 		ParaGPtr PNTR cur_pgp)
658 /*****************************************************************************
659 *  variation on DDV_GetCoordsGivenAClick.
660 *  pass: VScroll and HScroll -- the positions of the vertical and
661 *        horizontal scroll bars.
662 *****************************************************************************/
663 {
664 ValNodePtr     vnp;
665 ParaGPtr       pgp,TheParaG;
666 /*MsaTxtDispPtr  mtdp;*/
667 DDVRulerDescrPtr drdp;
668 Int4           mouse_row,mouse_col,i,diff;
669 Boolean        bFound;
670 
671   *ParaGLine_Num = -1;
672 	/*size of the Panel; see also DDV_DrawPanelContent_H()*/
673 	InsetRect(rcP,4,4);
674 	DDV_AdjustDrawingRect(rcP,&(dmp->GrData.udv_font),dmp);
675 	rcP->left+=dmp->GrData.udv_panel.cxName+dmp->GrData.udv_scale.cxLeftScale;
676 	rcP->top+=3*dmp->GrData.udv_panel.cyScale/2;
677 
678 	/*mouse position*/
679 	mouse_row=(pt->y-rcP->top)/dmp->GrData.udv_font.LineHeight+VScroll;
680 	mouse_col=(pt->x-rcP->left)/dmp->GrData.udv_font.ColWidth+HScroll;
681 
682 	bFound=FALSE;
683 
684 	for(i=0;i<dmp->MSA_d.pgp_l.nBsp;i++){
685 		/*use the first ParaG of each sequence and mouse_row to find
686 		row (==sequence) number; then go though the ParaG list of that
687 		sequence to find The ParaG, using mouse_col*/
688 		pgp=(ParaGPtr)(dmp->MSA_d.pgp_l.TableHead[i]->data.ptrvalue);
689 		if (mouse_row>=pgp->StartLine && mouse_row<=(pgp->StartLine+pgp->nLines-1)){
690 			vnp=dmp->MSA_d.pgp_l.TableHead[i];
691 		    *ParaGLine_Num = i + 1;
692 			while(vnp){
693 				pgp=(ParaGPtr)vnp->data.ptrvalue;
694 				if (mouse_col>=pgp->StartLetter && mouse_col<=pgp->StopLetter){
695 					bFound=TRUE;
696 					TheParaG=pgp;
697 					break;
698 				}
699 				vnp=vnp->next;
700 			}
701 			if (bFound) break;
702 		}
703 	}
704 	/*ok : the mouse is inside a ParaG*/
705 	if (bFound){
706 		*cur_pgp=TheParaG;
707 		/*where is the mouse in the ParaG ?*/
708 		*uWhere=PGP_REGION_NOWHERE;
709 		if (TheParaG->ScaleStyle==SCALE_POS_NONE)
710 			diff=0;
711 		else
712 			diff=1;
713 		if (mouse_row==(TheParaG->StartLine+diff)){
714 			*uWhere=PGP_REGION_SEQ;
715 		}
716 		else if (mouse_row>(TheParaG->StartLine+diff) &&
717 				mouse_row<=(pgp->StartLine+pgp->nLines-1)){
718 			*uWhere=PGP_REGION_FEAT;
719 		}
720 
721 		/*a. get Disp Coord*/
722 		*Line_num=mouse_row+1;/*base 1 value*/
723 		*Disp_coord=mouse_col;
724 
725 		/*on the Sequence ? Then, get the coords. (BSP, DISP, SEQALIGN)*/
726 		/*PGP_REGION_FEAT is not yet implemented...  ;-) */
727 		if (*uWhere==PGP_REGION_SEQ){
728 			/*b. get BSP coord*/
729 			*bsp_coord=DDV_GetBspCoordGivenDispCoord(TheParaG,mouse_col);
730 
731 			/*c. get SeqAlign Coord*/
732 			vnp=dmp->MSA_d.pgp_l.RulerDescr;
733 			while(vnp){
734 				drdp=(DDVRulerDescrPtr)vnp->data.ptrvalue;
735 				if (!drdp->bUnAligned){
736 					diff=mouse_col-drdp->disp_start;
737 					if (mouse_col>=drdp->disp_start && mouse_col<=drdp->disp_stop){
738 						*SeqAlign_coord=drdp->align_start+diff;
739 						break;
740 					}
741 				}
742 				else{
743 					*SeqAlign_coord=(Int4)-1;
744 				}
745 				vnp=vnp->next;
746 			}
747 		}
748 	}
749 
750 	return(bFound);
751 }
752 
753 
754 /*****************************************************************************
755 
756 Function: DDV_GetCoordsGivenAClick()
757 
758 Purpose: given some graphical info, this function returns bsp_coord, SeqAlign_coord,
759          Disp_coord. Future implementation : will also return eID, iID, idx of
760 		 a feature (if the nice user clicks on a feature).
761 
762 Parameters:	dmp; panel main data block
763             rcP; panel size
764 			pt; mouse position
765 			bsp_coord, SeqAlign_coord, Disp_coord,Line_num; return values
766             uWhere; where the mouse is in a ParaG
767 
768 Note : all but Line_num are zero-based values. Line_num is a one-based value.
769 
770 Return value: TRUE if the user clicks within a ParaG (see also
771 		bsp_coord, SeqAlign_coord, Disp_coord, uWhere). NOTE : if the function
772 		returns FALSE then bsp_coord, SeqAlign_coord, Line_num, Disp_coord and
773 		uWhere are undefined !
774 
775 *****************************************************************************/
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)776 static Boolean DDV_GetCoordsGivenAClick(DdvMainPtr dmp, RecT * rcP, PoinT * pt,
777 		Int4Ptr bsp_coord, Int4Ptr SeqAlign_coord, Int4Ptr Disp_coord,
778 		Int4Ptr Line_num, Int4Ptr ParaGLine_Num, Uint1Ptr uWhere,
779 		ParaGPtr PNTR cur_pgp)
780 {
781   /* return coordinates for the current scroll position */
782   return(DDV_GetCoordsGivenAClickAndScrollPos(dmp, rcP, pt,
783     dmp->GrData.udv_hscrl.ScrollPos, dmp->GrData.udv_vscrl.ScrollPos,
784     bsp_coord, SeqAlign_coord, Disp_coord, Line_num, ParaGLine_Num, uWhere, cur_pgp));
785 }
786 
787 /*****************************************************************************
788 
789 Function: DDV_AutoHScroll()
790 
791 Purpose: used from drag/hold mouse to auto-scroll the panel horizontally when
792          the mouse reaches the left/right borders of the panel
793 
794 
795 Return value: none
796 
797 *****************************************************************************/
DDV_AutoHScroll(DdvMainPtr dmp,Int4 Disp_coord)798 static void DDV_AutoHScroll(DdvMainPtr dmp,Int4 Disp_coord)
799 {
800 Int4 from_col,to_col,from_row,to_row,old_pos;
801 BaR hsb;
802 
803 	DDV_GetCurrentDispRange(dmp->hWndDDV,&(dmp->GrData),dmp->MSA_d.pgp_l.LengthAli,
804 			&from_col,&to_col,&from_row,&to_row);
805 
806 	hsb = GetSlateHScrollBar ((SlatE) dmp->hWndDDV);
807 	old_pos=GetBarValue(hsb);
808 	if (Disp_coord>=to_col){/*scroll to the right*/
809 		SetValue(hsb,old_pos+1);
810 	}
811 	else if (Disp_coord<=from_col){
812 		SetValue(hsb,old_pos-1);
813 	}
814 
815 }
816 
817 /*****************************************************************************
818 
819 Function: DDV_AutoVScroll()
820 
821 Purpose: used from drag/hold mouse to auto-scroll the panel vertically when
822          the mouse reaches the top/bottom borders of the panel
823 
824 
825 Return value: none
826 
827 *****************************************************************************/
DDV_AutoVScroll(DdvMainPtr dmp,Int4 Line_num)828 static void DDV_AutoVScroll(DdvMainPtr dmp,Int4 Line_num)
829 {
830 Int4 from_col,to_col,from_row,to_row,old_pos;
831 BaR vsb;
832 
833 	DDV_GetCurrentDispRange(dmp->hWndDDV,&(dmp->GrData),dmp->MSA_d.pgp_l.LengthAli,
834 			&from_col,&to_col,&from_row,&to_row);
835 
836 	vsb = GetSlateVScrollBar ((SlatE) dmp->hWndDDV);
837 	old_pos=GetBarValue(vsb);
838 	if (Line_num>=(to_row-1)){/*scroll down*/
839 		SetValue(vsb,old_pos+1);
840 	}
841 	else if (Line_num<=(from_row+1)){/*scroll up*/
842 		SetValue(vsb,old_pos-1);
843 	}
844 }
845 
846 
847 /*****************************************************************************
848 
849 Function: DDV_DispSelRangeInStatus()
850 
851 Purpose: display position while selection is in progress. (mouse mode : selection)
852 
853 Return value: none
854 
855 *****************************************************************************/
DDV_DispSelRangeInStatus(PrompT InfoPanel,Int4 bsp_start,Int4 bsp_stop,Int4 line_num,CharPtr szSeqName)856 static void DDV_DispSelRangeInStatus(PrompT InfoPanel,Int4 bsp_start, Int4 bsp_stop,
857 		Int4 line_num,CharPtr szSeqName)
858 {
859 Char szText[250];
860 
861 	sprintf(szText,"Selection : %s, [%i]:[%i..%i]",szSeqName,line_num,
862 		bsp_start,bsp_stop);
863 	SetTitle(InfoPanel,szText);
864 }
865 
866 
867 /*****************************************************************************
868 
869 Function: DDV_DispPositionInStatus()
870 
871 Purpose: display position (mouse mode : query).
872 
873 Return value: none
874 
875 *****************************************************************************/
DDV_DispPositionInStatus(PrompT InfoPanel,Int4 bsp_pos,Int4 line_num,CharPtr szSeqName)876 NLM_EXTERN void DDV_DispPositionInStatus(PrompT InfoPanel,Int4 bsp_pos,
877 		Int4 line_num,CharPtr szSeqName)
878 {
879 Char szText[250];
880 
881 	sprintf(szText,"Position : %s, [%i]:[%i]",szSeqName,line_num,bsp_pos);
882 	SetTitle(InfoPanel,szText);
883 }
884 
885 
DDV_DispStatus(DdvMainPtr dmp,Int4 Line_num_stop,Int4 Disp_coord_start,Int4 Disp_coord_stop)886 static void DDV_DispStatus(DdvMainPtr dmp, Int4 Line_num_stop,
887                            Int4 Disp_coord_start, Int4 Disp_coord_stop) {
888 /*****************************************************************************
889 
890 Function: DDV_DispStatus()
891 
892 Purpose: display position while selection is in progress. (mouse mode : selection)
893 
894 Return value: none
895 
896 *****************************************************************************/
897   DdvMainWinPtr  mWin_d;
898   Int4           ParaGLine_num, bsp_start, bsp_stop;
899   ParaGPtr       pgp;
900   char           szAccess[21];
901 
902   mWin_d = (DdvMainWinPtr) GetObjectExtra(dmp->hParent);
903   if (mWin_d != NULL) {
904     ParaGLine_num = DDV_GetParaGLineNumGivenLineNum(dmp, Line_num_stop);
905     if (ParaGLine_num != -1) {
906       DDV_GetSeqNameGivenRow(dmp->MSA_d.pgp_l.TableHead, ParaGLine_num, szAccess);
907       pgp = DDV_GetPGPGivenRowAndCol(dmp, Line_num_stop, Disp_coord_stop);
908       bsp_stop = DDV_GetBspCoordGivenDispCoord(pgp, Disp_coord_stop);
909       if (dmp->MouseMode == DDV_MOUSEMODE_SELECT ||
910           dmp->MouseMode == DDV_MOUSEMODE_SELECT_ONE_ROW) {
911         pgp = DDV_GetPGPGivenRowAndCol(dmp, Line_num_stop, Disp_coord_start);
912         bsp_start = DDV_GetBspCoordGivenDispCoord(pgp, Disp_coord_start);
913         DDV_DispSelRangeInStatus(mWin_d->InfoPanel, bsp_start+1, bsp_stop+1,
914           ParaGLine_num, szAccess);
915       }
916       else {
917         DDV_DispPositionInStatus(mWin_d->InfoPanel, bsp_stop+1,
918           ParaGLine_num, szAccess);
919       }
920     }
921   }
922 }
923 
924 
925 /*****************************************************************************
926 
927 Function: DDV_GetSeqNameGivenRow()
928 
929 Purpose: get a sequence number, given a list of ParaG and a row number
930 
931 Note: row_num is a one-based value; this value must be in the range 0 to nBsp.
932 
933 (I don't check that here, so be carefull when calling this function)
934 
935 
936 Return value: -
937 
938 *****************************************************************************/
DDV_GetSeqNameGivenRow(ValNodePtr * ParaG_List,Int4 row_num,CharPtr szSeqName)939 NLM_EXTERN void DDV_GetSeqNameGivenRow(ValNodePtr * ParaG_List, Int4 row_num,
940 	CharPtr szSeqName)
941 {
942   SeqIdPtr sip;
943   ParaGPtr pgp;
944   BioseqPtr bsp;
945 
946   pgp=(ParaGPtr)(ParaG_List[row_num-1]->data.ptrvalue);
947 
948   /*get a name*/
949   bsp = BioseqLockById(pgp->sip);
950   if(bsp) {
951     /* get name but not gi */
952     sip = SeqIdFindBestAccession(bsp->id);
953     BioseqUnlock(bsp);
954   }
955 
956   if (!sip)
957     sip = SeqIdFindBest(pgp->sip, 0);
958   SeqIdWrite(sip, szSeqName,PRINTID_TEXTID_ACCESSION, 20);
959 }
960 
961 /*****************************************************************************
962 
963 Function: DDV_SendBSPSelectMsg_OLD()
964 
965 Purpose: send a message to select a range of letters on a bioseq.
966 
967 Return value: none
968 
969 *****************************************************************************/
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)970 static void DDV_SendBSPSelectMsg_OLD(DdvMainPtr dmp,Int4 bsp_coord,Int4 SeqAlign_coord,
971 		Int4 first_Disp_coord, Int4 Disp_coord,Int4 Line_num,Int4 ParaGLine_Num,
972     ParaGPtr cur_pgp,PoinT * pt, Boolean Display)
973 {
974 Int4        first_bsp_coord, bsp_pos;
975 Uint1       direction;/*use to tell ObjMgr the direction of the mouse (left,right)*/
976 SeqLocPtr   slp;/*to send an AlsoSelectMsg*/
977 Uint2       bsp_eID;
978 Uint4       bsp_iID;
979 Boolean     bDeselectAll=TRUE;
980 DdvMainWinPtr dmwp;
981 
982 	/*analyse the bsp coords*/
983 	if (bsp_coord==(Int4)-1){/*this is a gap*/
984 		dmp->ms.oldPos=dmp->ms.newPos=*pt;
985 		dmp->ms.old_row=Line_num;
986 		dmp->ms.old_col=Disp_coord;
987 		dmp->ms.old_pgp=cur_pgp;
988 		return;
989 	}
990 
991 	/*get the very first click (from DDV_ClickProc)*/
992 	first_bsp_coord=
993 		DDV_GetBspCoordGivenDispCoord(dmp->ms.first_pgps[Line_num-1],
994                                   dmp->ms.first_cols[Line_num-1]);
995 	if (first_bsp_coord==(Int4)-1){/*the first time the user
996 		clicked, it was on a gap*/
997 		/*if we are in this scope, that means we have a bsp coord*/
998 		first_bsp_coord=bsp_coord;
999 		dmp->ms.first_cols[Line_num-1]=Disp_coord;
1000 		dmp->ms.first_pgps[Line_num-1]=cur_pgp;
1001 	}
1002 
1003 	bsp_pos=bsp_coord;
1004 
1005 	if (ctrlKey || shftKey)
1006 		bDeselectAll=FALSE;
1007 
1008 	/*the mouse is moving to the left or to the right ?*/
1009 	/*don't forget to check the strand...  ;-) */
1010 	if (AlnMgrGetNthStrand(dmp->MSA_d.pgp_l.sap, ParaGLine_Num)==Seq_strand_plus){
1011 		if (dmp->ms.oldPos.x<pt->x)
1012 			direction=Seq_strand_plus;
1013 		else
1014 			direction=Seq_strand_minus;
1015 	}
1016 	else{
1017 		if (dmp->ms.oldPos.x>pt->x)
1018 			direction=Seq_strand_minus;
1019 		else
1020 			direction=Seq_strand_plus;
1021 	}
1022 	/*'from' (first_bsp_coord) always less than 'to' (bsp_coord)*/
1023 	if (first_bsp_coord>bsp_coord)
1024 		swap(&first_bsp_coord,&bsp_coord);
1025 	/*save the new position*/
1026 	dmp->ms.oldPos=dmp->ms.newPos=*pt;
1027 	dmp->ms.old_row=Line_num;
1028 	dmp->ms.old_col=Disp_coord;
1029 	dmp->ms.old_pgp=cur_pgp;
1030 
1031 	/*now, we can send the Select message*/
1032 	/* first_pgp, old_pgp & cur_pgp have the same sip...
1033 	they are on a same row; I can use one of them*/
1034 	slp = SeqLocIntNew (first_bsp_coord, bsp_coord, direction, cur_pgp->sip);
1035 	UDV_DecodeIdxFeat (dmp->MSA_d.pgp_l.entitiesTbl[ParaGLine_Num-1],&bsp_eID,&bsp_iID);
1036   if (bsp_eID!=0 && bsp_iID!=0 && slp){
1037     /*update InfoPanel*/
1038     dmwp=(DdvMainWinPtr)GetObjectExtra(dmp->hParent);
1039     if (dmwp){
1040       Char szAccess[21];
1041 
1042       DDV_GetSeqNameGivenRow(dmp->MSA_d.pgp_l.TableHead, ParaGLine_Num, szAccess);
1043 
1044       switch(dmp->MouseMode){
1045         case DDV_MOUSEMODE_SELECT:
1046         case DDV_MOUSEMODE_SELECT_ONE_ROW:
1047           if (Display) {
1048             DDV_DispSelRangeInStatus(dmwp->InfoPanel,first_bsp_coord+1,
1049               bsp_coord+1,ParaGLine_Num,szAccess);/*+1 : switch to one-based value*/
1050           }
1051           break;
1052         case DDV_MOUSEMODE_QUERY:
1053         case DDV_MOUSEMODE_EDIT:
1054           DDV_DispPositionInStatus(dmwp->InfoPanel,
1055             bsp_pos+1,ParaGLine_Num,szAccess);/*+1 : switch to one-based value*/
1056           break;
1057       }
1058     }
1059 		/*send the message*/
1060     if (dmp->MouseMode==DDV_MOUSEMODE_SELECT ||
1061         dmp->MouseMode==DDV_MOUSEMODE_SELECT_ONE_ROW){
1062       ObjMgrAlsoSelect (bsp_eID, bsp_iID, OBJ_BIOSEQ,OM_REGION_SEQLOC, slp);
1063     }
1064   }
1065   else {
1066     if (slp)
1067       SeqLocFree(slp);
1068   }
1069 }
1070 
1071 
1072 /*****************************************************************************
1073 
1074 Function: DDV_SendBSPSelectMsg()
1075 
1076 Purpose: send a message to select a range of letters on a bioseq.
1077          I've rewritten this.  Hope I did it right.  Dave H.
1078 
1079 Return value: none
1080 
1081 *****************************************************************************/
DDV_SendBSPSelectMsg(DdvMainPtr dmp,Int4 col_start,Int4 col_stop,Int4 row,Boolean Display)1082 static void DDV_SendBSPSelectMsg(DdvMainPtr dmp,
1083 		Int4 col_start, Int4 col_stop, Int4 row, Boolean Display)
1084 {
1085   Int4           bsp_coord_start, bsp_coord_stop, ParaGLine_Num, col;
1086   Uint1          direction;/*used to tell ObjMgr the direction of the mouse (left,right)*/
1087   SeqLocPtr      slp;/*to send an AlsoSelectMsg*/
1088   Uint2          bsp_eID;
1089   Uint4          bsp_iID;
1090   Boolean        bDeselectAll=TRUE;
1091   ParaGPtr       pgp;
1092   DdvMainWinPtr  dmwp;
1093 
1094   if (col_start > col_stop) swap(&col_start, &col_stop);
1095 
1096   /* calculate bsp_coord_start */
1097   for (col=col_start; col<=col_stop; col++) {
1098     pgp = DDV_GetPGPGivenRowAndCol(dmp, row, col);
1099     bsp_coord_start = DDV_GetBspCoordGivenDispCoord(pgp, col);
1100     if (bsp_coord_start != -1) break;
1101   }
1102 
1103   /* calculate bsp_coord_stop */
1104   for (col=col_stop; col>=col_start; col--) {
1105     pgp = DDV_GetPGPGivenRowAndCol(dmp, row, col);
1106     bsp_coord_stop = DDV_GetBspCoordGivenDispCoord(pgp, col);
1107     if (bsp_coord_stop != -1) break;
1108   }
1109 
1110   ParaGLine_Num = DDV_GetParaGLineNumGivenLineNum(dmp, row);
1111 
1112 	if (ctrlKey || shftKey)
1113 		bDeselectAll=FALSE;
1114 
1115 	/*the mouse is moving to the left or to the right ?*/
1116 	/*don't forget to check the strand...  ;-) */
1117   if (AlnMgrGetNthStrand(dmp->MSA_d.pgp_l.sap, ParaGLine_Num)==Seq_strand_plus) {
1118     direction=Seq_strand_plus;
1119   }
1120   else {
1121     direction=Seq_strand_minus;
1122   }
1123 
1124   /*now, we can send the Select message*/
1125   /* first_pgp, old_pgp & cur_pgp have the same sip...
1126   they are on a same row; I can use one of them*/
1127   slp = SeqLocIntNew (bsp_coord_start, bsp_coord_stop, direction, pgp->sip);
1128   UDV_DecodeIdxFeat (dmp->MSA_d.pgp_l.entitiesTbl[ParaGLine_Num-1],&bsp_eID,&bsp_iID);
1129   if (bsp_eID!=0 && bsp_iID!=0 && slp){
1130     /*update InfoPanel*/
1131     dmwp=(DdvMainWinPtr)GetObjectExtra(dmp->hParent);
1132     if (dmwp){
1133       Char szAccess[21];
1134 
1135       DDV_GetSeqNameGivenRow(dmp->MSA_d.pgp_l.TableHead, ParaGLine_Num, szAccess);
1136 
1137       switch(dmp->MouseMode){
1138         case DDV_MOUSEMODE_SELECT:
1139         case DDV_MOUSEMODE_SELECT_ONE_ROW:
1140           if (Display) {
1141             DDV_DispSelRangeInStatus(dmwp->InfoPanel, bsp_coord_start+1,
1142               bsp_coord_stop+1, ParaGLine_Num, szAccess); /*+1 : switch to one-based value*/
1143           }
1144           break;
1145         case DDV_MOUSEMODE_QUERY:
1146         case DDV_MOUSEMODE_EDIT:
1147           DDV_DispPositionInStatus(dmwp->InfoPanel,
1148             bsp_coord_stop+1, ParaGLine_Num, szAccess);/*+1 : switch to one-based value*/
1149           break;
1150       }
1151     }
1152 		/*send the message*/
1153     if (dmp->MouseMode==DDV_MOUSEMODE_SELECT ||
1154         dmp->MouseMode==DDV_MOUSEMODE_SELECT_ONE_ROW){
1155       ObjMgrAlsoSelect (bsp_eID, bsp_iID, OBJ_BIOSEQ, OM_REGION_SEQLOC, slp);
1156     }
1157   }
1158   else {
1159     if (slp)
1160       SeqLocFree(slp);
1161   }
1162 }
1163 
1164 
1165 /*****************************************************************************
1166 
1167 Functions: DDV_ClickProcUpper() and DDV_ClickProcLower()
1168 
1169 Purpose: mouse click funcions attached to the upper
1170             and lower panels in 2-panel mode.  They switch focus between the upper
1171             and lower panels, then call the main DDV_ClickProc.
1172 
1173 Parameters:	p; panel handle (currently unused)
1174 			pt; new mouse position
1175 
1176 Return value: none
1177 
1178 *****************************************************************************/
1179 
DDV_ClickProcUpper(PaneL p,PoinT pt)1180 NLM_EXTERN void DDV_ClickProcUpper(PaneL p, PoinT pt)
1181 {
1182 DdvMainWinPtr mWin_d;
1183 WindoW		  hWinMain;
1184 Boolean       tempClick;
1185 
1186 	hWinMain=(WindoW)ParentWindow(p);
1187 	if (hWinMain==NULL) return;
1188 	mWin_d = (DdvMainWinPtr) GetObjectExtra (hWinMain);
1189 	if (mWin_d==NULL) return;
1190 	mWin_d->hWndDDV = mWin_d->hUpperPanel;
1191     DDV_SetMenuFocus(hWinMain);
1192 	mWin_d->InfoPanel = mWin_d->UpperInfoPanel;
1193     tempClick = Nlm_dblClick;  /* keep vibrant from resetting double click */
1194     SetTitle(mWin_d->InfoPanel,"Ready !");
1195     SetTitle(mWin_d->LowerInfoPanel,"");
1196     Nlm_dblClick = tempClick;
1197 
1198     DDV_ClickProc(p, pt);
1199 }
1200 
DDV_ClickProcLower(PaneL p,PoinT pt)1201 NLM_EXTERN void DDV_ClickProcLower(PaneL p, PoinT pt)
1202 {
1203 DdvMainWinPtr mWin_d;
1204 WindoW		  hWinMain;
1205 Boolean       tempClick;
1206 
1207 	hWinMain=(WindoW)ParentWindow(p);
1208 	if (hWinMain==NULL) return;
1209 	mWin_d = (DdvMainWinPtr) GetObjectExtra (hWinMain);
1210 	if (mWin_d==NULL) return;
1211 	mWin_d->hWndDDV = mWin_d->hLowerPanel;
1212     DDV_SetMenuFocus(hWinMain);
1213 	mWin_d->InfoPanel = mWin_d->LowerInfoPanel;
1214     tempClick = Nlm_dblClick;  /* keep vibrant from resetting double click */
1215     SetTitle(mWin_d->InfoPanel,"Ready !");
1216     SetTitle(mWin_d->UpperInfoPanel,"");
1217     Nlm_dblClick = tempClick;
1218 
1219     DDV_ClickProc(p, pt);
1220 }
1221 
1222 /*****************************************************************************
1223 
1224 Function: DDV_ClickProc()
1225 
1226 Purpose: manage Mouse-Click; this function is designed for the autonomous viewer
1227 		to manage the InfoPanel and the Features List Dialog Box
1228 		DON'T USE FOR EXTERNAL SOFTWARE...
1229 
1230 Parameters:	p; panel handle (currently unused)
1231 			pt; new mouse position
1232 
1233 Return value: none
1234 
1235 *****************************************************************************/
DDV_ClickProc(PaneL p,PoinT pt)1236 NLM_EXTERN void DDV_ClickProc(PaneL p, PoinT pt)
1237 {
1238 DdvMainPtr 	   dmp;
1239 DdvMainWinPtr  mWin_d;
1240 RecT           rcP, rcP2;
1241 Int4           bsp_coord, SeqAlign_coord, Disp_coord, Line_num,bsp_start,bsp_stop,
1242                old_pos, ParaGLine_Num, VPos, HPos;
1243 Int4           from_row, to_row, from_col, to_col;
1244 Uint1          uWhere;
1245 ParaGPtr       cur_pgp=NULL;
1246 SeqLocPtr      slp;
1247 Uint2          bsp_eID;
1248 Uint4          bsp_iID;
1249 Boolean        bDeselectAll=TRUE,bIsAlreadyFullSel;
1250 Int4           BlockIndex, Col, NumBlocks;
1251 Boolean        LeftBoundary, IsUnAligned;
1252 DdvMainWinPtr  dmwp;
1253 BioseqPtr      bsp;
1254 Char           buf[81], szAccess[21];
1255 ParaGPtr       pgp;
1256 Int4           i, NumRows, ColCnt, Offset, Width;
1257 
1258 MsaParaGPopListPtr  mpplp;
1259 SeqAlignPtr         sap;
1260 DDE_StackPtr        dsp;
1261 Boolean             IsEditable, *pNoGaps, NoGaps, FoundIt;
1262 
1263 	/*get the panel data*/
1264 	dmp = (DdvMainPtr) GetObjectExtra(p);
1265 	if (dmp==NULL) return;
1266   mWin_d = (DdvMainWinPtr) GetObjectExtra(dmp->hParent);
1267   if (mWin_d == NULL) return;
1268 
1269 	ObjectRect(p,&rcP);
1270 
1271 	if (ctrlKey || shftKey)
1272 		bDeselectAll=FALSE;
1273 
1274   /* handle the case when a block is being deleted in DDV */
1275   if (dmp->MouseMode == DDV_MOUSEMODE_DELETEBLOCK) {
1276     /* get block index, etc */
1277     if (GetBlockAndAlignment(pt, p, dmp, &BlockIndex, &IsUnAligned, &Col, &Offset, &Width, &rcP)) {
1278       /* if block is aligned */
1279       if (!IsUnAligned) {
1280         /* create display for single block */
1281         sap = ViewMgr_GetBeginIndexed(dmp->MSA_d.pgp_l.sap);
1282         dmp->MSA_d.pgp_l.viewed_sap = dmp->MSA_d.pgp_l.sap;
1283         mpplp = DDE_CreateDisplay(sap, BlockIndex, IsUnAligned, &NumBlocks);
1284         dsp = DDE_NewStack(mpplp);
1285         /* record which block is being edited, etc */
1286         dsp->LaunchBlock = BlockIndex;
1287         dsp->NumBlocks =   NumBlocks;
1288         dsp->IsUnAligned = IsUnAligned;
1289         DDE_MergeNodesLists(dsp->pEdit);
1290         /* delete block, tell AlnMgr to save edits, redraw DDV */
1291         DDE_DeleteBlock(dsp, 0, FALSE);
1292         dmp->dsp = dsp;
1293         DDV_SaveEdits(dmp, TRUE);
1294         /* free stack */
1295         dsp = DDE_FreeStack(dsp);
1296         dmp->dsp = dsp;
1297       }
1298     }
1299     ArrowCursor();
1300     dmp->MouseMode = dmp->SavedMouseMode;
1301   }
1302 
1303   /* handle the click when splitting 2 blocks */
1304   if (dmp->MouseMode == DDV_MOUSEMODE_SPLITBLOCK) {
1305     FoundIt = FALSE;
1306     /* adjust x position so vertical bar jumps when mouse is on center of char */
1307     pt.x -= dmp->GrData.udv_font.ColWidth/2;
1308     /* if user clicked on an aligned block */
1309     if (GetBlockAndAlignment(pt, p, dmp, &BlockIndex, &IsUnAligned, &Col, &Offset, &Width, &rcP)) {
1310       /* save col where vertical bar was last drawn */
1311       dmp->SaveCol = Col;
1312       /* draw vertical bar after this column */
1313       HPos = DDV_GetHPixelPosGivenColNumber(dmp, rcP, Col);
1314       UDV_draw_vertical_bar(rcP, HPos, FALSE);
1315       dmp->ms.Action_type = MS_ACTION_SPLIT_BLOCK;
1316       FoundIt = TRUE;
1317     }
1318     if (!FoundIt) {
1319       ArrowCursor();
1320     }
1321     dmp->MouseMode = dmp->SavedMouseMode;
1322   }
1323 
1324   /* handle the 1st click when merging 2 blocks */
1325   /* for the 1st click just need to record the block */
1326   else if (dmp->MouseMode == DDV_MOUSEMODE_MERGEBLOCKS1) {
1327     FoundIt = FALSE;
1328     /* if mouse is in a valid place, get BlockIndex and alignment status */
1329     if (GetBlockAndAlignment(pt, p, dmp, &BlockIndex, &IsUnAligned, &Col, &Offset, &Width, &rcP)) {
1330       if (!IsUnAligned) {
1331         dmp->BlockIndex = BlockIndex;
1332         dmp->MouseMode = DDV_MOUSEMODE_MERGEBLOCKS2;
1333         FoundIt = TRUE;
1334       }
1335     }
1336     if (!FoundIt) {
1337       dmp->MouseMode = dmp->SavedMouseMode;
1338       ArrowCursor();
1339     }
1340   }
1341 
1342   /* handle the 2nd click when merging 2 blocks */
1343   else if (dmp->MouseMode == DDV_MOUSEMODE_MERGEBLOCKS2) {
1344     /* if mouse is in a valid place, get BlockIndex and alignment status */
1345     if (GetBlockAndAlignment(pt, p, dmp, &BlockIndex, &IsUnAligned, &Col, &Offset, &Width, &rcP)) {
1346       /* if 2 blocks are next to each other and both aligned */
1347       if ((!IsUnAligned) && (ABS(BlockIndex - dmp->BlockIndex) == 1)) {
1348         /* create a stack for the block on the right */
1349         BlockIndex = MAX(BlockIndex, dmp->BlockIndex);
1350         sap = ViewMgr_GetBeginIndexed(dmp->MSA_d.pgp_l.sap);
1351         dmp->MSA_d.pgp_l.viewed_sap = dmp->MSA_d.pgp_l.sap;
1352         mpplp = DDE_CreateDisplay(sap, BlockIndex, IsUnAligned, &NumBlocks);
1353         dsp = DDE_NewStack(mpplp);
1354         /* record which block is being edited, etc */
1355         dsp->LaunchBlock = BlockIndex;
1356         dsp->NumBlocks =   NumBlocks;
1357         dsp->IsUnAligned = IsUnAligned;
1358         DDE_MergeNodesLists(dsp->pEdit);
1359         /* if block on right is flush left */
1360         if (DDE_FirstColumnIsAligned(dsp->pEdit)) {
1361           /* delete block on right.  count number of cols that were in block. */
1362           ColCnt = DDE_DeleteBlock(dsp, 0, FALSE);
1363           /* tell AlnMgr to save edits, don't redraw yet */
1364           dmp->dsp = dsp;
1365           DDV_SaveEdits(dmp, FALSE);
1366           /* free stack for block on right.  create stack for block on left */
1367           DDE_FreeStack(dsp);
1368           sap = ViewMgr_GetBeginIndexed(dmp->MSA_d.pgp_l.sap);
1369           dmp->MSA_d.pgp_l.viewed_sap = dmp->MSA_d.pgp_l.sap;
1370           mpplp = DDE_CreateDisplay(sap, BlockIndex-1, IsUnAligned, &NumBlocks);
1371           dsp = DDE_NewStack(mpplp);
1372           /* record which block is being edited, etc */
1373           dsp->LaunchBlock = BlockIndex-1;
1374           dsp->NumBlocks =   NumBlocks;
1375           dsp->IsUnAligned = IsUnAligned;
1376           DDE_MergeNodesLists(dsp->pEdit);
1377           DDE_Verify(dsp->pEdit);
1378           /* shift right boundary of left block by number cols in right block */
1379           DDE_ShiftRightBoundary(dsp, 0, ColCnt, FALSE);
1380           /* tell AlnMgr to save edits, now redraw */
1381           dmp->dsp = dsp;
1382           DDV_SaveEdits(dmp, TRUE);
1383         }
1384         /* free remaining stack */
1385         dsp = DDE_FreeStack(dsp);
1386         dmp->dsp = dsp;
1387       }
1388     }
1389     dmp->MouseMode = dmp->SavedMouseMode;
1390     ArrowCursor();
1391   }
1392 
1393 
1394   /* handle the case when we're launching the editor on a block */
1395   else if (dmp->MouseMode == DDV_MOUSEMODE_LAUNCHEDITOR) {
1396     /* if mouse is in a valid place, get BlockIndex and alignment status */
1397     if (GetBlockAndAlignment(pt, p, dmp, &BlockIndex, &IsUnAligned, &Col, &Offset, &Width, &rcP)) {
1398       /* don't allow editing when there are gaps and no gaps are allowed */
1399       pNoGaps = (Boolean*) GetAppProperty("dde_nogaps");
1400       if (pNoGaps == NULL) NoGaps = TRUE;
1401       else NoGaps = *pNoGaps;
1402       IsEditable = AlnMgrIsEditable(dmp->MSA_d.pgp_l.sap);
1403       if (!(IsEditable == AM_EDITGAPS && NoGaps) && IsEditable) {
1404         ViewMgr_MakeMultiple(dmp->MSA_d.pgp_l.sap);
1405       }
1406       else {
1407         Message(MSG_OK, "%s", "Unable to convert this alignment\n into an editable form.");
1408         dmp->MouseMode = dmp->SavedMouseMode;
1409         ArrowCursor();
1410         return;
1411       }
1412       /* get pointer to original seqAlign */
1413       sap = ViewMgr_GetBeginIndexed(dmp->MSA_d.pgp_l.sap);
1414       /* create display for editor */
1415       mpplp = DDE_CreateDisplay(sap, BlockIndex, IsUnAligned, &NumBlocks);
1416       mpplp->viewed_sap = dmp->MSA_d.pgp_l.sap;
1417       /* create the stack used by editor */
1418       dsp = DDE_NewStack(mpplp);
1419       DDE_MergeNodesLists(dsp->pEdit);
1420       /* record which block is being edited, etc */
1421       dsp->LaunchBlock = BlockIndex;
1422       dsp->NumBlocks =   NumBlocks;
1423       dsp->IsUnAligned = IsUnAligned;
1424       /* hide the rows in DDE that are hidden in DDV */
1425       NumRows = dsp->pEdit->TotalNumRows;
1426       for (i=0; i<NumRows; i++) {
1427         if (ViewMgr_TRow2VRow(dmp->MSA_d.pgp_l.sap, i+1) == -1) {
1428           DDE_HideRow(dsp, i, FALSE);
1429         }
1430       }
1431       DDE_Add(dsp);
1432       dsp->SomethingToSave = FALSE;
1433       /* launch the editor as a slave */
1434       SetAppProperty("ddeinterndata",(void*)dsp);
1435       GatherProcLaunch(OMPROC_EDIT, FALSE, dmp->MSA_d.entityID,
1436 					dmp->MSA_d.itemID, OBJ_SEQALIGN, 0, 0, OBJ_SEQALIGN, 0);
1437       RemoveAppProperty("ddeinterndata");
1438     }
1439     dmp->MouseMode = dmp->SavedMouseMode;
1440     ArrowCursor();
1441   }
1442 
1443   /* handle the case when we're creating an aligned block */
1444   else if (dmp->MouseMode == DDV_MOUSEMODE_CREATEBLOCK) {
1445     ObjectRect(p, &rcP);
1446     InsetRect(&rcP,4,4);
1447     DDV_AdjustDrawingRect(&rcP,&(dmp->GrData.udv_font),dmp);
1448     rcP.left += dmp->GrData.udv_panel.cxName + dmp->GrData.udv_scale.cxLeftScale;
1449     /* if the point is in a valid spot */
1450     if (PtInRect(pt, &rcP)) {
1451       ObjectRect(p, &rcP);
1452       Col = DDV_GetColNumberGivenMousePos(dmp, rcP, pt);
1453       /* and the column's legal */
1454       if ((Col >= 0) && (Col < dmp->MSA_d.pgp_l.LengthAli)) {
1455         /* and there is no aligned block already */
1456         if (DDE_GetNumBlocks(dmp->dsp->pEdit) == 0) {
1457           /* save start col */
1458           dmp->dsp->FromCol = Col;
1459           /* save col where vertical bar was last drawn */
1460           dmp->dsp->SaveCol = Col;
1461           /* draw vertical bar before and after this column */
1462           HPos = DDV_GetHPixelPosGivenColNumber(dmp, rcP, dmp->dsp->SaveCol);
1463           UDV_draw_vertical_bar(rcP, HPos, TRUE);
1464           HPos -= dmp->GrData.udv_font.ColWidth;
1465           UDV_draw_vertical_bar(rcP, HPos, TRUE);
1466           dmp->ms.Action_type = MS_ACTION_CREATE_BLOCK;
1467         }
1468         else {
1469           dmp->MouseMode = dmp->SavedMouseMode;
1470           ArrowCursor();
1471         }
1472       }
1473       else {
1474         dmp->MouseMode = dmp->SavedMouseMode;
1475         ArrowCursor();
1476       }
1477     }
1478     else {
1479       dmp->MouseMode = dmp->SavedMouseMode;
1480       ArrowCursor();
1481     }
1482   }
1483 
1484   /*the mouse is located in a ParaG ?*/
1485 	/*if YES : the user is selecting either sequence letter(s) or a feature*/
1486 	else if ((pt.x>(rcP.left+dmp->GrData.udv_panel.cxName+
1487        dmp->GrData.udv_scale.cxLeftScale)) &&
1488 		  (pt.y>(rcP.top+dmp->GrData.udv_panel.cyScale))) {
1489 			/*get the ParaG list and look for the ParaG where the mouse is located*/
1490 			/*note : only implemented for DDV_DISP_HORZ type of display...*/
1491 			if (dmp->MSA_d.pgp_l.DisplayType==DDV_DISP_HORZ){
1492 				if (DDV_GetCoordsGivenAClick(dmp,&rcP,&pt,
1493 					&bsp_coord,&SeqAlign_coord,&Disp_coord,&Line_num,
1494 					&ParaGLine_Num,&uWhere,&cur_pgp)){
1495 					if (uWhere==PGP_REGION_SEQ){
1496 						if (bDeselectAll && (dmp->MouseMode==DDV_MOUSEMODE_SELECT ||
1497                                  dmp->MouseMode==DDV_MOUSEMODE_SELECT_ONE_ROW))
1498 							ObjMgrDeSelectAll ();
1499 						if (shftKey && bsp_coord!=(Int4)-1){
1500 							UDV_DecodeIdxFeat (dmp->MSA_d.pgp_l.entitiesTbl[ParaGLine_Num-1],
1501 								&bsp_eID,&bsp_iID);
1502 							if (bsp_eID!=0 && bsp_iID!=0){
1503 								slp=DDV_GetClosetSeqLocGivenBspPos(cur_pgp->sip,bsp_eID,
1504 									bsp_iID, bsp_coord, &old_pos, TRUE);
1505 								if (slp){
1506 									if (dmp->MouseMode==DDV_MOUSEMODE_SELECT ||
1507                       dmp->MouseMode==DDV_MOUSEMODE_SELECT_ONE_ROW)
1508 										ObjMgrAlsoSelect (bsp_eID, bsp_iID,
1509 											OBJ_BIOSEQ,OM_REGION_SEQLOC, slp);
1510 									if (old_pos!=(Int4)-1)
1511 										Disp_coord=old_pos;
1512 								}
1513 							}
1514 							dmp->ms.oldPos=pt;
1515 							dmp->ms.Action_type=MS_ACTION_SELECT_SEQ;
1516 							return;
1517 						}
1518 
1519             /* display info about residues that's clicked */
1520             if (ParaGLine_Num != -1) {
1521               DDV_GetSeqNameGivenRow(dmp->MSA_d.pgp_l.TableHead, ParaGLine_Num, szAccess);
1522               DDV_DispPositionInStatus(mWin_d->InfoPanel, bsp_coord+1, ParaGLine_Num, szAccess);
1523             }
1524 
1525 						/*save the positions */
1526 						dmp->ms.oldPos=pt;
1527 						dmp->ms.newPos=pt;
1528 						dmp->ms.Action_type=MS_ACTION_SELECT_SEQ;
1529 						dmp->ms.old_row=Line_num;
1530 						dmp->ms.old_col=Disp_coord;
1531 						dmp->ms.old_pgp=cur_pgp;
1532 						dmp->ms.first_row=Line_num;
1533             dmp->ms.first_col=Disp_coord;
1534             dmp->ms.last_row=Line_num;
1535             dmp->ms.last_col=Disp_coord;
1536 
1537             /* show outline of highlighted area */
1538             CopyMode();
1539             DrawOutline(p, Line_num, Disp_coord, Line_num, Disp_coord, TRUE);
1540 
1541             if (dmp->ms.first_cols == NULL) {
1542               NumRows = dmp->MSA_d.pgp_l.nBsp;
1543               dmp->ms.first_cols = MemNew(NumRows * sizeof(Int4));
1544               dmp->ms.first_pgps = MemNew(NumRows * sizeof(ParaGPtr));
1545             }
1546 						dmp->ms.first_cols[Line_num-1]=Disp_coord;
1547 						dmp->ms.first_pgps[Line_num-1]=cur_pgp;
1548             dmp->ms.first_point=pt;
1549             dmp->ms.first_HScroll=dmp->GrData.udv_hscrl.ScrollPos;
1550             dmp->ms.first_VScroll=dmp->GrData.udv_vscrl.ScrollPos;
1551             dmp->ms.old_HScroll = dmp->GrData.udv_hscrl.ScrollPos;
1552             dmp->ms.old_VScroll = dmp->GrData.udv_vscrl.ScrollPos;
1553 						/*update caret pos, if needed only*/
1554 						if (dmp->MouseMode==DDV_MOUSEMODE_EDIT){
1555 							dmp->dci.old_row=dmp->dci.new_row;
1556 							dmp->dci.old_col=dmp->dci.new_col;
1557 						}
1558             /* if we're in the editor and mousemode is query */
1559             /* click and drag on sequence will cause the whole row to shift */
1560             if (dmp->bEditor) {
1561               if (dmp->MouseMode == DDV_MOUSEMODE_QUERY) {
1562                 /* make sure column is legit */
1563                 DDV_GetCurrentDispRange(dmp->hWndDDV,&(dmp->GrData),
1564                   dmp->MSA_d.pgp_l.LengthAli,&from_col,&to_col,&from_row,&to_row);
1565                 /* Don't shift row if clicking on first or last column of */
1566                 /* display because then the screen scrolls */
1567                 if (((Disp_coord>from_col) && (Disp_coord<=to_col)) || (Disp_coord==0)) {
1568                   /* draw a double rectangle around the selected char */
1569                   /* to mark the from spot */
1570                   ObjectRect(p, &rcP);
1571                   VPos = DDV_GetVPixelPosGivenRowNumber(dmp, rcP, Line_num-1); /* 1-based */
1572                   HPos = DDV_GetHPixelPosGivenColNumber(dmp, rcP, Disp_coord); /* 0-based */
1573                   rcP2.left =    HPos - dmp->GrData.udv_font.ColWidth;
1574                   rcP2.right =   HPos;
1575                   rcP2.top =     VPos - dmp->GrData.udv_font.LineHeight;
1576                   rcP2.bottom =  VPos;
1577                   UDV_draw_rectangle(rcP2, FALSE);
1578                   InsetRect(&rcP2, 1, 1);
1579                   UDV_draw_rectangle(rcP2, FALSE);
1580                   CrossCursor();
1581                   dmp->dsp->FromCol = Disp_coord;
1582                   dmp->dsp->FromRow = Line_num-1;
1583                   dmp->dsp->SaveCol = Disp_coord;
1584                   dmp->dsp->SaveRow = Line_num-1;
1585                   dmp->ms.Action_type = MS_ACTION_SHIFT_ROW;
1586                 }
1587               }
1588             }
1589 						/*select a single letter*/
1590             if (dmp->MouseMode == DDV_MOUSEMODE_SELECT ||
1591                 dmp->MouseMode == DDV_MOUSEMODE_SELECT_ONE_ROW) {
1592 /*
1593               DDV_SendBSPSelectMsg(dmp, bsp_coord, SeqAlign_coord,
1594                 Disp_coord, Line_num, ParaGLine_Num, cur_pgp, &pt, TRUE);
1595 */
1596             }
1597 					}
1598 				}
1599 			}
1600 	}
1601 	/*the mouse is located within the Name list region (left of ParaG) ?*/
1602 	else if (pt.x>=dmp->GrData.udv_panel.cxName-1 &&
1603 			pt.x<=dmp->GrData.udv_panel.cxName+3){
1604 				rcP.left=5*dmp->GrData.udv_font.cxChar; /*min value*/
1605 				rcP.right=2*PANEL_NAME_WIDTH*dmp->GrData.udv_font.cxChar;/*max val*/
1606 				pt.x=dmp->GrData.udv_panel.cxName;
1607 				dmp->ms.oldPos=pt;
1608 				dmp->ms.newPos=pt;
1609 				dmp->ms.rcClip=rcP;
1610 				dmp->ms.Action_type=MS_ACTION_RESIZE_WIN;
1611 				InvertMode();
1612 				UDV_draw_double_cursor(dmp->ms.rcClip,
1613 					dmp->ms.oldPos);
1614 				CrossCursor();
1615 	}
1616 	/*the mouse is located on a sequence name ?*/
1617 	else if (pt.x<dmp->GrData.udv_panel.cxName &&
1618 			pt.y>(rcP.top+dmp->GrData.udv_panel.cyScale)){
1619 		Line_num=DDV_GetRowGivenMousePos(dmp, &rcP, &pt,&ParaGLine_Num);
1620 		if (Line_num!=(Int4)-1){
1621 		    UDV_DecodeIdxFeat (dmp->MSA_d.pgp_l.entitiesTbl[ParaGLine_Num-1],
1622 				&bsp_eID,&bsp_iID);
1623 			if (dblClick /*&& !dmp->bEditor*/){/*load the sequence viewer on that sequence*/
1624                 {
1625                     SAM_ViewGlobal vg;
1626 
1627                     MemSet(&vg, 0, sizeof(SAM_ViewGlobal));
1628                     vg.pCGlobal = dmp->Globals.colorp;
1629                     vg.Row = Line_num;
1630                     if(!dmp->bEditor) vg.MasterViewer = SAMVIEWDDV;
1631                     else vg.MasterViewer = SAMVIEWDDE;
1632                     SetAppProperty(SAM_ViewString, &vg);
1633                     GatherSpecificProcLaunch(0, "OneD-Viewer", OMPROC_VIEW,
1634                       FALSE, bsp_eID, bsp_iID, OBJ_BIOSEQ);
1635                     RemoveAppProperty(SAM_ViewString);
1636                 }
1637             }
1638 			else{
1639 				if (dmp->bEditor){
1640 					WindoW temport;
1641 					dmp->deri.curEditRow=ParaGLine_Num-1;
1642 					rcP.left=0;
1643 					rcP.right=rcP.left+dmp->GrData.udv_panel.cxName;
1644 					temport=SavePort(ParentWindow(p));
1645 					Select(p);
1646 					InvalRect(&rcP);
1647 					Update();
1648 					RestorePort(temport);
1649           /* record the row that's moving */
1650           dmp->dsp->FromRow = Line_num - 1;
1651           /* keep track of where the underline is */
1652           dmp->dsp->SaveRow = Line_num - 1;
1653 					dmp->ms.Action_type = MS_ACTION_MOVE_ROW;
1654           /* make a rectangle of the sequence names region */
1655           ObjectRect(p,&rcP);
1656           rcP2.left =   rcP.left;
1657           rcP2.right =  rcP.left + dmp->GrData.udv_panel.cxName - 10;
1658           rcP2.top =    rcP.top;
1659           rcP2.bottom = rcP.bottom;
1660           /* draw the underline */
1661           VPos = DDV_GetVPixelPosGivenRowNumber(dmp, rcP2, Line_num-1);
1662           UDV_draw_horizontal_line(rcP2, VPos);
1663           CrossCursor();
1664 				}
1665         else  /* not editor */ {
1666             dmwp=(DdvMainWinPtr)GetObjectExtra(dmp->hParent);
1667             if(dmwp) {
1668                 pgp=(ParaGPtr)(dmp->MSA_d.pgp_l.TableHead[Line_num-1]->data.ptrvalue);
1669 		            bsp=BioseqLockById(pgp->sip);
1670                 CreateDefLine(NULL,bsp,buf,80,0,NULL,NULL);
1671                 BioseqUnlock(bsp);
1672                 SetTitle(dmwp->InfoPanel,buf);
1673             }
1674         }
1675 			}
1676 		}
1677 	}
1678 	/*the mouse is located  just on the left of a sequence ?
1679 		If true, select the full sequence*/
1680 	else if ((pt.x>=dmp->GrData.udv_panel.cxName+3) /*after the name of the sequence ?*/
1681 			&&
1682 			(pt.x<=dmp->GrData.udv_panel.cxName+3+dmp->GrData.udv_scale.cxLeftScale+
1683 			dmp->GrData.udv_font.cxChar) /*before the sequence ?*/
1684 			&&
1685 			(dmp->MouseMode==DDV_MOUSEMODE_SELECT ||
1686        dmp->MouseMode==DDV_MOUSEMODE_SELECT_ONE_ROW)/*valid only if selection mode*/
1687 			){
1688 		if (pt.y>(rcP.top+dmp->GrData.udv_panel.cyScale)){
1689 			/*get the ParaG list and look for the ParaG where the mouse is located*/
1690 			/*note : only implemented for DDV_DISP_HORZ type of display...*/
1691 			if (dmp->MSA_d.pgp_l.DisplayType==DDV_DISP_HORZ){
1692 				Line_num=DDV_GetRowGivenMousePos(dmp, &rcP, &pt,&ParaGLine_Num);
1693 				if (Line_num!=(Int4)-1){
1694 					/*get min,max coord. of BSP*/
1695 					UDV_GetBspRangeinPGPList(dmp->MSA_d.pgp_l.TableHead[ParaGLine_Num-1],
1696 						&bsp_start,&bsp_stop);
1697 					if (bsp_start!=INT4_MAX && bsp_stop!=INT4_MIN){
1698 						/*now, we can send the Select message*/
1699 						/* first_pgp, old_pgp & cur_pgp have the same sip...
1700 						they are on a same row; I can use one of them*/
1701 						cur_pgp=(ParaGPtr)(dmp->MSA_d.pgp_l.TableHead[ParaGLine_Num-1]->data.ptrvalue);
1702 						slp = SeqLocIntNew (bsp_start, bsp_stop, Seq_strand_plus, cur_pgp->sip);
1703 						UDV_DecodeIdxFeat (dmp->MSA_d.pgp_l.entitiesTbl[ParaGLine_Num-1],
1704 							&bsp_eID,&bsp_iID);
1705 						if (bsp_eID!=0 && bsp_iID!=0 && slp){
1706 							bIsAlreadyFullSel=DDV_IsFullBspAlreadySel(bsp_eID,bsp_iID,
1707 								bsp_start,bsp_stop);
1708 							if (!bIsAlreadyFullSel){
1709 								if (!bDeselectAll){
1710 									ObjMgrAlsoSelect (bsp_eID, bsp_iID,
1711 										OBJ_BIOSEQ,OM_REGION_SEQLOC, slp);
1712 								}
1713 								else{
1714 									ObjMgrDeSelectAll ();
1715 									ObjMgrSelect (bsp_eID, bsp_iID,
1716 										OBJ_BIOSEQ,OM_REGION_SEQLOC, slp);
1717 								}
1718 							}
1719 							else{
1720 								if (bDeselectAll)
1721 									ObjMgrDeSelectAll ();
1722 								ObjMgrDeSelect (bsp_eID, bsp_iID,
1723 									OBJ_BIOSEQ,OM_REGION_SEQLOC, slp);
1724 							}
1725 						}
1726 					}
1727 					dmp->ms.Action_type=MS_ACTION_SELECT_FULL_SEQ;
1728 				}
1729 			}
1730 		}
1731 	}
1732 
1733   /* if the mouse is located on one of the vertical bars, on top, that */
1734   /* mark an alignment boundary */
1735   else if (OnAlignmentBoundary(pt, p, dmp, &BlockIndex, &LeftBoundary, &Col, &HPos)) {
1736     /* record the boundary and block that are being moved */
1737     dmp->dsp->FromCol = Col;
1738     dmp->dsp->BlockIndex = BlockIndex;
1739     dmp->dsp->LeftBoundary = LeftBoundary;
1740     /* record the column of the last drawn vertical bar */
1741     dmp->dsp->SaveCol = Col;
1742     dmp->ms.Action_type = MS_ACTION_SHIFT_BOUNDARY;
1743     /* draw a dotted outline of the vertical bar */
1744     ObjectRect(p, &rcP);
1745     UDV_draw_vertical_bar(rcP, HPos, TRUE);
1746     CrossCursor();
1747   }
1748 
1749 	else{/*click outside "special" regions : deselect everything*/
1750 		if (dmp->MouseMode==DDV_MOUSEMODE_SELECT ||
1751         dmp->MouseMode==DDV_MOUSEMODE_SELECT_ONE_ROW)
1752 			ObjMgrDeSelectAll ();
1753 			/*this line if for cn3d only*/
1754             ObjMgrSendMsg(OM_MSG_MOUSEUP, dmp->MSA_d.entityID,
1755 						dmp->MSA_d.itemID, OBJ_SEQALIGN);
1756 	}
1757 
1758   if (dmp->bEditor) {
1759     DDV_GreyOut(mWin_d, DDE_AtStartOfStack(dmp->dsp), DDE_AtEndOfStack(dmp->dsp));
1760   }
1761 }
1762 
1763 
GetBlockAndAlignmentForCol(DdvMainPtr dmp,Int4 Col,Int4 * pBlockIndex,Boolean * pIsUnAligned,Int4 * pOffset,Int4 * pWidth)1764 static Boolean GetBlockAndAlignmentForCol(DdvMainPtr dmp, Int4 Col, Int4* pBlockIndex,
1765                                           Boolean* pIsUnAligned, Int4* pOffset, Int4* pWidth) {
1766 /*****************************************************************************
1767 *  get the BlockIndex and Alignment status for Col.
1768 *****************************************************************************/
1769   /* if Col is legal */
1770   if ((Col >= 0) && (Col < dmp->MSA_d.pgp_l.LengthAli)) {
1771     /* get the block or unaligned-region index */
1772     if (DDE_IsColValid(&(dmp->MSA_d.pgp_l), Col, pBlockIndex, pIsUnAligned, pOffset, pWidth)) {
1773       return(TRUE);
1774     }
1775   }
1776   *pBlockIndex = -1;
1777   *pIsUnAligned = TRUE;
1778   return(FALSE);
1779 }
1780 
1781 
GetBlockAndAlignment(PoinT pt,PaneL p,DdvMainPtr dmp,Int4 * pBlockIndex,Boolean * pIsUnAligned,Int4 * pCol,Int4 * pOffset,Int4 * pWidth,RecT * rcP)1782 static Boolean GetBlockAndAlignment(PoinT pt, PaneL p, DdvMainPtr dmp,
1783                                     Int4* pBlockIndex, Boolean* pIsUnAligned,
1784                                     Int4* pCol, Int4* pOffset, Int4* pWidth, RecT* rcP) {
1785 /*****************************************************************************
1786 *  get the BlockIndex and Alignment status for point pt.
1787 *****************************************************************************/
1788   ObjectRect(p, rcP);
1789   InsetRect(rcP,4,4);
1790   DDV_AdjustDrawingRect(rcP, &(dmp->GrData.udv_font), dmp);
1791   rcP->left += dmp->GrData.udv_panel.cxName + dmp->GrData.udv_scale.cxLeftScale;
1792   /* if the point is in a valid spot */
1793   if (PtInRect(pt, rcP)) {
1794     ObjectRect(p, rcP);
1795     *pCol = DDV_GetColNumberGivenMousePos(dmp, *rcP, pt);
1796     /* and the column's legal */
1797     if ((*pCol >= 0) && (*pCol < dmp->MSA_d.pgp_l.LengthAli)) {
1798       /* get the block or unaligned-region index */
1799       if (DDE_IsColValid(&(dmp->MSA_d.pgp_l), *pCol, pBlockIndex, pIsUnAligned, pOffset, pWidth)) {
1800         return(TRUE);
1801       }
1802     }
1803   }
1804   *pCol=-1;
1805   *pBlockIndex = -1;
1806   *pIsUnAligned = TRUE;
1807   return(FALSE);
1808 }
1809 
1810 
RectanglesAreSame(RecT rc1,RecT rc2)1811 static Boolean RectanglesAreSame(RecT rc1, RecT rc2) {
1812 /*****************************************************************************
1813 *  return TRUE if 2 rectangles are identical.
1814 *****************************************************************************/
1815   if (rc1.left   != rc2.left)    return(FALSE);
1816   if (rc1.right  != rc2.right)   return(FALSE);
1817   if (rc1.top    != rc2.top)     return(FALSE);
1818   if (rc1.bottom != rc2.bottom)  return(FALSE);
1819   return(TRUE);
1820 }
1821 
1822 
EraseOutline(PaneL p)1823 static void EraseOutline(PaneL p) {
1824 /*****************************************************************************
1825 *  erase the old outline of the region selected for highlighting.
1826 *****************************************************************************/
1827   DdvMainPtr  dmp;
1828   BaR         hsb, vsb;
1829   Int4        HScroll, VScroll;
1830 
1831   dmp = (DdvMainPtr) GetObjectExtra(p);
1832 	if (dmp==NULL) return;
1833 
1834   hsb = GetSlateHScrollBar((SlatE) dmp->hWndDDV);
1835   vsb = GetSlateVScrollBar((SlatE) dmp->hWndDDV);
1836 
1837   /* save current scroll positions, set scroll positions to saved scroll positions */
1838   HScroll = dmp->GrData.udv_hscrl.ScrollPos;
1839   VScroll = dmp->GrData.udv_vscrl.ScrollPos;
1840   SetValue(hsb, dmp->ms.old_HScroll);
1841   SetValue(vsb, dmp->ms.old_VScroll);
1842 
1843   /* erase the old rectangle */
1844   InvertMode();
1845   UDV_draw_rectangle(dmp->ms.outline, FALSE);
1846 
1847   /* restore scroll positions */
1848   SetValue(hsb, HScroll);
1849   SetValue(vsb, VScroll);
1850 }
1851 
1852 
DrawOutline(PaneL p,Int4 Line_num_start,Int4 Disp_coord_start,Int4 Line_num_stop,Int4 Disp_coord_stop,Boolean Draw)1853 static RecT DrawOutline(PaneL p, Int4 Line_num_start, Int4 Disp_coord_start,
1854                         Int4 Line_num_stop, Int4 Disp_coord_stop, Boolean Draw) {
1855 /*****************************************************************************
1856 *  use current scroll postions.
1857 *****************************************************************************/
1858   RecT        rcP2;
1859   DdvMainPtr  dmp;
1860 
1861   rcP2.left = rcP2.right = rcP2.top = rcP2.bottom = 0;
1862 
1863   dmp = (DdvMainPtr) GetObjectExtra(p);
1864 	if (dmp==NULL) return(rcP2);
1865 
1866   return(DrawOutlineGivenScroll(p,
1867     Line_num_start, Disp_coord_start, Line_num_stop, Disp_coord_stop,
1868     dmp->GrData.udv_vscrl.ScrollPos, dmp->GrData.udv_hscrl.ScrollPos, Draw));
1869 }
1870 
1871 
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)1872 static RecT DrawOutlineGivenScroll(PaneL p, Int4 Line_num_start, Int4 Disp_coord_start,
1873                                    Int4 Line_num_stop, Int4 Disp_coord_stop,
1874                                    Int4 VScroll, Int4 HScroll, Boolean Draw) {
1875 /*****************************************************************************
1876 *  draw the outline of the region being selected for highlighting.
1877 *  Line_num_stop and Disp_coord_stop are for the current mouse position.
1878 *  Line_num_start and Disp_coord_start are for the first click position.
1879 *  if Draw is FALSE, just return the rectangle and don't draw it.
1880 *  Line_num's are 1-based.  Disp_coord's are 0-based.
1881 *  treat VScroll and HScroll as the current scroll positions.
1882 *  return rectangle that's drawn.
1883 *****************************************************************************/
1884   RecT        rcP, rcP2;
1885   DdvMainPtr  dmp;
1886   Int4        Line_num_stop_save, Disp_coord_stop_save;
1887 
1888   rcP2.left = rcP2.right = rcP2.top = rcP2.bottom = 0;
1889   Line_num_stop_save = Line_num_stop;
1890   Disp_coord_stop_save = Disp_coord_stop;
1891 
1892   dmp = (DdvMainPtr) GetObjectExtra(p);
1893 	if (dmp==NULL) return(rcP2);
1894 
1895   if (Line_num_start > Line_num_stop) {
1896     swap(&Line_num_start, &Line_num_stop);
1897   }
1898   if (Disp_coord_start > Disp_coord_stop) {
1899     swap(&Disp_coord_start, &Disp_coord_stop);
1900   }
1901   if (Line_num_start < 1)
1902     Line_num_start=1;
1903   if (Line_num_stop > dmp->MSA_d.pgp_l.nBsp)
1904     Line_num_stop=dmp->MSA_d.pgp_l.nBsp;
1905   if (Disp_coord_start < 0)
1906     Disp_coord_start=0;
1907   if (Disp_coord_stop >= dmp->MSA_d.pgp_l.LengthAli)
1908     Disp_coord_stop=dmp->MSA_d.pgp_l.LengthAli;
1909 
1910   if (dmp->MouseMode==DDV_MOUSEMODE_SELECT || dmp->MouseMode==DDV_MOUSEMODE_SELECT_ONE_ROW) {
1911     /* calculate new rectangle */
1912     ObjectRect(p, &rcP);
1913     rcP2.top =    DDV_GetVPixelPosGivenRowNumber(dmp, rcP, Line_num_start-1);
1914     rcP2.bottom = DDV_GetVPixelPosGivenRowNumber(dmp, rcP, Line_num_stop-1);
1915     rcP2.left =   DDV_GetHPixelPosGivenColNumber(dmp, rcP, Disp_coord_start);
1916     rcP2.right =  DDV_GetHPixelPosGivenColNumber(dmp, rcP, Disp_coord_stop);
1917     rcP2.top -=   dmp->GrData.udv_font.LineHeight;
1918     rcP2.left -=  dmp->GrData.udv_font.ColWidth;
1919     if (Draw) {
1920       /* make clip region */
1921 	    InsetRect(&rcP,4,4);
1922 	    DDV_AdjustDrawingRect(&rcP,&(dmp->GrData.udv_font),dmp);
1923 	    rcP.left+=dmp->GrData.udv_panel.cxName+dmp->GrData.udv_scale.cxLeftScale;
1924 	    rcP.top+=3*dmp->GrData.udv_panel.cyScale/2;
1925       rcP.bottom+=2; /* so bottom of rectangle not cut */
1926       ClipRect(&rcP);
1927       /* draw new rectangle */
1928       UDV_draw_rectangle(rcP2, FALSE);
1929       ResetClip();
1930       /* save row and col for current mouse pos */
1931       dmp->ms.last_row = Line_num_stop_save;
1932       dmp->ms.last_col = Disp_coord_stop_save;
1933     }
1934   }
1935   return(rcP2);
1936 }
1937 
1938 
OnAlignmentBoundary(PoinT pt,PaneL p,DdvMainPtr dmp,Int4 * pBlockIndex,Boolean * pLeftBoundary,Int4 * pCol,Int4 * pHPos)1939 static Boolean OnAlignmentBoundary(PoinT pt, PaneL p, DdvMainPtr dmp,
1940                                    Int4* pBlockIndex, Boolean* pLeftBoundary,
1941                                    Int4* pCol, Int4* pHPos) {
1942 /*****************************************************************************
1943 *  check if point pt is on one of the vertical bars that mark
1944 *  alignment boundaries.  return TRUE if it is.
1945 *  whether it's TRUE or not, ...
1946 *  return BlockIndex indicating which aligned block,
1947 *  return LeftBoundary = TRUE if p is on a left boundary,
1948 *  return LeftBoundary = FALSE if p is on a right boundary.
1949 *  return Col; the display coordinate for the alignment boundary.
1950 *  return HPos; the horizontal pixel position of the boundary.
1951 *****************************************************************************/
1952   RecT  rcP, rcBanner;
1953   Int4  TopVPos, BotVPos, LeftHPos, RightHPos;
1954   Int4  i, NumBlocks;
1955 
1956   /* this only works in the editor */
1957   if (!dmp->bEditor) return(FALSE);
1958 
1959   /* make rectangle for banner across top.  make it extra wide */
1960   ObjectRect(p, &rcP);
1961   DDV_GetVPixelPosOfEmptySpace(dmp, rcP, &TopVPos, &BotVPos);
1962   rcBanner = rcP;
1963   rcBanner.left += dmp->GrData.udv_panel.cxName + dmp->GrData.udv_scale.cxLeftScale;
1964   rcBanner.top =    TopVPos-4;
1965   rcBanner.bottom = BotVPos+8;
1966   rcBanner.left -= 4;
1967 
1968   /* for each aligned block */
1969   NumBlocks = DDE_GetNumBlocks(dmp->dsp->pEdit);
1970   for (i=0; i<NumBlocks; i++) {
1971     /* check if the pt is reasonably close to the left vertical bar */
1972     *pCol = DDE_GetAlignStart(dmp->dsp->pEdit, i);
1973     LeftHPos = DDV_GetHPixelPosGivenColNumber(dmp, rcP, *pCol);
1974     LeftHPos -= dmp->GrData.udv_font.ColWidth;
1975     if ((pt.x >= LeftHPos-5) && (pt.x <= LeftHPos+5)) {
1976       *pBlockIndex = i;
1977       *pLeftBoundary = TRUE;
1978       *pHPos = LeftHPos;
1979       if (PtInRect(pt, &rcBanner)) return(TRUE);
1980       return(FALSE);
1981     }
1982     /* check if the pt is reasonably close to the right vertical bar */
1983     *pCol = DDE_GetAlignStop(dmp->dsp->pEdit, i);
1984     RightHPos = DDV_GetHPixelPosGivenColNumber(dmp, rcP, *pCol);
1985     if ((pt.x >= RightHPos-5) && (pt.x <= RightHPos+5)) {
1986       *pBlockIndex = i;
1987       *pLeftBoundary = FALSE;
1988       *pHPos = RightHPos;
1989       if (PtInRect(pt, &rcBanner)) return(TRUE);
1990       return(FALSE);
1991     }
1992   }
1993   return(FALSE);
1994 }
1995 
1996 
1997 /*****************************************************************************
1998 
1999 Function: DDV_DragProc()
2000 
2001 Purpose: manage Mouse-Drag
2002 
2003 Parameters:	p; panel handle (currently unused)
2004 			pt; new position
2005 
2006 Return value: none
2007 
2008 *****************************************************************************/
DDV_DragProc(PaneL p,PoinT pt)2009 NLM_EXTERN void DDV_DragProc(PaneL p, PoinT pt)
2010 {
2011 DdvMainPtr 	dmp;
2012 RecT        rcP, rcP2;
2013 ParaGPtr    cur_pgp=NULL;
2014 Int4        Jump;
2015 Int4        Line_num, ParaGLine_num;/*to get the coordinates*/
2016 Int4        VPos, SavedVPos, from_col, to_col, from_row, to_row, old_VPos;
2017 Int4        HPos, SavedHPos, Col;
2018 Int4        Disp_coord_stop;
2019 Int4        Line_num_stop, BlockIndex, Offset, Width;
2020 BaR         vsb;
2021 Boolean     IsUnAligned;
2022 static Boolean  LineToErase=TRUE;
2023 
2024 	/*get the panel data*/
2025 	dmp = (DdvMainPtr) GetObjectExtra(p);
2026 	if (dmp==NULL) return;
2027 
2028 	/*what is happening ?*/
2029 	switch(dmp->ms.Action_type){
2030 		case MS_ACTION_SELECT_SEQ:/*selection on a sequence*/
2031 			if (shftKey) break;
2032 			ObjectRect(p,&rcP);
2033 			/*get the ParaG list and look for the ParaG where the mouse is located*/
2034 			/*note : only implemented for DDV_DISP_HORZ type of display...*/
2035 			if (dmp->MSA_d.pgp_l.DisplayType==DDV_DISP_HORZ) {
2036         /* get line num and col for current mouse position */
2037         DDV_GetRowAndColGivenPt(dmp, rcP, pt, &Disp_coord_stop, &Line_num_stop);
2038         /* force single row selection when needed */
2039         if (dmp->MouseMode == DDV_MOUSEMODE_SELECT_ONE_ROW) Line_num_stop = dmp->ms.first_row;
2040         /* erase the old rectangle */
2041         InvertMode();
2042         DrawOutline(p, dmp->ms.first_row, dmp->ms.first_col,
2043                        dmp->ms.last_row,  dmp->ms.last_col, TRUE);
2044         /* get display info */
2045         DDV_GetCurrentDispRange(dmp->hWndDDV,&(dmp->GrData),
2046           dmp->MSA_d.pgp_l.LengthAli,&from_col,&to_col,&from_row,&to_row);
2047         /* draw the new rectangle */
2048         CopyMode();
2049         DrawOutline(p, dmp->ms.first_row, dmp->ms.first_col,
2050                        Line_num_stop,     Disp_coord_stop, TRUE);
2051         /* display info about residues that mouse is over */
2052         DDV_DispStatus(dmp, Line_num_stop, dmp->ms.first_col, Disp_coord_stop);
2053       }
2054 
2055       break;
2056 		case MS_ACTION_RESIZE_WIN:/*the user moves the 3D line located between
2057 			name area and SeqAlign area*/
2058 			InvertMode();
2059 			UDV_draw_double_cursor(dmp->ms.rcClip, dmp->ms.oldPos);
2060 			dmp->ms.newPos=pt;
2061 			UDV_draw_double_cursor(dmp->ms.rcClip, dmp->ms.newPos);
2062  			dmp->ms.oldPos=dmp->ms.newPos;
2063 			Update();
2064 			break;
2065 		case MS_ACTION_SELECT_FULL_SEQ:
2066 			break;
2067     case MS_ACTION_MOVE_ROW:
2068 			ObjectRect(p,&rcP);
2069       rcP2.left =   rcP.left;
2070       rcP2.right =  rcP.left + dmp->GrData.udv_panel.cxName - 10;
2071       rcP2.top =    rcP.top;
2072       rcP2.bottom = rcP.bottom;
2073       Line_num=DDV_GetRowGivenMousePos(dmp, &rcP, &pt,&ParaGLine_num);
2074 
2075       DDV_GetCurrentDispRange(dmp->hWndDDV,&(dmp->GrData),
2076         dmp->MSA_d.pgp_l.LengthAli,&from_col,&to_col,&from_row,&to_row);
2077       vsb = GetSlateVScrollBar ((SlatE)dmp->hWndDDV);
2078       old_VPos = GetBarValue(vsb);
2079 
2080       if ((Line_num != -1) && (Line_num-1 >= from_row) && (Line_num-1 <= to_row)) {
2081         /* scroll vertically */
2082         Jump = ABS((Line_num-1) - dmp->dsp->SaveRow);
2083         if (Line_num >= to_row) {
2084           SetValue(vsb, old_VPos + Jump);
2085         }
2086         if (Line_num <= from_row+1) {
2087           SetValue(vsb, old_VPos - Jump);
2088         }
2089         /* get new line number, erase last underline, draw new one */
2090         SavedVPos = DDV_GetVPixelPosGivenRowNumber(dmp, rcP2, dmp->dsp->SaveRow);
2091         if ((Line_num-1) <= dmp->dsp->FromRow) {
2092           /* move before new row */
2093           VPos = DDV_GetVPixelPosGivenRowNumber(dmp, rcP2, Line_num-2);
2094           dmp->dsp->SaveRow = Line_num-2;
2095         }
2096         else {
2097           /* move after new row */
2098           VPos = DDV_GetVPixelPosGivenRowNumber(dmp, rcP2, Line_num-1);
2099           dmp->dsp->SaveRow = Line_num-1;
2100         }
2101         if (LineToErase) {
2102           InvertMode();
2103           UDV_draw_horizontal_line(rcP2, SavedVPos);
2104         }
2105         LineToErase = TRUE;
2106         UDV_draw_horizontal_line(rcP2, VPos);
2107       }
2108       else {
2109         /* just one time, xor the horizontal line to turn it off */
2110         if (LineToErase) {
2111           InvertMode();
2112           SavedVPos = DDV_GetVPixelPosGivenRowNumber(dmp, rcP2, dmp->dsp->SaveRow);
2113           UDV_draw_horizontal_line(rcP2, SavedVPos);
2114           LineToErase = FALSE;
2115         }
2116       }
2117       break;
2118     case MS_ACTION_SHIFT_ROW:
2119 			ObjectRect(p,&rcP);
2120       Col = DDV_GetColNumberGivenMousePos(dmp, rcP, pt);
2121       DDV_GetCurrentDispRange(dmp->hWndDDV,&(dmp->GrData),
2122         dmp->MSA_d.pgp_l.LengthAli,&from_col,&to_col,&from_row,&to_row);
2123       /* if we're still in a legal area */
2124       if ((Col>=from_col) && (Col<=to_col) && PtInRect(pt, &rcP)) {
2125         /* if a new box needs to be drawn */
2126         if (dmp->dsp->SaveCol != Col) {
2127           ObjectRect(p,&rcP);
2128           SavedVPos = DDV_GetVPixelPosGivenRowNumber(dmp, rcP, dmp->dsp->SaveRow);
2129           SavedHPos = DDV_GetHPixelPosGivenColNumber(dmp, rcP, dmp->dsp->SaveCol);
2130           /* erase old box */
2131           rcP2.left =    SavedHPos - dmp->GrData.udv_font.ColWidth;
2132           rcP2.right =   SavedHPos;
2133           rcP2.top =     SavedVPos - dmp->GrData.udv_font.LineHeight;
2134           rcP2.bottom =  SavedVPos;
2135           InvertMode();
2136           UDV_draw_rectangle(rcP2, FALSE);
2137           /* draw new box */
2138           dmp->dsp->SaveCol = Col;
2139           HPos = DDV_GetHPixelPosGivenColNumber(dmp, rcP, Col);
2140           rcP2.left =    HPos - dmp->GrData.udv_font.ColWidth;
2141           rcP2.right =   HPos;
2142           rcP2.top =     SavedVPos - dmp->GrData.udv_font.LineHeight;
2143           rcP2.bottom =  SavedVPos;
2144           UDV_draw_rectangle(rcP2, FALSE);
2145         }
2146       }
2147       break;
2148     case MS_ACTION_SHIFT_BOUNDARY:
2149       /* if we're still in a legit area */
2150       ObjectRect(p, &rcP);
2151       InsetRect(&rcP,4,4);
2152       DDV_AdjustDrawingRect(&rcP,&(dmp->GrData.udv_font),dmp);
2153       rcP.left += dmp->GrData.udv_panel.cxName + dmp->GrData.udv_scale.cxLeftScale;
2154       if (PtInRect(pt, &rcP)) {
2155         ObjectRect(p, &rcP);
2156         /* get column of new vertical bar */
2157         Col = DDV_GetColNumberGivenMousePos(dmp, rcP, pt);
2158         /* if column has changed since vertical bar was last drawn */
2159         if (Col != dmp->dsp->SaveCol) {
2160           /* and the column's legal */
2161           if ((Col >= 0) && (Col < dmp->MSA_d.pgp_l.LengthAli)) {
2162             /* get horizontal pixel position of old column */
2163             HPos = DDV_GetHPixelPosGivenColNumber(dmp, rcP, dmp->dsp->SaveCol);
2164             /* adjust for drawing bar preceeding left boundary */
2165             if (dmp->dsp->LeftBoundary) HPos -= dmp->GrData.udv_font.ColWidth;
2166             /* erase old vertical bar */
2167             InvertMode();
2168             UDV_draw_vertical_bar(rcP, HPos, TRUE);
2169             /* get horizontal pixel position of new column */
2170             HPos = DDV_GetHPixelPosGivenColNumber(dmp, rcP, Col);
2171             /* adjust for drawing bar preceeding left boundary */
2172             if (dmp->dsp->LeftBoundary) HPos -= dmp->GrData.udv_font.ColWidth;
2173             /* draw the new vertical bar */
2174             UDV_draw_vertical_bar(rcP, HPos, TRUE);
2175             /* save the column */
2176             dmp->dsp->SaveCol = Col;
2177           }
2178         }
2179       }
2180       break;
2181     case MS_ACTION_CREATE_BLOCK:
2182       ObjectRect(p, &rcP);
2183       InsetRect(&rcP,4,4);
2184       DDV_AdjustDrawingRect(&rcP,&(dmp->GrData.udv_font),dmp);
2185       rcP.left += dmp->GrData.udv_panel.cxName + dmp->GrData.udv_scale.cxLeftScale;
2186       /* if we're still in a legit area */
2187       if (PtInRect(pt, &rcP)) {
2188         ObjectRect(p, &rcP);
2189         Col = DDV_GetColNumberGivenMousePos(dmp, rcP, pt);
2190         /* and the column has changed since vertical bar was last drawn */
2191         if (Col != dmp->dsp->SaveCol) {
2192           /* and the column's legal */
2193           if ((Col >= 0) && (Col < dmp->MSA_d.pgp_l.LengthAli)) {
2194             if (Col >= dmp->dsp->FromCol) {
2195               /* get horizontal pixel position of old column */
2196               HPos = DDV_GetHPixelPosGivenColNumber(dmp, rcP, dmp->dsp->SaveCol);
2197               /* erase old vertical bar */
2198               InvertMode();
2199               UDV_draw_vertical_bar(rcP, HPos, TRUE);
2200               /* get horizontal pixel position of new column */
2201               HPos = DDV_GetHPixelPosGivenColNumber(dmp, rcP, Col);
2202               /* draw the new vertical bar */
2203               UDV_draw_vertical_bar(rcP, HPos, TRUE);
2204               /* save the column */
2205               dmp->dsp->SaveCol = Col;
2206             }
2207           }
2208         }
2209       }
2210       break;
2211     case MS_ACTION_SPLIT_BLOCK:
2212       /* adjust x position so vertical bar jumps when mouse is on center of char */
2213       pt.x -= dmp->GrData.udv_font.ColWidth/2;
2214       /* get block, col, etc for new mouse position */
2215       if (GetBlockAndAlignment(pt, p, dmp, &BlockIndex, &IsUnAligned, &Col, &Offset, &Width, &rcP)) {
2216         /* if mouse col changed */
2217         if (Col != dmp->SaveCol) {
2218           /* get horizontal pixel position of old column */
2219           HPos = DDV_GetHPixelPosGivenColNumber(dmp, rcP, dmp->SaveCol);
2220           /* erase old vertical bar */
2221           InvertMode();
2222           UDV_draw_vertical_bar(rcP, HPos, FALSE);
2223           /* get horizontal pixel position of new column */
2224           HPos = DDV_GetHPixelPosGivenColNumber(dmp, rcP, Col);
2225           /* draw the new vertical bar */
2226           UDV_draw_vertical_bar(rcP, HPos, FALSE);
2227           /* save the column */
2228           dmp->SaveCol = Col;
2229         }
2230       }
2231 	}
2232 }
2233 
2234 /*****************************************************************************
2235 
2236 Function: DDV_ReleaseProc()
2237 
2238 Purpose: manage Mouse-Release
2239 
2240 Parameters:	p; panel handle (currently unused)
2241 			pt; new position
2242 
2243 Return value: none
2244 
2245 *****************************************************************************/
DDV_ReleaseProc(PaneL p,PoinT pt)2246 NLM_EXTERN void DDV_ReleaseProc(PaneL p, PoinT pt)
2247 {
2248 WindoW 	       temport;
2249 DdvMainPtr 	   dmp;
2250 DdvMainWinPtr  dmwp;
2251 DDVUpdateMSGPtr dump;
2252 RecT         rcP, rcP2;
2253 ParaGPtr     cur_pgp=NULL;
2254 Int4         bsp_coord, SeqAlign_coord;
2255 Int4         Disp_coord, Line_num,ParaGLine_Num;/*to get the coordinates*/
2256 Uint1        uWhere; /*where the use clicked (seq, feat, name,...)*/
2257 Uint2        bsp_eID;
2258 Uint4        bsp_iID;
2259 Int4         VPos, Shift, SavedVPos, SavedHPos, BlockIndex, NumBlocks;
2260 Boolean      IsUnAligned;
2261 MsaParaGPopListPtr  mpplp;
2262 SeqAlignPtr   sap;
2263 DDE_StackPtr  dsp;
2264 Int4          Offset, Width;
2265 BaR           hsb;
2266 RecT          rc;
2267 
2268 
2269 	/*get the panel data*/
2270 	dmp = (DdvMainPtr) GetObjectExtra(p);
2271 	if (dmp==NULL) return;
2272 
2273     switch(dmp->ms.Action_type){
2274 		case MS_ACTION_SELECT_FULL_SEQ:
2275             ObjectRect(p,&rcP);
2276 			Line_num=DDV_GetRowGivenMousePos(dmp,&rcP,&pt,&ParaGLine_Num);
2277 			if (Line_num!=(Int4)-1){
2278                 UDV_DecodeIdxFeat (dmp->MSA_d.pgp_l.entitiesTbl[ParaGLine_Num-1],
2279                     &bsp_eID,&bsp_iID);
2280                 ObjMgrSendMsg(OM_MSG_MOUSEUP, bsp_eID, bsp_iID, OBJ_BIOSEQ);
2281 			}
2282 			break;
2283         case MS_ACTION_SELECT_SEQ:
2284             /* erase outline */
2285             InvertMode();
2286             rc = DrawOutline(p, dmp->ms.first_row, dmp->ms.first_col,
2287                                 dmp->ms.last_row,   dmp->ms.last_col, TRUE);
2288             CopyMode();
2289             DDV_SelectRegion(dmp, pt, rc, dmp->ms.first_row, dmp->ms.last_row,
2290                                           dmp->ms.first_col, dmp->ms.last_col);
2291 
2292             ObjectRect(p,&rcP);
2293             pt.y=dmp->ms.oldPos.y;
2294             if (dmp->MSA_d.pgp_l.DisplayType==DDV_DISP_HORZ){
2295                 if (DDV_GetCoordsGivenAClick(dmp,&rcP,&pt,
2296                         &bsp_coord,&SeqAlign_coord,&Disp_coord,&Line_num,
2297 
2298 						&ParaGLine_Num,&uWhere,&cur_pgp)){
2299 					if (uWhere==PGP_REGION_SEQ){
2300                         UDV_DecodeIdxFeat (dmp->MSA_d.pgp_l.entitiesTbl[ParaGLine_Num-1],
2301                             &bsp_eID,&bsp_iID);
2302                         ObjMgrSendMsg(OM_MSG_MOUSEUP, bsp_eID, bsp_iID, OBJ_BIOSEQ);
2303 						/*send a OM_MSG_UPDATE message to move the caret (if needed)*/
2304 						if (dmp->MouseMode==DDV_MOUSEMODE_EDIT){
2305 							dump=(DDVUpdateMSGPtr)MemNew(sizeof(DDVUpdateMSG));
2306 							if (dump){
2307 								dmp->dci.new_row=Line_num;
2308 								dmp->dci.new_col=Disp_coord;
2309 								dump->type=UPDATE_TYPE_CARETPOS;
2310 								dump->data=NULL;
2311 								ObjMgrSendProcMsg(OM_MSG_UPDATE, bsp_eID, bsp_iID, OBJ_BIOSEQ,
2312 										0,0,(Pointer)dump);
2313 								MemFree(dump);
2314 							}
2315 						}
2316                     }
2317                 } else {  /* send mouse up anyway */
2318                     if(ParaGLine_Num > 0) {
2319                         UDV_DecodeIdxFeat (dmp->MSA_d.pgp_l.entitiesTbl[ParaGLine_Num-1],
2320                             &bsp_eID,&bsp_iID);
2321                         ObjMgrSendMsg(OM_MSG_MOUSEUP, bsp_eID, bsp_iID, OBJ_BIOSEQ);
2322                     }
2323                 }
2324             }
2325 			break;
2326 		case MS_ACTION_RESIZE_WIN:
2327 			temport=SavePort((WindoW)p);
2328 			Select(p);
2329 			InvertMode();
2330 			UDV_draw_double_cursor(dmp->ms.rcClip,
2331 				dmp->ms.oldPos);
2332 			/*redraw panel with new 'cxName' value*/
2333 			if (PtInRect(dmp->ms.newPos,&dmp->ms.rcClip)){
2334 				RecT rc;
2335 
2336 				ObjectRect(p,&rc);
2337 				rc.left=0;/*for obscure reasons, not == 0*/
2338 				rc.top=0;
2339 				dmp->GrData.udv_panel.cxName=dmp->ms.newPos.x;
2340 				DDV_Resize_DDV(p,FALSE); /*DDV_SetupWin (p,FALSE,NULL); */
2341 				InvalRect(&rc);
2342 			}
2343 			RestorePort(temport);
2344 			break;
2345     case MS_ACTION_MOVE_ROW:
2346       ObjectRect(p, &rcP);
2347       /* if the mouse is released in sequence name section */
2348       if (pt.x<dmp->GrData.udv_panel.cxName &&
2349           pt.y>(rcP.top+dmp->GrData.udv_panel.cyScale)){
2350         /* get the line number where the mouse is released */
2351         Line_num=DDV_GetRowGivenMousePos(dmp, &rcP, &pt,&ParaGLine_Num);
2352         if (Line_num != -1) {
2353           /* if the line number is valid */
2354           if (dmp->dsp->FromRow != Line_num-1) {
2355             /* move the saved row to this line number */
2356             DDE_MoveRow(dmp->dsp, dmp->dsp->FromRow, Line_num-1, TRUE);
2357             dmp->deri.curEditRow = Line_num-1;
2358             DDV_ReDraw(dmp);
2359           }
2360           /* otherwise */
2361           else {
2362             /* since screen's not redrawn, turn off the last drawn horizontal line */
2363             ObjectRect(p, &rcP);
2364             rcP2.left =   rcP.left;
2365             rcP2.right =  rcP.left + dmp->GrData.udv_panel.cxName - 10;
2366             rcP2.top =    rcP.top;
2367             rcP2.bottom = rcP.bottom;
2368             VPos = DDV_GetVPixelPosGivenRowNumber(dmp, rcP2, dmp->dsp->SaveRow);
2369             InvertMode();
2370             UDV_draw_horizontal_line(rcP2, VPos);
2371           }
2372         }
2373       }
2374       ArrowCursor();
2375       break;
2376     case MS_ACTION_SHIFT_ROW:
2377       /* shift row by diff between original col position and last position */
2378       Shift = dmp->dsp->SaveCol - dmp->dsp->FromCol;
2379       if (DDE_ShiftRow(dmp->dsp, dmp->dsp->SaveRow, Shift, TRUE, TRUE)) {
2380         DDV_ReDraw(dmp);
2381       }
2382       else {
2383         /* if no shift was done, erase the boxes */
2384         ObjectRect(p,&rcP);
2385         SavedVPos = DDV_GetVPixelPosGivenRowNumber(dmp, rcP, dmp->dsp->SaveRow);
2386         SavedHPos = DDV_GetHPixelPosGivenColNumber(dmp, rcP, dmp->dsp->SaveCol);
2387         rcP2.left =    SavedHPos - dmp->GrData.udv_font.ColWidth;
2388         rcP2.right =   SavedHPos;
2389         rcP2.top =     SavedVPos - dmp->GrData.udv_font.LineHeight;
2390         rcP2.bottom =  SavedVPos;
2391         InsetRect(&rcP2, -2, -2);
2392         InvalRect(&rcP2);
2393       }
2394       ArrowCursor();
2395       break;
2396     case MS_ACTION_SHIFT_BOUNDARY:
2397       /* shift boundary by diff between original col position and last position */
2398       Shift = dmp->dsp->SaveCol - dmp->dsp->FromCol;
2399       if (dmp->dsp->LeftBoundary) {
2400         DDE_ShiftLeftBoundary(dmp->dsp, dmp->dsp->BlockIndex, Shift, TRUE);
2401         DDV_ReDraw(dmp);
2402       }
2403       else {
2404         DDE_ShiftRightBoundary(dmp->dsp, dmp->dsp->BlockIndex, Shift, TRUE);
2405         DDV_ReDraw(dmp);
2406       }
2407       ArrowCursor();
2408       break;
2409     case MS_ACTION_CREATE_BLOCK:
2410       DDE_CreateBlock(dmp->dsp, dmp->dsp->FromCol, dmp->dsp->SaveCol, TRUE);
2411       dmp->MouseMode = dmp->SavedMouseMode;
2412       DDV_ReDraw(dmp);
2413       ArrowCursor();
2414       break;
2415     case MS_ACTION_SPLIT_BLOCK:
2416       /* get block and alignment for last saved col */
2417       /* also get offset into block and width of block */
2418       GetBlockAndAlignmentForCol(dmp, dmp->SaveCol, &BlockIndex, &IsUnAligned, &Offset, &Width);
2419       /* if col is in aligned region */
2420       if (!IsUnAligned && (Offset < (Width-1))) {
2421         /* create a stack for the block */
2422         sap = ViewMgr_GetBeginIndexed(dmp->MSA_d.pgp_l.sap);
2423         dmp->MSA_d.pgp_l.viewed_sap = dmp->MSA_d.pgp_l.sap;
2424         mpplp = DDE_CreateDisplay(sap, BlockIndex, FALSE, &NumBlocks);
2425         dsp = DDE_NewStack(mpplp);
2426         DDE_MergeNodesLists(dsp->pEdit);
2427         /* record which block is being edited, etc */
2428         dsp->LaunchBlock = BlockIndex;
2429         dsp->NumBlocks =   NumBlocks;
2430         dsp->IsUnAligned = IsUnAligned;
2431         /* shift right boundary of block left, to the split line */
2432         DDE_ShiftRightBoundary(dsp, 0, -(Width-(Offset+1)), FALSE);
2433         /* tell AlnMgr to save edits, don't redraw yet */
2434         dmp->dsp = dsp;
2435         DDV_SaveEdits(dmp, FALSE);
2436         /* free stack for block.  create stack for unaligned region to right of block */
2437         DDE_FreeStack(dsp);
2438         sap = ViewMgr_GetBeginIndexed(dmp->MSA_d.pgp_l.sap);
2439         dmp->MSA_d.pgp_l.viewed_sap = dmp->MSA_d.pgp_l.sap;
2440         mpplp = DDE_CreateDisplay(sap, BlockIndex+1, TRUE, &NumBlocks);
2441         dsp = DDE_NewStack(mpplp);
2442         DDE_MergeNodesLists(dsp->pEdit);
2443         /* create new block of part that was just unaligned */
2444         DDE_CreateBlock(dsp, 0, (Width-(Offset+1)-1), FALSE);
2445         /* tell AlnMgr to save edits, now redraw */
2446         dmp->dsp = dsp;
2447         DDV_SaveEdits(dmp, TRUE);
2448         /* free remaining stack */
2449         dsp = DDE_FreeStack(dsp);
2450         dmp->dsp = dsp;
2451         dmp->MouseMode = dmp->SavedMouseMode;
2452       }
2453       /* get rid of vertical bar */
2454       else {
2455         hsb = GetSlateHScrollBar((SlatE) dmp->hWndDDV);
2456         DDV_ReDrawAtCol(dmp, GetBarValue(hsb), FALSE);
2457       }
2458 	}
2459 
2460   ClearUDV_mouse_select(&(dmp->ms));
2461 	dmp->ms.Action_type=MS_ACTION_FEAT_NOTHING;
2462 	/*update InfoPanel*/
2463 	dmwp=(DdvMainWinPtr)GetObjectExtra(dmp->hParent);
2464   if (dmp->bEditor) {
2465     DDV_GreyOut(dmwp, DDE_AtStartOfStack(dmp->dsp), DDE_AtEndOfStack(dmp->dsp));
2466   }
2467 	if (dmwp && dmp->MouseMode!=DDV_MOUSEMODE_EDIT)
2468 		SetTitle(dmwp->InfoPanel,"Ready !");
2469 
2470   if (dmp->MouseMode != DDV_MOUSEMODE_MERGEBLOCKS2)
2471     ArrowCursor();
2472 }
2473 
2474 /*****************************************************************************
2475 
2476 Function: DDV_HoldProc()
2477 
2478 Purpose: manage Mouse-Hold
2479 
2480 Parameters:	p; panel handle (currently unused)
2481 			pt; new position
2482 
2483 Return value: none
2484 
2485 *****************************************************************************/
DDV_HoldProc(PaneL p,PoinT pt)2486 NLM_EXTERN void DDV_HoldProc(PaneL p, PoinT pt)
2487 {
2488 DdvMainPtr 	dmp;
2489 RecT        rcP;
2490 ParaGPtr    cur_pgp=NULL;
2491 Int4        Disp_coord_stop;
2492 Int4        Line_num_stop;
2493 Int4        from_col, to_col, from_row, to_row;
2494 Boolean     Scroll=FALSE;
2495 
2496 	/*get the panel data*/
2497 	dmp = (DdvMainPtr) GetObjectExtra(p);
2498 	if (dmp==NULL) return;
2499 
2500 	/*what is happening ?*/
2501 	switch(dmp->ms.Action_type){
2502 		case MS_ACTION_SELECT_SEQ:
2503 			if (shftKey) break;
2504 			ObjectRect(p,&rcP);
2505 			/*get the ParaG list and look for the ParaG where the mouse is located*/
2506 			/*note : only implemented for DDV_DISP_HORZ type of display...*/
2507 			if (dmp->MSA_d.pgp_l.DisplayType==DDV_DISP_HORZ) {
2508         /* get line num and col for current mouse position */
2509         DDV_GetRowAndColGivenPt(dmp, rcP, pt, &Disp_coord_stop, &Line_num_stop);
2510         /* force single row selection when needed */
2511         if (dmp->MouseMode == DDV_MOUSEMODE_SELECT_ONE_ROW) Line_num_stop = dmp->ms.first_row;
2512         /* erase the old rectangle */
2513         InvertMode();
2514         DrawOutline(p, dmp->ms.first_row, dmp->ms.first_col,
2515                        dmp->ms.last_row,  dmp->ms.last_col, TRUE);
2516         /* get display info */
2517         DDV_GetCurrentDispRange(dmp->hWndDDV,&(dmp->GrData),
2518           dmp->MSA_d.pgp_l.LengthAli,&from_col,&to_col,&from_row,&to_row);
2519         /* draw the new rectangle after scrolling */
2520         DDV_AutoHScroll(dmp, Disp_coord_stop);
2521         DDV_AutoVScroll(dmp, Line_num_stop);
2522         CopyMode();
2523         DrawOutline(p, dmp->ms.first_row, dmp->ms.first_col,
2524                        Line_num_stop,     Disp_coord_stop, TRUE);
2525         /* display info about residues that mouse is over */
2526         DDV_DispStatus(dmp, Line_num_stop, dmp->ms.first_col, Disp_coord_stop);
2527       }
2528       break;
2529 		case MS_ACTION_RESIZE_WIN:
2530 		case MS_ACTION_SELECT_FULL_SEQ:
2531 			break;
2532 	}/*end switch()*/
2533 }
2534 
2535 /*****************************************************************************
2536 
2537 Function: DDV_MoveCaretLR()
2538 
2539 Purpose: move the caret to the right or to the left
2540 
2541 Parameters:
2542 
2543 Return value: none
2544 
2545 *****************************************************************************/
DDV_MoveCaretLR(DdvMainPtr dmp,Int4 decal_Hscroll,Boolean bMoveRight,BaR hsb,Int4 old_Hpos,Int4 from_col,Int4 to_col)2546 static void DDV_MoveCaretLR(DdvMainPtr dmp,Int4 decal_Hscroll,
2547 	Boolean bMoveRight,BaR hsb,Int4 old_Hpos,Int4 from_col,Int4 to_col)
2548 {
2549 DDVUpdateMSGPtr dump;
2550 Uint2           bsp_eID;
2551 Uint4           bsp_iID;
2552 Int4            shift, new_from_col, new_to_col;
2553 
2554 	dump=(DDVUpdateMSGPtr)MemNew(sizeof(DDVUpdateMSG));
2555 	if (dump){
2556 		/*get bsp IDs*/
2557 		UDV_DecodeIdxFeat(dmp->MSA_d.pgp_l.entitiesTbl[dmp->dci.new_row-1],
2558             	&bsp_eID,&bsp_iID);
2559 		/*save old position*/
2560 		dmp->dci.old_col=dmp->dci.new_col;
2561 		dmp->dci.old_row=dmp->dci.new_row;
2562 		/*update the position*/
2563 		if (bMoveRight)
2564 			dmp->dci.new_col+=decal_Hscroll;
2565 		else
2566 			dmp->dci.new_col-=decal_Hscroll;
2567 		if (dmp->dci.new_col<0){
2568 			dmp->dci.new_col=0;
2569 			Beep();
2570 			return;
2571 		}
2572 		if (dmp->dci.new_col>dmp->MSA_d.pgp_l.LengthAli-1){
2573 			dmp->dci.new_col=dmp->MSA_d.pgp_l.LengthAli-1;
2574 			Beep();
2575 			return;
2576 		}
2577 		/*auto-scroll the panel if needed*/
2578     if (dmp->dci.new_col<=from_col){
2579       shift = (to_col-from_col)/2;
2580       new_from_col = from_col - shift;
2581       new_to_col = to_col - shift;
2582       if ((dmp->dci.new_col >= new_from_col) && (dmp->dci.new_col <= new_to_col)) {
2583         /* shift left by 1/2 the window width */
2584         SetValue(hsb,old_Hpos-shift);
2585       }
2586       else {
2587         /* shifting by more than 1/2 the window width */
2588         SetValue(hsb, dmp->dci.new_col);
2589       }
2590     }
2591     if (dmp->dci.new_col>=to_col){
2592       shift = (to_col-from_col)/2;
2593       new_from_col = from_col + shift;
2594       new_to_col = to_col + shift;
2595       if ((dmp->dci.new_col >= new_from_col) && (dmp->dci.new_col <= new_to_col)) {
2596         /* shift right by 1/2 the window width */
2597         SetValue(hsb,old_Hpos+shift);
2598       }
2599       else {
2600         /* shifting by more than 1/2 the window width */
2601         SetValue(hsb, dmp->dci.new_col);
2602       }
2603     }
2604 		/*if ok, move the caret*/
2605 		dump->type=UPDATE_TYPE_CARETPOS;
2606 		dump->data=NULL;
2607 		ObjMgrSendProcMsg(OM_MSG_UPDATE, bsp_eID, bsp_iID, OBJ_BIOSEQ,
2608 				0,0,(Pointer)dump);
2609 		MemFree(dump);
2610 	}
2611 }
2612 
2613 /*****************************************************************************
2614 
2615 Function: DDV_MoveCaretUD()
2616 
2617 Purpose: move the caret up or down
2618 
2619 Parameters:
2620 
2621 Return value: none
2622 
2623 *****************************************************************************/
DDV_MoveCaretUD(DdvMainPtr dmp,Int4 decal_Vscroll,Boolean bMoveDown,BaR vsb,Int4 old_Vpos,Int4 from_row,Int4 to_row)2624 static void DDV_MoveCaretUD(DdvMainPtr dmp,Int4 decal_Vscroll,
2625 	Boolean bMoveDown,BaR vsb,Int4 old_Vpos,Int4 from_row,Int4 to_row)
2626 {
2627 DDVUpdateMSGPtr dump;
2628 Uint2           bsp_eID;
2629 Uint4           bsp_iID;
2630 Int4            shift;
2631 
2632 	dump=(DDVUpdateMSGPtr)MemNew(sizeof(DDVUpdateMSG));
2633 	if (dump){
2634 		/*get bsp IDs*/
2635 		UDV_DecodeIdxFeat(dmp->MSA_d.pgp_l.entitiesTbl[dmp->dci.new_row-1],
2636             	&bsp_eID,&bsp_iID);
2637 		/*save old position*/
2638 		dmp->dci.old_row=dmp->dci.new_row;
2639 		dmp->dci.old_col=dmp->dci.new_col;
2640 		/*update the position*/
2641 		if (bMoveDown)
2642 			dmp->dci.new_row+=decal_Vscroll;
2643 		else
2644 			dmp->dci.new_row-=decal_Vscroll;
2645 
2646 		if (dmp->dci.new_row<1){
2647 			dmp->dci.new_row=1;
2648       SetValue(vsb, 0);
2649 			Beep();
2650       goto send_msg;
2651 		}
2652 		if (dmp->dci.new_row>dmp->MSA_d.pgp_l.nBsp){
2653 			dmp->dci.new_row=dmp->MSA_d.pgp_l.nBsp;
2654       SetValue(vsb, dmp->MSA_d.pgp_l.nBsp);
2655 			Beep();
2656       goto send_msg;
2657 		}
2658 
2659 		/*auto-scroll the panel if needed*/
2660     if (ABS(decal_Vscroll) == 1) {
2661 		  if (dmp->dci.new_row<=from_row){
2662         shift = (to_row-from_row)/2;
2663         SetValue(vsb, old_Vpos-shift);
2664 		  }
2665 		  if (dmp->dci.new_row>=to_row-1){
2666         shift = (to_row-from_row)/2;
2667         SetValue(vsb, old_Vpos+shift);
2668 		  }
2669     }
2670     else {
2671       if (bMoveDown) {
2672         SetValue(vsb, old_Vpos+decal_Vscroll);
2673       }
2674       else {
2675         SetValue(vsb, old_Vpos-decal_Vscroll);
2676       }
2677     }
2678 
2679 		/*if ok, move the caret*/
2680 send_msg:
2681 		dump->type=UPDATE_TYPE_CARETPOS;
2682 		dump->data=NULL;
2683 		ObjMgrSendProcMsg(OM_MSG_UPDATE, bsp_eID, bsp_iID, OBJ_BIOSEQ,
2684 				0,0,(Pointer)dump);
2685 		MemFree(dump);
2686 	}
2687 }
2688 
2689 /*****************************************************************************
2690 
2691 Function: DDV_KeyboardProc()
2692 
2693 Purpose: manage keyboard actions
2694 
2695 Parameters:	s; panel handle (DDV panel)
2696 			ch; key
2697 
2698 Return value: none
2699 
2700 *****************************************************************************/
DDV_KeyboardProc(SlatE s,Char ch)2701 NLM_EXTERN void DDV_KeyboardProc (SlatE s, Char ch)
2702 {
2703 DdvMainWinPtr dmwp; /*main window*/
2704 DdvMainPtr dmp;     /*DDV panel associated data*/
2705 BaR        hsb,vsb; /*DDV' scroll bars*/
2706 Int4       old_Hpos,old_Vpos,/*scrolls positions*/
2707            decal_Hscroll,decal_Vscroll,/*used to scroll DDV's panel*/
2708            from_col,to_col,from_row,to_row,/*display size*/
2709            bsp_pos, height;
2710 
2711 	if ( (int) ch == 0 ) return;
2712 
2713 	/*get the panel data*/
2714 	dmp = (DdvMainPtr) GetObjectExtra(s);
2715 	if (dmp==NULL) return;
2716 	dmwp = (DdvMainWinPtr) GetObjectExtra(dmp->hParent);
2717   if (dmwp == NULL) return;
2718 
2719 	/*get scroll handles and data*/
2720 	hsb = GetSlateHScrollBar ((SlatE) dmp->hWndDDV);
2721 	old_Hpos=GetBarValue(hsb);
2722 	vsb = GetSlateVScrollBar ((SlatE) dmp->hWndDDV);
2723 	old_Vpos=GetBarValue(vsb);
2724 
2725 	/*get the display size*/
2726 	DDV_GetCurrentDispRange(dmp->hWndDDV,&(dmp->GrData),
2727 		dmp->MSA_d.pgp_l.LengthAli,&from_col,&to_col,&from_row,&to_row);
2728 
2729 	/*if pressed, scroll panel by one 'panel' size*/
2730 	if (ctrlKey) {
2731 		decal_Hscroll=to_col-from_col;
2732 		decal_Vscroll=to_row-from_row;
2733 	}
2734 	else{
2735 		decal_Hscroll=1;
2736 		decal_Vscroll=1;
2737 	}
2738 
2739 	/*switch to one-bsed value because dmp->dci values
2740 	  are one-based values*/
2741 	from_row++;to_row++;
2742 
2743 	switch ((int) TO_UPPER(ch)){
2744     case NLM_PREV:
2745       /* page-up -- scoll page up one page height */
2746       height = (to_row-from_row) - 1;
2747 			if (dmp->MouseMode==DDV_MOUSEMODE_EDIT) {
2748         DDV_MoveCaretUD(dmp, height, FALSE, vsb, old_Vpos, from_row, to_row);
2749       }
2750       else {
2751         SetValue(vsb, old_Vpos - height);
2752       }
2753       break;
2754     case NLM_NEXT:
2755       /* page-down -- scoll page down one page height */
2756       height = (to_row-from_row) - 1;
2757 			if (dmp->MouseMode==DDV_MOUSEMODE_EDIT) {
2758 				DDV_MoveCaretUD(dmp, height, TRUE, vsb, old_Vpos, from_row, to_row);
2759       }
2760       else {
2761         SetValue(vsb, old_Vpos + height);
2762       }
2763       break;
2764     case NLM_HOME:
2765       /* for home key, move cursor to start of row */
2766 			if (dmp->MouseMode==DDV_MOUSEMODE_EDIT){
2767         /* move caret left by current col pos */
2768 				DDV_MoveCaretLR(dmp, dmp->dci.new_col, FALSE, hsb, old_Hpos, from_col, to_col);
2769       }
2770       else {
2771         SetValue(hsb, 0);
2772       }
2773       break;
2774     case NLM_END:
2775       /* for end key, move cursor to end of row */
2776 			if (dmp->MouseMode==DDV_MOUSEMODE_EDIT){
2777         /* move caret right by diff between last col and current col */
2778         DDV_MoveCaretLR(dmp, ((dmp->MSA_d.pgp_l.LengthAli-1) - dmp->dci.new_col), TRUE,
2779                         hsb, old_Hpos, from_col, to_col);
2780       }
2781       else {
2782         SetValue(hsb, dmp->MSA_d.pgp_l.LengthAli-1);
2783       }
2784       break;
2785     case 0x1a:
2786       /* for ctrl-z, undo the last edit */
2787       if (DDE_Prev(dmp->dsp)) {
2788         DDV_ReDraw(dmp);
2789       }
2790       break;
2791     case 0x19:
2792       /* for ctrl-y, redo the last undone edit */
2793       if (DDE_Next(dmp->dsp)) {
2794         DDV_ReDraw(dmp);
2795       }
2796       break;
2797     case NLM_DEL:
2798       /* delete key pressed -- remove a gap and leave carat in place */
2799 			if (dmp->MouseMode==DDV_MOUSEMODE_EDIT){
2800         if (DDE_RemoveGap(dmp->dsp, dmp->dci.new_row-1, dmp->dci.new_col+1, TRUE)) {
2801           DDV_ReDraw(dmp);
2802         }
2803       }
2804       break;
2805     case 0x08:
2806       /* backspace key pressed -- remove gap to the left and move carat left */
2807 			if (dmp->MouseMode==DDV_MOUSEMODE_EDIT){
2808         if (DDE_RemoveGap(dmp->dsp, dmp->dci.new_row-1, dmp->dci.new_col, TRUE)) {
2809           DDV_ReDraw(dmp);
2810         }
2811       }
2812 		case NLM_LEFT:
2813 			/*move the caret ?*/
2814 			if (dmp->MouseMode==DDV_MOUSEMODE_EDIT){
2815 				decal_Hscroll=1;/*doesn't accept ctrlKey motions*/
2816 				DDV_MoveCaretLR(dmp,decal_Hscroll,FALSE,hsb,old_Hpos,
2817 					from_col,to_col);
2818 			}
2819 			/*scroll the panel*/
2820 			else{
2821 				SetValue(hsb,old_Hpos-decal_Hscroll);
2822 			}
2823 			break;
2824     case 0x20:
2825       /* space bar pressed -- insert a gap and move carat to the right */
2826 			if (dmp->MouseMode==DDV_MOUSEMODE_EDIT){
2827         if (DDE_InsertGap(dmp->dsp, dmp->dci.new_row-1, dmp->dci.new_col+1, TRUE)) {
2828           DDV_ReDraw(dmp);
2829         }
2830       }
2831 		case NLM_RIGHT:
2832 			/*move the caret ?*/
2833 			if (dmp->MouseMode==DDV_MOUSEMODE_EDIT){
2834 				decal_Hscroll=1;/*doesn't accept ctrlKey motions*/
2835 				DDV_MoveCaretLR(dmp,decal_Hscroll,TRUE,hsb,old_Hpos,
2836 					from_col,to_col);
2837 			}
2838 			/*scroll the panel*/
2839 			else {
2840 				SetValue(hsb,old_Hpos+decal_Hscroll);
2841 			}
2842 			break;
2843 		case NLM_UP:
2844 			/*move the caret ?*/
2845 			if (dmp->MouseMode==DDV_MOUSEMODE_EDIT){
2846 				decal_Vscroll=1;/*doesn't accept ctrlKey motions*/
2847 				DDV_MoveCaretUD(dmp,decal_Vscroll,FALSE,vsb,old_Vpos,
2848 					from_row,to_row);
2849 			}
2850 			/*scroll the panel*/
2851 			else{
2852 				SetValue(vsb,old_Vpos-decal_Vscroll);
2853 			}
2854 			break;
2855 		case NLM_DOWN:
2856 			/*move the caret ?*/
2857 			if (dmp->MouseMode==DDV_MOUSEMODE_EDIT){
2858 				decal_Vscroll=1;/*doesn't accept ctrlKey motions*/
2859 				DDV_MoveCaretUD(dmp,decal_Vscroll,TRUE,vsb,old_Vpos,
2860 					from_row,to_row);
2861 			}
2862 			/*scroll the panel*/
2863 			else{
2864 				SetValue(vsb,old_Vpos+decal_Vscroll);
2865 			}
2866 			break;
2867 		default:
2868 			Beep ();
2869 			break;
2870 	}
2871   if (dmp->bEditor) {
2872     DDV_GreyOut(dmwp, DDE_AtStartOfStack(dmp->dsp), DDE_AtEndOfStack(dmp->dsp));
2873   }
2874 
2875 	/*update InfoPanel with position*/
2876 	if (dmwp && dmp->MouseMode==DDV_MOUSEMODE_EDIT){
2877 		Char szAccess[21];
2878 		DDV_GetSeqNameGivenRow(dmp->MSA_d.pgp_l.TableHead, dmp->dci.new_row,
2879 			szAccess);
2880 		bsp_pos=DDV_GetBspCoordGivenPgpList(
2881 			dmp->MSA_d.pgp_l.TableHead[dmp->dci.new_row-1],
2882 			dmp->dci.new_col);
2883 		if (bsp_pos!=(Int4)-1){
2884 			DDV_DispPositionInStatus(dmwp->InfoPanel,
2885 				bsp_pos+1,dmp->dci.new_row,szAccess);
2886 					/*+1 : switch to one-based value*/
2887 		}
2888 	}
2889 }
2890 
2891 
DDV_ReDrawAtCol(DdvMainPtr dmp,Int4 Col,Boolean DDE)2892 NLM_EXTERN void DDV_ReDrawAtCol(DdvMainPtr dmp, Int4 Col, Boolean DDE) {
2893 /*------------------------------------------
2894 *  resize, redraw.
2895 *------------------------------------------*/
2896   DdvMainWinPtr  dmwp;
2897   WindoW         temport;
2898   RecT 	         rcP;
2899   BaR            hsb;
2900   Int4           NumBlocks;
2901 
2902   if (DDE) {
2903     MemCopy(&(dmp->MSA_d.pgp_l), dmp->dsp->pEdit->pPopList, sizeof(MsaParaGPopList));
2904   }
2905 
2906   DDV_InitColour_When_Start(dmp->MSA_d.pgp_l.sap,
2907     &(dmp->MSA_d.pgp_l),&(dmp->Globals.colorp), FALSE);
2908   /* recalculate window size */
2909   DDV_WhatSize(dmp);
2910   /* adjust horizontal scroll bar */
2911   hsb = GetSlateHScrollBar((SlatE) dmp->hWndDDV);
2912   DDV_UpdateHScrollVal(dmp->hWndDDV, FALSE, GetBarValue(hsb));
2913 
2914   dmwp=(DdvMainWinPtr)GetObjectExtra(dmp->hParent);
2915   temport=SavePort(dmwp->hWndDDV);
2916   Select(dmwp->hWndDDV);
2917   ObjectRect(dmwp->hWndDDV, &rcP);
2918   InvalRect(&rcP);
2919   if (Col >= 0) {
2920     SetValue(hsb, Col);
2921   }
2922   Update();
2923   RestorePort(temport);
2924 
2925   if (DDE) {
2926     /* decide about greying out undo and redo functions */
2927     DDV_GreyOut(dmwp, DDE_AtStartOfStack(dmp->dsp), DDE_AtEndOfStack(dmp->dsp));
2928 
2929     /* decide about greying out left/right/center functions */
2930     NumBlocks = DDE_GetNumBlocks(dmp->dsp->pEdit);
2931     if (NumBlocks == 0) {
2932       Enable(dmwp->MainMenu.Justify);
2933     }
2934     else {
2935       Disable(dmwp->MainMenu.Justify);
2936     }
2937   }
2938 
2939  	return;
2940 }
2941 
2942 
DDV_ReDraw(DdvMainPtr dmp)2943 NLM_EXTERN void DDV_ReDraw(DdvMainPtr dmp) {
2944 /*------------------------------------------
2945 *  resize, redraw.
2946 *------------------------------------------*/
2947   /* give an illegal column so the column's not set */
2948   /* specify that this redraw is for DDE */
2949   DDV_ReDrawAtCol(dmp, -1, TRUE);
2950 }
2951 
2952 
DDV_SelectRegion(DdvMainPtr dmp,PoinT pt,RecT rc,Int4 row_start,Int4 row_stop,Int4 col_start,Int4 col_stop)2953 static void DDV_SelectRegion(DdvMainPtr dmp, PoinT pt, RecT rc,
2954                              Int4 row_start, Int4 row_stop,
2955                              Int4 col_start, Int4 col_stop) {
2956 /*----------------------------------------------------------------------------
2957 *  select from row_start to row_stop between columns col_start and col_stop.
2958 *  rows are 1-based, cols are 0-based.  why?  go figure.
2959 *
2960 *----------------------------------------------------------------------------*/
2961   Int4           row;
2962   Uint1          uWhere;
2963   ParaGPtr       pgp;
2964 
2965   if (row_start > row_stop) swap(&row_start, &row_stop);
2966   if (row_start < 1) row_start=1;
2967   if (row_stop > dmp->MSA_d.pgp_l.nBsp) row_stop=dmp->MSA_d.pgp_l.nBsp;
2968 
2969   for (row=row_start; row<=row_stop; row++) {
2970     /* send message to select all intervening columns on this row */
2971     pgp = DDV_GetPGPGivenRowAndCol(dmp, row, col_stop);
2972     uWhere = DDV_GetRegionInParaG(pgp, row);
2973     if (uWhere == PGP_REGION_SEQ) {
2974       DDV_SendBSPSelectMsg(dmp, col_start, col_stop, row, TRUE);
2975     }
2976   }
2977 
2978   /* redraw section that's been highlighted */
2979 /*
2980   InsetRect(&rc, -4, -4);
2981   InvalRect(&rc);
2982   Update();
2983 */
2984 }
2985