1 /*******************************************************************
2 *
3 * DESCRIPTION: string.cpp
4 *
5 * AUTHOR: David Malcolm
6 *
7 * HISTORY: Created ages ago
8 *
9 *******************************************************************/
10
11 /* Includes ********************************************************/
12
13 #include "3dc.h"
14 #include "scstring.hpp"
15
16 #include "strutil.h"
17 #include "indexfnt.hpp"
18
19 #if TrackReferenceCounted
20 #include "dcontext.hpp"
21 #endif
22
23 #define UseLocalAssert Yes
24 #include "ourasert.h"
25
26 /* Version settings ************************************************/
27 #define LogStringTables No
28
29 /* Constants *******************************************************/
30 #define MAX_BYTES_IN_NUMERIC_STRING (100)
31
32 /* Macros **********************************************************/
33
34 /* Imported function prototypes ************************************/
35
36 /* Imported data ***************************************************/
37
38 #include "teletype.hpp"
39
40 /* Exported globals ************************************************/
41 /*static*/ SCString* SCString :: pFirst = NULL;
42
43 /* Internal type definitions ***************************************/
44
45 /* Internal function prototypes ************************************/
46
47 /* Internal globals ************************************************/
48
49 /* Exported function definitions ***********************************/
50 // class SCString
51 // public:
52 #if TrackReferenceCounted
DumpIDForReferenceDump(R_DumpContext & theContext) const53 void SCString :: DumpIDForReferenceDump(R_DumpContext& theContext) const
54 {
55 theContext . dprintf("SCString \"%s\" refs remainining=%i\n",pProjCh_Val,CheckRef());
56 }
57 #endif
58
pProjCh(void) const59 ProjChar* SCString :: pProjCh(void) const
60 {
61 /* PRECONDITION */
62 {
63 GLOBALASSERT( pProjCh_Val );
64 }
65
66 /* CODE */
67 {
68 return pProjCh_Val;
69 }
70 }
71
72
SCString(const ProjChar * pProjCh_Init)73 SCString :: SCString
74 (
75 const ProjChar* pProjCh_Init
76 )
77 {
78 /* PRECONDITION */
79 {
80 GLOBALASSERT( pProjCh_Init );
81 }
82
83 /* CODE */
84 {
85 AllocatedSize = (size_t) STRUTIL_SC_NumBytes
86 (
87 pProjCh_Init
88 );
89
90 pProjCh_Val = new ProjChar[ AllocatedSize ];
91 GLOBALASSERT( pProjCh_Val );
92
93 STRUTIL_SC_StrCpy
94 (
95 pProjCh_Val,
96 pProjCh_Init
97 );
98
99 NumberOfCharacters = ( AllocatedSize / sizeof(ProjChar ) ) - 1;
100 // doesn't include NULL terminator
101
102 FontIndex i = IndexedFonts_MAX_NUMBER_OF_FONTS;
103
104 while ( i>0 )
105 {
106 i = (FontIndex)(i-1);
107
108 IndexedFont* pFont = IndexedFont :: GetFont( i );
109
110 if ( pFont )
111 {
112 R2Size[ i ] = pFont -> CalcSize
113 (
114 pProjCh_Val
115 );
116
117 bCanRender[ i ] = pFont -> bCanRenderFully
118 (
119 pProjCh_Val
120 );
121 }
122 else
123 {
124 R2Size[ i ] = r2size(0,0);
125
126 bCanRender[ i ] = No;
127 }
128 }
129
130 // Insert at head of list:
131 {
132 if ( pFirst )
133 {
134 pFirst -> pPrv = this;
135 }
136
137 pNxt = pFirst;
138 pPrv = NULL;
139
140 pFirst = this;
141 }
142 }
143 }
144
SCString(signed int Number)145 SCString :: SCString
146 (
147 signed int Number
148 )
149 {
150 // forms a new string object that describes the number passed
151 // standard decimal representation
152
153 /* PRECONDITION */
154 {
155 }
156
157 /* CODE */
158 {
159 ProjChar pProjCh_Init[ MAX_BYTES_IN_NUMERIC_STRING ];
160
161 sprintf
162 (
163 pProjCh_Init,
164 "%i",
165 (int)Number
166 );
167
168 #if 0
169 LOCALISEME();
170 #endif
171
172 AllocatedSize = (size_t) STRUTIL_SC_NumBytes
173 (
174 pProjCh_Init
175 );
176
177 pProjCh_Val = new ProjChar[ AllocatedSize ];
178 GLOBALASSERT( pProjCh_Val );
179 // this is always "owned" by the String
180
181 STRUTIL_SC_StrCpy
182 (
183 pProjCh_Val,
184 pProjCh_Init
185 );
186
187 NumberOfCharacters = ( AllocatedSize / sizeof(ProjChar ) ) - 1;
188 // doesn't include NULL terminator
189
190 FontIndex i = IndexedFonts_MAX_NUMBER_OF_FONTS;
191
192 while ( i>0 )
193 {
194 i = (FontIndex)(i-1);
195
196 IndexedFont* pFont = IndexedFont :: GetFont( i );
197
198 if ( pFont )
199 {
200 R2Size[ i ] = pFont -> CalcSize
201 (
202 pProjCh_Val
203 );
204
205 bCanRender[ i ] = pFont -> bCanRenderFully
206 (
207 pProjCh_Val
208 );
209 }
210 else
211 {
212 R2Size[ i ] = r2size(0,0);
213
214 bCanRender[ i ] = No;
215 }
216 }
217
218 // Insert at head of list:
219 {
220 if ( pFirst )
221 {
222 pFirst -> pPrv = this;
223 }
224
225 pNxt = pFirst;
226 pPrv = NULL;
227
228 pFirst = this;
229 }
230
231 }
232 }
233
SCString(unsigned int Number)234 SCString :: SCString
235 (
236 unsigned int Number
237 )
238 {
239 // forms a new string object that describes the number passed
240 // standard decimal representation
241
242 /* PRECONDITION */
243 {
244 }
245
246 /* CODE */
247 {
248 ProjChar pProjCh_Init[ MAX_BYTES_IN_NUMERIC_STRING ];
249
250 sprintf
251 (
252 pProjCh_Init,
253 "%u",
254 Number
255 );
256
257 #if 0
258 LOCALISEME();
259 #endif
260
261 AllocatedSize = (size_t) STRUTIL_SC_NumBytes
262 (
263 pProjCh_Init
264 );
265
266 pProjCh_Val = new ProjChar[ AllocatedSize ];
267 GLOBALASSERT( pProjCh_Val );
268 // this is always "owned" by the String
269
270 STRUTIL_SC_StrCpy
271 (
272 pProjCh_Val,
273 pProjCh_Init
274 );
275
276 NumberOfCharacters = ( AllocatedSize / sizeof(ProjChar ) ) - 1;
277 // doesn't include NULL terminator
278
279 FontIndex i = IndexedFonts_MAX_NUMBER_OF_FONTS;
280
281 while ( i>0 )
282 {
283 i = (FontIndex)(i-1);
284
285 IndexedFont* pFont = IndexedFont :: GetFont( i );
286
287 if ( pFont )
288 {
289 R2Size[ i ] = pFont -> CalcSize
290 (
291 pProjCh_Val
292 );
293
294 bCanRender[ i ] = pFont -> bCanRenderFully
295 (
296 pProjCh_Val
297 );
298 }
299 else
300 {
301 R2Size[ i ] = r2size(0,0);
302
303 bCanRender[ i ] = No;
304 }
305 }
306
307 // Insert at head of list:
308 {
309 if ( pFirst )
310 {
311 pFirst -> pPrv = this;
312 }
313
314 pNxt = pFirst;
315 pPrv = NULL;
316
317 pFirst = this;
318 }
319
320 }
321 }
322
SCString(float Number)323 SCString :: SCString
324 (
325 float Number
326 )
327 {
328 /* PRECONDITION */
329 {
330 }
331
332 /* CODE */
333 {
334 ProjChar pProjCh_Init[ MAX_BYTES_IN_NUMERIC_STRING ];
335
336 sprintf
337 (
338 pProjCh_Init,
339 "%6f",
340 Number
341 );
342
343 #if 0
344 LOCALISEME();
345 #endif
346
347 AllocatedSize = (size_t) STRUTIL_SC_NumBytes
348 (
349 pProjCh_Init
350 );
351
352 pProjCh_Val = new ProjChar[ AllocatedSize ];
353 GLOBALASSERT( pProjCh_Val );
354 // this is always "owned" by the String
355
356 STRUTIL_SC_StrCpy
357 (
358 pProjCh_Val,
359 pProjCh_Init
360 );
361
362 NumberOfCharacters = ( AllocatedSize / sizeof(ProjChar ) ) - 1;
363 // doesn't include NULL terminator
364
365 FontIndex i = IndexedFonts_MAX_NUMBER_OF_FONTS;
366
367 while ( i>0 )
368 {
369 i = (FontIndex)(i-1);
370
371 IndexedFont* pFont = IndexedFont :: GetFont( i );
372
373 if ( pFont )
374 {
375 R2Size[ i ] = pFont -> CalcSize
376 (
377 pProjCh_Val
378 );
379
380 bCanRender[ i ] = pFont -> bCanRenderFully
381 (
382 pProjCh_Val
383 );
384 }
385 else
386 {
387 R2Size[ i ] = r2size(0,0);
388
389 bCanRender[ i ] = No;
390 }
391 }
392
393 // Insert at head of list:
394 {
395 if ( pFirst )
396 {
397 pFirst -> pPrv = this;
398 }
399
400 pNxt = pFirst;
401 pPrv = NULL;
402
403 pFirst = this;
404 }
405
406 }
407 }
408
409
410
SCString(ProjChar * pProjCh_Init,unsigned int Length)411 SCString :: SCString
412 (
413 ProjChar* pProjCh_Init,
414 unsigned int Length
415 )
416 {
417 // Forms a string of length at most Length (with 1 extra for NULL-terminator)
418
419 /* PRECONDITION */
420 {
421 GLOBALASSERT( pProjCh_Init );
422 }
423
424 /* CODE */
425 {
426 NumberOfCharacters = STRUTIL_SC_Strlen( pProjCh_Init );
427 // doesn't include NULL terminator
428
429 if ( (unsigned)NumberOfCharacters > Length )
430 {
431 NumberOfCharacters = Length;
432 }
433
434 AllocatedSize = (size_t) STRUTIL_SC_NumBytes
435 (
436 pProjCh_Init
437 );
438
439 {
440 size_t TruncSize = sizeof(ProjChar) * (Length + 1);
441
442 if (AllocatedSize > TruncSize )
443 {
444 AllocatedSize = TruncSize;
445 }
446 }
447
448 pProjCh_Val = new ProjChar[ AllocatedSize ];
449 GLOBALASSERT( pProjCh_Val );
450 // this is always "owned" by the String
451
452 STRUTIL_SC_SafeCopy
453 (
454 pProjCh_Val,
455 (NumberOfCharacters+1),
456
457 pProjCh_Init
458 );
459
460 FontIndex i = IndexedFonts_MAX_NUMBER_OF_FONTS;
461
462 while ( i>0 )
463 {
464 i = (FontIndex)(i-1);
465
466 IndexedFont* pFont = IndexedFont :: GetFont( i );
467
468 if ( pFont )
469 {
470 R2Size[ i ] = pFont -> CalcSize
471 (
472 pProjCh_Val
473 );
474
475 bCanRender[ i ] = pFont -> bCanRenderFully
476 (
477 pProjCh_Val
478 );
479 }
480 else
481 {
482 R2Size[ i ] = r2size(0,0);
483
484 bCanRender[ i ] = No;
485 }
486 }
487
488 // Insert at head of list:
489 {
490 if ( pFirst )
491 {
492 pFirst -> pPrv = this;
493 }
494
495 pNxt = pFirst;
496 pPrv = NULL;
497
498 pFirst = this;
499 }
500
501 }
502 }
503
504
SCString(SCString * pStringObj_0,SCString * pStringObj_1)505 SCString :: SCString
506 (
507 SCString* pStringObj_0,
508 SCString* pStringObj_1
509 )
510 {
511 // forms a new string object by concatenating the strings in 0
512 // and 1
513
514 /* PRECONDITION */
515 {
516 GLOBALASSERT( pStringObj_0 );
517 GLOBALASSERT( pStringObj_1 );
518 }
519
520 /* CODE */
521 {
522 ProjChar* pProjCh_Init_0 = pStringObj_0 -> pProjCh();
523 GLOBALASSERT( pProjCh_Init_0 );
524
525 ProjChar* pProjCh_Init_1 = pStringObj_1 -> pProjCh();
526 GLOBALASSERT( pProjCh_Init_1 );
527
528 AllocatedSize = (size_t)
529 (
530 STRUTIL_SC_NumBytes
531 (
532 pProjCh_Init_0
533 )
534 +
535 STRUTIL_SC_NumBytes
536 (
537 pProjCh_Init_1
538 )
539 - sizeof(ProjChar) // only one null terminator needed
540 );
541
542 pProjCh_Val = new ProjChar[ AllocatedSize ];
543 GLOBALASSERT( pProjCh_Val );
544
545 // this is always "owned" by the String
546 STRUTIL_SC_FastCat
547 (
548 pProjCh_Val,
549 pProjCh_Init_0,
550 pProjCh_Init_1
551 );
552
553 NumberOfCharacters = ( AllocatedSize / sizeof(ProjChar ) ) - 1;
554 // doesn't include NULL terminator
555
556 FontIndex i = IndexedFonts_MAX_NUMBER_OF_FONTS;
557
558 while ( i>0 )
559 {
560 i = (FontIndex)(i-1);
561
562 R2Size[ i ] = pStringObj_0 -> CalcSize( i );
563 R2Size[ i ] . w += pStringObj_1 -> CalcSize( i ) . w;
564
565 bCanRender[ i ] =
566 (
567 pStringObj_0 -> bCanRenderFully( i )
568 &&
569 pStringObj_1 -> bCanRenderFully( i )
570 );
571 }
572
573 // Insert at head of list:
574 {
575 if ( pFirst )
576 {
577 pFirst -> pPrv = this;
578 }
579
580 pNxt = pFirst;
581 pPrv = NULL;
582
583 pFirst = this;
584 }
585
586 }
587 }
588
589
SCString(SCString * pStringObj_0,SCString * pStringObj_1,SCString * pStringObj_2)590 SCString :: SCString
591 (
592 SCString* pStringObj_0,
593 SCString* pStringObj_1,
594 SCString* pStringObj_2
595 )
596 {
597 // forms a new string object by concatenating the strings in 0, 1 and 2
598
599 /* PRECONDITION */
600 {
601 GLOBALASSERT( pStringObj_0 );
602 GLOBALASSERT( pStringObj_1 );
603 GLOBALASSERT( pStringObj_2 );
604 }
605
606 /* CODE */
607 {
608 // Insert at head of list:
609 {
610 if ( pFirst )
611 {
612 pFirst -> pPrv = this;
613 }
614
615 pNxt = pFirst;
616 pPrv = NULL;
617
618 pFirst = this;
619 }
620
621 SCString* pStringObj_Intermediate = new SCString
622 (
623 pStringObj_1,
624 pStringObj_2
625 );
626
627 ProjChar* pProjCh_Init_0 = pStringObj_0 -> pProjCh();
628 GLOBALASSERT( pProjCh_Init_0 );
629
630 ProjChar* pProjCh_Intermediate = pStringObj_Intermediate -> pProjCh();
631 GLOBALASSERT( pProjCh_Intermediate );
632
633 AllocatedSize = (size_t)
634 (
635 STRUTIL_SC_NumBytes
636 (
637 pProjCh_Init_0
638 )
639 +
640 STRUTIL_SC_NumBytes
641 (
642 pProjCh_Intermediate
643 )
644 - sizeof(ProjChar) // only one null terminator needed
645 );
646
647 pProjCh_Val = new ProjChar[ AllocatedSize ];
648 GLOBALASSERT( pProjCh_Val );
649 // this is always "owned" by the String
650 STRUTIL_SC_FastCat
651 (
652 pProjCh_Val,
653 pProjCh_Init_0,
654 pProjCh_Intermediate
655 );
656
657 NumberOfCharacters = ( AllocatedSize / sizeof(ProjChar ) ) - 1;
658 // doesn't include NULL terminator
659
660 FontIndex i = IndexedFonts_MAX_NUMBER_OF_FONTS;
661
662 while ( i>0 )
663 {
664 i = (FontIndex)(i-1);
665
666 R2Size[ i ] = pStringObj_0 -> CalcSize( i );
667 R2Size[ i ] . w +=
668 (
669 pStringObj_1 -> CalcSize( i ) . w
670 +
671 pStringObj_2 -> CalcSize( i ) . w
672 );
673
674 bCanRender[ i ] =
675 (
676 pStringObj_0 -> bCanRenderFully( i )
677 &&
678 pStringObj_1 -> bCanRenderFully( i )
679 &&
680 pStringObj_2 -> bCanRenderFully( i )
681 );
682 }
683
684 pStringObj_Intermediate -> R_Release();
685 }
686 }
687
SCString(SCString * pStringObj_0,SCString * pStringObj_1,SCString * pStringObj_2,SCString * pStringObj_3)688 SCString :: SCString
689 (
690 SCString* pStringObj_0,
691 SCString* pStringObj_1,
692 SCString* pStringObj_2,
693 SCString* pStringObj_3
694 )
695 {
696 /* PRECONDITION */
697 {
698 GLOBALASSERT( pStringObj_0 );
699 GLOBALASSERT( pStringObj_1 );
700 GLOBALASSERT( pStringObj_2 );
701 GLOBALASSERT( pStringObj_3 );
702 }
703
704 /* CODE */
705 {
706 // Insert at head of list:
707 {
708 if ( pFirst )
709 {
710 pFirst -> pPrv = this;
711 }
712
713 pNxt = pFirst;
714 pPrv = NULL;
715
716 pFirst = this;
717 }
718
719 SCString* pStringObj_Intermediate = new SCString
720 (
721 pStringObj_1,
722 pStringObj_2,
723 pStringObj_3
724 );
725
726 ProjChar* pProjCh_Init_0 = pStringObj_0 -> pProjCh();
727 GLOBALASSERT( pProjCh_Init_0 );
728
729 ProjChar* pProjCh_Intermediate = pStringObj_Intermediate -> pProjCh();
730 GLOBALASSERT( pProjCh_Intermediate );
731
732 AllocatedSize = (size_t)
733 (
734 STRUTIL_SC_NumBytes
735 (
736 pProjCh_Init_0
737 )
738 +
739 STRUTIL_SC_NumBytes
740 (
741 pProjCh_Intermediate
742 )
743 - sizeof(ProjChar) // only one null terminator needed
744 );
745
746 pProjCh_Val = new ProjChar[ AllocatedSize ];
747 GLOBALASSERT( pProjCh_Val );
748 // this is always "owned" by the String
749 STRUTIL_SC_FastCat
750 (
751 pProjCh_Val,
752 pProjCh_Init_0,
753 pProjCh_Intermediate
754 );
755
756 NumberOfCharacters = ( AllocatedSize / sizeof(ProjChar ) ) - 1;
757 // doesn't include NULL terminator
758
759 FontIndex i = IndexedFonts_MAX_NUMBER_OF_FONTS;
760
761 while ( i>0 )
762 {
763 i = (FontIndex)(i-1);
764
765 R2Size[ i ] = pStringObj_0 -> CalcSize( i );
766 R2Size[ i ] . w +=
767 (
768 pStringObj_1 -> CalcSize( i ) . w
769 +
770 pStringObj_2 -> CalcSize( i ) . w
771 +
772 pStringObj_3 -> CalcSize( i ) . w
773 );
774
775 bCanRender[ i ] =
776 (
777 pStringObj_0 -> bCanRenderFully( i )
778 &&
779 pStringObj_1 -> bCanRenderFully( i )
780 &&
781 pStringObj_2 -> bCanRenderFully( i )
782 &&
783 pStringObj_3 -> bCanRenderFully( i )
784 );
785 }
786
787 pStringObj_Intermediate -> R_Release();
788 }
789 }
790
791
SCString(SCString * pStringObj_0,SCString * pStringObj_1,SCString * pStringObj_2,SCString * pStringObj_3,SCString * pStringObj_4)792 SCString :: SCString
793 (
794 SCString* pStringObj_0,
795 SCString* pStringObj_1,
796 SCString* pStringObj_2,
797 SCString* pStringObj_3,
798 SCString* pStringObj_4
799 )
800 {
801 /* PRECONDITION */
802 {
803 GLOBALASSERT( pStringObj_0 );
804 GLOBALASSERT( pStringObj_1 );
805 GLOBALASSERT( pStringObj_2 );
806 GLOBALASSERT( pStringObj_3 );
807 GLOBALASSERT( pStringObj_4 );
808 }
809
810 /* CODE */
811 {
812 // Insert at head of list:
813 {
814 if ( pFirst )
815 {
816 pFirst -> pPrv = this;
817 }
818
819 pNxt = pFirst;
820 pPrv = NULL;
821
822 pFirst = this;
823 }
824
825 SCString* pStringObj_Intermediate = new SCString
826 (
827 pStringObj_1,
828 pStringObj_2,
829 pStringObj_3,
830 pStringObj_4
831 );
832
833 ProjChar* pProjCh_Init_0 = pStringObj_0 -> pProjCh();
834 GLOBALASSERT( pProjCh_Init_0 );
835
836 ProjChar* pProjCh_Intermediate = pStringObj_Intermediate -> pProjCh();
837 GLOBALASSERT( pProjCh_Intermediate );
838
839 AllocatedSize = (size_t)
840 (
841 STRUTIL_SC_NumBytes
842 (
843 pProjCh_Init_0
844 )
845 +
846 STRUTIL_SC_NumBytes
847 (
848 pProjCh_Intermediate
849 )
850 - sizeof(ProjChar) // only one null terminator needed
851 );
852
853 pProjCh_Val = new ProjChar[ AllocatedSize ];
854 GLOBALASSERT( pProjCh_Val );
855 // this is always "owned" by the String
856 STRUTIL_SC_FastCat
857 (
858 pProjCh_Val,
859 pProjCh_Init_0,
860 pProjCh_Intermediate
861 );
862
863 NumberOfCharacters = ( AllocatedSize / sizeof(ProjChar ) ) - 1;
864 // doesn't include NULL terminator
865
866 FontIndex i = IndexedFonts_MAX_NUMBER_OF_FONTS;
867
868 while ( i>0 )
869 {
870 i = (FontIndex)(i-1);
871
872 R2Size[ i ] = pStringObj_0 -> CalcSize( i );
873 R2Size[ i ] . w +=
874 (
875 pStringObj_1 -> CalcSize( i ) . w
876 +
877 pStringObj_2 -> CalcSize( i ) . w
878 +
879 pStringObj_3 -> CalcSize( i ) . w
880 +
881 pStringObj_4 -> CalcSize( i ) . w
882 );
883
884 bCanRender[ i ] =
885 (
886 pStringObj_0 -> bCanRenderFully( i )
887 &&
888 pStringObj_1 -> bCanRenderFully( i )
889 &&
890 pStringObj_2 -> bCanRenderFully( i )
891 &&
892 pStringObj_3 -> bCanRenderFully( i )
893 &&
894 pStringObj_4 -> bCanRenderFully( i )
895 );
896 }
897
898 pStringObj_Intermediate -> R_Release();
899 }
900 }
901
902
SCString(List<ProjChar> List_ProjChar)903 SCString :: SCString
904 (
905 List<ProjChar> List_ProjChar
906 )
907 {
908 {
909 AllocatedSize = (size_t) (List_ProjChar . size() + 1) * sizeof(ProjChar);
910
911 pProjCh_Val = new ProjChar[ AllocatedSize ];
912 GLOBALASSERT( pProjCh_Val );
913
914 #if 1
915 {
916 ProjChar* pDst = pProjCh_Val;
917
918 for
919 (
920 LIF<ProjChar> oi(&(List_ProjChar));
921 !oi.done();
922 oi.next()
923 )
924 {
925 *(pDst++) = oi();
926 }
927
928 // Write terminator:
929 *pDst = 0;
930 }
931 #else
932 STRUTIL_SC_StrCpy
933 (
934 pProjCh_Val,
935 pProjCh_Init
936 );
937 #endif
938
939 NumberOfCharacters = ( AllocatedSize / sizeof(ProjChar ) ) - 1;
940 // doesn't include NULL terminator
941
942 FontIndex i = IndexedFonts_MAX_NUMBER_OF_FONTS;
943
944 while ( i>0 )
945 {
946 i = (FontIndex)(i-1);
947
948 IndexedFont* pFont = IndexedFont :: GetFont( i );
949
950 if ( pFont )
951 {
952 R2Size[ i ] = pFont -> CalcSize
953 (
954 pProjCh_Val
955 );
956
957 bCanRender[ i ] = pFont -> bCanRenderFully
958 (
959 pProjCh_Val
960 );
961 }
962 else
963 {
964 R2Size[ i ] = r2size(0,0);
965
966 bCanRender[ i ] = No;
967 }
968 }
969
970 // Insert at head of list:
971 {
972 if ( pFirst )
973 {
974 pFirst -> pPrv = this;
975 }
976
977 pNxt = pFirst;
978 pPrv = NULL;
979
980 pFirst = this;
981 }
982 }
983
984 }
985
UpdateAfterFontChange(FontIndex I_Font_Changed)986 /*static*/ void SCString :: UpdateAfterFontChange( FontIndex I_Font_Changed )
987 {
988 // called by the font code whenever fonts are loaded/unloaded
989
990 /* PRECONDITION */
991 {
992 GLOBALASSERT( I_Font_Changed < IndexedFonts_MAX_NUMBER_OF_FONTS );
993 }
994
995 /* CODE */
996 {
997 IndexedFont* pFont = IndexedFont :: GetFont( I_Font_Changed );
998
999 SCString* pSCString = pFirst;
1000
1001 while ( pSCString )
1002 {
1003 if ( pFont )
1004 {
1005 pSCString -> R2Size[ I_Font_Changed ] = pFont -> CalcSize
1006 (
1007 pSCString -> pProjCh_Val
1008 );
1009
1010 pSCString -> bCanRender[ I_Font_Changed ] = pFont -> bCanRenderFully
1011 (
1012 pSCString -> pProjCh_Val
1013 );
1014 }
1015 else
1016 {
1017 pSCString -> R2Size[ I_Font_Changed ] = r2size(0,0);
1018
1019 pSCString -> bCanRender[ I_Font_Changed ] = No;
1020 }
1021
1022 pSCString = pSCString -> pNxt;
1023 }
1024 }
1025 }
1026
Parse(ProjChar * pProjChar_Start)1027 /*static*/ List<SCString*> SCString :: Parse
1028 (
1029 ProjChar* pProjChar_Start
1030 )
1031 {
1032 // takes a string and builds a list of new SCStrings, in which
1033 // each string in the list consists of non-whitespace characters from
1034 // the input, and the whitespace is used to separate individual
1035 // strings
1036
1037 // I call the strings "words"
1038
1039 /* PRECONDITION */
1040 {
1041 GLOBALASSERT( pProjChar_Start );
1042 }
1043
1044 /* CODE */
1045 {
1046 List<SCString*> List_Return;
1047
1048 ProjChar* pProjChar_Iterate = pProjChar_Start;
1049 int NumCharsNonWhitespace = 0;
1050
1051 while
1052 (
1053 *pProjChar_Iterate
1054 )
1055 {
1056 if
1057 (
1058 *pProjChar_Iterate == ' '
1059 )
1060 {
1061 // Whitespace:
1062 if ( NumCharsNonWhitespace > 0 )
1063 {
1064 // End of a word; add the string to the list:
1065 List_Return . add_entry
1066 (
1067 new SCString
1068 (
1069 pProjChar_Start,
1070 NumCharsNonWhitespace
1071 )
1072 );
1073 NumCharsNonWhitespace = 0;
1074 }
1075 else
1076 {
1077 // Already processing a block of whitespace; do nothing
1078 }
1079 }
1080 else
1081 {
1082 // Non-whitespace:
1083 if ( NumCharsNonWhitespace > 0 )
1084 {
1085 // In the middle of a word:
1086 }
1087 else
1088 {
1089 // Start of a word:
1090 pProjChar_Start = pProjChar_Iterate;
1091 }
1092
1093 NumCharsNonWhitespace++;
1094
1095 }
1096
1097 pProjChar_Iterate++;
1098 }
1099
1100 // End of the string; flush any remaining whitespace:
1101 if ( NumCharsNonWhitespace > 0 )
1102 {
1103 List_Return . add_entry
1104 (
1105 new SCString
1106 (
1107 pProjChar_Start,
1108 NumCharsNonWhitespace
1109 )
1110 );
1111 }
1112
1113 return List_Return;
1114 }
1115 }
1116
1117
1118 //private:
~SCString()1119 SCString :: ~SCString()
1120 {
1121 /* PRECONDITION */
1122 {
1123 GLOBALASSERT( pProjCh_Val );
1124 }
1125
1126 /* CODE */
1127 {
1128 delete[] pProjCh_Val;
1129
1130 // Remove from list:
1131 {
1132 if ( pFirst == this )
1133 {
1134 pFirst = pNxt;
1135 }
1136 else
1137 {
1138 pPrv -> pNxt = pNxt;
1139 }
1140
1141 if (pNxt)
1142 {
1143 pNxt -> pPrv = pPrv;
1144 }
1145 }
1146
1147 }
1148 }
1149