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