This commit was generated by cvs2svn to compensate for changes in r2,
[btb/d2x.git] / 2d / font.c
1 /*
2 THE COMPUTER CODE CONTAINED HEREIN IS THE SOLE PROPERTY OF PARALLAX
3 SOFTWARE CORPORATION ("PARALLAX").  PARALLAX, IN DISTRIBUTING THE CODE TO
4 END-USERS, AND SUBJECT TO ALL OF THE TERMS AND CONDITIONS HEREIN, GRANTS A
5 ROYALTY-FREE, PERPETUAL LICENSE TO SUCH END-USERS FOR USE BY SUCH END-USERS
6 IN USING, DISPLAYING,  AND CREATING DERIVATIVE WORKS THEREOF, SO LONG AS
7 SUCH USE, DISPLAY OR CREATION IS FOR NON-COMMERCIAL, ROYALTY OR REVENUE
8 FREE PURPOSES.  IN NO EVENT SHALL THE END-USER USE THE COMPUTER CODE
9 CONTAINED HEREIN FOR REVENUE-BEARING PURPOSES.  THE END-USER UNDERSTANDS
10 AND AGREES TO THE TERMS HEREIN AND ACCEPTS THE SAME BY USE OF THIS FILE.  
11 COPYRIGHT 1993-1999 PARALLAX SOFTWARE CORPORATION.  ALL RIGHTS RESERVED.
12 */
13
14 #include <conf.h>
15 #include <stdarg.h>
16 #include <stdio.h>
17 #include <stdlib.h>
18 #include <string.h>
19
20 #include <fcntl.h>
21 #include <unistd.h>
22
23 #include "pa_enabl.h"                   //$$POLY_ACC
24 #include "u_mem.h"
25
26 #include "gr.h"
27 #include "grdef.h"
28 #include "error.h"
29
30 #include "cfile.h"
31 #include "mono.h"
32 #include "byteswap.h"
33 #include "bitmap.h"
34
35 #if defined(POLY_ACC)
36 #include "poly_acc.h"
37 #endif
38
39 #define MAX_OPEN_FONTS  50
40 #define FILENAME_LEN            13
41
42 typedef struct openfont {
43         char filename[FILENAME_LEN];
44         grs_font *ptr;
45 } openfont;
46
47 //list of open fonts, for use (for now) for palette remapping
48 openfont open_font[MAX_OPEN_FONTS];
49
50 #define FONT        grd_curcanv->cv_font
51 #define FG_COLOR    grd_curcanv->cv_font_fg_color
52 #define BG_COLOR    grd_curcanv->cv_font_bg_color
53 #define FWIDTH       FONT->ft_w
54 #define FHEIGHT      FONT->ft_h
55 #define FBASELINE    FONT->ft_baseline
56 #define FFLAGS       FONT->ft_flags
57 #define FMINCHAR     FONT->ft_minchar
58 #define FMAXCHAR     FONT->ft_maxchar
59 #define FDATA        FONT->ft_data
60 #define FCHARS       FONT->ft_chars
61 #define FWIDTHS      FONT->ft_widths
62
63 #define BITS_TO_BYTES(x)    (((x)+7)>>3)
64
65 int gr_internal_string_clipped(int x, int y, char *s );
66 int gr_internal_string_clipped_m(int x, int y, char *s );
67
68 ubyte *find_kern_entry(grs_font *font,ubyte first,ubyte second)
69 {
70         ubyte *p=font->ft_kerndata;
71
72         while (*p!=255)
73                 if (p[0]==first && p[1]==second)
74                         return p;
75                 else p+=3;
76
77         return NULL;
78
79 }
80
81 //takes the character AFTER being offset into font
82 #define INFONT(_c) ((_c >= 0) && (_c <= FMAXCHAR-FMINCHAR))
83
84 //takes the character BEFORE being offset into current font
85 void get_char_width(ubyte c,ubyte c2,int *width,int *spacing)
86 {
87         int letter;
88
89         letter = c-FMINCHAR;
90
91         if (!INFONT(letter)) {                          //not in font, draw as space
92                 *width=0;
93                 if (FFLAGS & FT_PROPORTIONAL)
94                         *spacing = FWIDTH/2;
95                 else
96                         *spacing = FWIDTH;
97                 return;
98         }
99
100         if (FFLAGS & FT_PROPORTIONAL)
101                 *width = FWIDTHS[letter];
102         else
103                 *width = FWIDTH;
104
105         *spacing = *width;
106
107         if (FFLAGS & FT_KERNED)  {
108                 ubyte *p;
109
110                 if (!(c2==0 || c2=='\n')) {
111                         int letter2;
112
113                         letter2 = c2-FMINCHAR;
114
115                         if (INFONT(letter2)) {
116
117                                 p = find_kern_entry(FONT,letter,letter2);
118
119                                 if (p)
120                                         *spacing = p[2];
121                         }
122                 }
123         }
124 }
125
126 int get_centered_x(char *s)
127 {
128         int w,w2,s2;
129
130         for (w=0;*s!=0 && *s!='\n';s++) {
131                 get_char_width(s[0],s[1],&w2,&s2);
132                 w += s2;
133         }
134
135         return ((grd_curcanv->cv_bitmap.bm_w - w) / 2);
136 }
137
138
139 int gr_internal_string0(int x, int y, char *s )
140 {
141         unsigned char * fp;
142         ubyte * text_ptr, * next_row, * text_ptr1;
143         int r, BitMask, i, bits, width, spacing, letter, underline;
144         int     skip_lines = 0;
145
146         unsigned int VideoOffset, VideoOffset1;
147
148         VideoOffset1 = y * ROWSIZE + x;
149
150         next_row = s;
151
152         while (next_row != NULL )
153         {
154                 text_ptr1 = next_row;
155                 next_row = NULL;
156
157                 if (x==0x8000) {                        //centered
158                         int xx = get_centered_x(text_ptr1);
159                         VideoOffset1 = y * ROWSIZE + xx;
160                 }
161
162                 for (r=0; r<FHEIGHT; r++)
163                 {
164
165                         text_ptr = text_ptr1;
166
167                         VideoOffset = VideoOffset1;
168
169                         while (*text_ptr)
170                         {
171                                 if (*text_ptr == '\n' )
172                                 {
173                                         next_row = &text_ptr[1];
174                                         break;
175                                 }
176
177                                 if (*text_ptr == CC_COLOR) {
178                                         FG_COLOR = *(text_ptr+1);
179                                         text_ptr += 2;
180                                         continue;
181                                 }
182
183                                 if (*text_ptr == CC_LSPACING) {
184                                         skip_lines = *(text_ptr+1) - '0';
185                                         text_ptr += 2;
186                                         continue;
187                                 }
188
189                                 underline = 0;
190                                 if (*text_ptr == CC_UNDERLINE )
191                                 {
192                                         if ((r==FBASELINE+2) || (r==FBASELINE+3))
193                                                 underline = 1;
194                                         text_ptr++;
195                                 }
196
197                                 get_char_width(text_ptr[0],text_ptr[1],&width,&spacing);
198
199                                 letter = *text_ptr-FMINCHAR;
200
201                                 if (!INFONT(letter)) {  //not in font, draw as space
202                                         VideoOffset += spacing;
203                                         text_ptr++;
204                                         continue;
205                                 }
206
207                                 if (FFLAGS & FT_PROPORTIONAL)
208                                         fp = FCHARS[letter];
209                                 else
210                                         fp = FDATA + letter * BITS_TO_BYTES(width)*FHEIGHT;
211
212                                 if (underline)
213                                         for (i=0; i< width; i++ )
214                                                 DATA[VideoOffset++] = FG_COLOR;
215                                 else
216                                 {
217                                         fp += BITS_TO_BYTES(width)*r;
218
219                                         BitMask = 0;
220
221                                         for (i=0; i< width; i++ )
222                                         {
223                                                 if (BitMask==0) {
224                                                         bits = *fp++;
225                                                         BitMask = 0x80;
226                                                 }
227
228                                                 if (bits & BitMask)
229                                                         DATA[VideoOffset++] = FG_COLOR;
230                                                 else
231                                                         DATA[VideoOffset++] = BG_COLOR;
232                                                 BitMask >>= 1;
233                                         }
234                                 }
235
236                                 VideoOffset += spacing-width;           //for kerning
237
238                                 text_ptr++;
239                         }
240
241                         VideoOffset1 += ROWSIZE; y++;
242                 }
243
244                 y += skip_lines;
245                 VideoOffset1 += ROWSIZE * skip_lines;
246                 skip_lines = 0;
247         }
248         return 0;
249 }
250
251 int gr_internal_string0m(int x, int y, char *s )
252 {
253         unsigned char * fp;
254         ubyte * text_ptr, * next_row, * text_ptr1;
255         int r, BitMask, i, bits, width, spacing, letter, underline;
256         int     skip_lines = 0;
257
258         unsigned int VideoOffset, VideoOffset1;
259
260         VideoOffset1 = y * ROWSIZE + x;
261
262         next_row = s;
263
264         while (next_row != NULL )
265         {
266                 text_ptr1 = next_row;
267                 next_row = NULL;
268
269                 if (x==0x8000) {                        //centered
270                         int xx = get_centered_x(text_ptr1);
271                         VideoOffset1 = y * ROWSIZE + xx;
272                 }
273
274                 for (r=0; r<FHEIGHT; r++)
275                 {
276
277                         text_ptr = text_ptr1;
278
279                         VideoOffset = VideoOffset1;
280
281                         while (*text_ptr)
282                         {
283                                 if (*text_ptr == '\n' )
284                                 {
285                                         next_row = &text_ptr[1];
286                                         break;
287                                 }
288
289                                 if (*text_ptr == CC_COLOR) {
290                                         FG_COLOR = *(text_ptr+1);
291                                         text_ptr += 2;
292                                         continue;
293                                 }
294
295                                 if (*text_ptr == CC_LSPACING) {
296                                         skip_lines = *(text_ptr+1) - '0';
297                                         text_ptr += 2;
298                                         continue;
299                                 }
300
301                                 underline = 0;
302                                 if (*text_ptr == CC_UNDERLINE )
303                                 {
304                                         if ((r==FBASELINE+2) || (r==FBASELINE+3))
305                                                 underline = 1;
306                                         text_ptr++;
307                                 }
308
309                                 get_char_width(text_ptr[0],text_ptr[1],&width,&spacing);
310
311                                 letter = *text_ptr-FMINCHAR;
312
313                                 if (!INFONT(letter)) {  //not in font, draw as space
314                                         VideoOffset += spacing;
315                                         text_ptr++;
316                                         continue;
317                                 }
318
319                                 if (FFLAGS & FT_PROPORTIONAL)
320                                         fp = FCHARS[letter];
321                                 else
322                                         fp = FDATA + letter * BITS_TO_BYTES(width)*FHEIGHT;
323
324                                 if (underline)
325                                         for (i=0; i< width; i++ )
326                                                 DATA[VideoOffset++] = FG_COLOR;
327                                 else
328                                 {
329                                         fp += BITS_TO_BYTES(width)*r;
330
331                                         BitMask = 0;
332
333                                         for (i=0; i< width; i++ )
334                                         {
335                                                 if (BitMask==0) {
336                                                         bits = *fp++;
337                                                         BitMask = 0x80;
338                                                 }
339
340                                                 if (bits & BitMask)
341                                                         DATA[VideoOffset++] = FG_COLOR;
342                                                 else
343                                                         VideoOffset++;
344                                                 BitMask >>= 1;
345                                         }
346                                 }
347                                 text_ptr++;
348
349                                 VideoOffset += spacing-width;
350                         }
351
352                         VideoOffset1 += ROWSIZE; y++;
353                 }
354                 y += skip_lines;
355                 VideoOffset1 += ROWSIZE * skip_lines;
356                 skip_lines = 0;
357         }
358         return 0;
359 }
360
361 #ifdef __ENV_MSDOS__
362 int gr_internal_string2(int x, int y, char *s )
363 {
364         unsigned char * fp;
365         char * text_ptr, * next_row, * text_ptr1;
366         int r, BitMask, i, bits, width, spacing, letter, underline;
367         int page_switched, skip_lines = 0;
368
369         unsigned int VideoOffset, VideoOffset1;
370
371         VideoOffset1 = (unsigned int)DATA + y * ROWSIZE + x;
372
373         gr_vesa_setpage(VideoOffset1 >> 16);
374
375         VideoOffset1 &= 0xFFFF;
376
377         next_row = s;
378
379         while (next_row != NULL )
380         {
381                 text_ptr1 = next_row;
382                 next_row = NULL;
383
384                 if (x==0x8000) {                        //centered
385                         int xx = get_centered_x(text_ptr1);
386                         VideoOffset1 = y * ROWSIZE + xx;
387                         gr_vesa_setpage(VideoOffset1 >> 16);
388                         VideoOffset1 &= 0xFFFF;
389                 }
390
391                 for (r=0; r<FHEIGHT; r++)
392                 {
393                         text_ptr = text_ptr1;
394
395                         VideoOffset = VideoOffset1;
396
397                         page_switched = 0;
398
399                         while (*text_ptr)
400                         {
401                                 if (*text_ptr == '\n' )
402                                 {
403                                         next_row = &text_ptr[1];
404                                         break;
405                                 }
406
407                                 if (*text_ptr == CC_COLOR) {
408                                         FG_COLOR = *(text_ptr+1);
409                                         text_ptr += 2;
410                                         continue;
411                                 }
412
413                                 if (*text_ptr == CC_LSPACING) {
414                                         skip_lines = *(text_ptr+1) - '0';
415                                         text_ptr += 2;
416                                         continue;
417                                 }
418
419                                 underline = 0;
420                                 if (*text_ptr == CC_UNDERLINE )
421                                 {
422                                         if ((r==FBASELINE+2) || (r==FBASELINE+3))
423                                                 underline = 1;
424                                         text_ptr++;
425                                 }
426
427                                 get_char_width(text_ptr[0],text_ptr[1],&width,&spacing);
428
429                                 Assert(width==spacing);         //no kerning support here
430
431                                 letter = *text_ptr-FMINCHAR;
432
433                                 if (!INFONT(letter)) {  //not in font, draw as space
434                                         VideoOffset += spacing;
435                                         text_ptr++;
436                                         continue;
437                                 }
438
439                                 if (FFLAGS & FT_PROPORTIONAL)
440                                         fp = FCHARS[letter];
441                                 else
442                                         fp = FDATA + letter * BITS_TO_BYTES(width)*FHEIGHT;
443
444                                 if (underline)
445                                 {
446                                         if ( VideoOffset+width > 0xFFFF )
447                                         {
448                                                 for (i=0; i< width; i++ )
449                                                 {
450                                                         gr_video_memory[VideoOffset++] = FG_COLOR;
451
452                                                         if (VideoOffset > 0xFFFF )
453                                                         {
454                                                                 VideoOffset -= 0xFFFF + 1;
455                                                                 page_switched = 1;
456                                                                 gr_vesa_incpage();
457                                                         }
458                                                 }
459                                         }
460                                         else
461                                         {
462                                                 for (i=0; i< width; i++ )
463                                                         gr_video_memory[VideoOffset++] = FG_COLOR;
464                                         }
465                                 }
466                                 else
467                                 {
468                                         // fp -- dword
469                                         // VideoOffset
470                                         // width
471
472                                         fp += BITS_TO_BYTES(width)*r;
473
474                                         BitMask = 0;
475
476                                         if ( VideoOffset+width > 0xFFFF )
477                                         {
478                                                 for (i=0; i< width; i++ )
479                                                 {
480                                                         if (BitMask==0) {
481                                                                 bits = *fp++;
482                                                                 BitMask = 0x80;
483                                                         }
484
485                                                         if (bits & BitMask)
486                                                                 gr_video_memory[VideoOffset++] = FG_COLOR;
487                                                         else
488                                                                 gr_video_memory[VideoOffset++] = BG_COLOR;
489
490                                                         BitMask >>= 1;
491
492                                                         if (VideoOffset > 0xFFFF )
493                                                         {
494                                                                 VideoOffset -= 0xFFFF + 1;
495                                                                 page_switched = 1;
496                                                                 gr_vesa_incpage();
497                                                         }
498
499                                                 }
500                                         } else {
501
502                                                 if (width == 8 )
503                                                 {
504                                                         bits = *fp++;
505
506                                                         if (bits & 0x80) gr_video_memory[VideoOffset+0] = FG_COLOR;
507                                                         else gr_video_memory[VideoOffset+0] = BG_COLOR;
508
509                                                         if (bits & 0x40) gr_video_memory[VideoOffset+1] = FG_COLOR;
510                                                         else gr_video_memory[VideoOffset+1] = BG_COLOR;
511
512                                                         if (bits & 0x20) gr_video_memory[VideoOffset+2] = FG_COLOR;
513                                                         else gr_video_memory[VideoOffset+2] = BG_COLOR;
514
515                                                         if (bits & 0x10) gr_video_memory[VideoOffset+3] = FG_COLOR;
516                                                         else gr_video_memory[VideoOffset+3] = BG_COLOR;
517
518                                                         if (bits & 0x08) gr_video_memory[VideoOffset+4] = FG_COLOR;
519                                                         else gr_video_memory[VideoOffset+4] = BG_COLOR;
520
521                                                         if (bits & 0x04) gr_video_memory[VideoOffset+5] = FG_COLOR;
522                                                         else gr_video_memory[VideoOffset+5] = BG_COLOR;
523
524                                                         if (bits & 0x02) gr_video_memory[VideoOffset+6] = FG_COLOR;
525                                                         else gr_video_memory[VideoOffset+6] = BG_COLOR;
526
527                                                         if (bits & 0x01) gr_video_memory[VideoOffset+7] = FG_COLOR;
528                                                         else gr_video_memory[VideoOffset+7] = BG_COLOR;
529
530                                                         VideoOffset += 8;
531                                                 } else {
532                                                         for (i=0; i< width/2 ; i++ )
533                                                         {
534                                                                 if (BitMask==0) {
535                                                                         bits = *fp++;
536                                                                         BitMask = 0x80;
537                                                                 }
538
539                                                                 if (bits & BitMask)
540                                                                         gr_video_memory[VideoOffset++] = FG_COLOR;
541                                                                 else
542                                                                         gr_video_memory[VideoOffset++] = BG_COLOR;
543                                                                 BitMask >>= 1;
544
545
546                                                                 // Unroll twice
547
548                                                                 if (BitMask==0) {
549                                                                         bits = *fp++;
550                                                                         BitMask = 0x80;
551                                                                 }
552
553                                                                 if (bits & BitMask)
554                                                                         gr_video_memory[VideoOffset++] = FG_COLOR;
555                                                                 else
556                                                                         gr_video_memory[VideoOffset++] = BG_COLOR;
557                                                                 BitMask >>= 1;
558                                                         }
559                                                 }
560                                         }
561                                 }
562                                 text_ptr++;
563                         }
564
565                         y ++;
566                         VideoOffset1 += ROWSIZE;
567
568                         if (VideoOffset1 > 0xFFFF ) {
569                                 VideoOffset1 -= 0xFFFF + 1;
570                                 if (!page_switched)
571                                         gr_vesa_incpage();
572                         }
573                 }
574
575                 y += skip_lines;
576                 VideoOffset1 += ROWSIZE * skip_lines;
577                 skip_lines = 0;
578         }
579         return 0;
580 }
581
582 int gr_internal_string2m(int x, int y, char *s )
583 {
584         unsigned char * fp;
585         char * text_ptr, * next_row, * text_ptr1;
586         int r, BitMask, i, bits, width, spacing, letter, underline;
587         int page_switched, skip_lines = 0;
588
589         unsigned int VideoOffset, VideoOffset1;
590
591         VideoOffset1 = (unsigned int)DATA + y * ROWSIZE + x;
592
593         gr_vesa_setpage(VideoOffset1 >> 16);
594
595         VideoOffset1 &= 0xFFFF;
596
597         next_row = s;
598
599         while (next_row != NULL )
600         {
601                 text_ptr1 = next_row;
602                 next_row = NULL;
603
604                 if (x==0x8000) {                        //centered
605                         int xx = get_centered_x(text_ptr1);
606                         VideoOffset1 = y * ROWSIZE + xx;
607                         gr_vesa_setpage(VideoOffset1 >> 16);
608                         VideoOffset1 &= 0xFFFF;
609                 }
610
611                 for (r=0; r<FHEIGHT; r++)
612                 {
613                         text_ptr = text_ptr1;
614
615                         VideoOffset = VideoOffset1;
616
617                         page_switched = 0;
618
619                         while (*text_ptr)
620                         {
621                                 if (*text_ptr == '\n' )
622                                 {
623                                         next_row = &text_ptr[1];
624                                         break;
625                                 }
626
627                                 if (*text_ptr == CC_COLOR) {
628                                         FG_COLOR = *(text_ptr+1);
629                                         text_ptr += 2;
630                                         continue;
631                                 }
632
633                                 if (*text_ptr == CC_LSPACING) {
634                                         skip_lines = *(text_ptr+1) - '0';
635                                         text_ptr += 2;
636                                         continue;
637                                 }
638
639                                 underline = 0;
640                                 if (*text_ptr == CC_UNDERLINE )
641                                 {
642                                         if ((r==FBASELINE+2) || (r==FBASELINE+3))
643                                                 underline = 1;
644                                         text_ptr++;
645                                 }
646
647                                 get_char_width(text_ptr[0],text_ptr[1],&width,&spacing);
648
649                                 letter = *text_ptr-FMINCHAR;
650
651                                 if (!INFONT(letter)) {  //not in font, draw as space
652                                         VideoOffset += width;
653                                         text_ptr++;
654                                         continue;
655                                 }
656
657                                 if (FFLAGS & FT_PROPORTIONAL)
658                                         fp = FCHARS[letter];
659                                 else
660                                         fp = FDATA + letter * BITS_TO_BYTES(width)*FHEIGHT;
661
662                                 if (underline)
663                                 {
664                                         if ( VideoOffset+width > 0xFFFF )
665                                         {
666                                                 for (i=0; i< width; i++ )
667                                                 {
668                                                         gr_video_memory[VideoOffset++] = FG_COLOR;
669
670                                                         if (VideoOffset > 0xFFFF )
671                                                         {
672                                                                 VideoOffset -= 0xFFFF + 1;
673                                                                 page_switched = 1;
674                                                                 gr_vesa_incpage();
675                                                         }
676                                                 }
677                                         }
678                                         else
679                                         {
680                                                 for (i=0; i< width; i++ )
681                                                         gr_video_memory[VideoOffset++] = FG_COLOR;
682                                         }
683                                 }
684                                 else
685                                 {
686                                         fp += BITS_TO_BYTES(width)*r;
687
688                                         BitMask = 0;
689
690                                         if ( VideoOffset+width > 0xFFFF )
691                                         {
692                                                 for (i=0; i< width; i++ )
693                                                 {
694                                                         if (BitMask==0) {
695                                                                 bits = *fp++;
696                                                                 BitMask = 0x80;
697                                                         }
698
699                                                         if (bits & BitMask)
700                                                                 gr_video_memory[VideoOffset++] = FG_COLOR;
701                                                         else
702                                                                 VideoOffset++;
703
704                                                         BitMask >>= 1;
705
706                                                         if (VideoOffset > 0xFFFF )
707                                                         {
708                                                                 VideoOffset -= 0xFFFF + 1;
709                                                                 page_switched = 1;
710                                                                 gr_vesa_incpage();
711                                                         }
712
713                                                 }
714                                         } else {
715                                                 for (i=0; i< width; i++ )
716                                                 {
717                                                         if (BitMask==0) {
718                                                                 bits = *fp++;
719                                                                 BitMask = 0x80;
720                                                         }
721
722                                                         if (bits & BitMask)
723                                                                 gr_video_memory[VideoOffset++] = FG_COLOR;
724                                                         else
725                                                                 VideoOffset++;;
726                                                         BitMask >>= 1;
727                                                 }
728                                         }
729                                 }
730                                 text_ptr++;
731
732                                 VideoOffset += spacing-width;
733                         }
734
735                         y ++;
736                         VideoOffset1 += ROWSIZE;
737
738                         if (VideoOffset1 > 0xFFFF ) {
739                                 VideoOffset1 -= 0xFFFF + 1;
740                                 if (!page_switched)
741                                         gr_vesa_incpage();
742                         }
743                 }
744
745                 y += skip_lines;
746                 VideoOffset1 += ROWSIZE * skip_lines;
747                 skip_lines = 0;
748         }
749         return 0;
750 }
751
752 #endif // __ENV_MSDOS__
753
754 #if defined(POLY_ACC)
755 int gr_internal_string5(int x, int y, char *s )
756 {
757         unsigned char * fp;
758         ubyte * text_ptr, * next_row, * text_ptr1;
759         int r, BitMask, i, bits, width, spacing, letter, underline;
760         int     skip_lines = 0;
761
762         unsigned int VideoOffset, VideoOffset1;
763
764     pa_flush();
765     VideoOffset1 = y * ROWSIZE + x * PA_BPP;
766
767         next_row = s;
768
769         while (next_row != NULL )
770         {
771                 text_ptr1 = next_row;
772                 next_row = NULL;
773
774                 if (x==0x8000) {                        //centered
775                         int xx = get_centered_x(text_ptr1);
776             VideoOffset1 = y * ROWSIZE + xx * PA_BPP;
777                 }
778
779                 for (r=0; r<FHEIGHT; r++)
780                 {
781
782                         text_ptr = text_ptr1;
783
784                         VideoOffset = VideoOffset1;
785
786                         while (*text_ptr)
787                         {
788                                 if (*text_ptr == '\n' )
789                                 {
790                                         next_row = &text_ptr[1];
791                                         break;
792                                 }
793
794                                 if (*text_ptr == CC_COLOR) {
795                                         FG_COLOR = *(text_ptr+1);
796                                         text_ptr += 2;
797                                         continue;
798                                 }
799
800                                 if (*text_ptr == CC_LSPACING) {
801                                         skip_lines = *(text_ptr+1) - '0';
802                                         text_ptr += 2;
803                                         continue;
804                                 }
805
806                                 underline = 0;
807                                 if (*text_ptr == CC_UNDERLINE )
808                                 {
809                                         if ((r==FBASELINE+2) || (r==FBASELINE+3))
810                                                 underline = 1;
811                                         text_ptr++;
812                                 }
813
814                                 get_char_width(text_ptr[0],text_ptr[1],&width,&spacing);
815
816                                 letter = *text_ptr-FMINCHAR;
817
818                                 if (!INFONT(letter)) {  //not in font, draw as space
819                     VideoOffset += spacing * PA_BPP;
820                                         text_ptr++;
821                                         continue;
822                                 }
823
824                                 if (FFLAGS & FT_PROPORTIONAL)
825                                         fp = FCHARS[letter];
826                                 else
827                                         fp = FDATA + letter * BITS_TO_BYTES(width)*FHEIGHT;
828
829                                 if (underline)
830                                         for (i=0; i< width; i++ )
831                     {    *(short *)(DATA + VideoOffset) = pa_clut[FG_COLOR]; VideoOffset += PA_BPP; }
832                                 else
833                                 {
834                                         fp += BITS_TO_BYTES(width)*r;
835
836                                         BitMask = 0;
837
838                                         for (i=0; i< width; i++ )
839                                         {
840                                                 if (BitMask==0) {
841                                                         bits = *fp++;
842                                                         BitMask = 0x80;
843                                                 }
844
845                                                 if (bits & BitMask)
846                         {    *(short *)(DATA + VideoOffset) = pa_clut[FG_COLOR]; VideoOffset += PA_BPP; }
847                         else
848                         {    *(short *)(DATA + VideoOffset) = pa_clut[BG_COLOR]; VideoOffset += PA_BPP; }
849                         BitMask >>= 1;
850                                         }
851                                 }
852
853                 VideoOffset += PA_BPP * (spacing-width);       //for kerning
854
855                                 text_ptr++;
856                         }
857
858                         VideoOffset1 += ROWSIZE; y++;
859                 }
860
861                 y += skip_lines;
862                 VideoOffset1 += ROWSIZE * skip_lines;
863                 skip_lines = 0;
864         }
865         return 0;
866 }
867
868 int gr_internal_string5m(int x, int y, char *s )
869 {
870         unsigned char * fp;
871         ubyte * text_ptr, * next_row, * text_ptr1;
872         int r, BitMask, i, bits, width, spacing, letter, underline;
873         int     skip_lines = 0;
874
875         unsigned int VideoOffset, VideoOffset1;
876
877     pa_flush();
878     VideoOffset1 = y * ROWSIZE + x * PA_BPP;
879
880         next_row = s;
881
882         while (next_row != NULL )
883         {
884                 text_ptr1 = next_row;
885                 next_row = NULL;
886
887                 if (x==0x8000) {                        //centered
888                         int xx = get_centered_x(text_ptr1);
889             VideoOffset1 = y * ROWSIZE + xx * PA_BPP;
890                 }
891
892                 for (r=0; r<FHEIGHT; r++)
893                 {
894
895                         text_ptr = text_ptr1;
896
897                         VideoOffset = VideoOffset1;
898
899                         while (*text_ptr)
900                         {
901                                 if (*text_ptr == '\n' )
902                                 {
903                                         next_row = &text_ptr[1];
904                                         break;
905                                 }
906
907                                 if (*text_ptr == CC_COLOR) {
908                                         FG_COLOR = *(text_ptr+1);
909                                         text_ptr += 2;
910                                         continue;
911                                 }
912
913                                 if (*text_ptr == CC_LSPACING) {
914                                         skip_lines = *(text_ptr+1) - '0';
915                                         text_ptr += 2;
916                                         continue;
917                                 }
918
919                                 underline = 0;
920                                 if (*text_ptr == CC_UNDERLINE )
921                                 {
922                                         if ((r==FBASELINE+2) || (r==FBASELINE+3))
923                                                 underline = 1;
924                                         text_ptr++;
925                                 }
926
927                                 get_char_width(text_ptr[0],text_ptr[1],&width,&spacing);
928
929                                 letter = *text_ptr-FMINCHAR;
930
931                                 if (!INFONT(letter)) {  //not in font, draw as space
932                     VideoOffset += spacing * PA_BPP;
933                                         text_ptr++;
934                                         continue;
935                                 }
936
937                                 if (FFLAGS & FT_PROPORTIONAL)
938                                         fp = FCHARS[letter];
939                                 else
940                                         fp = FDATA + letter * BITS_TO_BYTES(width)*FHEIGHT;
941
942                                 if (underline)
943                                         for (i=0; i< width; i++ )
944                     {    *(short *)(DATA + VideoOffset) = pa_clut[FG_COLOR]; VideoOffset += PA_BPP; }
945                 else
946                                 {
947                                         fp += BITS_TO_BYTES(width)*r;
948
949                                         BitMask = 0;
950
951                                         for (i=0; i< width; i++ )
952                                         {
953                                                 if (BitMask==0) {
954                                                         bits = *fp++;
955                                                         BitMask = 0x80;
956                                                 }
957
958                                                 if (bits & BitMask)
959                         {    *(short *)(DATA + VideoOffset) = pa_clut[FG_COLOR]; VideoOffset += PA_BPP; }
960                         else
961                             VideoOffset += PA_BPP;
962                                                 BitMask >>= 1;
963                                         }
964                                 }
965                                 text_ptr++;
966
967                 VideoOffset += PA_BPP * (spacing-width);
968                         }
969
970                         VideoOffset1 += ROWSIZE; y++;
971                 }
972                 y += skip_lines;
973                 VideoOffset1 += ROWSIZE * skip_lines;
974                 skip_lines = 0;
975         }
976         return 0;
977 }
978 #endif
979
980 //a bitmap for the character
981 grs_bitmap char_bm = {
982                                 0,0,0,0,                                                //x,y,w,h
983                                 BM_LINEAR,                                      //type
984                                 BM_FLAG_TRANSPARENT,            //flags
985                                 0,                                                              //rowsize
986                                 NULL,                                                   //data
987                                 0                                                               //selector
988 };
989
990 int gr_internal_color_string(int x, int y, char *s )
991 {
992         unsigned char * fp;
993         ubyte * text_ptr, * next_row, * text_ptr1;
994         int width, spacing,letter;
995         int xx,yy;
996
997         char_bm.bm_h = FHEIGHT;         //set height for chars of this font
998
999         next_row = s;
1000
1001         yy = y;
1002
1003
1004         while (next_row != NULL)
1005         {
1006                 text_ptr1 = next_row;
1007                 next_row = NULL;
1008
1009                 text_ptr = text_ptr1;
1010
1011                 xx = x;
1012
1013                 if (xx==0x8000)                 //centered
1014                         xx = get_centered_x(text_ptr);
1015
1016                 while (*text_ptr)
1017                 {
1018                         if (*text_ptr == '\n' )
1019                         {
1020                                 next_row = &text_ptr[1];
1021                                 yy += FHEIGHT;
1022                                 break;
1023                         }
1024
1025                         letter = *text_ptr-FMINCHAR;
1026
1027                         get_char_width(text_ptr[0],text_ptr[1],&width,&spacing);
1028
1029                         if (!INFONT(letter)) {  //not in font, draw as space
1030                                 xx += spacing;
1031                                 text_ptr++;
1032                                 continue;
1033                         }
1034
1035                         if (FFLAGS & FT_PROPORTIONAL)
1036                                 fp = FCHARS[letter];
1037                         else
1038                                 fp = FDATA + letter * BITS_TO_BYTES(width)*FHEIGHT;
1039
1040                         char_bm.bm_w = char_bm.bm_rowsize = width;
1041
1042                         char_bm.bm_data = fp;
1043                         gr_bitmapm(xx,yy,&char_bm);
1044
1045                         xx += spacing;
1046
1047                         text_ptr++;
1048                 }
1049
1050         }
1051         return 0;
1052 }
1053
1054 int gr_string(int x, int y, char *s )
1055 {
1056         int w, h, aw;
1057         int clipped=0;
1058
1059         Assert(FONT != NULL);
1060
1061         if ( x == 0x8000 )      {
1062                 if ( y<0 ) clipped |= 1;
1063                 gr_get_string_size(s, &w, &h, &aw );
1064                 // for x, since this will be centered, only look at
1065                 // width.
1066                 if ( w > grd_curcanv->cv_bitmap.bm_w ) clipped |= 1;
1067                 if ( (y+h) > grd_curcanv->cv_bitmap.bm_h ) clipped |= 1;
1068
1069                 if ( (y+h) < 0 ) clipped |= 2;
1070                 if ( y > grd_curcanv->cv_bitmap.bm_h ) clipped |= 2;
1071
1072         } else {
1073                 if ( (x<0) || (y<0) ) clipped |= 1;
1074                 gr_get_string_size(s, &w, &h, &aw );
1075                 if ( (x+w) > grd_curcanv->cv_bitmap.bm_w ) clipped |= 1;
1076                 if ( (y+h) > grd_curcanv->cv_bitmap.bm_h ) clipped |= 1;
1077                 if ( (x+w) < 0 ) clipped |= 2;
1078                 if ( (y+h) < 0 ) clipped |= 2;
1079                 if ( x > grd_curcanv->cv_bitmap.bm_w ) clipped |= 2;
1080                 if ( y > grd_curcanv->cv_bitmap.bm_h ) clipped |= 2;
1081         }
1082
1083         if ( !clipped )
1084                 return gr_ustring(x, y, s );
1085
1086         if ( clipped & 2 )      {
1087                 // Completely clipped...
1088                 mprintf( (1, "Text '%s' at (%d,%d) is off screen!\n", s, x, y ));
1089                 return 0;
1090         }
1091
1092         if ( clipped & 1 )      {
1093                 // Partially clipped...
1094                 //mprintf( (0, "Text '%s' at (%d,%d) is getting clipped!\n", s, x, y ));
1095         }
1096
1097         // Partially clipped...
1098
1099         if (FFLAGS & FT_COLOR)
1100                 return gr_internal_color_string( x, y, s);
1101
1102         if ( BG_COLOR == -1)
1103                 return gr_internal_string_clipped_m( x, y, s );
1104
1105         return gr_internal_string_clipped( x, y, s );
1106 }
1107
1108 int gr_ustring(int x, int y, char *s )
1109 {
1110         if (FFLAGS & FT_COLOR) {
1111
1112                 return gr_internal_color_string(x,y,s);
1113
1114         }
1115         else
1116                 switch( TYPE )
1117                 {
1118                 case BM_LINEAR:
1119                         if ( BG_COLOR == -1)
1120                                 return gr_internal_string0m(x,y,s);
1121                         else
1122                                 return gr_internal_string0(x,y,s);
1123 #ifdef __ENV_MSDOS__
1124                 case BM_SVGA:
1125                         if ( BG_COLOR == -1)
1126                                 return gr_internal_string2m(x,y,s);
1127                         else
1128                                 return gr_internal_string2(x,y,s);
1129 #endif // __ENV_MSDOS__
1130 #if defined(POLY_ACC)
1131         case BM_LINEAR15:
1132                         if ( BG_COLOR == -1)
1133                 return gr_internal_string5m(x,y,s);
1134                         else
1135                 return gr_internal_string5(x,y,s);
1136 #endif
1137         }
1138
1139         return 0;
1140 }
1141
1142
1143 void gr_get_string_size(char *s, int *string_width, int *string_height, int *average_width )
1144 {
1145         int i = 0, longest_width = 0;
1146         int width,spacing;
1147
1148         *string_height = FHEIGHT;
1149         *string_width = 0;
1150         *average_width = FWIDTH;
1151
1152         if (s != NULL )
1153         {
1154                 *string_width = 0;
1155                 while (*s)
1156                 {
1157 //                      if (*s == CC_UNDERLINE)
1158 //                              s++;
1159                         while (*s == '\n')
1160                         {
1161                                 s++;
1162                                 *string_height += FHEIGHT;
1163                                 *string_width = 0;
1164                         }
1165
1166                         if (*s == 0) break;
1167
1168                         //      1 = next byte specifies color, so skip the 1 and the color value
1169                         if (*s == CC_COLOR)
1170                                 s += 2;
1171                         else if (*s == CC_LSPACING) {
1172                                 *string_height += *(s+1)-'0';
1173                                 s += 2;
1174                         } else {
1175                                 get_char_width(s[0],s[1],&width,&spacing);
1176                                 *string_width += spacing;
1177                                 if (*string_width > longest_width)
1178                                         longest_width = *string_width;
1179                                 i++;
1180                                 s++;
1181                         }
1182                 }
1183         }
1184         *string_width = longest_width;
1185 }
1186
1187
1188 int gr_uprintf( int x, int y, char * format, ... )
1189 {
1190         char buffer[1000];
1191         va_list args;
1192
1193         va_start(args, format );
1194         vsprintf(buffer,format,args);
1195         return gr_ustring( x, y, buffer );
1196 }
1197
1198 int gr_printf( int x, int y, char * format, ... )
1199 {
1200         char buffer[1000];
1201         va_list args;
1202
1203         va_start(args, format );
1204         vsprintf(buffer,format,args);
1205         return gr_string( x, y, buffer );
1206 }
1207
1208 void gr_close_font( grs_font * font )
1209 {
1210         if (font)
1211         {
1212                 int fontnum;
1213
1214                 //find font in list
1215                 for (fontnum=0;fontnum<MAX_OPEN_FONTS && open_font[fontnum].ptr!=font;fontnum++);
1216                 Assert(fontnum<MAX_OPEN_FONTS); //did we find slot?
1217
1218                 open_font[fontnum].ptr = NULL;
1219
1220                 if ( font->ft_chars )
1221                         d_free( font->ft_chars );
1222                 d_free( font );
1223
1224         }
1225 }
1226
1227 //remap (by re-reading) all the color fonts
1228 void gr_remap_color_fonts()
1229 {
1230         int fontnum;
1231
1232         for (fontnum=0;fontnum<MAX_OPEN_FONTS;fontnum++) {
1233                 grs_font *font;
1234
1235                 font = open_font[fontnum].ptr;
1236
1237                 if (font && (font->ft_flags & FT_COLOR))
1238                         gr_remap_font(font,open_font[fontnum].filename);
1239         }
1240 }
1241
1242 void build_colormap_good( ubyte * palette, ubyte * colormap, int * freq );
1243 void decode_data_asm(ubyte *data, int num_pixels, ubyte * colormap, int * count );
1244 #ifdef __WATCOMC__
1245 #pragma aux decode_data_asm parm [esi] [ecx] [edi] [ebx] modify exact [esi edi eax ebx ecx] = \
1246 "again_ddn:"                                                    \
1247         "xor    eax,eax"                                \
1248         "mov    al,[esi]"                       \
1249         "inc    dword ptr [ebx+eax*4]"          \
1250         "mov    al,[edi+eax]"           \
1251         "mov    [esi],al"                       \
1252         "inc    esi"                                    \
1253         "dec    ecx"                                    \
1254         "jne    again_ddn"
1255
1256 #endif
1257
1258 grs_font * gr_init_font( char * fontname )
1259 {
1260         static int first_time=1;
1261         grs_font *font;
1262         int i,fontnum;
1263         unsigned char * ptr;
1264         int nchars;
1265         CFILE *fontfile;
1266         char file_id[4];
1267         int datasize;           //size up to (but not including) palette
1268
1269         if (first_time) {
1270                 int i;
1271                 for (i=0;i<MAX_OPEN_FONTS;i++)
1272                         open_font[i].ptr = NULL;
1273                 first_time=0;
1274         }
1275
1276         //find free font slot
1277         for (fontnum=0;fontnum<MAX_OPEN_FONTS && open_font[fontnum].ptr!=NULL;fontnum++);
1278         Assert(fontnum<MAX_OPEN_FONTS); //did we find one?
1279
1280         strncpy(open_font[fontnum].filename,fontname,FILENAME_LEN);
1281
1282         fontfile = cfopen(fontname, "rb");
1283
1284         if (!fontfile)
1285                 Error( "Can't open font file %s", fontname );
1286
1287         cfread( file_id, 1, 4, fontfile );
1288         datasize = cfile_read_int(fontfile);
1289         
1290
1291         if ((file_id[0] != 'P') ||
1292             (file_id[1] != 'S') ||
1293             (file_id[2] != 'F') ||
1294             (file_id[3] != 'N'))
1295                 Error( "File %s is not a font file", fontname );
1296
1297         font = (grs_font *) d_malloc(datasize);
1298
1299         open_font[fontnum].ptr = font;
1300
1301         cfread(font,1,datasize,fontfile);
1302
1303 #ifdef MACINTOSH
1304 // gotta translate those endian things
1305
1306         font->ft_w = SWAPSHORT(font->ft_w);
1307         font->ft_h = SWAPSHORT(font->ft_h);
1308         font->ft_flags = SWAPSHORT(font->ft_flags);
1309         font->ft_bytewidth = SWAPSHORT(font->ft_bytewidth);
1310         font->ft_data = (ubyte *)SWAPINT((int)(font->ft_data));
1311         font->ft_chars = (ubyte **)SWAPINT((int)(font->ft_chars));
1312         font->ft_widths = (short *)SWAPINT((int)(font->ft_widths));
1313         font->ft_kerndata = (ubyte *)SWAPINT((int)(font->ft_kerndata));
1314 #endif
1315
1316         nchars = font->ft_maxchar-font->ft_minchar+1;
1317
1318         if (font->ft_flags & FT_PROPORTIONAL) {
1319
1320                 font->ft_widths = (short *) (((int) font->ft_widths) + ((ubyte *) font));
1321
1322 #ifdef MACINTOSH
1323                 for (i = 0; i < nchars; i++)
1324                         font->ft_widths[i] = SWAPSHORT(font->ft_widths[i]);
1325 #endif
1326
1327                 font->ft_data = ((int) font->ft_data) + ((ubyte *) font);
1328
1329                 font->ft_chars = (unsigned char **)d_malloc( nchars * sizeof(unsigned char *));
1330
1331                 ptr = font->ft_data;
1332
1333                 for (i=0; i< nchars; i++ ) {
1334                         font->ft_chars[i] = ptr;
1335                         if (font->ft_flags & FT_COLOR)
1336                                 ptr += font->ft_widths[i] * font->ft_h;
1337                         else
1338                                 ptr += BITS_TO_BYTES(font->ft_widths[i]) * font->ft_h;
1339                 }
1340
1341         } else  {
1342
1343                 font->ft_data = ((unsigned char *) font) + sizeof(*font);
1344
1345                 font->ft_chars  = NULL;
1346                 font->ft_widths = NULL;
1347
1348                 ptr = font->ft_data + (nchars * font->ft_w * font->ft_h);
1349         }
1350
1351         if (font->ft_flags & FT_KERNED)
1352                 font->ft_kerndata = ((int) font->ft_kerndata) + ((ubyte *) font);
1353
1354
1355         if (font->ft_flags & FT_COLOR) {                //remap palette
1356                 ubyte palette[256*3];
1357                 ubyte colormap[256];
1358                 int freq[256];
1359
1360                 cfread(palette,3,256,fontfile);         //read the palette
1361
1362 #ifdef MACINTOSH                        // swap the first and last palette entries (black and white)
1363                 {
1364                         int i;
1365                         ubyte c;
1366
1367                         for (i = 0; i < 3; i++) {
1368                                 c = palette[i];
1369                                 palette[i] = palette[765+i];
1370                                 palette[765+i] = c;
1371                         }
1372
1373 //  we also need to swap the data entries as well.  black is white and white is black
1374
1375                         for (i = 0; i < ptr-font->ft_data; i++) {
1376                                 if (font->ft_data[i] == 0)
1377                                         font->ft_data[i] = 255;
1378                                 else if (font->ft_data[i] == 255)
1379                                         font->ft_data[i] = 0;
1380                         }
1381
1382                 }
1383 #endif
1384
1385                 build_colormap_good( (ubyte *)&palette, colormap, freq );
1386
1387                 colormap[TRANSPARENCY_COLOR] = TRANSPARENCY_COLOR;              // chaged from colormap[255] = 255 to this for macintosh
1388
1389                 decode_data_asm(font->ft_data, ptr-font->ft_data, colormap, freq );
1390
1391         }
1392
1393         cfclose(fontfile);
1394
1395         //set curcanv vars
1396
1397         FONT        = font;
1398         FG_COLOR    = 0;
1399         BG_COLOR    = 0;
1400
1401         return font;
1402
1403 }
1404
1405 //remap a font by re-reading its data & palette
1406 void gr_remap_font( grs_font *font, char * fontname )
1407 {
1408         int i;
1409         int nchars;
1410         CFILE *fontfile;
1411         char file_id[4];
1412         int datasize;           //size up to (but not including) palette
1413         int data_ofs,data_len;
1414
1415         if (! (font->ft_flags & FT_COLOR))
1416                 return;
1417
1418         fontfile = cfopen(fontname, "rb");
1419
1420         if (!fontfile)
1421                 Error( "Can't open font file %s", fontname );
1422
1423         cfread( file_id, 1, 4, fontfile );
1424         datasize = cfile_read_int(fontfile);
1425         
1426
1427         if ((file_id[0] != 'P') ||
1428             (file_id[1] != 'S') ||
1429             (file_id[2] != 'F') ||
1430             (file_id[3] != 'N'))
1431                 Error( "File %s is not a font file", fontname );
1432
1433         nchars = font->ft_maxchar-font->ft_minchar+1;
1434
1435         //compute data length
1436         data_len = 0;
1437         if (font->ft_flags & FT_PROPORTIONAL) {
1438
1439                 for (i=0; i< nchars; i++ ) {
1440                         if (font->ft_flags & FT_COLOR)
1441                                 data_len += font->ft_widths[i] * font->ft_h;
1442                         else
1443                                 data_len += BITS_TO_BYTES(font->ft_widths[i]) * font->ft_h;
1444                 }
1445
1446         } else
1447                 data_len = nchars * font->ft_w * font->ft_h;
1448
1449         data_ofs = font->ft_data - ((ubyte *) font);
1450
1451         cfseek(fontfile,data_ofs,SEEK_CUR);
1452         cfread(font->ft_data,1,data_len,fontfile);              //read raw data
1453
1454         if (font->ft_flags & FT_COLOR) {                //remap palette
1455                 ubyte palette[256*3];
1456                 ubyte colormap[256];
1457                 int freq[256];
1458
1459                 cfseek(fontfile,-sizeof(palette),SEEK_END);
1460
1461                 cfread(palette,3,256,fontfile);         //read the palette
1462
1463 #ifdef MACINTOSH                        // swap the first and last palette entries (black and white)
1464                 {
1465                         int i;
1466                         ubyte c;
1467
1468                         for (i = 0; i < 3; i++) {
1469                                 c = palette[i];
1470                                 palette[i] = palette[765+i];
1471                                 palette[765+i] = c;
1472                         }
1473
1474 //  we also need to swap the data entries as well.  black is white and white is black
1475
1476                         for (i = 0; i < data_len; i++) {
1477                                 if (font->ft_data[i] == 0)
1478                                         font->ft_data[i] = 255;
1479                                 else if (font->ft_data[i] == 255)
1480                                         font->ft_data[i] = 0;
1481                         }
1482
1483                 }
1484 #endif
1485
1486                 build_colormap_good( (ubyte *)&palette, colormap, freq );
1487
1488                 colormap[TRANSPARENCY_COLOR] = TRANSPARENCY_COLOR;      // changed from         colormap[255] = 255;
1489
1490                 decode_data_asm(font->ft_data, data_len, colormap, freq );
1491
1492
1493         }
1494
1495         cfclose(fontfile);
1496 }
1497
1498
1499 void gr_set_fontcolor( int fg, int bg )
1500 {
1501         FG_COLOR    = fg;
1502         BG_COLOR    = bg;
1503 }
1504
1505 void gr_set_curfont( grs_font * new )
1506 {
1507         FONT = new;
1508 }
1509
1510
1511 int gr_internal_string_clipped(int x, int y, char *s )
1512 {
1513         unsigned char * fp;
1514         char * text_ptr, * next_row, * text_ptr1;
1515         int r, BitMask, i, bits, width, spacing, letter, underline;
1516         int x1 = x, last_x;
1517
1518         next_row = s;
1519
1520         while (next_row != NULL )
1521         {
1522                 text_ptr1 = next_row;
1523                 next_row = NULL;
1524
1525                 x = x1;
1526                 if (x==0x8000)                  //centered
1527                         x = get_centered_x(text_ptr1);
1528
1529                 last_x = x;
1530
1531                 for (r=0; r<FHEIGHT; r++)       {
1532                         text_ptr = text_ptr1;
1533                         x = last_x;
1534
1535                         while (*text_ptr)       {
1536                                 if (*text_ptr == '\n' ) {
1537                                         next_row = &text_ptr[1];
1538                                         break;
1539                                 }
1540
1541                                 if (*text_ptr == CC_COLOR) {
1542                                         FG_COLOR = *(text_ptr+1);
1543                                         text_ptr += 2;
1544                                         continue;
1545                                 }
1546
1547                                 if (*text_ptr == CC_LSPACING) {
1548                                         Int3(); //      Warning: skip lines not supported for clipped strings.
1549                                         text_ptr += 2;
1550                                         continue;
1551                                 }
1552
1553                                 underline = 0;
1554                                 if (*text_ptr == CC_UNDERLINE ) {
1555                                         if ((r==FBASELINE+2) || (r==FBASELINE+3))
1556                                                 underline = 1;
1557                                         text_ptr++;
1558                                 }
1559
1560                                 get_char_width(text_ptr[0],text_ptr[1],&width,&spacing);
1561
1562                                 letter = *text_ptr-FMINCHAR;
1563
1564                                 if (!INFONT(letter)) {  //not in font, draw as space
1565                                         x += spacing;
1566                                         text_ptr++;
1567                                         continue;
1568                                 }
1569
1570                                 if (FFLAGS & FT_PROPORTIONAL)
1571                                         fp = FCHARS[letter];
1572                                 else
1573                                         fp = FDATA + letter * BITS_TO_BYTES(width)*FHEIGHT;
1574
1575                                 if (underline)  {
1576                                         for (i=0; i< width; i++ )       {
1577                                                 gr_setcolor(FG_COLOR);
1578                                                 gr_pixel( x++, y );
1579                                         }
1580                                 } else {
1581                                         fp += BITS_TO_BYTES(width)*r;
1582
1583                                         BitMask = 0;
1584
1585                                         for (i=0; i< width; i++ )       {
1586                                                 if (BitMask==0) {
1587                                                         bits = *fp++;
1588                                                         BitMask = 0x80;
1589                                                 }
1590                                                 if (bits & BitMask)
1591                                                         gr_setcolor(FG_COLOR);
1592                                                 else
1593                                                         gr_setcolor(BG_COLOR);
1594                                                 gr_pixel( x++, y );
1595                                                 BitMask >>= 1;
1596                                         }
1597                                 }
1598
1599                                 x += spacing-width;             //for kerning
1600
1601                                 text_ptr++;
1602                         }
1603                         y++;
1604                 }
1605         }
1606         return 0;
1607 }
1608
1609 int gr_internal_string_clipped_m(int x, int y, char *s )
1610 {
1611         unsigned char * fp;
1612         char * text_ptr, * next_row, * text_ptr1;
1613         int r, BitMask, i, bits, width, spacing, letter, underline;
1614         int x1 = x, last_x;
1615
1616         next_row = s;
1617
1618         while (next_row != NULL )
1619         {
1620                 text_ptr1 = next_row;
1621                 next_row = NULL;
1622
1623                 x = x1;
1624                 if (x==0x8000)                  //centered
1625                         x = get_centered_x(text_ptr1);
1626
1627                 last_x = x;
1628
1629                 for (r=0; r<FHEIGHT; r++)       {
1630                         x = last_x;
1631
1632                         text_ptr = text_ptr1;
1633
1634                         while (*text_ptr)       {
1635                                 if (*text_ptr == '\n' ) {
1636                                         next_row = &text_ptr[1];
1637                                         break;
1638                                 }
1639
1640                                 if (*text_ptr == CC_COLOR) {
1641                                         FG_COLOR = *(text_ptr+1);
1642                                         text_ptr += 2;
1643                                         continue;
1644                                 }
1645
1646                                 if (*text_ptr == CC_LSPACING) {
1647                                         Int3(); //      Warning: skip lines not supported for clipped strings.
1648                                         text_ptr += 2;
1649                                         continue;
1650                                 }
1651
1652                                 underline = 0;
1653                                 if (*text_ptr == CC_UNDERLINE ) {
1654                                         if ((r==FBASELINE+2) || (r==FBASELINE+3))
1655                                                 underline = 1;
1656                                         text_ptr++;
1657                                 }
1658
1659                                 get_char_width(text_ptr[0],text_ptr[1],&width,&spacing);
1660
1661                                 letter = *text_ptr-FMINCHAR;
1662
1663                                 if (!INFONT(letter)) {  //not in font, draw as space
1664                                         x += spacing;
1665                                         text_ptr++;
1666                                         continue;
1667                                 }
1668
1669                                 if (FFLAGS & FT_PROPORTIONAL)
1670                                         fp = FCHARS[letter];
1671                                 else
1672                                         fp = FDATA + letter * BITS_TO_BYTES(width)*FHEIGHT;
1673
1674                                 if (underline)  {
1675                                         for (i=0; i< width; i++ )       {
1676                                                 gr_setcolor(FG_COLOR);
1677                                                 gr_pixel( x++, y );
1678                                         }
1679                                 } else {
1680                                         fp += BITS_TO_BYTES(width)*r;
1681
1682                                         BitMask = 0;
1683
1684                                         for (i=0; i< width; i++ )       {
1685                                                 if (BitMask==0) {
1686                                                         bits = *fp++;
1687                                                         BitMask = 0x80;
1688                                                 }
1689                                                 if (bits & BitMask)     {
1690                                                         gr_setcolor(FG_COLOR);
1691                                                         gr_pixel( x++, y );
1692                                                 } else {
1693                                                         x++;
1694                                                 }
1695                                                 BitMask >>= 1;
1696                                         }
1697                                 }
1698
1699                                 x += spacing-width;             //for kerning
1700
1701                                 text_ptr++;
1702                         }
1703                         y++;
1704                 }
1705         }
1706         return 0;
1707 }