1 /* drawing.c
2 * ===========================================================================
3 *
4 * PUBLIC DOMAIN NOTICE
5 * National Center for Biotechnology Information (NCBI)
6 *
7 * This software/database is a "United States Government Work" under the
8 * terms of the United States Copyright Act. It was written as part of
9 * the author's official duties as a United States Government employee and
10 * thus cannot be copyrighted. This software/database is freely available
11 * to the public for use. The National Library of Medicine and the U.S.
12 * Government do not place any restriction on its use or reproduction.
13 * We would, however, appreciate having the NCBI and the author cited in
14 * any work or product based on this material
15 *
16 * Although all reasonable efforts have been taken to ensure the accuracy
17 * and reliability of the software and data, the NLM and the U.S.
18 * Government do not and cannot warrant the performance or results that
19 * may be obtained by using this software or data. The NLM and the U.S.
20 * Government disclaim all warranties, express or implied, including
21 * warranties of performance, merchantability or fitness for any particular
22 * purpose.
23 *
24 * ===========================================================================
25 *
26 * File Name: drawing.c
27 *
28 * Author: Jonathan Kans, Alex Smirnov, Jill Shermer, Denis Vakatov
29 *
30 * Version Creation Date: 11/13/92
31 *
32 * $Revision: 6.16 $
33 *
34 * File Description:
35 *
36 * Modifications:
37 * --------------------------------------------------------------------------
38 * $Log: drawing.c,v $
39 * Revision 6.16 2003/03/18 17:00:10 kans
40 * Nlm_AddSilentSegRect does not absorb clicks, SegRect reverted to absorb clicks, so desktop click responsiveness is maintained
41 *
42 * Revision 6.15 2003/02/19 17:36:19 rsmith
43 * SegRect (borders around a SegmenT) can not longer absorb clicks.
44 *
45 * Revision 6.14 2001/12/13 14:51:31 kans
46 * DrawSegment calls SetPrimAttribute only if it will be drawing
47 *
48 * Revision 6.13 2000/10/25 20:47:17 vakatov
49 * Rollback R6.10 (still may need add. fix for MS-Windows) [w/ V.Chetvernin]
50 *
51 * Revision 6.12 1999/10/04 17:16:30 kans
52 * include ncbidraw.h instead of vibrant.h, a couple Nlm_ prefixes
53 *
54 * Revision 6.11 1998/07/01 18:27:39 vakatov
55 * Use "const" qualifier somewhere
56 *
57 * Revision 6.10 1998/06/25 18:41:12 vakatov
58 * s_DoRoundRect(): oval_[hc] -- multiply by 2 when using Paint/FrameRoundRect
59 *
60 * Revision 6.9 1998/06/15 22:07:44 vakatov
61 * RecDrawProc(), RoRecDrawProc() -- do not add extra pixel to the
62 * horiz. and vert. dimensions; thus get it in-sync with other primitives
63 *
64 * Revision 6.8 1998/06/01 17:29:18 vakatov
65 * Extended rounded rect. options -- let it roundup only two(adjacent)
66 * corners(see "flags" arg in Nlm_AddRoundedRectangle())
67 *
68 * Revision 6.7 1998/04/27 16:03:57 vakatov
69 * Added rounded rectangles
70 * Re-implemented the ovals -- dont emulate them by polygons anymore,
71 * use the "native" drawing functions instead
72 *
73 * Revision 6.6 1997/12/16 18:38:39 kans
74 * sentinel draw callback has draw info context parameter
75 *
76 * Revision 6.5 1997/12/15 18:10:46 kans
77 * added cleanup data function to sentinel
78 *
79 * Revision 6.4 1997/11/19 17:38:09 kans
80 * added ChangeSentinelRectangle
81 *
82 * Revision 6.3 1997/11/13 21:41:31 vakatov
83 * Added "sentinel rectangle" primitive[Nlm_AddSntRectangle] which
84 * calls its callback procedure[Nlm_SntOnDrawProc] on each redraw
85 *
86 * Revision 6.2 1997/10/30 20:01:40 vakatov
87 * Added Nlm_PrimitiveBox()
88 *
89 * Revision 6.1 1997/09/16 18:56:54 vakatov
90 * RecDrawProc(): setup WIDTH_ATT for non-filled rectangle
91 *
92 * Revision 5.4 1997/07/23 19:48:54 vakatov
93 * Use Nlm_PaintStringEx function where non-display HDC can be used
94 * (on MS-Win, MoveToEx()/GetCurrentPositionEx() don't work in this case)
95 *
96 * Revision 5.3 1997/05/08 14:05:21 vakatov
97 * [WIN_MSWIN] PaintStringWin() is obsolete; replaced by MoveTo + PaintString
98 *
99 * Revision 5.2 1996/11/07 15:06:06 kans
100 * extra break needed
101 *
102 * Revision 5.1 1996/11/05 22:30:11 vakatov
103 * MakeAlignRect()/...Box(): Made the alignment be UPPER_LEFT by default
104 *
105 * Revision 4.7 1996/03/21 21:05:23 vakatov
106 * Arrow-rectangle FRAME_PRIMITIVE highlighting now merely
107 * draw a box embracing RECTANGLE or LINE primitive
108 *
109 * Revision 4.6 1996/03/15 19:49:52 vakatov
110 * Arrow-rectangle FRAME_PRIMITIVE highlighting corrected
111 *
112 * Revision 4.5 1995/11/17 20:44:48 smirnov
113 * Alex: fix DrawArc function.
114 *
115 * Revision 4.4 1995/11/09 16:35:55 kans
116 * removed static from AddArc
117 *
118 * Revision 4.3 1995/11/07 23:21:53 kans
119 * moved Nlm_DrawSegment from viewer.c to drawing.c (for GIF without Vibrant)
120 *
121 * Revision 4.1 1995/09/12 00:39:10 ostell
122 * changes for text to appear in windows metafiles
123 *
124 * ==========================================================================
125 */
126
127 #ifndef _NCBIDRAW_
128 #include <ncbidraw.h>
129 #endif
130
131 #ifndef _PICTURE_
132 #include <picture.h>
133 #endif
134
135 #ifndef _PICTUREP_
136 #include <picturep.h>
137 #endif
138
139 #ifndef _MAPPINGP_
140 #include <mappingp.h>
141 #endif
142
143 #ifndef _DRAWINGP_
144 #include <drawingp.h>
145 #endif
146
147 #ifndef _VIEWERP_
148 #include <viewerp.h>
149 #endif
150
151 /*****************************************************************************
152 *
153 * DEFINES
154 *
155 *****************************************************************************/
156 #define ARROWWIDTH2 36
157
158 /*****************************************************************************
159 *
160 * EXTERNAL VARIABLES
161 *
162 *****************************************************************************/
163 FonT smallFont = NULL;
164 FonT mediumFont = NULL;
165 FonT largeFont = NULL;
166
167 AttPData blackAttPData =
168 { {0,0,0}, SOLID_LINE, SOLID_SHADING, STD_PEN_WIDTH, COPY_MODE };
169 AttPData whiteAttPData =
170 { {255,255,255}, SOLID_LINE, SOLID_SHADING, STD_PEN_WIDTH, COPY_MODE };
171
172 /*****************************************************************************
173 *
174 * STATIC VARIABLES
175 *
176 *****************************************************************************/
177 static Int1 sin100[91] = {
178 0,2,3,5,7,9,10,12,14,16,17,19,21,22,24,26,28,29,31,33,34,36,37,39,41,42,
179 44,45,47,48,50,51,53,54,56,57,59,60,62,63,64,66,67,68,69,71,72,73,74,75,
180 77,78,79,80,81,82,83,84,85,86,87,87,88,89,90,91,91,92,93,93,94,95,95,96,
181 96,97,97,97,98,98,98,99,99,99,99,100,100,100,100,100,100 };
182
183 static Int1 atan100[101] = {
184 0,1,1,2,2,3,3,4,5,5,6,6,7,7,8,9,9,10,10,11,11,12,12,13,13,14,15,15,16,16,17,
185 17,18,18,19,19,20,20,21,21,22,22,23,23,24,24,25,25,26,26,27,27,27,28,28,29,
186 29,30,30,31,31,31,32,32,33,33,33,34,34,35,35,35,36,36,37,37,37,38,38,38,39,
187 39,39,40,40,40,41,41,41,42,42,42,43,43,43,44,44,44,44,45,45 };
188
189 static PoinT polyPoints[362];
190
191 static Uint1 thinNews [] = {
192 0x11, 0x22, 0x44, 0x88, 0x11, 0x22, 0x44, 0x88
193 };
194 static Uint1 thinNwse [] = {
195 0x88, 0x44, 0x22, 0x11, 0x88, 0x44, 0x22, 0x11
196 };
197 static Uint1 thickNews [] = {
198 0x33, 0x66, 0xCC, 0x99, 0x33, 0x66, 0xCC, 0x99
199 };
200 static Uint1 thickNwse [] = {
201 0x99, 0xCC, 0x66, 0x33, 0x99, 0xCC, 0x66, 0x33
202 };
203 static Uint1 thinHoriz [] = {
204 0xFF, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x00
205 };
206 static Uint1 thinVert [] = {
207 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11
208 };
209 static Uint1 thickHoriz [] = {
210 0xFF, 0xFF, 0x00, 0x00, 0xFF, 0xFF, 0x00, 0x00
211 };
212 static Uint1 thickVert [] = {
213 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33
214 };
215
216 #ifdef WIN_MAC
217 static Int1 userArrowSize = 10;
218 #endif
219 #ifdef WIN_MSWIN
220 static Int1 userArrowSize = 7;
221 #endif
222 #ifdef WIN_MOTIF
223 static Int1 userArrowSize = 10;
224 #endif
225
226 /*****************************************************************************
227 *
228 * SetXXXFont (void)
229 * Creates fonts of various sizes.
230 *
231 *****************************************************************************/
232
SetSmallFont(void)233 FonT SetSmallFont (void)
234
235 {
236 if (smallFont == NULL) {
237 #ifdef WIN_MAC
238 smallFont = ParseFont ("Monaco,9");
239 #endif
240 #ifdef WIN_MSWIN
241 smallFont = ParseFont ("Courier,9");
242 #endif
243 #ifdef WIN_MOTIF
244 smallFont = ParseFont ("Courier,12");
245 #endif
246 }
247 return smallFont;
248 }
249
SetMediumFont(void)250 FonT SetMediumFont (void)
251
252 {
253 if (mediumFont == NULL) {
254 #ifdef WIN_MAC
255 mediumFont = ParseFont ("Monaco,12");
256 #endif
257 #ifdef WIN_MSWIN
258 mediumFont = ParseFont ("Courier,12");
259 #endif
260 #ifdef WIN_MOTIF
261 mediumFont = ParseFont ("Courier,14");
262 #endif
263 }
264 return mediumFont;
265 }
266
SetLargeFont(void)267 FonT SetLargeFont (void)
268
269 {
270 if (largeFont == NULL) {
271 #ifdef WIN_MAC
272 largeFont = ParseFont ("Monaco,18");
273 #endif
274 #ifdef WIN_MSWIN
275 largeFont = ParseFont ("Courier,18");
276 #endif
277 #ifdef WIN_MOTIF
278 largeFont = ParseFont ("Courier,18");
279 #endif
280 }
281 return largeFont;
282 }
283
284 /*****************************************************************************
285 *
286 * DISPATCHERS FOR GENERIC PRIMITIVE OPERATIONS
287 *
288 *****************************************************************************/
289
290 /*****************************************************************************
291 *
292 * GetPrimDrawAttribute (primdrawcontect, ...)
293 * helper function for PrimDrawProc
294 *
295 *****************************************************************************/
296
Nlm_GetPrimDrawAttribute(PrimitivE prim,Uint1Ptr color,Int1Ptr plinestyle,Int1Ptr pshading,Int1Ptr ppenwidth,Int1Ptr pmode,Int1Ptr phighlight)297 void Nlm_GetPrimDrawAttribute (PrimitivE prim,
298 Uint1Ptr color, Int1Ptr plinestyle,
299 Int1Ptr pshading, Int1Ptr ppenwidth,
300 Int1Ptr pmode, Int1Ptr phighlight)
301 {
302 AttPData* atts;
303
304 if (prim != NULL ) {
305 atts = &(((GenPPtr)prim)->att);
306 if (color != NULL) {
307 color[0] = atts->color[0];
308 color[1] = atts->color[1];
309 color[2] = atts->color[2];
310 }
311 if (plinestyle != NULL) *plinestyle = atts->linestyle;
312 if (pshading != NULL) *pshading = atts->shading;
313 if (ppenwidth != NULL) *ppenwidth = atts->penwidth;
314 if (pmode != NULL) *pmode = atts->mode;
315 if (phighlight != NULL) *phighlight = ((GenPPtr)prim)->highlight;
316 }
317 }
318
319 /*****************************************************************************
320 *
321 * HELPER FUNCTIONS
322 *
323 *****************************************************************************/
Nlm_GetWorldWindow(Nlm_PrimDrawContext pdc)324 Nlm_BoxPtr Nlm_GetWorldWindow (Nlm_PrimDrawContext pdc) {
325 if ( pdc != NULL ){
326 return ( &(((DrawInfoPtr)pdc)->scale.worldWindow) );
327 }
328 return NULL;
329 }
330
Nlm_GetScaleX(PrimDrawContext pdc)331 Int4 Nlm_GetScaleX (PrimDrawContext pdc){
332 if ( pdc != NULL ){
333 return ( ((DrawInfoPtr)pdc)->scale.scaleX );
334 }
335 return 0;
336 }
337
Nlm_GetScaleY(Nlm_PrimDrawContext pdc)338 Int4 Nlm_GetScaleY (Nlm_PrimDrawContext pdc){
339 if ( pdc != NULL ){
340 return ( ((DrawInfoPtr)pdc)->scale.scaleY );
341 }
342 return 0;
343 }
344
Nlm_GetOffsetX(PrimDrawContext pdc)345 Int4 Nlm_GetOffsetX (PrimDrawContext pdc){
346 if ( pdc != NULL ){
347 return ( ((DrawInfoPtr)pdc)->scale.offsetX );
348 }
349 return 0;
350 }
351
Nlm_GetOffsetY(PrimDrawContext pdc)352 Int4 Nlm_GetOffsetY (PrimDrawContext pdc){
353 if ( pdc != NULL ){
354 return ( ((DrawInfoPtr)pdc)->scale.offsetY );
355 }
356 return 0;
357 }
358
Nlm_isPrimInWindow(PrimDrawContext pdc)359 Boolean Nlm_isPrimInWindow (PrimDrawContext pdc){
360 if ( pdc != NULL ){
361 return ( ((DrawInfoPtr)pdc)->checked );
362 }
363 return FALSE;
364 }
365
Nlm_GetPrimHligh(PrimDrawContext pdc)366 Int1 Nlm_GetPrimHligh (PrimDrawContext pdc){
367 if ( pdc != NULL ){
368 return ( ((DrawInfoPtr)pdc)->highlight );
369 }
370 return PLAIN_SEGMENT;
371 }
372
Nlm_GetHitWindow(PrimHitContext phc)373 BoxPtr Nlm_GetHitWindow (PrimHitContext phc){
374 if ( phc != NULL ){
375 return ( &(((ScalePtr)phc)->worldWindow) );
376 }
377 return NULL;
378 }
379
Nlm_SetPrimAttribute(PrimDrawContext pdc,Nlm_Uint1 flags)380 void Nlm_SetPrimAttribute (PrimDrawContext pdc, Nlm_Uint1 flags ){
381 AttPPtr atts;
382
383 if (pdc != NULL) {
384 atts = ((DrawInfoPtr)pdc)->primattrib;
385 if ( flags & COLOR_ATT ) {
386 SelectColor (atts->color [0], atts->color [1], atts->color [2]);
387 }
388 if ( flags & WIDTH_ATT ){
389 WidePen (atts->penwidth);
390 }
391 if ( flags & STYLE_ATT ) {
392 switch (atts->linestyle) {
393 case SOLID_LINE :
394 Solid ();
395 break;
396 case DOTTED_LINE :
397 Dotted ();
398 break;
399 case DASHED_LINE :
400 Dashed ();
401 }
402 }
403 if ( flags & SHADING_ATT ) {
404 switch (atts->shading) {
405 case SOLID_SHADING :
406 Solid ();
407 break;
408 case DARK_SHADING :
409 Dark ();
410 break;
411 case MEDIUM_SHADING :
412 Medium ();
413 break;
414 case LIGHT_SHADING :
415 Light ();
416 break;
417 case EMPTY_SHADING :
418 Empty ();
419 break;
420 case THIN_HORIZ_SHADING :
421 SetPenPattern (thinHoriz);
422 break;
423 case THIN_VERT_SHADING :
424 SetPenPattern (thinVert);
425 break;
426 case THICK_HORIZ_SHADING :
427 SetPenPattern (thickHoriz);
428 break;
429 case THICK_VERT_SHADING :
430 SetPenPattern (thickVert);
431 break;
432 case THIN_NESW_SHADING :
433 SetPenPattern (thinNews);
434 break;
435 case THIN_NWSE_SHADING :
436 SetPenPattern (thinNwse);
437 break;
438 case THICK_NESW_SHADING :
439 SetPenPattern (thickNews);
440 break;
441 case THICK_NWSE_SHADING :
442 SetPenPattern (thickNwse);
443 }
444 }
445 if ( flags & MODE_ATT ) {
446 switch (atts->mode) {
447 case COPY_MODE :
448 CopyMode ();
449 break;
450 case MERGE_MODE :
451 MergeMode ();
452 break;
453 case INVERT_MODE :
454 InvertMode ();
455 break;
456 case ERASE_MODE :
457 EraseMode ();
458 }
459 }
460 }
461 }
462
Nlm_RestorePrimAttribute(PrimDrawContext pdc)463 void Nlm_RestorePrimAttribute (PrimDrawContext pdc){
464 Nlm_SetPrimAttribute (pdc, (Uint1)0xFF);
465 }
466
467 /*****************************************************************************
468 *
469 * OPERATIONS ON PRIMITIVES
470 *
471 *****************************************************************************/
472 /*****************************************************************************
473 *
474 * Set Arrow Size
475 *
476 *****************************************************************************/
Nlm_SetDefArrowSize(Int1 arrowSize)477 void Nlm_SetDefArrowSize ( Int1 arrowSize )
478 {
479 if ( arrowSize < 4 ) arrowSize = 4;
480 if ( arrowSize > 16 ) arrowSize = 16;
481 userArrowSize = arrowSize;
482 }
483
MakeAlignRect(Int2 x,Int2 y,Int2 width,Int2 height,Int2 offset,Int2 align,RectPtr rPtr)484 static void MakeAlignRect ( Int2 x, Int2 y, Int2 width, Int2 height,
485 Int2 offset, Int2 align, RectPtr rPtr )
486 {
487 RecT r;
488
489 switch (align) {
490 case UPPER_CENTER :
491 r.left = x - (width>>1); r.top = y - height - offset;
492 break;
493 case UPPER_RIGHT :
494 r.left = x + offset; r.top = y - height - offset;
495 break;
496 case MIDDLE_LEFT :
497 r.left = x - width - offset; r.top = y - (height>>1);
498 break;
499 case MIDDLE_CENTER :
500 r.left = x - (width>>1); r.top = y - (height>>1);
501 break;
502 case MIDDLE_RIGHT :
503 r.left = x + offset; r.top = y - (height>>1);
504 break;
505 case LOWER_LEFT :
506 r.left = x - width - offset; r.top = y + offset;
507 break;
508 case LOWER_CENTER :
509 r.left = x - (width>>1); r.top = y + offset;
510 break;
511 case LOWER_RIGHT :
512 r.left = x + offset; r.top = y + offset;
513 break;
514 case UPPER_LEFT :
515 default:
516 r.left = x - width - offset; r.top = y - height - offset;
517 break;
518 }
519 r.right = r.left + width; r.bottom = r.top + height;
520 *rPtr = r;
521 }
522
MakeAlignBox(Int4 x,Int4 y,Int4 width,Int4 height,Int4 offsetX,Int4 offsetY,Int2 align,BoxPtr boxPtr)523 static void MakeAlignBox ( Int4 x, Int4 y, Int4 width, Int4 height,
524 Int4 offsetX, Int4 offsetY, Int2 align,
525 BoxPtr boxPtr )
526 {
527 BoxInfo box;
528
529 switch (align) {
530 case UPPER_CENTER :
531 box.left = x - (width>>1); box.top = y + height + offsetY;
532 break;
533 case UPPER_RIGHT :
534 box.left = x + offsetX; box.top = y + height + offsetY;
535 break;
536 case MIDDLE_LEFT :
537 box.left = x - width - offsetX; box.top = y + (height>>1);
538 break;
539 case MIDDLE_CENTER :
540 box.left = x - (width>>1); box.top = y + (height>>1);
541 break;
542 case MIDDLE_RIGHT :
543 box.left = x + offsetX; box.top = y + (height>>1);
544 break;
545 case LOWER_LEFT :
546 box.left = x - width - offsetX; box.top = y - offsetY;
547 break;
548 case LOWER_CENTER :
549 box.left = x - (width>>1); box.top = y - offsetY;
550 break;
551 case LOWER_RIGHT :
552 box.left = x + offsetX; box.top = y - offsetY;
553 break;
554 case UPPER_LEFT :
555 default:
556 box.left = x - width - offsetX; box.top = y + height + offsetY;
557 break;
558 }
559 box.right = box.left + width; box.bottom = box.top - height;
560 *boxPtr = box;
561 }
562
563 /*****************************************************************************
564 *
565 * DrawPrimitive (item, scale)
566 * Draws a primitive
567 *
568 *****************************************************************************/
569
Nlm_DrawPrimitive(BasePPtr item,DrawInfoPtr drawinfo)570 void Nlm_DrawPrimitive (BasePPtr item, DrawInfoPtr drawinfo)
571 {
572 PrimDefPtr pdp;
573
574 if (item != NULL && drawinfo != NULL) {
575 switch (item->code) {
576 case GENERIC :
577 pdp = ((GenPPtr)item)->pdp;
578 if ( pdp != NULL && pdp->draw != NULL) {
579 pdp->draw ( &(((GenPPtr)item)->data), (PrimDrawContext)drawinfo);
580 }
581 break;
582 default :
583 Message (MSG_ERROR, "DrawPrimitive item unknown");
584 break;
585 }
586 }
587 }
588
589 /*****************************************************************************
590 *
591 * PrimitiveIsCloseToPoint (item, &id)
592 *
593 *****************************************************************************/
594
Nlm_PrimitiveIsCloseToPoint(BasePPtr item,ScalePtr scale)595 Boolean Nlm_PrimitiveIsCloseToPoint (BasePPtr item, ScalePtr scale )
596 {
597 PrimDefPtr pdp;
598
599 if (item != NULL && scale != NULL) {
600 switch (item->code) {
601 case GENERIC :
602 pdp = ((GenPPtr)item)->pdp;
603 if ( pdp != NULL && pdp->hittest != NULL) {
604 return pdp->hittest ( &(((GenPPtr)item)->data),
605 (PrimHitContext)scale);
606 }
607 break;
608 default :
609 Message (MSG_ERROR, "PrimitiveIsCloseToPoint item unknown");
610 break;
611 }
612 }
613 return FALSE;
614 }
615
616 /*****************************************************************************
617 *
618 * TryHighlightPrimitive (item, highlight)
619 *
620 *****************************************************************************/
621
Nlm_TryHighlightPrimitive(BasePPtr item,Int1 highlight)622 Boolean Nlm_TryHighlightPrimitive (BasePPtr item, Int1 highlight)
623 {
624 if (item != NULL) {
625 switch (item->code) {
626 case GENERIC :
627 ((GenPPtr)item)->highlight = highlight;
628 return TRUE;
629 default:
630 Message (MSG_ERROR, "TryHighlightPrimitive item unknown");
631 break;
632 }
633 }
634 return FALSE;
635 }
636
637 /*****************************************************************************
638 *
639 * TryOffsetPrimitive (item, deltaX, deltaY)
640 *
641 *****************************************************************************/
642
Nlm_TryOffsetPrimitive(BasePPtr item,Int4 deltaX,Int4 deltaY)643 Boolean Nlm_TryOffsetPrimitive (BasePPtr item, Int4 deltaX, Int4 deltaY)
644 {
645 PrimDefPtr pdp;
646
647 if (item != NULL) {
648 switch (item->code) {
649 case GENERIC :
650 pdp = ((GenPPtr)item)->pdp;
651 if ( pdp != NULL && pdp->offset != NULL) {
652 return pdp->offset ( &(((GenPPtr)item)->data), deltaX, deltaY);
653 }
654 break;
655 default:
656 Message (MSG_ERROR, "TryOffsetPrimitive item unknown");
657 break;
658 }
659 }
660 return FALSE;
661 }
662
663 /*****************************************************************************
664 *
665 * TryGetPrimitiveLimits (item, scaleX, scaleY, pLimits)
666 *
667 *****************************************************************************/
Nlm_TryGetPrimitiveLimits(Nlm_BasePPtr item,Nlm_Int4 scaleX,Nlm_Int4 scaleY,Nlm_BoxPtr pLimits)668 Nlm_Boolean Nlm_TryGetPrimitiveLimits (Nlm_BasePPtr item, Nlm_Int4 scaleX,
669 Nlm_Int4 scaleY, Nlm_BoxPtr pLimits)
670 {
671 PrimDefPtr pdp;
672
673 if (item != NULL) {
674 switch (item->code) {
675 case GENERIC :
676 pdp = ((GenPPtr)item)->pdp;
677 if ( pdp != NULL && pdp->getlimits != NULL) {
678 return pdp->getlimits ( &(((GenPPtr)item)->data), scaleX, scaleY,
679 pLimits );
680 }
681 break;
682 default:
683 Message (MSG_ERROR, "TryOffsetPrimitive item unknown");
684 break;
685 }
686 }
687 return FALSE;
688 }
689
Nlm_PrimitiveBox(Nlm_PrimitivE prim,Nlm_Int4 scaleX,Nlm_Int4 scaleY,Nlm_BoxPtr pBox)690 extern Nlm_Boolean Nlm_PrimitiveBox(Nlm_PrimitivE prim,
691 Nlm_Int4 scaleX, Nlm_Int4 scaleY,
692 Nlm_BoxPtr pBox) {
693 return Nlm_TryGetPrimitiveLimits((Nlm_BasePPtr)prim, scaleX, scaleY, pBox);
694 }
695
696
697 /*****************************************************************************
698 *
699 * CleanupPrimitive (item)
700 * Deleted all data, owned by primitive
701 *
702 *****************************************************************************/
703
Nlm_CleanupPrimitive(BasePPtr item)704 void Nlm_CleanupPrimitive (BasePPtr item)
705 {
706 PrimDefPtr pdp;
707
708 if (item != NULL) {
709 switch (item->code) {
710 case GENERIC :
711 pdp = ((GenPPtr)item)->pdp;
712 if ( pdp != NULL && pdp->cleanup != NULL) {
713 pdp->cleanup ( &(((GenPPtr)item)->data) );
714 }
715 break;
716 default:
717 Message (MSG_ERROR, "CleanupPrimitive item unknown");
718 break;
719 }
720 }
721 }
722
723 /*****************************************************************************
724 *
725 * PRIMITIVES
726 *
727 *****************************************************************************/
728
729 /*****************************************************************************
730 *
731 * INVISIBLE FRAME
732 *
733 *****************************************************************************/
734
735 typedef struct frampdata {
736 BoxInfo box;
737 } FramPData, PNTR FramPDataPtr;
738
FramHitTestProc(FramPDataPtr pdata,PrimHitContext phc)739 static Boolean FramHitTestProc ( FramPDataPtr pdata, PrimHitContext phc)
740 {
741 register ScalePtr dInfoPtr;
742
743 dInfoPtr = (ScalePtr)phc;
744 if ( (pdata->box.left < dInfoPtr->worldWindow.right) &&
745 (pdata->box.right > dInfoPtr->worldWindow.left) &&
746 (pdata->box.top > dInfoPtr->worldWindow.bottom) &&
747 (pdata->box.bottom < dInfoPtr->worldWindow.top) ) return TRUE;
748 return FALSE;
749 }
750
FramOffsetProc(FramPDataPtr pdata,Int4 deltaX,Int4 deltaY)751 static Boolean FramOffsetProc ( FramPDataPtr pdata, Int4 deltaX,
752 Int4 deltaY )
753 {
754 pdata->box.left += deltaX;
755 pdata->box.right += deltaX;
756 pdata->box.top += deltaY;
757 pdata->box.bottom += deltaY;
758 return TRUE;
759 }
760
FramGetLimitsProc(FramPDataPtr pdata,Int4 scaleX,Int4 scaleY,BoxPtr pLimits)761 static Boolean FramGetLimitsProc ( FramPDataPtr pdata, Int4 scaleX,
762 Int4 scaleY, BoxPtr pLimits )
763 {
764 *pLimits = pdata->box;
765 return TRUE;
766 }
767
768 static PrimDef framPrimDef = {
769 (PrimDrawProc) NULL,
770 (PrimHitTestProc) FramHitTestProc,
771 (PrimOffsetProc) FramOffsetProc,
772 (PrimCleanupProc) NULL,
773 (PrimGetLimitsProc) FramGetLimitsProc
774 };
775
776 /*****************************************************************************
777 *
778 * AddInvFrame (parent, left, top, right, bottom, primID)
779 *
780 *****************************************************************************/
781
AddInvFrame(SegmenT parent,Int4 left,Int4 top,Int4 right,Int4 bottom,Uint2 primID)782 PrimitivE AddInvFrame (SegmenT parent, Int4 left, Int4 top, Int4 right,
783 Int4 bottom, Uint2 primID)
784 {
785 FramPData data;
786 Int4 swap;
787
788 if (left > right) {
789 swap = left;
790 left = right;
791 right = swap;
792 }
793 if (bottom > top) {
794 swap = bottom;
795 bottom = top;
796 top = swap;
797 }
798 data.box.left = left;
799 data.box.top = top;
800 data.box.right = right;
801 data.box.bottom = bottom;
802 return AddPrimitive (&framPrimDef, parent, primID, (VoidPtr)&data,
803 sizeof(FramPData));
804 }
805
806
807 /*****************************************************************************
808 *
809 * RECTANGLE
810 *
811 *****************************************************************************/
812
813 typedef struct recpdata {
814 BoxInfo box;
815 Int2 arrow;
816 Int1 arrowSize;
817 Boolean fill;
818 } RecPData, PNTR RecPDataPtr;
819
820
RecDrawProc(RecPDataPtr pdata,PrimDrawContext pdc)821 static void RecDrawProc (RecPDataPtr pdata, PrimDrawContext pdc)
822 {
823 register DrawInfoPtr dInfoPtr = (DrawInfoPtr)pdc;
824 BoxInfo tmpBox;
825 RecT r;
826 Int4 curScale;
827 PoinT pts [3];
828 Int1 arrowSize;
829 Boolean vis = TRUE;
830 RecT rect;
831
832 tmpBox = pdata->box;
833 if ( (tmpBox.left > dInfoPtr->scale.worldWindow.right ) ||
834 (tmpBox.right < dInfoPtr->scale.worldWindow.left ) ||
835 (tmpBox.top < dInfoPtr->scale.worldWindow.bottom) ||
836 (tmpBox.bottom > dInfoPtr->scale.worldWindow.top ) )
837 return;
838
839 if ( dInfoPtr->checked == FALSE ) {
840 if ( tmpBox.left < dInfoPtr->scale.worldWindow16.left )
841 tmpBox.left = dInfoPtr->scale.worldWindow16.left;
842 if ( tmpBox.right > dInfoPtr->scale.worldWindow16.right )
843 tmpBox.right = dInfoPtr->scale.worldWindow16.right;
844 if ( tmpBox.top > dInfoPtr->scale.worldWindow16.top )
845 tmpBox.top = dInfoPtr->scale.worldWindow16.top;
846 if ( tmpBox.bottom < dInfoPtr->scale.worldWindow16.bottom )
847 tmpBox.bottom = dInfoPtr->scale.worldWindow16.bottom;
848 }
849
850 arrowSize = pdata->arrowSize;
851 curScale = dInfoPtr->scale.scaleX;
852 r.left = (Int2)((dInfoPtr->scale.offsetX + tmpBox.left ) / curScale);
853 r.right = (Int2)((dInfoPtr->scale.offsetX + tmpBox.right) / curScale);
854 curScale = dInfoPtr->scale.scaleY;
855 r.top = (Int2)((dInfoPtr->scale.offsetY - tmpBox.top ) / curScale);
856 r.bottom = (Int2)((dInfoPtr->scale.offsetY - tmpBox.bottom) / curScale);
857
858 /* calculate vertexes */
859 rect = r;
860
861 switch ( pdata->arrow )
862 {
863 Int2 oldPoint;
864
865 case LEFT_ARROW :
866 oldPoint = r.left;
867 if (r.right - r.left > (Int2)arrowSize) r.left += (Int2)arrowSize;
868 else r.left += (Int2)(arrowSize>>1);
869 pts[0].x = r.left; pts[0].y = r.bottom + (Int2)2;
870 pts[1].x = oldPoint; pts[1].y = (r.bottom + r.top)>>1;
871 pts[2].x = r.left; pts[2].y = r.top - (Int2)2;
872 if (r.right < r.left)
873 {
874 vis = FALSE;
875 rect.left = pts[1].x;
876 rect.right = pts[0].x;
877 }
878 break;
879
880 case RIGHT_ARROW :
881 oldPoint = r.right;
882 if (r.right - r.left >= arrowSize) r.right -= (Int2)arrowSize;
883 else r.right -= (Int2)(arrowSize>>1);
884 if ( r.right < r.left ) vis = FALSE;
885 pts[0].x = r.right; pts[0].y = r.bottom + (Int2)2;
886 pts[1].x = oldPoint; pts[1].y = (r.bottom + r.top)>>1;
887 pts[2].x = r.right; pts[2].y = r.top - (Int2)2;
888 if (r.right < r.left)
889 {
890 vis = FALSE;
891 rect.left = pts[0].x;
892 rect.right = pts[1].x;
893 }
894 break;
895
896 case UP_ARROW :
897 oldPoint = r.top;
898 if (r.bottom - r.top >= (Int2)arrowSize) r.top += (Int2)arrowSize;
899 else r.top += (Int2)(arrowSize>>1);
900 if ( r.bottom < r.top ) vis = FALSE;
901 pts[0].x = r.right + (Int2)2; pts[0].y = r.top;
902 pts[1].x = (r.right+r.left)>>1; pts[1].y = oldPoint;
903 pts[2].x = r.left - (Int2)2; pts[2].y = r.top;
904 if (r.right < r.left)
905 {
906 vis = FALSE;
907 rect.top = pts[1].y;
908 rect.bottom = pts[0].y;
909 }
910 break;
911
912 case DOWN_ARROW :
913 oldPoint = r.bottom;
914 if (r.bottom - r.top >= (Int2)arrowSize) r.bottom -= (Int2)arrowSize;
915 else r.bottom -= (Int2)(arrowSize>>1);
916 if ( r.bottom < r.top ) vis = FALSE;
917 pts[0].x = r.right + (Int2)2; pts[0].y = r.bottom;
918 pts[1].x = (r.right+r.left)>>1; pts[1].y = oldPoint;
919 pts[2].x = r.left - (Int2)2; pts[2].y = r.bottom;
920 if (r.right < r.left)
921 {
922 vis = FALSE;
923 rect.top = pts[0].y;
924 rect.bottom = pts[1].y;
925 }
926 break;
927 }
928
929 SetPrimAttribute (pdc, COLOR_ATT|SHADING_ATT|MODE_ATT);
930 if ( !pdata->fill )
931 SetPrimAttribute (pdc, WIDTH_ATT);
932
933 /* draw arrow */
934 if (pdata->arrow != NO_ARROW)
935 {
936 if (pdata->fill)
937 PaintPoly (3, pts);
938 else
939 FramePoly (3, pts);
940
941 if (dInfoPtr->highlight == FILL_PRIMITIVE)
942 PaintPoly(3, pts);
943 }
944
945 /* draw rectangle */
946 if ( vis ) {
947 if ( pdata->fill )
948 PaintRect( &r );
949 else
950 FrameRect( &r );
951 }
952
953 /* highlighting */
954 switch ( dInfoPtr->highlight )
955 {
956 case PLAIN_PRIMITIVE:
957 break;
958 case FRAME_PRIMITIVE:
959 case OUTLINE_PRIMITIVE:
960 Black();
961 WidePen( 1 );
962 InsetRect(&rect, -3, -3);
963 FrameRect( &rect );
964 InsetRect(&rect, +3, +3);
965 break;
966 case FILL_PRIMITIVE:
967 InsetRect(&rect, -2, -2);
968 PaintRect( &rect );
969 InsetRect(&rect, +2, +2);
970 break;
971 }
972 }
973
974
RecHitTestProc(RecPDataPtr pdata,PrimHitContext phc)975 static Boolean RecHitTestProc ( RecPDataPtr pdata, PrimHitContext phc)
976 {
977 register ScalePtr dInfoPtr;
978
979 dInfoPtr = (ScalePtr)phc;
980 if ( (pdata->box.left < dInfoPtr->worldWindow.right) &&
981 (pdata->box.right > dInfoPtr->worldWindow.left) &&
982 (pdata->box.top > dInfoPtr->worldWindow.bottom) &&
983 (pdata->box.bottom < dInfoPtr->worldWindow.top) ) return TRUE;
984 return FALSE;
985 }
986
RecOffsetProc(RecPDataPtr pdata,Int4 deltaX,Int4 deltaY)987 static Boolean RecOffsetProc ( RecPDataPtr pdata, Int4 deltaX,
988 Int4 deltaY )
989 {
990 pdata->box.left += deltaX;
991 pdata->box.right += deltaX;
992 pdata->box.top += deltaY;
993 pdata->box.bottom += deltaY;
994 return TRUE;
995 }
996
RecGetLimitsProc(RecPDataPtr pdata,Int4 scaleX,Int4 scaleY,BoxPtr pLimits)997 static Boolean RecGetLimitsProc ( RecPDataPtr pdata, Int4 scaleX,
998 Int4 scaleY, BoxPtr pLimits )
999 {
1000 Int4 arrowSize;
1001
1002 *pLimits = pdata->box;
1003 switch ( pdata->arrow ){
1004 case LEFT_ARROW :
1005 arrowSize = pdata->arrowSize*scaleX/2;
1006 if ( pLimits->right - pLimits->left < arrowSize )
1007 pLimits->right = pLimits->left + arrowSize;
1008 break;
1009 case RIGHT_ARROW :
1010 arrowSize = pdata->arrowSize*scaleX/2;
1011 if ( pLimits->right - pLimits->left < arrowSize )
1012 pLimits->left = pLimits->right - arrowSize;
1013 break;
1014 case UP_ARROW :
1015 arrowSize = pdata->arrowSize*scaleY/2;
1016 if ( pLimits->top - pLimits->bottom < arrowSize )
1017 pLimits->bottom = pLimits->top - arrowSize;
1018 break;
1019 case DOWN_ARROW :
1020 arrowSize = pdata->arrowSize*scaleY/2;
1021 if ( pLimits->top - pLimits->bottom < arrowSize )
1022 pLimits->top = pLimits->bottom + arrowSize;
1023 }
1024 OutsetBox ( pLimits, scaleX<<2, scaleY<<2 );
1025 return TRUE;
1026 }
1027
1028 static PrimDef recPrimDef = {
1029 (PrimDrawProc) RecDrawProc,
1030 (PrimHitTestProc) RecHitTestProc,
1031 (PrimOffsetProc) RecOffsetProc,
1032 (PrimCleanupProc) NULL,
1033 (PrimGetLimitsProc) RecGetLimitsProc
1034 };
1035
1036 /*****************************************************************************
1037 *
1038 * AddRectangle (parent, left, top, right, bottom, arrow, fill, primID)
1039 *
1040 *****************************************************************************/
1041
AddRectangle(SegmenT parent,Int4 left,Int4 top,Int4 right,Int4 bottom,Int2 arrow,Boolean fill,Uint2 primID)1042 PrimitivE AddRectangle (SegmenT parent, Int4 left, Int4 top, Int4 right,
1043 Int4 bottom, Int2 arrow, Boolean fill, Uint2 primID)
1044 {
1045 RecPData data;
1046 Int4 swap;
1047
1048 if (left > right) {
1049 swap = left;
1050 left = right;
1051 right = swap;
1052 }
1053 if (bottom > top) {
1054 swap = bottom;
1055 bottom = top;
1056 top = swap;
1057 }
1058 data.box.left = left;
1059 data.box.top = top;
1060 data.box.right = right;
1061 data.box.bottom = bottom;
1062 data.fill = fill;
1063 data.arrow = arrow;
1064 data.arrowSize = userArrowSize;
1065 return AddPrimitive (&recPrimDef, parent, primID, (VoidPtr)&data,
1066 sizeof(RecPData));
1067 }
1068
1069
1070 /*****************************************************************************
1071 *
1072 * ROUNDED RECTANGLE
1073 *
1074 *****************************************************************************/
1075
1076 typedef struct {
1077 BoxInfo box;
1078 Int4 oval_w;
1079 Int4 oval_h;
1080 Boolean fill;
1081 Uint4 flags;
1082 } RoRecPData, PNTR RoRecPDataPtr;
1083
1084
s_DoRoundRect(RectPtr r,Int2 oval_w,Int2 oval_h,Boolean fill,Uint4 flags)1085 static void s_DoRoundRect(RectPtr r,
1086 Int2 oval_w, Int2 oval_h, Boolean fill, Uint4 flags)
1087 {
1088 Int2 W, dW, H, dH;
1089 RecT r1, r2, qr1, qr2;
1090 EQuadrant q1, q2;
1091 PoinT p1, p2;
1092
1093 if (!flags ||
1094 (flags & ROREC_TOP && flags & ROREC_BOTTOM) ||
1095 (flags & ROREC_LEFT && flags & ROREC_RIGHT)) {
1096 if ( fill )
1097 PaintRoundRect(r, oval_w, oval_h);
1098 else
1099 FrameRoundRect(r, oval_w, oval_h);
1100 return;
1101 }
1102
1103 W = r->right - r->left;
1104 H = r->bottom - r->top;
1105 LoadRect(&r1, 0, 0, 0, 0);
1106 LoadRect(&r2, 0, 0, 0, 0);
1107
1108 if (flags & ROREC_TOP || flags & ROREC_BOTTOM) {
1109 if (2 * oval_w > W)
1110 oval_w = W / 2;
1111 dW = W - 2 * oval_w;
1112
1113 if (oval_h > H)
1114 oval_h = H;
1115 dH = H - oval_h;
1116 }
1117 else { /* ROREC_LEFT || ROREC_RIGHT */
1118 if (2 * oval_h > H)
1119 oval_h = H / 2;
1120 dH = H - 2 * oval_h;
1121
1122 if (oval_w > W)
1123 oval_w = W;
1124 dW = W - oval_w;
1125 }
1126
1127 if (oval_w < 2 || oval_h < 2) {
1128 if ( fill )
1129 PaintRect(r);
1130 else
1131 FrameRect(r);
1132 return;
1133 }
1134
1135
1136 if (flags & ROREC_TOP || flags & ROREC_BOTTOM) {
1137 if (flags & ROREC_TOP) {
1138 if ( dW )
1139 LoadRect(&r1, (Int2)(r->left + oval_w), r->top,
1140 (Int2)(r->right - oval_w), (Int2)(r->top + oval_h));
1141 if ( dH )
1142 LoadRect(&r2, r->left, (Int2)(r->top + oval_h),
1143 r->right, r->bottom);
1144 q1 = eQ_LeftTop;
1145 LoadRect(&qr1, r->left, r->top,
1146 (Int2)(r->left + oval_w), (Int2)(r->top + oval_h));
1147 q2 = eQ_RightTop;
1148 LoadRect(&qr2, (Int2)(r->right - oval_w), r->top,
1149 r->right, (Int2)(r->top + oval_h));
1150
1151 if ( !fill ) {
1152 p1.y = p2.y = r->bottom; p1.x = r->left; p2.x = r->right;
1153 DrawLine(p1, p2);
1154 if ( dW ) {
1155 p1.y = p2.y = r1.top; p1.x = r1.left; p2.x = r1.right;
1156 DrawLine(p1, p2);
1157 }
1158 }
1159 }
1160 else { /* ROREC_BOTTOM */
1161 if ( dW )
1162 LoadRect(&r1, (Int2)(r->left + oval_w), (Int2)(r->bottom - oval_h),
1163 (Int2)(r->right - oval_w), r->bottom);
1164 if ( dH )
1165 LoadRect(&r2, r->left, r->top,
1166 r->right, (Int2)(r->bottom - oval_h));
1167 q1 = eQ_LeftBottom;
1168 LoadRect(&qr1, r->left, r->bottom,
1169 (Int2)(r->left + oval_w), (Int2)(r->bottom - oval_h));
1170 q2 = eQ_RightBottom;
1171 LoadRect(&qr2, (Int2)(r->right - oval_w), r->bottom,
1172 r->right, (Int2)(r->bottom - oval_h));
1173
1174 if ( !fill ) {
1175 p1.y = p2.y = r->top; p1.x = r->left; p2.x = r->right;
1176 DrawLine(p1, p2);
1177 if ( dW ) {
1178 p1.y = p2.y = r->bottom; p1.x = r1.left; p2.x = r1.right;
1179 DrawLine(p1, p2);
1180 }
1181 }
1182 }
1183
1184 if (!fill && dH) {
1185 p1.y = r2.top; p2.y = r2.bottom;
1186
1187 p1.x = p2.x = r->left;
1188 DrawLine(p1, p2);
1189 p1.x = p2.x = r->right;
1190 DrawLine(p1, p2);
1191 }
1192 }
1193
1194 else { /* ROREC_LEFT | ROREC_RIGHT */
1195 if (flags & ROREC_LEFT) {
1196 if ( dH )
1197 LoadRect(&r1, r->left, (Int2)(r->top + oval_h),
1198 (Int2)(r->left + oval_w), (Int2)(r->bottom - oval_h));
1199 if ( dW )
1200 LoadRect(&r2, (Int2)(r->left + oval_w), r->top,
1201 r->right, r->bottom);
1202 q1 = eQ_LeftTop;
1203 LoadRect(&qr1, r->left, r->top,
1204 (Int2)(r->left + oval_w), (Int2)(r->top + oval_h));
1205 q2 = eQ_LeftBottom;
1206 LoadRect(&qr2, r->left, r->bottom,
1207 (Int2)(r->left + oval_w), (Int2)(r->bottom - oval_h));
1208
1209 if ( !fill ) {
1210 p1.x = p2.x = r->right; p1.y = r->top; p2.y = r->bottom;
1211 DrawLine(p1, p2);
1212 if ( dW ) {
1213 p1.x = p2.x = r->left; p1.y = r1.top; p2.y = r1.bottom;
1214 DrawLine(p1, p2);
1215 }
1216 }
1217 }
1218 else { /* ROREC_RIGHT */
1219 if ( dH )
1220 LoadRect(&r1, (Int2)(r->right - oval_w), (Int2)(r->top + oval_h),
1221 r->right, (Int2)(r->bottom - oval_h));
1222 if ( dW )
1223 LoadRect(&r2, r->left, r->top,
1224 (Int2)(r->right - oval_w), r->bottom);
1225 q1 = eQ_RightTop;
1226 LoadRect(&qr1, (Int2)(r->right - oval_w), r->top,
1227 r->right, (Int2)(r->top + oval_h));
1228 q2 = eQ_RightBottom;
1229 LoadRect(&qr2, (Int2)(r->right - oval_w), r->bottom,
1230 r->right, (Int2)(r->bottom - oval_h));
1231
1232 if ( !fill ) {
1233 p1.x = p2.x = r->left; p1.y = r->top; p2.y = r->bottom;
1234 DrawLine(p1, p2);
1235 if ( dW ) {
1236 p1.x = p2.x = r->right; p1.y = r1.top; p2.y = r1.bottom;
1237 DrawLine(p1, p2);
1238 }
1239 }
1240 }
1241
1242 if (!fill && dH) {
1243 p1.x = r2.left; p2.x = r2.right;
1244
1245 p1.y = p2.y = r->top;
1246 DrawLine(p1, p2);
1247 p1.y = p2.y = r->bottom;
1248 DrawLine(p1, p2);
1249 }
1250 }
1251
1252 if ( fill ) {
1253 if ( !EmptyRect(&r1) )
1254 PaintRect(&r1);
1255 if ( !EmptyRect(&r2) )
1256 PaintRect(&r2);
1257 PaintQuadrant(&qr1, q1);
1258 PaintQuadrant(&qr2, q2);
1259 } else {
1260 FrameQuadrant(&qr1, q1);
1261 FrameQuadrant(&qr2, q2);
1262 }
1263 }
1264
1265
RoRecDrawProc(RoRecPDataPtr pdata,PrimDrawContext pdc)1266 static void RoRecDrawProc(RoRecPDataPtr pdata, PrimDrawContext pdc)
1267 {
1268 register DrawInfoPtr dInfoPtr = (DrawInfoPtr)pdc;
1269 BoxInfo tmpBox;
1270 RecT r;
1271 Int4 curScale;
1272 Int2 oval_w, oval_h;
1273
1274 /* check limits */
1275 tmpBox = pdata->box;
1276 if ( (tmpBox.left > dInfoPtr->scale.worldWindow.right ) ||
1277 (tmpBox.right < dInfoPtr->scale.worldWindow.left ) ||
1278 (tmpBox.top < dInfoPtr->scale.worldWindow.bottom) ||
1279 (tmpBox.bottom > dInfoPtr->scale.worldWindow.top ) )
1280 return;
1281
1282 if ( dInfoPtr->checked == FALSE ) {
1283 if ( tmpBox.left < dInfoPtr->scale.worldWindow16.left )
1284 tmpBox.left = dInfoPtr->scale.worldWindow16.left;
1285 if ( tmpBox.right > dInfoPtr->scale.worldWindow16.right )
1286 tmpBox.right = dInfoPtr->scale.worldWindow16.right;
1287 if ( tmpBox.top > dInfoPtr->scale.worldWindow16.top )
1288 tmpBox.top = dInfoPtr->scale.worldWindow16.top;
1289 if ( tmpBox.bottom < dInfoPtr->scale.worldWindow16.bottom )
1290 tmpBox.bottom = dInfoPtr->scale.worldWindow16.bottom;
1291 }
1292
1293 /* scale */
1294 curScale = dInfoPtr->scale.scaleX;
1295 r.left = (Int2)((dInfoPtr->scale.offsetX + tmpBox.left ) / curScale);
1296 r.right = (Int2)((dInfoPtr->scale.offsetX + tmpBox.right) / curScale);
1297 oval_w = (Int2)(pdata->oval_w / curScale);
1298
1299 curScale = dInfoPtr->scale.scaleY;
1300 r.top = (Int2)((dInfoPtr->scale.offsetY - tmpBox.top ) / curScale);
1301 r.bottom = (Int2)((dInfoPtr->scale.offsetY - tmpBox.bottom) / curScale);
1302 oval_h = (Int2)(pdata->oval_h / curScale);
1303
1304 /* attributes */
1305 SetPrimAttribute(pdc, COLOR_ATT|SHADING_ATT|MODE_ATT);
1306 if ( !pdata->fill )
1307 SetPrimAttribute(pdc, WIDTH_ATT);
1308
1309 /* draw */
1310 s_DoRoundRect(&r, oval_w, oval_h, pdata->fill, pdata->flags);
1311
1312 /* highlight */
1313 switch ( dInfoPtr->highlight ) {
1314 case PLAIN_PRIMITIVE:
1315 break;
1316 case FRAME_PRIMITIVE:
1317 case OUTLINE_PRIMITIVE:
1318 Black();
1319 WidePen( 1 );
1320 InsetRect(&r, -3, -3);
1321 s_DoRoundRect(&r, (Int2)(oval_w + 3), (Int2)(oval_h + 3),
1322 FALSE, pdata->flags);
1323 break;
1324 case FILL_PRIMITIVE:
1325 InsetRect(&r, -2, -2);
1326 s_DoRoundRect(&r, (Int2)(oval_w + 3), (Int2)(oval_h + 3),
1327 TRUE, pdata->flags);
1328 break;
1329 }
1330 }
1331
1332
RoRecHitTestProc(RoRecPDataPtr pdata,PrimHitContext phc)1333 static Boolean RoRecHitTestProc(RoRecPDataPtr pdata, PrimHitContext phc)
1334 {
1335 ScalePtr dInfoPtr = (ScalePtr)phc;
1336
1337 return (Boolean)
1338 ((pdata->box.left < dInfoPtr->worldWindow.right) &&
1339 (pdata->box.right > dInfoPtr->worldWindow.left) &&
1340 (pdata->box.top > dInfoPtr->worldWindow.bottom) &&
1341 (pdata->box.bottom < dInfoPtr->worldWindow.top));
1342 }
1343
RoRecOffsetProc(RoRecPDataPtr pdata,Int4 deltaX,Int4 deltaY)1344 static Boolean RoRecOffsetProc(RoRecPDataPtr pdata, Int4 deltaX, Int4 deltaY)
1345 {
1346 pdata->box.left += deltaX;
1347 pdata->box.right += deltaX;
1348 pdata->box.top += deltaY;
1349 pdata->box.bottom += deltaY;
1350 return TRUE;
1351 }
1352
RoRecGetLimitsProc(RoRecPDataPtr pdata,Int4 scaleX,Int4 scaleY,BoxPtr pLimits)1353 static Boolean RoRecGetLimitsProc(RoRecPDataPtr pdata,
1354 Int4 scaleX, Int4 scaleY, BoxPtr pLimits )
1355 {
1356 *pLimits = pdata->box;
1357 OutsetBox(pLimits, scaleX<<2, scaleY<<2);
1358 return TRUE;
1359 }
1360
1361 static PrimDef rorecPrimDef = {
1362 (PrimDrawProc ) RoRecDrawProc,
1363 (PrimHitTestProc ) RoRecHitTestProc,
1364 (PrimOffsetProc ) RoRecOffsetProc,
1365 (PrimCleanupProc ) 0,
1366 (PrimGetLimitsProc) RoRecGetLimitsProc
1367 };
1368
1369
1370 /*****************************************************************************
1371 *
1372 * AddRoundedRectangle
1373 *
1374 *****************************************************************************/
1375
AddRoundedRectangle(SegmenT parent,Int4 left,Int4 top,Int4 right,Int4 bottom,Int4 oval_w,Int4 oval_h,Boolean fill,Uint4 flags,Uint2 primID)1376 PrimitivE AddRoundedRectangle(SegmenT parent,
1377 Int4 left, Int4 top, Int4 right, Int4 bottom,
1378 Int4 oval_w, Int4 oval_h, Boolean fill,
1379 Uint4 flags, Uint2 primID)
1380 {
1381 RoRecPData data;
1382 Int4 tmp;
1383
1384 if (left > right) {
1385 tmp = left;
1386 left = right;
1387 right = tmp;
1388 }
1389 if (bottom > top) {
1390 tmp = bottom;
1391 bottom = top;
1392 top = tmp;
1393 }
1394
1395 data.box.left = left;
1396 data.box.top = top;
1397 data.box.right = right;
1398 data.box.bottom = bottom;
1399
1400 data.flags = flags;
1401
1402 data.oval_w = oval_w;
1403 data.oval_h = oval_h;
1404
1405 data.fill = fill;
1406 return AddPrimitive(&rorecPrimDef, parent, primID, (VoidPtr)&data,
1407 sizeof(RoRecPData));
1408 }
1409
1410
1411 /*****************************************************************************
1412 *
1413 * SEGMENT RECTANGLE
1414 *
1415 *****************************************************************************/
1416
1417 typedef struct segrecpdata {
1418 BoxPtr parentBox;
1419 Boolean fill;
1420 } SegRecPData, PNTR SegRecPDataPtr;
1421
SegRecDrawProc(SegRecPDataPtr pdata,PrimDrawContext pdc)1422 static void SegRecDrawProc (SegRecPDataPtr pdata, PrimDrawContext pdc)
1423 {
1424 register DrawInfoPtr dInfoPtr;
1425 BoxInfo tmpBox;
1426 Int4 curScale;
1427 RecT r;
1428
1429 dInfoPtr = (DrawInfoPtr)pdc;
1430 tmpBox = *(pdata->parentBox);
1431 if ( (tmpBox.left > dInfoPtr->scale.worldWindow.right) ||
1432 (tmpBox.right < dInfoPtr->scale.worldWindow.left) ||
1433 (tmpBox.top < dInfoPtr->scale.worldWindow.bottom) ||
1434 (tmpBox.bottom > dInfoPtr->scale.worldWindow.top) ) return;
1435 if ( dInfoPtr->checked == FALSE ) {
1436 if ( tmpBox.left < dInfoPtr->scale.worldWindow16.left )
1437 tmpBox.left = dInfoPtr->scale.worldWindow16.left;
1438 if ( tmpBox.right > dInfoPtr->scale.worldWindow16.right )
1439 tmpBox.right = dInfoPtr->scale.worldWindow16.right;
1440 if ( tmpBox.top > dInfoPtr->scale.worldWindow16.top )
1441 tmpBox.top = dInfoPtr->scale.worldWindow16.top;
1442 if ( tmpBox.bottom < dInfoPtr->scale.worldWindow16.bottom )
1443 tmpBox.bottom = dInfoPtr->scale.worldWindow16.bottom;
1444 }
1445 if (pdata->fill) {
1446 SetPrimAttribute (pdc, COLOR_ATT|SHADING_ATT|MODE_ATT);
1447 } else {
1448 SetPrimAttribute (pdc, COLOR_ATT|STYLE_ATT|WIDTH_ATT|MODE_ATT);
1449 }
1450 curScale = dInfoPtr->scale.scaleX;
1451 r.left = (Int2)((dInfoPtr->scale.offsetX + tmpBox.left) / curScale);
1452 r.right = (Int2)((dInfoPtr->scale.offsetX + tmpBox.right) / curScale);
1453 curScale = dInfoPtr->scale.scaleY;
1454 r.top = (Int2)((dInfoPtr->scale.offsetY - tmpBox.top) / curScale);
1455 r.bottom = (Int2)((dInfoPtr->scale.offsetY - tmpBox.bottom) / curScale);
1456 r.right++; r.bottom++;
1457 if ( pdata->fill ) PaintRect (&r);
1458 else FrameRect (&r);
1459 r.right--; r.bottom--;
1460 switch ( dInfoPtr->highlight ) {
1461 case FRAME_PRIMITIVE:
1462 case OUTLINE_PRIMITIVE:
1463 SetPrimAttribute (pdc, STYLE_ATT|WIDTH_ATT);
1464 WidePen((Int2)(dInfoPtr->primattrib->penwidth + 1));
1465 r.right ++; r.bottom ++;
1466 FrameRect (&r);
1467 InsetRect (&r, -1, -1 );
1468 FrameRect (&r);
1469 break;
1470 case FILL_PRIMITIVE:
1471 SetPrimAttribute (pdc, SHADING_ATT);
1472 r.right ++; r.bottom ++;
1473 InsetRect (&r, -1, -1);
1474 PaintRect (&r);
1475 }
1476 }
1477
SegRecHitTestProc(SegRecPDataPtr pdata,PrimHitContext phc)1478 static Boolean SegRecHitTestProc ( SegRecPDataPtr pdata, PrimHitContext phc)
1479 {
1480 register ScalePtr dInfoPtr;
1481 BoxInfo tmpBox;
1482
1483
1484
1485 dInfoPtr = (ScalePtr)phc;
1486 tmpBox = *(pdata->parentBox);
1487 if ( (tmpBox.left < dInfoPtr->worldWindow.right) &&
1488 (tmpBox.right > dInfoPtr->worldWindow.left) &&
1489 (tmpBox.top > dInfoPtr->worldWindow.bottom) &&
1490 (tmpBox.bottom < dInfoPtr->worldWindow.top) ) return TRUE;
1491 return FALSE;
1492 }
1493
SegRecOffsetProc(SegRecPDataPtr pdata,Int4 deltaX,Int4 deltaY)1494 static Boolean SegRecOffsetProc ( SegRecPDataPtr pdata, Int4 deltaX,
1495 Int4 deltaY )
1496 {
1497 return FALSE;
1498 }
1499
SegRecGetLimitsProc(SegRecPDataPtr pdata,Int4 scaleX,Int4 scaleY,BoxPtr pLimits)1500 static Boolean SegRecGetLimitsProc ( SegRecPDataPtr pdata, Int4 scaleX,
1501 Int4 scaleY, BoxPtr pLimits )
1502 {
1503 *pLimits = *(pdata->parentBox);
1504 return TRUE;
1505 }
1506
1507 static PrimDef segrecPrimDef = {
1508 (PrimDrawProc) SegRecDrawProc,
1509 (PrimHitTestProc) SegRecHitTestProc,
1510 (PrimOffsetProc) SegRecOffsetProc,
1511 (PrimCleanupProc) NULL,
1512 (PrimGetLimitsProc) SegRecGetLimitsProc
1513 };
1514
Nlm_AddSegRect(SegmenT parent,Boolean fill,Uint2 primID)1515 Nlm_PrimitivE Nlm_AddSegRect ( SegmenT parent, Boolean fill,
1516 Uint2 primID )
1517 {
1518 SegRecPData data;
1519
1520 data.parentBox = &(((SegPPtr)parent)->seg.box);
1521 data.fill = fill;
1522 return AddPrimitive (&segrecPrimDef, parent, primID, (VoidPtr)&data,
1523 sizeof(SegRecPData));
1524 }
1525
SilentSegRecHitTestProc(SegRecPDataPtr pdata,PrimHitContext phc)1526 static Boolean SilentSegRecHitTestProc ( SegRecPDataPtr pdata, PrimHitContext phc)
1527 {
1528 /* SilentSegRect's should never absorb clicks */
1529 return FALSE;
1530 }
1531
1532 static PrimDef silentSegrecPrimDef = {
1533 (PrimDrawProc) SegRecDrawProc,
1534 (PrimHitTestProc) SilentSegRecHitTestProc,
1535 (PrimOffsetProc) SegRecOffsetProc,
1536 (PrimCleanupProc) NULL,
1537 (PrimGetLimitsProc) SegRecGetLimitsProc
1538 };
1539
Nlm_AddSilentSegRect(SegmenT parent,Boolean fill,Uint2 primID)1540 Nlm_PrimitivE Nlm_AddSilentSegRect ( SegmenT parent, Boolean fill,
1541 Uint2 primID )
1542 {
1543 SegRecPData data;
1544
1545 data.parentBox = &(((SegPPtr)parent)->seg.box);
1546 data.fill = fill;
1547 return AddPrimitive (&silentSegrecPrimDef, parent, primID, (VoidPtr)&data,
1548 sizeof(SegRecPData));
1549 }
1550
1551 /*****************************************************************************
1552 *
1553 * H - LINE
1554 *
1555 *****************************************************************************/
1556 typedef struct hlinepdata {
1557 Int4 x1;
1558 Int4 x2;
1559 Int4 y;
1560 Int1 fArrowPoint;
1561 Int1 arrowSize;
1562 } HLinePData, PNTR HLinePDataPtr;
1563
HLineDrawProc(HLinePDataPtr pdata,PrimDrawContext pdc)1564 static void HLineDrawProc (HLinePDataPtr pdata, PrimDrawContext pdc)
1565 {
1566 register DrawInfoPtr dInfoPtr;
1567 Int4 curScale;
1568 Int4 x1,x2,y;
1569 PoinT pt1, pt2;
1570 PoinT pts [3];
1571 Int2 oldPoint;
1572 Int1 arrowSize;
1573 Boolean vis = TRUE;
1574 RecT rect;
1575
1576 dInfoPtr = (DrawInfoPtr)pdc;
1577 x1 = pdata->x1;
1578 x2 = pdata->x2;
1579 y = pdata->y;
1580 if ( (y > dInfoPtr->scale.worldWindow.top ) ||
1581 (y < dInfoPtr->scale.worldWindow.bottom) ||
1582 (x1 > dInfoPtr->scale.worldWindow.right ) ||
1583 (x2 < dInfoPtr->scale.worldWindow.left ) )
1584 return;
1585
1586 if ( dInfoPtr->checked == FALSE ) {
1587 curScale = dInfoPtr->scale.worldWindow16.left;
1588 if ( x1 < curScale ) x1 = curScale;
1589 curScale = dInfoPtr->scale.worldWindow16.right;
1590 if ( x2 > curScale ) x2 = curScale;
1591 }
1592
1593 SetPrimAttribute (pdc, COLOR_ATT|STYLE_ATT|WIDTH_ATT|MODE_ATT);
1594
1595 arrowSize = pdata->arrowSize;
1596 curScale = dInfoPtr->scale.scaleX;
1597 pt1.x = (Int2)((dInfoPtr->scale.offsetX + x1) / curScale);
1598 pt2.x = (Int2)((dInfoPtr->scale.offsetX + x2) / curScale);
1599 curScale = dInfoPtr->scale.scaleY;
1600 pt1.y = pt2.y = (Int2)((dInfoPtr->scale.offsetY - y) / curScale);
1601
1602 if (dInfoPtr->highlight != PLAIN_PRIMITIVE)
1603 {
1604 rect.left = pt1.x;
1605 rect.right = pt2.x;
1606 rect.top = rect.bottom = pt1.y;
1607 }
1608
1609 switch ( pdata->fArrowPoint ) {
1610 case 0:
1611 oldPoint = pt2.x;
1612 if (pt2.x - pt1.x > (Int2)arrowSize) pt2.x -= (Int2)arrowSize;
1613 else pt2.x -= (Int2)(arrowSize>>1);
1614 if ( pt2.x < pt1.x ) vis = FALSE;
1615 pts[1].x = oldPoint; pts[1].y = pt1.y;
1616 oldPoint = (Int2)ARROWWIDTH2 * (Int2)arrowSize / (Int2)100;
1617 pts[0].x = pt2.x; pts[0].y = pt1.y + oldPoint;
1618 pts[2].x = pt2.x; pts[2].y = pt2.y - oldPoint ;
1619 break;
1620 case 1:
1621 oldPoint = pt1.x;
1622 if (pt2.x - pt1.x > (Int2)arrowSize) pt1.x += (Int2)arrowSize;
1623 else pt1.x += (Int2)(arrowSize>>1);
1624 if ( pt2.x < pt1.x ) vis = FALSE;
1625 pts[1].x = oldPoint; pts[1].y = pt1.y;
1626 oldPoint = (Int2)ARROWWIDTH2 * (Int2)arrowSize / (Int2)100;
1627 pts[0].x = pt1.x; pts[0].y = pt1.y - oldPoint;
1628 pts[2].x = pt1.x; pts[2].y = pt2.y + oldPoint ;
1629 }
1630
1631 if ( vis ) DrawLine (pt1, pt2);
1632 if ( pdata->fArrowPoint != 0xF ){
1633 SetPrimAttribute (pdc, SHADING_ATT);
1634 PaintPoly (3, pts);
1635 }
1636
1637 switch ( dInfoPtr->highlight )
1638 {
1639 case PLAIN_PRIMITIVE:
1640 break;
1641 case FRAME_PRIMITIVE:
1642 case OUTLINE_PRIMITIVE:
1643 Black();
1644 WidePen( 1 );
1645 InsetRect(&rect, -2, -2);
1646 rect.bottom++;
1647 FrameRect( &rect );
1648 break;
1649 case FILL_PRIMITIVE:
1650 SetPrimAttribute (pdc, STYLE_ATT|WIDTH_ATT);
1651 WidePen((Int2)(((DrawInfoPtr)pdc)->primattrib->penwidth + 2));
1652 if ( vis ) DrawLine (pt1, pt2);
1653 if ( pdata->fArrowPoint != 0xF ){
1654 FramePoly (3, pts);
1655 SetPrimAttribute (pdc, SHADING_ATT);
1656 PaintPoly (3, pts);
1657 }
1658 break;
1659 }
1660 }
1661
1662
HLineHitTestProc(HLinePDataPtr pdata,PrimHitContext phc)1663 static Boolean HLineHitTestProc ( HLinePDataPtr pdata, PrimHitContext phc)
1664 {
1665 register ScalePtr dInfoPtr;
1666
1667 dInfoPtr = (ScalePtr)phc;
1668 if ( (pdata->x1 < dInfoPtr->worldWindow.right) &&
1669 (pdata->x2 > dInfoPtr->worldWindow.left) &&
1670 (pdata->y > dInfoPtr->worldWindow.bottom) &&
1671 (pdata->y < dInfoPtr->worldWindow.top) ) return TRUE;
1672 return FALSE;
1673 }
1674
HLineOffsetProc(HLinePDataPtr pdata,Int4 deltaX,Int4 deltaY)1675 static Boolean HLineOffsetProc ( HLinePDataPtr pdata, Int4 deltaX,
1676 Int4 deltaY )
1677 {
1678 pdata->x1 += deltaX;
1679 pdata->x2 += deltaX;
1680 pdata->y += deltaY;
1681 return TRUE;
1682 }
1683
HLineGetLimitsProc(HLinePDataPtr pdata,Int4 scaleX,Int4 scaleY,BoxPtr pLimits)1684 static Boolean HLineGetLimitsProc ( HLinePDataPtr pdata, Int4 scaleX,
1685 Int4 scaleY, BoxPtr pLimits )
1686 {
1687 Int4 arrowSize;
1688
1689 switch ( pdata->fArrowPoint ) {
1690 case 0:
1691 arrowSize = pdata->arrowSize*scaleX/2;
1692 if ( pdata->x2 - pdata->x1 < arrowSize )
1693 pLimits->left = pdata->x2 - arrowSize;
1694 else pLimits->left = pdata->x1;
1695 pLimits->right = pdata->x2;
1696 pLimits->top = pdata->y + arrowSize;
1697 pLimits->bottom = pdata->y - arrowSize;
1698 break;
1699 case 1:
1700 arrowSize = pdata->arrowSize*scaleX/2;
1701 if ( pdata->x2 - pdata->x1 < arrowSize )
1702 pLimits->right = pdata->x2 - arrowSize;
1703 else pLimits->right = pdata->x2;
1704 pLimits->left = pdata->x1;
1705 pLimits->top = pdata->y + arrowSize;
1706 pLimits->bottom = pdata->y - arrowSize;
1707 break;
1708 default:
1709 pLimits->left = pdata->x1;
1710 pLimits->right = pdata->x2;
1711 pLimits->top = pLimits->bottom = pdata->y;
1712 }
1713 OutsetBox ( pLimits, scaleX<<2, scaleY<<2 );
1714 return TRUE;
1715 }
1716
1717 static PrimDef hlinePrimDef = {
1718 (PrimDrawProc) HLineDrawProc,
1719 (PrimHitTestProc) HLineHitTestProc,
1720 (PrimOffsetProc) HLineOffsetProc,
1721 (PrimCleanupProc) NULL,
1722 (PrimGetLimitsProc) HLineGetLimitsProc
1723 };
1724
1725 /*****************************************************************************
1726 *
1727 * AddHLine (parent, x1, x2, y, arrow, primID)
1728 *
1729 *****************************************************************************/
1730
Nlm_AddHLine(SegmenT parent,Int4 pnt1X,Int4 pnt2X,Int4 pntY,Boolean arrow,Uint2 primID)1731 static PrimitivE Nlm_AddHLine ( SegmenT parent, Int4 pnt1X, Int4 pnt2X,
1732 Int4 pntY, Boolean arrow, Uint2 primID )
1733 {
1734 HLinePData data;
1735
1736 if ( pnt1X == pnt2X ) arrow = FALSE;
1737 data.y = pntY;
1738 data.arrowSize = userArrowSize;
1739 if ( pnt2X >= pnt1X ) {
1740 data.x1 = pnt1X;
1741 data.x2 = pnt2X;
1742 data.fArrowPoint = 0;
1743 } else {
1744 data.x1 = pnt2X;
1745 data.x2 = pnt1X;
1746 data.fArrowPoint = 1;
1747 }
1748 if ( !arrow ) data.fArrowPoint = (Int1)0xF;
1749 return AddPrimitive (&hlinePrimDef, parent, primID, (VoidPtr)&data,
1750 sizeof(HLinePData));
1751 }
1752
1753 /*****************************************************************************
1754 *
1755 * V - LINE
1756 *
1757 *****************************************************************************/
1758 typedef struct vlinepdata {
1759 Int4 y1;
1760 Int4 y2;
1761 Int4 x;
1762 Int1 fArrowPoint;
1763 Int1 arrowSize;
1764 } VLinePData, PNTR VLinePDataPtr;
1765
VLineDrawProc(VLinePDataPtr pdata,PrimDrawContext pdc)1766 static void VLineDrawProc (VLinePDataPtr pdata, PrimDrawContext pdc)
1767 {
1768 register DrawInfoPtr dInfoPtr;
1769 Int4 curScale;
1770 Int4 y1,y2,x;
1771 PoinT pt1, pt2;
1772 PoinT pts [3];
1773 Int2 oldPoint;
1774 Int1 arrowSize;
1775 Boolean vis = TRUE;
1776
1777 dInfoPtr = (DrawInfoPtr)pdc;
1778 y1 = pdata->y1;
1779 y2 = pdata->y2;
1780 x = pdata->x;
1781 if ( (y1 > dInfoPtr->scale.worldWindow.top) ||
1782 (y2 < dInfoPtr->scale.worldWindow.bottom) ||
1783 (x > dInfoPtr->scale.worldWindow.right) ||
1784 (x < dInfoPtr->scale.worldWindow.left) ) return;
1785 if ( dInfoPtr->checked == FALSE ) {
1786 curScale = dInfoPtr->scale.worldWindow16.bottom;
1787 if ( y1 < curScale ) y1 = curScale;
1788 curScale = dInfoPtr->scale.worldWindow16.top;
1789 if ( y2 > curScale ) y2 = curScale;
1790 }
1791 SetPrimAttribute (pdc, COLOR_ATT|STYLE_ATT|WIDTH_ATT|MODE_ATT);
1792 arrowSize = pdata->arrowSize;
1793 curScale = dInfoPtr->scale.scaleY;
1794 pt1.y = (Int2)((dInfoPtr->scale.offsetY - y1) / curScale);
1795 pt2.y = (Int2)((dInfoPtr->scale.offsetY - y2) / curScale);
1796 curScale = dInfoPtr->scale.scaleX;
1797 pt1.x = pt2.x = (Int2)((dInfoPtr->scale.offsetX + x) / curScale);
1798 switch ( pdata->fArrowPoint ) {
1799 case 0:
1800 oldPoint = pt2.y;
1801 if (pt1.y - pt2.y > (Int2)arrowSize) pt2.y += (Int2)arrowSize;
1802 else pt2.y += (Int2)(arrowSize>>1);
1803 if ( pt2.y > pt1.y ) vis = FALSE;
1804 pts[1].x = pt1.x; pts[1].y = oldPoint;
1805 oldPoint = (Int2)ARROWWIDTH2 * (Int2)arrowSize / (Int2)100;
1806 pts[0].x = pt1.x - oldPoint; pts[0].y = pt2.y;
1807 pts[2].x = pt1.x + oldPoint; pts[2].y = pt2.y;
1808 break;
1809 case 1:
1810 oldPoint = pt1.y;
1811 if (pt1.y - pt2.y > (Int2)arrowSize) pt1.y -= (Int2)arrowSize;
1812 else pt1.y -= (Int2)(arrowSize>>1);
1813 if ( pt2.y > pt1.y ) vis = FALSE;
1814 pts[1].x = pt1.x; pts[1].y = oldPoint;
1815 oldPoint = (Int2)ARROWWIDTH2 * (Int2)arrowSize / (Int2)100;
1816 pts[0].x = pt1.x + oldPoint; pts[0].y = pt1.y;
1817 pts[2].x = pt1.x - oldPoint; pts[2].y = pt1.y;
1818 }
1819 if ( vis ) DrawLine (pt1, pt2);
1820 if ( pdata->fArrowPoint != 0xF ){
1821 FramePoly (3, pts);
1822 SetPrimAttribute (pdc, SHADING_ATT);
1823 PaintPoly (3, pts);
1824 }
1825 if ( dInfoPtr->highlight != PLAIN_SEGMENT ) {
1826 SetPrimAttribute (pdc, STYLE_ATT|WIDTH_ATT);
1827 WidePen((Int2)(((DrawInfoPtr)pdc)->primattrib->penwidth + 2));
1828 if ( vis ) DrawLine (pt1, pt2);
1829 if ( pdata->fArrowPoint != 0xF ){
1830 SetPrimAttribute (pdc, SHADING_ATT);
1831 PaintPoly (3, pts);
1832 }
1833 }
1834 }
1835
VLineHitTestProc(VLinePDataPtr pdata,PrimHitContext phc)1836 static Boolean VLineHitTestProc ( VLinePDataPtr pdata, PrimHitContext phc)
1837 {
1838 register ScalePtr dInfoPtr;
1839
1840 dInfoPtr = (ScalePtr)phc;
1841 if ( (pdata->x < dInfoPtr->worldWindow.right) &&
1842 (pdata->x > dInfoPtr->worldWindow.left) &&
1843 (pdata->y1 < dInfoPtr->worldWindow.top) &&
1844 (pdata->y2 > dInfoPtr->worldWindow.bottom) ) return TRUE;
1845 return FALSE;
1846 }
1847
VLineOffsetProc(VLinePDataPtr pdata,Int4 deltaX,Int4 deltaY)1848 static Boolean VLineOffsetProc ( VLinePDataPtr pdata, Int4 deltaX,
1849 Int4 deltaY )
1850 {
1851 pdata->x += deltaX;
1852 pdata->y1 += deltaY;
1853 pdata->y2 += deltaY;
1854 return TRUE;
1855 }
1856
VLineGetLimitsProc(VLinePDataPtr pdata,Int4 scaleX,Int4 scaleY,BoxPtr pLimits)1857 static Boolean VLineGetLimitsProc ( VLinePDataPtr pdata, Int4 scaleX,
1858 Int4 scaleY, BoxPtr pLimits )
1859 {
1860 Int4 arrowSize;
1861
1862 switch ( pdata->fArrowPoint ) {
1863 case 0:
1864 arrowSize = pdata->arrowSize*scaleY/2;
1865 if ( pdata->y2 - pdata->y1 < arrowSize )
1866 pLimits->bottom = pdata->y2 + arrowSize;
1867 else pLimits->bottom = pdata->y1;
1868 pLimits->top = pdata->y2;
1869 pLimits->right = pdata->x + arrowSize;
1870 pLimits->left = pdata->x - arrowSize;
1871 break;
1872 case 1:
1873 arrowSize = pdata->arrowSize*scaleY/2;
1874 if ( pdata->y2 - pdata->y1 < arrowSize )
1875 pLimits->top = pdata->y1 - arrowSize;
1876 else pLimits->top = pdata->y2;
1877 pLimits->bottom = pdata->y1;
1878 pLimits->right = pdata->x + arrowSize;
1879 pLimits->left = pdata->x - arrowSize;
1880 break;
1881 default:
1882 pLimits->top = pdata->y2;
1883 pLimits->bottom = pdata->y1;
1884 pLimits->left = pLimits->right = pdata->x;
1885 }
1886 OutsetBox ( pLimits, scaleX<<2, scaleY<<2 );
1887 return TRUE;
1888 }
1889
1890 static PrimDef vlinePrimDef = {
1891 (PrimDrawProc) VLineDrawProc,
1892 (PrimHitTestProc) VLineHitTestProc,
1893 (PrimOffsetProc) VLineOffsetProc,
1894 (PrimCleanupProc) NULL,
1895 (PrimGetLimitsProc) VLineGetLimitsProc
1896 };
1897
1898 /*****************************************************************************
1899 *
1900 * AddVLine (parent, x, y1, y2, arrow, primID)
1901 *
1902 *****************************************************************************/
1903
Nlm_AddVLine(SegmenT parent,Int4 pntX,Int4 pnt1Y,Int4 pnt2Y,Boolean arrow,Uint2 primID)1904 static PrimitivE Nlm_AddVLine ( SegmenT parent, Int4 pntX, Int4 pnt1Y,
1905 Int4 pnt2Y, Boolean arrow, Uint2 primID )
1906 {
1907 VLinePData data;
1908
1909 if ( pnt1Y == pnt2Y ) arrow = FALSE;
1910 data.x = pntX;
1911 data.arrowSize = userArrowSize;
1912 if ( pnt2Y >= pnt1Y ) {
1913 data.y1 = pnt1Y;
1914 data.y2 = pnt2Y;
1915 data.fArrowPoint = 0;
1916 } else {
1917 data.y1 = pnt2Y;
1918 data.y2 = pnt1Y;
1919 data.fArrowPoint = 1;
1920 }
1921 if ( !arrow ) data.fArrowPoint = (Int1)0xF;
1922 return AddPrimitive (&vlinePrimDef, parent, primID, (VoidPtr)&data,
1923 sizeof(VLinePData));
1924 }
1925
1926 /*****************************************************************************
1927 *
1928 * LINE
1929 *
1930 *****************************************************************************/
1931
1932 typedef struct linepdata {
1933 BoxInfo box;
1934 Int1 fPoint;
1935 Int1 fArrowPoint;
1936 Int1 arrowSize;
1937 } LinePData, PNTR LinePDataPtr;
1938
MSin(Int4 a)1939 static Int2 MSin(Int4 a)
1940 {
1941 if (a < 0)
1942 a += INT4_MAX / 360 * 360;
1943 a %= 360;
1944
1945 if (a < 90)
1946 return sin100[a];
1947 if (a < 180)
1948 return sin100[180-a];
1949 if (a < 270)
1950 return -sin100[a-180];
1951 return -sin100[360-a];
1952 }
1953
1954 /* (for future use)
1955 static Int2 MCos(Int4 a)
1956 {
1957 if (a < 0)
1958 a += INT4_MAX / 360 * 360;
1959 a %= 360;
1960
1961 if (a < 90)
1962 return sin100[90 - a];
1963 if (a < 180)
1964 return -sin100[a - 90];
1965 if (a < 270)
1966 return -sin100[270 - a];
1967 return sin100[a-270];
1968 }
1969 */
1970
LineDrawProc(LinePDataPtr pdata,PrimDrawContext pdc)1971 static void LineDrawProc (LinePDataPtr pdata, PrimDrawContext pdc)
1972 {
1973 register DrawInfoPtr dInfoPtr;
1974 Int4 curScale;
1975 Int4 x1,y1,x2,y2;
1976 PoinT pt1, pt2;
1977 PoinT pts [3];
1978 Int2 angle;
1979 Int2 dangle = 20;
1980 Int2 arrowSize;
1981 Int2 arrowLen = 106;
1982 Int2 dx, dy;
1983 Boolean vis = TRUE;
1984
1985 dInfoPtr = (DrawInfoPtr)pdc;
1986 arrowSize = (Int2)pdata->arrowSize;
1987 x1 = pdata->box.left;
1988 x2 = pdata->box.right;
1989 if ( pdata->fPoint == 0 ) {
1990 y1 = pdata->box.bottom;
1991 y2 = pdata->box.top;
1992 } else {
1993 y1 = pdata->box.top;
1994 y2 = pdata->box.bottom;
1995 }
1996 if ( pdata->fArrowPoint == 0xF ) {
1997 if ( (x1 > dInfoPtr->scale.worldWindow.right) ||
1998 (x2 < dInfoPtr->scale.worldWindow.left) ||
1999 (pdata->box.bottom > dInfoPtr->scale.worldWindow.top) ||
2000 (pdata->box.top < dInfoPtr->scale.worldWindow.bottom) ) return;
2001 } else {
2002 curScale = arrowSize * dInfoPtr->scale.scaleX / 2;
2003 if ( ((x1+curScale) > dInfoPtr->scale.worldWindow.right) ||
2004 ((x2-curScale) < dInfoPtr->scale.worldWindow.left) ) return;
2005 curScale = arrowSize * dInfoPtr->scale.scaleY / 2;
2006 if ( ((pdata->box.bottom+curScale) > dInfoPtr->scale.worldWindow.top) ||
2007 ((pdata->box.top+curScale) < dInfoPtr->scale.worldWindow.bottom) )
2008 return;
2009 }
2010 if ( dInfoPtr->checked == FALSE ) {
2011 if ( LineIntoVPort ( &x1, &y1, &x2, &y2,
2012 &(dInfoPtr->scale.worldWindow16)) == FALSE ) return;
2013 }
2014 SetPrimAttribute (pdc, COLOR_ATT|STYLE_ATT|WIDTH_ATT|MODE_ATT);
2015 curScale = dInfoPtr->scale.scaleX;
2016 pt1.x = (Int2)((dInfoPtr->scale.offsetX + x1) / curScale);
2017 pt2.x = (Int2)((dInfoPtr->scale.offsetX + x2) / curScale);
2018 curScale = dInfoPtr->scale.scaleY;
2019 pt1.y = (Int2)((dInfoPtr->scale.offsetY - y1) / curScale);
2020 pt2.y = (Int2)((dInfoPtr->scale.offsetY - y2) / curScale);
2021 if ( pdata->fArrowPoint != 0xF ){
2022 dx = pt2.x - pt1.x;
2023 dy = pt2.y - pt1.y; if ( dy < 0 ) dy = -dy;
2024 if ( (dx < 4) || ( dy < 4 ) ){
2025 x2 -= x1;
2026 y2 -= y1; if ( y2 < 0 ) y2 = -y2;
2027 } else {
2028 x2 = (Int4)dx; y2 = (Int4)dy;
2029 }
2030 x1 = x2*x2 + y2*y2;
2031 y1 = (Int4)arrowSize * (Int4)arrowSize;
2032 if ( x1 < y1 ) {
2033 dangle = 36;
2034 arrowLen = 61;
2035 if ( x1 < y1/4 ) vis = FALSE;
2036 }
2037 if ( x2 > y2 ) {
2038 if ( x2 > 0xFFFFFF ) angle = atan100[ y2/(x2/100) ] ;
2039 else angle = atan100[ y2*100/x2 ] ;
2040 } else {
2041 if ( y2 > 0xFFFFFF ) angle = 90 - atan100[ x2/(y2/100) ] ;
2042 angle = 90 - atan100[ x2*100/y2 ] ;
2043 }
2044 switch ( pdata->fArrowPoint ){
2045 case 0:
2046 pts[0] = pt2;
2047 angle += 180;
2048 break;
2049 case 1:
2050 pts[0] = pt2;
2051 angle = 180 - angle;
2052 break;
2053 case 2:
2054 pts[0] = pt1;
2055 break;
2056 default:
2057 pts[0] = pt1;
2058 angle = 360 - angle;
2059 }
2060 angle += dangle;
2061 pts[1].x = pts[0].x + MSin(angle+90)*arrowLen/100*arrowSize/100;
2062 pts[1].y = pts[0].y - MSin(angle)*arrowLen/100*arrowSize/100;
2063 angle -= 2*dangle;
2064 pts[2].x = pts[0].x + MSin(angle+90)*arrowLen/100*arrowSize/100;
2065 pts[2].y = pts[0].y - MSin(angle)*arrowLen/100*arrowSize/100;
2066 }
2067 if ( vis ) DrawLine (pt1, pt2);
2068 if ( pdata->fArrowPoint != 0xF ){
2069 FramePoly (3, pts);
2070 SetPrimAttribute (pdc, SHADING_ATT);
2071 PaintPoly (3, pts);
2072 }
2073 if ( dInfoPtr->highlight != PLAIN_SEGMENT ) {
2074 SetPrimAttribute (pdc, STYLE_ATT|WIDTH_ATT);
2075 WidePen((Int2)(((DrawInfoPtr)pdc)->primattrib->penwidth + 2));
2076 if ( vis ) DrawLine (pt1, pt2);
2077 if ( pdata->fArrowPoint != 0xF ){
2078 FramePoly (3, pts);
2079 SetPrimAttribute (pdc, SHADING_ATT);
2080 PaintPoly (3, pts);
2081 }
2082 }
2083 }
2084
LineHitTestProc(LinePDataPtr pdata,PrimHitContext phc)2085 static Boolean LineHitTestProc ( LinePDataPtr pdata, PrimHitContext phc)
2086 {
2087 register ScalePtr dInfoPtr;
2088 Int4 x1,y1,x2,y2;
2089
2090 dInfoPtr = (ScalePtr)phc;
2091 if ( (pdata->box.left < dInfoPtr->worldWindow.right) &&
2092 (pdata->box.right > dInfoPtr->worldWindow.left) &&
2093 (pdata->box.top > dInfoPtr->worldWindow.bottom) &&
2094 (pdata->box.bottom < dInfoPtr->worldWindow.top) ) {
2095 x1 = pdata->box.left;
2096 x2 = pdata->box.right;
2097 if ( pdata->fPoint == 0 ) {
2098 y1 = pdata->box.bottom;
2099 y2 = pdata->box.top;
2100 } else {
2101 y2 = pdata->box.bottom;
2102 y1 = pdata->box.top;
2103 }
2104 return IsLineInVPort ( x1, y1, x2, y2, &(dInfoPtr->worldWindow) );
2105 }
2106 return FALSE;
2107 }
2108
LineOffsetProc(LinePDataPtr pdata,Int4 deltaX,Int4 deltaY)2109 static Boolean LineOffsetProc ( LinePDataPtr pdata, Int4 deltaX,
2110 Int4 deltaY )
2111 {
2112 pdata->box.left += deltaX;
2113 pdata->box.right += deltaX;
2114 pdata->box.top += deltaY;
2115 pdata->box.bottom += deltaY;
2116 return TRUE;
2117 }
2118
LineGetLimitsProc(LinePDataPtr pdata,Int4 scaleX,Int4 scaleY,BoxPtr pLimits)2119 static Boolean LineGetLimitsProc ( LinePDataPtr pdata, Int4 scaleX,
2120 Int4 scaleY, BoxPtr pLimits )
2121 {
2122 *pLimits = pdata->box;
2123 switch ( pdata->fArrowPoint ) {
2124 case 0:
2125 pLimits->right += pdata->arrowSize*scaleX/2;
2126 pLimits->top += pdata->arrowSize*scaleY/2;
2127 break;
2128 case 1:
2129 pLimits->right += pdata->arrowSize*scaleX/2;
2130 pLimits->bottom -= pdata->arrowSize*scaleY/2;
2131 break;
2132 case 2:
2133 pLimits->left -= pdata->arrowSize*scaleX/2;
2134 pLimits->bottom -= pdata->arrowSize*scaleY/2;
2135 break;
2136 case 3:
2137 pLimits->left -= pdata->arrowSize*scaleX/2;
2138 pLimits->top += pdata->arrowSize*scaleY/2;
2139 }
2140 OutsetBox ( pLimits, scaleX<<2, scaleY<<2 );
2141 return TRUE;
2142 }
2143
2144 static PrimDef linePrimDef = {
2145 (PrimDrawProc) LineDrawProc,
2146 (PrimHitTestProc) LineHitTestProc,
2147 (PrimOffsetProc) LineOffsetProc,
2148 (PrimCleanupProc) NULL,
2149 (PrimGetLimitsProc) LineGetLimitsProc
2150 };
2151
2152 /*****************************************************************************
2153 *
2154 * AddLine (parent, x1, y1, x2, y2, arrow, primID)
2155 *
2156 *****************************************************************************/
2157
Nlm_AddLine(SegmenT parent,Int4 pnt1X,Int4 pnt1Y,Int4 pnt2X,Int4 pnt2Y,Boolean arrow,Uint2 primID)2158 PrimitivE Nlm_AddLine ( SegmenT parent, Int4 pnt1X, Int4 pnt1Y, Int4 pnt2X,
2159 Int4 pnt2Y, Boolean arrow, Uint2 primID )
2160 {
2161 LinePData data;
2162 GenPPtr gpp;
2163
2164 if ( pnt1Y == pnt2Y ){
2165 return Nlm_AddHLine ( parent, pnt1X, pnt2X, pnt2Y, arrow, primID );
2166 }
2167 if ( pnt1X == pnt2X ){
2168 return Nlm_AddVLine ( parent, pnt1X, pnt1Y, pnt2Y, arrow, primID );
2169 }
2170 if ( (pnt1X == pnt2X) || (pnt1Y == pnt2Y) ) arrow = FALSE;
2171 if ( pnt2X >= pnt1X ) {
2172 data.box.left = pnt1X;
2173 data.box.right = pnt2X;
2174 data.fArrowPoint = 0;
2175 } else {
2176 data.box.left = pnt2X;
2177 data.box.right = pnt1X;
2178 data.fArrowPoint = 2;
2179 }
2180 if ( pnt2Y >= pnt1Y ) {
2181 data.box.bottom = pnt1Y;
2182 data.box.top = pnt2Y;
2183 if ( data.fArrowPoint ) data.fArrowPoint = 3;
2184 } else {
2185 data.box.bottom = pnt2Y;
2186 data.box.top = pnt1Y;
2187 if ( data.fArrowPoint == 0 ) data.fArrowPoint = 1;
2188 }
2189 data.arrowSize = userArrowSize;
2190 if ( data.fArrowPoint & 0x1 ) data.fPoint = 1;
2191 else data.fPoint = 0;
2192 if ( arrow == FALSE ) data.fArrowPoint = (Int1)0xF;
2193 gpp = (GenPPtr)AddPrimitive (&linePrimDef, parent, primID, (VoidPtr)&data,
2194 sizeof(LinePData));
2195 if ( gpp != NULL ){
2196 gpp->att.shading = SOLID_SHADING;
2197 }
2198 return (PrimitivE)gpp;
2199 }
2200
2201 /*****************************************************************************
2202 *
2203 * BITMAP & SYMBOL
2204 *
2205 *****************************************************************************/
2206
2207 typedef struct bmppdata {
2208 Uint1Ptr bits;
2209 PntInfo pnt;
2210 Int2 width;
2211 Int2 height;
2212 Int2 align;
2213 } BmpPData, PNTR BmpPDataPtr;
2214
BmpDrawProc(BmpPDataPtr pdata,PrimDrawContext pdc)2215 static void BmpDrawProc (BmpPDataPtr pdata, PrimDrawContext pdc)
2216 {
2217 register DrawInfoPtr dInfoPtr;
2218 Int4 x, y;
2219 BoxInfo tmpBox;
2220 RecT r;
2221
2222 dInfoPtr = (DrawInfoPtr)pdc;
2223 MakeAlignBox ( pdata->pnt.x, pdata->pnt.y,
2224 (Int4)pdata->width * dInfoPtr->scale.scaleX,
2225 (Int4)pdata->height * dInfoPtr->scale.scaleY,
2226 0, 0, pdata->align, &tmpBox );
2227 if ( (tmpBox.left > dInfoPtr->scale.worldWindow.right) ||
2228 (tmpBox.right < dInfoPtr->scale.worldWindow.left) ||
2229 (tmpBox.top < dInfoPtr->scale.worldWindow.bottom) ||
2230 (tmpBox.bottom > dInfoPtr->scale.worldWindow.top) ) return;
2231 x = (dInfoPtr->scale.offsetX + pdata->pnt.x) / dInfoPtr->scale.scaleX;
2232 y = (dInfoPtr->scale.offsetY - pdata->pnt.y) / dInfoPtr->scale.scaleY;
2233 MakeAlignRect ( (Int2)x, (Int2)y, pdata->width, pdata->height,
2234 0, pdata->align, &r );
2235 SetPrimAttribute (pdc, COLOR_ATT|MODE_ATT);
2236 if (pdata->bits != NULL) CopyBits (&r, pdata->bits);
2237 switch ( dInfoPtr->highlight ) {
2238 case FRAME_PRIMITIVE:
2239 case FILL_PRIMITIVE:
2240 case OUTLINE_PRIMITIVE:
2241 r.right ++; r.bottom ++;
2242 SetPrimAttribute (pdc, STYLE_ATT|WIDTH_ATT);
2243 FrameRect (&r);
2244 InsetRect (&r, -1, -1);
2245 FrameRect (&r);
2246 }
2247 }
2248
BmpHitTestProc(BmpPDataPtr pdata,PrimHitContext phc)2249 static Boolean BmpHitTestProc ( BmpPDataPtr pdata, PrimHitContext phc)
2250 {
2251 register ScalePtr dInfoPtr;
2252 BoxInfo box;
2253
2254 dInfoPtr = (ScalePtr)phc;
2255 MakeAlignBox ( pdata->pnt.x, pdata->pnt.y,
2256 (Int4)pdata->width * dInfoPtr->scaleX,
2257 (Int4)pdata->height * dInfoPtr->scaleY,
2258 0, 0, pdata->align, &box );
2259 if ( (box.left < dInfoPtr->worldWindow.right) &&
2260 (box.right > dInfoPtr->worldWindow.left) &&
2261 (box.top > dInfoPtr->worldWindow.bottom) &&
2262 (box.bottom < dInfoPtr->worldWindow.top) ) return TRUE;
2263 return FALSE;
2264 }
2265
BmpOffsetProc(BmpPDataPtr pdata,Int4 deltaX,Int4 deltaY)2266 static Boolean BmpOffsetProc ( BmpPDataPtr pdata, Int4 deltaX,
2267 Int4 deltaY )
2268 {
2269 pdata->pnt.x += deltaX;
2270 pdata->pnt.y += deltaY;
2271 return TRUE;
2272 }
2273
BmpGetLimitsProc(BmpPDataPtr pdata,Int4 scaleX,Int4 scaleY,BoxPtr pLimits)2274 static Boolean BmpGetLimitsProc ( BmpPDataPtr pdata, Int4 scaleX,
2275 Int4 scaleY, BoxPtr pLimits )
2276 {
2277 MakeAlignBox ( pdata->pnt.x, pdata->pnt.y,
2278 (Int4)pdata->width * scaleX,
2279 (Int4)pdata->height * scaleY,
2280 0, 0, pdata->align, pLimits );
2281 OutsetBox ( pLimits, scaleX<<2, scaleY<<2 );
2282 return TRUE;
2283 }
2284
2285 static PrimDef bmpPrimDef = {
2286 (PrimDrawProc) BmpDrawProc,
2287 (PrimHitTestProc) BmpHitTestProc,
2288 (PrimOffsetProc) BmpOffsetProc,
2289 (PrimCleanupProc) NULL,
2290 (PrimGetLimitsProc) BmpGetLimitsProc
2291 };
2292
2293 /*****************************************************************************
2294 *
2295 * AddBitmap (parent, pntX, pntY, width, height, data, align, primID)
2296 *
2297 *****************************************************************************/
2298
AddBitmap(SegmenT parent,Int4 pntX,Int4 pntY,Int2 width,Int2 height,Uint1Ptr bits,Int2 align,Uint2 primID)2299 PrimitivE AddBitmap (SegmenT parent, Int4 pntX, Int4 pntY, Int2 width,
2300 Int2 height, Uint1Ptr bits, Int2 align, Uint2 primID)
2301 {
2302 BmpPData data;
2303
2304 data.pnt.x = pntX;
2305 data.pnt.y = pntY;
2306 data.bits = bits;
2307 data.width = width;
2308 data.height = height;
2309 data.align = align;
2310 return AddPrimitive (&bmpPrimDef, parent, primID, (VoidPtr)&data,
2311 sizeof(BmpPData));
2312 }
2313
2314 #define SYMBOL_WIDTH 8
2315 #define SYMBOL_HEIGHT 8
2316
2317 static Uint1 rectSym [] = {
2318 0xFE, 0x82, 0x82, 0x82, 0x82, 0x82, 0xFE, 0x00
2319 };
2320 static Uint1 diamondSym [] = {
2321 0x10, 0x28, 0x44, 0x82, 0x44, 0x28, 0x10, 0x00
2322 };
2323 static Uint1 ovalSym [] = {
2324 0x38, 0x44, 0x82, 0x82, 0x82, 0x44, 0x38, 0x00
2325 };
2326 static Uint1 leftTriSym [] = {
2327 0x06, 0x1A, 0x62, 0x82, 0x62, 0x1A, 0x06, 0x00
2328 };
2329 static Uint1 rightTriSym [] = {
2330 0xC0, 0xB0, 0x8C, 0x82, 0x8C, 0xB0, 0xC0, 0x00
2331 };
2332 static Uint1 upTriSym [] = {
2333 0x10, 0x28, 0x28, 0x44, 0x44, 0x82, 0xFE, 0x00
2334 };
2335 static Uint1 downTriSym [] = {
2336 0xFE, 0x82, 0x44, 0x44, 0x28, 0x28, 0x10, 0x00
2337 };
2338 static Uint1 rectFillSym [] = {
2339 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0x00
2340 };
2341 static Uint1 diamondFillSym [] = {
2342 0x10, 0x38, 0x7C, 0xFE, 0x7C, 0x38, 0x10, 0x00
2343 };
2344 static Uint1 ovalFillSym [] = {
2345 0x38, 0x7C, 0xFE, 0xFE, 0xFE, 0x7C, 0x38, 0x00
2346 };
2347 static Uint1 leftTriFillSym [] = {
2348 0x06, 0x1E, 0x7E, 0xFE, 0x7E, 0x1E, 0x06, 0x00
2349 };
2350 static Uint1 rightTriFillSym [] = {
2351 0xC0, 0xF0, 0xFC, 0xFE, 0xFC, 0xF0, 0xC0, 0x00
2352 };
2353 static Uint1 upTriFillSym [] = {
2354 0x10, 0x38, 0x38, 0x7C, 0x7C, 0xFE, 0xFE, 0x00
2355 };
2356 static Uint1 downTriFillSym [] = {
2357 0xFE, 0xFE, 0x7C, 0x7C, 0x38, 0x38, 0x10, 0x00
2358 };
2359
2360 static Uint1Ptr symbolList [] = {
2361 rectSym, diamondSym, ovalSym, leftTriSym,
2362 rightTriSym, upTriSym, downTriSym,
2363 rectFillSym, diamondFillSym, ovalFillSym, leftTriFillSym,
2364 rightTriFillSym, upTriFillSym, downTriFillSym
2365 };
2366
2367 /*****************************************************************************
2368 *
2369 * AddSymbol (parent, pntX, pntY, symbol, fill, align, primID)
2370 *
2371 *****************************************************************************/
2372
AddSymbol(SegmenT parent,Int4 pntX,Int4 pntY,Int2 symbol,Boolean fill,Int2 align,Uint2 primID)2373 PrimitivE AddSymbol (SegmenT parent, Int4 pntX, Int4 pntY,
2374 Int2 symbol, Boolean fill, Int2 align, Uint2 primID)
2375
2376 {
2377 Int2 index;
2378
2379 if (symbol < RECT_SYMBOL || symbol > DOWN_TRIANGLE_SYMBOL) {
2380 Message (MSG_ERROR, "AddSymbol symbol out of range");
2381 return NULL;
2382 }
2383 index = symbol - (Int2)RECT_SYMBOL;
2384 if (fill) index += 7;
2385 return AddBitmap (parent, pntX, pntY, SYMBOL_WIDTH, SYMBOL_HEIGHT,
2386 symbolList [index], align, primID);
2387 }
2388
2389 /*****************************************************************************
2390 *
2391 * MARKER
2392 *
2393 *****************************************************************************/
2394 typedef struct markpdata {
2395 PntInfo pnt;
2396 Int2 length;
2397 Int2 orient;
2398 } MarkPData, PNTR MarkPDataPtr;
2399
MarkDrawProc(MarkPDataPtr pdata,PrimDrawContext pdc)2400 static void MarkDrawProc (MarkPDataPtr pdata, PrimDrawContext pdc)
2401 {
2402 register DrawInfoPtr dInfoPtr;
2403 Int4 x1, y1, x2, y2;
2404 Int4 curScale;
2405 Int4 len;
2406
2407 dInfoPtr = (DrawInfoPtr)pdc;
2408 curScale = dInfoPtr->scale.scaleX;
2409 len = (Int4)pdata->length * curScale;
2410 x1 = (dInfoPtr->scale.offsetX + pdata->pnt.x) / curScale;
2411 if ( ( (pdata->pnt.x+len) < dInfoPtr->scale.worldWindow.left) ||
2412 ( (pdata->pnt.x-len) > dInfoPtr->scale.worldWindow.right) ) return;
2413 curScale = dInfoPtr->scale.scaleY;
2414 len = (Int4)pdata->length * curScale;
2415 y1 = (dInfoPtr->scale.offsetY - pdata->pnt.y) / curScale;
2416 if ( ((pdata->pnt.y+len) < dInfoPtr->scale.worldWindow.bottom) ||
2417 ((pdata->pnt.y-len) > dInfoPtr->scale.worldWindow.top) ) return;
2418 switch (pdata->orient){
2419 case HORIZ_LEFT :
2420 x2 = x1; y2 = y1;
2421 x1 -= (Int4)pdata->length;
2422 break;
2423 case HORIZ_CENTER :
2424 x2 = x1+(Int4)pdata->length / 2; y2 = y1;
2425 x1 = x2 - (Int4)pdata->length;
2426 break;
2427 case HORIZ_RIGHT :
2428 x2 = x1 + (Int4)pdata->length; y2 = y1;
2429 break;
2430 case VERT_ABOVE :
2431 x2 = x1; y2 = y1 - (Int4)pdata->length;
2432 break;
2433 case VERT_MIDDLE :
2434 x2 = x1; y2 = y1 - (Int4)pdata->length / 2;
2435 y1 = y2 + (Int4)pdata->length;
2436 break;
2437 default:
2438 x2 = x1; y2 = y1;
2439 y1 += (Int4)pdata->length;
2440 }
2441 SetPrimAttribute (pdc, COLOR_ATT|STYLE_ATT|WIDTH_ATT|MODE_ATT);
2442 MoveTo ((Int2)x1, (Int2)y1);
2443 LineTo ((Int2)x2, (Int2)y2);
2444 if ( dInfoPtr->highlight != PLAIN_SEGMENT ) {
2445 WidePen((Int2)(((DrawInfoPtr)pdc)->primattrib->penwidth + 2));
2446 MoveTo ((Int2)x1, (Int2)y1);
2447 LineTo ((Int2)x2, (Int2)y2);
2448 }
2449 }
2450
MarkHitTestProc(MarkPDataPtr pdata,PrimHitContext phc)2451 static Boolean MarkHitTestProc ( MarkPDataPtr pdata, PrimHitContext phc)
2452 {
2453 register ScalePtr dInfoPtr;
2454 Int4 curScale;
2455 Int4 lenXY;
2456
2457 dInfoPtr = (ScalePtr)phc;
2458 switch (pdata->orient){
2459 case HORIZ_LEFT :
2460 case HORIZ_CENTER :
2461 case HORIZ_RIGHT :
2462 lenXY = pdata->pnt.y;
2463 if ( (lenXY < dInfoPtr->worldWindow.bottom) ||
2464 (lenXY > dInfoPtr->worldWindow.top )) return FALSE;
2465 curScale = dInfoPtr->scaleX;
2466 lenXY = (Int4)pdata->length * curScale;
2467 switch (pdata->orient){
2468 case HORIZ_LEFT :
2469 if ( (pdata->pnt.x < dInfoPtr->worldWindow.left) ||
2470 ((pdata->pnt.x - lenXY) > dInfoPtr->worldWindow.right))
2471 return FALSE;
2472 break;
2473 case HORIZ_CENTER :
2474 lenXY /= 2;
2475 if ( ((pdata->pnt.x + lenXY) < dInfoPtr->worldWindow.left) ||
2476 ((pdata->pnt.x - lenXY) > dInfoPtr->worldWindow.right))
2477 return FALSE;
2478 break;
2479 default:
2480 if ( ((pdata->pnt.x + lenXY) < dInfoPtr->worldWindow.left) ||
2481 ( pdata->pnt.x > dInfoPtr->worldWindow.right))
2482 return FALSE;
2483 }
2484 break;
2485 default:
2486 lenXY = pdata->pnt.x;
2487 if ( (lenXY < dInfoPtr->worldWindow.left) ||
2488 (lenXY > dInfoPtr->worldWindow.right )) return FALSE;
2489 curScale = dInfoPtr->scaleY;
2490 lenXY = (Int4)pdata->length * curScale;
2491 switch (pdata->orient){
2492 case VERT_ABOVE :
2493 if ( ((pdata->pnt.y + lenXY) < dInfoPtr->worldWindow.bottom) ||
2494 (pdata->pnt.y > dInfoPtr->worldWindow.top))
2495 return FALSE;
2496 break;
2497 case VERT_MIDDLE :
2498 lenXY /= 2;
2499 if ( ((pdata->pnt.y + lenXY) < dInfoPtr->worldWindow.bottom) ||
2500 ((pdata->pnt.y - lenXY) > dInfoPtr->worldWindow.top))
2501 return FALSE;
2502 break;
2503 default:
2504 if ( (pdata->pnt.y < dInfoPtr->worldWindow.bottom) ||
2505 ((pdata->pnt.y - lenXY) > dInfoPtr->worldWindow.top))
2506 return FALSE;
2507 break;
2508 }
2509 }
2510 return TRUE;
2511 }
2512
MarkOffsetProc(MarkPDataPtr pdata,Int4 deltaX,Int4 deltaY)2513 static Boolean MarkOffsetProc ( MarkPDataPtr pdata, Int4 deltaX,
2514 Int4 deltaY )
2515 {
2516 pdata->pnt.x += deltaX;
2517 pdata->pnt.y += deltaY;
2518 return TRUE;
2519 }
2520
MarkGetLimitsProc(MarkPDataPtr pdata,Int4 scaleX,Int4 scaleY,BoxPtr pLimits)2521 static Boolean MarkGetLimitsProc ( MarkPDataPtr pdata, Int4 scaleX,
2522 Int4 scaleY, BoxPtr pLimits )
2523 {
2524 LoadBox (pLimits, pdata->pnt.x, pdata->pnt.y, pdata->pnt.x, pdata->pnt.y);
2525 switch (pdata->orient){
2526 case HORIZ_LEFT :
2527 pLimits->left -= (Int4)pdata->length * scaleX;
2528 break;
2529 case HORIZ_CENTER :
2530 pLimits->left -= (Int4)pdata->length * scaleX / 2;
2531 pLimits->right += (Int4)pdata->length * scaleX / 2;
2532 break;
2533 case HORIZ_RIGHT :
2534 pLimits->right += (Int4)pdata->length * scaleX;
2535 break;
2536 case VERT_ABOVE :
2537 pLimits->top += (Int4)pdata->length * scaleY;
2538 break;
2539 case VERT_MIDDLE :
2540 pLimits->top += (Int4)pdata->length * scaleY / 2;
2541 pLimits->bottom -= (Int4)pdata->length * scaleY / 2;
2542 break;
2543 default:
2544 pLimits->bottom -= (Int4)pdata->length * scaleY;
2545 }
2546 OutsetBox ( pLimits, scaleX<<2, scaleY<<2 );
2547 return TRUE;
2548 }
2549
2550 static PrimDef markPrimDef = {
2551 (PrimDrawProc) MarkDrawProc,
2552 (PrimHitTestProc) MarkHitTestProc,
2553 (PrimOffsetProc) MarkOffsetProc,
2554 (PrimCleanupProc) NULL,
2555 (PrimGetLimitsProc) MarkGetLimitsProc
2556 };
2557
2558 /*****************************************************************************
2559 *
2560 * AddMarker (parent, pntX, pntY, length, orient, primID)
2561 *
2562 *****************************************************************************/
2563
AddMarker(SegmenT parent,Int4 pntX,Int4 pntY,Int2 length,Int2 orient,Uint2 primID)2564 PrimitivE AddMarker (SegmenT parent, Int4 pntX, Int4 pntY,
2565 Int2 length, Int2 orient, Uint2 primID)
2566 {
2567 MarkPData data;
2568
2569 data.pnt.x = pntX;
2570 data.pnt.y = pntY;
2571 data.length = length;
2572 data.orient = orient;
2573 return AddPrimitive (&markPrimDef, parent, primID, (VoidPtr)&data,
2574 sizeof(MarkPData));
2575 }
2576
2577 /*****************************************************************************
2578 *
2579 * TEXT LABEL
2580 *
2581 *****************************************************************************/
2582
2583 typedef struct lblpdata {
2584 PntInfo pnt;
2585 FonT font;
2586 Int2 width;
2587 Int2 height;
2588 Int2 align;
2589 Int2 offset;
2590 Char str;
2591 } LblPData, PNTR LblPDataPtr;
2592
2593
LblDrawProc(LblPDataPtr pdata,PrimDrawContext pdc)2594 static void LblDrawProc (LblPDataPtr pdata, PrimDrawContext pdc)
2595 {
2596 register DrawInfoPtr dInfoPtr;
2597 BoxInfo tmpBox;
2598 Int4 x, y;
2599 RecT r;
2600
2601 dInfoPtr = (DrawInfoPtr)pdc;
2602 MakeAlignBox ( pdata->pnt.x, pdata->pnt.y,
2603 (Int4)pdata->width * dInfoPtr->scale.scaleX,
2604 (Int4)pdata->height * dInfoPtr->scale.scaleY,
2605 pdata->offset * dInfoPtr->scale.scaleX,
2606 pdata->offset * dInfoPtr->scale.scaleY,
2607 pdata->align, &tmpBox );
2608 if ( (tmpBox.left > dInfoPtr->scale.worldWindow.right) ||
2609 (tmpBox.right < dInfoPtr->scale.worldWindow.left) ||
2610 (tmpBox.top < dInfoPtr->scale.worldWindow.bottom) ||
2611 (tmpBox.bottom > dInfoPtr->scale.worldWindow.top) ) return;
2612 x = (dInfoPtr->scale.offsetX + pdata->pnt.x) / dInfoPtr->scale.scaleX;
2613 y = (dInfoPtr->scale.offsetY - pdata->pnt.y) / dInfoPtr->scale.scaleY;
2614 MakeAlignRect ( (Int2)x, (Int2)y, pdata->width, pdata->height,
2615 pdata->offset, pdata->align, &r );
2616 SelectFont (pdata->font);
2617 SetPrimAttribute (pdc, COLOR_ATT|MODE_ATT);
2618 PaintStringEx(&pdata->str, r.left, (Nlm_Int2)(r.top + Ascent()));
2619 if ( dInfoPtr->highlight == OUTLINE_PRIMITIVE ){
2620 r.right ++; r.bottom ++;
2621 SetPrimAttribute (pdc, STYLE_ATT|WIDTH_ATT);
2622 FrameRect (&r);
2623 InsetRect (&r, -1, -1);
2624 FrameRect (&r);
2625 }
2626 }
2627
LblHitTestProc(LblPDataPtr pdata,PrimHitContext phc)2628 static Boolean LblHitTestProc (LblPDataPtr pdata, PrimHitContext phc )
2629 {
2630 register ScalePtr dInfoPtr;
2631 BoxInfo box;
2632
2633 dInfoPtr = (ScalePtr)phc;
2634 MakeAlignBox ( pdata->pnt.x, pdata->pnt.y,
2635 (Int4)pdata->width * dInfoPtr->scaleX,
2636 (Int4)pdata->height * dInfoPtr->scaleY,
2637 pdata->offset * dInfoPtr->scaleX,
2638 pdata->offset * dInfoPtr->scaleY,
2639 pdata->align, &box );
2640 if ( (box.left < dInfoPtr->worldWindow.right) &&
2641 (box.right > dInfoPtr->worldWindow.left) &&
2642 (box.top > dInfoPtr->worldWindow.bottom) &&
2643 ((box.bottom + (dInfoPtr->scaleY<<1)) < dInfoPtr->worldWindow.top) )
2644 return TRUE;
2645 return FALSE;
2646 }
2647
LblCleanupProc(LblPDataPtr pdata)2648 static void LblCleanupProc (LblPDataPtr pdata)
2649 {
2650 DeleteFont (pdata->font);
2651 }
2652
LblOffsetProc(LblPDataPtr pdata,Int4 deltaX,Int4 deltaY)2653 static Boolean LblOffsetProc (LblPDataPtr pdata, Int4 deltaX, Int4 deltaY)
2654 {
2655 pdata->pnt.x += deltaX;
2656 pdata->pnt.y += deltaY;
2657 return TRUE;
2658 }
2659
LblGetLimitsProc(LblPDataPtr pdata,Int4 scaleX,Int4 scaleY,BoxPtr pLimits)2660 static Boolean LblGetLimitsProc ( LblPDataPtr pdata, Int4 scaleX,
2661 Int4 scaleY, BoxPtr pLimits )
2662 {
2663 MakeAlignBox ( pdata->pnt.x, pdata->pnt.y,
2664 (Int4)pdata->width * scaleX,
2665 (Int4)pdata->height * scaleY,
2666 pdata->offset * scaleX,
2667 pdata->offset * scaleY,
2668 pdata->align, pLimits );
2669 OutsetBox ( pLimits, scaleX<<2, scaleY<<2 );
2670 return TRUE;
2671 }
2672
2673 static PrimDef lblPrimDef = {
2674 (PrimDrawProc) LblDrawProc,
2675 (PrimHitTestProc) LblHitTestProc,
2676 (PrimOffsetProc) LblOffsetProc,
2677 (PrimCleanupProc) LblCleanupProc,
2678 (PrimGetLimitsProc) LblGetLimitsProc
2679 };
2680
2681 /*****************************************************************************
2682 *
2683 * AddTextLabel (parent, pntX, pntY, string, font, offset, align, primID)
2684 *
2685 *****************************************************************************/
2686
Nlm_AddTextLabel(SegmenT parent,Int4 pntX,Int4 pntY,const Char * string,FonT font,Int2 offset,Int2 align,Uint2 primID)2687 PrimitivE Nlm_AddTextLabel (SegmenT parent, Int4 pntX, Int4 pntY,
2688 const Char* string, FonT font, Int2 offset,
2689 Int2 align, Uint2 primID )
2690 {
2691 size_t data_size = sizeof(LblPData) + Nlm_StringLen(string) + 1;
2692 LblPDataPtr dataPtr = (LblPDataPtr)MemNew( data_size );
2693 PrimitivE txtLabel;
2694
2695 dataPtr->pnt.x = pntX;
2696 dataPtr->pnt.y = pntY;
2697 Nlm_StringCpy(&(dataPtr->str), string);
2698 dataPtr->font = CopyFont (font);
2699 SelectFont (font);
2700 dataPtr->width = StringWidth (string) + 2;
2701 dataPtr->height = LineHeight () + 2;
2702 dataPtr->align = align;
2703 dataPtr->offset = offset;
2704 SelectFont (programFont);
2705 txtLabel = AddPrimitive (&lblPrimDef, parent, primID,
2706 (VoidPtr)dataPtr, (Int2)data_size);
2707 MemFree ( dataPtr );
2708 return txtLabel;
2709 }
2710
2711 /*****************************************************************************
2712 *
2713 * AddLabel (parent, pntX, pntY, string, size, offset, align, primID)
2714 *
2715 *****************************************************************************/
2716
AddLabel(SegmenT parent,Int4 pntX,Int4 pntY,const Char * string,Int2 size,Int2 offset,Int2 align,Uint2 primID)2717 PrimitivE AddLabel (SegmenT parent, Int4 pntX, Int4 pntY, const Char* string,
2718 Int2 size, Int2 offset, Int2 align, Uint2 primID)
2719 {
2720 FonT font;
2721 switch (size) {
2722 case SMALL_TEXT:
2723 if (smallFont == NULL) SetSmallFont ();
2724 font = smallFont;
2725 break;
2726 case MEDIUM_TEXT:
2727 if (mediumFont == NULL) SetMediumFont ();
2728 font = mediumFont;
2729 break;
2730 case LARGE_TEXT:
2731 if (largeFont == NULL) SetLargeFont ();
2732 font = largeFont;
2733 break;
2734 default :
2735 font = programFont;
2736 break;
2737 }
2738 return AddTextLabel (parent, pntX, pntY, string, font,
2739 offset, align, primID);
2740 }
2741
2742
2743 /*****************************************************************************
2744 *
2745 * OVAL
2746 *
2747 *****************************************************************************/
2748
2749 typedef struct {
2750 PntInfo pnt;
2751 Int4 radx;
2752 Int4 rady;
2753 Boolean fill;
2754 } OvalPData, PNTR OvalPDataPtr;
2755
2756
OvalDrawProc(OvalPDataPtr pdata,PrimDrawContext pdc)2757 static void OvalDrawProc(OvalPDataPtr pdata, PrimDrawContext pdc)
2758 {
2759 DrawInfoPtr dInfoPtr = (DrawInfoPtr)pdc;
2760 Int4 rad;
2761 Int4 tmp4;
2762 Int2 radx, rady;
2763 Int2 cx, cy;
2764 RecT oval_rect;
2765
2766 rad = pdata->radx;
2767 tmp4 = pdata->pnt.x;
2768 if ((tmp4-rad) > dInfoPtr->scale.worldWindow.right ||
2769 (tmp4+rad) < dInfoPtr->scale.worldWindow.left)
2770 return;
2771
2772 rad = pdata->rady;
2773 tmp4 = pdata->pnt.y;
2774 if ((tmp4+rad) < dInfoPtr->scale.worldWindow.bottom ||
2775 (tmp4-rad) > dInfoPtr->scale.worldWindow.top)
2776 return;
2777
2778 radx = (Int2)(pdata->radx / dInfoPtr->scale.scaleX);
2779 rady = (Int2)(pdata->rady / dInfoPtr->scale.scaleY);
2780 cx = (Int2)((dInfoPtr->scale.offsetX + pdata->pnt.x)
2781 / dInfoPtr->scale.scaleX);
2782 cy = (Int2)((dInfoPtr->scale.offsetY - pdata->pnt.y)
2783 / dInfoPtr->scale.scaleY);
2784 LoadRect(&oval_rect,
2785 (Int2)(cx - radx), (Int2)(cy - rady),
2786 (Int2)(cx + radx + 1), (Int2)(cy + rady + 1));
2787
2788 if ( pdata->fill ) {
2789 SetPrimAttribute(pdc, COLOR_ATT|SHADING_ATT|MODE_ATT);
2790 PaintOval(&oval_rect);
2791 }
2792 else {
2793 SetPrimAttribute(pdc, COLOR_ATT|STYLE_ATT|WIDTH_ATT|MODE_ATT);
2794 FrameOval(&oval_rect);
2795 }
2796
2797 switch ( dInfoPtr->highlight ) {
2798 case PLAIN_SEGMENT:
2799 break;
2800 case FILL_PRIMITIVE:
2801 if ( !pdata->fill ) {
2802 SetPrimAttribute (pdc, SHADING_ATT);
2803 PaintOval(&oval_rect);
2804 }
2805 break;
2806 default :
2807 SetPrimAttribute (pdc, STYLE_ATT|WIDTH_ATT);
2808 FrameRect(&oval_rect);
2809 InsetRect(&oval_rect, -1, -1);
2810 FrameRect(&oval_rect);
2811 }
2812 }
2813
2814
OvalHitTestProc(OvalPDataPtr pdata,PrimHitContext phc)2815 static Boolean OvalHitTestProc(OvalPDataPtr pdata, PrimHitContext phc)
2816 {
2817 ScalePtr dInfoPtr = (ScalePtr)phc;
2818 Int4 x,y;
2819 Int4 dx,dy;
2820 Int4 deltax, deltay;
2821 Int2 angle;
2822
2823 if ((pdata->pnt.x - pdata->radx) > dInfoPtr->worldWindow.right ||
2824 (pdata->pnt.x + pdata->radx) < dInfoPtr->worldWindow.left ||
2825 (pdata->pnt.y - pdata->rady) > dInfoPtr->worldWindow.top ||
2826 (pdata->pnt.y + pdata->rady) < dInfoPtr->worldWindow.bottom)
2827 return FALSE;
2828
2829 x = (dInfoPtr->worldWindow.right + dInfoPtr->worldWindow.left) / 2;
2830 y = (dInfoPtr->worldWindow.top + dInfoPtr->worldWindow.bottom) / 2;
2831 deltax = dInfoPtr->worldWindow.right - dInfoPtr->worldWindow.left;
2832 deltay = dInfoPtr->worldWindow.top - dInfoPtr->worldWindow.bottom;
2833 dx = x - pdata->pnt.x;
2834 dy = y - pdata->pnt.y;
2835 if (!dx && !dy)
2836 return TRUE;
2837 x = (dx > 0) ? dx : -dx;
2838 y = (dy > 0) ? dy : -dy;
2839 if (x > y)
2840 angle = atan100[y * 100 / x];
2841 else
2842 angle = 90 - atan100[x * 100 / y] ;
2843 dx = (Int4)MSin(90 + angle) * pdata->radx / 100L;
2844 dy = (Int4)MSin( angle) * pdata->rady / 100L;
2845
2846 return (Boolean)(dx + deltax > x && dy + deltay > y);
2847 }
2848
OvalOffsetProc(OvalPDataPtr pdata,Int4 deltaX,Int4 deltaY)2849 static Boolean OvalOffsetProc(OvalPDataPtr pdata, Int4 deltaX, Int4 deltaY)
2850 {
2851 pdata->pnt.x += deltaX;
2852 pdata->pnt.y += deltaY;
2853 return TRUE;
2854 }
2855
OvalGetLimitsProc(OvalPDataPtr pdata,Int4 scaleX,Int4 scaleY,BoxPtr pLimits)2856 static Boolean OvalGetLimitsProc(OvalPDataPtr pdata,
2857 Int4 scaleX, Int4 scaleY, BoxPtr pLimits)
2858 {
2859 Int4 xy = pdata->pnt.x;
2860 pLimits->left = xy - pdata->radx;
2861 pLimits->right = xy + pdata->radx;
2862 xy = pdata->pnt.y;
2863 pLimits->bottom = xy - pdata->rady;
2864 pLimits->top = xy + pdata->rady;
2865 OutsetBox(pLimits, scaleX<<2, scaleY<<2);
2866 return TRUE;
2867 }
2868
2869 static PrimDef ovalPrimDef = {
2870 (PrimDrawProc ) OvalDrawProc,
2871 (PrimHitTestProc ) OvalHitTestProc,
2872 (PrimOffsetProc ) OvalOffsetProc,
2873 (PrimCleanupProc ) NULL,
2874 (PrimGetLimitsProc) OvalGetLimitsProc
2875 };
2876
2877 /*****************************************************************************
2878 *
2879 * AddOval (parent, pntX, pntY, radius, fill, primID)
2880 *
2881 *****************************************************************************/
2882
AddOval(SegmenT parent,Int4 pntX,Int4 pntY,Int4 radiusX,Int4 radiusY,Boolean fill,Uint2 primID)2883 PrimitivE AddOval(SegmenT parent, Int4 pntX, Int4 pntY, Int4 radiusX,
2884 Int4 radiusY, Boolean fill, Uint2 primID)
2885 {
2886 OvalPData data;
2887
2888 data.pnt.x = pntX;
2889 data.pnt.y = pntY;
2890 data.radx = radiusX;
2891 data.rady = radiusY;
2892 data.fill = fill;
2893 return AddPrimitive(&ovalPrimDef, parent, primID, (VoidPtr)&data,
2894 sizeof(OvalPData));
2895 }
2896
2897
2898 /*****************************************************************************
2899 *
2900 * ARC
2901 *
2902 *****************************************************************************/
2903
2904 typedef struct arcpdata {
2905 BoxInfo box;
2906 PntInfo pnt;
2907 Int4 radx;
2908 Int4 rady;
2909 Int4 start;
2910 Int4 end;
2911 Boolean fill;
2912 } ArcPData, PNTR ArcPDataPtr;
2913
FrameArcProc(Int2 pNum,PoinT PNTR points)2914 static void FrameArcProc ( Int2 pNum, PoinT PNTR points )
2915 {
2916 Int2 i;
2917
2918 MoveTo ( points->x, points->y );
2919 points++;
2920 for (i=1; i<pNum; i++ ){
2921 LineTo ( points->x, points->y );
2922 points++;
2923 }
2924 }
2925
ArcDrawProc(ArcPDataPtr pdata,PrimDrawContext pdc)2926 static void ArcDrawProc (ArcPDataPtr pdata, PrimDrawContext pdc)
2927 {
2928 register DrawInfoPtr dInfoPtr;
2929 BoxInfo tmpBox;
2930 Int4 curScale;
2931 Int2 radx, rady;
2932 Int2 cx, cy;
2933 Int2 i,j,pNum;
2934 Int2 start, end;
2935 Int2 step;
2936 RecT r;
2937
2938 dInfoPtr = (DrawInfoPtr)pdc;
2939 tmpBox = pdata->box;
2940 if ( (tmpBox.left > dInfoPtr->scale.worldWindow.right) ||
2941 (tmpBox.right < dInfoPtr->scale.worldWindow.left) ||
2942 (tmpBox.top < dInfoPtr->scale.worldWindow.bottom) ||
2943 (tmpBox.bottom > dInfoPtr->scale.worldWindow.top) ) return;
2944 radx = (Int2)(pdata->radx / dInfoPtr->scale.scaleX);
2945 rady = (Int2)(pdata->rady / dInfoPtr->scale.scaleY);
2946 cx = (Int2)((dInfoPtr->scale.offsetX + pdata->pnt.x)
2947 / dInfoPtr->scale.scaleX);
2948 cy = (Int2)((dInfoPtr->scale.offsetY - pdata->pnt.y)
2949 / dInfoPtr->scale.scaleY);
2950 if ( radx < rady ) i = rady;
2951 else i = radx;
2952 if ( i < 10 ) step = 10;
2953 else if ( i < 30 ) step = 5;
2954 else if ( i < 60 ) step = 3;
2955 else step = 1;
2956 start = (Int2) (pdata->start / 1000);
2957 end = (Int2) (pdata->end / 1000);
2958 if ( end < start ) end += 360;
2959 polyPoints[0].x = cx;
2960 polyPoints[0].y = cy;
2961 pNum = 1;
2962 for (j=0; j<2; j++ ) {
2963 for ( i=MAX(0,start); (i<90) && (i<=end); i+= step){
2964 polyPoints[pNum].x = cx +
2965 (Int2)(((Int4)radx * (Int4)sin100[90-i]) / (Int4)100);
2966 polyPoints[pNum++].y = cy -
2967 (Int2)(((Int4)rady * (Int4)sin100[i]) / (Int4)100);
2968 }
2969 start -= 90; end -= 90;
2970 for ( i=MAX(0,start); (i<90) && (i<=end); i+= step){
2971 polyPoints[pNum].x = cx -
2972 (Int2)(((Int4)radx * (Int4)sin100[i]) / (Int4)100);
2973 polyPoints[pNum++].y = cy -
2974 (Int2)(((Int4)rady * (Int4)sin100[90-i]) / (Int4)100);
2975 }
2976 start -= 90; end -= 90;
2977 for ( i=MAX(0,start); (i<90) && (i<=end); i+= step){
2978 polyPoints[pNum].x = cx -
2979 (Int2)(((Int4)radx * (Int4)sin100[90-i]) / (Int4)100);
2980 polyPoints[pNum++].y = cy +
2981 (Int2)(((Int4)rady * (Int4)sin100[i]) / (Int4)100);
2982 }
2983 start -= 90; end -= 90;
2984 for ( i=MAX(0,start); (i<90) && (i<=end); i+= step){
2985 polyPoints[pNum].x = cx +
2986 (Int2)(((Int4)radx * (Int4)sin100[i]) / (Int4)100);
2987 polyPoints[pNum++].y = cy +
2988 (Int2)(((Int4)rady * (Int4)sin100[90-i]) / (Int4)100);
2989 }
2990 start -= 90; end -= 90;
2991 }
2992 if (pdata->fill) {
2993 SetPrimAttribute (pdc, COLOR_ATT|SHADING_ATT|MODE_ATT);
2994 } else {
2995 SetPrimAttribute (pdc, COLOR_ATT|STYLE_ATT|WIDTH_ATT|MODE_ATT);
2996 }
2997 if ( pdata->fill ) PaintPoly(pNum, polyPoints);
2998 else FrameArcProc ( (Int2)(pNum-1), &(polyPoints[1]));
2999 switch ( dInfoPtr->highlight ) {
3000 case PLAIN_SEGMENT:
3001 break;
3002 case FILL_PRIMITIVE:
3003 if ( pdata->fill == 0 ) {
3004 SetPrimAttribute (pdc, SHADING_ATT);
3005 PaintPoly(pNum, polyPoints);
3006 }
3007 break;
3008 default :
3009 curScale = dInfoPtr->scale.scaleX;
3010 r.left = (Int2)((dInfoPtr->scale.offsetX + tmpBox.left) / curScale);
3011 r.right = (Int2)((dInfoPtr->scale.offsetX + tmpBox.right) / curScale)+1;
3012 curScale = dInfoPtr->scale.scaleY;
3013 r.top = (Int2)((dInfoPtr->scale.offsetY - tmpBox.top) / curScale);
3014 r.bottom = (Int2)((dInfoPtr->scale.offsetY - tmpBox.bottom) / curScale)+1;
3015 SetPrimAttribute (pdc, STYLE_ATT|WIDTH_ATT);
3016 FrameRect (&r);
3017 InsetRect (&r, -1, -1);
3018 FrameRect (&r);
3019 }
3020 }
3021
ArcHitTestProc(ArcPDataPtr pdata,PrimHitContext phc)3022 static Boolean ArcHitTestProc ( ArcPDataPtr pdata, PrimHitContext phc)
3023 {
3024 register ScalePtr dInfoPtr;
3025
3026 dInfoPtr = (ScalePtr)phc;
3027 if ( (pdata->box.left < dInfoPtr->worldWindow.right) &&
3028 (pdata->box.right > dInfoPtr->worldWindow.left) &&
3029 (pdata->box.top > dInfoPtr->worldWindow.bottom) &&
3030 (pdata->box.bottom < dInfoPtr->worldWindow.top) ) return TRUE;
3031 return FALSE;
3032 }
3033
ArcOffsetProc(ArcPDataPtr pdata,Int4 deltaX,Int4 deltaY)3034 static Boolean ArcOffsetProc ( ArcPDataPtr pdata, Int4 deltaX,
3035 Int4 deltaY )
3036 {
3037 pdata->pnt.x += deltaX;
3038 pdata->pnt.y += deltaY;
3039 pdata->box.left += deltaX;
3040 pdata->box.right += deltaX;
3041 pdata->box.bottom += deltaY;
3042 pdata->box.top += deltaY;
3043 return TRUE;
3044 }
3045
ArcGetLimitsProc(ArcPDataPtr pdata,Int4 scaleX,Int4 scaleY,BoxPtr pLimits)3046 static Boolean ArcGetLimitsProc ( ArcPDataPtr pdata, Int4 scaleX,
3047 Int4 scaleY, BoxPtr pLimits )
3048 {
3049 *pLimits = pdata->box;
3050 return TRUE;
3051 }
3052
3053 static PrimDef arcPrimDef = {
3054 (PrimDrawProc) ArcDrawProc,
3055 (PrimHitTestProc) ArcHitTestProc,
3056 (PrimOffsetProc) ArcOffsetProc,
3057 (PrimCleanupProc) NULL,
3058 (PrimGetLimitsProc) ArcGetLimitsProc
3059 };
3060
3061 /*****************************************************************************
3062 *
3063 * AddArc (parent, pntX, pntY, radius, start, end, fill, primID)
3064 *
3065 *****************************************************************************/
3066
AddArc(SegmenT parent,Int4 pntX,Int4 pntY,Int4 radiusX,Int4 radiusY,Int4 start,Int4 end,Boolean fill,Uint2 primID)3067 PrimitivE AddArc (SegmenT parent, Int4 pntX, Int4 pntY, Int4 radiusX,
3068 Int4 radiusY, Int4 start, Int4 end, Boolean fill,
3069 Uint2 primID)
3070 {
3071 ArcPData data;
3072
3073 data.pnt.x = pntX;
3074 data.pnt.y = pntY;
3075 data.radx = radiusX;
3076 data.rady = radiusY;
3077 data.start = start;
3078 data.end = end;
3079 data.fill = fill;
3080 data.box.left = pntX - radiusX;
3081 data.box.right = pntX + radiusX;
3082 data.box.top = pntY + radiusY;
3083 data.box.bottom = pntY - radiusY;
3084 return AddPrimitive (&arcPrimDef, parent, primID, (VoidPtr)&data,
3085 sizeof(ArcPData));
3086 }
3087
3088 /*****************************************************************************
3089 *
3090 * POLYGON
3091 *
3092 *****************************************************************************/
3093 typedef struct polpdata {
3094 BoxInfo box;
3095 Int2 vernum;
3096 Int2 fill;
3097 PntInfo pnt;
3098 } PolyPData, PNTR PolyPDataPtr;
3099
PolyDrawProc(PolyPDataPtr pdata,PrimDrawContext pdc)3100 static void PolyDrawProc (PolyPDataPtr pdata, PrimDrawContext pdc)
3101 {
3102 register DrawInfoPtr dInfoPtr;
3103 PntPtr pPtr;
3104 BoxInfo tmpBox;
3105 Int4 curScale;
3106 RecT r;
3107 Int2 vernum;
3108 Int2 i;
3109
3110 dInfoPtr = (DrawInfoPtr)pdc;
3111 tmpBox = pdata->box;
3112 if ( (tmpBox.left > dInfoPtr->scale.worldWindow.right) ||
3113 (tmpBox.right < dInfoPtr->scale.worldWindow.left) ||
3114 (tmpBox.top < dInfoPtr->scale.worldWindow.bottom) ||
3115 (tmpBox.bottom > dInfoPtr->scale.worldWindow.top) ) return;
3116 if (pdata->fill) {
3117 SetPrimAttribute (pdc, COLOR_ATT|SHADING_ATT|MODE_ATT);
3118 } else {
3119 SetPrimAttribute (pdc, COLOR_ATT|STYLE_ATT|WIDTH_ATT|MODE_ATT);
3120 }
3121 vernum = pdata->vernum;
3122 pPtr = &(pdata->pnt);
3123 for ( i=0; i<vernum; i++ ){
3124 polyPoints[i].x = (Int2)((dInfoPtr->scale.offsetX + pPtr->x)
3125 / dInfoPtr->scale.scaleX);
3126 polyPoints[i].y = (Int2)((dInfoPtr->scale.offsetY - pPtr->y)
3127 / dInfoPtr->scale.scaleY);
3128 pPtr++;
3129 }
3130 if ( pdata->fill ) PaintPoly(vernum, polyPoints);
3131 else FramePoly(vernum, polyPoints);
3132 switch ( dInfoPtr->highlight ) {
3133 case PLAIN_SEGMENT:
3134 break;
3135 case FILL_PRIMITIVE:
3136 if ( pdata->fill == 0 ) {
3137 SetPrimAttribute (pdc, SHADING_ATT);
3138 PaintPoly(vernum, polyPoints);
3139 }
3140 break;
3141 default:
3142 curScale = dInfoPtr->scale.scaleX;
3143 r.left = (Int2)((dInfoPtr->scale.offsetX + tmpBox.left) / curScale);
3144 r.right = (Int2)((dInfoPtr->scale.offsetX + tmpBox.right) / curScale)+1;
3145 curScale = dInfoPtr->scale.scaleY;
3146 r.top = (Int2)((dInfoPtr->scale.offsetY - tmpBox.top) / curScale);
3147 r.bottom = (Int2)((dInfoPtr->scale.offsetY - tmpBox.bottom) / curScale)+1;
3148 SetPrimAttribute (pdc, STYLE_ATT|WIDTH_ATT);
3149 FrameRect (&r);
3150 InsetRect (&r, -1, -1);
3151 FrameRect (&r);
3152 }
3153 }
3154
PolyHitTestProc(PolyPDataPtr pdata,PrimHitContext phc)3155 static Boolean PolyHitTestProc ( PolyPDataPtr pdata, PrimHitContext phc)
3156 {
3157 register ScalePtr dInfoPtr;
3158
3159 dInfoPtr = (ScalePtr)phc;
3160 if ( (pdata->box.left < dInfoPtr->worldWindow.right) &&
3161 (pdata->box.right > dInfoPtr->worldWindow.left) &&
3162 (pdata->box.top > dInfoPtr->worldWindow.bottom) &&
3163 (pdata->box.bottom < dInfoPtr->worldWindow.top) ) return TRUE;
3164 return FALSE;
3165 }
3166
PolyOffsetProc(PolyPDataPtr pdata,Int4 deltaX,Int4 deltaY)3167 static Boolean PolyOffsetProc ( PolyPDataPtr pdata, Int4 deltaX,
3168 Int4 deltaY )
3169 {
3170 PntPtr pPtr;
3171 Int2 vernum;
3172 Int2 i;
3173
3174 pdata->box.left += deltaX;
3175 pdata->box.right += deltaX;
3176 pdata->box.top += deltaY;
3177 pdata->box.bottom += deltaY;
3178 vernum = pdata->vernum;
3179 pPtr = &(pdata->pnt);
3180 for ( i=0; i<vernum; i++ ){
3181 pPtr->x += deltaX;
3182 pPtr->y += deltaY;
3183 pPtr++;
3184 }
3185 return TRUE;
3186 }
3187
PolyGetLimitsProc(PolyPDataPtr pdata,Int4 scaleX,Int4 scaleY,BoxPtr pLimits)3188 static Boolean PolyGetLimitsProc ( PolyPDataPtr pdata, Int4 scaleX,
3189 Int4 scaleY, BoxPtr pLimits )
3190 {
3191 *pLimits = pdata->box;
3192 OutsetBox ( pLimits, scaleX<<2, scaleY<<2 );
3193 return TRUE;
3194 }
3195
3196 static PrimDef polyPrimDef = {
3197 (PrimDrawProc) PolyDrawProc,
3198 (PrimHitTestProc) PolyHitTestProc,
3199 (PrimOffsetProc) PolyOffsetProc,
3200 (PrimCleanupProc) NULL,
3201 (PrimGetLimitsProc) PolyGetLimitsProc
3202 };
3203
3204 /*****************************************************************************
3205 *
3206 * AddPolygon (parent, vernum, points, fill, primID)
3207 *
3208 *****************************************************************************/
3209
AddPolygon(SegmenT parent,Int2 vernum,PntPtr points,Boolean fill,Uint2 primID)3210 PrimitivE AddPolygon (SegmenT parent, Int2 vernum, PntPtr points,
3211 Boolean fill, Uint2 primID)
3212 {
3213 PrimitivE poly = NULL;
3214 PolyPDataPtr dataPtr;
3215 PntPtr pPtr;
3216 Int2 i;
3217
3218 if ( (vernum > 1) && (vernum <= 32) && (points != NULL) ){
3219 dataPtr = (PolyPDataPtr)MemNew(sizeof(PolyPData) + vernum*sizeof(PntInfo));
3220 dataPtr->vernum = vernum;
3221 dataPtr->fill = (Int2)fill;
3222 LoadBox ( &(dataPtr->box), INT4_MAX, INT4_MIN, INT4_MIN, INT4_MAX );
3223 pPtr = &(dataPtr->pnt);
3224 for ( i=0; i<vernum; i++ ){
3225 pPtr->x = points[i].x;
3226 if ( dataPtr->box.left > pPtr->x ) dataPtr->box.left = pPtr->x;
3227 if ( dataPtr->box.right < pPtr->x ) dataPtr->box.right = pPtr->x;
3228 pPtr->y = points[i].y;
3229 if ( dataPtr->box.top < pPtr->y ) dataPtr->box.top = pPtr->y;
3230 if ( dataPtr->box.bottom > pPtr->y ) dataPtr->box.bottom = pPtr->y;
3231 pPtr++;
3232 }
3233 poly = AddPrimitive (&polyPrimDef, parent, primID, (VoidPtr)dataPtr,
3234 (Int2)(sizeof(PolyPData) + vernum*sizeof(PntInfo)));
3235 MemFree ( dataPtr );
3236 }
3237 return poly;
3238 }
3239
3240 /*****************************************************************************
3241 *
3242 * DrawSegment (seg, drawinfo )
3243 * Draws a segment, recursively tracking attributes
3244 *
3245 *****************************************************************************/
3246
Nlm_DrawSegment(SegPPtr seg,Nlm_DrawInfoPtr drawinfoPtr)3247 extern void Nlm_DrawSegment (SegPPtr seg, Nlm_DrawInfoPtr drawinfoPtr )
3248 {
3249 BasePPtr item;
3250 DrawInfo drawinfo;
3251 RecT r;
3252 Int1 highlight;
3253 Int1 highlightPrim;
3254
3255 if (seg != NULL && drawinfoPtr != NULL) {
3256 drawinfo = *drawinfoPtr;
3257 drawinfo.primattrib = &blackAttPData;
3258 if (seg->base.code == SEGMENT || seg->base.code == PICTURE) {
3259 if (seg->seg.maxscale == 0 ||
3260 seg->seg.maxscale >=
3261 MAX (drawinfo.scale.scaleX, drawinfo.scale.scaleY)) {
3262 if ( (seg->seg.box.left <= drawinfo.scale.worldWindow.right) &&
3263 (seg->seg.box.right >= drawinfo.scale.worldWindow.left) &&
3264 (seg->seg.box.top >= drawinfo.scale.worldWindow.bottom) &&
3265 (seg->seg.box.bottom <= drawinfo.scale.worldWindow.top) ){
3266 if (seg->seg.visible) {
3267 SetPrimAttribute ( (Nlm_PrimDrawContext)&drawinfo, (Uint1)0xFF );
3268 if ( !drawinfo.checked ) {
3269 if ((seg->seg.box.left >= drawinfo.scale.worldWindow16.left) &&
3270 (seg->seg.box.right <= drawinfo.scale.worldWindow16.right) &&
3271 (seg->seg.box.top <= drawinfo.scale.worldWindow16.top) &&
3272 (seg->seg.box.bottom >= drawinfo.scale.worldWindow16.bottom))
3273 drawinfo.checked = TRUE;
3274 }
3275 if ( seg->seg.highlight != PLAIN_SEGMENT ) {
3276 highlight = seg->seg.highlight;
3277 } else {
3278 highlight = drawinfo.highlight;
3279 }
3280 switch ( highlight ) {
3281 case FRAME_CONTENTS:
3282 highlightPrim = FRAME_PRIMITIVE;
3283 break;
3284 case FILL_CONTENTS:
3285 highlightPrim = FILL_PRIMITIVE;
3286 break;
3287 case OUTLINE_CONTENTS:
3288 highlightPrim = OUTLINE_PRIMITIVE;
3289 break;
3290 default:
3291 highlightPrim = PLAIN_PRIMITIVE;
3292 }
3293 item = seg->seg.head;
3294 while (item != NULL) {
3295 switch (item->code) {
3296 case GENERIC :
3297 drawinfo.primattrib = &(((Nlm_GenPPtr)item)->att);
3298 drawinfo.highlight = ((Nlm_GenPPtr)item)->highlight;
3299 if ( drawinfo.highlight == PLAIN_PRIMITIVE ) {
3300 drawinfo.highlight = highlightPrim;
3301 }
3302 DrawPrimitive (item, &drawinfo );
3303 break;
3304 case PICTURE :
3305 Message (MSG_ERROR, "DrawSegment child is a picture");
3306 break;
3307 case SEGMENT :
3308 drawinfo.highlight = highlight;
3309 Nlm_DrawSegment ((SegPPtr)item, &drawinfo);
3310 break;
3311 default :
3312 Message (MSG_ERROR, "DrawSegment child is unknown");
3313 }
3314 item = item->next;
3315 }
3316 if ( seg->seg.highlight != PLAIN_SEGMENT ) {
3317 drawinfo.primattrib = &blackAttPData;
3318 SetPrimAttribute ( (Nlm_PrimDrawContext)&drawinfo, 0xFF );
3319 MapWorldBoxToRect ( &r, &(seg->seg.box), &(drawinfo.scale) );
3320 switch (seg->seg.highlight) {
3321 case FRAME_SEGMENT :
3322 FrameRect (&r);
3323 break;
3324 case FILL_SEGMENT :
3325 PaintRect (&r);
3326 break;
3327 case OUTLINE_SEGMENT :
3328 InsetRect (&r, -4, -4);
3329 FrameRect (&r);
3330 InsetRect (&r, 1, 1);
3331 FrameRect (&r);
3332 InsetRect (&r, 2, 2);
3333 drawinfo.primattrib = &whiteAttPData;
3334 SetPrimAttribute ( (Nlm_PrimDrawContext)&drawinfo, 0xFF );
3335 FrameRect (&r);
3336 }
3337 }
3338 }
3339 }
3340 }
3341 drawinfoPtr->curattrib = drawinfo.curattrib;
3342 } else {
3343 Message (MSG_ERROR, "DrawSegment argument not a segment or picture");
3344 }
3345 }
3346 }
3347
3348
3349 /*****************************************************************************
3350 *
3351 * SENTINEL RECTANGLE
3352 *
3353 *****************************************************************************/
3354
3355 typedef struct sntrecpdata {
3356 BoxInfo box;
3357 SntOnDrawProc callback;
3358 BigScalar calldata;
3359 SntOnCleanupProc cleanup;
3360 } SntRecPData, PNTR SntRecPDataPtr;
3361
3362
SntRecDrawProc(SntRecPDataPtr pdata,PrimDrawContext pdc)3363 static void SntRecDrawProc(SntRecPDataPtr pdata, PrimDrawContext pdc)
3364 {
3365 BoxPtr primBoxPtr = &pdata->box;
3366 BoxPtr drawBoxPtr = &((DrawInfoPtr)pdc)->scale.worldWindow;
3367
3368 if ( (primBoxPtr->left > drawBoxPtr->right ) ||
3369 (primBoxPtr->right < drawBoxPtr->left ) ||
3370 (primBoxPtr->top < drawBoxPtr->bottom) ||
3371 (primBoxPtr->bottom > drawBoxPtr->top ) )
3372 return;
3373
3374 if ( pdata->callback )
3375 (*pdata->callback)( pdata->calldata, pdc );
3376 }
3377
SntRecHitTestProc(SntRecPDataPtr pdata,PrimHitContext phc)3378 static Boolean SntRecHitTestProc(SntRecPDataPtr pdata, PrimHitContext phc)
3379 {
3380 BoxPtr primBoxPtr = &pdata->box;
3381 BoxPtr drawBoxPtr = &((ScalePtr)phc)->worldWindow;
3382
3383 return (Boolean)((primBoxPtr->left < drawBoxPtr->right ) &&
3384 (primBoxPtr->right > drawBoxPtr->left ) &&
3385 (primBoxPtr->top > drawBoxPtr->bottom) &&
3386 (primBoxPtr->bottom < drawBoxPtr->top ));
3387 }
3388
SntRecCleanupProc(SntRecPDataPtr pdata)3389 static void SntRecCleanupProc (SntRecPDataPtr pdata)
3390 {
3391 if ( pdata->cleanup )
3392 (*pdata->cleanup)( pdata->calldata );
3393 }
3394
SntRecOffsetProc(SntRecPDataPtr pdata,Int4 deltaX,Int4 deltaY)3395 static Boolean SntRecOffsetProc(SntRecPDataPtr pdata, Int4 deltaX, Int4 deltaY)
3396 {
3397 BoxPtr primBoxPtr = &pdata->box;
3398
3399 primBoxPtr->left += deltaX;
3400 primBoxPtr->right += deltaX;
3401 primBoxPtr->top += deltaY;
3402 primBoxPtr->bottom += deltaY;
3403
3404 return TRUE;
3405 }
3406
SntRecGetLimitsProc(SntRecPDataPtr pdata,Int4 scaleX,Int4 scaleY,BoxPtr pLimits)3407 static Boolean SntRecGetLimitsProc(SntRecPDataPtr pdata,
3408 Int4 scaleX, Int4 scaleY, BoxPtr pLimits)
3409 {
3410 *pLimits = pdata->box;
3411 OutsetBox(pLimits, scaleX<<2, scaleY<<2);
3412 return TRUE;
3413 }
3414
ChangeSentinelRectangle(PrimitivE prim,Int4 left,Int4 top,Int4 right,Int4 bottom)3415 extern void ChangeSentinelRectangle (PrimitivE prim, Int4 left, Int4 top, Int4 right, Int4 bottom)
3416
3417 {
3418 SntRecPDataPtr pdata;
3419
3420 if (prim == NULL) return;
3421 pdata = (SntRecPDataPtr) &(((GenPPtr) prim)->data);
3422 pdata->box.left = left;
3423 pdata->box.top = top;
3424 pdata->box.right = right;
3425 pdata->box.bottom = bottom;
3426 }
3427
3428 static PrimDef sntrecPrimDef = {
3429 (PrimDrawProc) SntRecDrawProc,
3430 (PrimHitTestProc) SntRecHitTestProc,
3431 (PrimOffsetProc) SntRecOffsetProc,
3432 (PrimCleanupProc) SntRecCleanupProc,
3433 (PrimGetLimitsProc) SntRecGetLimitsProc
3434 };
3435
3436 /*****************************************************************************
3437 *
3438 * AddSntRectangle(parent, left,top,right,bottom, callback,calldata, primID)
3439 *
3440 *****************************************************************************/
AddSntRectangle(SegmenT parent,Int4 left,Int4 top,Int4 right,Int4 bottom,SntOnDrawProc callback,BigScalar calldata,SntOnCleanupProc cleanup,Uint2 primID)3441 extern PrimitivE AddSntRectangle(SegmenT parent,
3442 Int4 left, Int4 top, Int4 right, Int4 bottom,
3443 SntOnDrawProc callback, BigScalar calldata,
3444 SntOnCleanupProc cleanup, Uint2 primID)
3445 {
3446 SntRecPData data;
3447 Int4 swap;
3448
3449 if (left > right) {
3450 swap = left;
3451 left = right;
3452 right = swap;
3453 }
3454 if (bottom > top) {
3455 swap = bottom;
3456 bottom = top;
3457 top = swap;
3458 }
3459 data.box.left = left;
3460 data.box.top = top;
3461 data.box.right = right;
3462 data.box.bottom = bottom;
3463 data.callback = callback;
3464 data.calldata = calldata;
3465 data.cleanup = cleanup;
3466 return AddPrimitive(&sntrecPrimDef, parent, primID, (VoidPtr)&data,
3467 sizeof(SntRecPData));
3468 }
3469
3470