NCBI C Toolkit Cross Reference

C/vibrant/ncbidraw.c


  1 /*   ncbidraw.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:  ncbidraw.c
 27 *
 28 * Author:  Jonathan Kans, Denis Vakatov
 29 *
 30 * Version Creation Date:   1/1/91
 31 *
 32 * $Revision: 6.45 $
 33 *
 34 * File Description: 
 35 *       Vibrant drawing functions.
 36 *
 37 * Modifications:  
 38 * --------------------------------------------------------------------------
 39 *
 40 * ==========================================================================
 41 */
 42 
 43 #include <vibtypes.h>
 44 #include <vibincld.h>
 45 
 46 #ifdef VAR_ARGS
 47 #  include <varargs.h>
 48 #else
 49 #  include <stdarg.h>
 50 #endif
 51 
 52 #ifdef WIN_GIF
 53 #  include <gifgen.h>
 54 #  ifdef Nlm_RgnTool
 55 #    undef Nlm_RgnTool 
 56 #  endif
 57 #  ifdef Nlm_RectTool
 58 #    undef Nlm_RectTool 
 59 #  endif
 60 #  define Nlm_RectTool Nlm_RecT
 61 #  ifdef WIN_MOTIF
 62 #    undef WIN_MOTIF
 63 #    ifdef WIN_X
 64 #      undef WIN_X
 65 #    endif
 66 #    define Nlm_RgnTool Nlm_VoidPtr
 67 #  endif
 68 #  ifdef WIN_MAC
 69 #    undef WIN_MAC
 70 #    define Nlm_RgnTool Handle
 71 #  endif
 72 #  ifdef WIN_MSWIN
 73 #    undef WIN_MSWIN
 74 #    define Nlm_RgnTool HANDLE
 75 #  endif
 76 #else  /* WIN_GIF */
 77 typedef struct gdImageStruct { void* dummy; } gdImage;
 78 #endif /* WIN_GIF */
 79 
 80 #if defined(WIN_X) && !defined(__hpux)
 81 #include <X11/Xmu/Drawing.h>
 82 #endif
 83 
 84 Nlm_Boolean  Nlm_nowPrinting = FALSE;
 85 
 86 #ifdef WIN_MAC
 87 #ifdef __MWERKS__
 88 #include "MoreCarbonAccessors.h"
 89 #else
 90 #define GetPortAndCall_(function, arg)           \
 91     do {                                          \
 92         GrafPtr port_;                            \
 93         GetPort(&port_);                          \
 94         function(GetWindowFromPort(port_), (arg));  \
 95     } while (0)
 96 #define InvalRect(rect)  GetPortAndCall_(InvalWindowRect, (rect))
 97 #define InvalRgn(rgn)    GetPortAndCall_(InvalWindowRgn,  (rgn ))
 98 #define ValidRect(rect)  GetPortAndCall_(ValidWindowRect, (rect))
 99 #define ValidRgn(rgn)    GetPortAndCall_(ValidWindowRgn,  (rgn ))
100 #endif
101 #endif
102 
103 #ifdef WIN_MAC
104 #ifdef WIN_MAC_QUARTZ
105 CFMutableArrayRef Nlm_QContextStack = 0;
106 static void Nlm_PushQContext( CGContextRef ctx )
107 {
108   if (!Nlm_QContextStack)
109     Nlm_QContextStack = CFArrayCreateMutable (NULL, 0, NULL);
110   CFArrayAppendValue (Nlm_QContextStack, ctx);
111 }
112 static CGContextRef Nlm_PeekQContext (void)
113 {
114   if (!Nlm_QContextStack)
115     return NULL;
116   
117   CFIndex count = CFArrayGetCount (Nlm_QContextStack);
118   return count ? (CGContextRef)CFArrayGetValueAtIndex (Nlm_QContextStack, count - 1) : NULL;
119 }
120 static CGContextRef Nlm_PopQContext (void)
121 {
122   if (!Nlm_QContextStack)
123     return NULL;
124   
125   void *ret = Nlm_PeekQContext();
126   CFIndex count = CFArrayGetCount (Nlm_QContextStack);
127   if (count)
128     CFArrayRemoveValueAtIndex (Nlm_QContextStack, count - 1);
129   return ret;
130 }
131 
132 WindowRef Nlm_QWindow = 0;
133 Nlm_QuartzColor Nlm_QuartzForeColor;
134 Nlm_QuartzColor Nlm_QuartzBackColor;
135 Nlm_Boolean  Nlm_hasColorQD = TRUE;
136 #else
137 RGBColor     Nlm_RGBforeColor;
138 RGBColor     Nlm_RGBbackColor;
139 Nlm_Boolean  Nlm_hasColorQD = FALSE;
140 #endif
141 #endif
142 
143 #ifdef WIN_MSWIN
144 #define ATT_PENSTYLE  1
145 #define ATT_PENWIDTH  2
146 #define ATT_PATTERN   4
147 HWND         Nlm_currentHWnd;
148 HDC          Nlm_currentHDC;
149 #endif
150 
151 #ifdef WIN_X
152 Display      *Nlm_currentXDisplay;
153 int          Nlm_currentXScreen;
154 Window       Nlm_currentXWindow;
155 GC           Nlm_currentXGC;
156 Nlm_Uint4    Nlm_XbackColor;
157 Nlm_Uint4    Nlm_XforeColor;
158 Nlm_Int2     Nlm_XOffset;
159 Nlm_Int2     Nlm_YOffset;
160 Nlm_RegioN   Nlm_clpRgn;
161 Nlm_Boolean  Nlm_hasColor = FALSE;
162 #endif
163 
164 #ifdef WIN_GIF
165 #define      GIF_SOLID   0
166 #define      GIF_DASHED  1
167 static gdImagePtr  Nlm_currentGIF  = NULL;
168 static int         Nlm_curGIFColor = 1;
169 static int         Nlm_curGIFLType = GIF_SOLID;
170 static gdFontPtr   Nlm_curGIFFont  = NULL;
171 static Nlm_PoinT   Nlm_curGIFPoint = {0,0};
172 #endif
173 
174 Nlm_RegioN   Nlm_updateRgn;
175 Nlm_RecT     Nlm_updateRect;
176 
177 Nlm_Int2     Nlm_stdAscent;
178 Nlm_Int2     Nlm_stdDescent;
179 Nlm_Int2     Nlm_stdLeading;
180 Nlm_Int2     Nlm_stdFontHeight;
181 Nlm_Int2     Nlm_stdLineHeight;
182 Nlm_Int2     Nlm_stdCharWidth;
183 
184 Nlm_FonT     Nlm_systemFont = NULL;
185 Nlm_FonT     Nlm_programFont = NULL;
186 
187 #define COPY_MODE   1
188 #define MERGE_MODE  2
189 #define INVERT_MODE 3
190 #define ERASE_MODE  4
191 
192 static Nlm_Int2    currentMode = COPY_MODE;
193 
194 static Nlm_FonT    Nlm_fontList = NULL;
195 static Nlm_FonT    Nlm_fontInUse = NULL;
196 
197 #ifndef WIN_GIF
198 static Nlm_RegioN  Nlm_scrollRgn;
199 #endif
200 
201 #ifdef WIN_MAC
202 static Nlm_Byte  whitePat [] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
203 static Nlm_Byte  ltGrayPat [] = {0x88, 0x22, 0x88, 0x22, 0x88, 0x22, 0x88, 0x22};
204 static Nlm_Byte  grayPat [] = {0xAA, 0x55, 0xAA, 0x55, 0xAA, 0x55, 0xAA, 0x55};
205 static Nlm_Byte  dkGrayPat [] = {0x77, 0xDD, 0x77, 0xDD, 0x77, 0xDD, 0x77, 0xDD};
206 static Nlm_Byte  blackPat [] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
207 
208 static Nlm_Byte  dotPat [] = {0xAA, 0x55, 0xAA, 0x55, 0xAA, 0x55, 0xAA, 0x55};
209 static Nlm_Byte  dashPat [] = {0xCC, 0xCC, 0x33, 0x33, 0xCC, 0xCC, 0x33, 0x33};
210 #endif
211 
212 #ifdef WIN_MSWIN
213 static DWORD       dash_gap[2];
214 static Nlm_Int2    currentPenStyle = PS_SOLID;
215 static Nlm_Int2    currentPenWidth = 1;
216 static void        *currentPattern = NULL;
217 static COLORREF    prevColor = 12346;
218 static Nlm_Int2    prevPenStyle = -1;
219 static Nlm_Int2    prevPenWidth = -1;
220 static void        *prevPattern = NULL;
221 static HDC         prevPenHDC = NULL;
222 
223 static COLORREF    blackColor;
224 static COLORREF    redColor;
225 static COLORREF    greenColor;
226 static COLORREF    blueColor;
227 static COLORREF    cyanColor;
228 static COLORREF    magentaColor;
229 static COLORREF    yellowColor;
230 static COLORREF    whiteColor;
231 
232 static Nlm_Uint2   blackPat [] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
233 static Nlm_Uint2   dkGrayPat [] = {0x88, 0x22, 0x88, 0x22, 0x88, 0x22, 0x88, 0x22};
234 static Nlm_Uint2   grayPat [] = {0xAA, 0x55, 0xAA, 0x55, 0xAA, 0x55, 0xAA, 0x55};
235 static Nlm_Uint2   ltGrayPat [] = {0x77, 0xDD, 0x77, 0xDD, 0x77, 0xDD, 0x77, 0xDD};
236 static Nlm_Uint2   whitePat [] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
237 
238 static Nlm_Uint2   dotPat [] = {0xAA, 0x55, 0xAA, 0x55, 0xAA, 0x55, 0xAA, 0x55};
239 static Nlm_Uint2   dashPat [] = {0xCC, 0xCC, 0x33, 0x33, 0xCC, 0xCC, 0x33, 0x33};
240 
241 static HPEN        hBlackPen;
242 static HPEN        hNullPen;
243 static HPEN        hWhitePen;
244 static HBRUSH      hBlackBrush;
245 static HBRUSH      hDkGrayBrush;
246 static HBRUSH      hGrayBrush;
247 static HBRUSH      hHollowBrush;
248 static HBRUSH      hLtGrayBrush;
249 static HBRUSH      hNullBrush;
250 static HBRUSH      hWhiteBrush;
251 static HFONT       hAnsiFixedFont;
252 static HFONT       hAnsiVarFont;
253 static HFONT       hDeviceDefaultFont;
254 static HFONT       hOemFixedFont;
255 static HFONT       hSystemFont;
256 static HFONT       hSystemFixedFont;
257 static HFONT       hDefaultGuiFont;
258 
259 static TEXTMETRIC  textMetrics;
260 
261 static COLORREF    winTextColor;
262 static COLORREF    winBkColor;
263 
264 #endif
265 
266 #ifdef WIN_X
267 static XFontStruct  *currentFont;
268 static Pixmap       currentPixmap = 0;
269 static Nlm_PoinT    currentPoint;
270 static Nlm_Uint4    currentBkColor;
271 static Nlm_Uint4    currentFgColor;
272 static int          currentFunction = GXcopy;
273 static int          currentFillStyle = FillOpaqueStippled;
274 
275 static Nlm_Uint4    blackColor;
276 static Nlm_Uint4    redColor;
277 static Nlm_Uint4    greenColor;
278 static Nlm_Uint4    blueColor;
279 static Nlm_Uint4    cyanColor;
280 static Nlm_Uint4    magentaColor;
281 static Nlm_Uint4    yellowColor;
282 static Nlm_Uint4    whiteColor;
283 
284 static XFontStruct  fontInfo;
285 static Nlm_Uint1    flip [256];
286 
287 static Nlm_RgnTool  emptyRgn;
288 
289 #define ULTRA_SPARC_X_SERVER_BUG
290 #ifdef ULTRA_SPARC_X_SERVER_BUG
291 /* Attention! This looks as an X-server(not X-client) bug;  it means
292  * that all X applications intended to run on an Ultra-SPARC's X-server
293  * must be compiled with this option, no matter where the X-client
294  * was built and run on(e.g. SGI, Linux, etc.)
295  */
296 void Nlm_XSetForeground(Display *display, GC gc, unsigned long color) {
297   if (currentFillStyle == FillOpaqueStippled) {
298     XSetFillStyle(Nlm_currentXDisplay, Nlm_currentXGC, FillSolid);
299     XSetFillStyle(Nlm_currentXDisplay, Nlm_currentXGC, FillOpaqueStippled);
300   }
301   XSetForeground(display, gc, color);
302 }
303 #define XSetForeground Nlm_XSetForeground
304 #endif
305 
306 #endif /* WIN_X */
307 
308 #if defined(WIN_X) || defined(WIN_GIF)
309 static Nlm_Uint1 whitePat []= {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
310 static Nlm_Uint1 ltGrayPat[]= {0x88, 0x22, 0x88, 0x22, 0x88, 0x22, 0x88, 0x22};
311 static Nlm_Uint1 grayPat  []= {0xAA, 0x55, 0xAA, 0x55, 0xAA, 0x55, 0xAA, 0x55};
312 static Nlm_Uint1 dkGrayPat[]= {0x77, 0xDD, 0x77, 0xDD, 0x77, 0xDD, 0x77, 0xDD};
313 static Nlm_Uint1 blackPat []= {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
314 #endif /* WIN_X | WIN_GIF */
315 
316 #ifdef WIN_MAC
317 #ifdef WIN_MAC_QUARTZ
318 extern  void  Nlm_SetPort (CGContextRef ctx)
319 {
320   if (Nlm_PeekQContext()) {
321     CGContextSynchronize(Nlm_PeekQContext());
322     CGContextRelease(Nlm_PeekQContext());
323     Nlm_PopQContext();
324   }
325   
326   if (ctx)
327   {
328         Nlm_PushQContext(ctx);
329         CGContextRetain(Nlm_PeekQContext());
330   }
331 // QUARTZ_FIXME: some of this might be useful, somehow
332 //  if (grafptr != 0) {
333 //    CGAffineTransform textTransform;
334 //    
335 //    GetPortBounds(grafptr, &pBounds);
336 //    pHeight = pBounds.bottom - pBounds.top;
337 //    QDBeginCGContext(grafptr, &Nlm_PeekQContext());
338 //    CGContextTranslateCTM(Nlm_PeekQContext(), 0, pHeight);
339 //    CGContextScaleCTM(Nlm_PeekQContext(), 1.0f, -1.0f);
340 //    
341 //    textTransform = CGAffineTransformMakeScale(1.0f, -1.0f);
342 //    CGContextSetTextMatrix(Nlm_PeekQContext(), textTransform);
343 //  } else {
344 //    Nlm_PeekQContext() = 0;
345 //  }
346 }
347 
348 void  Nlm_PushPort (CGContextRef ctx)
349 {
350   Nlm_PushQContext (ctx);
351 }
352 
353 CGContextRef Nlm_PopPort (void)
354 {
355   return Nlm_PopQContext ();
356 }
357 
358 #else
359 extern  void  Nlm_SetPort (GrafPtr grafptr)
360 {
361   SetPort (grafptr);
362 }
363 #endif
364 
365 extern void Nlm_SetPortWindowPort(Nlm_WindowTool wptr)
366 {
367 #ifdef WIN_MAC_QUARTZ
368     Nlm_QWindow = wptr;
369 #else
370     SetPortWindowPort(wptr);
371 #endif
372 }
373 
374 #ifdef WIN_MAC_QUARTZ
375 WindowRef Nlm_GetQuartzCurrentWindow (void)
376 {
377   return Nlm_QWindow;
378 }
379 
380 void Nlm_SetGraphicNeedsDisplay (Nlm_GraphiC graphic)
381 {
382   HIViewSetNeedsDisplay (HIViewGetRoot (Nlm_ParentWindowPtr (graphic)), 1);
383 }
384 #endif
385 
386 #endif
387 
388 #ifdef WIN_MSWIN
389 extern  void  Nlm_SetPort (HWND hwnd, HDC hdc)
390 {
391   Nlm_currentHWnd = hwnd;
392   Nlm_currentHDC = hdc;
393 }
394 
395 #endif
396 
397 #ifdef WIN_X
398 
399 /* for internal Vibrant use only */
400 extern  XFontStruct * Nlm_XLoadQueryFont (Display *d, Nlm_CharPtr fDescr, Nlm_Boolean critical)
401 {
402   XFontStruct *f;
403 
404   if ((f = XLoadQueryFont(d, fDescr)) == NULL && critical)
405   {
406     fprintf (stderr, "Vibrant: Unable to load critical font <%s>\n", fDescr);
407     exit (1);
408   }
409 
410   return f;
411 }
412 #endif
413 
414 
415 extern Nlm_Boolean Nlm_CreateGIF(Nlm_Int2 width, Nlm_Int2 height, Nlm_Boolean transparent)
416 {
417 #ifdef WIN_GIF
418   gdImage* im = gdImageCreate((int)width, (int)height);
419   if ( im ) {
420     int white_color = gdImageColorAllocate(im, 255, 255, 255);
421     if ( transparent )
422       gdImageColorTransparent(im, white_color);
423     gdImageColorAllocate(im, 0, 0, 0);
424 
425     Nlm_SetCurrentGIF(im);
426     return TRUE;
427   }
428 #endif /* WIN_GIF */
429   return FALSE;
430 }
431 
432 
433 extern Nlm_Boolean Nlm_SaveGIF(FILE* out)
434 {
435 #ifdef WIN_GIF
436   if (Nlm_currentGIF  &&  out) {
437     gdImageGif(Nlm_currentGIF, out);
438     return TRUE;
439   }
440 #endif /* WIN_GIF */
441   return FALSE;
442 }
443 
444 
445 extern void Nlm_DestroyGIF(void)
446 {
447 #ifdef WIN_GIF
448   gdImage* im = Nlm_SetCurrentGIF(0);
449   if ( im )
450     gdImageDestroy(im);
451 #endif /* WIN_GIF */
452 }
453 
454 
455 extern struct gdImageStruct* Nlm_SetCurrentGIF(struct gdImageStruct* im)
456 {
457 #ifdef WIN_GIF
458   gdImage* im_prev = Nlm_currentGIF;
459   if (im == im_prev)
460     return im;
461 
462   Nlm_curGIFColor   = 1;
463   Nlm_curGIFLType   = GIF_SOLID;
464   Nlm_curGIFFont    = gdFont7X13b;
465   Nlm_curGIFPoint.x = 0;
466   Nlm_curGIFPoint.y = 0;
467   Nlm_currentGIF    = im;
468   return im_prev;
469 #else
470   return 0;
471 #endif /* WIN_GIF */
472 }
473 
474 
475 static void Nlm_SetFontData (Nlm_FonT f, Nlm_FontData * fdata)
476 
477 {
478   Nlm_FntPtr  fp;
479 
480   if (f != NULL && fdata != NULL) {
481     fp = (Nlm_FntPtr) Nlm_HandLock (f);
482     *fp = *fdata;
483     Nlm_HandUnlock (f);
484   }
485 }
486 
487 static void Nlm_GetFontData (Nlm_FonT f, Nlm_FontData * fdata)
488 
489 {
490   Nlm_FntPtr  fp;
491 
492   if (f != NULL && fdata != NULL) {
493     fp = (Nlm_FntPtr) Nlm_HandLock (f);
494     *fdata = *fp;
495     Nlm_HandUnlock (f);
496   }
497 }
498 
499 
500 #ifdef WIN_MSWIN
501 static Nlm_Boolean Nlm_NotAStockPen (HPEN pen)
502 {
503   return (Nlm_Boolean) (pen != hBlackPen && pen != hNullPen && pen != hWhitePen);
504 }
505 
506 static Nlm_Boolean Nlm_NotAStockBrush (HBRUSH brush)
507 {
508   return (Nlm_Boolean) (brush != hBlackBrush && brush != hDkGrayBrush &&
509                         brush != hGrayBrush && brush != hHollowBrush &&
510                         brush != hLtGrayBrush && hNullBrush &&
511                         brush != hWhiteBrush);
512 }
513 
514 /*
515 static Nlm_Boolean Nlm_NotAStockFont (HFONT font)
516 {
517   return (Nlm_Boolean) (font != hAnsiFixedFont && font != hAnsiVarFont &&
518                         font != hDeviceDefaultFont && font != hOemFixedFont &&
519                         font != hSystemFont && font != hSystemFixedFont);
520 }
521 */
522 #endif
523 
524 
525 extern void Nlm_SetPenDash(Nlm_Uint1 offset, Nlm_Uint1 dash, Nlm_Uint1 gap)
526 {
527   if (dash == 0)
528     dash = 1;
529   if (gap == 0)
530     gap = 1;
531 
532 #ifdef WIN_X
533   if (Nlm_currentXDisplay != NULL  &&  Nlm_currentXGC != NULL)
534     {
535       XGCValues gcv;
536       char dash_gap[2];
537       dash_gap[0] = dash;
538       dash_gap[1] = gap;
539       gcv.line_style = LineOnOffDash;
540       XChangeGC(Nlm_currentXDisplay, Nlm_currentXGC,
541                 GCLineStyle, &gcv);
542       XSetDashes(Nlm_currentXDisplay, Nlm_currentXGC,
543                  (int)offset, dash_gap, sizeof(dash_gap));
544     }
545 
546 #elif defined(WIN32)  &&  defined(WIN_MSWIN)
547   dash_gap[0] = dash;
548   dash_gap[1] = gap;
549 
550   if ( Nlm_GetPicWinHDC() ) {
551     Nlm_Dashed(); /* metafile-dumping driver does not support ext.pens */
552     return;
553   }
554 
555   {{
556   HPEN     newPen, oldPen;
557   LOGBRUSH newBrush;
558 
559   newBrush.lbStyle = BS_SOLID;
560   newBrush.lbColor = winTextColor;
561   newBrush.lbHatch = 0;
562   if ((newPen = ExtCreatePen(PS_GEOMETRIC|PS_USERSTYLE|PS_ENDCAP_SQUARE,
563                              1, &newBrush, 2, dash_gap)) == NULL  ||
564       (oldPen = SelectObject(Nlm_currentHDC, newPen)) == NULL)
565     {
566       if ( newPen )
567         DeleteObject( newPen );
568       Nlm_Dashed();
569       return;
570     }
571 
572   prevColor = winTextColor;
573   if ( Nlm_NotAStockPen( oldPen ) )
574     DeleteObject( oldPen );
575   }}
576 
577 #elif defined(WIN_MAC_QUARTZ)
578   {
579     float dashes[2];
580     dashes[0] = (float) dash;
581     dashes[1] = (float) gap;
582     CGContextSetLineDash(Nlm_PeekQContext(), (float) offset, dashes, 2);
583   }
584 #else
585   Nlm_Dashed();
586 #endif
587 }
588 
589 
590 #ifdef WIN_MAC
591 static void Nlm_ChooseColor (Nlm_Int4 color)
592 {
593 #ifdef WIN_MAC_QUARTZ
594   ASSERT(false);
595 #else
596   ForeColor (color);
597 #endif
598 }
599 #endif
600 
601 
602 #ifdef WIN_MSWIN
603 static void Nlm_RecreateBrushes (void)
604 {
605   COLORREF  color;
606   HBITMAP   hBitmap;
607   HBRUSH    newBrush;
608   HPEN      newPen;
609   HBRUSH    oldBrush;
610   HPEN      oldPen;
611 
612   if (Nlm_currentHDC != NULL) {
613     color = winTextColor;
614     if ( (prevColor != color)||(prevPenStyle != currentPenStyle)||
615          (prevPenWidth != currentPenWidth) ||
616          (prevPenHDC != Nlm_currentHDC) ){
617 
618 #ifdef WIN32
619       if (dash_gap[0] != 0) {
620         if (prevColor != winTextColor)
621           Nlm_SetPenDash(0, (Nlm_Uint1)dash_gap[0], (Nlm_Uint1)dash_gap[1]);
622         return;
623       }
624 
625       if ( Nlm_GetPicWinHDC() ) /* metafile driver does not support ext.pens */
626         newPen = CreatePen(currentPenStyle, currentPenWidth, color);
627       else {
628         LOGBRUSH brush;
629         brush.lbStyle = BS_SOLID;
630         brush.lbColor = color;
631         brush.lbHatch = 0;
632         newPen = ExtCreatePen(currentPenStyle|PS_GEOMETRIC|PS_ENDCAP_SQUARE,
633                               currentPenWidth, &brush, 0, NULL);
634       }
635 #else
636       newPen = CreatePen(currentPenStyle, currentPenWidth, color);
637 #endif /* else!WIN32 */
638 
639       if (newPen != NULL) {
640         oldPen = SelectObject (Nlm_currentHDC, newPen);
641         if (oldPen == NULL) {
642           OutputDebugString ("Cannot select pen\n");
643           DeleteObject (newPen);
644         } else {
645           prevColor = color;
646           prevPenStyle = currentPenStyle;
647           prevPenWidth = currentPenWidth;
648           if (Nlm_NotAStockPen (oldPen)) DeleteObject (oldPen);
649         }
650       }
651     }
652     if (currentPattern == NULL) {
653       currentPattern = whitePat;
654     }
655     if ( (currentPattern != prevPattern) ||
656          (prevPenHDC != Nlm_currentHDC) ){
657       hBitmap = CreateBitmap (8, 8, 1, 1, (LPSTR) currentPattern);
658       newBrush = CreatePatternBrush (hBitmap);
659       if (newBrush != NULL) {
660         oldBrush = SelectObject (Nlm_currentHDC, newBrush);
661         if (oldBrush == NULL) {
662           OutputDebugString ("Cannot select brush\n");
663           DeleteObject (newBrush);
664         } else {
665           prevPenHDC = Nlm_currentHDC;
666           prevPattern = currentPattern;
667           if ( Nlm_NotAStockBrush(oldBrush) )
668             DeleteObject (oldBrush);
669         }
670       }
671       DeleteObject (hBitmap);
672     }
673   }
674 }
675 
676 static void Nlm_SelectPattern (Nlm_Int2 style, Nlm_Int2 width, void * pat,
677                                Nlm_Int1 flags )
678 
679 {
680   if ( flags & ATT_PENSTYLE ) currentPenStyle = style;
681   if ( flags & ATT_PENWIDTH ) currentPenWidth = width;
682   if ( flags & ATT_PATTERN ) currentPattern = pat;
683 #ifdef WIN32
684   dash_gap[0] = 0;
685 #endif
686   Nlm_RecreateBrushes ();
687 }
688 
689 static void Nlm_ChooseColor (Nlm_Int4 color)
690 
691 {
692   if (Nlm_currentHDC != NULL) {
693     SetTextColor (Nlm_currentHDC, color);
694     winTextColor = color;
695     Nlm_RecreateBrushes ();
696   }
697 }
698 
699 static Nlm_Boolean Nlm_GetTextMetrics (void)
700 
701 {
702   HDC          hDC;
703   Nlm_Boolean  success;
704 
705   success = FALSE;
706   if (Nlm_currentHDC != NULL) {
707     success = (Nlm_Boolean) GetTextMetrics (Nlm_currentHDC, &textMetrics);
708   } else {
709     hDC = CreateIC ("DISPLAY", NULL, NULL, NULL);
710     success = (Nlm_Boolean) GetTextMetrics (hDC, &textMetrics);
711     DeleteDC (hDC);
712   }
713   return success;
714 }
715 
716 
717 static HBRUSH GetBackgroundBrush (HWND hwnd)
718 
719 {
720 #ifndef WIN32
721   return (HBRUSH) GetClassWord (hwnd, GCLP_HBRBACKGROUND);
722 #else
723   return (HBRUSH) GetClassLongPtr (hwnd, GCLP_HBRBACKGROUND);
724 #endif
725 }
726 #endif
727 
728 #ifdef WIN_X
729 static void Nlm_SelectPattern (void * pat)
730 
731 {
732   if (Nlm_currentXDisplay != NULL && Nlm_currentXWindow != 0) {
733     if (currentPixmap != 0) {
734       XFreePixmap (Nlm_currentXDisplay, currentPixmap);
735     }
736     currentPixmap = XCreateBitmapFromData (Nlm_currentXDisplay, Nlm_currentXWindow,
737                                            (char *) pat, 8, 8);
738     if (currentPixmap != 0 && Nlm_currentXGC != NULL) {
739       XSetStipple (Nlm_currentXDisplay, Nlm_currentXGC, currentPixmap);
740     }
741   }
742 }
743 
744 static void Nlm_ChooseColor (Nlm_Uint4 color)
745 
746 {
747   if (Nlm_currentXDisplay != NULL && Nlm_currentXGC != NULL) {
748     XSetForeground (Nlm_currentXDisplay, Nlm_currentXGC, color);
749     currentFgColor = color;
750   }
751 }
752 
753 static Nlm_Boolean Nlm_GetTextMetrics (void)
754 
755 {
756   Nlm_Boolean  success;
757 
758   success = FALSE;
759   if (Nlm_currentXDisplay != NULL && Nlm_currentXGC != NULL) {
760     if (currentFont != NULL) {
761       fontInfo = *currentFont;
762       success = TRUE;
763     }
764   }
765   return success;
766 }
767 #endif
768 
769 
770 #ifdef WIN_MSWIN
771 extern BOOLEAN Nlm_hasBackColor;
772 extern COLORREF Nlm_crBackColor;
773 extern HBRUSH Nlm_hbrWindowBackground;
774 #endif
775 
776 #ifdef WIN_MAC_QUARTZ
777 static void Nlm_SelectQuartzColor (Nlm_QuartzColor c)
778 {
779   CGContextSetRGBFillColor  (Nlm_PeekQContext(), c.r, c.g, c.b, 1.0);
780   CGContextSetRGBStrokeColor(Nlm_PeekQContext(), c.r, c.g, c.b, 1.0);
781 }
782 #endif
783 
784 extern void Nlm_ResetDrawingTools (void)
785 {
786 #ifdef WIN_MAC
787 #ifdef WIN_MAC_QUARTZ
788   if (Nlm_PeekQContext())
789   {
790     CGContextSetLineWidth(Nlm_PeekQContext(), 1.0);
791     CGContextSetLineDash(Nlm_PeekQContext(), 0, NULL, 0);
792     CGContextSetAlpha(Nlm_PeekQContext(), 1.0);
793     Nlm_SelectQuartzColor(Nlm_QuartzForeColor);
794   }
795 #else
796   PenNormal ();
797   PenMode (patCopy);
798   TextMode (srcOr);
799   if (Nlm_hasColorQD) {
800     RGBForeColor (&Nlm_RGBforeColor);
801     RGBBackColor (&Nlm_RGBbackColor);
802   } else {
803     ForeColor (blackColor);
804     BackColor (whiteColor);
805   }
806 #endif
807 #endif
808 #ifdef WIN_MSWIN
809   if (Nlm_currentHDC != NULL) {
810     SetROP2 (Nlm_currentHDC, R2_COPYPEN);
811     SelectObject(Nlm_currentHDC, GetStockObject(SYSTEM_FONT));
812     winTextColor = GetSysColor (COLOR_WINDOWTEXT);
813     winBkColor = Nlm_hasBackColor ?
814            Nlm_crBackColor :
815            GetSysColor (COLOR_WINDOW);
816     SetTextColor (Nlm_currentHDC, winTextColor);
817     SetBkColor (Nlm_currentHDC, winBkColor);
818     SetBkMode (Nlm_currentHDC, TRANSPARENT);
819     Nlm_SelectPattern (PS_SOLID, 1, blackPat, 
820                        ATT_PENSTYLE|ATT_PENWIDTH|ATT_PATTERN );
821     prevPenHDC = NULL;
822   }
823 #endif
824 #ifdef WIN_X
825   if (Nlm_currentXDisplay != NULL && Nlm_currentXGC != NULL) {
826     currentMode = COPY_MODE;
827     currentFunction = GXcopy;
828     currentFillStyle = FillOpaqueStippled;
829     XSetFunction (Nlm_currentXDisplay, Nlm_currentXGC, currentFunction);
830     XSetFillStyle (Nlm_currentXDisplay, Nlm_currentXGC, currentFillStyle);
831     if (Nlm_hasColor) {
832       XSetBackground (Nlm_currentXDisplay, Nlm_currentXGC, Nlm_XbackColor);
833       XSetForeground (Nlm_currentXDisplay, Nlm_currentXGC, Nlm_XforeColor);
834       currentBkColor = Nlm_XbackColor;
835       currentFgColor = Nlm_XforeColor;
836     } else {
837       XSetBackground (Nlm_currentXDisplay, Nlm_currentXGC, whiteColor);
838       XSetForeground (Nlm_currentXDisplay, Nlm_currentXGC, blackColor);
839       currentBkColor = whiteColor;
840       currentFgColor = blackColor;
841     }
842     XSetLineAttributes (Nlm_currentXDisplay, Nlm_currentXGC,
843                         1, LineSolid, CapProjecting, JoinMiter);
844     Nlm_SelectPattern (blackPat);
845   }
846 #endif
847 #ifdef WIN_GIF
848   Nlm_SelectColor (0,0,0);
849   Nlm_curGIFLType = GIF_SOLID;
850   Nlm_curGIFFont = gdFont7X13b;
851   gdImageSelectPattern(Nlm_currentGIF, blackPat);
852 #endif
853   currentMode = COPY_MODE;
854 }
855 
856 /* The following functions:
857  *   Local__PointToolToPoinT
858  *   Local__PoinTToPointTool
859  *   Local__RectToolToRecT
860  *   Local__RecTToRectTool
861  * are the local versions of relevant global Nlm_... functions
862  * declared in "vibincld.h" and defined in "vibutils.c" 
863  */
864 
865 #ifdef WIN_MAC
866 static void Local__PointToolToPoinT(Nlm_PointTool src, Nlm_PointPtr dst)
867 {
868   if ( !dst )
869     return;
870 
871   dst->x = src.h;
872   dst->y = src.v;
873 }
874 #endif /* WIN_MAC */
875 
876 #ifndef WIN_GIF
877 static void Local__PoinTToPointTool(Nlm_PoinT src, Nlm_PointTool PNTR dst)
878 {
879   if ( !dst )
880     return;
881 
882 #ifdef WIN_MAC
883   dst->h = src.x;
884   dst->v = src.y;
885 #endif
886 #if defined(WIN_MSWIN) || defined(WIN_X)
887   dst->x = src.x;
888   dst->y = src.y;
889 #endif
890 }
891 
892 
893 static void Local__RectToolToRecT(Nlm_RectTool PNTR src, Nlm_RectPtr dst)
894 {
895   if (!dst  ||  !src)
896     return;
897 
898 #if defined(WIN_MAC) || defined(WIN_MSWIN)
899   dst->left   = (Nlm_Int2)src->left;
900   dst->top    = (Nlm_Int2)src->top;
901   dst->right  = (Nlm_Int2)src->right;
902   dst->bottom = (Nlm_Int2)src->bottom;
903 #endif
904 #ifdef WIN_X
905   dst->left   = src->x;
906   dst->top    = src->y;
907   dst->right  = src->x + src->width;
908   dst->bottom = src->y + src->height;
909 #endif
910 }
911 #endif /* !WIN_GIF */
912 
913 static void Local__RecTToRectTool(Nlm_RectPtr src, Nlm_RectTool PNTR dst)
914 {
915   if (!dst  ||  !src)
916     return;
917 
918 #if defined(WIN_MAC) || defined(WIN_MSWIN) || defined(WIN_GIF)
919   dst->left   = MIN(src->left, src->right );
920   dst->top    = MIN(src->top,  src->bottom);
921   dst->right  = MAX(src->left, src->right );
922   dst->bottom = MAX(src->top,  src->bottom);
923 #endif
924 #ifdef WIN_X
925   dst->x = MIN(src->left, src->right);
926   dst->y = MIN(src->top, src->bottom);
927   dst->width  = ABS(src->right - src->left);
928   dst->height = ABS(src->bottom - src->top);
929 #endif
930 }
931 
932 
933 extern void Nlm_CopyMode (void)
934 {
935 #if defined(WIN_MAC) && !defined(WIN_MAC_QUARTZ)
936   PenMode (patCopy);
937   TextMode (srcOr);
938 #endif
939 #ifdef WIN_MSWIN
940   if (Nlm_currentHDC != NULL) {
941     SetROP2 (Nlm_currentHDC, R2_COPYPEN);
942   }
943 #endif
944 #ifdef WIN_X
945   currentFunction = GXcopy;
946   currentFillStyle = FillOpaqueStippled;
947   if (Nlm_currentXDisplay != NULL && Nlm_currentXGC != NULL) {
948     XSetFunction (Nlm_currentXDisplay, Nlm_currentXGC, currentFunction);
949     XSetFillStyle (Nlm_currentXDisplay, Nlm_currentXGC, currentFillStyle);
950   }
951 #endif
952   currentMode = COPY_MODE;
953 }
954 
955 extern void Nlm_MergeMode (void)
956 {
957 #if defined(WIN_MAC) && !defined(WIN_MAC_QUARTZ)
958   PenMode (patOr);
959   TextMode (srcOr);
960 #endif
961 #ifdef WIN_MSWIN
962   if (Nlm_currentHDC != NULL) {
963     SetROP2 (Nlm_currentHDC, R2_MASKPEN);
964   }
965 #endif
966 #ifdef WIN_X
967   if (Nlm_hasColor) {
968     currentFunction = GXand;
969   } else {
970     currentFunction = GXor;
971   }
972   currentFillStyle = FillStippled;
973   if (Nlm_currentXDisplay != NULL && Nlm_currentXGC != NULL) {
974     XSetFunction (Nlm_currentXDisplay, Nlm_currentXGC, currentFunction);
975     XSetFillStyle (Nlm_currentXDisplay, Nlm_currentXGC, currentFillStyle);
976   }
977 #endif
978   currentMode = MERGE_MODE;
979 }
980 
981 extern void Nlm_InvertMode (void)
982 {
983 #if defined(WIN_MAC) && !defined(WIN_MAC_QUARTZ)
984   PenMode (patXor);
985   TextMode (srcXor);
986 #endif
987 #ifdef WIN_MSWIN
988   if (Nlm_currentHDC != NULL) {
989     SetROP2 (Nlm_currentHDC, R2_NOTXORPEN);
990   }
991 #endif
992 #ifdef WIN_X
993   if (Nlm_hasColor) {
994     currentFunction = GXequiv;
995   } else {
996     currentFunction = GXinvert;
997   }
998   currentFillStyle = FillStippled;
999   if (Nlm_currentXDisplay != NULL && Nlm_currentXGC != NULL) {
1000     XSetFunction (Nlm_currentXDisplay, Nlm_currentXGC, currentFunction);
1001     XSetFillStyle (Nlm_currentXDisplay, Nlm_currentXGC, currentFillStyle);
1002   }
1003 #endif
1004   currentMode = INVERT_MODE;
1005 }
1006 
1007 extern void Nlm_EraseMode (void)
1008 {
1009 #if defined(WIN_MAC) && !defined(WIN_MAC_QUARTZ)
1010   PenMode (patBic);
1011   TextMode (srcBic);
1012 #endif
1013 #ifdef WIN_MSWIN
1014   if (Nlm_currentHDC != NULL) {
1015     SetROP2 (Nlm_currentHDC, R2_MERGENOTPEN);
1016   }
1017 #endif
1018 #ifdef WIN_X
1019   if (Nlm_hasColor) {
1020     currentFunction = GXorInverted;
1021   } else {
1022     currentFunction = GXand;
1023   }
1024   currentFillStyle = FillStippled;
1025   if (Nlm_currentXDisplay != NULL && Nlm_currentXGC != NULL) {
1026     XSetFunction (Nlm_currentXDisplay, Nlm_currentXGC, currentFunction);
1027     XSetFillStyle (Nlm_currentXDisplay, Nlm_currentXGC, currentFillStyle);
1028   }
1029 #endif
1030   currentMode = ERASE_MODE;
1031 }
1032 
1033 extern void Nlm_Black (void)
1034 
1035 {
1036 #ifdef WIN_MAC
1037   if (Nlm_hasColorQD) {
1038     Nlm_SelectColor (0, 0, 0);
1039   } else {
1040     Nlm_ChooseColor (blackColor);
1041   }
1042 #endif
1043 #ifdef WIN_MSWIN
1044   Nlm_ChooseColor (blackColor);
1045 #endif
1046 #ifdef WIN_X
1047   Nlm_ChooseColor (blackColor);
1048 #endif
1049 #ifdef WIN_GIF
1050   Nlm_SelectColor (0, 0, 0);
1051 #endif
1052 }
1053 
1054 extern void Nlm_Red (void)
1055 
1056 {
1057 #ifdef WIN_MAC
1058   if (Nlm_hasColorQD) {
1059     Nlm_SelectColor (255, 0, 0);
1060   } else {
1061     Nlm_ChooseColor (redColor);
1062   }
1063 #endif
1064 #ifdef WIN_MSWIN
1065   Nlm_ChooseColor (redColor);
1066 #endif
1067 #ifdef WIN_X
1068   Nlm_ChooseColor (redColor);
1069 #endif
1070 #ifdef WIN_GIF
1071   Nlm_SelectColor (255, 0, 0);
1072 #endif
1073 }
1074 
1075 extern void Nlm_Green (void)
1076 
1077 {
1078 #ifdef WIN_MAC
1079   if (Nlm_hasColorQD) {
1080     Nlm_SelectColor (0, 255, 0);
1081   } else {
1082     Nlm_ChooseColor (greenColor);
1083   }
1084 #endif
1085 #ifdef WIN_MSWIN
1086   Nlm_ChooseColor (greenColor);
1087 #endif
1088 #ifdef WIN_X
1089   Nlm_ChooseColor (greenColor);
1090 #endif
1091 #ifdef WIN_GIF
1092   Nlm_SelectColor (0, 255, 0);
1093 #endif
1094 }
1095 
1096 extern void Nlm_Blue (void)
1097 
1098 {
1099 #ifdef WIN_MAC
1100   if (Nlm_hasColorQD) {
1101     Nlm_SelectColor (0, 0, 255);
1102   } else {
1103     Nlm_ChooseColor (blueColor);
1104   }
1105 #endif
1106 #ifdef WIN_MSWIN
1107   Nlm_ChooseColor (blueColor);
1108 #endif
1109 #ifdef WIN_X
1110   Nlm_ChooseColor (blueColor);
1111 #endif
1112 #ifdef WIN_GIF
1113   Nlm_SelectColor (0, 0, 255);
1114 #endif
1115 }
1116 
1117 extern void Nlm_Cyan (void)
1118 
1119 {
1120 #ifdef WIN_MAC
1121   if (Nlm_hasColorQD) {
1122     Nlm_SelectColor (0, 255, 255);
1123   } else {
1124     Nlm_ChooseColor (cyanColor);
1125   }
1126 #endif
1127 #ifdef WIN_MSWIN
1128   Nlm_ChooseColor (cyanColor);
1129 #endif
1130 #ifdef WIN_X
1131   Nlm_ChooseColor (cyanColor);
1132 #endif
1133 #ifdef WIN_GIF
1134   Nlm_SelectColor (0, 255, 255);
1135 #endif
1136 }
1137 
1138 extern void Nlm_Magenta (void)
1139 
1140 {
1141 #ifdef WIN_MAC
1142   if (Nlm_hasColorQD) {
1143     Nlm_SelectColor (255, 0, 255);
1144   } else {
1145     Nlm_ChooseColor (magentaColor);
1146   }
1147 #endif
1148 #ifdef WIN_MSWIN
1149   Nlm_ChooseColor (magentaColor);
1150 #endif
1151 #ifdef WIN_X
1152   Nlm_ChooseColor (magentaColor);
1153 #endif
1154 #ifdef WIN_GIF
1155   Nlm_SelectColor (255, 0, 255);
1156 #endif
1157 }
1158 
1159 extern void Nlm_Yellow (void)
1160 
1161 {
1162 #ifdef WIN_MAC
1163   if (Nlm_hasColorQD) {
1164     Nlm_SelectColor (255, 255, 0);
1165   } else {
1166     Nlm_ChooseColor (yellowColor);
1167   }
1168 #endif
1169 #ifdef WIN_MSWIN
1170   Nlm_ChooseColor (yellowColor);
1171 #endif
1172 #ifdef WIN_X
1173   Nlm_ChooseColor (yellowColor);
1174 #endif
1175 #ifdef WIN_GIF
1176   Nlm_SelectColor (255, 255, 0);
1177 #endif
1178 }
1179 
1180 extern void Nlm_White (void)
1181 
1182 {
1183 #ifdef WIN_MAC
1184   if (Nlm_hasColorQD) {
1185     Nlm_SelectColor (255, 255, 255);
1186   } else {
1187     Nlm_ChooseColor (whiteColor);
1188   }
1189 #endif
1190 #ifdef WIN_MSWIN
1191   Nlm_ChooseColor (whiteColor);
1192 #endif
1193 #ifdef WIN_X
1194   Nlm_ChooseColor (whiteColor);
1195 #endif
1196 #ifdef WIN_GIF
1197   Nlm_SelectColor (255, 255, 255);
1198 #endif
1199 }
1200 
1201 extern void Nlm_Gray (void)
1202 
1203 {
1204   Nlm_SelectColor (127, 127, 127);
1205 }
1206 
1207 extern void Nlm_LtGray (void)
1208 
1209 {
1210   Nlm_SelectColor (191, 191, 191);
1211 }
1212 
1213 extern void Nlm_DkGray (void)
1214 
1215 {
1216   Nlm_SelectColor (63, 63, 63);
1217 }
1218 
1219 
1220 #ifdef WIN_X
1221 #define COLOR_HASH(lrgb) (lrgb % 251)  /* 251 is the largest prime less than 256 */
1222 #define RGB_2_LRGB(red, green, blue) ((red) | (green << 8) | (blue << 16))
1223 #define LRGB_RED(lrgb)   ((lrgb) & 0xFF)
1224 #define LRGB_GREEN(lrgb) ((lrgb >> 8) & 0xFF)
1225 #define LRGB_BLUE(lrgb)  (((lrgb >> 16) & 0xFF)
1226 
1227 /* note: without a lock, the same color may appear multiple times in the hash table (not the end of the world) */
1228 typedef struct nlm_colorHashBucket {
1229   Nlm_Uint4  lrgb;
1230   XColor xcolor;
1231   struct nlm_colorHashBucket PNTR next;
1232 } Nlm_ColorHashBucket, PNTR Nlm_ColorHashBucketPtr;
1233 #endif
1234 
1235 extern void Nlm_SelectColor (Nlm_Uint1 red, Nlm_Uint1 green, Nlm_Uint1 blue)
1236 {
1237 #ifdef WIN_MAC
1238 #ifdef WIN_MAC_QUARTZ
1239   Nlm_QuartzForeColor.r = red/255.0;
1240   Nlm_QuartzForeColor.g = green/255.0;
1241   Nlm_QuartzForeColor.b = blue/255.0;
1242   Nlm_SelectQuartzColor (Nlm_QuartzForeColor);
1243 #else
1244   RGBColor   color;
1245   Nlm_Uint2  bl;
1246   Nlm_Uint2  gn;
1247   Nlm_Uint2  rd;
1248 
1249   if (Nlm_hasColorQD) {
1250     rd = (Nlm_Uint2) red;
1251     gn = (Nlm_Uint2) green;
1252     bl = (Nlm_Uint2) blue;
1253     color.red = rd << 8 | rd;
1254     color.green = gn << 8 | gn;
1255     color.blue = bl << 8 | bl;
1256     RGBForeColor (&color);
1257   } else if ((int) red + (int) green + (int) blue < 192) {
1258     Nlm_ChooseColor (blackColor);
1259   } else {
1260     Nlm_ChooseColor (whiteColor);
1261   }
1262 #endif
1263 #endif
1264 #ifdef WIN_MSWIN
1265   COLORREF   color;
1266   Nlm_Uint2  bl;
1267   Nlm_Uint2  gn;
1268   Nlm_Uint2  rd;
1269 
1270   rd = (Nlm_Uint2) red;
1271   gn = (Nlm_Uint2) green;
1272   bl = (Nlm_Uint2) blue;
1273   color = RGB (rd, gn, bl);
1274   Nlm_ChooseColor (color);
1275 #endif
1276 #ifdef WIN_X
1277   XColor xcolor;
1278   Nlm_Uint1  hash;
1279   Nlm_Uint4  lrgb;
1280   Nlm_ColorHashBucketPtr CHBP, tail;
1281   static Nlm_ColorHashBucketPtr ColorHashBuckets [256] = {NULL};
1282 
1283   lrgb = RGB_2_LRGB (red, green, blue);
1284   hash = COLOR_HASH (lrgb);
1285   tail = NULL;
1286   if (ColorHashBuckets [hash] != NULL) {
1287     for (CHBP = ColorHashBuckets [hash]; CHBP != NULL; CHBP = CHBP->next) {
1288       if (CHBP->lrgb == lrgb) {
1289         xcolor = CHBP->xcolor;
1290         Nlm_ChooseColor (xcolor.pixel);
1291         return;
1292       }
1293       tail = CHBP;
1294     }
1295   }
1296 
1297   Nlm_XAllocColor(&xcolor, Nlm_VibrantDefaultColormap(), red, green, blue);
1298   Nlm_ChooseColor(xcolor.pixel );
1299 
1300   if (tail != NULL) {
1301     tail->next = MemNew (sizeof (Nlm_ColorHashBucket));
1302     tail = tail->next;
1303   } else {
1304     tail = ColorHashBuckets [hash] = MemNew (sizeof (Nlm_ColorHashBucket));
1305   }
1306   if (tail != NULL) {
1307     tail->lrgb = lrgb;
1308     tail->xcolor = xcolor;
1309   }  
1310   
1311 #endif
1312 #ifdef WIN_GIF
1313   Nlm_curGIFColor = (int)Nlm_GetColorRGB ( red, green, blue );
1314 #endif
1315 }
1316 
1317 #ifdef WIN_X
1318 #undef COLOR_HASH
1319 #undef RGB_2_LRGB
1320 #undef LRGB_RED
1321 #undef LRGB_GREEN
1322 #undef LRGB_BLUE
1323 #endif
1324 
1325 
1326 extern Nlm_Uint4 Nlm_GetColorRGB (Nlm_Uint1 red, Nlm_Uint1 green,
1327                                   Nlm_Uint1 blue)
1328 {
1329 #ifdef WIN_MAC
1330   Nlm_Uint1  colors [4];
1331 
1332   colors [0] = 0;
1333   colors [1] = red;
1334   colors [2] = green;
1335   colors [3] = blue;
1336   return *((Nlm_Int4Ptr) colors);
1337 #endif
1338 #ifdef WIN_MSWIN
1339   Nlm_Uint2  bl;
1340   Nlm_Uint2  gn;
1341   Nlm_Uint2  rd;
1342 
1343   rd = (Nlm_Uint2) red;
1344   gn = (Nlm_Uint2) green;
1345   bl = (Nlm_Uint2) blue;
1346   return (Nlm_Uint4)(RGB(rd, gn, bl));
1347 #endif
1348 #ifdef WIN_X
1349   XColor xcolor;
1350   Nlm_XAllocColor(&xcolor, Nlm_VibrantDefaultColormap(), red, green, blue);
1351   return xcolor.pixel;
1352 #endif
1353 #ifdef WIN_GIF
1354   int i;
1355 
1356   if ( Nlm_currentGIF != NULL ){
1357     i = gdImageColorExact ( Nlm_currentGIF, (int)red, (int)green, (int)blue );
1358     if ( i == -1 ){
1359       i = gdImageColorAllocate ( Nlm_currentGIF, (int)red, (int)green, 
1360                                                  (int)blue );
1361       if ( i == -1 ){
1362         i = gdImageColorClosest ( Nlm_currentGIF, (int)red, (int)green, 
1363                                                   (int)blue );
1364       }
1365     }
1366   }
1367   return (Nlm_Uint4)i;
1368 #endif
1369 }
1370 
1371 
1372 extern Nlm_Uint4 Nlm_GetColor (void)
1373 {
1374 #ifdef WIN_MAC
1375   Nlm_Uint1  colors [4] = { 0 };
1376   Nlm_Int4   fgColor;
1377 #ifdef WIN_MAC_QUARTZ
1378   colors[0] = 0;
1379   colors[1] = Nlm_QuartzForeColor.r * 255.0;
1380   colors[2] = Nlm_QuartzForeColor.g * 255.0;
1381   colors[3] = Nlm_QuartzForeColor.b * 255.0;
1382 #else
1383   RGBColor   foreColor;
1384 
1385   if (Nlm_hasColorQD) {
1386     GetForeColor (&foreColor);
1387     colors [0] = 0;
1388     colors [1] = (Nlm_Uint1) (foreColor.red >> 8);
1389     colors [2] = (Nlm_Uint1) (foreColor.green >> 8);
1390     colors [3] = (Nlm_Uint1) (foreColor.blue >> 8);
1391     fgColor = *((Nlm_Int4Ptr) colors);
1392   }
1393 #endif
1394   fgColor = (colors[0] << 24) | (colors[1] << 16) | (colors[2] << 8) | colors[3];
1395 #if !defined( WIN_MAC_QUARTZ ) && !defined( OPAQUE_TOOLBOX_STRUCTS )
1396   if (!Nlm_hasColorQD) {
1397       GrafPtr port;
1398     GetPort (&port);
1399     if (port != NULL) {
1400       fgColor = port->fgColor;
1401     }
1402   }
1403 #endif
1404   return (Nlm_Uint4) fgColor;
1405 #endif
1406 #ifdef WIN_MSWIN
1407   Nlm_Int4  fgColor;
1408 
1409   fgColor = 0;
1410   if (Nlm_currentHDC != NULL) {
1411     fgColor = GetTextColor (Nlm_currentHDC);
1412   }
1413   return (Nlm_Uint4) fgColor;
1414 #endif
1415 #ifdef WIN_X
1416   return currentFgColor;
1417 #endif
1418 #ifdef WIN_GIF
1419   return (Nlm_Uint4)Nlm_curGIFColor;
1420 #endif
1421 }
1422 
1423 /*
1424 Used to set the color of text or foreground color.  This function is the same
1425 as Nlm_SetColor except on Windows, where it does not call the
1426 extremely expensive Nlm_RecreateBrushes()
1427 */
1428 
1429 extern void Nlm_SetColorEx (Nlm_Uint4 color)
1430 {
1431 #ifdef WIN_MAC
1432     Nlm_SetColor (color);
1433 #endif
1434 #ifdef WIN_MSWIN
1435     if (Nlm_currentHDC != NULL) {
1436         SetTextColor (Nlm_currentHDC, (Nlm_Int4) color);
1437         winTextColor = color;
1438     }
1439 #endif
1440 #ifdef WIN_X
1441     Nlm_SetColor (color);
1442 #endif
1443 }
1444 
1445 
1446 extern void Nlm_SetColor (Nlm_Uint4 color)
1447 
1448 {
1449 #ifdef WIN_MAC
1450   Nlm_Uint2  bl;
1451   Nlm_Uint2  gn;
1452   Nlm_Uint2  rd;
1453   Nlm_Uint1  colors [4];
1454   RGBColor   foreColor;
1455   GrafPtr    port;
1456 
1457   if (Nlm_hasColorQD) {
1458     *((Nlm_Int4Ptr) colors) = color;
1459     rd = (Nlm_Uint2) colors [1];
1460     gn = (Nlm_Uint2) colors [2];
1461     bl = (Nlm_Uint2) colors [3];
1462 #ifdef WIN_MAC_QUARTZ
1463     Nlm_SelectColor(rd, gn, bl);
1464 #else
1465     foreColor.red = rd << 8 | rd;
1466     foreColor.green = gn << 8 | gn;
1467     foreColor.blue = bl << 8 | bl;
1468     RGBForeColor (&foreColor);
1469   } else {
1470     GetPort (&port);
1471     if (port != NULL) {
1472       ForeColor ((Nlm_Int4) color);
1473     }
1474 #endif
1475   }
1476 #endif
1477 #ifdef WIN_MSWIN
1478   if (Nlm_currentHDC != NULL) {
1479     SetTextColor (Nlm_currentHDC, (Nlm_Int4) color);
1480     winTextColor = color;
1481     Nlm_RecreateBrushes ();
1482   }
1483 #endif
1484 #ifdef WIN_X
1485   XSetForeground (Nlm_currentXDisplay, Nlm_currentXGC, color);
1486   currentFgColor = color;
1487 #endif
1488 #ifdef WIN_GIF
1489   Nlm_curGIFColor = (int)color;
1490 #endif
1491 }
1492 
1493 extern void Nlm_InvertColors (void)
1494 
1495 {
1496 #ifdef WIN_MAC
1497 #ifdef WIN_MAC_QUARTZ
1498   Nlm_QuartzColor temp = Nlm_QuartzForeColor;
1499   Nlm_QuartzForeColor = Nlm_QuartzBackColor;
1500   Nlm_QuartzBackColor = temp;
1501   
1502   Nlm_SelectQuartzColor (Nlm_QuartzForeColor);
1503 #else
1504   RGBColor  backColor;
1505   RGBColor  foreColor;
1506 
1507   if (Nlm_hasColorQD) {
1508     GetForeColor (&foreColor);
1509     GetBackColor (&backColor);
1510     RGBForeColor (&backColor);
1511     RGBBackColor (&foreColor);
1512 #if !OPAQUE_TOOLBOX_STRUCTS
1513   } else {
1514     Nlm_Int4  bkColor;
1515     Nlm_Int4  fgColor;
1516       GrafPtr port;
1517     GetPort (&port);
1518     if (port != NULL) {
1519       fgColor = port->fgColor;
1520       bkColor = port->bkColor;
1521       ForeColor (bkColor);
1522       BackColor (fgColor);
1523 #endif
1524   }
1525 #endif
1526 #endif
1527 #ifdef WIN_MSWIN
1528   Nlm_Int4  bkColor;
1529   Nlm_Int4  fgColor;
1530 
1531   if (Nlm_currentHDC != NULL) {
1532     fgColor = GetTextColor (Nlm_currentHDC);
1533     bkColor = GetBkColor (Nlm_currentHDC);
1534     SetTextColor (Nlm_currentHDC, bkColor);
1535     winTextColor = bkColor;
1536     SetBkColor (Nlm_currentHDC, fgColor);
1537     winBkColor  = fgColor;
1538     Nlm_RecreateBrushes ();
1539   }
1540 #endif
1541 #ifdef WIN_X
1542   Nlm_Uint4  newBkColor;
1543   Nlm_Uint4  newFgColor;
1544 
1545   newBkColor = currentFgColor;
1546   newFgColor = currentBkColor;
1547   XSetBackground (Nlm_currentXDisplay, Nlm_currentXGC, newBkColor);
1548   XSetForeground (Nlm_currentXDisplay, Nlm_currentXGC, newFgColor);
1549   currentBkColor = newBkColor;
1550   currentFgColor = newFgColor;
1551 #endif
1552 #ifdef WIN_GIF
1553 #endif
1554 }
1555 
1556 extern void Nlm_DecodeColor (Nlm_Uint4 color, Nlm_Uint1Ptr red,
1557                              Nlm_Uint1Ptr green, Nlm_Uint1Ptr blue)
1558 
1559 {
1560 #ifdef WIN_MAC
1561   Nlm_Uint1Ptr  colors;
1562   Nlm_Uint1     bl;
1563   Nlm_Uint1     gn;
1564   Nlm_Uint1     rd;
1565 
1566   rd = 0;
1567   gn = 0;
1568   bl = 0;
1569   if (Nlm_hasColorQD) {
1570     colors = (Nlm_Uint1Ptr) (&color);
1571     rd = (Nlm_Uint1) colors [1];
1572     gn = (Nlm_Uint1) colors [2];
1573     bl = (Nlm_Uint1) colors [3];
1574   } else if (color == whiteColor) {
1575     rd = 255;
1576     gn = 255;
1577     bl = 255;
1578   }
1579   if (red != NULL) {
1580     *red = (Nlm_Uint1) rd;
1581   }
1582   if (green != NULL) {
1583     *green = (Nlm_Uint1) gn;
1584   }
1585   if (blue != NULL) {
1586     *blue = (Nlm_Uint1) bl;
1587   }
1588 #endif
1589 #ifdef WIN_MSWIN
1590   Nlm_Uint1  bl;
1591   Nlm_Uint1  gn;
1592   Nlm_Uint1  rd;
1593 
1594   rd = GetRValue (color);
1595   gn = GetGValue (color);
1596   bl = GetBValue (color);
1597   if (red != NULL) {
1598     *red = (Nlm_Uint1) rd;
1599   }
1600   if (green != NULL) {
1601     *green = (Nlm_Uint1) gn;
1602   }
1603   if (blue != NULL) {
1604     *blue = (Nlm_Uint1) bl;
1605   }
1606 #endif
1607 #ifdef WIN_X
1608   Nlm_Uint2  bl;
1609   Nlm_Uint2  gn;
1610   Nlm_Uint2  rd;
1611   XColor     xcolor;
1612 
1613   rd = 0;
1614   gn = 0;
1615   bl = 0;
1616   if (Nlm_hasColor) {
1617     xcolor.pixel = color;
1618     if (Nlm_currentXDisplay != NULL) {
1619       XQueryColor(Nlm_currentXDisplay, Nlm_VibrantDefaultColormap(), &xcolor);
1620       rd = xcolor.red >> 8;
1621       gn = xcolor.green >> 8;
1622       bl = xcolor.blue >> 8;
1623     }
1624   } else if (color == whiteColor) {
1625     rd = 255;
1626     gn = 255;
1627     bl = 255;
1628   }
1629   if (red != NULL) {
1630     *red = (Nlm_Uint1) rd;
1631   }
1632   if (green != NULL) {
1633     *green = (Nlm_Uint1) gn;
1634   }
1635   if (blue != NULL) {
1636     *blue = (Nlm_Uint1) bl;
1637   }
1638 #endif
1639 #ifdef WIN_GIF
1640 #endif
1641 }
1642 
1643 extern void Nlm_Dark (void)
1644 {
1645 #ifdef WIN_MAC_QUARTZ
1646   CGContextSetGrayFillColor  (Nlm_PeekQContext(), .25, 1.0);
1647   CGContextSetGrayStrokeColor(Nlm_PeekQContext(), .25, 1.0);
1648 #elif defined(WIN_MAC)
1649   PenPat ((ConstPatternParam) dkGrayPat);
1650 #endif
1651 #ifdef WIN_MSWIN
1652   Nlm_SelectPattern (PS_SOLID, 1, dkGrayPat, ATT_PATTERN );
1653 #endif
1654 #ifdef WIN_X
1655   Nlm_SelectPattern (dkGrayPat);
1656 #endif
1657 #ifdef WIN_GIF
1658   gdImageSelectPattern(Nlm_currentGIF, dkGrayPat);
1659 #endif
1660 }
1661 
1662 extern void Nlm_Medium (void)
1663 {
1664 #ifdef WIN_MAC_QUARTZ
1665   CGContextSetGrayFillColor  (Nlm_PeekQContext(), .5, 1.0);
1666   CGContextSetGrayStrokeColor(Nlm_PeekQContext(), .5, 1.0);
1667 #elif defined(WIN_MAC)
1668   PenPat ((ConstPatternParam) grayPat);
1669 #endif
1670 #ifdef WIN_MSWIN
1671   Nlm_SelectPattern (PS_SOLID, 1, grayPat, ATT_PATTERN );
1672 #endif
1673 #ifdef WIN_X
1674   Nlm_SelectPattern (grayPat);
1675 #endif
1676 #ifdef WIN_GIF
1677   gdImageSelectPattern(Nlm_currentGIF, grayPat);
1678 #endif
1679 }
1680 
1681 extern void Nlm_Light (void)
1682 {
1683 #ifdef WIN_MAC_QUARTZ
1684   CGContextSetGrayFillColor  (Nlm_PeekQContext(), .75, 1.0);
1685   CGContextSetGrayStrokeColor(Nlm_PeekQContext(), .75, 1.0);
1686 #elif defined(WIN_MAC)
1687   PenPat ((ConstPatternParam) ltGrayPat);
1688 #endif
1689 #ifdef WIN_MSWIN
1690   Nlm_SelectPattern (PS_SOLID, 1, ltGrayPat, ATT_PATTERN);
1691 #endif
1692 #ifdef WIN_X
1693   Nlm_SelectPattern (ltGrayPat);
1694 #endif
1695 #ifdef WIN_GIF
1696   gdImageSelectPattern(Nlm_currentGIF, ltGrayPat);
1697 #endif
1698 }
1699 
1700 extern void Nlm_Empty (void)
1701 {
1702 #ifdef WIN_MAC
1703 #ifdef WIN_MAC_QUARTZ
1704   CGContextSetGrayFillColor  (Nlm_PeekQContext(), 1.0, 1.0);
1705   CGContextSetGrayStrokeColor(Nlm_PeekQContext(), 1.0, 1.0);
1706 #else
1707   PenPat ((ConstPatternParam) whitePat);
1708 #endif
1709 #endif
1710 #ifdef WIN_MSWIN
1711   Nlm_SelectPattern (PS_SOLID, 1, whitePat, ATT_PATTERN);
1712 #endif
1713 #ifdef WIN_X
1714   Nlm_SelectPattern (whitePat);
1715 #endif
1716 #ifdef WIN_GIF
1717   gdImageSelectPattern(Nlm_currentGIF, whitePat);
1718 #endif
1719 }
1720 
1721 extern void Nlm_SetPenPattern (Nlm_VoidPtr pattern)
1722 {
1723 #ifdef WIN_MAC
1724   Nlm_Int2      i;
1725 #ifdef WIN_MAC_QUARTZ
1726   float         pat[8];
1727 #else
1728   Nlm_Byte      pat [8];
1729 #endif
1730   Nlm_BytePtr   ptr;
1731 #endif
1732 #ifdef WIN_MSWIN
1733   Nlm_Int2      i;
1734   Nlm_Uint2     pat [8];
1735   Nlm_Uint1Ptr  ptr;
1736   Nlm_Uint1Ptr  q;
1737 #endif
1738 #ifdef WIN_X
1739   Nlm_Int2      i;
1740   Nlm_Uint1     pat [8];
1741   Nlm_Uint1Ptr  ptr;
1742   Nlm_Uint1Ptr  q;
1743 #endif
1744 
1745   if (pattern != NULL) {
1746 #ifdef WIN_MAC
1747     ptr = (Nlm_BytePtr) pattern;
1748     for (i = 0; i < 8; i++) {
1749       pat [i] = *ptr;
1750       ptr++;
1751     }
1752 #ifdef WIN_MAC_QUARTZ
1753     CGContextSetLineDash(Nlm_PeekQContext(), 0, pat, 8);
1754 #else
1755     PenPat ((ConstPatternParam) pat);
1756 #endif
1757 #endif
1758 #ifdef WIN_MSWIN
1759     ptr = (Nlm_Uint1Ptr) pattern;
1760     q = (Nlm_Uint1Ptr) pat;
1761     for (i = 0; i < 8; i++) {
1762       *q = (Nlm_Uint1) ~(*ptr);
1763       ptr++;
1764       q++;
1765       *q = 0;
1766       q++;
1767     }
1768     Nlm_SelectPattern (PS_SOLID, 1, pat, ATT_PATTERN);
1769 #endif
1770 #ifdef WIN_X
1771     ptr = (Nlm_Uint1Ptr) pattern;
1772     q = (Nlm_Uint1Ptr) pat;
1773     for (i = 0; i < 8; i++) {
1774       *q = flip [*ptr];
1775       ptr++;
1776       q++;
1777     }
1778     Nlm_SelectPattern (pat);
1779 #endif
1780 #ifdef WIN_GIF
1781     gdImageSelectPattern(Nlm_currentGIF, (const unsigned char*)pattern);
1782 #endif
1783   }
1784 }
1785 
1786 extern void Nlm_Solid (void)
1787 { /* Reset *both* line stile and drawing pattern to SOLID */
1788 #ifdef WIN_MAC_QUARTZ
1789   CGContextSetGrayFillColor  (Nlm_PeekQContext(), 0.0, 1.0);
1790   CGContextSetGrayStrokeColor(Nlm_PeekQContext(), 0.0, 1.0);
1791   CGContextSetLineDash(Nlm_PeekQContext(), 0, NULL, 0);
1792 #elif defined(WIN_MAC)
1793   PenPat ((ConstPatternParam) blackPat);
1794 #endif
1795 #ifdef WIN_MSWIN
1796   Nlm_SelectPattern (PS_SOLID, 1, blackPat, ATT_PATTERN|ATT_PENSTYLE );
1797 #endif
1798 #ifdef WIN_X
1799   Nlm_SelectPattern( blackPat );
1800   if (Nlm_currentXDisplay  &&  Nlm_currentXGC) {
1801     XGCValues values;
1802     values.line_style = LineSolid;
1803     XChangeGC (Nlm_currentXDisplay, Nlm_currentXGC, GCLineStyle, &values);
1804   }
1805 #endif
1806 #ifdef WIN_GIF
1807   Nlm_SetPenPattern( blackPat );
1808   Nlm_curGIFLType = GIF_SOLID;
1809 #endif
1810 }
1811 
1812 extern void Nlm_Dotted (void)
1813 {
1814 #ifdef WIN_MAC_QUARTZ
1815   float dashes[] = { 1.0, 1.0 };
1816   CGContextSetLineDash(Nlm_PeekQContext(), 0, dashes, 2);
1817 #elif defined(WIN_MAC)
1818   PenPat ((ConstPatternParam) dotPat);
1819 #endif
1820 #ifdef WIN_MSWIN
1821   Nlm_SelectPattern (PS_DOT, 1, dotPat, ATT_PENSTYLE|ATT_PATTERN);
1822 #endif
1823 #ifdef WIN_X
1824   if (Nlm_currentXDisplay  &&  Nlm_currentXGC) {
1825     XGCValues values;
1826     values.line_style = LineOnOffDash;
1827     XChangeGC (Nlm_currentXDisplay, Nlm_currentXGC, GCLineStyle, &values);
1828   }
1829 #endif
1830 #ifdef WIN_GIF
1831   Nlm_curGIFLType = GIF_DASHED;
1832 #endif
1833 }
1834 
1835 extern void Nlm_Dashed (void)
1836 {
1837 #ifdef WIN_MAC_QUARTZ
1838   float dashes[] = { 3.0, 1.0 };
1839   CGContextSetLineDash(Nlm_PeekQContext(), 0, dashes, 2);
1840 #elif defined(WIN_MAC)
1841   PenPat ((ConstPatternParam) dashPat);
1842 #endif
1843 #ifdef WIN_MSWIN
1844   Nlm_SelectPattern (PS_DASH, 1, dashPat, ATT_PENSTYLE|ATT_PATTERN);
1845 #endif
1846 #ifdef WIN_X
1847   if (Nlm_currentXDisplay  &&  Nlm_currentXGC) {
1848     XGCValues values;
1849     values.line_style = LineOnOffDash;
1850     XChangeGC (Nlm_currentXDisplay, Nlm_currentXGC, GCLineStyle, &values);
1851   }
1852 #endif
1853 #ifdef WIN_GIF
1854   Nlm_curGIFLType = GIF_DASHED;
1855 #endif
1856 }
1857 
1858 extern void Nlm_WidePen (Nlm_Int2 width)
1859 {
1860 #ifdef WIN_MAC_QUARTZ
1861   CGContextSetLineDash(Nlm_PeekQContext(), 0, NULL, 0);
1862   CGContextSetLineWidth(Nlm_PeekQContext(), (float) width);
1863 #elif defined(WIN_MAC)
1864   PenPat ((ConstPatternParam) blackPat);
1865   PenSize (width, width);
1866 #endif
1867 #ifdef WIN_MSWIN
1868   Nlm_SelectPattern (PS_SOLID, width, blackPat, ATT_PENWIDTH);
1869 #endif
1870 #ifdef WIN_X
1871   XGCValues  values;
1872 
1873   if (Nlm_currentXDisplay != NULL && Nlm_currentXGC != NULL) {
1874     values.line_width = width;
1875     XChangeGC (Nlm_currentXDisplay, Nlm_currentXGC, GCLineWidth, &values);
1876   }
1877 #endif
1878 #ifdef WIN_GIF
1879 #endif
1880 }
1881 
1882 /* esl: changed to work with new FontData format */
1883 static void Nlm_LoadFontData (Nlm_FonT font,
1884                               Nlm_FonT next,
1885                               Nlm_Int4 refcnt,
1886                               Nlm_FontSpecPtr fsp,
1887 #if defined(WIN_MAC) && ! defined(WIN_MAC_ATSUI)
1888                               Nlm_Int2 num,
1889                               Nlm_Int2 size,
1890                               Nlm_Int2 styl,
1891 #else
1892                               Nlm_FontTool  hdl,
1893 #endif
1894                               Nlm_FonT print)
1895 { /* load font data */
1896   Nlm_FontData fdata;
1897   if (font == NULL) return;
1898   fdata.next = next;
1899   fdata.refcnt = refcnt;
1900   if (fsp != NULL) fdata.fontspec = *fsp;
1901   else Nlm_MemSet (&fdata.fontspec, 0, sizeof (Nlm_FontSpec));
1902 #if defined(WIN_MAC) && ! defined(WIN_MAC_ATSUI)
1903   fdata.number = num;
1904   fdata.size = size;
1905   fdata.style = styl;
1906 #elif defined(WIN_MSWIN) || defined(WIN_X) || defined(WIN_MAC_ATSUI)
1907   fdata.handle = hdl;
1908 #endif
1909   fdata.print = print;
1910   Nlm_SetFontData (font, &fdata);
1911 }
1912 
1913 /* esl: public proc for Windows font mapping (used also in ChooseFont) */
1914 #ifdef WIN_MSWIN
1915 extern void Nlm_FontSpecToLOGFONT (Nlm_FontSpecPtr fsp, LOGFONT *lfp)
1916 {
1917   if (fsp == NULL || lfp == NULL) return;
1918 
1919   memset (lfp, 0, sizeof (LOGFONT));
1920 
1921   { /* height & width */
1922     HDC hDC = GetDC (NULL);
1923     lfp->lfHeight = - MulDiv (fsp->size, GetDeviceCaps (hDC, LOGPIXELSY), 72);
1924     ReleaseDC (NULL, hDC);
1925     lfp->lfWidth = 0;
1926   }
1927 
1928   /* weight & style */
1929   lfp->lfWeight = ((fsp->style & STYLE_BOLD) != 0) ? FW_BOLD : FW_DONTCARE; /*FW_NORMAL?*/
1930   lfp->lfItalic = (BYTE)((fsp->style & STYLE_ITALIC) != 0);
1931   lfp->lfUnderline = (BYTE)((fsp->style & STYLE_UNDERLINE) != 0);
1932   lfp->lfStrikeOut = (BYTE)((fsp->style & 128) != 0); /* Windows specific */
1933 
1934   /* character set */
1935   switch (fsp->charset) {
1936     case CHARSET_SYMBOL: lfp->lfCharSet = SYMBOL_CHARSET; break;
1937     case CHARSET_KANJI: lfp->lfCharSet = SHIFTJIS_CHARSET; break;
1938     default: lfp->lfCharSet = ANSI_CHARSET; break;
1939  }
1940 
1941   /* precisions & quality */
1942   lfp->lfOutPrecision = OUT_DEFAULT_PRECIS;
1943   lfp->lfClipPrecision = CLIP_DEFAULT_PRECIS;
1944   lfp->lfQuality = DEFAULT_QUALITY;
1945 
1946   { /* pitch & family */
1947     BYTE pitch, family;
1948     switch (fsp->pitch) {
1949       case PITCH_FIXED: pitch = FIXED_PITCH; break;
1950       case PITCH_VARIABLE: pitch = VARIABLE_PITCH; break;
1951       default: pitch = DEFAULT_PITCH; break;
1952     }
1953     switch (fsp->family) {
1954       case FAMILY_ROMAN: family = FF_ROMAN; break;
1955       case FAMILY_SWISS: family = FF_SWISS; break;
1956       case FAMILY_MODERN: family = FF_MODERN; break;
1957       case FAMILY_SCRIPT: family = FF_SCRIPT; break;
1958       case FAMILY_DECORATIVE: family = FF_DECORATIVE; break;
1959       default: family = FF_DONTCARE; break;
1960     }
1961     lfp->lfPitchAndFamily = (BYTE)(pitch | family);
1962   }
1963 
1964   /* face name */
1965   Nlm_StringNCpy_0 (lfp->lfFaceName, fsp->name, LF_FACESIZE - 1);
1966 }
1967 #endif /* WIN_MSWIN */
1968 
1969 /* VL */
1970 #ifdef WIN_X  
1971 static Nlm_CharPtr Xi[]={
1972   "times",
1973   "palatino",
1974   "utopia",
1975   "new century schoolbook",
1976   "lucidabright",
1977   "lucida",
1978   "charter"
1979 };
1980 
1981 extern XFontStruct *Nlm_XLoadStandardFont(void)
1982 {
1983   static char* s_StdXFontName[] = {
1984     "-*-helvetica-bold-r-*--14-*",
1985     "-*-helvetica-bold-r-*--*-140-*",
1986     "-*-helvetica-bold-r-*-*-*-140-*",
1987     "-*-fixed-medium-r-*--*-120-*",
1988     "-*-courier-medium-r-*--*-120-*",
1989     "8x13",
1990     "9x15",
1991     "fixed"
1992   };
1993 
1994   int i;
1995   for (i = 0;  i < DIM(s_StdXFontName);  i++) {
1996     XFontStruct* font = Nlm_XLoadQueryFont(Nlm_currentXDisplay,
1997                                            s_StdXFontName[i], FALSE);
1998     if ( font )
1999       return font;
2000   }
2001 
2002   /* the last-chance font */
2003   return Nlm_XLoadQueryFont(Nlm_currentXDisplay, "fixed", TRUE);
2004 }
2005 #endif
2006 
2007 #ifdef WIN_MAC_ATSUI
2008 
2009 static Nlm_FontTool Nlm_FontToATSUStyle(Nlm_FonT f)
2010 {
2011   Nlm_FontData  fontData;
2012   Nlm_GetFontData (f, &fontData);
2013   return fontData.handle;
2014 }
2015 
2016 
2017 static Nlm_FontTool Nlm_NewATSUStyle(Nlm_FontSpecPtr fsp)
2018 {
2019   OSErr err;
2020   Nlm_FontTool style = NULL; /* type ATSUStyle */
2021   
2022   err = ATSUCreateStyle(&style);
2023   if (err == noErr) {
2024     ATSUFontID  fontID;
2025     Fixed atsuSize;
2026     Boolean boldTag = FALSE;
2027     Boolean italicTag = FALSE;
2028     
2029     ATSUAttributeTag theTags[] = {kATSUFontTag, kATSUSizeTag, kATSUQDBoldfaceTag, kATSUQDItalicTag};
2030     ByteCount theSizes[] = {sizeof(ATSUFontID), sizeof(Fixed), sizeof(Boolean), sizeof(Boolean)};
2031     ATSUAttributeValuePtr theValues[] = {&fontID, &atsuSize, &boldTag, &italicTag};
2032 
2033     /* Get Font id from the name. */
2034     OSStatus err = ATSUFindFontFromName (
2035        fsp->name, strlen(fsp->name), 
2036        kFontFullName, // kFontFamilyName,  
2037        kFontMacintoshPlatform, // kFontUnicodePlatform for Unicode support.
2038        kFontNoScriptCode, kFontNoLanguageCode,
2039        &fontID
2040     );
2041     if (err == kATSUInvalidFontErr)
2042     {
2043       /* or can we do something more intelligent here? */
2044       return NULL;
2045     }
2046     
2047     if ((fsp->style & STYLE_BOLD) != 0) boldTag = TRUE;
2048     if ((fsp->style & STYLE_ITALIC) != 0) italicTag = TRUE;
2049 
2050     /* get the size ready */
2051     atsuSize = Long2Fix (fsp->size);
2052     
2053     /* put the attributes in to the style. */
2054     err = ATSUSetAttributes (
2055        style, 
2056        sizeof(theTags)/sizeof(ATSUAttributeTag), 
2057        theTags, 
2058        theSizes, 
2059        theValues
2060     );
2061   }
2062     
2063   return style;
2064 }
2065 
2066 
2067 #endif
2068 
2069 /* esl: main internal procedure to create fonts */
2070 static Nlm_FonT Nlm_AddNewFont (Nlm_FontSpecPtr fsp, Nlm_Boolean residentp)
2071 {
2072   Nlm_FonT rsult;
2073 #if defined(WIN_MAC) && ! defined(WIN_MAC_ATSUI)
2074   Nlm_Int2 num = 0;
2075   Nlm_Int2 styl = 0;
2076 #else /* WIN_MSWIN | WIN_X | WIN_GIF | WIN_MAC_ATSUI */
2077   Nlm_FontTool hdl = NULL;
2078 #endif
2079 
2080   if (fsp == NULL)
2081     return NULL;
2082   if ( (rsult = (Nlm_FonT)Nlm_HandNew( sizeof(Nlm_FontRec) )) == NULL )
2083     return NULL;
2084 
2085 #ifdef WIN_MAC
2086 #ifdef WIN_MAC_ATSUI
2087   hdl = Nlm_NewATSUStyle(fsp);
2088 #else
2089   {{
2090     Nlm_Char temp[256];
2091     if (fsp->name[0] != '\0') {
2092       Nlm_StringNCpy_0 (temp, fsp->name, sizeof (temp));
2093       Nlm_CtoPstr (temp);
2094       GetFNum ((StringPtr) temp, &num);
2095     }
2096     if (num == 0) { /* use standard fonts */
2097       if (fsp->charset == CHARSET_KANJI) {
2098         if (fsp->pitch == PITCH_FIXED) num = 0x4034;     /* osaka(fixed) */
2099         else num = 0x4000;                               /* osaka */
2100       }
2101       else if (fsp->charset == CHARSET_SYMBOL) num = 23; /* symbol */
2102       else if (fsp->family == FAMILY_ROMAN) {
2103         if (fsp->pitch == PITCH_FIXED) num = 22;         /* courier */
2104         else num = 2;                                    /* new york */
2105       } else if (fsp->family == FAMILY_SWISS) {
2106         if (fsp->pitch == PITCH_FIXED) num = 4;          /* monaco */
2107         else num = 3;                                    /* geneva */
2108       } else if (fsp->family == FAMILY_MODERN) num = 22; /* courier */
2109       else if (fsp->family == FAMILY_SCRIPT) num = 12;   /* los angeles */
2110       else if (fsp->pitch == PITCH_FIXED) num = 4;       /* monaco */
2111       else num = 0;                                      /* system */
2112     }
2113     if ((fsp->style & STYLE_BOLD) != 0) styl += bold;
2114     if ((fsp->style & STYLE_ITALIC) != 0) styl += italic;
2115     if ((fsp->style & STYLE_UNDERLINE) != 0)  styl += underline;
2116     /* other Mac-specific styles??? */
2117     if ((fsp->style &  8) != 0)  styl += outline;
2118     if ((fsp->style & 16) != 0)  styl += shadow;
2119     if ((fsp->style & 32) != 0)  styl += condense;
2120     if ((fsp->style & 64) != 0)  styl += extend;
2121   }}
2122 #endif /* WIN_MAC_ATSUI */
2123 #endif /* WIN_MAC */
2124 #ifdef WIN_MSWIN
2125   {{
2126     LOGFONT lf;
2127     Nlm_FontSpecToLOGFONT (fsp, &lf);
2128     hdl = CreateFontIndirect (&lf);
2129   }}
2130 #endif /* WIN_MSWIN */
2131 #ifdef WIN_X
2132   if ( !Nlm_currentXDisplay )
2133     return (Nlm_FonT) Nlm_MemFree(rsult);
2134     
2135   {{
2136     Nlm_Char fspec[256];
2137     Nlm_CharPtr bs = ((fsp->style & STYLE_BOLD) != 0) ? "bold" : "medium";
2138     Nlm_CharPtr is = "r";
2139     int sz = (int)fsp->size;
2140 
2141     if (fsp->style & STYLE_ITALIC) {
2142       size_t i;
2143       is="o";
2144       for (i=0; i<DIM(Xi); i++)
2145         if ( !Nlm_StringICmp(fsp->name, Xi[i]) ) {
2146           is="i";
2147           break;
2148         }
2149     }
2150     if ( *fsp->name ) { /* try the whole data */
2151       sprintf (fspec, "-*-%s-%s-%s-*--*-%d-*-*-*-*-*-*",
2152                fsp->name, bs, is, sz*10);
2153       hdl = Nlm_XLoadQueryFont (Nlm_currentXDisplay, fspec, FALSE);
2154       if ( ! hdl ) {
2155         sprintf (fspec, "-*-%s-%s-%s-*-*-*-%d-*-*-*-*-*-*",
2156                  fsp->name, bs, is, sz*10);
2157         hdl = Nlm_XLoadQueryFont (Nlm_currentXDisplay, fspec, FALSE);
2158       }
2159     }
2160     if (!hdl  &&  *fsp->name) { /* try the name only */
2161       sprintf (fspec, "-*-%s-*", fsp->name);
2162       hdl = Nlm_XLoadQueryFont (Nlm_currentXDisplay, fspec, FALSE);
2163     }
2164     if (hdl == NULL) { /* try charset/pitch/family */
2165       Nlm_CharPtr ns;
2166       if      (fsp->charset == CHARSET_SYMBOL) ns = "symbol";
2167       else if (fsp->family  == FAMILY_ROMAN  ) ns = "times";
2168       else if (fsp->family  == FAMILY_SWISS  ) ns = "helvetica";
2169       else if (fsp->family  == FAMILY_MODERN ) ns = "courier";
2170       else if (fsp->pitch   == PITCH_FIXED   ) ns = "fixed";
2171       else ns = "helvetica";
2172 
2173       sprintf(fspec, "-*-%s-%s-%s-*--*-%d-*", ns, bs, is, sz*10);
2174       hdl = Nlm_XLoadQueryFont (Nlm_currentXDisplay, fspec, FALSE);
2175       if ( !hdl ) {
2176         sprintf(fspec, "-*-%s-%s-%s-*-*-*-%d-*", ns, bs, is, sz*10);
2177         hdl = Nlm_XLoadQueryFont(Nlm_currentXDisplay, fspec, FALSE);
2178       }
2179     }
2180 
2181     if ( !hdl ) /* last resort:  try "standard" font */
2182       hdl = Nlm_XLoadStandardFont();
2183   }}
2184 #endif /* WIN_X */
2185 
2186   Nlm_LoadFontData (rsult,
2187                     Nlm_fontList,
2188                     residentp ? -1 : 1,
2189                     fsp,
2190 #if defined(WIN_MAC) && ! defined(WIN_MAC_ATSUI)
2191                     num,
2192                     fsp->size,
2193                     styl,
2194 #else /* WIN_MSWIN | WIN_X | WIN_GIF | WIN_MAC_ATSUI */
2195                     hdl,
2196 #endif
2197                     NULL);
2198 
2199   Nlm_fontList = rsult;
2200   return rsult;
2201 }
2202 
2203 
2204 /* esl: public procedure to compare FontSpecs */
2205 extern Nlm_Boolean Nlm_EqualFontSpec (Nlm_FontSpecPtr fsp1,
2206                                       Nlm_FontSpecPtr fsp2)
2207 {
2208   if (fsp1 == NULL || fsp2 == NULL) return FALSE;
2209   return (Nlm_Boolean) (
2210     (Nlm_StrNICmp (fsp1->name, fsp2->name, FONT_NAME_SIZE) == 0) &&
2211     fsp1->size == fsp2->size &&
2212     fsp1->style == fsp2->style &&
2213     fsp1->charset == fsp2->charset &&
2214     fsp1->pitch == fsp2->pitch &&
2215     fsp1->family == fsp2->family
2216   );
2217 }
2218 
2219 /* esl: internal procedure to find existing fonts */
2220 static Nlm_FonT Nlm_FindFont (Nlm_FontSpecPtr fsp)
2221 {
2222   if (fsp != NULL) {
2223     Nlm_FonT font = Nlm_fontList;
2224     while (font != NULL) {
2225       Nlm_FntPtr fp = (Nlm_FntPtr) Nlm_HandLock (font);
2226       Nlm_Boolean found = Nlm_EqualFontSpec (fsp, &fp->fontspec);
2227       Nlm_FonT next = fp->next;
2228       Nlm_HandUnlock (font);
2229       if (found) return font;
2230       font = next;
2231     }
2232   }
2233   return NULL;
2234 }
2235 
2236 /* esl: internal procedure to increase refcnt */
2237 static void Nlm_ReuseFont (Nlm_FonT font, Nlm_Boolean residentp)
2238 {
2239   if (font != NULL) {
2240     Nlm_FntPtr fp = (Nlm_FntPtr) Nlm_HandLock (font);
2241     /* ASSERT (fp->refcnt != 0) */
2242     if (fp->refcnt > 0) {
2243       /* font is temporary: make it resident or increment refcnt */
2244       fp->refcnt = residentp ? -1 : fp->refcnt + 1;
2245     } /* else font is resident: just use it */
2246     Nlm_HandUnlock (font);
2247   }
2248 }
2249 
2250 /* esl: internal procedure to create resident/temporary fonts */
2251 static Nlm_FonT Nlm_CreateFontIndirect (Nlm_FontSpecPtr fsp,
2252                                         Nlm_Boolean residentp)
2253 {
2254   if (fsp != NULL) {
2255     if (fsp->family == 255) { /* magic number! */
2256       /* conventional specification of the standard fonts */
2257       return (fsp->pitch == PITCH_FIXED) ? Nlm_programFont : Nlm_systemFont;
2258     } else {
2259       Nlm_FonT font = Nlm_FindFont (fsp);
2260       if (font == NULL) {
2261         /* create new font and add it to the font list */
2262         return  Nlm_AddNewFont (fsp, residentp);
2263       } else {
2264         /* reuse existing font */
2265         Nlm_ReuseFont (font, residentp);
2266         return font;
2267       }
2268     }
2269   }
2270   return NULL;
2271 }
2272 
2273 #ifdef WIN_MSWIN
2274 /* Creates(if yet no one) FonT based on the properties of "screen_font".
2275  * Use this function to choose a font corresponding to a stock font.
2276  */
2277 static Nlm_FonT HFONT2Font(HFONT screen_font)
2278 {
2279   HDC hDC;
2280   if ( !screen_font )
2281     return NULL;
2282 
2283   hDC = GetDC( NULL ); /* CreateIC("DISPLAY", NULL, NULL, NULL); */
2284   if ( !hDC )
2285     return NULL;
2286 
2287   {{
2288     TEXTMETRIC tMetrics;
2289 
2290     BOOL ok = SelectObject(hDC, screen_font)  &&
2291               GetTextMetrics(hDC, &tMetrics);
2292     int height = MulDiv(tMetrics.tmHeight, 72, GetDeviceCaps(hDC, LOGPIXELSY));
2293 
2294     ReleaseDC(NULL, hDC); /* DeleteDC( hDC ); */
2295     if ( !ok )
2296       return NULL;
2297 
2298     {{
2299       Nlm_FontSpec fs;
2300       fs.name[0] = '\0';
2301       fs.size    = (Nlm_Int2)height;
2302       fs.style   = 0;
2303       if (tMetrics.tmWeight == FW_BOLD)
2304         fs.style |= STYLE_BOLD;
2305       if ( tMetrics.tmItalic )
2306         fs.style |= STYLE_ITALIC;
2307       if ( tMetrics.tmUnderlined )
2308         fs.style |= STYLE_UNDERLINE;
2309       fs.charset = CHARSET_NULL;
2310       fs.pitch   = (Nlm_Uint1)((tMetrics.tmPitchAndFamily & TMPF_FIXED_PITCH) ?
2311                                  PITCH_VARIABLE : PITCH_FIXED);
2312       switch (tMetrics.tmPitchAndFamily & 0xF0)
2313         {
2314         case FF_DECORATIVE: fs.family = FAMILY_DECORATIVE;  break;
2315         case FF_MODERN:     fs.family = FAMILY_MODERN;      break;
2316         case FF_ROMAN:      fs.family = FAMILY_ROMAN;       break;
2317         case FF_SCRIPT:     fs.family = FAMILY_SCRIPT;      break;
2318         case FF_SWISS:      fs.family = FAMILY_SWISS;       break;
2319         default:
2320           fs.family = FAMILY_NULL;
2321         }
2322 
2323       return Nlm_CreateFontIndirect(&fs, TRUE);
2324     }}
2325   }}
2326 }
2327 #endif /* WIN_MSWIN */
2328 
2329 /* esl: public procedures to create resident/temporary fonts */
2330 extern Nlm_FonT Nlm_CreateFont (Nlm_FontSpecPtr fsp)
2331 {
2332   return Nlm_CreateFontIndirect (fsp, FALSE);
2333 }
2334 extern Nlm_FonT Nlm_GetResidentFont (Nlm_FontSpecPtr fsp)
2335 {
2336   return Nlm_CreateFontIndirect (fsp, TRUE);
2337 }
2338 
2339 /* esl: public procedure to "copy" font (actually to increment refcnt) */
2340 extern Nlm_FonT Nlm_CopyFont (Nlm_FonT font)
2341 {
2342   Nlm_ReuseFont (font, FALSE); /* do not make it resident */
2343   return font;
2344 }
2345 
2346 /* esl: fonts created this way are resident for compatibility */
2347 extern Nlm_FonT Nlm_GetFont (Nlm_CharPtr name, Nlm_Int2 size,
2348                              Nlm_Boolean bld, Nlm_Boolean itlc,
2349                              Nlm_Boolean undrln, Nlm_CharPtr fmly)
2350 {
2351   Nlm_Uint1 style, charset, pitch, family;
2352 
2353   /* style */
2354   style = 0;
2355   if (bld) style |= STYLE_BOLD;
2356   if (itlc) style |= STYLE_ITALIC;
2357   if (undrln) style |= STYLE_UNDERLINE;
2358 
2359   /* charset */
2360   charset = CHARSET_NULL;
2361 
2362   /* pitch */
2363   pitch = PITCH_NULL;
2364 
2365   /* family */
2366   if (fmly == NULL || fmly [0] != '\0') family = FAMILY_NULL;
2367   else if (Nlm_StringICmp (fmly, "Roman") == 0) family = FAMILY_ROMAN;
2368   else if (Nlm_StringICmp (fmly, "Swiss") == 0) family = FAMILY_SWISS;
2369   else if (Nlm_StringICmp (fmly, "Modern") == 0) family = FAMILY_MODERN;
2370   else if (Nlm_StringICmp (fmly, "Script") == 0) family = FAMILY_SCRIPT;
2371   else if (Nlm_StringICmp (fmly, "Decorative") == 0) family = FAMILY_DECORATIVE;
2372   else family = FAMILY_NULL;
2373 
2374   /* create resident font */
2375   { Nlm_FontSpec fs;
2376     Nlm_MemSet (fs.name, 0, FONT_NAME_SIZE);
2377     if (name != NULL) Nlm_StringNCpy_0 (fs.name, name, FONT_NAME_SIZE - 1);
2378     fs.size = size;
2379     fs.style = style;
2380     fs.charset = charset;
2381     fs.pitch = pitch;
2382     fs.family = family;
2383     return Nlm_CreateFontIndirect (&fs, TRUE);
2384   }
2385 }
2386 
2387 static Nlm_FonT Nlm_ParseFontSpec (Nlm_CharPtr spec)
2388 {
2389   Nlm_Boolean  bold;
2390   Nlm_CharPtr  fmly;
2391   Nlm_Boolean  ital;
2392   Nlm_Char     name [128];
2393   Nlm_CharPtr  p;
2394   Nlm_CharPtr  q;
2395   Nlm_CharPtr  r;
2396   Nlm_FonT     rsult;
2397   Nlm_Int2     size;
2398   Nlm_Char     temp [128];
2399   Nlm_Boolean  undr;
2400   int          val;
2401 
2402   rsult = NULL;
2403   if (spec != NULL && spec [0] != '\0') {
2404     fmly = NULL;
2405     bold = FALSE;
2406     ital = FALSE;
2407     undr = FALSE;
2408     Nlm_StringNCpy_0 (name, spec, sizeof (name) - 1);
2409     p = Nlm_StringChr (name, ',');
2410     if (p != NULL) {
2411       *p = '\0';
2412       p++;
2413       q = Nlm_StringChr (p, ',');
2414       if (q != NULL) {
2415         *q = '\0';
2416         q++;
2417       }
2418       r = Nlm_StringChr (q, 'B');
2419       if (r == NULL) {
2420         r = Nlm_StringChr (q, 'b');
2421       }
2422       if (r != NULL) {
2423         bold = TRUE;
2424       }
2425       r = Nlm_StringChr (q, 'I');
2426       if (r == NULL) {
2427         r = Nlm_StringChr (q, 'i');
2428       }
2429       if (r != NULL) {
2430         ital = TRUE;
2431       }
2432       r = Nlm_StringChr (q, 'U');
2433       if (r == NULL) {
2434         r = Nlm_StringChr (q, 'u');
2435       }
2436       if (r != NULL) {
2437         undr = TRUE;
2438       }
2439       Nlm_StringNCpy_0 (temp, p, sizeof (temp) - 1);
2440       if (sscanf (temp, "%d", &val) != EOF) {
2441         size = (Nlm_Int2) val;
2442         rsult = Nlm_GetFont (name, size, bold, ital, undr, fmly);
2443       }
2444     }
2445   }
2446   return rsult;
2447 }
2448 
2449 /* esl: fonts created this way are resident for compatibility */
2450 extern Nlm_FonT Nlm_ParseFont (Nlm_CharPtr spec)
2451 
2452 {
2453   Nlm_Char     name [128];
2454   Nlm_CharPtr  p;
2455   Nlm_FonT     prtr;
2456   Nlm_CharPtr  q;
2457   Nlm_FonT     rsult;
2458 
2459   rsult = NULL;
2460   if (spec != NULL && spec [0] != '\0') {
2461     Nlm_StringNCpy_0 (name, spec, sizeof (name) - 1);
2462     p = Nlm_StringChr (name, '|');
2463     if (p != NULL) {
2464       *p = '\0';
2465       p++;
2466       while (*p == ' ') {
2467         p++;
2468       }
2469       q = name;
2470       while (*q == ' ') {
2471         q++;
2472       }
2473       rsult = Nlm_ParseFontSpec (q);
2474       prtr = Nlm_ParseFontSpec (p);
2475       Nlm_AssignPrinterFont (rsult, prtr);
2476     } else {
2477       q = name;
2478       while (*q == ' ') {
2479         q++;
2480       }
2481       rsult = Nlm_ParseFontSpec (q);
2482     }
2483   }
2484   return rsult;
2485 }
2486 
2487 extern Nlm_FonT Nlm_GetFontEx (Nlm_CharPtr name, Nlm_Int2 size,
2488                              Nlm_Boolean bld, Nlm_Boolean itlc,
2489                              Nlm_Boolean undrln, Nlm_CharPtr fmly,
2490                              Nlm_CharPtr chset, Nlm_Boolean fixed)
2491 {
2492   Nlm_Uint1 style, charset, pitch, family;
2493 
2494   /* style */
2495   style = 0;
2496   if (bld) style |= STYLE_BOLD;
2497   if (itlc) style |= STYLE_ITALIC;
2498   if (undrln) style |= STYLE_UNDERLINE;
2499 
2500   /* charset */
2501   if (chset == NULL || chset [0] == '\0') charset = CHARSET_NULL;
2502   else if (Nlm_StringICmp (chset, "Ansi") == 0) charset = CHARSET_ANSI;
2503   else if (Nlm_StringICmp (chset, "Symbol") == 0) charset = CHARSET_SYMBOL;
2504   else if (Nlm_StringICmp (chset, "Kanji") == 0) charset = CHARSET_KANJI;
2505   else if (Nlm_StringICmp (chset, "Hangul") == 0) charset = CHASET_HANGUL;
2506   else charset = CHARSET_NULL;
2507 
2508   /* pitch */
2509   if (fixed) pitch = PITCH_FIXED;
2510   else pitch = PITCH_NULL;
2511 
2512   /* family */
2513   if (fmly == NULL || fmly [0] == '\0') family = FAMILY_NULL;
2514   else if (Nlm_StringICmp (fmly, "Roman") == 0) family = FAMILY_ROMAN;
2515   else if (Nlm_StringICmp (fmly, "Swiss") == 0) family = FAMILY_SWISS;
2516   else if (Nlm_StringICmp (fmly, "Modern") == 0) family = FAMILY_MODERN;
2517   else if (Nlm_StringICmp (fmly, "Script") == 0) family = FAMILY_SCRIPT;
2518   else if (Nlm_StringICmp (fmly, "Decorative") == 0) family = FAMILY_DECORATIVE;
2519   else family = FAMILY_NULL;
2520 
2521   /* create resident font */
2522   { Nlm_FontSpec fs;
2523     Nlm_MemSet (fs.name, 0, FONT_NAME_SIZE);
2524     if (name != NULL) Nlm_StringNCpy_0 (fs.name, name, FONT_NAME_SIZE - 1);
2525     fs.size = size;
2526     fs.style = style;
2527     fs.charset = charset;
2528     fs.pitch = pitch;
2529     fs.family = family;
2530     return Nlm_CreateFontIndirect (&fs, TRUE);
2531   }
2532 }
2533 
2534 static Nlm_FonT Nlm_ParseFontSpecEx (Nlm_CharPtr spec)
2535 {
2536   Nlm_Boolean  bold;
2537   Nlm_CharPtr  fmly;
2538   Nlm_Boolean  ital;
2539   Nlm_Char     name [128];
2540   Nlm_CharPtr  p;
2541   Nlm_CharPtr  q;
2542   Nlm_CharPtr  r;
2543   Nlm_CharPtr  s;
2544   Nlm_FonT     rsult;
2545   Nlm_Int2     size;
2546   Nlm_Char     temp [128];
2547   Nlm_Boolean  undr;
2548   int          val;
2549   Nlm_Char     chst [128];
2550   Nlm_Boolean  fixd;
2551 
2552   rsult = NULL;
2553   if (spec != NULL && spec [0] != '\0') {
2554     fmly = NULL;
2555     bold = FALSE;
2556     ital = FALSE;
2557     undr = FALSE;
2558     fixd = FALSE;
2559     chst [0] = '\0';
2560     Nlm_StringNCpy_0 (name, spec, sizeof (name) - 1);
2561     p = Nlm_StringChr (name, ',');
2562     if (p != NULL) {
2563       *p = '\0';
2564       p++;
2565       q = Nlm_StringChr (p, ',');
2566       if (q != NULL) {
2567         *q = '\0';
2568         q++;
2569       }
2570       s = Nlm_StringChr (q, ',');
2571       if (s != NULL) {
2572         *s = '\0';
2573         s++;
2574       }
2575       r = Nlm_StringChr (q, 'B');
2576       if (r == NULL) {
2577         r = Nlm_StringChr (q, 'b');
2578       }
2579       if (r != NULL) {
2580         bold = TRUE;
2581       }
2582       r = Nlm_StringChr (q, 'I');
2583       if (r == NULL) {
2584         r = Nlm_StringChr (q, 'i');
2585       }
2586       if (r != NULL) {
2587         ital = TRUE;
2588       }
2589       r = Nlm_StringChr (q, 'U');
2590       if (r == NULL) {
2591         r = Nlm_StringChr (q, 'u');
2592       }
2593       if (r != NULL) {
2594         undr = TRUE;
2595       }
2596       r = Nlm_StringChr (q, 'F');
2597       if (r == NULL) {
2598         r = Nlm_StringChr (q, 'f');
2599       }
2600       if (r != NULL) {
2601         fixd = TRUE;
2602       }
2603       if (s != NULL) {
2604         Nlm_StringNCpy_0 (chst, s, sizeof (chst) - 1);
2605       }
2606       Nlm_StringNCpy_0 (temp, p, sizeof (temp) - 1);
2607       if (sscanf (temp, "%d", &val) != EOF) {
2608         size = (Nlm_Int2) val;
2609         rsult = Nlm_GetFontEx (name, size, bold, ital, undr, fmly, chst, fixd);
2610       }
2611     }
2612   }
2613   return rsult;
2614 }
2615 
2616 extern Nlm_FonT Nlm_ParseFontEx (Nlm_CharPtr scrSpec, Nlm_CharPtr prtSpec)
2617 {
2618   Nlm_CharPtr  p;
2619   Nlm_FonT     prtr;
2620   Nlm_CharPtr  q;
2621   Nlm_FonT     rsult;
2622 
2623   rsult = NULL;
2624   if (scrSpec != NULL && scrSpec [0] != '\0') {
2625       q = scrSpec;
2626       while (*q == ' ') {
2627           q++;
2628       }
2629       rsult = Nlm_ParseFontSpecEx(q);
2630   }
2631   prtr = NULL;
2632   if (prtSpec != NULL && prtSpec [0] != '\0') {
2633       p = prtSpec;
2634       while (*p == ' ') {
2635           p++;
2636       }
2637       prtr = Nlm_ParseFontSpecEx(p);
2638     Nlm_AssignPrinterFont (rsult, prtr);
2639   }
2640   return rsult;
2641 }
2642 
2643 /* esl: public procedures to get specifications for common fonts */
2644 /* ToDo: add platform-dependent names? */
2645 
2646 static Nlm_FontSpec Nlm_commonFontSpec;
2647 extern Nlm_FontSpecPtr Nlm_Helvetica (Nlm_Int2 size, Nlm_Uint1 style)
2648 {
2649 #ifdef WIN_MAC_QUARTZ
2650   strncpy(Nlm_commonFontSpec.name, "Helvetica", sizeof(Nlm_commonFontSpec.name));
2651 #else
2652   Nlm_commonFontSpec.name[0] = '\0';
2653 #endif
2654   Nlm_commonFontSpec.size = size;
2655   Nlm_commonFontSpec.style = style;
2656   Nlm_commonFontSpec.charset = CHARSET_ANSI;
2657   Nlm_commonFontSpec.pitch = PITCH_VARIABLE;
2658   Nlm_commonFontSpec.family = FAMILY_SWISS;
2659   return &Nlm_commonFontSpec;
2660 }
2661 
2662 extern Nlm_FontSpecPtr Nlm_Times (Nlm_Int2 size, Nlm_Uint1 style)
2663 {
2664 #ifdef WIN_MAC_QUARTZ
2665   strncpy(Nlm_commonFontSpec.name, "Times", sizeof(Nlm_commonFontSpec.name));
2666 #else
2667   Nlm_commonFontSpec.name[0] = '\0';
2668 #endif
2669   Nlm_commonFontSpec.size = size;
2670   Nlm_commonFontSpec.style = style;
2671   Nlm_commonFontSpec.charset = CHARSET_ANSI;
2672   Nlm_commonFontSpec.pitch = PITCH_VARIABLE;
2673   Nlm_commonFontSpec.family = FAMILY_ROMAN;
2674   return &Nlm_commonFontSpec;
2675 }
2676 
2677 extern Nlm_FontSpecPtr Nlm_Courier (Nlm_Int2 size, Nlm_Uint1 style)
2678 {
2679 #ifdef WIN_MAC_QUARTZ
2680   strncpy(Nlm_commonFontSpec.name, "Courier", sizeof(Nlm_commonFontSpec.name));
2681 #else
2682   Nlm_commonFontSpec.name[0] = '\0';
2683 #endif
2684   Nlm_commonFontSpec.size = size;
2685   Nlm_commonFontSpec.style = style;
2686   Nlm_commonFontSpec.charset = CHARSET_ANSI;
2687   Nlm_commonFontSpec.pitch = PITCH_FIXED;
2688   Nlm_commonFontSpec.family = FAMILY_MODERN;
2689   return &Nlm_commonFontSpec;
2690 }
2691 
2692 extern Nlm_FontSpecPtr Nlm_Symbol (Nlm_Int2 size, Nlm_Uint1 style)
2693 {
2694 #ifdef WIN_MAC_QUARTZ
2695   strncpy(Nlm_commonFontSpec.name, "Symbol", sizeof(Nlm_commonFontSpec.name));
2696 #else
2697   Nlm_commonFontSpec.name[0] = '\0';
2698 #endif
2699   Nlm_commonFontSpec.size = size;
2700   Nlm_commonFontSpec.style = style;
2701   Nlm_commonFontSpec.charset = CHARSET_SYMBOL; /* should be enough */
2702   Nlm_commonFontSpec.pitch = PITCH_NULL;
2703   Nlm_commonFontSpec.family = FAMILY_NULL;
2704   return &Nlm_commonFontSpec;
2705 }
2706 
2707 extern Nlm_FontSpecPtr Nlm_Gothic (Nlm_Int2 size, Nlm_Uint1 style)
2708 
2709 {
2710 #ifdef WIN_MAC
2711   strncpy(Nlm_commonFontSpec.name, "Osaka", sizeof(Nlm_commonFontSpec.name));
2712 #endif
2713 #ifdef WIN_MSWIN
2714   strncpy(Nlm_commonFontSpec.name, "\x82\x6c\x82\x72\x20\x82\x6f\x83\x53\x83\x56\x83\x62\x83\x4e", sizeof(Nlm_commonFontSpec.name));
2715 #endif
2716 #ifdef WIN_MOTIF
2717   strncpy(Nlm_commonFontSpec.name, "gothic", sizeof(Nlm_commonFontSpec.name));
2718 #endif
2719   Nlm_commonFontSpec.size = size;
2720   Nlm_commonFontSpec.style = style;
2721   Nlm_commonFontSpec.charset = CHARSET_KANJI;
2722   Nlm_commonFontSpec.pitch = PITCH_NULL;
2723   Nlm_commonFontSpec.family = FAMILY_GOTHIC;
2724   return &Nlm_commonFontSpec;
2725 }
2726 
2727 extern Nlm_FontSpecPtr Nlm_Minchou (Nlm_Int2 size, Nlm_Uint1 style)
2728 
2729 {
2730 #ifdef WIN_MAC
2731   strncpy(Nlm_commonFontSpec.name, "Osaka", sizeof(Nlm_commonFontSpec.name));
2732 #endif
2733 #ifdef WIN_MSWIN
2734   strncpy(Nlm_commonFontSpec.name, "\x82\x6c\x82\x72\x20\x82\x6f\x96\xbe\x92\xa9", sizeof(Nlm_commonFontSpec.name));
2735 #endif
2736 #ifdef WIN_MOTIF
2737   strncpy(Nlm_commonFontSpec.name, "minchou", sizeof(Nlm_commonFontSpec.name));
2738 #endif
2739   Nlm_commonFontSpec.size = size;
2740   Nlm_commonFontSpec.style = style;
2741   Nlm_commonFontSpec.charset = CHARSET_KANJI;
2742   Nlm_commonFontSpec.pitch = PITCH_NULL;
2743   Nlm_commonFontSpec.family = FAMILY_MINCHOU;
2744   return &Nlm_commonFontSpec;
2745 }
2746 
2747 extern Nlm_FontSpecPtr Nlm_GothicFixed (Nlm_Int2 size, Nlm_Uint1 style)
2748 
2749 {
2750   Nlm_Gothic(size, style);
2751 #ifdef WIN_MAC
2752   strncpy(Nlm_commonFontSpec.name, "Osaka\x81\x7c\x93\x99\x95\x9d", sizeof(Nlm_commonFontSpec.name));
2753 #endif
2754 #ifdef WIN_MSWIN
2755   strncpy(Nlm_commonFontSpec.name, "\x82\x6c\x82\x72\x20\x83\x53\x83\x56\x83\x62\x83\x4e", sizeof(Nlm_commonFontSpec.name));
2756 #endif
2757   Nlm_commonFontSpec.pitch = PITCH_FIXED;
2758   return &Nlm_commonFontSpec;
2759 }
2760 extern Nlm_FontSpecPtr Nlm_MinchouFixed (Nlm_Int2 size, Nlm_Uint1 style)
2761 {
2762   Nlm_Minchou(size, style);
2763 #ifdef WIN_MAC
2764   strncpy(Nlm_commonFontSpec.name, "Osaka\x81\x7c\x93\x99\x95\x9d", sizeof(Nlm_commonFontSpec.name));
2765 #endif
2766 #ifdef WIN_MSWIN
2767   strncpy(Nlm_commonFontSpec.name, "\x82\x6c\x82\x72\x20\x96\xbe\x92\xa9", sizeof(Nlm_commonFontSpec.name));
2768 #endif
2769   Nlm_commonFontSpec.pitch = PITCH_FIXED;
2770   return &Nlm_commonFontSpec;
2771 }
2772 
2773 
2774 /* esl: public procedure to delete temporary fonts */
2775 /* ToDo: track associated fdata.print font! */
2776 extern Nlm_FonT Nlm_DeleteFont (Nlm_FonT font)
2777 {
2778   if (font != NULL) {
2779     Nlm_FontData fdata;
2780     Nlm_GetFontData (font, &fdata);
2781     /* ASSERT(fdata.refcnt != 0) */
2782     if (fdata.refcnt > 0) {
2783       if (fdata.refcnt > 1) {
2784         /* still in use somewhere else: decrement refcnt */
2785         fdata.refcnt--;
2786         Nlm_SetFontData (font, &fdata);
2787       } else {
2788         /* last reference should be lost: remove from the list and delete */
2789         Nlm_FonT prev = NULL;
2790         Nlm_FonT curr = Nlm_fontList;
2791         while (curr != NULL) {
2792           if (curr == font) { /* font is found! */
2793             Nlm_GetFontData (curr, &fdata);
2794             curr = fdata.next;
2795             if (prev != NULL) { /* remove in the middle */
2796               Nlm_GetFontData (prev, &fdata);
2797               fdata.next = curr;
2798               Nlm_SetFontData (prev, &fdata);
2799             } else { /* remove first */
2800               Nlm_fontList = curr;
2801             }
2802           } else { /* check next! */
2803             prev = curr;
2804             Nlm_GetFontData (curr, &fdata);
2805             curr = fdata.next;
2806           }
2807         }
2808         /* if font is selected, unselect it before deletion! */
2809         if (font == Nlm_fontInUse) Nlm_SelectFont (Nlm_systemFont);
2810         /* delete it! */
2811         Nlm_GetFontData (font, &fdata);
2812 #ifdef WIN_MSWIN
2813         if (fdata.handle != NULL)
2814           DeleteObject (fdata.handle);
2815 #endif
2816 #ifdef WIN_MOTIF
2817         if (fdata.handle != NULL)
2818           XFreeFont (Nlm_currentXDisplay, fdata.handle);
2819 #endif
2820         Nlm_HandFree (font);
2821       }
2822     } /* else font is resident: leave it as it is */
2823   }
2824   return NULL;
2825 }
2826 
2827 /* esl: procedure to enumerate resident fonts */
2828 extern Nlm_FonT Nlm_FindNextResidentFont (Nlm_FonT font)
2829 {
2830   Nlm_FonT curr;
2831   Nlm_FontData fdata;
2832   if (font == NULL) {
2833     curr = Nlm_fontList;
2834   } else {
2835     Nlm_GetFontData (font, &fdata);
2836     curr = fdata.next;
2837   }
2838   while (curr != NULL) { /* skip temporary fonts */
2839     Nlm_GetFontData (curr, &fdata);
2840     if (fdata.refcnt < 0) return curr; else curr = fdata.next;
2841   }
2842   return NULL;
2843 }
2844 
2845 /* esl: procedure to extract specification from font */
2846 extern Nlm_Boolean Nlm_GetFontSpec (Nlm_FonT font, Nlm_FontSpecPtr fsp)
2847 {
2848   if (font == NULL || fsp == NULL) return FALSE;
2849   /* use conventional specification for system/program fonts */
2850   if (font == Nlm_systemFont || font == Nlm_programFont) {
2851   /*alexs: copy fontspec for System and Program font */
2852     Nlm_FntPtr fp = (Nlm_FntPtr) Nlm_HandLock (font);
2853     *fsp = fp->fontspec;
2854     Nlm_HandUnlock (font);
2855     fsp->family = 255; /* magic number! */
2856     fsp->pitch = (Nlm_Uint1)((font == Nlm_programFont) ?
2857                                PITCH_FIXED : PITCH_NULL);
2858   } else {
2859     Nlm_FntPtr fp = (Nlm_FntPtr) Nlm_HandLock (font);
2860     *fsp = fp->fontspec;
2861     Nlm_HandUnlock (font);
2862   }
2863   return TRUE;
2864 }
2865 
2866 extern void Nlm_SelectFont (Nlm_FonT f)
2867 
2868 {
2869   Nlm_FontData  fdata;
2870 
2871   if (f != NULL) {
2872     Nlm_GetFontData (f, &fdata);
2873     if (fdata.print != NULL && Nlm_nowPrinting) {
2874       f = fdata.print;
2875       Nlm_GetFontData (f, &fdata);
2876     }
2877 #ifdef WIN_MAC
2878 #ifdef WIN_MAC_ATSUI
2879     Nlm_fontInUse = f;
2880 #else
2881     TextFont (fdata.number);
2882     TextSize (fdata.size);
2883     TextFace (fdata.style);
2884 #endif
2885 #endif
2886 #ifdef WIN_MSWIN
2887     if (Nlm_currentHDC != NULL) {
2888       SelectObject (Nlm_currentHDC, fdata.handle);
2889     }
2890 #endif
2891 #ifdef WIN_X
2892     if (Nlm_currentXDisplay != NULL && Nlm_currentXGC != NULL) {
2893       if (fdata.handle != NULL) {
2894         XSetFont (Nlm_currentXDisplay, Nlm_currentXGC, fdata.handle->fid);
2895         currentFont = fdata.handle;
2896       }
2897     }
2898 #endif
2899 #ifdef WIN_GIF
2900     if (fdata.fontspec.size >= 16) {
2901       Nlm_curGIFFont = gdFont8X16;
2902     } else if (fdata.fontspec.size >= 15) {
2903       Nlm_curGIFFont = gdFont9X15b;
2904     } else if (fdata.fontspec.size >= 13) {
2905       Nlm_curGIFFont = gdFont7X13b;
2906     } else if (fdata.fontspec.size >= 10) {
2907       Nlm_curGIFFont = gdFont6X12;
2908     } else {
2909       Nlm_curGIFFont = gdFont5X8;
2910     }
2911 #endif
2912     Nlm_fontInUse = f;
2913   }
2914 }
2915 
2916 /* esl ToDo: increment refcnt for fdata.print font? */
2917 extern void Nlm_AssignPrinterFont (Nlm_FonT scrnFont, Nlm_FonT prtrFont)
2918 {
2919   if (scrnFont != NULL) {
2920     Nlm_FntPtr fp = (Nlm_FntPtr) Nlm_HandLock (scrnFont);
2921     fp->print = prtrFont;
2922     Nlm_HandUnlock (scrnFont);
2923   }
2924 }
2925 
2926 extern Nlm_Int2 Nlm_CharWidth (Nlm_Char ch)
2927 
2928 {
2929 #ifdef WIN_MAC
2930 #ifdef WIN_MAC_QUARTZ
2931   return Nlm_TextWidth (&ch, 1);
2932 #else
2933   return (CharWidth (ch));
2934 #endif
2935 #endif
2936 #ifdef WIN_MSWIN
2937   Nlm_Char  str [4];
2938 
2939   str [0] = ch;
2940   str [1] = '\0';
2941   return (Nlm_TextWidth (str, 1));
2942 #endif
2943 #ifdef WIN_X
2944   Nlm_Char  str [4];
2945 
2946   str [0] = ch;
2947   str [1] = '\0';
2948   return (Nlm_TextWidth (str, 1));
2949 #endif
2950 #ifdef WIN_GIF
2951  return (Nlm_Int2)Nlm_curGIFFont->w;
2952 #endif
2953 }
2954 
2955 extern Nlm_Int2 Nlm_StringWidth(const Nlm_Char* text)
2956 {
2957   return Nlm_TextWidth(text, Nlm_StringLen(text));
2958 }
2959 
2960 extern Nlm_Int2 Nlm_TextWidth(const Nlm_Char* text, size_t len)
2961 {
2962   if (text  &&  len) {
2963 #if defined(WIN_MAC)
2964 #if defined(WIN_MAC_ATSUI)
2965   OSErr err;
2966   Nlm_PoinT  pt;
2967   CFStringRef cfString;
2968   CFIndex cfsLen;
2969   const UniChar * unicodeString;
2970   ATSUTextLayout layout;
2971   Nlm_FontTool  curStyle;
2972   Rect          tr;
2973   
2974   /* convert the string to Unicode */
2975   cfString = CFStringCreateWithCString(kCFAllocatorDefault, text, kCFStringEncodingMacRoman);
2976   if (cfString == NULL)
2977     return 0;
2978   cfsLen = CFStringGetLength(cfString);
2979   unicodeString = CFStringGetCharactersPtr(cfString);
2980   if (unicodeString == NULL) {
2981       CFRange range;
2982       static UniChar ucbuf[1024];
2983       
2984       range.location = 0;
2985       range.length = MIN(cfsLen, 1024);
2986       CFStringGetCharacters (cfString, range, ucbuf);
2987       unicodeString = ucbuf;
2988   }
2989 
2990   /* get the current style */
2991   curStyle = Nlm_FontToATSUStyle(Nlm_fontInUse);
2992   
2993   /* create the layout */
2994   err = ATSUCreateTextLayoutWithTextPtr (
2995      unicodeString,
2996      0,
2997      cfsLen,
2998      cfsLen, 
2999      1, 
3000      (unsigned long *)&cfsLen, 
3001      &curStyle, 
3002      &layout
3003   );
3004   /* how big is the text. */
3005   err = ATSUMeasureTextImage(layout, kATSUFromTextBeginning, kATSUToTextEnd, 
3006        0,  0, &tr);
3007 
3008   if (err == noErr)
3009     return (tr.right - tr.left) + 3;
3010 #else
3011     return TextWidth(text, 0, (Nlm_Int2)len);
3012 #endif
3013 #elif defined(WIN_MSWIN)
3014     SIZE tag;
3015     if ( Nlm_currentHDC )
3016       GetTextExtentPoint(Nlm_currentHDC, text, (int)len, &tag);
3017     else {
3018       HDC hDC = CreateIC("DISPLAY", NULL, NULL, NULL);
3019       GetTextExtentPoint (hDC, text, (int)len, &tag);
3020       DeleteDC(hDC);
3021     }
3022     return (Nlm_Int2)tag.cx;
3023 
3024 #elif defined(WIN_X)
3025     if ( Nlm_GetTextMetrics() )
3026       return (Nlm_Int2)XTextWidth(&fontInfo, text, (int)len);
3027 
3028 #elif defined(WIN_GIF)
3029     return (Nlm_Int2)(Nlm_curGIFFont->w * len);
3030 #endif
3031   }
3032 
3033  return 0;
3034 }
3035 
3036 #if defined(WIN_MAC) && defined(WIN_MAC_ATSUI)
3037 static ATSFontMetrics Nlm_CurrentATSUFontMetrics(void)
3038 {
3039   Nlm_FontTool curStyle = Nlm_FontToATSUStyle (Nlm_fontInUse);
3040   ATSUFontID fontID = 0;
3041   ByteCount ignoredCount;
3042   
3043   ATSUGetAttribute (curStyle, kATSUFontTag, sizeof (fontID), &fontID, &ignoredCount);
3044   
3045   ATSFontRef font = FMGetATSFontRefFromFont (fontID);
3046   
3047   ATSFontMetrics metrics;
3048   memset (&metrics, 0, sizeof (metrics));
3049   ATSFontGetHorizontalMetrics (font, kATSOptionFlagsDefault, &metrics);
3050   
3051   return metrics;
3052 }
3053 
3054 static Fixed Nlm_CurrentATSUFontSize(void)
3055 {
3056   Nlm_FontTool curStyle = Nlm_FontToATSUStyle (Nlm_fontInUse);
3057   Fixed size = 0;
3058   ByteCount ignoredCount;
3059   
3060   ATSUGetAttribute (curStyle, kATSUSizeTag, sizeof (size), &size, &ignoredCount);
3061   
3062   return size;
3063 }
3064 #endif
3065 
3066 extern Nlm_Int2 Nlm_Ascent (void)
3067 
3068 {
3069 #ifdef WIN_MAC
3070 #ifdef WIN_MAC_ATSUI
3071   return ceilf (Nlm_CurrentATSUFontMetrics().ascent * Nlm_CurrentATSUFontSize() / 65536.0);
3072 #else
3073   FontInfo  fontinfo;
3074 
3075   GetFontInfo (&fontinfo);
3076   return (fontinfo.ascent);
3077 #endif
3078 #endif
3079 #ifdef WIN_MSWIN
3080   Nlm_Int2  rsult;
3081 
3082   rsult = 0;
3083   if (Nlm_GetTextMetrics ()) {
3084     rsult = (Nlm_Int2) textMetrics.tmAscent;
3085   }
3086   return rsult;
3087 #endif
3088 #ifdef WIN_X
3089   Nlm_Int2  rsult;
3090 
3091   rsult = 0;
3092   if (Nlm_GetTextMetrics ()) {
3093     rsult = MAX (fontInfo.ascent, fontInfo.max_bounds.ascent);
3094   }
3095   return rsult;
3096 #endif
3097 #ifdef WIN_GIF
3098  return (Nlm_Int2)Nlm_curGIFFont->h - (Nlm_Int2)Nlm_curGIFFont->d;
3099 #endif
3100 }
3101 
3102 extern Nlm_Int2 Nlm_Descent (void)
3103 
3104 {
3105 #ifdef WIN_MAC
3106 #ifdef WIN_MAC_ATSUI
3107   return ceilf (-Nlm_CurrentATSUFontMetrics().descent * Nlm_CurrentATSUFontSize() / 65536.0);
3108 #else
3109   FontInfo  fontinfo;
3110 
3111   GetFontInfo (&fontinfo);
3112   return (fontinfo.descent);
3113 #endif
3114 #endif
3115 #ifdef WIN_MSWIN
3116   Nlm_Int2  rsult;
3117 
3118   rsult = 0;
3119   if (Nlm_GetTextMetrics ()) {
3120     rsult = (Nlm_Int2) textMetrics.tmDescent;
3121   }
3122   return rsult;
3123 #endif
3124 #ifdef WIN_X
3125   Nlm_Int2  rsult;
3126 
3127   rsult = 0;
3128   if (Nlm_GetTextMetrics ()) {
3129     rsult = MAX (fontInfo.descent, fontInfo.max_bounds.descent);
3130   }
3131   return rsult;
3132 #endif
3133 #ifdef WIN_GIF
3134  return (Nlm_Int2)Nlm_curGIFFont->d;
3135 #endif
3136 }
3137 
3138 extern Nlm_Int2 Nlm_Leading (void)
3139 
3140 {
3141 #ifdef WIN_MAC
3142 #ifdef WIN_MAC_ATSUI
3143   return ceilf (Nlm_CurrentATSUFontMetrics().leading * Nlm_CurrentATSUFontSize() / 65536.0);
3144 #else
3145   FontInfo  fontinfo;
3146 
3147   GetFontInfo (&fontinfo);
3148   return (fontinfo.leading);
3149 #endif
3150 #endif
3151 #ifdef WIN_MSWIN
3152   Nlm_Int2  rsult;
3153 
3154   rsult = 0;
3155   if (Nlm_GetTextMetrics ()) {
3156     rsult = (Nlm_Int2) textMetrics.tmExternalLeading;
3157   }
3158   return rsult;
3159 #endif
3160 #ifdef WIN_X
3161   return 0;
3162 #endif
3163 #ifdef WIN_GIF
3164  return 0;
3165 #endif
3166 }
3167 
3168 extern Nlm_Int2 Nlm_FontHeight (void)
3169 
3170 {
3171 #ifdef WIN_MAC
3172 #ifdef WIN_MAC_ATSUI
3173   return Nlm_Ascent() + Nlm_Descent();
3174 #else
3175   FontInfo  fontinfo;
3176 
3177   GetFontInfo (&fontinfo);
3178   return (fontinfo.ascent + fontinfo.descent);
3179 #endif
3180 #endif
3181 #ifdef WIN_MSWIN
3182   Nlm_Int2  rsult;
3183 
3184   rsult = 0;
3185   if (Nlm_GetTextMetrics ()) {
3186     rsult = (Nlm_Int2) textMetrics.tmHeight;
3187   }
3188   return rsult;
3189 #endif
3190 #ifdef WIN_X
3191   Nlm_Int2  rsult;
3192 
3193   rsult = 0;
3194   if (Nlm_GetTextMetrics ()) {
3195     rsult = (MAX (fontInfo.ascent, fontInfo.max_bounds.ascent) +
3196              MAX (fontInfo.descent, fontInfo.max_bounds.descent));
3197   }
3198   return rsult;
3199 #endif
3200 #ifdef WIN_GIF
3201  return (Nlm_Int2)Nlm_curGIFFont->h;
3202 #endif
3203 }
3204 
3205 extern Nlm_Int2 Nlm_LineHeight (void)
3206 
3207 {
3208 #ifdef WIN_MAC
3209 #ifdef WIN_MAC_ATSUI
3210   return Nlm_Ascent() + Nlm_Descent() + Nlm_Leading();
3211 #else
3212   FontInfo  fontinfo;
3213 
3214   GetFontInfo (&fontinfo);
3215   return (fontinfo.ascent + fontinfo.descent + fontinfo.leading);
3216 #endif
3217 #endif
3218 #ifdef WIN_MSWIN
3219   Nlm_Int2  rsult;
3220 
3221   rsult = 0;
3222   if (Nlm_GetTextMetrics ()) {
3223     rsult = (Nlm_Int2) (textMetrics.tmHeight + textMetrics.tmExternalLeading);
3224   }
3225   return rsult;
3226 #endif
3227 #ifdef WIN_X
3228   Nlm_Int2  rsult;
3229 
3230   rsult = 0;
3231   if (Nlm_GetTextMetrics ()) {
3232     rsult = (MAX (fontInfo.ascent, fontInfo.max_bounds.ascent) +
3233              MAX (fontInfo.descent, fontInfo.max_bounds.descent));
3234   }
3235   return rsult;
3236 #endif
3237 #ifdef WIN_GIF
3238  return (Nlm_Int2)(Nlm_curGIFFont->h + 1);
3239 #endif
3240 }
3241 
3242 extern Nlm_Int2 Nlm_MaxCharWidth (void)
3243 
3244 {
3245 #ifdef WIN_MAC
3246 #ifdef WIN_MAC_ATSUI
3247   return ceilf (Nlm_CurrentATSUFontMetrics().maxAdvanceWidth * Nlm_CurrentATSUFontSize() / 65536.0);
3248 #else
3249   FontInfo  fontinfo;
3250 
3251   GetFontInfo (&fontinfo);
3252   return (fontinfo.widMax);
3253 #endif
3254 #endif
3255 #ifdef WIN_MSWIN
3256   Nlm_Int2  rsult;
3257 
3258   rsult = 0;
3259   if (Nlm_GetTextMetrics ()) {
3260     rsult = (Nlm_Int2) textMetrics.tmMaxCharWidth;
3261   }
3262   return rsult;
3263 #endif
3264 #ifdef WIN_X
3265   Nlm_Int2  rsult;
3266 
3267   rsult = 0;
3268   if (Nlm_GetTextMetrics ()) {
3269     rsult = fontInfo.max_bounds.width;
3270   }
3271   return rsult;
3272 #endif
3273 #ifdef WIN_GIF
3274  return (Nlm_Int2)Nlm_curGIFFont->w;
3275 #endif
3276 }
3277 
3278 
3279 size_t Nlm_FitStringWidth(const Nlm_Char PNTR str, Nlm_Int4 max_width)
3280 {
3281   size_t len;
3282   if (!str  ||  !*str  ||  max_width < 1)
3283     return 0;
3284 
3285 #if defined(WIN_X)
3286   {{
3287     if ( !Nlm_GetTextMetrics() )
3288       return 0;
3289 
3290     if (fontInfo.min_byte1  ||  fontInfo.max_byte1)
3291       return 0; /* two-byte font */
3292 
3293     if ( !fontInfo.per_char ) /* non-proportional font */
3294       return (fontInfo.max_bounds.width > 0 ?
3295               max_width / fontInfo.max_bounds.width : 0);
3296 
3297     {{
3298       Nlm_Int4 width = 0;
3299       unsigned min_char = fontInfo.min_char_or_byte2;
3300       unsigned max_char = fontInfo.max_char_or_byte2;
3301       XCharStruct *per_char = fontInfo.per_char;
3302       int def_char_width =
3303         (min_char <= fontInfo.default_char  &&
3304          fontInfo.default_char <= max_char) ?
3305         per_char[fontInfo.default_char - min_char].width : 0;
3306       const unsigned char *ustr = (const unsigned char *) str;
3307 
3308       for (len = 0;  width <= max_width  &&  *ustr;  len++, ustr++)
3309         {
3310           if (min_char <= *ustr  &&  *ustr <= max_char) {
3311             int w = per_char[*ustr - min_char].width;
3312             width += w ? w : def_char_width;
3313           }
3314           else
3315             width += def_char_width;
3316         }
3317 
3318       return (width > max_width ? len-1 : len);
3319     }}
3320   }}
3321 #else
3322   {{ /* platform-independent algorithm */
3323     Nlm_Int2 max_char_width = Nlm_MaxCharWidth();
3324     if (max_char_width < 1)
3325       return 0;
3326 
3327     ASSERT ( max_width > 0 );
3328     if (Nlm_StringWidth( (Nlm_CharPtr)str ) <= max_width)
3329       return Nlm_StringLen( str );
3330 
3331     len = (size_t)(max_width / max_char_width);
3332     ASSERT ( len < StringLen( str ) );
3333 
3334     while (str[len] != '\0'  &&
3335            Nlm_TextWidth((Nlm_CharPtr)str, len) <= max_width)
3336       len++;
3337 
3338     return (len ? len-1 : 0);
3339   }}
3340 #endif
3341 }
3342 
3343 
3344 extern void Nlm_SetPen (Nlm_PoinT pt)
3345 {
3346 #ifdef WIN_MAC
3347   Nlm_MoveTo (pt.x, pt.y);
3348 #endif
3349 #ifdef WIN_MSWIN
3350   if (Nlm_currentHDC != NULL) {
3351     MoveToEx (Nlm_currentHDC, pt.x, pt.y, NULL);
3352   }
3353 #endif
3354 #ifdef WIN_X
3355   currentPoint = pt;
3356 #endif
3357 #ifdef WIN_GIF
3358   Nlm_curGIFPoint = pt;
3359 #endif
3360 }
3361 
3362 extern void Nlm_GetPen (Nlm_PointPtr pt)
3363 
3364 {
3365 #ifdef WIN_MAC_QUARTZ
3366   CGPoint cgp;
3367   
3368   if (pt != NULL) {
3369     cgp = CGContextGetPathCurrentPoint(Nlm_PeekQContext());
3370   }
3371   pt->x = cgp.x;
3372   pt->y = cgp.y;
3373 #elif defined(WIN_MAC)
3374   Nlm_PointTool  ptool;
3375 
3376   if (pt != NULL) {
3377     GetPen (&ptool);
3378     Local__PointToolToPoinT (ptool, pt);
3379   }
3380 #endif
3381 #ifdef WIN_MSWIN
3382   POINT  pos;
3383 
3384   if (pt != NULL && Nlm_currentHDC != NULL) {
3385     GetCurrentPositionEx (Nlm_currentHDC, &pos);
3386     pt->x = (Nlm_Int2) pos.x;
3387     pt->y = (Nlm_Int2) pos.y;
3388   }
3389 #endif
3390 #ifdef WIN_X
3391   if (pt != NULL) {
3392     *pt = currentPoint;
3393   }
3394 #endif
3395 #ifdef WIN_GIF
3396   *pt = Nlm_curGIFPoint;
3397 #endif
3398 }
3399 
3400 void Nlm_SetPenWidth(Nlm_Int2 width)
3401 {
3402 #ifdef WIN_MAC
3403 #ifdef WIN_MAC_QUARTZ
3404   CGContextSetLineWidth (Nlm_PeekQContext(), width);
3405 #else
3406   PenSize (width, width);
3407 #endif
3408 #endif
3409 }
3410 
3411 extern void Nlm_PaintChar (Nlm_Char ch)
3412 
3413 {
3414 #ifdef WIN_MAC
3415 #ifdef WIN_MAC_QUARTZ
3416   Nlm_PoinT pt;
3417   Nlm_GetPen (& pt);
3418   CGContextShowTextAtPoint(Nlm_PeekQContext(), pt.x, pt.y, & ch, 1);
3419 #else
3420   DrawChar (ch);
3421 #endif
3422 #endif
3423 #ifdef WIN_MSWIN
3424   Nlm_PoinT  pt;
3425   Nlm_Char   str [2];
3426 
3427   if (Nlm_currentHDC != NULL) {
3428     str [0] = ch;
3429     str [1] = '\0';
3430     Nlm_GetPen (&pt);
3431     TextOut (Nlm_currentHDC, pt.x, pt.y - Nlm_Ascent (), str, 1);
3432     pt.x += Nlm_CharWidth (ch);
3433     Nlm_MoveTo (pt.x, pt.y);
3434   }
3435 #endif
3436 #ifdef WIN_X
3437   Nlm_PoinT  pt;
3438   Nlm_Char   str [2];
3439 
3440   if (Nlm_currentXDisplay != NULL && Nlm_currentXWindow != 0 &&
3441       Nlm_currentXGC != NULL) {
3442     str [0] = ch;
3443     str [1] = '\0';
3444     Nlm_GetPen (&pt);
3445     XDrawString (Nlm_currentXDisplay, Nlm_currentXWindow, Nlm_currentXGC,
3446                  pt.x - Nlm_XOffset, pt.y - Nlm_YOffset, str, 1);
3447     pt.x += Nlm_CharWidth (ch);
3448     Nlm_MoveTo (pt.x, pt.y);
3449   }
3450 #endif
3451 #ifdef WIN_GIF
3452   if ( Nlm_currentGIF != NULL ){
3453     gdImageChar ( Nlm_currentGIF, Nlm_curGIFFont, Nlm_curGIFPoint.x, 
3454                                   Nlm_curGIFPoint.y - Nlm_Ascent(), 
3455                                   (int)ch, Nlm_curGIFColor );
3456     Nlm_curGIFPoint.x += Nlm_CharWidth (ch);
3457   }
3458 #endif
3459 }
3460 
3461 
3462 extern void Nlm_PaintStringEx(Nlm_CharPtr text, Nlm_Int2 x, Nlm_Int2 y)
3463 {
3464 #ifdef WIN_MSWIN
3465   if (!text  ||  !*text  ||  !Nlm_currentHDC)
3466     return;
3467 
3468   TextOut(Nlm_currentHDC, x, y - Nlm_Ascent(),
3469           text, (Nlm_Int2)Nlm_StringLen( text ));
3470   Nlm_MoveTo((Nlm_Int2)(x + Nlm_StringWidth(text)), y);
3471 #else
3472   Nlm_MoveTo(x, y);
3473   Nlm_PaintString( text );
3474 #endif
3475 }
3476 
3477 
3478 extern void Nlm_PaintString (Nlm_CharPtr text)
3479 {
3480 #ifdef WIN_MAC
3481 #ifdef WIN_MAC_ATSUI
3482   OSErr err;
3483   Nlm_PoinT  pt;
3484   CFStringRef cfString;
3485   CFIndex cfsLen;
3486   const UniChar * unicodeString;
3487   ATSUTextLayout layout;
3488   Nlm_FontTool  curStyle;
3489   
3490   /* convert the string to Unicode */
3491   cfString = CFStringCreateWithCString(kCFAllocatorDefault, text, kCFStringEncodingMacRoman);
3492   if (cfString == NULL)
3493     return;
3494   cfsLen = CFStringGetLength(cfString);
3495   unicodeString = CFStringGetCharactersPtr(cfString);
3496   if (unicodeString == NULL) {
3497       CFRange range;
3498       static UniChar ucbuf[1024];
3499       
3500       range.location = 0;
3501       range.length = MIN(cfsLen, 1024);
3502       CFStringGetCharacters (cfString, range, ucbuf);
3503       unicodeString = ucbuf;
3504   }
3505 
3506   /* get the current style */
3507   curStyle = Nlm_FontToATSUStyle(Nlm_fontInUse);
3508   
3509   /* create the layout */
3510   err = ATSUCreateTextLayoutWithTextPtr (
3511      unicodeString,
3512      0,
3513      cfsLen,
3514      cfsLen, 
3515      1, 
3516      (unsigned long *)&cfsLen, 
3517      &curStyle, 
3518      &layout
3519   );
3520 
3521   /* draw where? */
3522   Nlm_GetPen (&pt);
3523   /* CGContextShowTextAtPoint(Nlm_PeekQContext(), pt.x, pt.y, text, Nlm_StringLen (text)); */
3524   err = ATSUDrawText(layout, kATSUFromTextBeginning, kATSUToTextEnd, 
3525        Long2Fix(pt.x),  Long2Fix(pt.y));
3526   
3527 #else
3528   Nlm_PoinT  pt;
3529   Nlm_Char   str [256];
3530 
3531   if (text != NULL) {
3532     Nlm_GetPen (&pt);
3533     if (Nlm_StringLen (text) > 0) {
3534       Nlm_StringNCpy_0 (str, text, sizeof (str));
3535       Nlm_CtoPstr (str);
3536       DrawString ((StringPtr) str);
3537     }
3538     pt.x += Nlm_StringWidth (text);
3539     Nlm_MoveTo (pt.x, pt.y);
3540   }
3541 #endif
3542 #endif
3543 #ifdef WIN_MSWIN
3544   Nlm_PoinT pt;
3545   Nlm_GetPen( &pt );
3546   Nlm_PaintStringEx(text, pt.x, pt.y);
3547 #endif
3548 #ifdef WIN_X
3549   Nlm_Int2   len;
3550   Nlm_PoinT  pt;
3551 
3552   if (text != NULL && Nlm_currentXDisplay != NULL &&
3553       Nlm_currentXWindow != 0 && Nlm_currentXGC != NULL) {
3554     len = (Nlm_Int2) Nlm_StringLen (text);
3555     Nlm_GetPen (&pt);
3556     if (len > 0) {
3557       XDrawString (Nlm_currentXDisplay, Nlm_currentXWindow, Nlm_currentXGC,
3558                    pt.x - Nlm_XOffset, pt.y - Nlm_YOffset, text, len);
3559     }
3560     pt.x += Nlm_StringWidth (text);
3561     Nlm_MoveTo (pt.x, pt.y);
3562   }
3563 #endif
3564 #ifdef WIN_GIF
3565   if ( text != NULL && Nlm_currentGIF != NULL ){
3566     gdImageString ( Nlm_currentGIF, Nlm_curGIFFont, Nlm_curGIFPoint.x, 
3567                     Nlm_curGIFPoint.y - Nlm_Ascent(),               
3568                     text, Nlm_curGIFColor );
3569     Nlm_curGIFPoint.x += Nlm_StringWidth (text);
3570   }
3571 #endif
3572 }
3573 
3574 
3575 #ifdef VAR_ARGS
3576 void CDECL Nlm_PaintText (format, va_alist)
3577   char *format;
3578   va_dcl
3579 #else
3580 void CDECL Nlm_PaintText (char *format, ...)
3581 #endif
3582 {
3583 #ifdef WIN_MAC
3584   va_list    args;
3585   Nlm_PoinT  pt;
3586   Nlm_Char   str [256];
3587 
3588   if (format != NULL) {
3589 #ifdef VAR_ARGS
3590     va_start(args);
3591 #else
3592     va_start(args, format);
3593 #endif
3594     vsprintf(str, format, args);
3595     va_end(args);
3596     Nlm_GetPen (&pt);
3597 #ifdef WIN_MAC_QUARTZ
3598     CGContextShowTextAtPoint(Nlm_PeekQContext(), pt.x, pt.y, str, Nlm_StringLen (str));
3599 #else
3600     if (Nlm_StringLen (str) > 0) {
3601       Nlm_CtoPstr (str);
3602       DrawString ((StringPtr) str);
3603     }
3604     pt.y += Nlm_LineHeight ();
3605     Nlm_MoveTo (pt.x, pt.y);
3606 #endif
3607   }
3608 #endif
3609 #ifdef WIN_MSWIN
3610   va_list    args;
3611   Nlm_Int2   len;
3612   Nlm_PoinT  pt;
3613   Nlm_Char   str [256];
3614 
3615   if (format != NULL && Nlm_currentHDC != NULL) {
3616 #ifdef VAR_ARGS
3617     va_start(args);
3618 #else
3619     va_start(args, format);
3620 #endif
3621     vsprintf(str, format, args);
3622     va_end(args);
3623     len = (Nlm_Int2) Nlm_StringLen (str);
3624     Nlm_GetPen (&pt);
3625     if (len > 0) {
3626       TextOut (Nlm_currentHDC, pt.x, pt.y - Nlm_Ascent (), str, len);
3627     }
3628     pt.y += Nlm_LineHeight ();
3629     Nlm_MoveTo (pt.x, pt.y);
3630   }
3631 #endif
3632 #ifdef WIN_X
3633   va_list    args;
3634   Nlm_Int2   len;
3635   Nlm_PoinT  pt;
3636   Nlm_Char   str [256];
3637 
3638   if (format != NULL && Nlm_currentXDisplay != NULL &&
3639       Nlm_currentXWindow != 0 && Nlm_currentXGC != NULL) {
3640 #ifdef VAR_ARGS
3641     va_start(args);
3642 #else
3643     va_start(args, format);
3644 #endif
3645     vsprintf(str, format, args);
3646     va_end(args);
3647     len = (Nlm_Int2) Nlm_StringLen (str);
3648     Nlm_GetPen (&pt);
3649     if (len > 0) {
3650       XDrawString (Nlm_currentXDisplay, Nlm_currentXWindow, Nlm_currentXGC,
3651                    pt.x - Nlm_XOffset, pt.y - Nlm_YOffset, str, len);
3652     }
3653     pt.y += Nlm_LineHeight ();
3654     Nlm_MoveTo (pt.x, pt.y);
3655   }
3656 #endif
3657 #ifdef WIN_GIF
3658   va_list    args;
3659   Nlm_Char   str [256];
3660 
3661   if ( format != NULL && Nlm_currentGIF != NULL ){
3662 #ifdef VAR_ARGS
3663     va_start(args);
3664 #else
3665     va_start(args, format);
3666 #endif
3667     vsprintf(str, format, args);
3668     va_end(args);
3669     gdImageString ( Nlm_currentGIF, Nlm_curGIFFont, Nlm_curGIFPoint.x, 
3670                     Nlm_curGIFPoint.y - Nlm_Ascent(), 
3671                     str, Nlm_curGIFColor );
3672     Nlm_curGIFPoint.x += Nlm_StringWidth (str);
3673   }
3674 #endif
3675 }
3676 
3677 extern void Nlm_DrawString (Nlm_RectPtr r, Nlm_CharPtr text,
3678                             Nlm_Char jst, Nlm_Boolean gray)
3679 
3680 {
3681   Nlm_DrawText (r, text, Nlm_StringLen (text), jst, gray);
3682 }
3683 
3684 extern void Nlm_DrawText (Nlm_RectPtr r, Nlm_CharPtr text,
3685                           size_t len, Nlm_Char jst,
3686                           Nlm_Boolean gray)
3687 
3688 {
3689 #ifdef WIN_MAC
3690 #ifdef WIN_MAC_ATSUI
3691   CFStringRef cfString;
3692   CFIndex cfsLen;
3693   Nlm_RectTool  rtool;
3694   OSStatus    err;
3695   ATSUStyle   aStyle;
3696   TXNTextBoxOptionsData boxOptions;
3697       
3698   if (r != NULL) {
3699     Nlm_EraseRect (r);
3700     if (text != NULL && len > 0) {
3701       cfString = CFStringCreateWithBytes(kCFAllocatorDefault, (UInt8 *)text, len, kCFStringEncodingMacRoman, false);
3702       if (cfString == NULL)
3703         return;
3704       cfsLen = CFStringGetLength(cfString);
3705 
3706       Local__RecTToRectTool(r, &rtool);
3707       
3708       boxOptions.optionTags = kTXNSetFlushnessMask;
3709       switch (jst) {
3710         case 'r':
3711           boxOptions.flushness = kATSUEndAlignment;
3712           break;
3713         case 'l':
3714           boxOptions.flushness = kATSUStartAlignment;
3715           break;
3716         case 'c':
3717           boxOptions.flushness = kATSUCenterAlignment;
3718           break;
3719         default:
3720           boxOptions.flushness = kATSUStartAlignment;
3721           break;
3722       }
3723       aStyle = Nlm_FontToATSUStyle(Nlm_fontInUse);  
3724       
3725 #ifdef WIN_MAC_QUARTZ
3726 // QUARTZ_FIXME: is this stuff necessary?
3727 //      boxOptions.optionTags |= kTXNUseCGContextRefMask;
3728 //      boxOptions.options = Nlm_PeekQContext();
3729 //      CGContextSaveGState(Nlm_PeekQContext());
3730 //      /* need to undo the coordinate transforms, otherwise the text comes out upside down. */
3731 //      CGContextScaleCTM(Nlm_PeekQContext(), 1.0f, -1.0f);
3732 //      {  
3733 //        Rect      pBounds;
3734 //        int       pHeight;
3735 //        GrafPtr   grafptr;
3736 //
3737 //        GetPort(&grafptr);
3738 //        GetPortBounds(grafptr, &pBounds);
3739 //        pHeight = pBounds.bottom - pBounds.top;
3740 //        CGContextTranslateCTM(Nlm_PeekQContext(), 0, -pHeight);
3741 //      }
3742 #endif
3743 
3744       err = TXNDrawCFStringTextBox(cfString, &rtool, aStyle, &boxOptions);
3745       CFRelease(cfString);
3746       
3747 //#ifdef WIN_MAC_QUARTZ
3748 //      CGContextRestoreGState(Nlm_PeekQContext());
3749 //#endif
3750     }
3751   }
3752 
3753 #else
3754   Nlm_Int2      delta;
3755   Nlm_Int2      height;
3756   Nlm_Int2      just;
3757   Nlm_Int2      limit;
3758   PenState      pnState;
3759   Nlm_RectTool  rtool;
3760 
3761   if (r != NULL) {
3762     Nlm_EraseRect (r);
3763     if (text != NULL && len > 0) {
3764       Local__RecTToRectTool (r, &rtool);
3765       limit = ABS (r->bottom - r->top);
3766       height = Nlm_LineHeight ();
3767       delta = limit - height;
3768       if (delta > 0) {
3769         rtool.top += delta / 2;
3770         rtool.bottom = rtool.top + height;
3771       }
3772       switch (jst) {
3773         case 'r':
3774           just = -1;
3775           break;
3776         case 'l':
3777           just = 0;
3778           break;
3779         case 'c':
3780           just = 1;
3781           break;
3782         default:
3783           just = 0;
3784           break;
3785       }
3786       TETextBox (text, len, &rtool, just);
3787       if (gray) {
3788         GetPenState (&pnState);
3789         PenMode (patBic);
3790         PenPat ((ConstPatternParam) grayPat);
3791         PaintRect (&rtool);
3792         SetPenState (&pnState);
3793       }
3794     }
3795   }
3796 #endif
3797 #endif
3798 #ifdef WIN_MSWIN
3799   Nlm_Int2      format;
3800   Nlm_Int4      oldcolor = 0;
3801   Nlm_RectTool  rtool;
3802   Nlm_FontData  fdata;
3803   SIZE          tsize;
3804   HDC           hdc;
3805 
3806   if (r != NULL && Nlm_currentHDC != NULL) {
3807     Local__RecTToRectTool (r, &rtool);
3808     if (Nlm_currentHWnd != NULL) {
3809       Nlm_EraseRect (r);
3810     } else {
3811       FillRect (Nlm_currentHDC, &rtool, hWhiteBrush);
3812     }
3813     if (text != NULL && len > 0) {
3814       switch (jst) {
3815         case 'r':
3816           format = DT_RIGHT;
3817           break;
3818         case 'l':
3819           format = DT_LEFT;
3820           break;
3821         case 'c':
3822           format = DT_CENTER;
3823           break;
3824         default:
3825           format = DT_LEFT;
3826           break;
3827       }
3828       if (gray) {
3829         winTextColor = GetSysColor (COLOR_GRAYTEXT);
3830         oldcolor = SetTextColor (Nlm_currentHDC, winTextColor);
3831       }
3832       hdc = Nlm_GetPicWinHDC();
3833       if ( hdc == NULL ){
3834         /* esl: DT_VCENTER must be combined with DT_SINGLELINE!  */
3835         DrawText (Nlm_currentHDC, text, (Nlm_Int2) len, &rtool,
3836                   format | DT_VCENTER | DT_NOPREFIX | DT_SINGLELINE);
3837       } else {
3838         if ( Nlm_fontInUse != NULL ){
3839           Nlm_GetFontData (Nlm_fontInUse, &fdata);
3840           SelectObject (hdc, fdata.handle);
3841         }
3842         GetTextExtentPoint ( hdc, text, len, &tsize );
3843         tsize.cy = (r->top + r->bottom)/2 - tsize.cy/2;
3844         switch ( format ){
3845           case DT_LEFT:
3846             tsize.cx = r->left; break;
3847           case DT_RIGHT:
3848             tsize.cx = r->right - tsize.cx; break;
3849           default:
3850             tsize.cx = (r->left + r->right)/2 - tsize.cx/2;
3851         }
3852         Nlm_PaintStringEx(text, (Nlm_Int2)tsize.cx, (Nlm_Int2)tsize.cy);
3853       }
3854       if (gray) {
3855         SetTextColor (Nlm_currentHDC, oldcolor);
3856         winTextColor = oldcolor;
3857       }
3858     }
3859   }
3860 #endif
3861 #ifdef WIN_X
3862   Nlm_Int2   delta;
3863   Nlm_Int2   height;
3864   Nlm_Int2   limit;
3865   Pixmap     pix = 0;
3866   Nlm_PoinT  pt;
3867   Nlm_Int2   width;
3868 
3869   if (r != NULL && Nlm_currentXDisplay != NULL &&
3870       Nlm_currentXWindow != 0 && Nlm_currentXGC != NULL) {
3871     Nlm_EraseRect (r);
3872     if (text != NULL && len > 0) {
3873       pt.x = r->left;
3874       pt.y = r->top;
3875       limit = ABS (r->right - r->left);
3876       width = Nlm_TextWidth (text, len);
3877       while (len > 0 && width > limit) {
3878         len--;
3879         width = Nlm_TextWidth (text, len);
3880       }
3881       delta = limit - width;
3882       switch (jst) {
3883         case 'r':
3884           pt.x += delta;
3885           break;
3886         case 'l':
3887           break;
3888         case 'c':
3889           pt.x += delta / 2;
3890           break;
3891         default:
3892           break;
3893       }
3894       limit = ABS (r->bottom - r->top);
3895       height = Nlm_LineHeight ();
3896       delta = limit - height;
3897       if (delta > 0) {
3898         pt.y += delta / 2;
3899       }
3900       if (limit >= height) {
3901         if (gray) {
3902           pix = XCreateBitmapFromData (Nlm_currentXDisplay, Nlm_currentXWindow,
3903                                        (char *) grayPat, 8, 8);
3904           if (pix != 0 && Nlm_currentXGC != NULL) {
3905             XSetStipple (Nlm_currentXDisplay, Nlm_currentXGC, pix);
3906           }
3907         }
3908         XSetFillStyle (Nlm_currentXDisplay, Nlm_currentXGC, FillStippled);
3909         XDrawString (Nlm_currentXDisplay, Nlm_currentXWindow, Nlm_currentXGC,
3910                      pt.x - Nlm_XOffset, pt.y + Nlm_Ascent () - Nlm_YOffset,
3911                      text, (int) len);
3912         if (gray && pix != 0) {
3913           XFreePixmap (Nlm_currentXDisplay, pix);
3914           if (Nlm_currentXGC != NULL) {
3915             XSetStipple (Nlm_currentXDisplay, Nlm_currentXGC, currentPixmap);
3916           }
3917         }
3918         XSetFillStyle (Nlm_currentXDisplay, Nlm_currentXGC, currentFillStyle);
3919       }
3920     }
3921   }
3922 #endif
3923 #ifdef WIN_GIF
3924   Nlm_Int2   delta;
3925   Nlm_Int2   height;
3926   Nlm_Int2   limit;
3927   Nlm_PoinT  pt;
3928   Nlm_Int2   width;
3929 
3930   if (r != NULL && Nlm_currentGIF != NULL ) {
3931     Nlm_EraseRect (r);
3932     if (text != NULL && len > 0) {
3933       pt.x = r->left;
3934       pt.y = r->top;
3935       limit = ABS (r->right - r->left);
3936       width = Nlm_TextWidth (text, len);
3937       while (len > 0 && width > limit) {
3938         len--;
3939         width = Nlm_TextWidth (text, len);
3940       }
3941       delta = limit - width;
3942       switch (jst) {
3943         case 'r':
3944           pt.x += delta;
3945           break;
3946         case 'l':
3947           break;
3948         case 'c':
3949           pt.x += delta / 2;
3950           break;
3951         default:
3952           break;
3953       }
3954       limit = ABS (r->bottom - r->top);
3955       height = Nlm_LineHeight ();
3956       delta = limit - height;
3957       if (delta > 0) {
3958         pt.y += delta / 2;
3959       }
3960       if (limit >= height) {
3961         char save;
3962         save = text[len];
3963         text[len] = 0;
3964         gdImageString ( Nlm_currentGIF, Nlm_curGIFFont, 
3965                         pt.x, pt.y,
3966                         text, Nlm_curGIFColor );
3967         text[len] = save;
3968       }
3969     }
3970   }
3971 #endif
3972 }
3973 
3974 extern void Nlm_MoveTo (Nlm_Int2 x, Nlm_Int2 y)
3975 
3976 {
3977 #ifdef WIN_MAC
3978 #ifdef WIN_MAC_QUARTZ
3979   CGContextMoveToPoint(Nlm_PeekQContext(), x, y);
3980 #else
3981   MoveTo (x, y);
3982 #endif
3983 #endif
3984 #ifdef WIN_MSWIN
3985   if (Nlm_currentHDC != NULL) {
3986     MoveToEx (Nlm_currentHDC, x, y, NULL);
3987   }
3988 #endif
3989 #ifdef WIN_X
3990   currentPoint.x = x;
3991   currentPoint.y = y;
3992 #endif
3993 #ifdef WIN_GIF
3994   Nlm_curGIFPoint.x = x;
3995   Nlm_curGIFPoint.y = y;
3996 #endif
3997 }
3998 
3999 
4000 extern void Nlm_LineTo (Nlm_Int2 x, Nlm_Int2 y)
4001 
4002 {
4003 #ifdef WIN_MAC
4004 #ifdef WIN_MAC_QUARTZ
4005   CGContextAddLineToPoint(Nlm_PeekQContext(), x, y);
4006   CGContextStrokePath(Nlm_PeekQContext());
4007   CGContextMoveToPoint(Nlm_PeekQContext(), x, y);
4008 #else
4009   LineTo (x, y);
4010 #endif
4011 #endif
4012 #ifdef WIN_MSWIN
4013   if (Nlm_currentHDC != NULL) {
4014     LineTo (Nlm_currentHDC, x, y);
4015   }
4016 #endif
4017 #ifdef WIN_X
4018   Nlm_PoinT to_point;
4019   to_point.x = x;
4020   to_point.y = y;
4021   Nlm_DrawLine(currentPoint, to_point);
4022 #endif
4023 #ifdef WIN_GIF
4024   if ( Nlm_currentGIF != NULL ){
4025     if ( Nlm_curGIFLType == GIF_DASHED ) {
4026       gdImageDashedLine ( Nlm_currentGIF, Nlm_curGIFPoint.x, Nlm_curGIFPoint.y,
4027                           x, y, Nlm_curGIFColor );
4028     } else {
4029       gdImageLine ( Nlm_currentGIF, Nlm_curGIFPoint.x, Nlm_curGIFPoint.y,
4030                     x, y, Nlm_curGIFColor );
4031     }
4032     Nlm_MoveTo ( x,y );
4033   }
4034 #endif
4035 }
4036 
4037 extern void Nlm_DrawLine (Nlm_PoinT pt1, Nlm_PoinT pt2)
4038 {
4039 #ifdef WIN_MAC
4040 #ifdef WIN_MAC_QUARTZ
4041   CGContextMoveToPoint(Nlm_PeekQContext(), pt1.x, pt1.y);
4042   CGContextAddLineToPoint(Nlm_PeekQContext(), pt2.x, pt2.y);
4043   CGContextStrokePath(Nlm_PeekQContext());
4044 #else
4045   MoveTo (pt1.x, pt1.y);
4046   LineTo (pt2.x, pt2.y);
4047 #endif
4048 #endif
4049 #ifdef WIN_MSWIN
4050   if (Nlm_currentHDC != NULL) {
4051     if (pt1.x == pt2.x  &&  pt1.y == pt2.y) {
4052       SetPixel(Nlm_currentHDC, pt1.x, pt1.y, winTextColor); /* just a dot */
4053     } else {
4054       MoveToEx(Nlm_currentHDC, pt1.x, pt1.y, NULL);
4055       LineTo  (Nlm_currentHDC, pt2.x, pt2.y);
4056     }
4057   }
4058 #endif
4059 #ifdef WIN_X
4060   if (Nlm_currentXDisplay != NULL && Nlm_currentXWindow != 0 &&
4061       Nlm_currentXGC != NULL)
4062     {
4063       XDrawLine(Nlm_currentXDisplay, Nlm_currentXWindow, Nlm_currentXGC,
4064                 pt1.x - Nlm_XOffset, pt1.y - Nlm_YOffset,
4065                 pt2.x - Nlm_XOffset, pt2.y - Nlm_YOffset);
4066       currentPoint.x = pt2.x;
4067       currentPoint.y = pt2.y;
4068     }
4069 #endif
4070 #ifdef WIN_GIF
4071   if ( Nlm_currentGIF != NULL ){
4072     if ( Nlm_curGIFLType == GIF_DASHED ) {
4073       gdImageDashedLine ( Nlm_currentGIF, pt1.x, pt1.y, pt2.x, pt2.y, 
4074                           Nlm_curGIFColor );
4075     } else {
4076       gdImageLine ( Nlm_currentGIF, pt1.x, pt1.y, pt2.x, pt2.y, 
4077                           Nlm_curGIFColor );
4078     }
4079     Nlm_MoveTo ( pt2.x, pt2.y );
4080   }
4081 #endif
4082 }
4083 
4084 #ifdef WIN_GIF
4085 static void Nlm_GIFRgnToRect ( Nlm_RgnTool t, Nlm_RectPtr r )
4086 {
4087   Nlm_RectPtr rTool;
4088 
4089   if ( t != NULL && r != NULL ){
4090     rTool = (Nlm_RectPtr)HandLock(t);
4091     *r = *rTool;
4092     HandUnlock(rTool);
4093   }
4094 }
4095 
4096 static void Nlm_RectToGIFRgn ( Nlm_RectPtr r, Nlm_RgnTool t )
4097 {
4098   Nlm_RectPtr rTool;
4099 
4100   if ( t != NULL && r != NULL ){
4101     rTool = (Nlm_RectPtr)HandLock(t);
4102     *rTool = *r;
4103     HandUnlock(rTool);
4104   }
4105 }
4106 #endif
4107 
4108 extern void Nlm_LoadPt (Nlm_PointPtr pt, Nlm_Int2 x, Nlm_Int2 y)
4109 
4110 {
4111   if (pt != NULL) {
4112     pt->x = x;
4113     pt->y = y;
4114   }
4115 }
4116 
4117 extern void Nlm_AddPt (Nlm_PoinT src, Nlm_PointPtr dst)
4118 
4119 {
4120   if (dst != NULL) {
4121     dst->x += src.x;
4122     dst->y += src.y;
4123   }
4124 }
4125 
4126 extern void Nlm_SubPt (Nlm_PoinT src, Nlm_PointPtr dst)
4127 
4128 {
4129   if (dst != NULL) {
4130     dst->x -= src.x;
4131     dst->y -= src.y;
4132   }
4133 }
4134 
4135 extern Nlm_Boolean Nlm_EqualPt (Nlm_PoinT p1, Nlm_PoinT p2)
4136 
4137 {
4138   return (Nlm_Boolean) (p1.x == p2.x && p1.y == p2.y);
4139 }
4140 
4141 extern Nlm_Boolean Nlm_PtInRect (Nlm_PoinT pt, Nlm_RectPtr r)
4142 
4143 {
4144   return (Nlm_Boolean) (r != NULL && pt.x >= r->left && pt.x < r->right &&
4145                         pt.y >= r->top && pt.y < r->bottom);
4146 }
4147 
4148 extern Nlm_Boolean Nlm_PtInRgn (Nlm_PoinT pt, Nlm_RegioN rgn)
4149 
4150 {
4151   Nlm_RgnTool    ntool;
4152   Nlm_Boolean    rsult;
4153 #ifdef WIN_MAC
4154 #ifdef WIN_MAC_QUARTZ
4155   CGPoint        ptool;
4156 #else
4157   Nlm_PointTool  ptool;
4158 #endif
4159 #endif
4160 #ifdef WIN_GIF
4161   Nlm_RecT r;
4162 #endif
4163 
4164   rsult = FALSE;
4165   if (rgn != NULL) {
4166     ntool = (Nlm_RgnTool) rgn;
4167 #ifdef WIN_MAC
4168 #ifdef WIN_MAC_QUARTZ
4169     ptool = Nlm_PoinTToCGPoint (pt);
4170     rsult = HIShapeContainsPoint (ntool, &ptool);
4171 #else
4172     Local__PoinTToPointTool (pt, &ptool);
4173     rsult = PtInRgn (ptool, ntool);
4174 #endif
4175 #endif
4176 #ifdef WIN_MSWIN
4177     rsult = (Nlm_Boolean) PtInRegion (ntool, pt.x, pt.y);
4178 #endif
4179 #ifdef WIN_X
4180     rsult = (XPointInRegion (ntool, pt.x, pt.y) != 0);
4181 #endif
4182 #ifdef WIN_GIF
4183     Nlm_GIFRgnToRect ( ntool, &r );
4184     rsult = Nlm_PtInRect (pt, &r);
4185 #endif
4186   }
4187   return rsult;
4188 }
4189 
4190 extern void Nlm_LoadRect (Nlm_RectPtr r, Nlm_Int2 lf,
4191                           Nlm_Int2 tp, Nlm_Int2 rt,
4192                           Nlm_Int2 bt)
4193 
4194 {
4195   if (r != NULL) {
4196     r->left = lf;
4197     r->top = tp;
4198     r->right = rt;
4199     r->bottom = bt;
4200   }
4201 }
4202 
4203 extern void Nlm_UpsetRect (Nlm_RectPtr r, Nlm_Int2 lf,
4204                            Nlm_Int2 tp, Nlm_Int2 rt,
4205                            Nlm_Int2 bt)
4206 
4207 {
4208   if (r != NULL) {
4209     r->left += lf;
4210     r->top += tp;
4211     r->right -= rt;
4212     r->bottom -= bt;
4213   }
4214 }
4215 
4216 extern void Nlm_OffsetRect (Nlm_RectPtr r, Nlm_Int2 dx, Nlm_Int2 dy)
4217 
4218 {
4219   if (r != NULL) {
4220     r->left += dx;
4221     r->top += dy;
4222     r->right += dx;
4223     r->bottom += dy;
4224   }
4225 }
4226 
4227 extern void Nlm_InsetRect (Nlm_RectPtr r, Nlm_Int2 dx, Nlm_Int2 dy)
4228 
4229 {
4230   if (r != NULL) {
4231     r->left += dx;
4232     r->top += dy;
4233     r->right -= dx;
4234     r->bottom -= dy;
4235   }
4236 }
4237 
4238 
4239 static void Nlm_LoadNormalized (Nlm_RectPtr dst, Nlm_RectPtr src)
4240 {
4241   if (!src  ||  !dst)
4242     return;
4243 
4244   Nlm_LoadRect(dst,
4245                (Nlm_Int2)MIN(src->left, src->right),
4246                (Nlm_Int2)MIN(src->top, src->bottom),
4247                (Nlm_Int2)MAX(src->left, src->right),
4248                (Nlm_Int2)MAX(src->top, src->bottom));
4249 }
4250 
4251 
4252 extern Nlm_Boolean Nlm_SectRect(Nlm_RectPtr src1, Nlm_RectPtr src2,
4253                                 Nlm_RectPtr dst)
4254 {
4255 #ifdef WIN_MAC_QUARTZ
4256   CGRect r1 = Nlm_RecTToCGRect (*src1);
4257   CGRect r2 = Nlm_RecTToCGRect (*src2);
4258   CGRect d  = CGRectIntersection (r1, r2);
4259   *dst = Nlm_CGRectToRecT (d);
4260   return !CGRectIsNull (d);
4261 #else
4262 
4263 #if defined(WIN_MSWIN) || (defined(WIN_MAC) && !defined(WIN_MAC_QUARTZ))
4264   Nlm_Boolean   rsult;
4265   Nlm_RectTool  rtool1;
4266   Nlm_RectTool  rtool2;
4267   Nlm_RectTool  rtool3;
4268 #elif defined(WIN_X) || defined(WIN_GIF)
4269   Nlm_RecT      rect1;
4270   Nlm_RecT      rect2;
4271 #endif
4272 
4273   if (!src1  ||  !src2  ||  !dst)
4274     return FALSE;
4275 
4276 #if defined(WIN_MSWIN) || (defined(WIN_MAC) && !defined(WIN_MAC_QUARTZ))
4277   Local__RecTToRectTool(src1, &rtool1);
4278   Local__RecTToRectTool(src2, &rtool2);
4279 #ifdef WIN_MSWIN
4280   rsult = (Nlm_Boolean)IntersectRect(&rtool3, &rtool1, &rtool2);
4281 #else
4282   rsult = SectRect(&rtool1, &rtool2, &rtool3);
4283 #endif
4284   Local__RectToolToRecT(&rtool3, dst);
4285   return rsult;
4286 
4287 #elif defined(WIN_X) || defined(WIN_GIF)
4288     Nlm_LoadNormalized(&rect1, src1);
4289     Nlm_LoadNormalized(&rect2, src2);
4290     dst->left   = MAX(rect1.left,   rect2.left  );
4291     dst->right  = MIN(rect1.right,  rect2.right );
4292     dst->top    = MAX(rect1.top,    rect2.top   );
4293     dst->bottom = MIN(rect1.bottom, rect2.bottom);
4294     if (dst->left > dst->right  ||  dst->top > dst->bottom)
4295       {
4296         Nlm_LoadRect(dst, 0, 0, 0, 0);
4297         return FALSE;
4298       }
4299     return TRUE;
4300 #endif
4301 #endif
4302 }
4303 
4304 
4305 extern Nlm_Boolean Nlm_UnionRect(Nlm_RectPtr src1, Nlm_RectPtr src2,
4306                                  Nlm_RectPtr dst)
4307 {
4308 #ifdef WIN_MAC_QUARTZ
4309   CGRect r1 = Nlm_RecTToCGRect (*src1);
4310   CGRect r2 = Nlm_RecTToCGRect (*src2);
4311   CGRect d  = CGRectUnion (r1, r2);
4312   *dst = Nlm_CGRectToRecT (d);
4313   return CGRectIsEmpty (d);
4314 #else
4315 
4316 #if defined(WIN_MSWIN) || (defined(WIN_MAC) && !defined(WIN_MAC_QUARTZ))
4317   Nlm_Boolean   rsult;
4318   Nlm_RectTool  rtool1;
4319   Nlm_RectTool  rtool2;
4320   Nlm_RectTool  rtool3;
4321 #elif defined(WIN_X) || defined(WIN_GIF)
4322   Nlm_RecT      rect1;
4323   Nlm_RecT      rect2;
4324 #endif
4325 
4326   if (!src1  ||  !src2  ||  !dst)
4327     return FALSE;
4328 
4329 #if defined(WIN_MSWIN) || (defined(WIN_MAC) && !defined(WIN_MAC_QUARTZ))
4330   Local__RecTToRectTool(src1, &rtool1);
4331   Local__RecTToRectTool(src2, &rtool2);
4332 #ifdef WIN_MSWIN
4333   rsult = (Nlm_Boolean)UnionRect(&rtool3, &rtool1, &rtool2);
4334 #else
4335   UnionRect(&rtool1, &rtool2, &rtool3);
4336   rsult = EmptyRect(&rtool3);
4337 #endif
4338   Local__RectToolToRecT(&rtool3, dst);
4339   return rsult;
4340 
4341 #elif defined(WIN_X) || defined(WIN_GIF)
4342   Nlm_LoadNormalized (&rect1, src1);
4343   Nlm_LoadNormalized (&rect2, src2);
4344   dst->left   = MIN(rect1.left,   rect2.left  );
4345   dst->right  = MAX(rect1.right,  rect2.right );
4346   dst->top    = MIN(rect1.top,    rect2.top   );
4347   dst->bottom = MAX(rect1.bottom, rect2.bottom);
4348   return TRUE;
4349 #endif
4350 #endif
4351 }
4352 
4353 
4354 extern Nlm_Boolean Nlm_EqualRect (Nlm_RectPtr r1, Nlm_RectPtr r2)
4355 
4356 {
4357   return (Nlm_Boolean) (r1 != NULL && r2 != NULL && r1->left == r2->left &&
4358                         r1->top == r2->top && r1->right == r2->right &&
4359                         r1->bottom == r2->bottom);
4360 }
4361 
4362 extern Nlm_Boolean Nlm_EmptyRect (Nlm_RectPtr r)
4363 
4364 {
4365   return (Nlm_Boolean) ! (r != NULL && r->bottom > r->top && r->right > r->left);
4366 }
4367 
4368 extern Nlm_Boolean Nlm_RectInRect (Nlm_RectPtr r1, Nlm_RectPtr r2)
4369 
4370 {
4371   Nlm_Boolean  rsult;
4372 
4373   rsult = FALSE;
4374   if (r1 != NULL && r2 != NULL &&
4375     r1->top >= r2->top && r1->bottom <= r2->bottom &&
4376     r1->left >= r2->left && r1->right <= r2->right) {
4377     rsult = TRUE;
4378   }
4379   return rsult;
4380 }
4381 
4382 extern Nlm_Boolean Nlm_RectInRgn (Nlm_RectPtr r, Nlm_RegioN rgn)
4383 
4384 {
4385   Nlm_RgnTool   ntool;
4386   Nlm_Boolean   rsult;
4387   Nlm_RectTool  rtool;
4388 #ifdef WIN_MAC_QUARTZ
4389   CGRect        rect;
4390 #endif
4391 #ifdef WIN_GIF
4392   Nlm_RecT      rect;
4393 #endif
4394 
4395   rsult = FALSE;
4396   if (r != NULL && rgn != NULL) {
4397     Local__RecTToRectTool (r, &rtool);
4398     ntool = (Nlm_RgnTool) rgn;
4399 #ifdef WIN_MAC
4400 #ifdef WIN_MAC_QUARTZ
4401     rect = Nlm_RecTToCGRect (*r);
4402     rsult = HIShapeIntersectsRect (ntool, &rect);
4403 #else
4404     rsult = RectInRgn (&rtool, ntool);
4405 #endif
4406 #endif
4407 #ifdef WIN_MSWIN
4408     rsult = (Nlm_Boolean) RectInRegion (ntool, &rtool);
4409 #endif
4410 #ifdef WIN_X
4411     rsult = (XRectInRegion (ntool, rtool.x, rtool.y, rtool.width+1, rtool.height+1) != 0);
4412 #endif
4413 #ifdef WIN_GIF
4414     Nlm_GIFRgnToRect ( ntool, &rect );
4415     rsult = Nlm_RectInRect (r, &rect) ;
4416 #endif
4417   }
4418   return rsult;
4419 }
4420 
4421 
4422 extern void Nlm_EraseRect (Nlm_RectPtr r)
4423 {
4424   Nlm_RectTool rtool;
4425   if ( !r )
4426     return;
4427 
4428   Local__RecTToRectTool(r, &rtool);
4429     
4430 #ifdef WIN_MAC
4431 #ifdef WIN_MAC_QUARTZ
4432   CGRect cgr;
4433   cgr = Nlm_RecTToCGRect(*r);
4434   CGContextSaveGState(Nlm_PeekQContext());
4435   Nlm_White();
4436   CGContextFillRect(Nlm_PeekQContext(), cgr);
4437   CGContextRestoreGState(Nlm_PeekQContext());
4438 #else
4439   EraseRect (&rtool);
4440 #endif
4441 #endif
4442 #ifdef WIN_MSWIN
4443   if (Nlm_currentHDC  &&  Nlm_currentHWnd) {
4444     Nlm_Int4 bkColor    = GetBkColor (Nlm_currentHDC);
4445     HBRUSH   hBackBrush = CreateSolidBrush (bkColor);
4446     FillRect (Nlm_currentHDC, &rtool, hBackBrush);
4447     DeleteObject (hBackBrush);
4448   }
4449 #endif
4450 #ifdef WIN_X
4451   if (Nlm_currentXDisplay  &&  Nlm_currentXWindow) {
4452     XGCValues values;
4453     XGetGCValues(Nlm_currentXDisplay, Nlm_currentXGC, GCFillStyle, &values);
4454     XSetForeground (Nlm_currentXDisplay, Nlm_currentXGC, currentBkColor);
4455     XSetFillStyle (Nlm_currentXDisplay, Nlm_currentXGC, FillSolid);
4456     XFillRectangle (Nlm_currentXDisplay, Nlm_currentXWindow, Nlm_currentXGC,
4457                     rtool.x - Nlm_XOffset, rtool.y - Nlm_YOffset,
4458                     rtool.width+1, rtool.height+1);
4459     XSetFillStyle (Nlm_currentXDisplay, Nlm_currentXGC, values.fill_style);
4460     XSetForeground (Nlm_currentXDisplay, Nlm_currentXGC, currentFgColor);
4461   }
4462 #endif
4463 #ifdef WIN_GIF
4464   if ( Nlm_currentGIF )
4465     gdImageFilledRectangle(Nlm_currentGIF, rtool.left, rtool.top, 
4466                            rtool.right, rtool.bottom, 0);
4467 #endif
4468 }
4469 
4470 
4471 extern void Nlm_FrameRect (Nlm_RectPtr r)
4472 
4473 {
4474 #ifdef WIN_MAC
4475 #ifdef WIN_MAC_QUARTZ
4476   CGRect rtool;
4477   rtool = Nlm_RecTToCGRect(*r);
4478   CGContextStrokeRect(Nlm_PeekQContext(), rtool);
4479 #else
4480   Nlm_RectTool  rtool;
4481 
4482   if (r != NULL) {
4483     Local__RecTToRectTool (r, &rtool);
4484     if (rtool.right == rtool.left) {
4485       rtool.right = rtool.left + 1;
4486     }
4487     if (rtool.bottom == rtool.top) {
4488       rtool.bottom = rtool.top + 1;
4489     }
4490     FrameRect (&rtool);
4491   }
4492 #endif
4493 #endif
4494 #ifdef WIN_MSWIN
4495   HBRUSH        oldBrush;
4496   POINT         pos;
4497   Nlm_RectTool  rtool;
4498 
4499   if (r != NULL && Nlm_currentHDC != NULL) {
4500     oldBrush = SelectObject (Nlm_currentHDC, GetStockObject (NULL_BRUSH));
4501     Local__RecTToRectTool (r, &rtool);
4502     if (rtool.right == rtool.left) {
4503       rtool.right = rtool.left + 1;
4504     }
4505     if (rtool.bottom == rtool.top) {
4506       rtool.bottom = rtool.top + 1;
4507     }
4508     if ( (rtool.bottom == (rtool.top+1)) &&
4509          (rtool.right == (rtool.left+1)) ){
4510       GetCurrentPositionEx (Nlm_currentHDC, &pos);
4511       MoveToEx (Nlm_currentHDC, rtool.left, rtool.top, NULL);
4512       LineTo (Nlm_currentHDC, rtool.left+1, rtool.top);
4513       MoveToEx (Nlm_currentHDC, pos.x, pos.y, NULL);
4514     } else {
4515       Rectangle (Nlm_currentHDC, rtool.left, rtool.top, rtool.right+1, rtool.bottom+1);
4516     }
4517     if (oldBrush != NULL) {
4518       SelectObject (Nlm_currentHDC, oldBrush);
4519     }
4520   }
4521 #endif
4522 #ifdef WIN_X
4523   Nlm_RectTool  rtool;
4524 
4525   if (r != NULL && Nlm_currentXDisplay != NULL &&
4526       Nlm_currentXWindow != 0 && Nlm_currentXGC != NULL) {
4527     Local__RecTToRectTool (r, &rtool);
4528     if ( !rtool.width  ) rtool.width++;
4529     if ( !rtool.height ) rtool.height++;
4530     XDrawRectangle (Nlm_currentXDisplay, Nlm_currentXWindow, Nlm_currentXGC,
4531                     rtool.x - Nlm_XOffset, rtool.y - Nlm_YOffset,
4532                     rtool.width, rtool.height);
4533   }
4534 #endif
4535 #ifdef WIN_GIF
4536   Nlm_RectTool  rtool;
4537 
4538   if ( r != NULL && Nlm_currentGIF != NULL ){
4539     Local__RecTToRectTool (r, &rtool);
4540     gdImageRectangle (Nlm_currentGIF, rtool.left, rtool.top, 
4541                       rtool.right, rtool.bottom, Nlm_curGIFColor );
4542   }
4543 #endif
4544 }
4545 
4546 extern void Nlm_PaintRect(Nlm_RectPtr r)
4547 
4548 {
4549 #ifndef WIN_MAC_QUARTZ
4550   Nlm_RectTool rtool;
4551   if ( !r )
4552     return;
4553   Local__RecTToRectTool(r, &rtool);
4554 #endif
4555   
4556 #ifdef WIN_MAC_QUARTZ
4557   CGRect cgr;
4558   cgr = Nlm_RecTToCGRect(*r);
4559   CGContextFillRect(Nlm_PeekQContext(), cgr);
4560 #elif defined(WIN_MAC)
4561   if (rtool.right == rtool.left) {
4562     rtool.right = rtool.left + 1;
4563   }
4564   if (rtool.bottom == rtool.top) {
4565     rtool.bottom = rtool.top + 1;
4566   }
4567   PaintRect(&rtool);
4568 
4569 #elif defined(WIN_MSWIN)
4570   if ( Nlm_currentHDC ) {
4571     HPEN oldPen = SelectObject (Nlm_currentHDC, GetStockObject (NULL_PEN));
4572     Rectangle(Nlm_currentHDC,
4573               rtool.left, rtool.top, rtool.right+2, rtool.bottom+2);
4574     if ( oldPen )
4575       SelectObject(Nlm_currentHDC, oldPen);
4576   }
4577 
4578 #elif defined(WIN_X)
4579   if (Nlm_currentXDisplay  &&  Nlm_currentXWindow  &&  Nlm_currentXGC) {
4580     XFillRectangle(Nlm_currentXDisplay, Nlm_currentXWindow, Nlm_currentXGC,
4581                    rtool.x - Nlm_XOffset, rtool.y - Nlm_YOffset,
4582                    rtool.width + 1, rtool.height + 1);
4583   }
4584 #elif defined(WIN_GIF)
4585   if ( Nlm_currentGIF ) {
4586     gdImageFilledRectangle(Nlm_currentGIF, rtool.left, rtool.top, 
4587                            rtool.right, rtool.bottom, Nlm_curGIFColor);
4588   }
4589 #endif
4590 }
4591 
4592 extern void Nlm_InvertRect (Nlm_RectPtr r)
4593 {
4594 #ifndef WIN_GIF
4595   Nlm_RectTool  rtool;
4596 #endif
4597 
4598   if (r == NULL)
4599     return;
4600 
4601 #ifdef WIN_MAC
4602 #ifdef WIN_MAC_QUARTZ
4603   /* ASSERT(false); */ /* Can't invert rectangles in Quartz */
4604 #else
4605   Local__RecTToRectTool (r, &rtool);
4606   InvertRect (&rtool);
4607 #endif
4608 #endif
4609 #ifdef WIN_MSWIN
4610   if (Nlm_currentHDC == NULL)
4611     return;
4612 
4613   Local__RecTToRectTool (r, &rtool);
4614   InvertRect (Nlm_currentHDC, &rtool);
4615 #endif
4616 #ifdef WIN_X
4617   if (Nlm_currentXDisplay == NULL  ||
4618       Nlm_currentXWindow == 0  ||  Nlm_currentXGC == NULL)
4619     return;
4620 
4621   Local__RecTToRectTool (r, &rtool);
4622   XSetFunction  (Nlm_currentXDisplay, Nlm_currentXGC, GXinvert);
4623   XSetFillStyle (Nlm_currentXDisplay, Nlm_currentXGC, FillStippled);
4624   XFillRectangle(Nlm_currentXDisplay, Nlm_currentXWindow, Nlm_currentXGC,
4625                  rtool.x - Nlm_XOffset, rtool.y - Nlm_YOffset,
4626                  rtool.width + 1, rtool.height + 1);
4627   XSetFunction  (Nlm_currentXDisplay, Nlm_currentXGC, currentFunction);
4628   XSetFillStyle (Nlm_currentXDisplay, Nlm_currentXGC, currentFillStyle);
4629 #endif
4630 }
4631 
4632 
4633 extern void Nlm_ScrollRect (Nlm_RectPtr r, Nlm_Int2 dx, Nlm_Int2 dy)
4634 
4635 {
4636 #ifdef WIN_MAC
4637   Nlm_RectTool  rtool;
4638 
4639   if (r != NULL) {
4640     Local__RecTToRectTool (r, &rtool);
4641 #ifdef WIN_MAC_QUARTZ
4642 // QUARTZ_FIXME: might want to do a little more than this
4643     HIViewSetNeedsDisplay (HIViewGetRoot (Nlm_QWindow), 1);
4644 #else
4645     ScrollRect (&rtool, dx, dy, (Nlm_RgnTool) Nlm_scrollRgn);
4646     InvalRgn ((Nlm_RgnTool) Nlm_scrollRgn);
4647 #endif
4648   }
4649 #endif
4650 #ifdef WIN_MSWIN
4651   Nlm_RectTool  rtool;
4652 
4653   if (r != NULL && Nlm_currentHDC != NULL) {
4654     SetRectRgn ((Nlm_RgnTool) Nlm_scrollRgn, 0, 0, 0, 0);
4655     Local__RecTToRectTool (r, &rtool);
4656     ScrollDC (Nlm_currentHDC, dx, dy, &rtool, &rtool,
4657               (Nlm_RgnTool) Nlm_scrollRgn, NULL);
4658     if (Nlm_currentHWnd != NULL && Nlm_scrollRgn != NULL) {
4659       FillRgn (Nlm_currentHDC, (Nlm_RgnTool) Nlm_scrollRgn,
4660                GetBackgroundBrush (Nlm_currentHWnd));
4661     }
4662     InvalidateRgn (Nlm_currentHWnd, (Nlm_RgnTool) Nlm_scrollRgn, TRUE);
4663   }
4664 #endif
4665 #ifdef WIN_X
4666   XEvent        event;
4667   unsigned int  height;
4668   Nlm_RecT      rct;
4669   Nlm_RectTool  rtool;
4670   unsigned int  width;
4671   unsigned int  dstX;
4672   unsigned int  dstY;
4673   unsigned int  srcX;
4674   unsigned int  srcY;
4675 
4676   if (r != NULL) {
4677     if (ABS (dy) >= ABS (r->bottom - r->top) || ABS (dx) >= ABS (r->right - r->left)) {
4678       Nlm_InvalRect (r);
4679       return;
4680     }
4681   }
4682   if (r != NULL && Nlm_currentXDisplay != NULL &&
4683       Nlm_currentXGC != NULL && Nlm_currentXWindow != 0) {
4684     height = ABS (r->bottom - r->top) - ABS (dy);
4685     width = ABS (r->right - r->left) - ABS (dx);
4686     if (dx > 0) {
4687       srcX = r->left - Nlm_XOffset;
4688       dstX = r->left - Nlm_XOffset + dx;
4689     } else if (dx < 0) {
4690       srcX = r->left - Nlm_XOffset - dx;
4691       dstX = r->left - Nlm_XOffset;
4692     } else {
4693       srcX = r->left - Nlm_XOffset;
4694       dstX = r->left - Nlm_XOffset;
4695     }
4696     if (dy > 0) {
4697       srcY = r->top - Nlm_YOffset;
4698       dstY = r->top - Nlm_YOffset + dy;
4699     } else if (dy < 0) {
4700       srcY = r->top - Nlm_YOffset - dy;
4701       dstY = r->top - Nlm_YOffset;
4702     } else {
4703       srcY = r->top - Nlm_YOffset;
4704       dstY = r->top - Nlm_YOffset;
4705     }
4706     if (Nlm_hasColor) {
4707       XSetForeground (Nlm_currentXDisplay, Nlm_currentXGC, currentBkColor);
4708     }
4709     XCopyArea (Nlm_currentXDisplay, Nlm_currentXWindow, Nlm_currentXWindow,
4710                Nlm_currentXGC, srcX, srcY, width, height, dstX, dstY);
4711     XSync (Nlm_currentXDisplay, FALSE);
4712     if (! XCheckTypedWindowEvent (Nlm_currentXDisplay,
4713                                   Nlm_currentXWindow, NoExpose, &event)) {
4714       while (XCheckTypedWindowEvent (Nlm_currentXDisplay,
4715              Nlm_currentXWindow, GraphicsExpose, &event)) {
4716         XClearArea (Nlm_currentXDisplay, Nlm_currentXWindow,
4717                     event.xgraphicsexpose.x, event.xgraphicsexpose.y,
4718                     event.xgraphicsexpose.width, event.xgraphicsexpose.height,
4719                     TRUE);
4720       }
4721     }
4722     if (dx > 0) {
4723       rct = *r;
4724       rct.right = rct.left + dx;
4725       Local__RecTToRectTool (&rct, &rtool);
4726       XClearArea (Nlm_currentXDisplay, Nlm_currentXWindow,
4727                   rtool.x - Nlm_XOffset, rtool.y - Nlm_YOffset,
4728                   rtool.width, rtool.height, TRUE);
4729     } else if (dx < 0) {
4730       rct = *r;
4731       rct.left = rct.right + dx;
4732       Local__RecTToRectTool (&rct, &rtool);
4733       XClearArea (Nlm_currentXDisplay, Nlm_currentXWindow,
4734                   rtool.x - Nlm_XOffset, rtool.y - Nlm_YOffset,
4735                   rtool.width, rtool.height, TRUE);
4736     }
4737     if (dy > 0) {
4738       rct = *r;
4739       rct.bottom = rct.top + dy;
4740       Local__RecTToRectTool (&rct, &rtool);
4741       XClearArea (Nlm_currentXDisplay, Nlm_currentXWindow,
4742                   rtool.x - Nlm_XOffset, rtool.y - Nlm_YOffset,
4743                   rtool.width, rtool.height, TRUE);
4744     } else if (dy < 0) {
4745       rct = *r;
4746       rct.top = rct.bottom + dy;
4747       Local__RecTToRectTool (&rct, &rtool);
4748       XClearArea (Nlm_currentXDisplay, Nlm_currentXWindow,
4749                   rtool.x - Nlm_XOffset, rtool.y - Nlm_YOffset,
4750                   rtool.width, rtool.height, TRUE);
4751     }
4752     if (Nlm_hasColor) {
4753       XSetForeground (Nlm_currentXDisplay, Nlm_currentXGC, currentFgColor);
4754     }
4755   }
4756 #endif
4757 #ifdef WIN_GIF
4758 #endif
4759 }
4760 
4761 #ifdef WIN_MAC_QUARTZ
4762 
4763 static void Nlm_addOvalToPath(CGContextRef context, CGRect r) 
4764 {     
4765   CGAffineTransform matrix;    
4766   CGContextSaveGState(context);   
4767   matrix = CGAffineTransformMake((r.size.width)/2, 0,                                     
4768     0, (r.size.height)/2,                                    
4769     r.origin.x + (r.size.width)/2,                                    
4770     r.origin.y + (r.size.height)/2);
4771   CGContextConcatCTM(context, matrix);  
4772   CGContextBeginPath(context);
4773   CGContextAddArc(context, 0, 0, 1, 0, 2*pi, true);
4774   CGContextRestoreGState(context);
4775 }
4776 #endif
4777 
4778 extern void Nlm_EraseOval (Nlm_RectPtr r)
4779 {
4780   Nlm_RectTool rtool;
4781   if ( !r )
4782     return;
4783   Local__RecTToRectTool(r, &rtool);
4784 
4785 #if   defined(WIN_MAC)
4786 #if defined(WIN_MAC_QUARTZ)
4787   {
4788   CGRect cgr;
4789   cgr = Nlm_RecTToCGRect(*r);
4790   Nlm_addOvalToPath(Nlm_PeekQContext(), cgr);
4791   }
4792   CGContextSaveGState(Nlm_PeekQContext());
4793   Nlm_White();
4794   CGContextFillPath(Nlm_PeekQContext());
4795   CGContextRestoreGState(Nlm_PeekQContext());
4796 #else
4797   EraseOval(&rtool);
4798 #endif
4799 #elif defined(WIN_MSWIN)
4800   if (Nlm_currentHDC  &&  Nlm_currentHWnd) {
4801     HPEN   xPen   = SelectObject(Nlm_currentHDC, GetStockObject(NULL_PEN));
4802     HBRUSH xBrush = SelectObject(Nlm_currentHDC,
4803                                  GetBackgroundBrush(Nlm_currentHWnd));
4804     Ellipse(Nlm_currentHDC,
4805             rtool.left, rtool.top, rtool.right + 2, rtool.bottom + 2);
4806     if ( xPen )
4807       SelectObject(Nlm_currentHDC, xPen);
4808     if ( xBrush )
4809       SelectObject(Nlm_currentHDC, xBrush);
4810   }
4811 
4812 #elif defined(WIN_X)
4813   if (Nlm_currentXDisplay  &&  Nlm_currentXWindow) {
4814     XGCValues values;
4815     XGetGCValues  (Nlm_currentXDisplay, Nlm_currentXGC, GCFillStyle, &values);
4816     XSetForeground(Nlm_currentXDisplay, Nlm_currentXGC, currentBkColor);
4817     XSetFillStyle (Nlm_currentXDisplay, Nlm_currentXGC, FillSolid);
4818     XFillArc(Nlm_currentXDisplay, Nlm_currentXWindow, Nlm_currentXGC,
4819              rtool.x - Nlm_XOffset, rtool.y - Nlm_YOffset,
4820              rtool.width, rtool.height, 0, 23040);
4821     XSetFillStyle (Nlm_currentXDisplay, Nlm_currentXGC, values.fill_style);
4822     XSetForeground(Nlm_currentXDisplay, Nlm_currentXGC, currentFgColor);
4823   }
4824 
4825 #elif defined(WIN_GIF)
4826   gdImageEllipse(Nlm_currentGIF,
4827                  (rtool.left + rtool.right) /2, (rtool.top + rtool.bottom) /2,
4828                  (rtool.right - rtool.left) /2, (rtool.bottom - rtool.top) /2,
4829                  0, TRUE);
4830 #endif
4831 }
4832 
4833 extern void Nlm_FrameOval(Nlm_RectPtr r)
4834 {
4835   Nlm_RectTool rtool;
4836   if ( !r )
4837     return;
4838   Local__RecTToRectTool(r, &rtool);
4839 
4840 #if   defined(WIN_MAC)
4841 #if defined(WIN_MAC_QUARTZ)
4842   {
4843   CGRect cgr;
4844   cgr = Nlm_RecTToCGRect(*r);
4845   Nlm_addOvalToPath(Nlm_PeekQContext(), cgr);
4846   }
4847   CGContextStrokePath(Nlm_PeekQContext());
4848 #else
4849   FrameOval(&rtool);
4850 #endif
4851 #elif defined(WIN_MSWIN)
4852   if ( Nlm_currentHDC ) {
4853     HBRUSH xBrush = SelectObject(Nlm_currentHDC, GetStockObject(NULL_BRUSH));
4854     Ellipse(Nlm_currentHDC, rtool.left, rtool.top, rtool.right, rtool.bottom);
4855     if ( xBrush )
4856       SelectObject(Nlm_currentHDC, xBrush);
4857   }
4858 
4859 #elif defined(WIN_X)
4860   if ( Nlm_currentXDisplay  &&  Nlm_currentXWindow  &&  Nlm_currentXGC) {
4861     XDrawArc(Nlm_currentXDisplay, Nlm_currentXWindow, Nlm_currentXGC,
4862              rtool.x - Nlm_XOffset, rtool.y - Nlm_YOffset,
4863              rtool.width - 1, rtool.height - 1, 0, 23040);
4864   }
4865 
4866 #elif defined(WIN_GIF)
4867   gdImageEllipse(Nlm_currentGIF,
4868                  (rtool.left + rtool.right) /2, (rtool.top + rtool.bottom) /2,
4869                  (rtool.right - rtool.left) /2, (rtool.bottom - rtool.top) /2,
4870                  Nlm_curGIFColor, FALSE);
4871 #endif
4872 }
4873 
4874 extern void Nlm_PaintOval(Nlm_RectPtr r)
4875 {
4876   Nlm_RectTool rtool;
4877   if ( !r )
4878     return;
4879   Local__RecTToRectTool(r, &rtool);
4880 
4881 #if   defined(WIN_MAC)
4882 #if defined(WIN_MAC_QUARTZ) 
4883   {
4884   CGRect cgr;
4885   cgr = Nlm_RecTToCGRect(*r);
4886   Nlm_addOvalToPath(Nlm_PeekQContext(), cgr);
4887   }
4888   CGContextFillPath(Nlm_PeekQContext());
4889 #else
4890   PaintOval(&rtool);
4891 
4892 #endif
4893 #elif defined(WIN_MSWIN)
4894   if ( Nlm_currentHDC ) {
4895     HPEN xPen = SelectObject(Nlm_currentHDC, GetStockObject(NULL_PEN));
4896     Ellipse(Nlm_currentHDC,
4897             rtool.left, rtool.top, rtool.right+1, rtool.bottom+1);
4898     if ( xPen )
4899       SelectObject(Nlm_currentHDC, xPen);
4900   }
4901 
4902 #elif defined(WIN_X)
4903   if (Nlm_currentXDisplay  &&  Nlm_currentXWindow  &&  Nlm_currentXGC) {
4904     XFillArc(Nlm_currentXDisplay, Nlm_currentXWindow, Nlm_currentXGC,
4905              rtool.x - Nlm_XOffset, rtool.y - Nlm_YOffset,
4906              rtool.width, rtool.height, 0, 23040);
4907   }
4908 
4909 #elif defined(WIN_GIF)
4910   gdImageEllipse(Nlm_currentGIF,
4911                  (rtool.left + rtool.right) /2, (rtool.top + rtool.bottom) /2,
4912                  (rtool.right - rtool.left) /2, (rtool.bottom - rtool.top) /2,
4913                  Nlm_curGIFColor, TRUE);
4914 #endif
4915 }
4916 
4917 
4918 extern void Nlm_InvertOval(Nlm_RectPtr r)
4919 {
4920   Nlm_RectTool rtool;
4921   if ( !r )
4922     return;
4923   Local__RecTToRectTool(r, &rtool);
4924 
4925 #if   defined(WIN_MAC)
4926 #ifdef WIN_MAC_QUARTZ
4927 /* QUART_FIXME: can't invert, what to do? */
4928   Nlm_PaintOval (r);
4929 #else
4930   InvertOval (&rtool);
4931 #endif
4932 
4933 #elif defined(WIN_MSWIN)
4934   if ( Nlm_currentHDC ) {
4935     HPEN   xPen   = SelectObject(Nlm_currentHDC, GetStockObject(BLACK_PEN  ));
4936     HBRUSH xBrush = SelectObject(Nlm_currentHDC, GetStockObject(BLACK_BRUSH));
4937     int    xMode  = GetROP2(Nlm_currentHDC);
4938     SetROP2(Nlm_currentHDC, R2_NOTXORPEN);
4939     Ellipse(Nlm_currentHDC,
4940             rtool.left, rtool.top, rtool.right+1, rtool.bottom+1);
4941     if ( xPen )
4942       SelectObject(Nlm_currentHDC, xPen);
4943     if ( xBrush )
4944       SelectObject(Nlm_currentHDC, xBrush);
4945     SetROP2(Nlm_currentHDC, xMode);
4946   }
4947 
4948 #elif defined(WIN_X)
4949   if (Nlm_currentXDisplay  &&  Nlm_currentXWindow  &&  Nlm_currentXGC) {
4950     XSetFunction (Nlm_currentXDisplay, Nlm_currentXGC, GXinvert);
4951     XSetFillStyle(Nlm_currentXDisplay, Nlm_currentXGC, FillStippled);
4952     XFillArc(Nlm_currentXDisplay, Nlm_currentXWindow, Nlm_currentXGC,
4953              rtool.x - Nlm_XOffset, rtool.y - Nlm_YOffset,
4954              rtool.width, rtool.height, 0, 23040);
4955     XSetFunction (Nlm_currentXDisplay, Nlm_currentXGC, currentFunction);
4956     XSetFillStyle(Nlm_currentXDisplay, Nlm_currentXGC, currentFillStyle);
4957   }
4958 #elif defined(WIN_GIF)
4959 #endif
4960 }
4961 
4962 
4963 static void s_AdjustRoundRect(const Nlm_RecT* r, Nlm_Int2 *w, Nlm_Int2 *h)
4964 {
4965   Nlm_Int2 w2, h2;
4966 
4967   w2 = r->right - r->left;  w2 = ABS(w2) / 2;
4968   if (*w > w2)
4969     *w = w2;
4970 
4971   h2 = r->bottom - r->top;  h2 = ABS(h2) / 2;
4972   if (*h > h2)
4973     *h = h2;
4974 }
4975 
4976 
4977 #ifdef WIN_MAC_QUARTZ
4978 static void addRoundedRectToPath(CGContextRef context, CGRect rect, 
4979   float ovalWidth,float ovalHeight) 
4980 {     
4981   float fw, fh;    
4982   if (ovalWidth == 0 || ovalHeight == 0) {          
4983     CGContextAddRect(context, rect);         
4984     return;     
4985   }    
4986   CGContextSaveGState(context);     
4987   CGContextTranslateCTM (context, CGRectGetMinX(rect),                           
4988   CGRectGetMinY(rect));    
4989   CGContextScaleCTM (context, ovalWidth, ovalHeight);     
4990   fw = CGRectGetWidth (rect) / ovalWidth;     
4991   fh = CGRectGetHeight (rect) / ovalHeight;     
4992   CGContextMoveToPoint(context, fw, fh/2);      
4993   CGContextAddArcToPoint(context, fw, fh, fw/2, fh, 1);     
4994   CGContextAddArcToPoint(context, 0, fh, 0, fh/2, 1);
4995   CGContextAddArcToPoint(context, 0, 0, fw/2, 0, 1);    
4996   CGContextAddArcToPoint(context, fw, 0, fw, fh/2, 1);      
4997   CGContextClosePath(context);     
4998   CGContextRestoreGState(context);  
4999 } 
5000 #endif
5001 
5002 extern void Nlm_EraseRoundRect(Nlm_RectPtr r, Nlm_Int2 ovlWid, Nlm_Int2 ovlHgt)
5003 {
5004   Nlm_RectTool rtool;
5005   if ( !r )
5006     return;
5007   Local__RecTToRectTool(r, &rtool);
5008   s_AdjustRoundRect(r, &ovlWid, &ovlHgt);
5009 
5010 #if defined(WIN_MAC)
5011 #if defined(WIN_MAC_QUARTZ)
5012   {
5013   CGRect cgr;
5014   cgr = Nlm_RecTToCGRect(*r);
5015   addRoundedRectToPath(Nlm_PeekQContext(), cgr, ovlWid, ovlHgt);
5016   }
5017   CGContextSaveGState(Nlm_PeekQContext());
5018   Nlm_White();
5019   CGContextFillPath(Nlm_PeekQContext());
5020   CGContextRestoreGState(Nlm_PeekQContext());
5021 #else
5022   EraseRoundRect(&rtool, ovlWid, ovlHgt);
5023 #endif
5024 #elif defined(WIN_MSWIN)
5025   if (Nlm_currentHDC  &&  Nlm_currentHWnd) {
5026     HPEN   xPen   = SelectObject(Nlm_currentHDC, GetStockObject(NULL_PEN));
5027     HBRUSH xBrush = SelectObject(Nlm_currentHDC,
5028                                  GetBackgroundBrush(Nlm_currentHWnd));
5029     RoundRect(Nlm_currentHDC, rtool.left, rtool.top,
5030               rtool.right + 2, rtool.bottom + 2, ovlWid, ovlHgt);
5031     if ( xPen )
5032       SelectObject(Nlm_currentHDC, xPen);
5033     if ( xBrush )
5034       SelectObject(Nlm_currentHDC, xBrush);
5035   }
5036 
5037 #elif defined(WIN_X)
5038   if (Nlm_currentXDisplay  &&  Nlm_currentXWindow  &&  Nlm_currentXGC) {
5039     XGCValues values;
5040     XGetGCValues  (Nlm_currentXDisplay, Nlm_currentXGC, GCFillStyle, &values);
5041     XSetForeground(Nlm_currentXDisplay, Nlm_currentXGC, currentBkColor);
5042     XSetFillStyle (Nlm_currentXDisplay, Nlm_currentXGC, FillSolid);
5043     XmuFillRoundedRectangle(Nlm_currentXDisplay, Nlm_currentXWindow,
5044                             Nlm_currentXGC,
5045                             rtool.x - Nlm_XOffset, rtool.y - Nlm_YOffset,
5046                             rtool.width+1, rtool.height+1, ovlWid, ovlHgt);
5047     XSetFillStyle (Nlm_currentXDisplay, Nlm_currentXGC, values.fill_style);
5048     XSetForeground(Nlm_currentXDisplay, Nlm_currentXGC, currentFgColor);
5049   }
5050 
5051 #elif defined(WIN_GIF)
5052   if ( Nlm_currentGIF ) {
5053     gdImageRoundRectangle(Nlm_currentGIF,
5054                           rtool.left, rtool.top, rtool.right, rtool.bottom,
5055                           ovlWid, ovlHgt, 0, TRUE);
5056   }
5057 #endif
5058 }
5059 
5060 
5061 extern void Nlm_FrameRoundRect(Nlm_RectPtr r, Nlm_Int2 ovlWid, Nlm_Int2 ovlHgt)
5062 {
5063   Nlm_RectTool rtool;
5064   if ( !r )
5065     return;
5066   Local__RecTToRectTool(r, &rtool);
5067   s_AdjustRoundRect(r, &ovlWid, &ovlHgt);
5068 
5069 #if   defined(WIN_MAC)
5070 #if defined(WIN_MAC_QUARTZ)
5071   {
5072   CGRect cgr;
5073   cgr = Nlm_RecTToCGRect(*r);
5074   addRoundedRectToPath(Nlm_PeekQContext(), cgr, ovlWid, ovlHgt);
5075   }
5076   CGContextStrokePath(Nlm_PeekQContext());
5077 #else
5078   FrameRoundRect(&rtool, ovlWid, ovlHgt);
5079 #endif
5080 #elif defined(WIN_MSWIN)
5081   if ( Nlm_currentHDC ) {
5082     HBRUSH xBrush = SelectObject(Nlm_currentHDC, GetStockObject(NULL_BRUSH));
5083     RoundRect(Nlm_currentHDC, rtool.left, rtool.top,
5084               rtool.right + 1, rtool.bottom + 1, ovlWid, ovlHgt);
5085     if ( xBrush )
5086       SelectObject(Nlm_currentHDC, xBrush);
5087   }
5088 
5089 #elif defined(WIN_X)
5090   if (Nlm_currentXDisplay  &&  Nlm_currentXWindow  &&  Nlm_currentXGC) {
5091     XmuDrawRoundedRectangle(Nlm_currentXDisplay, Nlm_currentXWindow,
5092                             Nlm_currentXGC,
5093                             rtool.x - Nlm_XOffset, rtool.y - Nlm_YOffset,
5094                             rtool.width, rtool.height, ovlWid, ovlHgt);
5095   }
5096 
5097 #elif defined(WIN_GIF)
5098   if ( Nlm_currentGIF ) {
5099     gdImageRoundRectangle(Nlm_currentGIF,
5100                           rtool.left, rtool.top, rtool.right, rtool.bottom,
5101                           ovlWid, ovlHgt, Nlm_curGIFColor, FALSE);
5102   }
5103 #endif
5104 }
5105 
5106 
5107 extern void Nlm_PaintRoundRect(Nlm_RectPtr r, Nlm_Int2 ovlWid, Nlm_Int2 ovlHgt)
5108 {
5109   Nlm_RectTool rtool;
5110   if ( !r )
5111     return;
5112   Local__RecTToRectTool(r, &rtool);
5113   s_AdjustRoundRect(r, &ovlWid, &ovlHgt);
5114 
5115 #if   defined(WIN_MAC)
5116 #if defined(WIN_MAC_QUARTZ)
5117   {
5118   CGRect cgr;
5119   cgr = Nlm_RecTToCGRect(*r);
5120   addRoundedRectToPath(Nlm_PeekQContext(), cgr, ovlWid, ovlHgt);
5121   }
5122   CGContextFillPath(Nlm_PeekQContext());
5123 #else
5124   PaintRoundRect(&rtool, ovlWid, ovlHgt);
5125 #endif
5126 #elif defined(WIN_MSWIN)
5127   if ( Nlm_currentHDC ) {
5128     HPEN xPen = SelectObject(Nlm_currentHDC, GetStockObject(NULL_PEN));
5129     RoundRect(Nlm_currentHDC, rtool.left, rtool.top,
5130               rtool.right + 2, rtool.bottom + 2, ovlWid, ovlHgt);
5131     if ( xPen )
5132       SelectObject(Nlm_currentHDC, xPen);
5133   }
5134 
5135 #elif defined(WIN_X)
5136   if (Nlm_currentXDisplay  &&  Nlm_currentXWindow  &&  Nlm_currentXGC) {
5137     XmuFillRoundedRectangle(Nlm_currentXDisplay, Nlm_currentXWindow,
5138                             Nlm_currentXGC,
5139                             rtool.x - Nlm_XOffset, rtool.y - Nlm_YOffset,
5140                             rtool.width+1, rtool.height+1, ovlWid, ovlHgt);
5141   }
5142 
5143 #elif defined(WIN_GIF)
5144   if ( Nlm_currentGIF ) {
5145     gdImageRoundRectangle(Nlm_currentGIF,
5146                           rtool.left, rtool.top, rtool.right, rtool.bottom,
5147                           ovlWid, ovlHgt, Nlm_curGIFColor, TRUE);
5148   }
5149 #endif
5150 }
5151 
5152 
5153 extern void Nlm_InvertRoundRect(Nlm_RectPtr r,
5154                                 Nlm_Int2 ovlWid, Nlm_Int2 ovlHgt)
5155 {
5156   Nlm_RectTool rtool;
5157   if ( !r )
5158     return;
5159   Local__RecTToRectTool(r, &rtool);
5160   s_AdjustRoundRect(r, &ovlWid, &ovlHgt);
5161 
5162 #if   defined(WIN_MAC)
5163 #ifdef WIN_MAC_QUARTZ
5164 /* QUARTZ_FIXME: can't invert, what to do? */
5165   Nlm_PaintRoundRect (r, ovlWid, ovlHgt);
5166 #else
5167   InvertRoundRect (&rtool, ovlWid, ovlHgt);
5168 #endif
5169 
5170 #elif defined(WIN_MSWIN)
5171   if ( Nlm_currentHDC ) {
5172     HPEN   xPen   = SelectObject(Nlm_currentHDC, GetStockObject(BLACK_PEN  ));
5173     HBRUSH xBrush = SelectObject(Nlm_currentHDC, GetStockObject(BLACK_BRUSH));
5174     int    xMode  = GetROP2(Nlm_currentHDC);
5175     SetROP2(Nlm_currentHDC, R2_NOTXORPEN);
5176     RoundRect(Nlm_currentHDC, rtool.left, rtool.top,
5177               rtool.right + 2, rtool.bottom + 2, ovlWid, ovlHgt);
5178     if ( xPen )
5179       SelectObject(Nlm_currentHDC, xPen);
5180     if ( xBrush )
5181       SelectObject(Nlm_currentHDC, xBrush);
5182     SetROP2(Nlm_currentHDC, xMode);
5183   }
5184 
5185 #elif defined(WIN_X)
5186   if (Nlm_currentXDisplay  &&  Nlm_currentXWindow  &&  Nlm_currentXGC) {
5187     XSetFunction  (Nlm_currentXDisplay, Nlm_currentXGC, GXinvert);
5188     XSetFillStyle (Nlm_currentXDisplay, Nlm_currentXGC, FillStippled);
5189     XmuFillRoundedRectangle(Nlm_currentXDisplay, Nlm_currentXWindow,
5190                             Nlm_currentXGC,
5191                             rtool.x - Nlm_XOffset, rtool.y - Nlm_YOffset,
5192                             rtool.width+1, rtool.height+1, ovlWid, ovlHgt);
5193     XSetFunction  (Nlm_currentXDisplay, Nlm_currentXGC, currentFunction);
5194     XSetFillStyle (Nlm_currentXDisplay, Nlm_currentXGC, currentFillStyle);
5195   }
5196 #elif defined(WIN_GIF)
5197 #endif
5198 }
5199 
5200 
5201 #ifdef WIN_X
5202 static int Nlm_PtToAngle (Nlm_RectPtr r, Nlm_PoinT pt)
5203 
5204 {
5205   int     rsult;
5206   double  val;
5207   double  x;
5208   double  y;
5209 
5210   x = pt.x - (r->right + r->left) / 2;
5211   y = (r->bottom + r->top) / 2 - pt.y;
5212   if (x == 0) {
5213     rsult = 5760;
5214   } else if (y == 0) {
5215     rsult = 0;
5216   } else {
5217     val = atan2 (ABS (y), ABS (x));
5218     rsult = (int)(val * 11520.0 / 3.14159);
5219   }
5220   if (x < 0) {
5221     if (y < 0) {
5222       rsult = 11520 + rsult;
5223     } else {
5224       rsult = 11520 - rsult;
5225     }
5226   } else if (y < 0) {
5227     rsult = 23040 - rsult;
5228   }
5229   return rsult;
5230 }
5231 #endif
5232 
5233 
5234 #ifdef WIN_MAC_QUARTZ
5235 /*
5236 static void pathForArc (CGContextRef context, CGRect r,                      
5237                 int startAngle, int arcAngle) 
5238 {
5239   float start, end;     
5240   CGAffineTransform matrix;
5241   CGContextSaveGState(context);
5242   matrix = CGAffineTransformMake(r.size.width/2, 0,                                     
5243                                 0, r.size.height/2,                                    
5244                                 r.origin.x + r.size.width/2,                                   
5245                                 r.origin.y + r.size.height/2);
5246   CGContextConcatCTM(context, matrix);
5247   if (arcAngle > 0) {          
5248     start = (90 - startAngle - arcAngle) * M_PI / 180;         
5249     end = (90 - startAngle) * M_PI / 180;     
5250   } else {         
5251     start = (90 - startAngle) * M_PI / 180;         
5252     end = (90 - startAngle - arcAngle) * M_PI / 180;     
5253   } 
5254   CGContextAddArc (context, 0, 0, 1, start, end, false);   
5255   CGContextRestoreGState(context);  
5256 }
5257 */
5258 
5259 static void pathForArc (CGContextRef context, CGRect r,   
5260 CGPoint startPt, CGPoint endPt) 
5261 {
5262   float start, end;     
5263   CGAffineTransform matrix, invMatrix;
5264   CGContextSaveGState(context);
5265   matrix = CGAffineTransformMake(r.size.width/2, 0,                                     
5266                                 0, r.size.height/2,                                    
5267                                 r.origin.x + r.size.width/2,                                   
5268                                 r.origin.y + r.size.height/2);
5269   CGContextConcatCTM(context, matrix);
5270                                 
5271   invMatrix = CGAffineTransformInvert(matrix);
5272   startPt = CGPointApplyAffineTransform(startPt, invMatrix);
5273   endPt = CGPointApplyAffineTransform(endPt, invMatrix);
5274   start = atan2(startPt.y, startPt.x);
5275   end   = atan2(  endPt.y,   endPt.x);
5276     
5277   
5278   CGContextAddArc (context, 0, 0, 1, start, end, 0);   
5279   CGContextRestoreGState(context);  
5280 }
5281 
5282 #endif
5283 
5284 
5285 extern void Nlm_EraseArc(Nlm_RectPtr r, Nlm_PoinT start, Nlm_PoinT end)
5286 {
5287   Nlm_RectTool rtool;
5288   if ( !r )
5289     return;
5290   Local__RecTToRectTool(r, &rtool);
5291 
5292 #if   defined(WIN_MAC)
5293   {{
5294 #if   defined(WIN_MAC_QUARTZ)
5295     CGRect  cgr;
5296     CGPoint startPt;
5297     CGPoint endPt;
5298     
5299     cgr = Nlm_RecTToCGRect(*r);
5300     startPt = Nlm_PoinTToCGPoint(start);
5301     endPt = Nlm_PoinTToCGPoint(end);
5302     Nlm_MoveTo((r->right + r->left)/2, (r->top + r->bottom)/2);
5303     pathForArc (Nlm_PeekQContext(), cgr, startPt, endPt);
5304     
5305     CGContextSaveGState(Nlm_PeekQContext());
5306     Nlm_White();
5307     CGContextFillPath(Nlm_PeekQContext());
5308     CGContextRestoreGState(Nlm_PeekQContext());
5309 #else
5310     Nlm_Int2      angle1;
5311     Nlm_Int2      angle2;
5312     Nlm_Int2      arcAngle;
5313     Nlm_PointTool ptool1;
5314     Nlm_PointTool ptool2;
5315     Nlm_RectTool  rtool;
5316 
5317     Local__RecTToRectTool(r, &rtool);
5318     Local__PoinTToPointTool(start, &ptool1);
5319     Local__PoinTToPointTool(  end, &ptool2);
5320     PtToAngle(&rtool, ptool1, &angle1);
5321     PtToAngle(&rtool, ptool2, &angle2);
5322     if (angle2 > angle1)
5323       arcAngle = angle2 - angle1;
5324     else
5325       arcAngle = 360 - angle1 + angle2;
5326 
5327     EraseArc(&rtool, angle1, arcAngle);
5328 #endif
5329   }}
5330 
5331 #elif defined(WIN_MSWIN)
5332   if (Nlm_currentHDC  &&  Nlm_currentHWnd) {
5333     HPEN   xPen   = SelectObject(Nlm_currentHDC, GetStockObject(NULL_PEN));
5334     HBRUSH xBrush = SelectObject(Nlm_currentHDC,
5335                                  GetBackgroundBrush(Nlm_currentHWnd));
5336     Pie(Nlm_currentHDC,
5337         rtool.left, rtool.top, rtool.right + 2, rtool.bottom + 2,
5338         end.x, end.y, start.x, start.y);
5339     if ( xPen )
5340       SelectObject(Nlm_currentHDC, xPen);
5341     if ( xBrush )
5342       SelectObject(Nlm_currentHDC, xBrush);
5343   }
5344 
5345 #elif defined(WIN_X)
5346   if (Nlm_currentXDisplay  &&  Nlm_currentXWindow) {
5347     XGCValues values;
5348     int angle1 = Nlm_PtToAngle(r, start);
5349     int angle2 = Nlm_PtToAngle(r, end);
5350     int arcAngle;
5351 
5352     if (angle1 > angle2)
5353       arcAngle = angle1 - angle2;
5354     else
5355       arcAngle = 23040 - angle2 + angle1;
5356 
5357     XGetGCValues  (Nlm_currentXDisplay, Nlm_currentXGC, GCFillStyle, &values);
5358     XSetForeground(Nlm_currentXDisplay, Nlm_currentXGC, currentBkColor);
5359     XSetFillStyle (Nlm_currentXDisplay, Nlm_currentXGC, FillSolid);
5360     XFillArc(Nlm_currentXDisplay, Nlm_currentXWindow, Nlm_currentXGC,
5361              rtool.x - Nlm_XOffset, rtool.y - Nlm_YOffset,
5362              rtool.width, rtool.height, angle1, -arcAngle);
5363     XSetFillStyle (Nlm_currentXDisplay, Nlm_currentXGC, values.fill_style);
5364     XSetForeground(Nlm_currentXDisplay, Nlm_currentXGC, currentFgColor);
5365   }
5366 #elif defined(WIN_GIF)
5367 #endif
5368 }
5369 
5370 extern void Nlm_FrameArc(Nlm_RectPtr r, Nlm_PoinT start, Nlm_PoinT end)
5371 {
5372   Nlm_RectTool rtool;
5373   if ( !r )
5374     return;
5375   Local__RecTToRectTool(r, &rtool);
5376 
5377 #if   defined(WIN_MAC)
5378   {{
5379 #if   defined(WIN_MAC_QUARTZ)
5380     CGRect  cgr;
5381     CGPoint startPt;
5382     CGPoint endPt;
5383     
5384     cgr = Nlm_RecTToCGRect(*r);
5385     startPt = Nlm_PoinTToCGPoint(start);
5386     endPt = Nlm_PoinTToCGPoint(end);
5387     pathForArc (Nlm_PeekQContext(), cgr, startPt, endPt);
5388     CGContextStrokePath(Nlm_PeekQContext());
5389 #else
5390     Nlm_Int2      angle1;
5391     Nlm_Int2      angle2;
5392     Nlm_Int2      arcAngle;
5393     Nlm_PointTool ptool1;
5394     Nlm_PointTool ptool2;
5395 
5396     Local__PoinTToPointTool(start, &ptool1);
5397     Local__PoinTToPointTool(  end, &ptool2);
5398     PtToAngle(&rtool, ptool1, &angle1);
5399     PtToAngle(&rtool, ptool2, &angle2);
5400     if (angle2 > angle1) {
5401       arcAngle = angle2 - angle1;
5402     } else {
5403       arcAngle = 360 - angle1 + angle2;
5404     }
5405     FrameArc (&rtool, angle1, arcAngle);
5406 #endif
5407   }}
5408 
5409 #elif defined(WIN_MSWIN)
5410   if ( Nlm_currentHDC ) {
5411     HBRUSH xBrush = SelectObject(Nlm_currentHDC, GetStockObject(NULL_BRUSH));
5412     Arc(Nlm_currentHDC, rtool.left, rtool.top, rtool.right+1, rtool.bottom+1,
5413         end.x, end.y, start.x, start.y);
5414     if ( xBrush )
5415       SelectObject(Nlm_currentHDC, xBrush);
5416   }
5417 
5418 #elif defined(WIN_X)
5419   if (Nlm_currentXDisplay  &&  Nlm_currentXWindow  &&  Nlm_currentXGC) {
5420     int angle1 = Nlm_PtToAngle(r, start);
5421     int angle2 = Nlm_PtToAngle(r, end);
5422     int arcAngle = angle1 > angle2 ? angle1 - angle2 : 23040 - angle2 + angle1;
5423     XDrawArc(Nlm_currentXDisplay, Nlm_currentXWindow, Nlm_currentXGC,
5424              rtool.x - Nlm_XOffset, rtool.y - Nlm_YOffset,
5425              rtool.width - 1, rtool.height - 1, angle1, -arcAngle);
5426   }
5427 
5428 #elif defined(WIN_GIF)
5429   {{
5430     int cx = (rtool.left + rtool.right) / 2;
5431     int cy = (rtool.top + rtool.bottom) / 2;
5432     double s_angle = atan2(start.x - cx, start.y - cy); 
5433     double e_angle = atan2(end.x   - cx, end.y   - cy); 
5434     gdImageArcEx(Nlm_currentGIF, cx, cy,
5435                  (rtool.right - rtool.left) /2, (rtool.bottom - rtool.top) /2,
5436                  s_angle, e_angle, Nlm_curGIFColor, FALSE);
5437   }}
5438 #endif
5439 }
5440 
5441 extern void Nlm_PaintArc(Nlm_RectPtr r, Nlm_PoinT start, Nlm_PoinT end)
5442 {
5443   Nlm_RectTool rtool;
5444   if ( !r )
5445     return;
5446   Local__RecTToRectTool(r, &rtool);
5447 
5448 #if   defined(WIN_MAC)
5449   {{
5450 #if   defined(WIN_MAC_QUARTZ)
5451     CGRect  cgr;
5452     CGPoint startPt;
5453     CGPoint endPt;
5454     
5455     cgr = Nlm_RecTToCGRect(*r);
5456     startPt = Nlm_PoinTToCGPoint(start);
5457     endPt = Nlm_PoinTToCGPoint(end);
5458     Nlm_MoveTo((r->right + r->left)/2, (r->top + r->bottom)/2);
5459     pathForArc (Nlm_PeekQContext(), cgr, startPt, endPt);
5460     CGContextFillPath(Nlm_PeekQContext());
5461 #else
5462     Nlm_Int2       angle1;
5463     Nlm_Int2       angle2;
5464     Nlm_Int2       arcAngle;
5465     Nlm_PointTool  ptool1;
5466     Nlm_PointTool  ptool2;
5467 
5468     Local__PoinTToPointTool(start, &ptool1);
5469     Local__PoinTToPointTool(end, &ptool2);
5470     PtToAngle(&rtool, ptool1, &angle1);
5471     PtToAngle(&rtool, ptool2, &angle2);
5472     if (angle2 > angle1)
5473       arcAngle = angle2 - angle1;
5474     else
5475       arcAngle = 360 - angle1 + angle2;
5476 
5477     PaintArc(&rtool, angle1, arcAngle);
5478 #endif
5479   }}
5480 
5481 #elif defined(WIN_MSWIN)
5482   if ( Nlm_currentHDC ) {
5483     HPEN xPen = SelectObject(Nlm_currentHDC, GetStockObject(NULL_PEN));
5484     Pie(Nlm_currentHDC,
5485         rtool.left, rtool.top, rtool.right + 2, rtool.bottom + 2,
5486         end.x, end.y, start.x, start.y);
5487     if ( xPen )
5488       SelectObject(Nlm_currentHDC, xPen);
5489   }
5490 
5491 #elif defined(WIN_X)
5492   if (Nlm_currentXDisplay  &&  Nlm_currentXWindow  &&  Nlm_currentXGC) {
5493     int angle1 = Nlm_PtToAngle(r, start);
5494     int angle2 = Nlm_PtToAngle(r, end);
5495     int arcAngle;
5496 
5497     if (angle1 > angle2)
5498       arcAngle = angle1 - angle2;
5499     else
5500       arcAngle = 23040 - angle2 + angle1;
5501 
5502     XFillArc(Nlm_currentXDisplay, Nlm_currentXWindow, Nlm_currentXGC,
5503              rtool.x - Nlm_XOffset, rtool.y - Nlm_YOffset,
5504              rtool.width, rtool.height, angle1, -arcAngle);
5505   }
5506 
5507 #elif defined(WIN_GIF)
5508   {{
5509     int cx = (rtool.left + rtool.right) / 2;
5510     int cy = (rtool.top + rtool.bottom) / 2;
5511     double s_angle = atan2(start.x - cx, start.y - cy); 
5512     double e_angle = atan2(end.x   - cx, end.y   - cy); 
5513     gdImageArcEx(Nlm_currentGIF, cx, cy,
5514                  (rtool.right - rtool.left) /2, (rtool.bottom - rtool.top) /2,
5515                  s_angle, e_angle, Nlm_curGIFColor, TRUE);
5516   }}
5517 #endif
5518 }
5519 
5520 extern void Nlm_InvertArc(Nlm_RectPtr r, Nlm_PoinT start, Nlm_PoinT end)
5521 {
5522   Nlm_RectTool rtool;
5523   if ( !r )
5524     return;
5525   Local__RecTToRectTool(r, &rtool);
5526 
5527 #if   defined(WIN_MAC)
5528 #ifdef WIN_MAC_QUARTZ
5529 /* QUARTZ_FIXME: can't invert, what to do? */
5530   Nlm_PaintArc (r, start, end);
5531 #else
5532   {{
5533     Nlm_Int2      angle1;
5534     Nlm_Int2      angle2;
5535     Nlm_Int2      arcAngle;
5536     Nlm_PointTool ptool1;
5537     Nlm_PointTool ptool2;
5538     Nlm_RectTool  rtool;
5539 
5540     Local__RecTToRectTool(r, &rtool);
5541     Local__PoinTToPointTool(start, &ptool1);
5542     Local__PoinTToPointTool(end,   &ptool2);
5543     PtToAngle(&rtool, ptool1, &angle1);
5544     PtToAngle(&rtool, ptool2, &angle2);
5545     if (angle2 > angle1)
5546       arcAngle = angle2 - angle1;
5547     else
5548       arcAngle = 360 - angle1 + angle2;
5549 
5550     InvertArc(&rtool, angle1, arcAngle);
5551   }}
5552 #endif
5553 
5554 #elif defined(WIN_MSWIN)
5555   if ( Nlm_currentHDC ) {
5556     HPEN   xPen   = SelectObject(Nlm_currentHDC, GetStockObject(BLACK_PEN  ));
5557     HBRUSH xBrush = SelectObject(Nlm_currentHDC, GetStockObject(BLACK_BRUSH));
5558     int    xMode  = GetROP2(Nlm_currentHDC);
5559     SetROP2(Nlm_currentHDC, R2_NOTXORPEN);
5560     Pie(Nlm_currentHDC,
5561         rtool.left, rtool.top, rtool.right + 2, rtool.bottom + 2,
5562         end.x, end.y, start.x, start.y);
5563     if ( xPen )
5564       SelectObject(Nlm_currentHDC, xPen);
5565     if ( xBrush )
5566       SelectObject(Nlm_currentHDC, xBrush);
5567     SetROP2(Nlm_currentHDC, xMode);
5568   }
5569 
5570 #elif defined(WIN_X)
5571   if (Nlm_currentXDisplay  &&  Nlm_currentXWindow  &&  Nlm_currentXGC) {
5572     int angle1 = Nlm_PtToAngle(r, start);
5573     int angle2 = Nlm_PtToAngle(r, end);
5574     int arcAngle;
5575 
5576     if (angle1 > angle2)
5577       arcAngle = angle1 - angle2;
5578     else
5579       arcAngle = 23040 - angle2 + angle1;
5580 
5581     XSetFunction (Nlm_currentXDisplay, Nlm_currentXGC, GXinvert);
5582     XSetFillStyle(Nlm_currentXDisplay, Nlm_currentXGC, FillStippled);
5583     XFillArc(Nlm_currentXDisplay, Nlm_currentXWindow, Nlm_currentXGC,
5584              rtool.x - Nlm_XOffset, rtool.y - Nlm_YOffset,
5585              rtool.width, rtool.height, angle1, -arcAngle);
5586     XSetFunction (Nlm_currentXDisplay, Nlm_currentXGC, currentFunction);
5587     XSetFillStyle(Nlm_currentXDisplay, Nlm_currentXGC, currentFillStyle);
5588   }
5589 #elif defined(WIN_GIF)
5590 #endif
5591 }
5592 
5593 typedef enum {
5594   eDM_Erase = 0,
5595   eDM_Frame,
5596   eDM_Paint,
5597   eDM_Invert
5598 } EDrawMethod;
5599 
5600 
5601 /*********************************
5602  *  QUADRANT
5603  */
5604 
5605 static void s_DoQuadrant(Nlm_RectPtr r, Nlm_EQuadrant quadrant,
5606                          EDrawMethod method)
5607 {
5608   Nlm_RecT rr;
5609   Nlm_Int2 rx, ry;
5610 
5611   Nlm_LoadNormalized(&rr, r);
5612   rx = rr.right  - rr.left;
5613   ry = rr.bottom - rr.top;
5614   
5615 #ifdef WIN_GIF
5616   {{
5617     int cx = 0, cy = 0;
5618 
5619     switch ( quadrant ) {
5620     case eQ_RightTop:
5621       cx = rr.left;   cy = rr.bottom;  break;
5622     case eQ_LeftTop:
5623       cx = rr.right;  cy = rr.bottom;  break;
5624     case eQ_LeftBottom:
5625       cx = rr.right;  cy = rr.top;     break;
5626     case eQ_RightBottom:
5627       cx = rr.left;   cy = rr.top;     break;
5628     }
5629 
5630     gdImageQuadrant(Nlm_currentGIF, cx, cy, rx, ry,
5631                     (method == eDM_Erase) ? 0 : Nlm_curGIFColor,
5632                     (method != eDM_Frame), (int)quadrant);
5633   }}
5634 #else
5635   {{
5636     Nlm_PoinT start, stop;
5637     switch ( quadrant ) {
5638     case eQ_RightTop:
5639       start.x = rr.left;   start.y = rr.top;
5640       stop.x  = rr.right;  stop.y  = rr.bottom;
5641       rr.left -= rx;  rr.bottom += ry;
5642       break;
5643     case eQ_LeftTop:
5644       start.x = rr.left;   start.y  = rr.bottom;
5645       stop.x  = rr.right;  stop.y = rr.top;
5646       rr.right += rx;  rr.bottom += ry;
5647       break;
5648     case eQ_LeftBottom:
5649       start.x = rr.right;  start.y = rr.bottom;
5650       stop.x  = rr.left;   stop.y  = rr.top;
5651       rr.right += rx;  rr.top -= ry;
5652       break;
5653     case eQ_RightBottom:
5654       start.x = rr.right;  start.y = rr.top;
5655       stop.x  = rr.left;   stop.y  = rr.bottom;
5656       rr.left -= rx;  rr.top -= ry;
5657       break;
5658     }
5659 
5660     switch ( method ) {
5661     case eDM_Erase:
5662       Nlm_EraseArc(&rr, start, stop);  break;
5663     case eDM_Frame:
5664       Nlm_FrameArc(&rr, start, stop);  break;
5665     case eDM_Paint:
5666       Nlm_PaintArc(&rr, start, stop);  break;
5667     case eDM_Invert:
5668       Nlm_InvertArc(&rr, start, stop); break;
5669     }
5670   }}
5671 #endif
5672 }
5673 
5674 void Nlm_EraseQuadrant(Nlm_RectPtr r, Nlm_EQuadrant quadrant) {
5675   s_DoQuadrant(r, quadrant, eDM_Erase);
5676 }
5677 void Nlm_FrameQuadrant(Nlm_RectPtr r, Nlm_EQuadrant quadrant) {
5678   s_DoQuadrant(r, quadrant, eDM_Frame);
5679 }
5680 void Nlm_PaintQuadrant(Nlm_RectPtr r, Nlm_EQuadrant quadrant) {
5681   s_DoQuadrant(r, quadrant, eDM_Paint);
5682 }
5683 void Nlm_InvertQuadrant(Nlm_RectPtr r, Nlm_EQuadrant quadrant) {
5684   s_DoQuadrant(r, quadrant, eDM_Invert);
5685 }
5686 
5687 
5688 /*********************************
5689  *  POLYGON
5690  */
5691 
5692 #ifdef WIN_MAC
5693 #ifdef WIN_MAC_QUARTZ
5694 static void Nlm_CreatePoly (Nlm_Int2 num, Nlm_PointPtr pts)
5695 {
5696   Nlm_PoinT   firstPt;
5697   Nlm_Int2    i;
5698   Nlm_PoinT   pt;
5699 
5700   if (pts != NULL && num > 0) {
5701     firstPt = pts [0];
5702     CGContextMoveToPoint(Nlm_PeekQContext(), (float) firstPt.x, (float) firstPt.y);
5703     for (i = 1; i < num; i++) {
5704       pt = pts [i];
5705       CGContextAddLineToPoint(Nlm_PeekQContext(), (float) pt.x, (float) pt.y);
5706     }
5707     if (! Nlm_EqualPt (pt, firstPt)) {
5708       CGContextClosePath(Nlm_PeekQContext());
5709     }
5710   }  
5711 }
5712 
5713 #else
5714 static PolyHandle Nlm_CreatePoly (Nlm_Int2 num, Nlm_PointPtr pts)
5715 
5716 {
5717   Nlm_PoinT   firstPt;
5718   Nlm_Int2    i;
5719   Nlm_PoinT   pt;
5720   PolyHandle  rsult;
5721 
5722   rsult = NULL;
5723   if (pts != NULL && num > 0) {
5724     rsult = OpenPoly ();
5725     firstPt = pts [0];
5726     MoveTo (firstPt.x, firstPt.y);
5727     for (i = 1; i < num; i++) {
5728       pt = pts [i];
5729       LineTo (pt.x, pt.y);
5730     }
5731     if (! Nlm_EqualPt (pt, firstPt)) {
5732       LineTo (firstPt.x, firstPt.y);
5733     }
5734     ClosePoly ();
5735   }
5736   return rsult;
5737 }
5738 
5739 static void Nlm_DestroyPoly (PolyHandle ply)
5740 
5741 {
5742   if (ply != NULL) {
5743     KillPoly (ply);
5744   }
5745 }
5746 #endif
5747 #endif
5748 
5749 #ifdef WIN_MSWIN
5750 static LPPOINT Nlm_CreatePoly (Nlm_Int2 num, Nlm_PointPtr pts)
5751 
5752 {
5753   Nlm_PoinT      firstPt;
5754   Nlm_Int2       i;
5755   Nlm_PoinT      pt;
5756   Nlm_PointTool  ptool;
5757   LPPOINT        rsult;
5758 
5759   rsult = NULL;
5760   if (pts != NULL && num > 0) {
5761     rsult = (LPPOINT) Nlm_MemNew ((size_t) ((num + 1) * sizeof (POINT)));
5762     if (rsult != NULL) {
5763       firstPt = pts [0];
5764       for (i = 0; i < num; i++) {
5765         pt = pts [i];
5766         Local__PoinTToPointTool (pt, &ptool);
5767         rsult [i] = ptool;
5768       }
5769       if (! Nlm_EqualPt (pt, firstPt)) {
5770         Local__PoinTToPointTool (firstPt, &ptool);
5771         rsult [i] = ptool;
5772       }
5773     }
5774   }
5775   return rsult;
5776 }
5777 
5778 static void Nlm_DestroyPoly (LPPOINT ply)
5779 
5780 {
5781   if (ply != NULL) {
5782     Nlm_MemFree (ply);
5783   }
5784 }
5785 #endif
5786 
5787 #ifdef WIN_X
5788 static XPoint *Nlm_CreatePoly (Nlm_Int2 num, Nlm_PointPtr pts)
5789 
5790 {
5791   Nlm_PoinT      firstPt;
5792   Nlm_Int2       i;
5793   Nlm_PoinT      pt;
5794   Nlm_PointTool  ptool;
5795   XPoint         *rsult;
5796 
5797   rsult = NULL;
5798   if (pts != NULL && num > 0) {
5799     rsult = (XPoint *) Nlm_MemNew ((size_t) ((num + 1) * sizeof (XPoint)));
5800     if (rsult != NULL) {
5801       firstPt = pts [0];
5802       firstPt.x -= Nlm_XOffset;
5803       firstPt.y -= Nlm_YOffset;
5804       for (i = 0; i < num; i++) {
5805         pt = pts [i];
5806         pt.x -= Nlm_XOffset;
5807         pt.y -= Nlm_YOffset;
5808         Local__PoinTToPointTool (pt, &ptool);
5809         rsult [i] = ptool;
5810       }
5811       if (! Nlm_EqualPt (pt, firstPt)) {
5812         Local__PoinTToPointTool (firstPt, &ptool);
5813         rsult [i] = ptool;
5814       }
5815     }
5816   }
5817   return rsult;
5818 }
5819 
5820 static void Nlm_DestroyPoly (XPoint *ply)
5821 
5822 {
5823   if (ply != NULL) {
5824     Nlm_MemFree (ply);
5825   }
5826 }
5827 #endif
5828 
5829 extern void Nlm_ErasePoly (Nlm_Int2 num, Nlm_PointPtr pts)
5830 
5831 {
5832   if (pts != NULL && num > 1) {
5833 #ifdef WIN_MAC
5834 #ifdef WIN_MAC_QUARTZ
5835   Nlm_CreatePoly (num, pts);
5836   CGContextSaveGState(Nlm_PeekQContext());
5837   Nlm_White();
5838   CGContextEOFillPath(Nlm_PeekQContext());
5839   CGContextRestoreGState(Nlm_PeekQContext());
5840 #else
5841   PolyHandle   ply;
5842 
5843   ply = Nlm_CreatePoly (num, pts);
5844   if (ply != NULL) {
5845     ErasePoly (ply);
5846   }
5847   Nlm_DestroyPoly (ply);
5848 #endif
5849 #endif
5850 #ifdef WIN_MSWIN
5851 #endif
5852 #ifdef WIN_X
5853 #endif
5854 #ifdef WIN_GIF
5855 #endif
5856   }
5857 }
5858 
5859 
5860 extern void Nlm_FramePoly(Nlm_Int2 num, Nlm_PointPtr pts)
5861 {
5862   if (pts != NULL && num > 1) {
5863 #ifdef WIN_MAC
5864 #ifdef WIN_MAC_QUARTZ
5865   Nlm_CreatePoly (num, pts);
5866   CGContextStrokePath(Nlm_PeekQContext());
5867 #else
5868   PolyHandle   ply;
5869 
5870   ply = Nlm_CreatePoly (num, pts);
5871   if (ply != NULL) {
5872     FramePoly (ply);
5873   }
5874   Nlm_DestroyPoly (ply);
5875 #endif
5876 #endif
5877 #ifdef WIN_MSWIN
5878   LPPOINT  ply;
5879 
5880   ply = Nlm_CreatePoly (num, pts);
5881   if (Nlm_currentHDC != NULL && ply != NULL) {
5882     if (! Nlm_EqualPt (pts [0], pts [num - 1])) {
5883       num++;
5884     }
5885     Polyline (Nlm_currentHDC, ply, num);
5886   }
5887   Nlm_DestroyPoly (ply);
5888 #endif
5889 #ifdef WIN_X
5890   XPoint  *ply;
5891 
5892   ply = Nlm_CreatePoly (num, pts);
5893   if (Nlm_currentXDisplay != NULL && Nlm_currentXWindow != 0 &&
5894       Nlm_currentXGC != NULL && ply != NULL) {
5895     if (! Nlm_EqualPt (pts [0], pts [num - 1])) {
5896       num++;
5897     }
5898     XDrawLines (Nlm_currentXDisplay, Nlm_currentXWindow, Nlm_currentXGC,
5899                 ply, num, CoordModeOrigin);
5900   }
5901   Nlm_DestroyPoly (ply);
5902 #endif
5903 #ifdef WIN_GIF
5904   gdPointPtr pPtr;
5905   int        i;
5906 
5907   if (Nlm_currentGIF != NULL && pts != NULL) {
5908     pPtr = (gdPointPtr)Nlm_MemNew(num * sizeof(gdPoint));
5909     for ( i=0; i<num; i++ ){
5910       pPtr[i].x = pts[i].x;
5911       pPtr[i].y = pts[i].y;
5912     }
5913     gdImagePolygon ( Nlm_currentGIF,  pPtr, num, Nlm_curGIFColor );
5914     MemFree (pPtr);
5915   }
5916 #endif
5917   }
5918 }
5919 
5920 extern void Nlm_PaintPoly (Nlm_Int2 num, Nlm_PointPtr pts)
5921 
5922 {
5923   if (pts != NULL && num > 1) {
5924 #ifdef WIN_MAC
5925 #ifdef WIN_MAC_QUARTZ
5926   Nlm_CreatePoly (num, pts);
5927   CGContextEOFillPath(Nlm_PeekQContext());
5928 #else
5929   PolyHandle   ply;
5930 
5931   ply = Nlm_CreatePoly (num, pts);
5932   if (ply != NULL) {
5933     PaintPoly (ply);
5934   }
5935   Nlm_DestroyPoly (ply);
5936 #endif
5937 #endif
5938 #ifdef WIN_MSWIN
5939   LPPOINT  ply;
5940 
5941   ply = Nlm_CreatePoly (num, pts);
5942   if (Nlm_currentHDC != NULL && ply != NULL) {
5943     if (! Nlm_EqualPt (pts [0], pts [num - 1])) {
5944       num++;
5945     }
5946     SetPolyFillMode (Nlm_currentHDC, ALTERNATE);
5947     Polygon (Nlm_currentHDC, ply, num);
5948   }
5949   Nlm_DestroyPoly (ply);
5950 #endif
5951 #ifdef WIN_X
5952   XPoint  *ply = Nlm_CreatePoly (num, pts);
5953   if (Nlm_currentXDisplay != NULL && Nlm_currentXWindow != 0 &&
5954       Nlm_currentXGC != NULL && ply != NULL)
5955     {
5956       int i;
5957       short left=32767, top=32767; 
5958       for (i = 0;  i < num;  i++)
5959         {
5960           if (ply[i].x < left)
5961             left = ply[i].x;
5962           if (ply[i].y < top)
5963             top  = ply[i].y;
5964         }
5965       for (i = 0;  i < num;  i++)
5966         {
5967           if (ply[i].x != left)
5968             ply[i].x++;
5969           if (ply[i].y != top)
5970             ply[i].y++;
5971         }
5972 
5973       XSetFillRule (Nlm_currentXDisplay, Nlm_currentXGC, EvenOddRule);
5974       XFillPolygon (Nlm_currentXDisplay, Nlm_currentXWindow, Nlm_currentXGC,
5975                     ply, num, Complex, CoordModeOrigin);
5976     }
5977   Nlm_DestroyPoly (ply);
5978 #endif
5979 #ifdef WIN_GIF
5980   gdPointPtr pPtr;
5981   int        i;
5982 
5983   if (Nlm_currentGIF != NULL && pts != NULL) {
5984     pPtr = (gdPointPtr)Nlm_MemNew(num * sizeof(gdPoint));
5985     for ( i=0; i<num; i++ ){
5986       pPtr[i].x = pts[i].x;
5987       pPtr[i].y = pts[i].y;
5988     }
5989     gdImageFilledPolygon ( Nlm_currentGIF,  pPtr, num, Nlm_curGIFColor );
5990     MemFree (pPtr);
5991   }
5992 #endif
5993   }
5994 }
5995 
5996 extern void Nlm_InvertPoly (Nlm_Int2 num, Nlm_PointPtr pts)
5997 
5998 {
5999   if (pts != NULL && num > 1) {
6000 #ifdef WIN_MAC
6001 #ifdef WIN_MAC_QUARTZ
6002 #else
6003   PolyHandle   ply;
6004 
6005   ply = Nlm_CreatePoly (num, pts);
6006   if (ply != NULL) {
6007     InvertPoly (ply);
6008   }
6009   Nlm_DestroyPoly (ply);
6010 #endif
6011 #endif
6012 #ifdef WIN_MSWIN
6013 #endif
6014 #ifdef WIN_X
6015 #endif
6016 #ifdef WIN_GIF
6017 #endif
6018   }
6019 }
6020 
6021 extern Nlm_RegioN Nlm_CreateRgn (void)
6022 
6023 {
6024   Nlm_RgnTool  ntool;
6025 
6026 #ifdef WIN_MAC
6027 #ifdef WIN_MAC_QUARTZ
6028   ntool = HIShapeCreateMutable();
6029 #else
6030   ntool = NewRgn ();
6031 #endif
6032 #endif
6033 #ifdef WIN_MSWIN
6034   ntool = CreateRectRgn (0, 0, 0, 0);
6035 #endif
6036 #ifdef WIN_X
6037   ntool = XCreateRegion ();
6038 #endif
6039 #ifdef WIN_GIF
6040   ntool = HandNew ( sizeof(Nlm_RecT) );
6041 #endif
6042   return (Nlm_RegioN) ntool;
6043 }
6044 
6045 extern Nlm_RegioN Nlm_DestroyRgn (Nlm_RegioN rgn)
6046 
6047 {
6048   Nlm_RgnTool  ntool;
6049 
6050   if (rgn != NULL) {
6051     ntool = (Nlm_RgnTool) rgn;
6052 #ifdef WIN_MAC
6053 #ifdef WIN_MAC_QUARTZ
6054     CFRelease (ntool);
6055 #else
6056     DisposeRgn (ntool);
6057 #endif
6058 #endif
6059 #ifdef WIN_MSWIN
6060     DeleteObject (ntool);
6061 #endif
6062 #ifdef WIN_X
6063     XDestroyRegion (ntool);
6064 #endif
6065 #ifdef WIN_GIF
6066     HandFree ( ntool );
6067 #endif
6068   }
6069   return NULL;
6070 }
6071 
6072 extern void Nlm_ClearRgn (Nlm_RegioN rgn)
6073 
6074 {
6075   Nlm_RgnTool  ntool;
6076 #ifdef WIN_MSWIN
6077   Nlm_RgnTool  temp;
6078 #endif
6079 
6080   if (rgn != NULL) {
6081     ntool = (Nlm_RgnTool) rgn;
6082 #ifdef WIN_MAC
6083 #ifdef WIN_MAC_QUARTZ
6084     HIShapeSetEmpty (ntool);
6085 #else
6086     SetEmptyRgn (ntool);
6087 #endif
6088 #endif
6089 #ifdef WIN_MSWIN
6090     temp = CreateRectRgn (0, 0, 0, 0);
6091     CombineRgn (ntool, temp, temp, RGN_COPY);
6092     DeleteObject (temp);
6093 #endif
6094 #ifdef WIN_X
6095     XUnionRegion (emptyRgn, emptyRgn, ntool);
6096 #endif
6097   } 
6098 }
6099 
6100 extern void Nlm_LoadRectRgn (Nlm_RegioN rgn, Nlm_Int2 lf,
6101                              Nlm_Int2 tp, Nlm_Int2 rt,
6102                              Nlm_Int2 bt)
6103 
6104 {
6105   Nlm_RgnTool   ntool;
6106 #ifdef WIN_X
6107   Nlm_RecT      rct;
6108   Nlm_RectTool  rtool;
6109 #endif
6110 #ifdef WIN_GIF
6111   Nlm_RecT      rct;
6112 #endif
6113 
6114   if (rgn != NULL) {
6115     ntool = (Nlm_RgnTool) rgn;
6116 #ifdef WIN_MAC
6117 #ifdef WIN_MAC_QUARTZ
6118     HIShapeSetEmpty (ntool);
6119     
6120     CGRect r = CGRectMake (lf, tp, rt - lf, bt - tp);
6121     HIShapeRef tempShape = HIShapeCreateWithRect (&r);
6122     HIShapeUnion (tempShape, ntool, ntool);
6123     CFRelease (tempShape);
6124 #else
6125     SetRectRgn (ntool, lf, tp, rt, bt);
6126 #endif
6127 #endif
6128 #ifdef WIN_MSWIN
6129     SetRectRgn (ntool, lf, tp, rt, bt);
6130 #endif
6131 #ifdef WIN_X
6132     Nlm_LoadRect (&rct, lf, tp, rt, bt);
6133     Local__RecTToRectTool (&rct, &rtool);
6134     XUnionRectWithRegion (&rtool, emptyRgn, ntool);
6135 #endif
6136 #ifdef WIN_GIF
6137     Nlm_LoadRect (&rct, lf, tp, rt, bt);
6138     Nlm_RectToGIFRgn ( &rct, ntool );
6139 #endif
6140   }
6141 }
6142 
6143 extern void Nlm_OffsetRgn (Nlm_RegioN rgn, Nlm_Int2 dx, Nlm_Int2 dy)
6144 
6145 {
6146   Nlm_RgnTool  ntool;
6147 #ifdef WIN_GIF
6148   Nlm_RecT rTool;
6149 #endif
6150 
6151   if (rgn != NULL) {
6152     ntool = (Nlm_RgnTool) rgn;
6153 #ifdef WIN_MAC
6154 #ifdef WIN_MAC_QUARTZ
6155     HIShapeOffset (ntool, dx, dy);
6156 #else
6157     OffsetRgn (ntool, dx, dy);
6158 #endif
6159 #endif
6160 #ifdef WIN_MSWIN
6161     OffsetRgn (ntool, dx, dy);
6162 #endif
6163 #ifdef WIN_X
6164     XOffsetRegion (ntool, dx, dy);
6165 #endif
6166 #ifdef WIN_GIF
6167     Nlm_GIFRgnToRect ( ntool, &rTool );
6168     Nlm_OffsetRect ( &rTool, dx, dy );
6169     Nlm_RectToGIFRgn ( &rTool, ntool );
6170 #endif
6171   }
6172 }
6173 
6174 extern void Nlm_SectRgn (Nlm_RegioN src1, Nlm_RegioN src2, Nlm_RegioN dst)
6175 
6176 {
6177   Nlm_RgnTool  ntool1;
6178   Nlm_RgnTool  ntool2;
6179   Nlm_RgnTool  ntool3;
6180 #ifdef WIN_X
6181   Nlm_RgnTool  temp;
6182 #endif
6183 #ifdef WIN_GIF
6184   Nlm_RecT     rsrc1;
6185   Nlm_RecT     rsrc2;
6186   Nlm_RecT     rdst;
6187 #endif
6188 
6189   if (src1 != NULL && src2 != NULL && dst != NULL) {
6190     ntool1 = (Nlm_RgnTool) src1;
6191     ntool2 = (Nlm_RgnTool) src2;
6192     ntool3 = (Nlm_RgnTool) dst;
6193 #ifdef WIN_MAC
6194 #ifdef WIN_MAC_QUARTZ
6195     HIShapeIntersect (ntool1, ntool2, ntool3);
6196 #else
6197     SectRgn (ntool1, ntool2, ntool3);
6198 #endif
6199 #endif
6200 #ifdef WIN_MSWIN
6201     CombineRgn (ntool3, ntool1, ntool2, RGN_AND);
6202 #endif
6203 #ifdef WIN_X
6204     temp = XCreateRegion ();
6205     XIntersectRegion (ntool1, ntool2, temp);
6206     XUnionRegion (temp, emptyRgn, ntool3);
6207     XDestroyRegion (temp);
6208 #endif
6209 #ifdef WIN_GIF
6210     Nlm_GIFRgnToRect ( ntool1, &rsrc1 );
6211     Nlm_GIFRgnToRect ( ntool2, &rsrc2 );
6212     Nlm_SectRect ( &rsrc1, &rsrc2, &rdst );
6213     Nlm_RectToGIFRgn ( &rdst, ntool3 );
6214 #endif
6215   }
6216 }
6217 
6218 extern void Nlm_UnionRgn (Nlm_RegioN src1, Nlm_RegioN src2, Nlm_RegioN dst)
6219 
6220 {
6221   Nlm_RgnTool  ntool1;
6222   Nlm_RgnTool  ntool2;
6223   Nlm_RgnTool  ntool3;
6224 #ifdef WIN_X
6225   Nlm_RgnTool  temp;
6226 #endif
6227 #ifdef WIN_GIF
6228   Nlm_RecT     rsrc1;
6229   Nlm_RecT     rsrc2;
6230   Nlm_RecT     rdst;
6231 #endif
6232 
6233   if (src1 != NULL && src2 != NULL && dst != NULL) {
6234     ntool1 = (Nlm_RgnTool) src1;
6235     ntool2 = (Nlm_RgnTool) src2;
6236     ntool3 = (Nlm_RgnTool) dst;
6237 #ifdef WIN_MAC
6238 #ifdef WIN_MAC_QUARTZ
6239     HIShapeUnion( ntool1, ntool2, ntool3);
6240 #else
6241     UnionRgn (ntool1, ntool2, ntool3);
6242 #endif
6243 #endif
6244 #ifdef WIN_MSWIN
6245     CombineRgn (ntool3, ntool1, ntool2, RGN_OR);
6246 #endif
6247 #ifdef WIN_X
6248     temp = XCreateRegion ();
6249     XUnionRegion (ntool1, ntool2, temp);
6250     XUnionRegion (temp, emptyRgn, ntool3);
6251     XDestroyRegion (temp);
6252 #endif
6253 #ifdef WIN_GIF
6254     Nlm_GIFRgnToRect ( ntool1, &rsrc1 );
6255     Nlm_GIFRgnToRect ( ntool2, &rsrc2 );
6256     Nlm_UnionRect ( &rsrc1, &rsrc2, &rdst );
6257     Nlm_RectToGIFRgn ( &rdst, ntool3 );
6258 #endif
6259   }
6260 }
6261 
6262 extern void Nlm_DiffRgn (Nlm_RegioN src1, Nlm_RegioN src2, Nlm_RegioN dst)
6263 
6264 {
6265   Nlm_RgnTool  ntool1;
6266   Nlm_RgnTool  ntool2;
6267   Nlm_RgnTool  ntool3;
6268 #ifdef WIN_X
6269   Nlm_RgnTool  temp;
6270 #endif
6271 
6272   if (src1 != NULL && src2 != NULL && dst != NULL) {
6273     ntool1 = (Nlm_RgnTool) src1;
6274     ntool2 = (Nlm_RgnTool) src2;
6275     ntool3 = (Nlm_RgnTool) dst;
6276 #ifdef WIN_MAC
6277 #ifdef WIN_MAC_QUARTZ
6278     HIShapeDifference (ntool1, ntool2, ntool3);
6279 #else
6280     DiffRgn (ntool1, ntool2, ntool3);
6281 #endif
6282 #endif
6283 #ifdef WIN_MSWIN
6284     CombineRgn (ntool3, ntool1, ntool2, RGN_DIFF);
6285 #endif
6286 #ifdef WIN_X
6287     temp = XCreateRegion ();
6288     XSubtractRegion (ntool1, ntool2, temp);
6289     XUnionRegion (temp, emptyRgn, ntool3);
6290     XDestroyRegion (temp);
6291 #endif
6292   }
6293 }
6294 
6295 extern void Nlm_XorRgn (Nlm_RegioN src1, Nlm_RegioN src2, Nlm_RegioN dst)
6296 
6297 {
6298 #ifdef WIN_MAC_QUARTZ
6299 /* this is actually a general solution, but less efficient
6300    Quartz has no choice but to use it since HIShape does not support
6301    the xor operation natively
6302    
6303    xor is equivalent to the union minus the intersection, so we do that */
6304 
6305   Nlm_RegioN   sum = Nlm_CreateRgn();
6306   Nlm_RegioN   intersection = Nlm_CreateRgn();
6307   
6308   Nlm_UnionRgn (src1, src2, sum);
6309   Nlm_SectRgn (src1, src2, intersection);
6310   Nlm_DiffRgn (sum, intersection, dst);
6311   
6312   Nlm_DestroyRgn (sum);
6313   Nlm_DestroyRgn (intersection);
6314 #else
6315   
6316   Nlm_RgnTool  ntool1;
6317   Nlm_RgnTool  ntool2;
6318   Nlm_RgnTool  ntool3;
6319 #ifdef WIN_X
6320   Nlm_RgnTool  temp;
6321 #endif
6322 
6323   if (src1 != NULL && src2 != NULL && dst != NULL) {
6324     ntool1 = (Nlm_RgnTool) src1;
6325     ntool2 = (Nlm_RgnTool) src2;
6326     ntool3 = (Nlm_RgnTool) dst;
6327 #ifdef WIN_MAC
6328     XorRgn (ntool1, ntool2, ntool3);
6329 #endif
6330 #ifdef WIN_MSWIN
6331     CombineRgn (ntool3, ntool1, ntool2, RGN_XOR);
6332 #endif
6333 #ifdef WIN_X
6334     temp = XCreateRegion ();
6335     XXorRegion (ntool1, ntool2, temp);
6336     XUnionRegion (temp, emptyRgn, ntool3);
6337     XDestroyRegion (temp);
6338 #endif
6339   }
6340 #endif
6341 }
6342 
6343 extern Nlm_Boolean Nlm_EqualRgn (Nlm_RegioN rgn1, Nlm_RegioN rgn2)
6344 
6345 {
6346   Nlm_RgnTool  ntool1;
6347   Nlm_RgnTool  ntool2;
6348   Nlm_Boolean  rsult;
6349 
6350   rsult = FALSE;
6351   if (rgn1 != NULL && rgn2 != NULL) {
6352     ntool1 = (Nlm_RgnTool) rgn1;
6353     ntool2 = (Nlm_RgnTool) rgn2;
6354 #ifdef WIN_MAC
6355 #ifdef WIN_MAC_QUARTZ
6356     /* HIShapeRefs are CFTypeRefs so we can use CFEqual */
6357     rsult = CFEqual (ntool1, ntool2);
6358 #else
6359     rsult = EqualRgn (ntool1, ntool2);
6360 #endif
6361 #endif
6362 #ifdef WIN_MSWIN
6363     rsult = (Nlm_Boolean) EqualRgn (ntool1, ntool2);
6364 #endif
6365 #ifdef WIN_X
6366     rsult = (XEqualRegion (ntool1, ntool2) != 0);
6367 #endif
6368   }
6369   return rsult;
6370 }
6371 
6372 extern Nlm_Boolean Nlm_EmptyRgn (Nlm_RegioN rgn)
6373 
6374 {
6375   Nlm_RgnTool   ntool;
6376   Nlm_Boolean   rsult;
6377 #ifdef WIN_MSWIN
6378   Nlm_RectTool  rtool;
6379 #endif
6380 
6381   rsult = FALSE;
6382   if (rgn != NULL) {
6383     ntool = (Nlm_RgnTool) rgn;
6384 #ifdef WIN_MAC
6385 #ifdef WIN_MAC_QUARTZ
6386     rsult = HIShapeIsEmpty (ntool);
6387 #else
6388     rsult = EmptyRgn (ntool);
6389 #endif
6390 #endif
6391 #ifdef WIN_MSWIN
6392     rsult = (Nlm_Boolean) (GetRgnBox (ntool, &rtool) == NULLREGION);
6393 #endif
6394 #ifdef WIN_X
6395     rsult = (XEmptyRegion (ntool) != 0);
6396 #endif
6397   }
6398   return rsult;
6399 }
6400 
6401 extern void Nlm_EraseRgn (Nlm_RegioN rgn)
6402 
6403 {
6404 #ifdef WIN_MAC
6405   Nlm_RgnTool  ntool;
6406 
6407   if (rgn != NULL) {
6408     ntool = (Nlm_RgnTool) rgn;
6409 #ifdef WIN_MAC_QUARTZ
6410     HIShapeReplacePathInCGContext (ntool, Nlm_PeekQContext());
6411     
6412     Nlm_SelectQuartzColor (Nlm_QuartzBackColor);
6413     CGContextFillPath (Nlm_PeekQContext());
6414     Nlm_SelectQuartzColor (Nlm_QuartzForeColor);
6415 #else
6416     EraseRgn (ntool);
6417 #endif
6418   }
6419 #endif
6420 #ifdef WIN_MSWIN
6421   Nlm_RgnTool  ntool;
6422 
6423   if (rgn != NULL && Nlm_currentHDC != NULL && Nlm_currentHWnd != NULL) {
6424     ntool = (Nlm_RgnTool) rgn;
6425     FillRgn (Nlm_currentHDC, ntool, GetBackgroundBrush (Nlm_currentHWnd));
6426   }
6427 #endif
6428 #ifdef WIN_X
6429 #endif
6430 }
6431 
6432 extern void Nlm_FrameRgn (Nlm_RegioN rgn)
6433 
6434 {
6435 #ifdef WIN_MAC
6436   Nlm_RgnTool  ntool;
6437 
6438   if (rgn != NULL) {
6439     ntool = (Nlm_RgnTool) rgn;
6440 #ifdef WIN_MAC_QUARTZ
6441     HIShapeReplacePathInCGContext (ntool, Nlm_PeekQContext());
6442     CGContextStrokePath (Nlm_PeekQContext());
6443 #else
6444     FrameRgn (ntool);
6445 #endif
6446   }
6447 #endif
6448 #ifdef WIN_MSWIN
6449   Nlm_RgnTool  ntool;
6450 
6451   if (rgn != NULL && Nlm_currentHDC != NULL) {
6452     ntool = (Nlm_RgnTool) rgn;
6453     FrameRgn (Nlm_currentHDC, ntool, GetStockObject (BLACK_BRUSH), 1, 1);
6454   }
6455 #endif
6456 #ifdef WIN_X
6457 #endif
6458 }
6459 
6460 extern void Nlm_PaintRgn (Nlm_RegioN rgn)
6461 
6462 {
6463 #ifdef WIN_MAC
6464   Nlm_RgnTool  ntool;
6465 
6466   if (rgn != NULL) {
6467     ntool = (Nlm_RgnTool) rgn;
6468 #ifdef WIN_MAC_QUARTZ
6469     HIShapeReplacePathInCGContext (ntool, Nlm_PeekQContext());
6470     CGContextFillPath (Nlm_PeekQContext());
6471 #else
6472     PaintRgn (ntool);
6473 #endif
6474   }
6475 #endif
6476 #ifdef WIN_MSWIN
6477   Nlm_RgnTool  ntool;
6478   HBRUSH       oldBrush;
6479 
6480   if (rgn != NULL && Nlm_currentHDC != NULL) {
6481     ntool = (Nlm_RgnTool) rgn;
6482     oldBrush = SelectObject (Nlm_currentHDC, GetStockObject (BLACK_BRUSH));
6483     if (oldBrush != NULL) {
6484       SelectObject (Nlm_currentHDC, oldBrush);
6485       FillRgn (Nlm_currentHDC, ntool, oldBrush);
6486     }
6487   }
6488 #endif
6489 #ifdef WIN_X
6490 #endif
6491 }
6492 
6493 extern void Nlm_InvertRgn (Nlm_RegioN rgn)
6494 
6495 {
6496 #ifdef WIN_MAC
6497   Nlm_RgnTool  ntool;
6498 
6499   if (rgn != NULL) {
6500     ntool = (Nlm_RgnTool) rgn;
6501 #ifdef WIN_MAC_QUARTZ
6502 // QUARTZ_FIXME: this operation does not make sense in quartz, what to do?
6503 #else
6504     InvertRgn (ntool);
6505 #endif
6506   }
6507 #endif
6508 #ifdef WIN_MSWIN
6509   Nlm_RgnTool  ntool;
6510 
6511   if (rgn != NULL && Nlm_currentHDC != NULL) {
6512     ntool = (Nlm_RgnTool) rgn;
6513     InvertRgn (Nlm_currentHDC, ntool);
6514   }
6515 #endif
6516 #ifdef WIN_X
6517 #endif
6518 }
6519 
6520 extern void Nlm_ClipRect (Nlm_RectPtr r)
6521 
6522 {
6523 #ifdef WIN_MAC
6524   Nlm_RectTool  rtool;
6525 
6526   if (r != NULL) {
6527     Local__RecTToRectTool (r, &rtool);
6528 #ifdef WIN_MAC_QUARTZ
6529     if (Nlm_PeekQContext())
6530     {
6531       CGRect cgr = Nlm_RecTToCGRect (*r);
6532       
6533       CGContextClipToRect (Nlm_PeekQContext(), cgr);
6534     }
6535 #else
6536     ClipRect (&rtool);
6537 #endif
6538   }
6539 #endif
6540 #ifdef WIN_MSWIN
6541   HRGN  hRgnClip;
6542 
6543   if (r != NULL && Nlm_currentHDC != NULL) {
6544     hRgnClip = CreateRectRgn (r->left, r->top, r->right, r->bottom);
6545     SelectClipRgn (Nlm_currentHDC, hRgnClip);
6546     DeleteObject (hRgnClip);
6547   }
6548 #endif
6549 #ifdef WIN_X
6550   Nlm_RectTool  rtool;
6551 
6552   if (r != NULL && Nlm_currentXDisplay != NULL && Nlm_currentXGC != NULL) {
6553     Local__RecTToRectTool (r, &rtool);
6554     rtool.x -= Nlm_XOffset;
6555     rtool.y -= Nlm_YOffset;
6556     XSetClipRectangles (Nlm_currentXDisplay, Nlm_currentXGC, 0, 0, &rtool, 1, Unsorted);
6557     if (Nlm_clpRgn != NULL) {
6558       XDestroyRegion ((Nlm_RgnTool) Nlm_clpRgn);
6559       Nlm_clpRgn = NULL;
6560     }
6561     Nlm_clpRgn = (Nlm_RegioN) XCreateRegion ();
6562     XUnionRectWithRegion (&rtool, (Nlm_RgnTool) Nlm_clpRgn, (Nlm_RgnTool) Nlm_clpRgn);
6563     XOffsetRegion ((Nlm_RgnTool) Nlm_clpRgn, Nlm_XOffset, Nlm_YOffset);
6564   }
6565 #endif
6566 }
6567 
6568 extern void Nlm_ClipRgn (Nlm_RegioN rgn)
6569 
6570 {
6571 #ifdef WIN_MAC
6572   Nlm_RgnTool  ntool;
6573 
6574   if (rgn != NULL) {
6575     ntool = (Nlm_RgnTool) rgn;
6576 #ifdef WIN_MAC_QUARTZ
6577     HIShapeReplacePathInCGContext (ntool, Nlm_PeekQContext());
6578     CGContextClip (Nlm_PeekQContext());
6579 #else
6580     SetClip (ntool);
6581 #endif
6582   }
6583 #endif
6584 #ifdef WIN_MSWIN
6585   Nlm_RgnTool  ntool;
6586 
6587   if (rgn != NULL && Nlm_currentHDC != NULL) {
6588     ntool = (Nlm_RgnTool) rgn;
6589     SelectClipRgn (Nlm_currentHDC, ntool);
6590   }
6591 #endif
6592 #ifdef WIN_X
6593   Nlm_RgnTool  ntool1;
6594   Nlm_RgnTool  ntool2;
6595 
6596   if (rgn != NULL && Nlm_currentXDisplay != NULL && Nlm_currentXGC != NULL) {
6597     ntool1 = XCreateRegion ();
6598     ntool2 = XCreateRegion ();
6599     XUnionRegion ((Nlm_RgnTool) rgn, ntool1, ntool2);
6600     XOffsetRegion (ntool2, -Nlm_XOffset, -Nlm_YOffset);
6601     XSetRegion (Nlm_currentXDisplay, Nlm_currentXGC, ntool2);
6602     if (Nlm_clpRgn != NULL) {
6603       XDestroyRegion ((Nlm_RgnTool) Nlm_clpRgn);
6604       Nlm_clpRgn = NULL;
6605     }
6606     Nlm_clpRgn = (Nlm_RegioN) XCreateRegion ();
6607     XUnionRegion ((Nlm_RgnTool) rgn, ntool1, (Nlm_RgnTool) Nlm_clpRgn);
6608     XOffsetRegion ((Nlm_RgnTool) Nlm_clpRgn, -Nlm_XOffset, -Nlm_YOffset);
6609     XDestroyRegion (ntool1);
6610     XDestroyRegion (ntool2);
6611   }
6612 #endif
6613 }
6614 
6615 extern void Nlm_ResetClip (void)
6616 
6617 {
6618 #ifdef WIN_MAC
6619 #ifdef WIN_MAC_QUARTZ
6620 // QUARTZ_FIXME: CGContext clips can only contract, not expand, needs to be handled by popping the context, but callers don't know about that... maybe have the global context always be inherently pushed, and this can pop and immediately re-push?
6621 #else
6622   Nlm_RecT      r;
6623   Nlm_RectTool  rtool;
6624 
6625   Nlm_LoadRect (&r, -32767, -32767, 32767, 32767);
6626   Local__RecTToRectTool (&r, &rtool);
6627   ClipRect (&rtool);
6628 #endif
6629 #endif
6630 #ifdef WIN_MSWIN
6631   if (Nlm_currentHDC != NULL) {
6632     SelectClipRgn (Nlm_currentHDC, NULL);
6633   }
6634 #endif
6635 #ifdef WIN_X
6636   if (Nlm_currentXDisplay != NULL && Nlm_currentXGC != NULL) {
6637     XSetClipMask (Nlm_currentXDisplay, Nlm_currentXGC, None);
6638     if (Nlm_clpRgn != NULL) {
6639       XDestroyRegion ((Nlm_RgnTool) Nlm_clpRgn);
6640       Nlm_clpRgn = NULL;
6641     }
6642   }
6643 #endif
6644 }
6645 
6646 extern void Nlm_ValidRect (Nlm_RectPtr r)
6647 
6648 {
6649 #ifdef WIN_MAC
6650 #ifdef WIN_MAC_QUARTZ
6651 // QUARTZ_FIXME: do we care? just let it redraw
6652 #else
6653   Nlm_RectTool  rtool;
6654 
6655   if (r != NULL) {
6656     Local__RecTToRectTool (r, &rtool);
6657     ValidRect (&rtool);
6658   }
6659 #endif
6660 #endif
6661 #ifdef WIN_MSWIN
6662   Nlm_RectTool  rtool;
6663 
6664   if (r != NULL && Nlm_currentHWnd != NULL) {
6665     Local__RecTToRectTool (r, &rtool);
6666     ValidateRect (Nlm_currentHWnd, &rtool);
6667   }
6668 #endif
6669 #ifdef WIN_X
6670 #endif
6671 }
6672 
6673 extern void Nlm_InvalRect (Nlm_RectPtr r)
6674 
6675 {
6676 #ifdef WIN_MAC
6677 #ifdef WIN_MAC_QUARTZ
6678 // QUARTZ_FIXME: this could stand to be a little more fine-grained
6679   HIViewRef view = HIViewGetRoot (Nlm_QWindow);
6680   HIViewSetNeedsDisplay (view, 1);
6681 #else
6682   Nlm_RectTool  rtool;
6683 
6684   if (r != NULL) {
6685     Local__RecTToRectTool (r, &rtool);
6686     InvalRect (&rtool);
6687   }
6688 #endif
6689 #endif
6690 #ifdef WIN_MSWIN
6691   Nlm_RectTool  rtool;
6692 
6693   if (r != NULL && Nlm_currentHWnd != NULL) {
6694     Local__RecTToRectTool (r, &rtool);
6695     InvalidateRect (Nlm_currentHWnd, &rtool, TRUE);
6696   }
6697 #endif
6698 #ifdef WIN_X
6699   Nlm_RectTool  rtool;
6700 
6701   if (r != NULL && Nlm_currentXDisplay != NULL && Nlm_currentXWindow != 0) {
6702     Local__RecTToRectTool (r, &rtool);
6703     XClearArea (Nlm_currentXDisplay, Nlm_currentXWindow,
6704                 rtool.x - Nlm_XOffset, rtool.y - Nlm_YOffset,
6705                 rtool.width, rtool.height, TRUE);
6706   }
6707 #endif
6708 }
6709 
6710 extern void Nlm_ValidRgn (Nlm_RegioN rgn)
6711 
6712 {
6713 #ifdef WIN_MAC
6714   if (rgn != NULL) {
6715 #ifdef WIN_MAC_QUARTZ
6716 // QUARTZ_FIXME: do we care? just let it redraw
6717 #else
6718     ValidRgn ((Nlm_RgnTool) rgn);
6719 #endif
6720   }
6721 #endif
6722 #ifdef WIN_MSWIN
6723   if (rgn != NULL && Nlm_currentHWnd != NULL) {
6724     ValidateRgn (Nlm_currentHWnd, (Nlm_RgnTool) rgn);
6725   }
6726 #endif
6727 #ifdef WIN_X
6728 #endif
6729 }
6730 
6731 extern void Nlm_InvalRgn (Nlm_RegioN rgn)
6732 
6733 {
6734 #ifdef WIN_MAC
6735   if (rgn != NULL) {
6736 #ifdef WIN_MAC_QUARTZ
6737 // QUARTZ_FIXME: this could stand to be a little more fine-grained
6738   HIViewRef view = HIViewGetRoot (Nlm_QWindow);
6739   HIViewSetNeedsDisplay (view, 1);
6740 #else
6741     InvalRgn ((Nlm_RgnTool) rgn);
6742 #endif
6743   }
6744 #endif
6745 #ifdef WIN_MSWIN
6746   if (rgn != NULL && Nlm_currentHWnd != NULL) {
6747     InvalidateRgn (Nlm_currentHWnd, (Nlm_RgnTool) rgn, TRUE);
6748   }
6749 #endif
6750 #ifdef WIN_X
6751   Nlm_RgnTool   ntool1;
6752   Nlm_RgnTool   ntool2;
6753   Nlm_RectTool  rtool;
6754 
6755   if (rgn != NULL && Nlm_currentXDisplay != NULL &&
6756       Nlm_currentXGC != NULL && Nlm_currentXWindow != 0) {
6757     ntool1 = XCreateRegion ();
6758     ntool2 = XCreateRegion ();
6759     XUnionRegion ((Nlm_RgnTool) rgn, ntool1, ntool2);
6760     XOffsetRegion (ntool2, -Nlm_XOffset, -Nlm_YOffset);
6761     XSetRegion (Nlm_currentXDisplay, Nlm_currentXGC, ntool2);
6762     XClipBox (ntool2, &rtool);
6763     XClearArea (Nlm_currentXDisplay, Nlm_currentXWindow, rtool.x,
6764                 rtool.y, rtool.width, rtool.height, TRUE);
6765     XDestroyRegion (ntool1);
6766     XDestroyRegion (ntool2);
6767     if (Nlm_clpRgn != NULL) {
6768       ntool1 = XCreateRegion ();
6769       ntool2 = XCreateRegion ();
6770       XUnionRegion ((Nlm_RgnTool) Nlm_clpRgn, ntool1, ntool2);
6771       XOffsetRegion (ntool2, -Nlm_XOffset, -Nlm_YOffset);
6772       XSetRegion (Nlm_currentXDisplay, Nlm_currentXGC, ntool2);
6773       XDestroyRegion (ntool1);
6774       XDestroyRegion (ntool2);
6775     } else {
6776       XSetClipMask (Nlm_currentXDisplay, Nlm_currentXGC, None);
6777     }
6778   }
6779 #endif
6780 }
6781 
6782 extern void Nlm_CopyBits (Nlm_RectPtr r, Nlm_VoidPtr source)
6783 
6784 {
6785 #ifdef WIN_MAC
6786 #ifdef WIN_MAC_QUARTZ
6787   CGRect rect = Nlm_RecTToCGRect (*r);
6788   
6789   int width = r->left - r->right;
6790   int height = r->bottom - r->top;
6791   int bytesPerRow = (width - 1) / 8 + 1;
6792   
6793   CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceGray();
6794   CGDataProviderRef dataProvider = CGDataProviderCreateWithData (NULL, source, bytesPerRow * height, NULL);
6795   
6796   CGImageRef image = CGImageCreate (
6797     width,
6798     height,
6799     1, /* bits per component */
6800     1, /* bits per pixel */
6801     bytesPerRow,
6802     colorSpace,
6803     0, /* bitmap info */
6804     dataProvider,
6805     NULL,
6806     1, /* should interpolate */
6807     kCGRenderingIntentDefault);
6808   
6809   CGContextDrawImage (Nlm_PeekQContext(), rect, image);
6810   
6811   CFRelease (image);
6812   CFRelease (dataProvider);
6813   CFRelease (colorSpace);
6814   
6815 #else
6816   const BitMap *dstBitsPtr;
6817   Nlm_Int2  mode;
6818   PenState  pnState;
6819   GrafPtr   port;
6820   Rect      rect;
6821   BitMap    srcBits;
6822   Rect      srcRect;
6823 
6824   if (r != NULL && source != NULL) {
6825     GetPort (&port);
6826     GetPenState (&pnState);
6827     switch (pnState.pnMode) {
6828       case patCopy:
6829         mode = srcCopy;
6830         break;
6831       case patOr:
6832         mode = srcOr;
6833         break;
6834       case patXor:
6835         mode = srcXor;
6836         break;
6837       case patBic:
6838         mode = srcBic;
6839         break;
6840       default:
6841         mode = srcCopy;
6842         break;
6843     }
6844     Local__RecTToRectTool (r, &rect);
6845     srcRect = rect;
6846     OffsetRect (&srcRect, -rect.left, -rect.top);
6847     srcBits.baseAddr = (Ptr) source;
6848     srcBits.rowBytes = (rect.right - rect.left - 1) / 8 + 1;
6849     srcBits.bounds = srcRect;
6850 #if OPAQUE_TOOLBOX_STRUCTS
6851     dstBitsPtr = GetPortBitMapForCopyBits(port);
6852 #else
6853     dstBitsPtr = &port->portBits;
6854 #endif
6855     CopyBits (&srcBits, dstBitsPtr, &srcRect, &rect, mode, NULL);
6856   }
6857 #endif
6858 #endif
6859 #ifdef WIN_MSWIN
6860   Nlm_Int2      cols;
6861   HBITMAP       hBitmap;
6862   HBITMAP       hOldBitmap;
6863   HDC           hMemoryDC;
6864   int           rop2;
6865   Nlm_Int2      i;
6866   Nlm_Int2      j;
6867   Nlm_Int4      mode;
6868   Nlm_Int4      num;
6869   Nlm_Boolean   odd;
6870   Nlm_Uint1Ptr  p;
6871   Nlm_Uint1Ptr  ptr;
6872   Nlm_Uint1Ptr  q;
6873   Nlm_Int2      rows;
6874 
6875   if (r != NULL && source != NULL && Nlm_currentHDC != NULL) {
6876     rows = (Nlm_Int2)((r->right - r->left - 1) / 8 + 1);
6877     odd  = (Nlm_Boolean) ((rows & 1) != 0);
6878     cols = (Nlm_Int2)(r->bottom - r->top);
6879     num = rows * cols;
6880     if (odd) {
6881       num += cols;
6882     }
6883     ptr = (Nlm_Uint1Ptr) Nlm_MemNew ((size_t) num * sizeof (Nlm_Uint1));
6884     if (ptr != NULL) {
6885       p = source;
6886       q = ptr;
6887       for (i = 0; i < cols; i++) {
6888         j = 0;
6889         while (j < rows) {
6890           *q = *p;
6891           p++;
6892           q++;
6893           j++;
6894         }
6895         if (odd) {
6896           *q = 0;
6897           q++;
6898         }
6899       }
6900       q = ptr;
6901       while (num > 0) {
6902         *q = (Nlm_Uint1) ~(*q);
6903         q++;
6904         num--;
6905       }
6906       hBitmap = CreateBitmap (r->right - r->left, r->bottom - r->top,
6907                               1, 1, (LPSTR) ptr);
6908       hMemoryDC = CreateCompatibleDC (Nlm_currentHDC);
6909       if ( hMemoryDC == NULL ) {
6910         hMemoryDC = CreateCompatibleDC (NULL);
6911         hOldBitmap = SelectObject (hMemoryDC, hBitmap);
6912         mode = SRCCOPY;
6913         BitBlt (Nlm_currentHDC, r->left, r->top,
6914                 r->right - r->left, r->bottom - r->top,
6915                 hMemoryDC, 0, 0, mode);
6916         SelectObject (hMemoryDC, hOldBitmap);
6917       } else {
6918         hOldBitmap = SelectObject (hMemoryDC, hBitmap);
6919         if (hOldBitmap != NULL) {
6920           rop2 = GetROP2( Nlm_currentHDC );
6921           switch (rop2) {
6922             case R2_COPYPEN:
6923               mode = SRCCOPY;
6924               break;
6925             case R2_MASKPEN:
6926               mode = SRCAND;
6927               break;
6928             case R2_NOTXORPEN:
6929               mode = 0x00990066;
6930               break;
6931             case R2_MERGENOTPEN:
6932               mode = MERGEPAINT;
6933               break;
6934             default:
6935               mode = WHITENESS;
6936               break;
6937           }
6938           BitBlt (Nlm_currentHDC, r->left, r->top,
6939                   r->right - r->left, r->bottom - r->top,
6940                   hMemoryDC, 0, 0, mode);
6941           SelectObject (hMemoryDC, hOldBitmap);
6942         }
6943       }
6944       Nlm_MemFree (ptr);
6945       DeleteDC (hMemoryDC);
6946       DeleteObject (hBitmap);
6947     }
6948   }
6949 #endif
6950 #ifdef WIN_X
6951   Nlm_Int2      cols;
6952   Nlm_Int2      height;
6953   Nlm_Int4      num;
6954   Pixmap        pixmap;
6955   Nlm_Uint1Ptr  ptr;
6956   Nlm_Uint1Ptr  q;
6957   Nlm_Int2      rows;
6958   Nlm_Int2      width;
6959 
6960   if (r != NULL && source != NULL && Nlm_currentXDisplay != NULL &&
6961       Nlm_currentXWindow != 0 && Nlm_currentXGC != NULL) {
6962     rows = (r->right - r->left - 1) / 8 + 1;
6963     cols = r->bottom - r->top;
6964     num = rows * cols;
6965     ptr = (Nlm_Uint1Ptr) Nlm_MemNew ((size_t) num * sizeof (Nlm_Uint1));
6966     if (ptr != NULL) {
6967       Nlm_MemCopy (ptr, source, (size_t) num);
6968       q = ptr;
6969       while (num > 0) {
6970         *q = flip [*q];
6971         q++;
6972         num--;
6973       }
6974       width = r->right - r->left;
6975       height = r->bottom - r->top;
6976       pixmap = XCreateBitmapFromData (Nlm_currentXDisplay, Nlm_currentXWindow,
6977                                       (char *) ptr, width, height);
6978       XSetGraphicsExposures (Nlm_currentXDisplay, Nlm_currentXGC, FALSE);
6979       if (currentMode != MERGE_MODE) {
6980         XCopyPlane (Nlm_currentXDisplay, pixmap, Nlm_currentXWindow,
6981                     Nlm_currentXGC, 0, 0, width, height,
6982                     r->left - Nlm_XOffset, r->top - Nlm_YOffset, 1);
6983       } else {
6984         XSetClipOrigin (Nlm_currentXDisplay, Nlm_currentXGC,
6985                         r->left - Nlm_XOffset, r->top - Nlm_YOffset);
6986         XSetClipMask (Nlm_currentXDisplay, Nlm_currentXGC, pixmap);
6987         XSetFunction (Nlm_currentXDisplay, Nlm_currentXGC, GXcopy);
6988         XCopyPlane (Nlm_currentXDisplay, pixmap, Nlm_currentXWindow,
6989                     Nlm_currentXGC, 0, 0, width, height,
6990                     r->left - Nlm_XOffset, r->top - Nlm_YOffset, 1);
6991         XSetFunction (Nlm_currentXDisplay, Nlm_currentXGC, GXand);
6992         XSetClipOrigin (Nlm_currentXDisplay, Nlm_currentXGC, 0, 0);
6993         if (Nlm_clpRgn != NULL) {
6994           XSetRegion (Nlm_currentXDisplay, Nlm_currentXGC, (Nlm_RgnTool) Nlm_clpRgn);
6995         } else {
6996           XSetClipMask (Nlm_currentXDisplay, Nlm_currentXGC, None);
6997         }
6998       }
6999       XSetGraphicsExposures (Nlm_currentXDisplay, Nlm_currentXGC, TRUE);
7000       XFreePixmap (Nlm_currentXDisplay, pixmap);
7001       Nlm_MemFree (ptr);
7002     }
7003   }
7004 #endif
7005 #ifdef WIN_GIF
7006   if (r != NULL && source != NULL && Nlm_currentGIF != NULL ){
7007     gdImageCopyBits ( Nlm_currentGIF, r->left, r->top,
7008                       r->right - r->left, r->bottom - r->top,
7009                       (char*)source, Nlm_curGIFColor );
7010   }
7011 #endif
7012 }
7013 
7014 extern void Nlm_CopyPixmap ( Nlm_RectPtr r, Nlm_Int1Ptr source, 
7015                              Nlm_Uint1 totalColors, 
7016                              Nlm_RGBColoRPtr colorTable )
7017 {
7018 #ifdef WIN_MSWIN
7019   BITMAPINFO       PNTR bInfoPtr;
7020   RGBQUAD          PNTR quadPtr;
7021   BITMAPINFOHEADER PNTR bmpHeader;
7022   HBITMAP               pixMap;
7023   HDC                   hMemDC;
7024 #endif
7025 #ifdef WIN_MAC
7026   PixMap           PNTR pixelMap;
7027   Rect                  rectSrc;
7028   Rect                  rectDst;
7029   GrafPtr               port;
7030   CTabHandle            tabHandle;
7031   CTabPtr               tabPtr;
7032 #endif
7033   Nlm_Int2              width;
7034   Nlm_Int2              height;
7035 #ifndef WIN_GIF
7036   Nlm_Int2              i;
7037 #endif
7038 
7039   if ( (r==NULL)||(source==NULL)||(totalColors==0)||
7040        (colorTable==NULL) ) return;
7041 
7042   width  = (Nlm_Int2)(r->right - r->left);
7043   height = (Nlm_Int2)(r->bottom - r->top);
7044 
7045 #ifdef WIN_MSWIN
7046   bInfoPtr = (BITMAPINFO*)MemNew ( sizeof(BITMAPINFOHEADER) +
7047                                    totalColors*sizeof(RGBQUAD) );
7048   bInfoPtr->bmiHeader.biClrUsed = totalColors;
7049   for( i=0; i<(Nlm_Int2)totalColors; i++ ) {
7050     quadPtr = &(bInfoPtr->bmiColors[i]);
7051     quadPtr->rgbRed = colorTable[i].red;
7052     quadPtr->rgbGreen = colorTable[i].green;
7053     quadPtr->rgbBlue = colorTable[i].blue;
7054     quadPtr->rgbReserved = 0;
7055   }
7056   bmpHeader = &(bInfoPtr->bmiHeader);
7057   bmpHeader->biWidth = width;
7058   bmpHeader->biHeight = height;
7059   bmpHeader->biSize = sizeof(BITMAPINFOHEADER);
7060   bmpHeader->biCompression = BI_RGB;
7061   bmpHeader->biXPelsPerMeter = 2000;
7062   bmpHeader->biYPelsPerMeter = 2000;
7063   bmpHeader->biClrImportant = 0;
7064   bmpHeader->biSizeImage = 0;
7065   bmpHeader->biBitCount = 8;
7066   bmpHeader->biPlanes = 1;
7067   pixMap = CreateDIBitmap( Nlm_currentHDC,
7068                            (BITMAPINFOHEADER*)bInfoPtr, 
7069                            CBM_INIT, source, bInfoPtr, 
7070                            DIB_RGB_COLORS );
7071   if ( pixMap != NULL ){
7072     hMemDC = CreateCompatibleDC ( Nlm_currentHDC );
7073     if ( hMemDC != NULL ){
7074       SelectObject( hMemDC, pixMap );
7075       StretchBlt ( Nlm_currentHDC, r->left, r->top+height, width, -height, 
7076                    hMemDC, 0, 0, width, height, SRCCOPY );
7077 
7078 /*      BitBlt( Nlm_currentHDC, r->left, r->top, width, height, hMemDC, 0, 0,
7079               SRCCOPY );*/
7080       DeleteDC( hMemDC );
7081     }
7082     DeleteObject( pixMap );
7083   }
7084   MemFree(bInfoPtr);
7085 #endif
7086 #ifdef WIN_MAC
7087 #ifdef WIN_MAC_QUARTZ
7088   CGRect rect = Nlm_RecTToCGRect (*r);
7089   
7090   width = r->left - r->right;
7091   height = r->bottom - r->top;
7092   
7093   CGColorSpaceRef baseSpace = CGColorSpaceCreateDeviceRGB ();
7094   
7095   /* we're going to pass the color table directly; it's an array of
7096      structs containing r, g, b, and the function wants an array
7097      of unsigned char containing r, g, b, so they all line up */
7098   CGColorSpaceRef colorSpace = CGColorSpaceCreateIndexed (baseSpace, totalColors - 1, (const unsigned char *)colorTable);
7099   
7100   CGDataProviderRef dataProvider = CGDataProviderCreateWithData (NULL, source, width * height, NULL);
7101   
7102   CGImageRef image = CGImageCreate (
7103     width,
7104     height,
7105     8, /* bits per component */
7106     8, /* bits per pixel */
7107     width * height,
7108     colorSpace,
7109     0, /* bitmap info */
7110     dataProvider,
7111     NULL,
7112     1, /* should interpolate */
7113     kCGRenderingIntentDefault);
7114   
7115   CGContextDrawImage (Nlm_PeekQContext(), rect, image);
7116   
7117   CFRelease (image);
7118   CFRelease (dataProvider);
7119   CFRelease (colorSpace);
7120   CFRelease (baseSpace);
7121 #else
7122   pixelMap = (PixMap*)MemNew(sizeof(PixMap));
7123   pixelMap->hRes = 72;
7124   pixelMap->vRes = 72;
7125   pixelMap->bounds.left = 0;
7126   pixelMap->bounds.top = 0;
7127   pixelMap->cmpSize = 8;
7128   /* 2001-03-22:  Joshua Juran */
7129   /* Evidently these two members don't exist in Carbon.  So don't set them. */
7130 #if !TARGET_API_MAC_CARBON
7131   pixelMap->planeBytes = 0;
7132   pixelMap->pmReserved = 0;
7133 #endif
7134   pixelMap->pmVersion = 0;
7135   pixelMap->packType = 0;
7136   pixelMap->packSize = 0;
7137   pixelMap->pixelSize = 8;
7138   pixelMap->pixelType = 0;
7139   pixelMap->cmpCount = 1;
7140   pixelMap->rowBytes = width | 0x8000;
7141   pixelMap->bounds.right = width;
7142   pixelMap->bounds.bottom = height;
7143   pixelMap->pmTable = tabHandle = GetCTable(72);
7144   if ( tabHandle != NULL ) {
7145     HLock ( (Handle)tabHandle );
7146     tabPtr = *tabHandle;
7147     for ( i=0; i<(Nlm_Int2)totalColors; i++ ){
7148       tabPtr->ctTable[i].rgb.red =   (Nlm_Uint2)colorTable[i].red<<8 | 
7149                                      (Nlm_Uint2)colorTable[i].red;
7150       tabPtr->ctTable[i].rgb.green = (Nlm_Uint2)colorTable[i].green<<8 | 
7151                                      (Nlm_Uint2)colorTable[i].green;
7152       tabPtr->ctTable[i].rgb.blue =  (Nlm_Uint2)colorTable[i].blue<<8 | 
7153                                      (Nlm_Uint2)colorTable[i].blue; 
7154       if (i >= 254) break;
7155     }
7156     tabPtr->ctSeed = GetCTSeed();
7157     HUnlock((Handle)tabHandle );
7158     pixelMap->baseAddr = (Ptr)source;
7159     rectSrc.top = 0;   rectSrc.bottom = height;
7160     rectSrc.left = 0;  rectSrc.right = width;
7161     rectDst.top = r->top;   rectDst.bottom = r->bottom;
7162     rectDst.left = r->left;  rectDst.right = r->right;
7163     GetPort(&port);
7164 #ifdef CopyBits
7165 #undef CopyBits
7166 #endif
7167     CopyBits((BitMap*)pixelMap,
7168              GetPortBitMapForCopyBits(port),
7169              &rectSrc, &rectDst, srcCopy, NULL);
7170     DisposeCTable(tabHandle);
7171   }
7172   MemFree(pixelMap);
7173 #endif
7174 #endif
7175 
7176 #ifdef WIN_MOTIF
7177   {{
7178   XVisualInfo visinfo;
7179   if (XMatchVisualInfo(Nlm_currentXDisplay, Nlm_currentXScreen,
7180                        8, PseudoColor, &visinfo) ||
7181       XMatchVisualInfo(Nlm_currentXDisplay, Nlm_currentXScreen,
7182                        8, GrayScale,   &visinfo) )
7183     {
7184       Visual*      vis    = visinfo.visual;
7185       Nlm_Uint1Ptr nSource = (Nlm_Uint1Ptr)MemNew(width * height);
7186       Nlm_Uint1Ptr iMap    = (Nlm_Uint1Ptr)MemNew( totalColors );
7187       XImage*      imageX11;
7188       Nlm_Uint1Ptr curPtr;
7189       Nlm_Uint1Ptr endPtr;
7190 
7191       for (i = 0;  i < (Nlm_Int2)totalColors;  i++)
7192         {
7193           XColor colorCell;
7194           Nlm_XAllocColor(&colorCell, Nlm_VibrantDefaultColormap(),
7195                           colorTable[i].red, colorTable[i].green,
7196                           colorTable[i].blue);
7197           iMap[i] = (Nlm_Uint1)colorCell.pixel;
7198         }
7199 
7200       curPtr = (Nlm_Uint1Ptr)nSource;
7201       endPtr = curPtr + width * height;
7202       while ( curPtr != endPtr )
7203         *curPtr++ = iMap[*source++];
7204 
7205       imageX11 = XCreateImage(Nlm_currentXDisplay, vis, 8, ZPixmap, 0, 
7206                               (char*)nSource, width, height, 8 , 0 );  
7207       XPutImage(Nlm_currentXDisplay, Nlm_currentXWindow, 
7208                 Nlm_currentXGC, imageX11, 0, 0, r->left-Nlm_XOffset, 
7209                 r->top-Nlm_YOffset, width, height );
7210       XFlush ( Nlm_currentXDisplay );
7211       XDestroyImage( imageX11 );
7212       MemFree( nSource );
7213       MemFree( iMap );
7214     }
7215   }}
7216 #endif
7217 }
7218 
7219 
7220 extern void Nlm_SetUpDrawingTools (void)
7221 {
7222 #ifdef WIN_MAC
7223   Rect bounds;
7224   Nlm_FontSpec fsp;
7225   long       gval;
7226   char       tmpFontName[256];
7227 
7228 
7229 #ifdef WIN_MAC_QUARTZ
7230   CGRect r = CGRectMake (-32768, -32768, 65535, 65535);
7231   HIShapeRef rectShape = HIShapeCreateWithRect (&r);
7232   Nlm_scrollRgn = HIShapeCreateMutableCopy (rectShape);
7233   Nlm_updateRgn = HIShapeCreateMutableCopy (rectShape);
7234   CFRelease (rectShape);
7235   
7236   /* can't use QuickDraw functions to get the system font,
7237      no replacemet available, so just hardcode it */
7238   memset ( &fsp, 0, sizeof(Nlm_FontSpec));
7239   Nlm_StrCpy (fsp.name, "Lucida Grande");
7240   fsp.size = 13;
7241 #else
7242   Nlm_scrollRgn = (Nlm_RegioN) (NewRgn ());
7243 
7244   Nlm_updateRgn = (Nlm_RegioN) (NewRgn ());
7245   SetRectRgn ((Nlm_RgnTool) Nlm_updateRgn, -32768, -32768, 32767, 32767);
7246   /* HLock ((Handle) Nlm_updateRgn); */
7247   GetRegionBounds(Nlm_updateRgn, &bounds);
7248   Local__RectToolToRecT (&bounds, &Nlm_updateRect);
7249   /* HUnlock ((Handle) Nlm_updateRgn); */
7250 
7251   /* esl: LoadFontData changed to work with new FontData format */
7252   /* alexs get font name */
7253   memset ( &fsp, 0, sizeof(Nlm_FontSpec));
7254   GetFontName ( GetSysFont(), (StringPtr) tmpFontName );
7255   Nlm_PtoCstr ( tmpFontName );
7256   Nlm_StringNCpy_0 (fsp.name, tmpFontName, FONT_NAME_SIZE - 1);
7257   fsp.name[FONT_NAME_SIZE - 1] = 0;
7258   fsp.size = GetDefFontSize ();
7259 #endif
7260 
7261   Nlm_fontList = NULL;
7262   Nlm_fontInUse = NULL;
7263   Nlm_systemFont = (Nlm_FonT) Nlm_HandNew (sizeof (Nlm_FontRec));
7264   
7265 #ifdef WIN_MAC_ATSUI
7266   Nlm_LoadFontData (Nlm_systemFont, NULL, -1, &fsp, Nlm_NewATSUStyle(&fsp), NULL);
7267 #else
7268   Nlm_LoadFontData (Nlm_systemFont, NULL, -1, &fsp, 0, fsp.size, 0, NULL);
7269 #endif
7270   Nlm_programFont = (Nlm_FonT) Nlm_HandNew (sizeof (Nlm_FontRec));
7271   /* esl: LoadFontData changed to work with new FontData format */
7272   Nlm_StrCpy (fsp.name, "Monaco");
7273   fsp.size = 9;
7274 #ifdef WIN_MAC_ATSUI
7275   Nlm_LoadFontData (Nlm_programFont, NULL, -1, &fsp, Nlm_NewATSUStyle(&fsp), NULL);
7276 #else
7277   Nlm_LoadFontData (Nlm_programFont, NULL, -1, &fsp, 4, 9, 0, NULL);
7278 #endif
7279   Nlm_fontList = NULL;
7280   Nlm_fontInUse = Nlm_systemFont;
7281 
7282   Nlm_stdAscent = Nlm_Ascent ();
7283   Nlm_stdDescent = Nlm_Descent ();
7284   Nlm_stdLeading = Nlm_Leading ();
7285   Nlm_stdFontHeight = Nlm_FontHeight ();
7286   Nlm_stdLineHeight = Nlm_LineHeight ();
7287   Nlm_stdCharWidth = Nlm_MaxCharWidth ();
7288   /* gestalt for quickdraw features are defined as bits in a bitfield
7289      for example gestaltHasColor = 0, thus we need to test for lsb set
7290    */
7291   if( Gestalt( gestaltQuickdrawFeatures, &gval) == noErr){
7292       Nlm_hasColorQD = (gval && (1 << gestaltHasColor));
7293   }
7294   if (Nlm_hasColorQD) {
7295 #ifdef WIN_MAC_QUARTZ
7296     Nlm_QuartzForeColor.r = 0;
7297     Nlm_QuartzForeColor.g = 0;
7298     Nlm_QuartzForeColor.b = 0;
7299     Nlm_QuartzBackColor.r = 1.0;
7300     Nlm_QuartzBackColor.g = 1.0;
7301     Nlm_QuartzBackColor.b = 1.0;
7302 #else
7303     Nlm_RGBforeColor.red = 0;
7304     Nlm_RGBforeColor.green = 0;
7305     Nlm_RGBforeColor.blue = 0;
7306     Nlm_RGBbackColor.red = 65535;
7307     Nlm_RGBbackColor.green = 65535;
7308     Nlm_RGBbackColor.blue = 65535;
7309 #endif
7310   }
7311 #endif
7312 #ifdef WIN_MSWIN
7313   Nlm_scrollRgn = (Nlm_RegioN)CreateRectRgn(0, 0, 0, 0);
7314   Nlm_updateRgn = (Nlm_RegioN)CreateRectRgn(-32767, -32767, 32767, 32767);
7315 
7316   {{
7317   Nlm_RectTool  rtool;
7318   GetRgnBox((Nlm_RgnTool)Nlm_updateRgn, &rtool);
7319   Local__RectToolToRecT(&rtool, &Nlm_updateRect);
7320   }}
7321 
7322   /* Stock fonts */
7323   hAnsiFixedFont     = GetStockObject( ANSI_FIXED_FONT     );
7324   hAnsiVarFont       = GetStockObject( ANSI_VAR_FONT       );
7325   hDeviceDefaultFont = GetStockObject( DEVICE_DEFAULT_FONT );
7326   hOemFixedFont      = GetStockObject( OEM_FIXED_FONT      );
7327   hSystemFont        = GetStockObject( SYSTEM_FONT         );
7328   hSystemFixedFont   = GetStockObject( SYSTEM_FIXED_FONT   );
7329   hDefaultGuiFont    = GetStockObject( DEFAULT_GUI_FONT    );
7330 
7331   Nlm_systemFont  = (Nlm_FonT) Nlm_HandNew( sizeof(Nlm_FontRec) );
7332   Nlm_LoadFontData(Nlm_systemFont,  NULL, -1, NULL, hDefaultGuiFont,
7333                    HFONT2Font( hDefaultGuiFont ));
7334 
7335   Nlm_fontList  = NULL;
7336   Nlm_fontInUse = Nlm_systemFont;
7337 
7338   Nlm_stdAscent     = Nlm_Ascent();
7339   Nlm_stdDescent    = Nlm_Descent();
7340   Nlm_stdLeading    = Nlm_Leading();
7341   Nlm_stdFontHeight = Nlm_FontHeight();
7342   Nlm_stdLineHeight = Nlm_LineHeight();
7343   Nlm_stdCharWidth  = Nlm_MaxCharWidth();
7344 
7345   Nlm_programFont = (Nlm_FonT) Nlm_HandNew( sizeof(Nlm_FontRec) );
7346   Nlm_LoadFontData(Nlm_programFont, NULL, -1, NULL, hAnsiFixedFont,
7347                    HFONT2Font( hAnsiFixedFont ));
7348 
7349   blackColor   = RGB(  0,   0,   0);
7350   redColor     = RGB(255,   0,   0);
7351   greenColor   = RGB(  0, 255,   0);
7352   blueColor    = RGB(  0,   0, 255);
7353   cyanColor    = RGB(  0, 255, 255);
7354   magentaColor = RGB(255,   0, 255);
7355   yellowColor  = RGB(255, 255,   0);
7356   whiteColor   = RGB(255, 255, 255);
7357 
7358   hBlackPen = GetStockObject( BLACK_PEN );
7359   hNullPen  = GetStockObject( NULL_PEN  );
7360   hWhitePen = GetStockObject( WHITE_PEN );
7361 
7362   hBlackBrush  = GetStockObject( BLACK_BRUSH  );
7363   hDkGrayBrush = GetStockObject( DKGRAY_BRUSH );
7364   hGrayBrush   = GetStockObject( GRAY_BRUSH   );
7365   hHollowBrush = GetStockObject( HOLLOW_BRUSH );
7366   hLtGrayBrush = GetStockObject( LTGRAY_BRUSH );
7367   hNullBrush   = GetStockObject( NULL_BRUSH   );
7368   hWhiteBrush  = GetStockObject( WHITE_BRUSH  );
7369 #endif
7370 #ifdef WIN_X
7371   XFontStruct   *f;
7372   Nlm_Int2      i;
7373   Nlm_Uint2     inv;
7374   Nlm_Int2      j;
7375   XFontStruct   *p;
7376   Nlm_RecT      r;
7377   Nlm_RectTool  rtool;
7378   Nlm_Uint2     val;
7379   Nlm_FontSpec  fsp;
7380   Nlm_Char      fSpecName[64];
7381 
7382 
7383   Nlm_scrollRgn = (Nlm_RegioN) (XCreateRegion ());
7384 
7385   Nlm_updateRgn = (Nlm_RegioN) (XCreateRegion ());
7386   Nlm_LoadRect (&r, -32767, -32767, 32767, 32767);
7387   Local__RecTToRectTool (&r, &rtool);
7388   XUnionRectWithRegion (&rtool, (Nlm_RgnTool) Nlm_updateRgn, (Nlm_RgnTool) Nlm_updateRgn);
7389   Local__RectToolToRecT (&rtool, &Nlm_updateRect);
7390 
7391   emptyRgn = XCreateRegion ();
7392 
7393   Nlm_fontList = NULL;
7394   Nlm_fontInUse = NULL;
7395   {{
7396     XFontStruct *F =XQueryFont(Nlm_currentXDisplay,
7397                                XGContextFromGC(DefaultGC(Nlm_currentXDisplay,
7398                                                          Nlm_currentXScreen)));
7399     i = F->ascent + F->descent;
7400     XFreeFontInfo(NULL, F, 1);
7401   }}
7402   sprintf ( fSpecName, "-*-helvetica-bold-r-*--%d-*-*", i );
7403   f = Nlm_XLoadQueryFont (Nlm_currentXDisplay, fSpecName, FALSE);
7404   if ( f == NULL ){
7405     i++;
7406     sprintf ( fSpecName, "-*-helvetica-bold-r-*--%d-*-*", i );
7407     f = Nlm_XLoadQueryFont (Nlm_currentXDisplay, fSpecName, FALSE);
7408   }
7409   if ( f == NULL ){
7410     i--; i--;
7411     sprintf ( fSpecName, "-*-helvetica-bold-r-*--%d-*-*", i );
7412     f = Nlm_XLoadQueryFont (Nlm_currentXDisplay, fSpecName, FALSE);
7413   }
7414   if ( f == NULL ){
7415     f = Nlm_XLoadQueryFont (Nlm_currentXDisplay, "-*-helvetica-bold-r-*--*-140-*", FALSE);
7416     i = 14;
7417   }
7418 
7419   memset(&fsp, 0, sizeof(Nlm_FontSpec));
7420   if ( f ) {
7421     Nlm_StrCpy(fsp.name, "helvetica");
7422     fsp.style = STYLE_BOLD;
7423   } else {
7424     f = Nlm_XLoadStandardFont();
7425     fsp.name[0] = '\0';
7426     fsp.style = STYLE_REGULAR;
7427     i = f->ascent + f->descent;
7428   }
7429   fsp.size = i;
7430   
7431   Nlm_systemFont = (Nlm_FonT) Nlm_HandNew (sizeof (Nlm_FontRec));
7432   Nlm_LoadFontData (Nlm_systemFont, NULL, -1, &fsp, f, NULL);
7433 
7434   sprintf ( fSpecName, "-*-fixed-medium-r-*--%d-*-*", i );
7435   p = Nlm_XLoadQueryFont (Nlm_currentXDisplay, fSpecName, FALSE);
7436   Nlm_StrCpy ( fsp.name, "fixed" );
7437   fsp.size = i;
7438   fsp.style = STYLE_REGULAR;
7439   if (p == NULL) {
7440     p = Nlm_XLoadQueryFont (Nlm_currentXDisplay, "-*-fixed-medium-r-*--*-120-*", FALSE);
7441     Nlm_StrCpy ( fsp.name, "fixed" );
7442     fsp.size = 12;
7443   }
7444   if (p == NULL) {
7445     p = Nlm_XLoadQueryFont (Nlm_currentXDisplay,
7446                             "-*-courier-medium-r-*--*-120-*", FALSE);
7447     Nlm_StrCpy ( fsp.name, "courier" );
7448     fsp.size = 12;
7449   }
7450   if ( !p ) {
7451     p = Nlm_XLoadStandardFont();
7452     fsp.name[0] = '\0';
7453     fsp.size = p->ascent + p->descent;
7454   }
7455   Nlm_programFont = (Nlm_FonT) Nlm_HandNew (sizeof (Nlm_FontRec));
7456   /* esl: LoadFontData changed to work with new FontData format */
7457   Nlm_LoadFontData (Nlm_programFont, NULL, -1, &fsp, p, NULL);
7458   Nlm_fontList = NULL;
7459   Nlm_fontInUse = Nlm_systemFont;
7460 
7461   XSetFont (Nlm_currentXDisplay, Nlm_currentXGC, f->fid);
7462   currentFont = f;
7463   Nlm_stdAscent = Nlm_Ascent ();
7464   Nlm_stdDescent = Nlm_Descent ();
7465   Nlm_stdLeading = Nlm_Leading ();
7466   Nlm_stdFontHeight = Nlm_FontHeight ();
7467   Nlm_stdLineHeight = Nlm_LineHeight ();
7468   Nlm_stdCharWidth = Nlm_MaxCharWidth ();
7469 
7470   Nlm_hasColor = (Nlm_currentXDisplay != NULL  &&
7471                   XDisplayCells(Nlm_currentXDisplay, Nlm_currentXScreen) > 2);
7472 
7473   if ( Nlm_hasColor )
7474     {
7475       whiteColor   = Nlm_GetColorRGB(255, 255, 255);
7476       blackColor   = Nlm_GetColorRGB(  0,   0,   0);
7477       redColor     = Nlm_GetColorRGB(255,   0,   0);
7478       greenColor   = Nlm_GetColorRGB(  0, 255,   0);
7479       blueColor    = Nlm_GetColorRGB(  0,   0, 255);
7480       cyanColor    = Nlm_GetColorRGB(  0, 255, 255);
7481       magentaColor = Nlm_GetColorRGB(255,   0, 255);
7482       yellowColor  = Nlm_GetColorRGB(255, 255,   0);
7483     }
7484   else
7485     {
7486       whiteColor   = WhitePixel(Nlm_currentXDisplay, Nlm_currentXScreen);
7487       blackColor   = BlackPixel(Nlm_currentXDisplay, Nlm_currentXScreen);
7488       redColor     = BlackPixel(Nlm_currentXDisplay, Nlm_currentXScreen);
7489       greenColor   = BlackPixel(Nlm_currentXDisplay, Nlm_currentXScreen);
7490       blueColor    = BlackPixel(Nlm_currentXDisplay, Nlm_currentXScreen);
7491       cyanColor    = BlackPixel(Nlm_currentXDisplay, Nlm_currentXScreen);
7492       magentaColor = BlackPixel(Nlm_currentXDisplay, Nlm_currentXScreen);
7493       yellowColor  = BlackPixel(Nlm_currentXDisplay, Nlm_currentXScreen);
7494     }
7495 
7496   fontInfo.fid = 0;
7497   for (i = 0; i < 256; i++) {
7498     inv = 0;
7499     val = (Nlm_Uint2) i;
7500     for (j = 0; j < 8; j++) {
7501       inv = (inv << 1);
7502       inv += (val % 2);
7503       val = (val >> 1);
7504     }
7505     flip [i] = inv;
7506   }
7507 
7508   Nlm_XbackColor = whiteColor;
7509   Nlm_XforeColor = blackColor;
7510   Nlm_XOffset = 0;
7511   Nlm_YOffset = 0;
7512   Nlm_clpRgn = NULL;
7513 #endif
7514 #ifdef WIN_GIF
7515   Nlm_curGIFColor = 1;
7516   Nlm_curGIFLType = GIF_SOLID;
7517   Nlm_curGIFFont = gdFont7X13b;
7518   Nlm_curGIFPoint.x = 0;
7519   Nlm_curGIFPoint.y = 0;
7520 #endif
7521 }
7522 
7523 extern void Nlm_CleanUpDrawingTools (void)
7524 
7525 {
7526   Nlm_FonT      f;
7527   Nlm_FontData  fdata;
7528 
7529 #ifndef WIN_MAC_QUARTZ
7530   Nlm_ResetDrawingTools ();
7531 #endif
7532 #ifdef WIN_MOTIF
7533   Nlm_GetFontData (Nlm_systemFont, &fdata);
7534   if (fdata.handle != NULL) {
7535     XFreeFont (Nlm_currentXDisplay, fdata.handle);
7536   }
7537   Nlm_GetFontData (Nlm_programFont, &fdata);
7538   if (fdata.handle != NULL) {
7539     XFreeFont (Nlm_currentXDisplay, fdata.handle);
7540   }
7541 #endif
7542   Nlm_HandFree (Nlm_systemFont);
7543   Nlm_HandFree (Nlm_programFont);
7544   f = Nlm_fontList;
7545   while (f != NULL) {
7546     Nlm_GetFontData (f, &fdata);
7547 #ifdef WIN_MSWIN
7548     if (fdata.handle != NULL) {
7549       DeleteObject (fdata.handle);
7550     }
7551 #endif
7552 #ifdef WIN_MOTIF
7553     if (fdata.handle != NULL) {
7554       XFreeFont (Nlm_currentXDisplay, fdata.handle);
7555     }
7556 #endif
7557     Nlm_HandFree (f);
7558     f = fdata.next;
7559   }
7560 
7561 #ifdef WIN_MOTIF
7562   XDestroyRegion (emptyRgn);
7563 #endif
7564 }
7565 
7566 
7567 size_t UpdateColorTable(Nlm_RGBColoR table[], size_t table_size,
7568                         const Nlm_Char PNTR filename)
7569 {
7570   size_t n_done = 0;
7571   FILE *file;
7572   Nlm_Char str[128];
7573 
7574   if (table_size < 1  ||  filename == NULL)  return 0;
7575 
7576   file = Nlm_FileOpen(filename, "r");
7577   if (file == NULL)
7578     {
7579       Nlm_ErrLogPrintf("\n\
7580 Warning:  Cannot open the user's color description file \"%s\"\n",
7581                        filename);
7582       return 0;
7583     }
7584 
7585   while (Nlm_FileGets(str, sizeof(str), file) != NULL)
7586     {
7587       int index;
7588       int red, green, blue;
7589       int n_char_read;
7590       if (sscanf(str, "%i %i %i %i %n",
7591                  &index, &red, &green, &blue, &n_char_read) != 4)
7592         {
7593           Nlm_ErrLogPrintf("\n\
7594 [%s] Warning:\n\
7595 Cannot extract <index> <red> <green> <blue> from the stroke:\n\
7596 \"%s\"\n",
7597                            filename, str);
7598           continue;
7599         }
7600 
7601       if (index < 0  ||  table_size <= (size_t)index)
7602         {
7603           Nlm_ErrLogPrintf("\n\
7604 [%s] Warning:\n\
7605 The color index is out of range = %d  (must be:  0 <= index <= %l)\n",
7606                            filename, index, (long)(table_size - 1));
7607           continue;
7608         }
7609 
7610 #ifdef WIN_MOTIF
7611       {{
7612         Nlm_CharPtr name, s;
7613         for (name=str+n_char_read;  *name != '\0' && !isalnum(*name);  name++);
7614         for (s   =name;             *s    != '\0' &&  isalnum(*s   );  s++   );
7615         *s = '\0';
7616 
7617         if (*name != '\0')
7618           {
7619             XColor rgb_db_def, hardware_def;
7620             if ( XLookupColor(Nlm_currentXDisplay,
7621                               Nlm_VibrantDefaultColormap(),
7622                               name,
7623                               &rgb_db_def, &hardware_def) )
7624               {
7625                 red   = (int)(hardware_def.red   >> 8);
7626                 green = (int)(hardware_def.green >> 8);
7627                 blue  = (int)(hardware_def.blue  >> 8);
7628               }
7629             else
7630               {
7631                 Nlm_ErrLogPrintf("\n\
7632 [%s] Warning:\n\
7633 Cannot find color of name \"%s\" in the X11 color database",
7634                                  filename, name);
7635                 continue;
7636               }
7637           }
7638       }}
7639 #endif
7640 
7641       if (red   < 0  ||  255 < red   ||
7642           green < 0  ||  255 < green ||
7643           blue  < 0  ||  255 < blue)
7644         {
7645           Nlm_ErrLogPrintf("\n\
7646 [%s] Warning:\n\
7647 The color component values are out of range = (%d, %d, %d)\n\
7648 (must be:  0 <= value <= 255)\n",
7649                            filename, red, green, blue);
7650           continue;
7651         }
7652 
7653       table[index].red   = (Nlm_Uint1) red;
7654       table[index].green = (Nlm_Uint1) green;
7655       table[index].blue  = (Nlm_Uint1) blue;
7656       n_done++;
7657     }
7658 
7659   Nlm_FileClose( file );
7660   return n_done;
7661 }
7662 
7663 
7664 static Nlm_Boolean s_VibrantIsGUI = FALSE;
7665 extern Nlm_Boolean Nlm_VibrantIsGUI(void) {
7666   return s_VibrantIsGUI;
7667 }
7668 extern void Nlm_VibrantSetGUI(void) {
7669   s_VibrantIsGUI = TRUE;
7670 }
7671 

source navigation ]   [ diff markup ]   [ identifier search ]   [ freetext search ]   [ file search ]  

This page was automatically generated by the LXR engine.
Visit the LXR main site for more information.