1 /* $NoKeywords: $ */
2 /*
3 //
4 // Copyright (c) 1993-2012 Robert McNeel & Associates. All rights reserved.
5 // OpenNURBS, Rhinoceros, and Rhino3D are registered trademarks of Robert
6 // McNeel & Associates.
7 //
8 // THIS SOFTWARE IS PROVIDED "AS IS" WITHOUT EXPRESS OR IMPLIED WARRANTY.
9 // ALL IMPLIED WARRANTIES OF FITNESS FOR ANY PARTICULAR PURPOSE AND OF
10 // MERCHANTABILITY ARE HEREBY DISCLAIMED.
11 //
12 // For complete openNURBS copyright information see <http://www.opennurbs.org>.
13 //
14 ////////////////////////////////////////////////////////////////
15 */
16 
17 #include "opennurbs.h"
18 
19 // {EA2EFFD2-C9A9-4cb1-BE15-D2F46290F1A1}
20 //const ON_UUID ON_MaterialRef::material_from_layer =
21 //{ 0xea2effd2, 0xc9a9, 0x4cb1, { 0xbe, 0x15, 0xd2, 0xf4, 0x62, 0x90, 0xf1, 0xa1 } };
22 
23 
24 
25 // {86EDFDE4-8AAF-4bcd-AB7C-F7111978D7FE}
26 //const ON_UUID ON_MaterialRef::material_from_parent =
27 //{ 0x86edfde4, 0x8aaf, 0x4bcd, { 0xab, 0x7c, 0xf7, 0x11, 0x19, 0x78, 0xd7, 0xfe } };
28 
29 
30 // on_stricmp() is a wrapper for case insensitive string compare
31 // and calls one of _stricmp(), stricmp(), or strcasecmp()
32 // depending on OS.
on_stricmp(const char * s1,const char * s2)33 int on_stricmp(const char * s1, const char * s2)
34 {
35 #if defined(ON_OS_WINDOWS)
36   //return stricmp(s1,s2);
37   return _stricmp(s1,s2);
38 #else
39   return strcasecmp(s1,s2);
40 #endif
41 }
42 
43 // on_strupr() calls _strupr() or strupr() depending on OS
on_strupr(char * s)44 char* on_strupr(char* s)
45 {
46 #if defined(ON_OS_WINDOWS)
47   return _strupr(s); // ANSI name
48 #else
49   if (s) {
50     while (*s) {
51       *s = toupper(*s);
52       s++;
53     }
54   }
55   return s;
56 #endif
57 }
58 
59 // on_strlwr() calls _strlwr() or strlwr() depending on OS
on_strlwr(char * s)60 char* on_strlwr(char* s)
61 {
62 #if defined(ON_OS_WINDOWS)
63   return _strlwr(s); // ANSI name
64 #else
65   if (s) {
66     while (*s) {
67       *s = tolower(*s);
68       s++;
69     }
70   }
71   return s;
72 #endif
73 }
74 
75 // on_strrev() calls _strrev() or strrev() depending on OS
on_strrev(char * s)76 char* on_strrev(char* s)
77 {
78 #if defined(ON_OS_WINDOWS)
79   return _strrev(s); // ANSI name
80 #else
81   int i, j;
82   char c;
83   for ( i = 0, j = ((int)strlen(s))-1; i < j; i++, j-- ) {
84     c = s[i];
85     s[i] = s[j];
86     s[j] = c;
87   }
88   return s;
89 #endif
90 }
91 
92 // Windows code page support
93 //   Only ON_SetStringConversionWindowsLocaleID,
94 //   ON_GetStringConversionWindowsLocaleID, and
95 //   on_wcsicmp should look at g_s__windows_locale_id
96 //   and g_s__windows_locale_os.
97 static unsigned int g_s__windows_locale_id = 0;
98 static unsigned int g_s__windows_locale_os = 0; // 0 = Win 95/98/ME...
99                                               // 1 = Win NT/2000/XP...
100 
ON_SetStringConversionWindowsLocaleID(unsigned int locale_id,ON_BOOL32 bWin9X)101 unsigned int ON_SetStringConversionWindowsLocaleID(unsigned int locale_id, ON_BOOL32 bWin9X)
102 {
103   unsigned int rc = g_s__windows_locale_id;
104   g_s__windows_locale_os = bWin9X ? 0 : 1;
105   g_s__windows_locale_id = locale_id?true:false;
106   return rc;
107 }
108 
ON_GetStringConversionWindowsLocaleID()109 unsigned int ON_GetStringConversionWindowsLocaleID()
110 {
111   return g_s__windows_locale_id;
112 }
113 
114 
on__hack__tolower(int c)115 static int on__hack__tolower(int c)
116 {
117   // This tolower is a simple "hack" to provide something that
118   // sort of works when OpenNURBS is used with a compiler that
119   // fails to provide functional localization tools.
120 
121 
122   // TODO:
123   //   Expand these switch statments as users provide support
124   //   for symbols.  This is not the correct way to solve this
125   //   problem, but it will work in some simple cases.
126   //   If you are using Microsoft Developer studio in Windows,
127   //   then this code is never called.
128   //
129   // Before you get too carried away, study
130   //
131   //  http://www.microsoft.com/globaldev/wrguide/WRG_sort.asp
132   //
133   // and make sure what you are attempting to do is worth the
134   // trouble.  In short, this approach is doomed to fail
135   // and is not good enough for robust applications that want
136   // to work well with most languages.
137   //
138   // That said, please post your additions to the OpenNURBS
139   // newsgroup so they can be included in future
140   // distrubutions.
141 
142   int i;
143   if ( c <= 0 )
144   {
145     i = c;
146   }
147   else if ( c <= 127 )
148   {
149     // ASCII character
150     i = tolower(c);
151   }
152   else if ( c <= 255 )
153   {
154     // "extended" ASCII character
155     switch(c)
156     {
157       case 192:  // UNICODE Latin capital letter A with grave  (A`)
158         i = 224; // UNICODE Latin small letter A with grave    (a`)
159         break;
160 
161       case 193:  // UNICODE Latin capital letter A with acute  (A')
162         i = 225; // UNICODE Latin small letter A with acute    (a')
163         break;
164 
165       case 194:  // UNICODE Latin capital letter A with circumflex (A^)
166         i = 226; // UNICODE Latin small letter A with circumflex   (a^)
167         break;
168 
169       case 195:  // UNICODE Latin capital letter A with tilde (A~)
170         i = 227; // UNICODE Latin small letter A with tilde   (a~)
171         break;
172 
173       case 196:  // UNICODE Latin capital letter A with diaeresis (A")
174         i = 228; // UNICODE Latin small letter A with diaeresis   (a")
175         break;
176 
177       case 197:  // UNICODE Latin capital letter A with ring above (A ring above)
178         i = 229; // UNICODE Latin small letter A with ring above   (a ring above)
179         break;
180 
181       case 198:  // UNICODE Latin capital letter Ae
182         i = 230; // UNICODE Latin small letter Ae
183         break;
184 
185       case 199:  // UNICODE Latin capital letter C with cedilla (C,)
186         i = 231; // UNICODE Latin small letter C with cedilla   (c,)
187         break;
188 
189       case 200:  // UNICODE Latin capital letter E with grave (E`)
190         i = 232; // UNICODE Latin small letter E with grave   (e`)
191         break;
192 
193       case 201:  // UNICODE Latin capital letter E with acute (E')
194         i = 233; // UNICODE Latin small letter E with acute   (e')
195         break;
196 
197       case 202:  // UNICODE Latin capital letter E with circumflex (E^)
198         i = 234; // UNICODE Latin small letter E with circumflex   (e^)
199         break;
200 
201       case 203:  // UNICODE Latin capital letter E with diaeresis (E")
202         i = 235; // UNICODE Latin small letter E with diaeresis   (e")
203         break;
204 
205       case 204:  // UNICODE Latin capital letter I with grave (I`)
206         i = 236; // UNICODE Latin small letter I with grave   (i`)
207         break;
208 
209       case 205:  // UNICODE Latin capital letter I with acute (I')
210         i = 237; // UNICODE Latin small letter I with acute   (i')
211         break;
212 
213       case 206:  // UNICODE Latin capital letter I with circumflex (I^)
214         i = 238; // UNICODE Latin small letter I with circumflex   (i^)
215         break;
216 
217       case 207:  // UNICODE Latin capital letter I with diaeresis (I")
218         i = 239; // UNICODE Latin small letter I with diaeresis   (i")
219         break;
220 
221       case 208:  // UNICODE Latin capital letter Eth (ED)
222         i = 240; // UNICODE Latin small letter Eth (ed)
223         break;
224 
225       case 209:  // UNICODE Latin capital letter N with tilde (N~)
226         i = 241; // UNICODE Latin small letter n with tilde (n~)
227         break;
228 
229       case 210:  // UNICODE Latin capital letter O with grave (O`)
230         i = 242; // UNICODE Latin small letter O with grave   (o`)
231         break;
232 
233       case 211:  // UNICODE Latin capital letter O with acute (O')
234         i = 243; // UNICODE Latin small letter O with acute   (o')
235         break;
236 
237       case 212:  // UNICODE Latin capital letter O with circumflex (O^)
238         i = 244; // UNICODE Latin small letter O with circumflex   (o^)
239         break;
240 
241       case 213:  // UNICODE Latin capital letter O with tilde (O~)
242         i = 245; // UNICODE Latin small letter O with tilde   (o~)
243         break;
244 
245       case 214:  // UNICODE Latin capital letter O with diaeresis (O")
246         i = 246; // UNICODE Latin small letter O with diaeresis   (o")
247         break;
248 
249       case 216:  // UNICODE Latin capital letter O with stroke (O/)
250         i = 248; // UNICODE Latin small letter O with stroke   (o/)
251         break;
252 
253       case 217:  // UNICODE Latin capital letter U with grave (U`)
254         i = 249; // UNICODE Latin small letter U with grave   (u`)
255         break;
256 
257       case 218:  // UNICODE Latin capital letter U with acute (U')
258         i = 250; // UNICODE Latin small letter U with acute   (u')
259         break;
260 
261       case 219:  // UNICODE Latin capital letter U with circumflex (U^)
262         i = 251; // UNICODE Latin small letter U with circumflex   (u^)
263         break;
264 
265       case 220:  // UNICODE Latin capital letter U with diaeresis (U")
266         i = 252; // UNICODE Latin small letter U with diaeresis   (u")
267         break;
268 
269       case 221:  // UNICODE Latin capital letter Y with acute (Y')
270         i = 253; // UNICODE Latin small letter Y with acute   (y')
271         break;
272 
273       case 222:  // UNICODE Latin capital letter Thorn (P|)
274         i = 254; // UNICODE Latin small letter Thorn   (p|)
275         break;
276 
277       default:
278         i = c;
279         break;
280     }
281   }
282   else if ( c <= 0x0177 )
283   {
284     if ( 0 == (c % 2) )
285       i = c+1;
286     else
287       i = c;
288   }
289   else if ( c <= 0x0192 )
290   {
291     switch( c)
292     {
293     case 0x0178:  // UNICODE Latin capital letter Y with diaeresis (Y")
294       i = 0x00FF; // UNICODE Latin small letter Y with diaeresis   (y")
295       break;
296 
297     case 0x0179:  // UNICODE Latin capital letter Z with acute (Z')
298       i = 0x017A; // UNICODE Latin small letter Z with acute   (z')
299       break;
300 
301     case 0x017B:  // UNICODE Latin capital letter Z with dot above
302       i = 0x017C; // UNICODE Latin small letter Z with dot above
303       break;
304 
305     case 0x017D:  // UNICODE Latin capital letter Z with caron
306       i = 0x017E; // UNICODE Latin small letter Z with caron
307       break;
308 
309     case 0x018F:  // UNICODE Latin capital letter Schwa
310       i = 0x0259; // UNICODE Latin small letter Schwa
311       break;
312 
313     default:
314       i = c;
315       break;
316     }
317   }
318   else if ( c <= 0x01FF )
319   {
320     if ( 0 == (c % 2) )
321       i = c+1;
322     else
323       i = c;
324   }
325   else
326   {
327     // My apologies to those of you whose languages use these symbols.
328     // I am too ignorant to make good guesses at what to do here.
329     // Please fill in as needed and post your changes so I can include
330     // them in future versions of OpenNURBS.
331     switch (c)
332     {
333       // example
334       case 0x0391:  // UNICODE Greek capital letter alpha
335         i = 0x03B1; // UNICODE Greek small letter alpha
336         break;
337 
338       default:
339         i = c;
340     }
341   }
342 
343   return i;
344 }
345 
346 static
on__hack__wcsicmp(const wchar_t * s1,const wchar_t * s2)347 int on__hack__wcsicmp( const wchar_t* s1, const wchar_t* s2)
348 {
349   // This "hack" case insensitive wchar_t compare tool is used
350   // when OpenNURBS is compiled in a development environment
351   // that does not provide proper localization support.
352 
353   // handle NULL strings consistently and without crashing.
354   if ( !s1 )
355   {
356     return s2 ? -1 : 0;
357   }
358   else if ( !s2 )
359   {
360     return 1;
361   }
362 
363   int rc, c1, c2;
364 
365   do
366   {
367     c1 = on__hack__tolower(*s1++);
368     c2 = on__hack__tolower(*s2++);
369     rc = c1-c2;
370   }
371   while( 0 == rc && c1 && c2 );
372 
373   return rc;
374 }
375 
376 #if defined(ON_COMPILER_MSC)
377 // Disable the MSC /W4 unreachable code warning for the call to on__hack__wcsicmp()
378 #pragma warning( push )
379 #pragma warning( disable : 4702 )
380 #endif
381 
on_wcsicmp(const wchar_t * s1,const wchar_t * s2)382 int on_wcsicmp( const wchar_t* s1, const wchar_t* s2)
383 {
384   // handle NULL strings consistently and without crashing.
385   if ( !s1 )
386   {
387     return s2 ? -1 : 0;
388   }
389   else if ( !s2 )
390   {
391     return 1;
392   }
393 
394 #if defined(ON_OS_WINDOWS)
395 
396 #if defined(ON_COMPILER_BORLAND)
397   // Borland's compiler / C library
398   return wcscmpi(s1,s2);
399 #else
400   // Microsoft compiler
401 
402   if ( 0 != g_s__windows_locale_id )
403   {
404     if ( 0 == g_s__windows_locale_os )
405     {
406       // On Win 95/98/ME, CompareStringW() doesn't work
407       // and CompareStringA() is glacial.  So we test
408       // strings and use wcsicmp() whenever it will return
409       // the right answer.
410       {
411         const wchar_t* c1 = s1;
412         const wchar_t* c2 = s2;
413         while ( *c1 > 0 && *c1 < 128 && *c2 > 0 && *c2 < 128 )
414         {
415           c1++;
416           c2++;
417         }
418         if ( 0 == *c1 || 0 == *c2 )
419         {
420 #if defined(ON_COMPILER_MSC1400)
421           return _wcsicmp(s1,s2);
422 #else
423           return wcsicmp(s1,s2);
424 #endif
425         }
426       }
427 
428       // These convert UNICODE to wide character strings
429       ON_String a(s1);
430       ON_String b(s2);
431 
432       // Wide char conversion
433       int rc = ::CompareStringA(g_s__windows_locale_id,
434                            NORM_IGNORECASE | NORM_IGNOREWIDTH,
435                            a.Array(),
436                            -1,
437                            b.Array(),
438                            -1);
439       if (rc == CSTR_LESS_THAN)
440         return -1;
441       if (rc == CSTR_EQUAL)
442         return 0;
443       if (rc == CSTR_GREATER_THAN)
444         return 1;
445     }
446     else
447     {
448       // a version of Windows with working UNICODE support
449       int rc = ::CompareStringW(g_s__windows_locale_id,
450                            NORM_IGNORECASE | NORM_IGNOREWIDTH,
451                            s1,
452                            -1,
453                            s2,
454                            -1);
455 
456       if (rc == CSTR_LESS_THAN)
457         return -1;
458       if (rc == CSTR_EQUAL)
459         return 0;
460       if (rc == CSTR_GREATER_THAN)
461         return 1;
462     }
463   }
464 
465   // Microsoft's wcsicmp() doesn't work right for
466   // upper/lower case accented latin characters,
467   // upper/lower case cyrillic, upper/lower case Greek,
468   // Asian characters, etc.
469   //
470   // Basically, if the character code >= 127 or you are
471   // using a language other than US english, then
472   // Microsoft's wcsicmp() blows it.
473   //
474 #if defined(ON_COMPILER_MSC1400)
475   return _wcsicmp(s1,s2); // Microsoft's compiler / C library
476 #else
477   return wcsicmp(s1,s2); // Microsoft's compiler / C library
478 #endif
479 
480 #endif
481 
482 
483 #endif
484 
485   // If your compiler does not have a way to perform
486   // a case insensitive compare of UNICODE strings,
487   // then use the "hack" version below.
488   return on__hack__wcsicmp(s1,s2);
489 }
490 
491 #if defined(ON_COMPILER_MSC)
492 #pragma warning( pop )
493 #endif
494 
on_wcsupr(wchar_t * s)495 wchar_t* on_wcsupr(wchar_t* s)
496 {
497 #if defined(ON_OS_WINDOWS)
498 #if defined(ON_COMPILER_BORLAND)
499   // Borland's compiler / C library
500   return _wcsupr(s);
501 #else
502   // Microsoft compiler
503   return _wcsupr(s);
504 #endif
505 #else
506   if (s)
507   {
508     wchar_t c;
509     while (*s)
510     {
511       if ( 0 != (c = toupper(*s)) )
512         *s = c;
513       s++;
514     }
515   }
516   return s;
517 #endif
518 }
519 
520 // on_wcslwr() calls _wcslwr() or wcslwr() depending on OS
on_wcslwr(wchar_t * s)521 wchar_t* on_wcslwr(wchar_t* s)
522 {
523 #if defined(ON_OS_WINDOWS)
524 #if defined(ON_COMPILER_BORLAND)
525   // Borland's compiler / C library
526   return _wcslwr(s);
527 #else
528   // Microsoft compiler
529   return _wcslwr(s);
530 #endif
531 #else
532   if (s)
533   {
534     wchar_t c;
535     while (*s)
536     {
537       if ( 0 != (c = tolower(*s)) )
538         *s = c;
539       s++;
540     }
541   }
542   return s;
543 #endif
544 }
545 
MakeUpper()546 void ON_wString::MakeUpper()
547 {
548   if ( !IsEmpty() )
549   {
550 #if defined(ON_OS_WINDOWS)
551     if ( 0 != g_s__windows_locale_id )
552     {
553       if ( 0 == g_s__windows_locale_os )
554       {
555         // On Win 95/98/ME, LCMapStringW() doesn't work.
556         // (I hope you don't need the right answer in a hurry on Win9X.)
557 
558         // These convert UNICODE to wide character strings
559         ON_String in(*this);
560         int len_in = in.Length();
561         int max_len_out = 2*len_in+16; // if 2x for wide char expansion
562         ON_String out;
563         out.ReserveArray(max_len_out+1);
564         out.SetLength(max_len_out+1);
565 
566         // Wide char conversion
567         int rc = ::LCMapStringA(g_s__windows_locale_id,
568                               LCMAP_UPPERCASE,
569                               in.Array(),
570                               len_in,
571                               out.Array(),
572                               max_len_out);
573         if (rc > 0 && rc <= max_len_out)
574         {
575           out.SetLength(rc);
576           operator=(out); // multi-byte to wchar conversion
577           return;
578         }
579       }
580       else
581       {
582         // a version of Windows with working UNICODE support
583         int len_in = Length();
584         int max_len_out = len_in+16;
585         ON_wString out;
586         out.ReserveArray(max_len_out+1);
587         out.SetLength(max_len_out+1);
588 
589         // Wide char conversion
590         int rc = ::LCMapStringW(g_s__windows_locale_id,
591                               LCMAP_UPPERCASE,
592                               Array(),
593                               len_in,
594                               out.Array(),
595                               max_len_out);
596         if (rc > 0 && rc <= max_len_out)
597         {
598           out.SetLength(rc);
599           operator=(out); // very fast - simply changes reference count
600           return;
601         }
602       }
603     }
604 #endif
605 
606     // If ::LCMapStringA() or ::LCMapStringW() failed or we are
607     // running on a non-Windows OS, then we fall through to the
608     // wcslwr() function which will handle most most characters
609     // in most Western European languages but is not adequate for
610     // commercial quality software.
611   	CopyArray();
612     on_wcsupr(m_s);
613   }
614 }
615 
MakeLower()616 void ON_wString::MakeLower()
617 {
618   if ( !IsEmpty() )
619   {
620 #if defined(ON_OS_WINDOWS)
621     if ( 0 != g_s__windows_locale_id )
622     {
623       if ( 0 == g_s__windows_locale_os )
624       {
625         // On Win 95/98/ME, LCMapStringW() doesn't work.
626         // (I hope you don't need the right answer in a hurry on Win9X.)
627 
628         // These convert UNICODE to wide character strings
629         ON_String in(*this);
630         int len_in = in.Length();
631         int max_len_out = 2*len_in+16; // if 2x for wide char expansion
632         ON_String out;
633         out.ReserveArray(max_len_out+1);
634         out.SetLength(max_len_out+1);
635 
636         // Wide char conversion to multi-byte lower case string
637         int rc = ::LCMapStringA(g_s__windows_locale_id,
638                               LCMAP_LOWERCASE,
639                               in.Array(),
640                               len_in,
641                               out.Array(),
642                               max_len_out);
643         if (rc > 0 && rc <= max_len_out)
644         {
645           out.SetLength(rc);
646           operator=(out); // multi-byte to wchar conversion
647           return;
648         }
649       }
650       else
651       {
652         // a version of Windows with working UNICODE support
653         int len_in = Length();
654         int max_len_out = len_in+16;
655 
656         // ReserveArray(max_len_out+1) allocates max_len_out+2
657         // wchars (room for the NULL terminator is allocatcated).
658         // The +1 is just in case LCMapStringW() has a bug and
659         // writes an extra wchar or puts a NULL terminator
660         // in s[max_len_out]. This is a lot of paranoia, but
661         // the memory cost is negligable and it will prevent
662         // difficult to diagnose crashes if MS releases a buggy
663         // version of LCMapStringW().
664         ON_wString out;
665         out.ReserveArray(max_len_out+1);
666         out.SetLength(max_len_out+1);
667 
668         // Wide char conversion to lower case.
669         // Note that changing to lower case in some languages
670         // can change the string length.
671         int rc = ::LCMapStringW(g_s__windows_locale_id,
672                               LCMAP_LOWERCASE,
673                               Array(),
674                               len_in,
675                               out.Array(),
676                               max_len_out);
677         if (rc > 0 && rc <= max_len_out)
678         {
679           out.SetLength(rc);
680           operator=(out); // very fast - simply changes reference count
681           return;
682         }
683       }
684     }
685 #endif
686 
687     // If ::LCMapStringA() or ::LCMapStringW() failed or we are
688     // running on a non-Windows OS, then we fall through to the
689     // wcslwr() function which will handle most most characters
690     // in most Western European languages but is not adequate for
691     // commercial quality software.
692     CopyArray();
693     on_wcslwr(m_s);
694   }
695 }
696 
on_wcsrev(wchar_t * s)697 wchar_t* on_wcsrev(wchar_t* s)
698 {
699   if ( !s )
700     return 0;
701   int i, j;
702   wchar_t w;
703   for ( j = 0; 0 != s[j]; j++ )
704   {
705     // empty for body
706   }
707 
708   for ( i = 0, j--; i < j; i++, j-- )
709   {
710     w = s[i];
711     if ( w >= 0xD800 && w <= 0xDBFF && s[i+1] >= 0xDC00 && s[i+1] <= 0xDFFF )
712     {
713       // UTF-16 surrogate pair
714       if ( i+1 < j-1 )
715       {
716         s[i] = s[j-1];
717         s[j-1] = w;
718         w = s[i+1];
719         s[i+1] = s[j];
720         s[j] = w;
721       }
722       i++;
723       j--;
724     }
725     else
726     {
727       s[i] = s[j];
728       s[j] = w;
729     }
730   }
731   return s;
732 }
733 
on_WideCharToMultiByte(const wchar_t * lpWideCharStr,int cchWideChar,char * lpMultiByteStr,int cchMultiByte)734 int on_WideCharToMultiByte(
735     const wchar_t* lpWideCharStr,
736     int cchWideChar,
737     char* lpMultiByteStr,
738     int cchMultiByte
739     )
740 {
741   // 14 March 2011 Dale Lear
742   //   It turns out that Windows WideCharToMultiByte does correctly
743   //   convert UTF-16 to UTF-8 in Windows 7 when the code page
744   //   is CP_ACP and calls with CP_UTF8 sometimes fail to do
745   //   any conversion.  So, I wrote ON_ConvertWideCharToUTF8()
746   //   and opennurbs will use ON_ConvertWideCharToUTF8 to get
747   //   consistent results on all platforms.
748   unsigned int error_status = 0;
749   unsigned int error_mask = 0xFFFFFFFF;
750   ON__UINT32 error_code_point = 0xFFFD;
751   const wchar_t* p1 = 0;
752   int count = ON_ConvertWideCharToUTF8(false,lpWideCharStr,cchWideChar,lpMultiByteStr,cchMultiByte,
753                                        &error_status,error_mask,error_code_point,&p1);
754   if ( 0 != error_status )
755   {
756     ON_ERROR("Error converting UTF-16 encoded wchar_t string to UTF-8 encoded char string.");
757   }
758   return count;
759 }
760 
on_MultiByteToWideChar(const char * lpMultiByteStr,int cchMultiByte,wchar_t * lpWideCharStr,int cchWideChar)761 int on_MultiByteToWideChar(
762     const char* lpMultiByteStr,
763     int cchMultiByte,
764     wchar_t* lpWideCharStr,
765     int cchWideChar
766     )
767 {
768   // 14 March 2011 Dale Lear
769   //   It turns out that Windows WideCharToMultiByte does not correctly
770   //   convert UTF-8 to UTF-16 in Windows 7 when the code page
771   //   is CP_ACP and calls with CP_UTF8 sometimes fail to do
772   //   any conversion.  So, I wrote ON_ConvertUTF8ToWideChar()
773   //   and opennurbs will use ON_ConvertUTF8ToWideChar to get
774   //   consistent results on all platforms.
775   unsigned int error_status = 0;
776   unsigned int error_mask = 0xFFFFFFFF;
777   ON__UINT32 error_code_point = 0xFFFD;
778   const char* p1 = 0;
779   int count = ON_ConvertUTF8ToWideChar(false,lpMultiByteStr,cchMultiByte,lpWideCharStr,cchWideChar,
780                                        &error_status,error_mask,error_code_point,&p1);
781   if ( 0 != error_status )
782   {
783     ON_ERROR("Error converting UTF-8 encoded char string to UTF-16 encoded wchar_t string.");
784   }
785   return count;
786 }
787 
on_vsnprintf(char * buffer,size_t count,const char * format,va_list argptr)788 int on_vsnprintf( char *buffer, size_t count, const char *format, va_list argptr )
789 {
790 #if defined(ON_OS_WINDOWS)
791 
792 #if defined(ON_COMPILER_BORLAND)
793   return vsprintf( buffer, format, argptr );
794 #else
795   return _vsnprintf( buffer, count, format, argptr );
796 #endif
797 
798 #else
799   return vsnprintf( buffer, count, format, argptr );
800 #endif
801 }
802 
on_vsnwprintf(wchar_t * buffer,size_t count,const wchar_t * format,va_list argptr)803 int on_vsnwprintf( wchar_t *buffer, size_t count, const wchar_t *format, va_list argptr )
804 {
805 #if defined(ON_OS_WINDOWS)
806 
807 #if defined(ON_COMPILER_BORLAND)
808   return vswprintf( buffer, format, argptr );
809 #else
810   return _vsnwprintf( buffer, count, format, argptr );
811 #endif
812 
813 #else
814   // if an OS doesn't support vsnwprintf(), use ASCII and hope for the best
815 
816   ON_String aformat = format; // convert format from UNICODE to ASCII
817 
818   // format an ASCII buffer
819   char* abuffer = (char*)onmalloc(4*count*sizeof(*abuffer));
820   int rc = on_vsnprintf( abuffer, 4*count, aformat.Array(), argptr );
821 
822   // convert formatted ASCII buffer to UNICODE
823   on_MultiByteToWideChar( abuffer, (int)strlen(abuffer), buffer, (int)count );
824   onfree(abuffer);
825   return rc;
826 #endif
827 }
828 
on_splitpath(const char * path,const char ** drive,const char ** dir,const char ** fname,const char ** ext)829 void on_splitpath(
830   const char* path,
831   const char** drive,
832   const char** dir,
833   const char** fname,
834   const char** ext
835   )
836 {
837   // The "const char* path" parameter is a UTF-8 encoded string.
838   // Since the unicode code point values for the characters we
839   // are searching for ( '/' '\' '.' ':' A-Z a-z) are all > 0
840   // and < 128, we can simply check for an array element having
841   // the character value and not have to worry about dealing
842   // with UTF-8 continuation values (>= 128).
843 
844   const char slash1 = '/';
845   const char slash2 = '\\'; // do this even with the os is unix because
846                             // we might be parsing a file name saved
847                             // in Windows.
848 
849   const char* f;
850   const char* e;
851   const char* s;
852   const char* s1;
853 
854   if ( 0 != drive )
855     *drive = 0;
856   if ( 0 != dir )
857     *dir = 0;
858   if ( 0 != fname )
859     *fname = 0;
860   if ( 0 != ext )
861     *ext = 0;
862 
863   if ( 0 != path && 0 != *path )
864   {
865     // deal with Windows' drive letter (even when the os is unix)
866     if ( ':' == path[1] )
867     {
868       if ( (path[0] >= 'A' && path[0] <= 'Z') || (path[0] >= 'a' && path[0] <= 'z') )
869       {
870         if ( drive )
871           *drive = path;
872         path += 2;
873         if ( 0 == *path )
874           return;
875       }
876     }
877   }
878 
879   if ( 0 != path && 0 != *path )
880   {
881     e = 0;
882     f = 0;
883     s1 = path;
884     while ( 0 != *s1 )
885       s1++;
886     s = (s1 > path) ? s1 - 1 : path;
887 
888     while ( s > path && '.' != *s && slash1 != *s && slash2 != *s )
889       s--;
890 
891     if ( '.' == *s && 0 != s[1] )
892     {
893       // extensions must have something after the dot.
894       e = s;
895       s1 = e;
896       s--;
897     }
898 
899     while ( s > path && slash1 != *s && slash2 != *s )
900       s--;
901 
902     if ( s >= path && s < s1 )
903     {
904       if (slash1 == *s || slash2 == *s )
905       {
906         if ( s+1 < s1 )
907           f = s+1;
908       }
909       else if ( s == path )
910       {
911         f = s;
912       }
913     }
914 
915     if ( 0 == f )
916     {
917       // must have a non-empty filename in order to have and "extension"
918       f = e;
919       e = 0;
920     }
921 
922     if ( 0 != dir && (0 == f || path < f) )
923       *dir = path;
924 
925     if ( 0 != f && 0 != fname )
926       *fname = f;
927 
928     if ( 0 != e && 0 != ext )
929       *ext = e;
930   }
931 
932 }
933 
on_wsplitpath(const wchar_t * path,const wchar_t ** drive,const wchar_t ** dir,const wchar_t ** fname,const wchar_t ** ext)934 void on_wsplitpath(
935   const wchar_t* path,
936   const wchar_t** drive,
937   const wchar_t** dir,
938   const wchar_t** fname,
939   const wchar_t** ext
940   )
941 {
942   // The "const wchar_t* path" parameter is a UTF-8, UTF-16 or UTF-32
943   // encoded string. Since the unicode code point values for the
944   // characters we are searching for ( '/' '\' '.' ':' A-Z a-z) are
945   // all > 0 and < 128, we can simply check for an array element
946   // having the character value and not have to worry about dealing
947   // with UTF-16 surrogate pair values (0xD800-0xDBFF and DC00-DFFF)
948   // and UTF-8 continuation values (>= 128).
949 
950   const wchar_t slash1 = '/';
951   const wchar_t slash2 = '\\'; // do this even with the os is unix because
952                                // we might be parsing a file name saved
953                                // in Windows.
954 
955   const wchar_t* f;
956   const wchar_t* e;
957   const wchar_t* s;
958   const wchar_t* s1;
959 
960   if ( 0 != drive )
961     *drive = 0;
962   if ( 0 != dir )
963     *dir = 0;
964   if ( 0 != fname )
965     *fname = 0;
966   if ( 0 != ext )
967     *ext = 0;
968 
969   if ( 0 != path && 0 != *path )
970   {
971     // deal with Windows' drive letter (even when the os is unix)
972     if ( ':' == path[1] )
973     {
974       if ( (path[0] >= 'A' && path[0] <= 'Z') || (path[0] >= 'a' && path[0] <= 'z') )
975       {
976         if ( drive )
977           *drive = path;
978         path += 2;
979         if ( 0 == *path )
980           return;
981       }
982     }
983   }
984 
985   if ( 0 != path && 0 != *path )
986   {
987     e = 0;
988     f = 0;
989     s1 = path;
990     while ( 0 != *s1 )
991       s1++;
992     s = (s1 > path) ? s1 - 1 : path;
993 
994     while ( s > path && '.' != *s && slash1 != *s && slash2 != *s )
995       s--;
996 
997     if ( '.' == *s && 0 != s[1] )
998     {
999       // extensions must have something after the dot.
1000       e = s;
1001       s1 = e;
1002       s--;
1003     }
1004 
1005     while ( s > path && slash1 != *s && slash2 != *s )
1006       s--;
1007 
1008     if ( s >= path && s < s1 )
1009     {
1010       if (slash1 == *s || slash2 == *s )
1011       {
1012         if ( s+1 < s1 )
1013           f = s+1;
1014       }
1015       else if ( s == path )
1016       {
1017         f = s;
1018       }
1019     }
1020 
1021     if ( 0 == f )
1022     {
1023       // must have a non-empty filename in order to have and "extension"
1024       f = e;
1025       e = 0;
1026     }
1027 
1028     if ( 0 != dir && (0 == f || path < f) )
1029       *dir = path;
1030 
1031     if ( 0 != f && 0 != fname )
1032       *fname = f;
1033 
1034     if ( 0 != e && 0 != ext )
1035       *ext = e;
1036   }
1037 
1038 }
1039 
1040 
1041 
Version()1042 int ON::Version()
1043 {
1044 #define OPENNURBS_VERSION_DEFINITION
1045 #include "opennurbs_version.h"
1046   return OPENNURBS_VERSION;
1047 #undef OPENNURBS_VERSION
1048 #undef OPENNURBS_VERSION_DEFINITION
1049 }
1050 
SourceRevision()1051 const char* ON::SourceRevision()
1052 {
1053   return OPENNURBS_SRC_SVN_REVISION;
1054 }
1055 
SourceBranch()1056 const char* ON::SourceBranch()
1057 {
1058   return OPENNURBS_SRC_SVN_BRANCH;
1059 }
1060 
DocumentationRevision()1061 const char* ON::DocumentationRevision()
1062 {
1063   return OPENNURBS_DOC_SVN_REVISION;
1064 }
1065 
DocumentationBranch()1066 const char* ON::DocumentationBranch()
1067 {
1068   return OPENNURBS_DOC_SVN_BRANCH;
1069 }
1070 
OpenFile(const char * filename,const char * filemode)1071 FILE* ON::OpenFile( // like fopen() - needed when OpenNURBS is used as a DLL
1072         const char* filename, // file name
1073         const char* filemode // file mode
1074         )
1075 {
1076   return ON_FileStream::Open(filename,filemode);
1077 }
1078 
OpenFile(const wchar_t * filename,const wchar_t * filemode)1079 FILE* ON::OpenFile( // like fopen() - needed when OpenNURBS is used as a DLL
1080         const wchar_t* filename, // file name
1081         const wchar_t* filemode // file mode
1082         )
1083 {
1084   return ON_FileStream::Open(filename,filemode);
1085 }
1086 
CloseFile(FILE * fp)1087 int ON::CloseFile( // like fclose() - needed when OpenNURBS is used as a DLL
1088         FILE* fp // pointer returned by OpenFile()
1089         )
1090 {
1091   return ON_FileStream::Close(fp);
1092 }
1093 
CloseAllFiles()1094 int ON::CloseAllFiles()
1095 {
1096   // returns number of files closed or EOF for error
1097 #if defined(ON_OS_WINDOWS)
1098   return _fcloseall(); // ANSI C name
1099 #else
1100   // I can't find an fcloseall() or _fcloseall() in
1101   // gcc version egcs-2.91.66 19990314/Linux (egcs-1.1.2 release)
1102   return EOF;
1103 #endif
1104 }
1105 
1106 
1107 
ActiveSpace(int i)1108 ON::active_space ON::ActiveSpace(int i)
1109 {
1110   ON::active_space as;
1111 
1112   switch(i)
1113   {
1114   case no_space:    as = no_space;    break;
1115   case model_space: as = model_space; break;
1116   case page_space:  as = page_space;  break;
1117   default:          as = no_space;    break;
1118   }
1119 
1120   return as;
1121 }
1122 
1123 
UnitSystem(int i)1124 ON::unit_system ON::UnitSystem(int i)
1125 {
1126   unit_system us = no_unit_system;
1127   switch(i) {
1128   case no_unit_system: us = no_unit_system; break;
1129 
1130   case angstroms: us = angstroms; break;
1131 
1132   case nanometers: us = nanometers; break;
1133   case microns: us = microns; break;
1134   case millimeters: us = millimeters; break;
1135   case centimeters: us = centimeters; break;
1136   case decimeters: us = decimeters; break;
1137   case meters: us = meters; break;
1138   case dekameters: us = dekameters; break;
1139   case hectometers: us = hectometers; break;
1140   case kilometers: us = kilometers; break;
1141   case megameters: us = megameters; break;
1142   case gigameters: us = gigameters; break;
1143   case microinches: us = microinches; break;
1144   case mils: us = mils; break;
1145   case inches: us = inches; break;
1146   case feet: us = feet; break;
1147   case yards: us = yards; break;
1148   case miles: us = miles; break;
1149   case printer_point: us = printer_point; break;
1150   case printer_pica: us = printer_pica; break;
1151   case nautical_mile: us = nautical_mile; break;
1152   case astronomical: us = astronomical; break;
1153   case lightyears: us = lightyears; break;
1154   case parsecs: us = parsecs; break;
1155   case custom_unit_system: us = custom_unit_system; break;
1156   default: us = no_unit_system; break;
1157   }
1158   return us;
1159 }
1160 
UnitScale(const class ON_3dmUnitsAndTolerances & u_and_t_from,const class ON_3dmUnitsAndTolerances & u_and_t_to)1161 double ON::UnitScale(
1162                      const class ON_3dmUnitsAndTolerances& u_and_t_from,
1163                      const class ON_3dmUnitsAndTolerances& u_and_t_to
1164                      )
1165 {
1166   return ON::UnitScale( u_and_t_from.m_unit_system, u_and_t_to.m_unit_system );
1167 }
1168 
UnitScale(ON::unit_system us_from,const class ON_UnitSystem & us_to)1169 double ON::UnitScale(
1170     ON::unit_system us_from,
1171     const class ON_UnitSystem& us_to
1172     )
1173 {
1174   double scale = 1.0;
1175   ON::unit_system us1 = us_to.m_unit_system;
1176   if ( ON::custom_unit_system == us1 )
1177   {
1178     if ( us_to.m_custom_unit_scale > 0.0 && ON_IsValid(us_to.m_custom_unit_scale) )
1179     {
1180       scale *= us_to.m_custom_unit_scale;
1181       us1 = ON::meters;
1182     }
1183   }
1184   return scale*ON::UnitScale(us_from,us1);
1185 }
1186 
UnitScale(const class ON_UnitSystem & us_from,ON::unit_system us_to)1187 double ON::UnitScale(
1188     const class ON_UnitSystem& us_from,
1189     ON::unit_system us_to
1190     )
1191 {
1192   double scale = 1.0;
1193   ON::unit_system us0 = us_from.m_unit_system;
1194   if ( ON::custom_unit_system == us0 )
1195   {
1196     if ( us_from.m_custom_unit_scale > 0.0 && ON_IsValid(us_from.m_custom_unit_scale) )
1197     {
1198       scale /= us_from.m_custom_unit_scale;
1199       us0 = ON::meters;
1200     }
1201   }
1202   return scale*ON::UnitScale(us0,us_to);
1203 }
1204 
UnitScale(const class ON_UnitSystem & u_and_t_from,const class ON_UnitSystem & u_and_t_to)1205 double ON::UnitScale(
1206                      const class ON_UnitSystem& u_and_t_from,
1207                      const class ON_UnitSystem& u_and_t_to
1208                      )
1209 {
1210   double scale = 1.0;
1211   ON::unit_system us_from = u_and_t_from.m_unit_system;
1212   ON::unit_system us_to   = u_and_t_to.m_unit_system;
1213 
1214   if ( ON::no_unit_system != us_from && ON::no_unit_system != us_to )
1215   {
1216     if ( ON::custom_unit_system == us_from
1217          && ON_IsValid(u_and_t_from.m_custom_unit_scale)
1218          && u_and_t_from.m_custom_unit_scale > 0.0 )
1219     {
1220       scale /= u_and_t_from.m_custom_unit_scale;
1221       us_from = ON::meters;
1222     }
1223 
1224     if ( ON::custom_unit_system == us_to
1225          && ON_IsValid(u_and_t_to.m_custom_unit_scale)
1226          && u_and_t_to.m_custom_unit_scale > 0.0 )
1227     {
1228       scale *= u_and_t_to.m_custom_unit_scale;
1229       us_to = ON::meters;
1230     }
1231 
1232     scale *= ON::UnitScale( us_from, us_to );
1233   }
1234 
1235   return scale;
1236 }
1237 
IsEnglishUnit(ON::unit_system us)1238 static bool IsEnglishUnit( ON::unit_system us )
1239 {
1240   return (
1241           ON::microinches == us
1242           || ON::mils == us
1243           || ON::inches == us
1244           || ON::feet == us
1245           || ON::yards == us
1246           || ON::miles == us
1247           || ON::printer_point == us
1248           || ON::printer_pica == us
1249          );
1250 }
1251 
UnitScale(ON::unit_system u0,ON::unit_system u1)1252 double ON::UnitScale(
1253             ON::unit_system u0, // from
1254             ON::unit_system u1  // to
1255             )
1256 {
1257   // Scale factor for changing unit systems
1258   // Examples
1259   //   100.0  = UnitScale( ON::meters, ON::centimeters )
1260   //     2.54 = UnitScale( ON::inches, ON::centimeters )
1261   //    12.0  = UnitScale( ON::feet, ON::inches )
1262 
1263   // the default cases are here to keep lint quiet
1264   double scale = 1.0;
1265 
1266   if (  u0 != u1
1267         && u1 != ON::custom_unit_system
1268         && ((int)u1) > 0 && ((int)u1) < 26
1269         // switch weeds out bogus values of u0
1270       )
1271   switch( u0 )
1272   {
1273   case ON::angstroms:
1274     scale = UnitScale( meters, u1)*1.0e-10;
1275     break;
1276 
1277   case ON::nanometers:
1278     scale = UnitScale( meters, u1)*1.0e-9;
1279     break;
1280 
1281   case ON::microns:
1282     scale = UnitScale( meters, u1)*1.0e-6;
1283     break;
1284 
1285   case ON::millimeters:
1286     switch( u1 )
1287     {
1288     case ON::meters:      scale = 1.0e-3; break;
1289     case ON::microns:     scale = 1.0e+3; break;
1290     case ON::centimeters: scale = 1.0e-1; break;
1291 
1292     default:
1293       scale = IsEnglishUnit(u1)
1294             ? UnitScale( inches, u1 )/25.4
1295             : UnitScale( meters, u1 )*1.0e-3;
1296       break;
1297     }
1298     break;
1299 
1300   case ON::centimeters:
1301     switch( u1 )
1302     {
1303     case ON::meters:      scale = 1.0e-2; break;
1304     case ON::millimeters: scale = 1.0e+1; break;
1305 
1306     default:
1307       scale = IsEnglishUnit(u1)
1308             ? UnitScale( inches, u1 )/2.54
1309             : UnitScale( meters, u1 )*1.0e-2;
1310       break;
1311     }
1312     break;
1313 
1314   case ON::decimeters:
1315     scale = IsEnglishUnit(u1)
1316           ? UnitScale( inches, u1 )/0.254
1317           : UnitScale( meters, u1 )*1.0e-1;
1318     break;
1319 
1320   case ON::meters:
1321     switch( u1 )
1322     {
1323     case ON::angstroms:      scale = 1.0e+10; break;
1324     case ON::nanometers:     scale = 1.0e+9;  break;
1325     case ON::microns:        scale = 1.0e+6;  break;
1326     case ON::millimeters:    scale = 1.0e+3;  break;
1327     case ON::centimeters:    scale = 1.0e+2;  break;
1328     case ON::decimeters:     scale = 1.0e1;   break;
1329     case ON::meters:         scale = 1.0;     break;
1330     case ON::dekameters:     scale = 1.0e-1;  break;
1331     case ON::hectometers:    scale = 1.0e-2;  break;
1332     case ON::kilometers:     scale = 1.0e-3;  break;
1333     case ON::megameters:     scale = 1.0e-6;  break;
1334     case ON::gigameters:     scale = 1.0e-9;  break;
1335 
1336     case ON::nautical_mile:  scale = 1.0/1852.0; break;
1337     case ON::astronomical:   scale = 1.0/1.4959787e+11; break;
1338     case ON::lightyears:     scale = 1.0/9.4607304725808e+15; break;
1339     case ON::parsecs:        scale = 1.0/3.08567758e+16; break;
1340 
1341     default:
1342       if ( IsEnglishUnit(u1) )
1343         scale = UnitScale( inches, u1 )/0.0254;
1344       break;
1345     }
1346     break;
1347 
1348   case ON::dekameters:
1349     scale = UnitScale( meters, u1 )*10.0;
1350     break;
1351 
1352   case ON::hectometers:
1353     scale = UnitScale( meters, u1 )*100.0;
1354     break;
1355 
1356   case ON::kilometers:
1357     scale = IsEnglishUnit(u1)
1358           ? UnitScale( inches, u1 )/0.0000254
1359           : UnitScale( meters, u1 )*1000.0;
1360     break;
1361 
1362   case ON::megameters:
1363     scale = UnitScale( meters, u1 )*1.0e6;
1364     break;
1365 
1366   case ON::gigameters:
1367     scale = UnitScale( meters, u1 )*1.0e9;
1368     break;
1369 
1370   case ON::microinches:
1371     scale = UnitScale( inches, u1 )*1.0e-6;
1372     break;
1373 
1374   case ON::mils:
1375     scale = UnitScale( inches, u1 )*1.0e-3;
1376     break;
1377 
1378   case ON::inches:
1379     switch( u1 )
1380     {
1381     case ON::angstroms:       scale = 2.54e+8; break;
1382     case ON::nanometers:      scale = 2.54e+7; break;
1383     case ON::microns:         scale = 2.54e+4; break;
1384     case ON::millimeters:     scale = 25.4; break;
1385     case ON::centimeters:     scale = 2.54; break;
1386     case ON::decimeters:      scale = 2.54e-1; break;
1387     case ON::meters:          scale = 2.54e-2; break;
1388     case ON::dekameters:      scale = 2.54e-3; break;
1389     case ON::hectometers:     scale = 2.54e-4; break;
1390     case ON::kilometers:      scale = 2.54e-5; break;
1391     case ON::megameters:      scale = 2.54e-8; break;
1392     case ON::gigameters:      scale = 2.54e-11; break;
1393 
1394     case ON::printer_point: scale = 72.0;            break;
1395     case ON::printer_pica:  scale = 6.0;             break;
1396     case ON::microinches: scale = 1.0e+6;            break;
1397     case ON::mils:        scale = 1.0e+3;            break;
1398     case ON::inches:      scale = 1.0;               break;
1399     case ON::feet:        scale = 1.0/12.0;          break;
1400     case ON::yards:       scale = 1.0/36.0;          break;
1401     case ON::miles:       scale = 1.0/(12.0*5280.0); break;
1402 
1403     default:
1404       scale = UnitScale( meters, u1 )*2.54e-2;
1405       break;
1406     }
1407     break;
1408 
1409   case ON::feet:
1410     switch( u1 )
1411     {
1412     case ON::yards:       scale = 1.0/3.0; break;
1413     case ON::miles:       scale = 1.0/5280.0; break;
1414     default:
1415       scale = UnitScale( inches, u1 )*12.0;
1416       break;
1417     }
1418     break;
1419 
1420   case ON::yards:
1421     switch( u1 )
1422     {
1423     case ON::feet:        scale = 3.0; break;
1424     case ON::miles:       scale = 1.0/1760.0; break;
1425     default:
1426       scale = UnitScale( inches, u1 )*36.0;
1427       break;
1428     }
1429     break;
1430 
1431   case ON::miles:
1432     if ( ON::feet == u1 )
1433     {
1434       scale = 5280.0;
1435     }
1436     else
1437     {
1438       scale = IsEnglishUnit(u1)
1439             ? UnitScale( inches, u1 )*12.0*5280.0
1440             : UnitScale( meters, u1 )*1609.344;
1441     }
1442     break;
1443 
1444   case ON::printer_point:
1445     scale = UnitScale( inches, u1 )/72.0;
1446     break;
1447 
1448   case ON::printer_pica:
1449     scale = UnitScale( inches, u1 )/6.0;
1450     break;
1451 
1452   case ON::nautical_mile:
1453     scale = UnitScale( meters, u1 )*1852.0;
1454     break;
1455 
1456   case ON::astronomical:
1457     // 1.4959787e+11  http://en.wikipedia.org/wiki/Astronomical_unit
1458     // 1.495979e+11   http://units.nist.gov/Pubs/SP811/appenB9.htm
1459     //    An astronomical unit (au) is the mean distance from the
1460     //    center of the earth to the center of the sun.
1461     scale = UnitScale( meters, u1 )*1.4959787e+11;
1462     break;
1463 
1464   case ON::lightyears:
1465     // 9.4607304725808e+15 http://en.wikipedia.org/wiki/Light_year
1466     // 9.46073e+15 meters  http://units.nist.gov/Pubs/SP811/appenB9.htm
1467     //    A light year is the distance light travels in one Julian year.
1468     //    The speed of light is exactly 299792458 meters/second.
1469     //    A Julian year is exactly 365.25 * 86400 seconds and is
1470     //    approximately the time it takes for one earth orbit.
1471     scale = UnitScale( meters, u1 )*9.4607304725808e+15;
1472     break;
1473 
1474   case ON::parsecs:
1475     // 3.08567758e+16  // http://en.wikipedia.org/wiki/Parsec
1476     // 3.085678e+16    // http://units.nist.gov/Pubs/SP811/appenB9.htm
1477     scale = UnitScale( meters, u1 )*3.08567758e+16;
1478     break;
1479 
1480   case ON::custom_unit_system:
1481   case ON::no_unit_system:
1482     // nothing to do here
1483     break;
1484   }
1485 
1486   return scale;
1487 }
1488 
1489 
1490 //// distance_display_mode ///////////////////////////////////
1491 enum distance_display_mode
1492 {
1493   decimal     = 0,
1494   fractional  = 1,
1495   feet_inches = 2
1496 };
1497 
DistanceDisplayMode(int i)1498 ON::distance_display_mode ON::DistanceDisplayMode(int i)
1499 {
1500   distance_display_mode dm = decimal;
1501   switch (i)
1502   {
1503   case decimal:
1504     dm = decimal;
1505     break;
1506   case fractional:
1507     dm = fractional;
1508     break;
1509   case feet_inches:
1510     dm = feet_inches;
1511     break;
1512   }
1513   return dm;
1514 }
1515 
1516 
PointStyle(int i)1517 ON::point_style ON::PointStyle(int i)
1518 {
1519   //convertintegertopoint_styleenum
1520   point_style ps = unknown_point_style;
1521   switch (i) {
1522   case not_rational: ps = not_rational; break;
1523   case homogeneous_rational: ps = homogeneous_rational; break;
1524   case euclidean_rational: ps = euclidean_rational; break;
1525   default: ps = unknown_point_style; break;
1526   }
1527   return ps;
1528 }
1529 
1530 
KnotStyle(int i)1531 ON::knot_style ON::KnotStyle(int i)
1532 {
1533   //convertintegertoknot_styleenum
1534   knot_style ks = unknown_knot_style;
1535   switch (i) {
1536   case uniform_knots: ks = uniform_knots; break;
1537   case quasi_uniform_knots: ks = quasi_uniform_knots; break;
1538   case piecewise_bezier_knots: ks = piecewise_bezier_knots; break;
1539   case clamped_end_knots: ks = clamped_end_knots; break;
1540   case non_uniform_knots: ks = non_uniform_knots; break;
1541   default: ks = unknown_knot_style; break;
1542   }
1543   return ks;
1544 }
1545 
Continuity(int i)1546 ON::continuity ON::Continuity(int i)
1547 {
1548   continuity c = unknown_continuity;
1549 
1550   switch(i)
1551   {
1552   case unknown_continuity: c = unknown_continuity; break;
1553   case C0_continuous: c = C0_continuous; break;
1554   case C1_continuous: c = C1_continuous; break;
1555   case C2_continuous: c = C2_continuous; break;
1556   case G1_continuous: c = G1_continuous; break;
1557   case G2_continuous: c = G2_continuous; break;
1558 
1559   // 30 March 2003 Dale Lear added these
1560   case C0_locus_continuous: c = C0_locus_continuous; break;
1561   case C1_locus_continuous: c = C1_locus_continuous; break;
1562   case C2_locus_continuous: c = C2_locus_continuous; break;
1563   case G1_locus_continuous: c = G1_locus_continuous; break;
1564   case G2_locus_continuous: c = G2_locus_continuous; break;
1565 
1566   case Cinfinity_continuous: c = Cinfinity_continuous; break;
1567 
1568   case Gsmooth_continuous: c = Gsmooth_continuous; break;
1569   };
1570 
1571   return c;
1572 }
1573 
ParametricContinuity(int i)1574 ON::continuity ON::ParametricContinuity(int i)
1575 {
1576   // "erase" the locus setting.
1577   continuity c = unknown_continuity;
1578 
1579   switch(i)
1580   {
1581   case unknown_continuity: c = unknown_continuity; break;
1582   case C0_continuous: c = C0_continuous; break;
1583   case C1_continuous: c = C1_continuous; break;
1584   case C2_continuous: c = C2_continuous; break;
1585   case G1_continuous: c = G1_continuous; break;
1586   case G2_continuous: c = G2_continuous; break;
1587   case C0_locus_continuous: c = C0_continuous; break;
1588   case C1_locus_continuous: c = C1_continuous; break;
1589   case C2_locus_continuous: c = C2_continuous; break;
1590   case G1_locus_continuous: c = G1_continuous; break;
1591   case G2_locus_continuous: c = G2_continuous; break;
1592   case Cinfinity_continuous: c = Cinfinity_continuous; break;
1593   case Gsmooth_continuous: c = Gsmooth_continuous; break;
1594   };
1595 
1596   return c;
1597 }
1598 
1599 
PolylineContinuity(int i)1600 ON::continuity ON::PolylineContinuity(int i)
1601 {
1602   continuity c = unknown_continuity;
1603 
1604   switch(i)
1605   {
1606   case unknown_continuity: c = unknown_continuity; break;
1607   case C0_continuous: c = C0_continuous; break;
1608   case C1_continuous: c = C1_continuous; break;
1609   case C2_continuous: c = C1_continuous; break;
1610   case G1_continuous: c = G1_continuous; break;
1611   case G2_continuous: c = G1_continuous; break;
1612   case C0_locus_continuous: c = C0_locus_continuous; break;
1613   case C1_locus_continuous: c = C1_locus_continuous; break;
1614   case C2_locus_continuous: c = C1_locus_continuous; break;
1615   case G1_locus_continuous: c = G1_locus_continuous; break;
1616   case G2_locus_continuous: c = G1_locus_continuous; break;
1617   case Cinfinity_continuous: c = C1_continuous; break;
1618   case Gsmooth_continuous: c = G1_continuous; break;
1619   };
1620 
1621   return c;
1622 }
1623 
1624 
CurveStyle(int i)1625 ON::curve_style ON::CurveStyle(int i)
1626 {
1627   //convertintegertocurve_styleenum
1628   curve_style cs = unknown_curve_style;
1629   switch (i) {
1630   case line: cs = line; break;
1631   case circle: cs = circle; break;
1632   case ellipse: cs = ellipse; break;
1633   case parabola: cs = parabola; break;
1634   case hyperbola: cs = hyperbola; break;
1635   case planar_polyline: cs = planar_polyline; break;
1636   case polyline: cs = polyline; break;
1637   case planar_freeform_curve: cs = planar_freeform_curve; break;
1638   case freeform_curve: cs = freeform_curve; break;
1639   default: cs = unknown_curve_style; break;
1640   }
1641   return cs;
1642 }
1643 
SurfaceStyle(int i)1644 ON::surface_style ON::SurfaceStyle(int i)
1645 {
1646   //convertintegertosurface_styleenum
1647   surface_style ss = unknown_surface_style;
1648 
1649   switch (i) {
1650   case plane: ss = plane; break;
1651   case circular_cylinder: ss = circular_cylinder; break;
1652   case elliptical_cylinder: ss = elliptical_cylinder; break;
1653   case circular_cone: ss = circular_cone; break;
1654   case elliptical_cone: ss = elliptical_cone; break;
1655   case sphere: ss = sphere; break;
1656   case torus: ss = torus; break;
1657   case surface_of_revolution: ss = surface_of_revolution; break;
1658   case ruled_surface: ss = ruled_surface; break;
1659   case freeform_surface: ss = freeform_surface; break;
1660   default: ss = unknown_surface_style; break;
1661   }
1662   return ss;
1663 }
1664 
SortAlgorithm(int i)1665 ON::sort_algorithm ON::SortAlgorithm(int i)
1666 {
1667   sort_algorithm sa = ON::quick_sort;
1668 
1669   switch (i) {
1670   case ON::heap_sort: sa = ON::heap_sort; break;
1671   case ON::quick_sort: sa = ON::quick_sort; break;
1672   default: sa = ON::quick_sort; break;
1673   }
1674   return sa;
1675 }
1676 
Endian(int i)1677 ON::endian ON::Endian(int i)
1678 { // convert integer to endian enum
1679   endian e = (i<=0) ? little_endian : big_endian;
1680   return e;
1681 }
1682 
Endian()1683 ON::endian ON::Endian()
1684 {
1685   // returns endian-ness of cpu.
1686   union {
1687     int i;
1688     unsigned char b[sizeof(int)];
1689   } u;
1690   u.i = 1;
1691   return (u.b[0] == 1) ? little_endian : big_endian;
1692 }
1693 
ArchiveMode(int i)1694 ON::archive_mode ON::ArchiveMode(int i)
1695 {
1696   // convert integer to endian enum
1697   archive_mode a = read;
1698   switch(i) {
1699   case read:      a = read; break;
1700   case write:     a = write; break;
1701   case readwrite: a = readwrite; break;
1702   case read3dm:   a = read3dm; break;
1703   case write3dm:  a = write3dm; break;
1704   }
1705   return a;
1706 }
1707 
ViewProjection(int i)1708 ON::view_projection ON::ViewProjection(int i)
1709 {
1710   // convert integer to view_projection enum
1711   view_projection v = ON::unknown_view;
1712   switch(i)
1713   {
1714   case ON::parallel_view:          v = ON::parallel_view;          break;
1715   case ON::perspective_view:       v = ON::perspective_view;       break;
1716   }
1717   return v;
1718 }
1719 
IsParallelProjection(ON::view_projection proj)1720 bool ON::IsParallelProjection( ON::view_projection proj )
1721 {
1722   return ON::parallel_view == proj;
1723 }
1724 
IsPerspectiveProjection(ON::view_projection proj)1725 bool ON::IsPerspectiveProjection( ON::view_projection proj )
1726 {
1727   return ( ON::perspective_view == proj );
1728 }
1729 
CoordinateSystem(int i)1730 ON::coordinate_system ON::CoordinateSystem(int i)
1731 {
1732   // convert integer to coordinate_system enum
1733   coordinate_system cs = world_cs;
1734   switch(i) {
1735   case world_cs:  cs = world_cs; break;
1736   case camera_cs: cs = camera_cs; break;
1737   case clip_cs:   cs = clip_cs; break;
1738   case screen_cs: cs = screen_cs; break;
1739   }
1740   return cs;
1741 }
1742 
ExceptionType(int i)1743 ON::exception_type ON::ExceptionType(int i)
1744 {
1745   // convert integer to exception_type enum
1746   ON::exception_type e = unknown_exception;
1747   switch(i) {
1748   case out_of_memory:               e = out_of_memory; break;
1749   case unable_to_write_archive:     e = unable_to_write_archive; break;
1750   case unable_to_read_archive:      e = unable_to_read_archive; break;
1751   case unable_to_seek_archive:      e = unable_to_seek_archive; break;
1752   case unexpected_end_of_archive:   e = unexpected_end_of_archive; break;
1753   case unexpected_value_in_archive: e = unexpected_value_in_archive; break;
1754   };
1755   return e;
1756 }
1757 
LayerMode(int i)1758 ON::layer_mode ON::LayerMode(int i)
1759 {
1760   ON::layer_mode m = normal_layer;
1761 	switch(i)
1762   {
1763     case normal_layer:        m = normal_layer;       break;
1764     case hidden_layer:        m = hidden_layer;       break;
1765     case locked_layer:        m = locked_layer;       break;
1766   }
1767   return m;
1768 }
1769 
ObjectMode(int i)1770 ON::object_mode ON::ObjectMode(int i)
1771 {
1772   ON::object_mode m = normal_object;
1773 	switch(i)
1774   {
1775     case normal_object:  m = normal_object;  break;
1776     case hidden_object:  m = hidden_object;  break;
1777     case locked_object:  m = locked_object;  break;
1778     case idef_object:    m = idef_object;    break;
1779   }
1780   return m;
1781 }
1782 
ObjectColorSource(int i)1783 ON::object_color_source ON::ObjectColorSource(int i)
1784 {
1785   // convert integer to object_mode enum
1786   ON::object_color_source cs = color_from_layer;
1787   switch (i)
1788   {
1789   case color_from_layer: // use color assigned to layer
1790     cs = color_from_layer;
1791     break;
1792   case color_from_object: // use color assigned to object
1793     cs = color_from_object;
1794     break;
1795   case color_from_material:  // use diffuse render material color
1796     cs = color_from_material;
1797     break;
1798   case color_from_parent:
1799     cs = color_from_parent;
1800     break;
1801   }
1802   return cs;
1803 }
1804 
PlotColorSource(int i)1805 ON::plot_color_source ON::PlotColorSource(int i)
1806 {
1807   // convert integer to object_mode enum
1808   ON::plot_color_source cs = plot_color_from_layer;
1809   switch (i)
1810   {
1811   case plot_color_from_layer:
1812     cs = plot_color_from_layer;
1813     break;
1814   case plot_color_from_object:
1815     cs = plot_color_from_object;
1816     break;
1817   case plot_color_from_display:
1818     cs = plot_color_from_display;
1819     break;
1820   case plot_color_from_parent:
1821     cs = plot_color_from_parent;
1822     break;
1823   }
1824   return cs;
1825 }
1826 
PlotWeightSource(int pw)1827 ON::plot_weight_source ON::PlotWeightSource(int pw)
1828 {
1829   switch(pw)
1830   {
1831   case plot_weight_from_layer:  return plot_weight_from_layer;  break;
1832   case plot_weight_from_object: return plot_weight_from_object; break;
1833   case plot_weight_from_parent: return plot_weight_from_parent; break;
1834   }
1835   return plot_weight_from_layer;
1836 }
1837 
1838 
ObjectLinetypeSource(int i)1839 ON::object_linetype_source ON::ObjectLinetypeSource(int i)
1840 {
1841   // convert integer to object_mode enum
1842   ON::object_linetype_source ls = linetype_from_layer;
1843   switch (i) {
1844   case linetype_from_layer: // use linetype assigned to layer
1845     ls = linetype_from_layer;
1846     break;
1847   case linetype_from_object: // use linetype assigned to object
1848     ls = linetype_from_object;
1849     break;
1850   case linetype_from_parent:
1851     ls = linetype_from_parent;
1852     break;
1853   }
1854   return ls;
1855 }
1856 
ObjectMaterialSource(int i)1857 ON::object_material_source ON::ObjectMaterialSource(int i)
1858 {
1859   ON::object_material_source ms = material_from_layer;
1860   switch(i) {
1861   case material_from_layer:
1862     ms = material_from_layer;
1863     break;
1864   case material_from_object:
1865     ms = material_from_object;
1866     break;
1867   case material_from_parent:
1868     ms = material_from_parent;
1869     break;
1870   }
1871   return ms;
1872 }
1873 
LightStyle(int i)1874 ON::light_style ON::LightStyle(int i)
1875 {
1876   // convert integer to light_style enum
1877   light_style ls = unknown_light_style;
1878   switch(i)
1879   {
1880     case unknown_light_style: ls = unknown_light_style; break;
1881     //case view_directional_light: ls = view_directional_light; break;
1882     //case view_point_light: ls = view_point_light; break;
1883     //case view_spot_light: ls = view_spot_light; break;
1884     case camera_directional_light: ls = camera_directional_light; break;
1885     case camera_point_light: ls = camera_point_light; break;
1886     case camera_spot_light: ls = camera_spot_light; break;
1887     case world_directional_light: ls = world_directional_light; break;
1888     case world_point_light: ls = world_point_light; break;
1889     case world_spot_light: ls = world_spot_light; break;
1890     case ambient_light: ls = ambient_light; break;
1891     case world_linear_light: ls = world_linear_light; break;
1892     case world_rectangular_light: ls = world_rectangular_light; break;
1893   }
1894   return ls;
1895 }
1896 
CurvatureStyle(int i)1897 ON::curvature_style ON::CurvatureStyle(int i)
1898 {
1899   // convert integer to light_style enum
1900   ON::curvature_style cs = unknown_curvature_style;
1901   switch(i) {
1902   case gaussian_curvature:
1903     cs = gaussian_curvature;
1904     break;
1905   case mean_curvature:
1906     cs = mean_curvature;
1907     break;
1908   case min_curvature:
1909     // minimum unsigned radius of curvature
1910     cs = min_curvature;
1911     break;
1912   case max_curvature:
1913     // maximum unsigned radius of curvature
1914     cs = max_curvature;
1915     break;
1916   //case section_curvature_x:
1917     // unsigned normal curvature with respect to sections cut perp to world x axis
1918     //cs = section_curvature_x;
1919     //break;
1920   //case section_curvature_y:
1921     // unsigned normal curvature with respect to sections cut perp to world y axis
1922     //cs = section_curvature_y;
1923     //break;
1924   //case section_curvature_z:
1925     // unsigned normal curvature with respect to sections cut perp to world z axis
1926     //cs = section_curvature_z;
1927     //break;
1928   }
1929   return cs;
1930 }
1931 
1932 /*enum view_type // This is already in the header. I commented it out to see if it would compile and it does. John Croudy.
1933 {
1934   model_view_type     = 0,
1935   plot_page_view_type = 1,
1936   nested_view_type    = 2
1937 };*/
1938 
ViewType(int vt)1939 ON::view_type ON::ViewType(int vt)
1940 {
1941   switch(vt)
1942   {
1943   case model_view_type:  return (model_view_type);  break;
1944   case page_view_type:   return (page_view_type);   break;
1945   case nested_view_type: return (nested_view_type); break;
1946   }
1947 
1948   return (model_view_type);
1949 }
1950 
1951 
DisplayMode(int i)1952 ON::display_mode ON::DisplayMode(int i)
1953 {
1954   // convert integer to light_style enum
1955   ON::display_mode dm = default_display;
1956   switch(i) {
1957   case default_display:
1958     dm = default_display;
1959     break;
1960   case wireframe_display:
1961     dm = wireframe_display;
1962     break;
1963   case shaded_display:
1964     dm = shaded_display;
1965     break;
1966   case renderpreview_display:
1967     dm = renderpreview_display;
1968     break;
1969   }
1970   return dm;
1971 }
1972 
TextureMode(int i)1973 ON::texture_mode ON::TextureMode(int i)
1974 {
1975   // convert integer to texture_mode enum
1976   ON::texture_mode tm;
1977   switch (i) {
1978   case no_texture:
1979     tm = no_texture;
1980     break;
1981   case modulate_texture:
1982     tm = modulate_texture;
1983     break;
1984   case decal_texture:
1985     tm = decal_texture;
1986     break;
1987   default:
1988     tm = no_texture;
1989     break;
1990   }
1991   return tm;
1992 }
1993 
ObjectType(int i)1994 ON::object_type ON::ObjectType(int i)
1995 {
1996   // convert integer to object_type enum
1997   object_type ot = unknown_object_type;
1998   switch(i)
1999   {
2000   case unknown_object_type:  ot = unknown_object_type; break;
2001 
2002   case point_object:         ot = point_object; break;
2003   case pointset_object:      ot = pointset_object; break;
2004   case curve_object:         ot = curve_object; break;
2005   case surface_object:       ot = surface_object; break;
2006   case brep_object:          ot = brep_object; break;
2007   case mesh_object:          ot = mesh_object; break;
2008   case layer_object:         ot = layer_object; break;
2009   case material_object:      ot = material_object; break;
2010   case light_object:         ot = light_object; break;
2011   case annotation_object:    ot = annotation_object; break;
2012   case userdata_object:      ot = userdata_object; break;
2013   case instance_definition:  ot = instance_definition; break;
2014   case instance_reference:   ot = instance_reference; break;
2015   case text_dot:             ot = text_dot; break;
2016   case grip_object:          ot = grip_object; break;
2017   case detail_object:        ot = detail_object; break;
2018   case hatch_object:         ot = hatch_object; break;
2019   case morph_control_object: ot = morph_control_object; break;
2020   case loop_object:          ot = loop_object; break;
2021   case polysrf_filter:       ot = polysrf_filter; break;
2022   case edge_filter:          ot = edge_filter; break;
2023   case polyedge_filter:      ot = polyedge_filter; break;
2024   case meshvertex_object:    ot = meshvertex_object; break;
2025   case meshedge_object:      ot = meshedge_object; break;
2026   case meshface_object:      ot = meshface_object; break;
2027   case cage_object:          ot = cage_object; break;
2028   case phantom_object:       ot = phantom_object; break;
2029   case extrusion_object:     ot = extrusion_object; break;
2030 
2031   default: ot = unknown_object_type; break;
2032   }
2033 
2034   return ot;
2035 }
2036 
BitmapType(int i)2037 ON::bitmap_type ON::BitmapType(int i)
2038 {
2039   // convert integer to object_type enum
2040   bitmap_type bt = unknown_bitmap_type;
2041   switch(i) {
2042   case unknown_bitmap_type: bt = unknown_bitmap_type; break;
2043   case windows_bitmap:      bt = windows_bitmap; break;
2044   case opengl_bitmap:       bt = opengl_bitmap; break;
2045   case png_bitmap:          bt = png_bitmap; break;
2046   default: bt = unknown_bitmap_type; break;
2047   }
2048   return bt;
2049 }
2050 
ObjectDecoration(int i)2051 ON::object_decoration ON::ObjectDecoration(int i)
2052 {
2053   ON::object_decoration d;
2054   switch(i)
2055   {
2056   case no_object_decoration: d = no_object_decoration; break;
2057   case start_arrowhead:      d = start_arrowhead; break;
2058   case end_arrowhead:        d = end_arrowhead;   break;
2059   case both_arrowhead:       d = both_arrowhead;  break;
2060   default:                   d = no_object_decoration; break;
2061   }
2062   return d;
2063 }
2064 
2065 
OSnapMode(int i)2066 ON::osnap_mode ON::OSnapMode(int i)
2067 {
2068   ON::osnap_mode osm;
2069   switch((unsigned int)i)
2070   {
2071   case os_none:          osm = os_none; break;
2072   case os_near:          osm = os_near; break;
2073   case os_focus:         osm = os_focus; break;
2074   case os_center:        osm = os_center; break;
2075   case os_vertex:        osm = os_vertex; break;
2076   case os_knot:          osm = os_knot; break;
2077   case os_quadrant:      osm = os_quadrant; break;
2078   case os_midpoint:      osm = os_midpoint; break;
2079   case os_intersection:  osm = os_intersection; break;
2080   case os_end:           osm = os_end; break;
2081   case os_perpendicular: osm = os_perpendicular; break;
2082   case os_tangent:       osm = os_tangent; break;
2083   case os_point:         osm = os_point; break;
2084   case os_all_snaps:     osm = os_all_snaps; break;
2085   default:
2086     osm = os_none;
2087     break;
2088   };
2089   return osm;
2090 }
2091 
2092 
CubicLoftEndCondition(int i)2093 ON::cubic_loft_end_condition ON::CubicLoftEndCondition(int i)
2094 {
2095   ON::cubic_loft_end_condition e;
2096   switch(i)
2097   {
2098   case cubic_loft_ec_quadratic:
2099     e = ON::cubic_loft_ec_quadratic;
2100     break;
2101   case cubic_loft_ec_linear:
2102     e = ON::cubic_loft_ec_linear;
2103     break;
2104   case cubic_loft_ec_cubic:
2105     e = ON::cubic_loft_ec_cubic;
2106     break;
2107   case cubic_loft_ec_natural:
2108     e = ON::cubic_loft_ec_natural;
2109     break;
2110   case cubic_loft_ec_unit_tangent:
2111     e = ON::cubic_loft_ec_unit_tangent;
2112     break;
2113   case cubic_loft_ec_1st_derivative:
2114     e = ON::cubic_loft_ec_1st_derivative;
2115     break;
2116   case cubic_loft_ec_2nd_derivative:
2117     e = ON::cubic_loft_ec_2nd_derivative;
2118     break;
2119   case cubic_loft_ec_free_cv:
2120     e = ON::cubic_loft_ec_free_cv;
2121     break;
2122   default:
2123     ON_ERROR("ON::CubicLoftEndCondition(i) value of i is not valid.");
2124     e = ON::cubic_loft_ec_quadratic;
2125     break;
2126   }
2127   return e;
2128 }
2129 
2130 
MeshType(int i)2131 ON::mesh_type ON::MeshType(int i)
2132 {
2133   mesh_type mt = default_mesh;
2134   switch(i)
2135   {
2136   case default_mesh:  mt = default_mesh;  break;
2137   case render_mesh:   mt = render_mesh;   break;
2138   case analysis_mesh: mt = analysis_mesh; break;
2139   case preview_mesh:  mt = preview_mesh; break;
2140   case any_mesh:      mt = any_mesh;      break;
2141   default:            mt = default_mesh;  break;
2142   }
2143   return mt;
2144 }
2145 
2146 
AnnotationType(int i)2147 ON::eAnnotationType ON::AnnotationType(int i)
2148 {
2149   // convert integer to eAnnotationType enum
2150   eAnnotationType at = dtNothing;
2151   switch(i) {
2152   case dtNothing:
2153     at = dtNothing;
2154     break;
2155   case dtDimLinear:
2156     at = dtDimLinear;
2157     break;
2158   case dtDimAligned:
2159     at = dtDimAligned;
2160     break;
2161   case dtDimAngular:
2162     at = dtDimAngular;
2163     break;
2164   case dtDimDiameter:
2165     at = dtDimDiameter;
2166     break;
2167   case dtDimRadius:
2168     at = dtDimRadius;
2169     break;
2170   case dtLeader:
2171     at = dtLeader;
2172     break;
2173   case dtTextBlock:
2174     at = dtTextBlock;
2175     break;
2176   case dtDimOrdinate:
2177     at = dtDimOrdinate;
2178     break;
2179   }
2180   return at;
2181 }
2182 
TextDisplayMode(int i)2183 ON::eTextDisplayMode ON::TextDisplayMode( int i)
2184 {
2185   eTextDisplayMode m = dtAboveLine;
2186   switch( i)
2187   {
2188   case dtHorizontal:
2189     m = dtHorizontal;
2190     break;
2191   case dtAboveLine:
2192     m = dtAboveLine;
2193     break;
2194   case dtInLine:
2195     m = dtInLine;
2196     break;
2197   }
2198   return m;
2199 }
2200 
2201 
2202 // Windows code page support
2203 //   Only ON_SetStringConversionWindowsCodePage
2204 //   and ON_GetStringConversionWindowsCodePage
2205 //   should look at g_s__windows_code_page.
2206 static unsigned int g_s__windows_code_page = 0;
2207 
ON_SetStringConversionWindowsCodePage(unsigned int code_page)2208 unsigned int ON_SetStringConversionWindowsCodePage( unsigned int code_page )
2209 {
2210   unsigned int prev_cp = g_s__windows_code_page;
2211   g_s__windows_code_page = code_page;
2212   return prev_cp;
2213 }
2214 
ON_GetStringConversionWindowsCodePage()2215 unsigned int ON_GetStringConversionWindowsCodePage()
2216 {
2217   return g_s__windows_code_page;
2218 }
2219 
2220 /*
2221 ON_TimeLimit::ON_TimeLimit()
2222 {
2223   m_time_limit[0] = 0;
2224   m_time_limit[1] = 0;
2225 }
2226 
2227 ON_TimeLimit::ON_TimeLimit(ON__UINT64 time_limit_seconds)
2228 {
2229   SetTimeLimit(time_limit_seconds);
2230 }
2231 
2232 void ON_TimeLimit::SetTimeLimit(ON__UINT64 time_limit_seconds)
2233 {
2234   m_time_limit[0] = 0;
2235   m_time_limit[1] = 0;
2236   if ( time_limit_seconds > 0 )
2237   {
2238     // This is a crude implementation that works
2239     // unless clock() is close to wrapping around
2240     // or time_limit_seconds is unreasonably large.
2241     clock_t max_ticks = (clock_t)(time_limit_seconds*((double)CLOCKS_PER_SEC));
2242     if ( max_ticks > 0 )
2243     {
2244       clock_t now_clock = ::clock();
2245       clock_t max_clock = max_ticks + now_clock;
2246       time_t ::time()
2247       if ( now_clock < max_clock )
2248       {
2249         *((clock_t*)(&m_time_limit[0])) = max_clock;
2250       }
2251     }
2252   }
2253 }
2254 
2255 bool ON_TimeLimit::Continue() const
2256 {
2257   clock_t max_clock = *((clock_t*)&m_time_limit[0]);
2258   return ( max_clock <= 0 || ::clock() <= max_clock );
2259 }
2260 
2261 bool ON_TimeLimit::IsSet() const
2262 {
2263   clock_t max_clock = *((clock_t*)&m_time_limit[0]);
2264   return ( max_clock > 0 );
2265 }
2266 */
2267