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