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 "pcl/surface/3rdparty/opennurbs/opennurbs.h"
18
19 //////////////////////////////////////////////////////////////////////////////
20
ON_TextLog()21 ON_TextLog::ON_TextLog() : m_pFile(0), m_pString(0), m_indent(""), m_beginning_of_line(1), m_indent_size(0)
22 {
23 SetFloatFormat("%g");
24 SetDoubleFormat("%.17g");
25 }
26
ON_TextLog(FILE * pFile)27 ON_TextLog::ON_TextLog( FILE* pFile ) : m_pFile(pFile), m_pString(0), m_indent(""), m_beginning_of_line(1), m_indent_size(0)
28 {
29 SetFloatFormat("%g");
30 SetDoubleFormat("%.17g");
31 }
32
ON_TextLog(ON_wString & wstr)33 ON_TextLog::ON_TextLog( ON_wString& wstr ) : m_pFile(0), m_pString(&wstr), m_indent(""), m_beginning_of_line(1), m_indent_size(0)
34 {
35 SetFloatFormat("%g");
36 SetDoubleFormat("%.17g");
37 }
38
~ON_TextLog()39 ON_TextLog::~ON_TextLog()
40 {
41 }
42
SetDoubleFormat(const char * sFormat)43 void ON_TextLog::SetDoubleFormat(const char* sFormat)
44 {
45 m_double_format = sFormat;
46 m_double2_format = m_double_format + ", " + m_double_format;
47 m_double3_format = m_double2_format + ", " + m_double_format;
48 m_double4_format = m_double3_format + ", " + m_double_format;
49 }
50
GetDoubleFormat(ON_String & s) const51 void ON_TextLog::GetDoubleFormat( ON_String& s ) const
52 {
53 s = m_double_format;
54 }
55
SetFloatFormat(const char * sFormat)56 void ON_TextLog::SetFloatFormat(const char* sFormat)
57 {
58 m_float_format = sFormat;
59 m_float2_format = m_float_format + ", " + m_float_format;
60 m_float3_format = m_float2_format + ", " + m_float_format;
61 m_float4_format = m_float3_format + ", " + m_float_format;
62 }
63
GetFloatFormat(ON_String & s) const64 void ON_TextLog::GetFloatFormat( ON_String& s ) const
65 {
66 s = m_float_format;
67 }
68
PushIndent()69 void ON_TextLog::PushIndent()
70 {
71 if ( m_indent_size > 0 ) {
72 int i;
73 for ( i = 0; i < m_indent_size; i++ ) {
74 m_indent += ' ';
75 }
76 }
77 else {
78 m_indent += "\t";
79 }
80 }
81
PopIndent()82 void ON_TextLog::PopIndent()
83 {
84 const int length = m_indent.Length();
85 const int indent_lenth = m_indent_size>0 ? m_indent_size : 1;
86 if ( length >= indent_lenth ) {
87 m_indent.SetLength(length-indent_lenth);
88 }
89 else {
90 m_indent.Destroy();
91 }
92 }
93
IndentSize() const94 int ON_TextLog::IndentSize() const
95 {
96 // 0: one tab per indent
97 // >0: number of spaces per indent
98 return m_indent_size;
99 }
100
SetIndentSize(int s)101 void ON_TextLog::SetIndentSize(int s)
102 {
103 m_indent_size = (s>0) ? s : 0;
104 }
105
Print(const char * format,...)106 void ON_TextLog::Print( const char* format, ... )
107 {
108 // format message and append it to the log
109 const int MAX_MSG_LENGTH = 2047;
110 char s[MAX_MSG_LENGTH+1];
111 va_list args;
112
113 s[0] = 0;
114 if (format)
115 {
116 va_start(args, format);
117 on_vsnprintf( s, MAX_MSG_LENGTH-1, format, args);
118 va_end(args);
119 s[MAX_MSG_LENGTH] = 0;
120 }
121 if ( *s )
122 {
123 char* s0 = s;
124 char* s1 = s;
125 for ( s1 = s0; *s1; s1++) {
126 if ( *s1 == '\n' ) {
127 *s1 = 0;
128 if ( m_beginning_of_line && m_indent && m_indent[0] )
129 AppendText( m_indent );
130 if (*s0)
131 AppendText(s0);
132 AppendText("\n");
133 m_beginning_of_line = 1;
134 s0 = s1+1;
135 }
136 }
137 if (*s0) {
138 if ( m_beginning_of_line && m_indent && m_indent[0] )
139 AppendText( m_indent );
140 AppendText(s0);
141 m_beginning_of_line = 0;
142 }
143 }
144 }
145
Print(const wchar_t * wformat,...)146 void ON_TextLog::Print( const wchar_t* wformat, ... )
147 {
148 // format message and append it to the log
149 const int MAX_MSG_LENGTH = 2047;
150 wchar_t s[MAX_MSG_LENGTH+1];
151 va_list args;
152
153 s[0] = 0;
154 if (wformat)
155 {
156 va_start(args, wformat);
157 on_vsnwprintf( s, MAX_MSG_LENGTH-1, wformat, args);
158 va_end(args);
159 s[MAX_MSG_LENGTH] = 0;
160 }
161 if ( *s )
162 {
163 wchar_t* s0 = s;
164 wchar_t* s1 = s;
165 for ( s1 = s0; *s1; s1++) {
166 if ( *s1 == '\n' ) {
167 *s1 = 0;
168 if ( m_beginning_of_line && m_indent && m_indent[0] )
169 AppendText( m_indent );
170 if (*s0)
171 AppendText(s0);
172 AppendText("\n");
173 m_beginning_of_line = 1;
174 s0 = s1+1;
175 }
176 }
177 if (*s0) {
178 if ( m_beginning_of_line && m_indent && m_indent[0] )
179 AppendText( m_indent );
180 AppendText(s0);
181 m_beginning_of_line = 0;
182 }
183 }
184 }
185
186
AppendText(const char * s)187 void ON_TextLog::AppendText( const char* s )
188 {
189 // This is a virtual function
190 if ( s && *s )
191 {
192 if ( m_pString )
193 {
194 (*m_pString) += s;
195 }
196 else if ( m_pFile )
197 {
198 fputs( s, m_pFile );
199 }
200 else
201 {
202 printf("%s",s);
203 }
204 }
205 }
206
AppendText(const wchar_t * s)207 void ON_TextLog::AppendText( const wchar_t* s )
208 {
209 // This is a virtual function
210 if ( m_pString )
211 {
212 (*m_pString) += s;
213 }
214 else
215 {
216 // If sizeof(wchar_t) = 2, str = s performs
217 // performs UTF-16 to UTF-8 conversion.
218 // If sizeof(wchar_t) = 4, str = s performs
219 // performs UTF-32 to UTF-8 conversion.
220 ON_String str = s;
221 AppendText(str.Array());
222 }
223 }
224
Print(float x)225 void ON_TextLog::Print( float x )
226 {
227 if ( ON_UNSET_FLOAT == x )
228 Print("ON_UNSET_FLOAT");
229 else
230 Print(m_float_format,x);
231 }
232
Print(double x)233 void ON_TextLog::Print( double x )
234 {
235 if ( ON_UNSET_VALUE == x )
236 Print("ON_UNSET_VALUE");
237 else
238 Print(m_double_format,x);
239 }
240
Print(const ON_2dPoint & p)241 void ON_TextLog::Print( const ON_2dPoint& p )
242 {
243 Print("(");
244 Print(m_double2_format, p.x, p.y);
245 Print(")");
246 }
247
Print(const ON_3dPoint & p)248 void ON_TextLog::Print( const ON_3dPoint& p )
249 {
250 Print("(");
251 if ( ON_3dPoint::UnsetPoint == p )
252 Print("UnsetPoint");
253 else
254 Print(m_double3_format, p.x, p.y, p.z );
255 Print(")");
256 }
257
Print(const ON_4dPoint & p)258 void ON_TextLog::Print( const ON_4dPoint& p )
259 {
260 Print("[");
261 Print(m_double4_format, p.x, p.y, p.z, p.w );
262 Print("]");
263 }
264
Print(const ON_2dVector & p)265 void ON_TextLog::Print( const ON_2dVector& p )
266 {
267 Print("<");
268 Print(m_double2_format, p.x, p.y);
269 Print(">");
270 }
271
Print(const ON_3dVector & p)272 void ON_TextLog::Print( const ON_3dVector& p )
273 {
274 Print("<");
275 if ( ON_3dVector::UnsetVector == p )
276 Print("UnsetVector");
277 else
278 Print(m_double3_format, p.x, p.y, p.z);
279 Print(">");
280 }
281
Print(const ON_Xform & xform)282 void ON_TextLog::Print( const ON_Xform& xform )
283 {
284 if ( xform.IsIdentity() )
285 {
286 Print("identity transformation\n");
287 }
288 else if ( xform.IsZero() )
289 {
290 Print("zero transformation\n");
291 }
292 else
293 {
294 Print(m_double4_format,xform[0][0],xform[0][1],xform[0][2],xform[0][3]);
295 Print("\n");
296 Print(m_double4_format,xform[1][0],xform[1][1],xform[1][2],xform[1][3]);
297 Print("\n");
298 Print(m_double4_format,xform[2][0],xform[2][1],xform[2][2],xform[2][3]);
299 Print("\n");
300 Print(m_double4_format,xform[3][0],xform[3][1],xform[3][2],xform[3][3]);
301 Print("\n");
302 }
303 }
304
Print(const ON_UUID & uuid)305 void ON_TextLog::Print( const ON_UUID& uuid )
306 {
307 Print("%08X-%04X-%04x-%02X%02X-%02X%02X%02X%02X%02X%02X",
308 uuid.Data1, uuid.Data2, uuid.Data3,
309 uuid.Data4[0], uuid.Data4[1], uuid.Data4[2], uuid.Data4[3],
310 uuid.Data4[4], uuid.Data4[5], uuid.Data4[6], uuid.Data4[7]
311 );
312 }
313
Print(const ON_COMPONENT_INDEX & ci)314 void ON_TextLog::Print( const ON_COMPONENT_INDEX& ci )
315 {
316 switch( ci.m_type )
317 {
318 case ON_COMPONENT_INDEX::invalid_type:
319 Print("invalid_type(%d)",ci.m_index);
320 break;
321 case ON_COMPONENT_INDEX::brep_vertex:
322 Print("brep_vertex(%d)",ci.m_index);
323 break;
324 case ON_COMPONENT_INDEX::brep_edge:
325 Print("brep_edge(%d)",ci.m_index);
326 break;
327 case ON_COMPONENT_INDEX::brep_face:
328 Print("brep_face(%d)",ci.m_index);
329 break;
330 case ON_COMPONENT_INDEX::brep_trim:
331 Print("brep_trim(%d)",ci.m_index);
332 break;
333 case ON_COMPONENT_INDEX::brep_loop:
334 Print("brep_loop(%d)",ci.m_index);
335 break;
336 case ON_COMPONENT_INDEX::mesh_vertex:
337 Print("mesh_vertex(%d)",ci.m_index);
338 break;
339 case ON_COMPONENT_INDEX::meshtop_vertex:
340 Print("meshtop_vertex(%d)",ci.m_index);
341 break;
342 case ON_COMPONENT_INDEX::meshtop_edge:
343 Print("meshtop_edge(%d)",ci.m_index);
344 break;
345 case ON_COMPONENT_INDEX::mesh_face:
346 Print("mesh_face(%d)",ci.m_index);
347 break;
348 case ON_COMPONENT_INDEX::idef_part:
349 Print("idef_part(%d)",ci.m_index);
350 break;
351 case ON_COMPONENT_INDEX::polycurve_segment:
352 Print("polycurve_segment(%d)",ci.m_index);
353 break;
354 case ON_COMPONENT_INDEX::pointcloud_point:
355 Print("pointcloud_point(%d)",ci.m_index);
356 break;
357 case ON_COMPONENT_INDEX::group_member:
358 Print("group_member(%d)",ci.m_index);
359 break;
360 case ON_COMPONENT_INDEX::no_type:
361 Print("no_type(%d)",ci.m_index);
362 break;
363 default:
364 Print("ON_COMPONENT_INDEX(%d,%d)",ci.m_type,ci.m_index);
365 break;
366 }
367 }
368
Print(const ON_wString & string)369 void ON_TextLog::Print( const ON_wString& string )
370 {
371 const wchar_t* s = string;
372 if ( s && *s )
373 AppendText(s);
374 }
375
Print(const ON_String & string)376 void ON_TextLog::Print( const ON_String& string )
377 {
378 const char* s = string;
379 if ( s && *s )
380 AppendText(s);
381 }
382
PrintString(const char * s)383 void ON_TextLog::PrintString( const char* s )
384 {
385 if ( s && *s )
386 AppendText(s);
387 }
388
PrintNewLine()389 void ON_TextLog::PrintNewLine()
390 {
391 Print("\n");
392 }
393
394
PrintString(const wchar_t * s)395 void ON_TextLog::PrintString( const wchar_t* s )
396 {
397 if ( s && *s )
398 AppendText(s);
399 }
400
PrintRGB(const ON_Color & color)401 void ON_TextLog::PrintRGB( const ON_Color& color )
402 {
403 if ( color == ON_UNSET_COLOR )
404 Print("ON_UNSET_COLOR");
405 else
406 Print("%d %d %d",color.Red(),color.Green(),color.Blue());
407 }
408
PrintTime(const struct tm & t)409 void ON_TextLog::PrintTime( const struct tm& t )
410 {
411 if ( 0 != t.tm_sec
412 || 0 != t.tm_min
413 || 0 != t.tm_hour
414 || 0 != t.tm_mday
415 || 0 != t.tm_mon
416 || 0 != t.tm_year
417 || 0 != t.tm_wday
418 )
419 {
420 const char* sDayName[8] = {"Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday","<invalid day>"};
421 const char* sMonName[13] = {"January","February","March","April","May","June",
422 "July","August","September","October","November","December","<invalid month>"};
423 int wday = t.tm_wday;
424 if ( wday < 0 || wday > 6 )
425 wday = 7;
426 int mon = t.tm_mon;
427 if ( mon < 0 || mon > 11 )
428 mon = 12;
429
430 Print("%s %s %02d %02d:%02d:%02d %4d",
431 sDayName[wday],
432 sMonName[mon],
433 t.tm_mday,
434 t.tm_hour,
435 t.tm_min,
436 t.tm_sec,
437 t.tm_year+1900);
438 }
439 }
440
441
PrintPointList(int dim,int is_rat,int count,int stride,const double * P,const char * sPreamble)442 void ON_TextLog::PrintPointList( int dim, int is_rat, int count, int stride, const double* P,
443 const char* sPreamble )
444 {
445 double w, x;
446 int i, j, cvdim;
447
448 ON_String preamble = "";
449 if ( sPreamble && *sPreamble )
450 preamble += sPreamble;
451 cvdim = (is_rat) ? dim+1 : dim;
452
453 if ( count == 0 ) {
454 Print( "%sEMPTY point list\n", preamble.Array() );
455 }
456 else if ( !P ) {
457 Print( "%sNULL point list\n", preamble.Array() );
458 }
459
460 for ( i = 0; i < count; i++ ) {
461 Print( "%s[%2d] %c", preamble.Array(), i, (is_rat) ? '[' : '(' );
462 Print( m_double_format, P[0] );
463 for ( j = 1; j < cvdim; j++ ) {
464 Print( ", ");
465 Print(m_double_format, P[j] );
466 }
467 Print("%c", (is_rat) ? ']' : ')' );
468 if ( is_rat )
469 {
470 w = P[dim];
471 if ( w != 0.0 )
472 {
473 // print euclidean coordinates
474 w = 1.0/w;
475 x = w*P[0];
476 Print( " = (");
477 Print( m_double_format, x );
478 for ( j = 1; j < dim; j++ )
479 {
480 x = w*P[j];
481 Print( ", ");
482 Print( m_double_format, x );
483 }
484 Print(")");
485 }
486 }
487 Print("\n");
488 P += stride;
489 }
490 }
491
PrintPointGrid(int dim,int is_rat,int point_count0,int point_count1,int point_stride0,int point_stride1,const double * P,const char * sPreamble)492 void ON_TextLog::PrintPointGrid( int dim, int is_rat,
493 int point_count0, int point_count1,
494 int point_stride0, int point_stride1,
495 const double* P,
496 const char* sPreamble )
497 {
498 char s[1024];
499 int i;
500 if (!sPreamble || !sPreamble[0])
501 sPreamble = "point";
502 for ( i = 0; i < point_count0; i++ ) {
503 sprintf( s, "%s[%2d]", sPreamble, i );
504 PrintPointList( dim, is_rat, point_count1, point_stride1, P + i*point_stride0, s );
505 }
506 }
507
PrintKnotVector(int order,int cv_count,const double * knot)508 void ON_TextLog::PrintKnotVector( int order, int cv_count, const double* knot )
509 {
510 int i, i0, mult, knot_count;
511 if ( !knot )
512 Print("NULL knot vector\n");
513 if ( order < 2 )
514 Print("knot vector order < 2\n");
515 if ( cv_count < order )
516 Print("knot vector cv_count < order\n");
517 if ( order >= 2 && cv_count >= order && knot ) {
518 knot_count = ON_KnotCount( order, cv_count );
519 i = i0 = 0;
520 Print("index value mult delta\n");
521 while ( i < knot_count ) {
522 mult = 1;
523 while ( i+mult < knot_count && knot[i] == knot[i+mult] )
524 mult++;
525 if ( i == 0 ) {
526 Print( "%5d %23.17g %4d\n", i, knot[i], mult );
527 }
528 else {
529 Print( "%5d %23.17g %4d %10.4g\n", i, knot[i], mult, knot[i]-knot[i0] );
530 }
531 i0 = i;
532 i += mult;
533 }
534 }
535 }
536
Print(const ON_3dPointArray & a,const char * sPreamble)537 void ON_TextLog::Print( const ON_3dPointArray& a, const char* sPreamble )
538 {
539 const double* p = (a.Array() ? &a.Array()[0].x : NULL );
540 PrintPointList( 3, false, a.Count(), 3, p, sPreamble );
541 }
542
Print(const ON_Matrix & M,const char * sPreamble,int precision)543 void ON_TextLog::Print( const ON_Matrix& M, const char* sPreamble, int precision )
544 {
545 double x;
546 char digit[10] = {'0','1','2','3','4','5','6','7','8','9'};
547 char* sRow;
548 char* sIJ;
549 int xi, row_count, column_count, row_index, column_index;
550
551 row_count = M.RowCount();
552 column_count = M.ColCount();
553
554 sRow = (char*)alloca( (5*column_count + 2 + 64)*sizeof(*sRow) );
555
556 if ( !sPreamble )
557 sPreamble = "Matrix";
558
559 Print("%s (%d rows %d columns)\n",sPreamble,row_count,column_count);
560 for ( row_index = 0; row_index < row_count; row_index++ ) {
561 sIJ = sRow;
562 Print("%5d:",row_index);
563 if ( precision > 3 ) {
564 for ( column_index = 0; column_index < column_count; column_index++ ) {
565 x = M.m[row_index][column_index];
566 Print( " %8f",x);
567 }
568 Print("\n");
569 }
570 else {
571 for ( column_index = 0; column_index < column_count; column_index++ ) {
572 x = M.m[row_index][column_index];
573 if ( x == 0.0 ) {
574 strcpy( sIJ, " 0 " );
575 sIJ += 4;
576 }
577 else {
578 *sIJ++ = ' ';
579 *sIJ++ = ( x >0.0 ) ? '+' : '-';
580 x = fabs( x );
581 if ( x >= 10.0 ) {
582 *sIJ++ = '*';
583 *sIJ++ = ' ';
584 *sIJ++ = ' ';
585 }
586 else if ( x <= ON_SQRT_EPSILON) {
587 *sIJ++ = '0';
588 *sIJ++ = ' ';
589 *sIJ++ = ' ';
590 }
591 else if ( x < 0.1) {
592 *sIJ++ = '~';
593 *sIJ++ = ' ';
594 *sIJ++ = ' ';
595 }
596 else if ( x < .95 ) {
597 *sIJ++ = '.';
598 xi = (int)floor(x*10.0);
599 if ( xi > 9 )
600 xi = 9;
601 else if (xi < 1)
602 xi = 1;
603 *sIJ++ = digit[xi];
604 *sIJ++ = '~';
605 }
606 else {
607 xi = (int)floor(x);
608 if ( xi < 1 )
609 xi = 1;
610 else if (xi > 9)
611 xi = 9;
612 *sIJ++ = digit[xi];
613 if ( x == floor(x) ) {
614 *sIJ++ = ' ';
615 *sIJ++ = ' ';
616 }
617 else {
618 *sIJ++ = '.';
619 *sIJ++ = '~';
620 }
621 }
622 }
623 }
624 *sIJ = 0;
625 Print("%s\n",sRow);
626 }
627 }
628 }
629
operator <<(const char * s)630 ON_TextLog& ON_TextLog::operator<<(const char* s)
631 {
632 Print( "%s", s );
633 return *this;
634 }
635
operator <<(char c)636 ON_TextLog& ON_TextLog::operator<<(char c)
637 {
638 Print( "%c", c );
639 return *this;
640 }
641
operator <<(short i)642 ON_TextLog& ON_TextLog::operator<<(short i)
643 {
644 int ii = (int)i;
645 Print("%d", ii );
646 return *this;
647 }
648
operator <<(int i)649 ON_TextLog& ON_TextLog::operator<<(int i)
650 {
651 Print("%d",i);
652 return *this;
653 }
654
operator <<(float x)655 ON_TextLog& ON_TextLog::operator<<(float x)
656 {
657 Print(m_float_format,x);
658 return *this;
659 }
660
operator <<(double x)661 ON_TextLog& ON_TextLog::operator<<(double x)
662 {
663 Print(m_double_format,x);
664 return *this;
665 }
666
operator <<(const ON_2dPoint & p)667 ON_TextLog& ON_TextLog::operator<<( const ON_2dPoint& p )
668 {
669 Print(p);
670 return *this;
671 }
672
operator <<(const ON_3dPoint & p)673 ON_TextLog& ON_TextLog::operator<<( const ON_3dPoint& p )
674 {
675 Print(p);
676 return *this;
677 }
678
operator <<(const ON_4dPoint & p)679 ON_TextLog& ON_TextLog::operator<<( const ON_4dPoint& p )
680 {
681 Print(p);
682 return *this;
683 }
684
operator <<(const ON_2dVector & p)685 ON_TextLog& ON_TextLog::operator<<( const ON_2dVector& p )
686 {
687 Print(p);
688 return *this;
689 }
690
operator <<(const ON_3dVector & p)691 ON_TextLog& ON_TextLog::operator<<( const ON_3dVector& p )
692 {
693 Print(p);
694 return *this;
695 }
696
operator <<(const ON_Xform & xform)697 ON_TextLog& ON_TextLog::operator<<( const ON_Xform& xform )
698 {
699 Print(xform);
700 return *this;
701 }
702
PrintWrappedText(const char * s,int line_length)703 void ON_TextLog::PrintWrappedText( const char* s, int line_length )
704 {
705 ON_wString ws = s;
706 PrintWrappedText(ws,line_length);
707 }
708
wsncpy(wchar_t * dst,const wchar_t * src,int n)709 static void wsncpy(wchar_t* dst, const wchar_t* src, int n)
710 {
711 // can't use _wcsncpy() because this has to compile on UNIX boxes
712 if ( dst && n > 0 ) {
713 if ( src ) {
714 while ( 0 != (*dst++ = *src++) && n-- > 0 );
715 }
716 else
717 *dst = 0;
718 }
719 }
720
721
PrintWrappedText(const wchar_t * s,int line_length)722 void ON_TextLog::PrintWrappedText( const wchar_t* s, int line_length )
723 {
724 ON_Workspace ws;
725 if ( s && *s && line_length > 0 ) {
726 const int max_line_length = line_length+255;
727 wchar_t* sLine = (wchar_t*)ws.GetMemory((max_line_length+1)*sizeof(*sLine));
728 const int wrap_length = line_length;
729 int i = 0;
730 int i1 = 0;
731 int isp = 0;
732 ON_BOOL32 bPrintLine = false;
733 while ( s[i] ) {
734 i1 = i;
735 if ( s[i] == 10 || s[i] == 13 ) {
736 // hard break at CR or LF
737 i++;
738 if ( s[i] == 10 && s[i-1] == 13 ) {
739 // it's a CR+LF hard end of line - skip LF too
740 i++;
741 }
742 bPrintLine = true;
743 }
744 else if ( i && s[i] == 32 ) {
745 if ( !isp ) {
746 isp = i++;
747 }
748 if ( i < wrap_length ) {
749 isp = i++;
750 }
751 else {
752 bPrintLine = true;
753 if ( isp ) {
754 i1 = i = isp;
755 while ( s[i] == 32 )
756 i++;
757 }
758 else {
759 i++;
760 }
761 }
762 }
763 else {
764 i++;
765 }
766 if ( bPrintLine ) {
767 if ( i1 >= max_line_length )
768 i1 = max_line_length-1;
769 if ( i1 > 0 ) {
770 wsncpy( sLine, s, i1 );
771 sLine[i1] = 0;
772 Print( "%ls\n", sLine );
773 }
774 else {
775 Print("\n");
776 }
777
778 s += i;
779 i = i1 = isp = 0;
780 bPrintLine = false;
781 }
782 }
783 if ( s[0] ) {
784 Print( "%ls", s );
785 }
786 }
787 }
788
789