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