This commit was manufactured by cvs2svn to create tag 'd2x-0_1_2'.
[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 /* $Source: /cvs/cvsroot/d2x/2d/font.c,v $
15  * $Revision: 1.10 $
16  * $Author: bradleyb $
17  * $Date: 2001-11-14 09:34:32 $
18  *
19  * Graphical routines for drawing fonts.
20  *
21  * $Log: not supported by cvs2svn $
22  * Revision 1.9  2001/11/08 10:37:25  bradleyb
23  * free OGL font data when rereading
24  *
25  * Revision 1.8  2001/11/04 03:58:25  bradleyb
26  * re-init ogl fonts after remapping colors.
27  *
28  * Revision 1.7  2001/11/02 10:46:23  bradleyb
29  * fixed gr_remap_font, minor stuff
30  *
31  * Revision 1.6  2001/11/02 02:03:35  bradleyb
32  * Enable OpenGL fonts\!
33  *
34  *
35  */
36
37 #ifdef HAVE_CONFIG_H
38 #include <conf.h>
39 #endif
40
41 #include <stdarg.h>
42 #include <stdio.h>
43 #include <stdlib.h>
44 #include <string.h>
45
46 #include <fcntl.h>
47 #include <unistd.h>
48
49 #include "pa_enabl.h"                   //$$POLY_ACC
50 #include "u_mem.h"
51
52 #include "gr.h"
53 #include "grdef.h"
54 #include "error.h"
55
56 #include "cfile.h"
57 #include "mono.h"
58 #include "byteswap.h"
59 #include "bitmap.h"
60
61 #if defined(POLY_ACC)
62 #include "poly_acc.h"
63 #endif
64
65 #include "makesig.h"
66
67 #define MAX_OPEN_FONTS  50
68 #define FILENAME_LEN            13
69
70 typedef struct openfont {
71         char filename[FILENAME_LEN];
72         grs_font *ptr;
73 } openfont;
74
75 //list of open fonts, for use (for now) for palette remapping
76 openfont open_font[MAX_OPEN_FONTS];
77
78 #define FONT        grd_curcanv->cv_font
79 #define FG_COLOR    grd_curcanv->cv_font_fg_color
80 #define BG_COLOR    grd_curcanv->cv_font_bg_color
81 #define FWIDTH       FONT->ft_w
82 #define FHEIGHT      FONT->ft_h
83 #define FBASELINE    FONT->ft_baseline
84 #define FFLAGS       FONT->ft_flags
85 #define FMINCHAR     FONT->ft_minchar
86 #define FMAXCHAR     FONT->ft_maxchar
87 #define FDATA        FONT->ft_data
88 #define FCHARS       FONT->ft_chars
89 #define FWIDTHS      FONT->ft_widths
90
91 #define BITS_TO_BYTES(x)    (((x)+7)>>3)
92
93 int gr_internal_string_clipped(int x, int y, char *s );
94 int gr_internal_string_clipped_m(int x, int y, char *s );
95
96 ubyte *find_kern_entry(grs_font *font,ubyte first,ubyte second)
97 {
98         ubyte *p=font->ft_kerndata;
99
100         while (*p!=255)
101                 if (p[0]==first && p[1]==second)
102                         return p;
103                 else p+=3;
104
105         return NULL;
106
107 }
108
109 //takes the character AFTER being offset into font
110 #define INFONT(_c) ((_c >= 0) && (_c <= FMAXCHAR-FMINCHAR))
111
112 //takes the character BEFORE being offset into current font
113 void get_char_width(ubyte c,ubyte c2,int *width,int *spacing)
114 {
115         int letter;
116
117         letter = c-FMINCHAR;
118
119         if (!INFONT(letter)) {                          //not in font, draw as space
120                 *width=0;
121                 if (FFLAGS & FT_PROPORTIONAL)
122                         *spacing = FWIDTH/2;
123                 else
124                         *spacing = FWIDTH;
125                 return;
126         }
127
128         if (FFLAGS & FT_PROPORTIONAL)
129                 *width = FWIDTHS[letter];
130         else
131                 *width = FWIDTH;
132
133         *spacing = *width;
134
135         if (FFLAGS & FT_KERNED)  {
136                 ubyte *p;
137
138                 if (!(c2==0 || c2=='\n')) {
139                         int letter2;
140
141                         letter2 = c2-FMINCHAR;
142
143                         if (INFONT(letter2)) {
144
145                                 p = find_kern_entry(FONT,(ubyte)letter,letter2);
146
147                                 if (p)
148                                         *spacing = p[2];
149                         }
150                 }
151         }
152 }
153
154 int get_centered_x(char *s)
155 {
156         int w,w2,s2;
157
158         for (w=0;*s!=0 && *s!='\n';s++) {
159                 if (*s<=0x06) {
160                         if (*s<=0x03)
161                                 s++;
162                         continue;//skip color codes.
163                 }
164                 get_char_width(s[0],s[1],&w2,&s2);
165                 w += s2;
166         }
167
168         return ((grd_curcanv->cv_bitmap.bm_w - w) / 2);
169 }
170
171 //hack to allow color codes to be embedded in strings -MPM
172 //note we subtract one from color, since 255 is "transparent" so it'll never be used, and 0 would otherwise end the string.
173 //function must already have orig_color var set (or they could be passed as args...)
174 //perhaps some sort of recursive orig_color type thing would be better, but that would be way too much trouble for little gain
175 int gr_message_color_level=1;
176 #define CHECK_EMBEDDED_COLORS() if ((*text_ptr >= 0x01) && (*text_ptr <= 0x03)) { \
177                 text_ptr++; \
178                 if (*text_ptr){ \
179                         if (gr_message_color_level >= *(text_ptr-1)) \
180                                 FG_COLOR = *text_ptr - 1; \
181                         text_ptr++; \
182                 } \
183         } \
184         else if ((*text_ptr >= 0x04) && (*text_ptr <= 0x06)){ \
185                 if (gr_message_color_level >= *text_ptr - 3) \
186                         FG_COLOR=orig_color; \
187                 text_ptr++; \
188         }
189
190 int gr_internal_string0(int x, int y, char *s )
191 {
192         unsigned char * fp;
193         ubyte * text_ptr, * next_row, * text_ptr1;
194         int r, BitMask, i, bits, width, spacing, letter, underline;
195         int     skip_lines = 0;
196
197         unsigned int VideoOffset, VideoOffset1;
198
199         bits=0;
200
201         VideoOffset1 = y * ROWSIZE + x;
202
203         next_row = s;
204
205         while (next_row != NULL )
206         {
207                 text_ptr1 = next_row;
208                 next_row = NULL;
209
210                 if (x==0x8000) {                        //centered
211                         int xx = get_centered_x(text_ptr1);
212                         VideoOffset1 = y * ROWSIZE + xx;
213                 }
214
215                 for (r=0; r<FHEIGHT; r++)
216                 {
217
218                         text_ptr = text_ptr1;
219
220                         VideoOffset = VideoOffset1;
221
222                         while (*text_ptr)
223                         {
224                                 if (*text_ptr == '\n' )
225                                 {
226                                         next_row = &text_ptr[1];
227                                         break;
228                                 }
229
230                                 if (*text_ptr == CC_COLOR) {
231                                         FG_COLOR = *(text_ptr+1);
232                                         text_ptr += 2;
233                                         continue;
234                                 }
235
236                                 if (*text_ptr == CC_LSPACING) {
237                                         skip_lines = *(text_ptr+1) - '0';
238                                         text_ptr += 2;
239                                         continue;
240                                 }
241
242                                 underline = 0;
243                                 if (*text_ptr == CC_UNDERLINE )
244                                 {
245                                         if ((r==FBASELINE+2) || (r==FBASELINE+3))
246                                                 underline = 1;
247                                         text_ptr++;
248                                 }
249
250                                 get_char_width(text_ptr[0],text_ptr[1],&width,&spacing);
251
252                                 letter = *text_ptr-FMINCHAR;
253
254                                 if (!INFONT(letter)) {  //not in font, draw as space
255                                         VideoOffset += spacing;
256                                         text_ptr++;
257                                         continue;
258                                 }
259
260                                 if (FFLAGS & FT_PROPORTIONAL)
261                                         fp = FCHARS[letter];
262                                 else
263                                         fp = FDATA + letter * BITS_TO_BYTES(width)*FHEIGHT;
264
265                                 if (underline)
266                                         for (i=0; i< width; i++ )
267                                                 DATA[VideoOffset++] = (unsigned char) FG_COLOR;
268                                 else
269                                 {
270                                         fp += BITS_TO_BYTES(width)*r;
271
272                                         BitMask = 0;
273
274                                         for (i=0; i< width; i++ )
275                                         {
276                                                 if (BitMask==0) {
277                                                         bits = *fp++;
278                                                         BitMask = 0x80;
279                                                 }
280
281                                                 if (bits & BitMask)
282                                                         DATA[VideoOffset++] = (unsigned char) FG_COLOR;
283                                                 else
284                                                         DATA[VideoOffset++] = (unsigned char) BG_COLOR;
285                                                 BitMask >>= 1;
286                                         }
287                                 }
288
289                                 VideoOffset += spacing-width;           //for kerning
290
291                                 text_ptr++;
292                         }
293
294                         VideoOffset1 += ROWSIZE; y++;
295                 }
296
297                 y += skip_lines;
298                 VideoOffset1 += ROWSIZE * skip_lines;
299                 skip_lines = 0;
300         }
301         return 0;
302 }
303
304 int gr_internal_string0m(int x, int y, char *s )
305 {
306         unsigned char * fp;
307         ubyte * text_ptr, * next_row, * text_ptr1;
308         int r, BitMask, i, bits, width, spacing, letter, underline;
309         int     skip_lines = 0;
310
311         unsigned int VideoOffset, VideoOffset1;
312
313         int orig_color=FG_COLOR;//to allow easy reseting to default string color with colored strings -MPM
314
315         bits=0;
316
317         VideoOffset1 = y * ROWSIZE + x;
318
319         next_row = s;
320
321         while (next_row != NULL )
322         {
323                 text_ptr1 = next_row;
324                 next_row = NULL;
325
326                 if (x==0x8000) {                        //centered
327                         int xx = get_centered_x(text_ptr1);
328                         VideoOffset1 = y * ROWSIZE + xx;
329                 }
330
331                 for (r=0; r<FHEIGHT; r++)
332                 {
333
334                         text_ptr = text_ptr1;
335
336                         VideoOffset = VideoOffset1;
337
338                         while (*text_ptr)
339                         {
340                                 if (*text_ptr == '\n' )
341                                 {
342                                         next_row = &text_ptr[1];
343                                         break;
344                                 }
345
346                                 if (*text_ptr == CC_COLOR) {
347                                         FG_COLOR = *(text_ptr+1);
348                                         text_ptr += 2;
349                                         continue;
350                                 }
351
352                                 if (*text_ptr == CC_LSPACING) {
353                                         skip_lines = *(text_ptr+1) - '0';
354                                         text_ptr += 2;
355                                         continue;
356                                 }
357
358                                 underline = 0;
359                                 if (*text_ptr == CC_UNDERLINE )
360                                 {
361                                         if ((r==FBASELINE+2) || (r==FBASELINE+3))
362                                                 underline = 1;
363                                         text_ptr++;
364                                 }
365
366                                 get_char_width(text_ptr[0],text_ptr[1],&width,&spacing);
367
368                                 letter = *text_ptr-FMINCHAR;
369
370                                 if (!INFONT(letter) || *text_ptr<=0x06) {       //not in font, draw as space
371                                         CHECK_EMBEDDED_COLORS() else{
372                                                 VideoOffset += spacing;
373                                                 text_ptr++;
374                                         }
375                                         continue;
376                                 }
377
378                                 if (FFLAGS & FT_PROPORTIONAL)
379                                         fp = FCHARS[letter];
380                                 else
381                                         fp = FDATA + letter * BITS_TO_BYTES(width)*FHEIGHT;
382
383                                 if (underline)
384                                         for (i=0; i< width; i++ )
385                                                 DATA[VideoOffset++] = (unsigned int) FG_COLOR;
386                                 else
387                                 {
388                                         fp += BITS_TO_BYTES(width)*r;
389
390                                         BitMask = 0;
391
392                                         for (i=0; i< width; i++ )
393                                         {
394                                                 if (BitMask==0) {
395                                                         bits = *fp++;
396                                                         BitMask = 0x80;
397                                                 }
398
399                                                 if (bits & BitMask)
400                                                         DATA[VideoOffset++] = (unsigned int) FG_COLOR;
401                                                 else
402                                                         VideoOffset++;
403                                                 BitMask >>= 1;
404                                         }
405                                 }
406                                 text_ptr++;
407
408                                 VideoOffset += spacing-width;
409                         }
410
411                         VideoOffset1 += ROWSIZE;
412                         y++;
413                 }
414                 y += skip_lines;
415                 VideoOffset1 += ROWSIZE * skip_lines;
416                 skip_lines = 0;
417         }
418         return 0;
419 }
420
421 #ifdef __MSDOS__
422 int gr_internal_string2(int x, int y, char *s )
423 {
424         unsigned char * fp;
425         ubyte * text_ptr, * next_row, * text_ptr1;
426         int r, BitMask, i, bits, width, spacing, letter, underline;
427         int page_switched, skip_lines = 0;
428
429         unsigned int VideoOffset, VideoOffset1;
430
431         VideoOffset1 = (size_t)DATA + y * ROWSIZE + x;
432
433         bits = 0;
434
435         gr_vesa_setpage(VideoOffset1 >> 16);
436
437         VideoOffset1 &= 0xFFFF;
438
439         next_row = s;
440
441         while (next_row != NULL )
442         {
443                 text_ptr1 = next_row;
444                 next_row = NULL;
445
446                 if (x==0x8000) {                        //centered
447                         int xx = get_centered_x(text_ptr1);
448                         VideoOffset1 = y * ROWSIZE + xx;
449                         gr_vesa_setpage(VideoOffset1 >> 16);
450                         VideoOffset1 &= 0xFFFF;
451                 }
452
453                 for (r=0; r<FHEIGHT; r++)
454                 {
455                         text_ptr = text_ptr1;
456
457                         VideoOffset = VideoOffset1;
458
459                         page_switched = 0;
460
461                         while (*text_ptr)
462                         {
463                                 if (*text_ptr == '\n' )
464                                 {
465                                         next_row = &text_ptr[1];
466                                         break;
467                                 }
468
469                                 if (*text_ptr == CC_COLOR) {
470                                         FG_COLOR = *(text_ptr+1);
471                                         text_ptr += 2;
472                                         continue;
473                                 }
474
475                                 if (*text_ptr == CC_LSPACING) {
476                                         skip_lines = *(text_ptr+1) - '0';
477                                         text_ptr += 2;
478                                         continue;
479                                 }
480
481                                 underline = 0;
482                                 if (*text_ptr == CC_UNDERLINE )
483                                 {
484                                         if ((r==FBASELINE+2) || (r==FBASELINE+3))
485                                                 underline = 1;
486                                         text_ptr++;
487                                 }
488
489                                 get_char_width(text_ptr[0],text_ptr[1],&width,&spacing);
490
491                                 Assert(width==spacing);         //no kerning support here
492
493                                 letter = *text_ptr-FMINCHAR;
494
495                                 if (!INFONT(letter)) {  //not in font, draw as space
496                                         VideoOffset += spacing;
497                                         text_ptr++;
498                                         continue;
499                                 }
500
501                                 if (FFLAGS & FT_PROPORTIONAL)
502                                         fp = FCHARS[letter];
503                                 else
504                                         fp = FDATA + letter * BITS_TO_BYTES(width)*FHEIGHT;
505
506                                 if (underline)
507                                 {
508                                         if ( VideoOffset+width > 0xFFFF )
509                                         {
510                                                 for (i=0; i< width; i++ )
511                                                 {
512                                                         gr_video_memory[VideoOffset++] = FG_COLOR;
513
514                                                         if (VideoOffset > 0xFFFF )
515                                                         {
516                                                                 VideoOffset -= 0xFFFF + 1;
517                                                                 page_switched = 1;
518                                                                 gr_vesa_incpage();
519                                                         }
520                                                 }
521                                         }
522                                         else
523                                         {
524                                                 for (i=0; i< width; i++ )
525                                                         gr_video_memory[VideoOffset++] = FG_COLOR;
526                                         }
527                                 }
528                                 else
529                                 {
530                                         // fp -- dword
531                                         // VideoOffset
532                                         // width
533
534                                         fp += BITS_TO_BYTES(width)*r;
535
536                                         BitMask = 0;
537
538                                         if ( VideoOffset+width > 0xFFFF )
539                                         {
540                                                 for (i=0; i< width; i++ )
541                                                 {
542                                                         if (BitMask==0) {
543                                                                 bits = *fp++;
544                                                                 BitMask = 0x80;
545                                                         }
546
547                                                         if (bits & BitMask)
548                                                                 gr_video_memory[VideoOffset++] = FG_COLOR;
549                                                         else
550                                                                 gr_video_memory[VideoOffset++] = BG_COLOR;
551
552                                                         BitMask >>= 1;
553
554                                                         if (VideoOffset > 0xFFFF )
555                                                         {
556                                                                 VideoOffset -= 0xFFFF + 1;
557                                                                 page_switched = 1;
558                                                                 gr_vesa_incpage();
559                                                         }
560
561                                                 }
562                                         } else {
563
564                                                 if (width == 8 )
565                                                 {
566                                                         bits = *fp++;
567
568                                                         if (bits & 0x80) gr_video_memory[VideoOffset+0] = FG_COLOR;
569                                                         else gr_video_memory[VideoOffset+0] = BG_COLOR;
570
571                                                         if (bits & 0x40) gr_video_memory[VideoOffset+1] = FG_COLOR;
572                                                         else gr_video_memory[VideoOffset+1] = BG_COLOR;
573
574                                                         if (bits & 0x20) gr_video_memory[VideoOffset+2] = FG_COLOR;
575                                                         else gr_video_memory[VideoOffset+2] = BG_COLOR;
576
577                                                         if (bits & 0x10) gr_video_memory[VideoOffset+3] = FG_COLOR;
578                                                         else gr_video_memory[VideoOffset+3] = BG_COLOR;
579
580                                                         if (bits & 0x08) gr_video_memory[VideoOffset+4] = FG_COLOR;
581                                                         else gr_video_memory[VideoOffset+4] = BG_COLOR;
582
583                                                         if (bits & 0x04) gr_video_memory[VideoOffset+5] = FG_COLOR;
584                                                         else gr_video_memory[VideoOffset+5] = BG_COLOR;
585
586                                                         if (bits & 0x02) gr_video_memory[VideoOffset+6] = FG_COLOR;
587                                                         else gr_video_memory[VideoOffset+6] = BG_COLOR;
588
589                                                         if (bits & 0x01) gr_video_memory[VideoOffset+7] = FG_COLOR;
590                                                         else gr_video_memory[VideoOffset+7] = BG_COLOR;
591
592                                                         VideoOffset += 8;
593                                                 } else {
594                                                         for (i=0; i< width/2 ; i++ )
595                                                         {
596                                                                 if (BitMask==0) {
597                                                                         bits = *fp++;
598                                                                         BitMask = 0x80;
599                                                                 }
600
601                                                                 if (bits & BitMask)
602                                                                         gr_video_memory[VideoOffset++] = FG_COLOR;
603                                                                 else
604                                                                         gr_video_memory[VideoOffset++] = BG_COLOR;
605                                                                 BitMask >>= 1;
606
607
608                                                                 // Unroll twice
609
610                                                                 if (BitMask==0) {
611                                                                         bits = *fp++;
612                                                                         BitMask = 0x80;
613                                                                 }
614
615                                                                 if (bits & BitMask)
616                                                                         gr_video_memory[VideoOffset++] = FG_COLOR;
617                                                                 else
618                                                                         gr_video_memory[VideoOffset++] = BG_COLOR;
619                                                                 BitMask >>= 1;
620                                                         }
621                                                 }
622                                         }
623                                 }
624                                 text_ptr++;
625                         }
626
627                         y ++;
628                         VideoOffset1 += ROWSIZE;
629
630                         if (VideoOffset1 > 0xFFFF ) {
631                                 VideoOffset1 -= 0xFFFF + 1;
632                                 if (!page_switched)
633                                         gr_vesa_incpage();
634                         }
635                 }
636
637                 y += skip_lines;
638                 VideoOffset1 += ROWSIZE * skip_lines;
639                 skip_lines = 0;
640         }
641         return 0;
642 }
643
644 int gr_internal_string2m(int x, int y, char *s )
645 {
646         unsigned char * fp;
647         char * text_ptr, * next_row, * text_ptr1;
648         int r, BitMask, i, bits, width, spacing, letter, underline;
649         int page_switched, skip_lines = 0;
650
651         unsigned int VideoOffset, VideoOffset1;
652
653         VideoOffset1 = (size_t)DATA + y * ROWSIZE + x;
654
655         gr_vesa_setpage(VideoOffset1 >> 16);
656
657         VideoOffset1 &= 0xFFFF;
658
659         next_row = s;
660
661         while (next_row != NULL )
662         {
663                 text_ptr1 = next_row;
664                 next_row = NULL;
665
666                 if (x==0x8000) {                        //centered
667                         int xx = get_centered_x(text_ptr1);
668                         VideoOffset1 = y * ROWSIZE + xx;
669                         gr_vesa_setpage(VideoOffset1 >> 16);
670                         VideoOffset1 &= 0xFFFF;
671                 }
672
673                 for (r=0; r<FHEIGHT; r++)
674                 {
675                         text_ptr = text_ptr1;
676
677                         VideoOffset = VideoOffset1;
678
679                         page_switched = 0;
680
681                         while (*text_ptr)
682                         {
683                                 if (*text_ptr == '\n' )
684                                 {
685                                         next_row = &text_ptr[1];
686                                         break;
687                                 }
688
689                                 if (*text_ptr == CC_COLOR) {
690                                         FG_COLOR = *(text_ptr+1);
691                                         text_ptr += 2;
692                                         continue;
693                                 }
694
695                                 if (*text_ptr == CC_LSPACING) {
696                                         skip_lines = *(text_ptr+1) - '0';
697                                         text_ptr += 2;
698                                         continue;
699                                 }
700
701                                 underline = 0;
702                                 if (*text_ptr == CC_UNDERLINE )
703                                 {
704                                         if ((r==FBASELINE+2) || (r==FBASELINE+3))
705                                                 underline = 1;
706                                         text_ptr++;
707                                 }
708
709                                 get_char_width(text_ptr[0],text_ptr[1],&width,&spacing);
710
711                                 letter = *text_ptr-FMINCHAR;
712
713                                 if (!INFONT(letter)) {  //not in font, draw as space
714                                         VideoOffset += width;
715                                         text_ptr++;
716                                         continue;
717                                 }
718
719                                 if (FFLAGS & FT_PROPORTIONAL)
720                                         fp = FCHARS[letter];
721                                 else
722                                         fp = FDATA + letter * BITS_TO_BYTES(width)*FHEIGHT;
723
724                                 if (underline)
725                                 {
726                                         if ( VideoOffset+width > 0xFFFF )
727                                         {
728                                                 for (i=0; i< width; i++ )
729                                                 {
730                                                         gr_video_memory[VideoOffset++] = FG_COLOR;
731
732                                                         if (VideoOffset > 0xFFFF )
733                                                         {
734                                                                 VideoOffset -= 0xFFFF + 1;
735                                                                 page_switched = 1;
736                                                                 gr_vesa_incpage();
737                                                         }
738                                                 }
739                                         }
740                                         else
741                                         {
742                                                 for (i=0; i< width; i++ )
743                                                         gr_video_memory[VideoOffset++] = FG_COLOR;
744                                         }
745                                 }
746                                 else
747                                 {
748                                         fp += BITS_TO_BYTES(width)*r;
749
750                                         BitMask = 0;
751
752                                         if ( VideoOffset+width > 0xFFFF )
753                                         {
754                                                 for (i=0; i< width; i++ )
755                                                 {
756                                                         if (BitMask==0) {
757                                                                 bits = *fp++;
758                                                                 BitMask = 0x80;
759                                                         }
760
761                                                         if (bits & BitMask)
762                                                                 gr_video_memory[VideoOffset++] = FG_COLOR;
763                                                         else
764                                                                 VideoOffset++;
765
766                                                         BitMask >>= 1;
767
768                                                         if (VideoOffset > 0xFFFF )
769                                                         {
770                                                                 VideoOffset -= 0xFFFF + 1;
771                                                                 page_switched = 1;
772                                                                 gr_vesa_incpage();
773                                                         }
774
775                                                 }
776                                         } else {
777                                                 for (i=0; i< width; i++ )
778                                                 {
779                                                         if (BitMask==0) {
780                                                                 bits = *fp++;
781                                                                 BitMask = 0x80;
782                                                         }
783
784                                                         if (bits & BitMask)
785                                                                 gr_video_memory[VideoOffset++] = FG_COLOR;
786                                                         else
787                                                                 VideoOffset++;;
788                                                         BitMask >>= 1;
789                                                 }
790                                         }
791                                 }
792                                 text_ptr++;
793
794                                 VideoOffset += spacing-width;
795                         }
796
797                         y ++;
798                         VideoOffset1 += ROWSIZE;
799
800                         if (VideoOffset1 > 0xFFFF ) {
801                                 VideoOffset1 -= 0xFFFF + 1;
802                                 if (!page_switched)
803                                         gr_vesa_incpage();
804                         }
805                 }
806
807                 y += skip_lines;
808                 VideoOffset1 += ROWSIZE * skip_lines;
809                 skip_lines = 0;
810         }
811         return 0;
812 }
813
814 #endif // __MSDOS__
815
816 #if defined(POLY_ACC)
817 int gr_internal_string5(int x, int y, char *s )
818 {
819         unsigned char * fp;
820         ubyte * text_ptr, * next_row, * text_ptr1;
821         int r, BitMask, i, bits, width, spacing, letter, underline;
822         int     skip_lines = 0;
823
824         unsigned int VideoOffset, VideoOffset1;
825
826     pa_flush();
827     VideoOffset1 = y * ROWSIZE + x * PA_BPP;
828
829         next_row = s;
830
831         while (next_row != NULL )
832         {
833                 text_ptr1 = next_row;
834                 next_row = NULL;
835
836                 if (x==0x8000) {                        //centered
837                         int xx = get_centered_x(text_ptr1);
838             VideoOffset1 = y * ROWSIZE + xx * PA_BPP;
839                 }
840
841                 for (r=0; r<FHEIGHT; r++)
842                 {
843
844                         text_ptr = text_ptr1;
845
846                         VideoOffset = VideoOffset1;
847
848                         while (*text_ptr)
849                         {
850                                 if (*text_ptr == '\n' )
851                                 {
852                                         next_row = &text_ptr[1];
853                                         break;
854                                 }
855
856                                 if (*text_ptr == CC_COLOR) {
857                                         FG_COLOR = *(text_ptr+1);
858                                         text_ptr += 2;
859                                         continue;
860                                 }
861
862                                 if (*text_ptr == CC_LSPACING) {
863                                         skip_lines = *(text_ptr+1) - '0';
864                                         text_ptr += 2;
865                                         continue;
866                                 }
867
868                                 underline = 0;
869                                 if (*text_ptr == CC_UNDERLINE )
870                                 {
871                                         if ((r==FBASELINE+2) || (r==FBASELINE+3))
872                                                 underline = 1;
873                                         text_ptr++;
874                                 }
875
876                                 get_char_width(text_ptr[0],text_ptr[1],&width,&spacing);
877
878                                 letter = *text_ptr-FMINCHAR;
879
880                                 if (!INFONT(letter)) {  //not in font, draw as space
881                     VideoOffset += spacing * PA_BPP;
882                                         text_ptr++;
883                                         continue;
884                                 }
885
886                                 if (FFLAGS & FT_PROPORTIONAL)
887                                         fp = FCHARS[letter];
888                                 else
889                                         fp = FDATA + letter * BITS_TO_BYTES(width)*FHEIGHT;
890
891                                 if (underline)
892                                         for (i=0; i< width; i++ )
893                     {    *(short *)(DATA + VideoOffset) = pa_clut[FG_COLOR]; VideoOffset += PA_BPP; }
894                                 else
895                                 {
896                                         fp += BITS_TO_BYTES(width)*r;
897
898                                         BitMask = 0;
899
900                                         for (i=0; i< width; i++ )
901                                         {
902                                                 if (BitMask==0) {
903                                                         bits = *fp++;
904                                                         BitMask = 0x80;
905                                                 }
906
907                                                 if (bits & BitMask)
908                         {    *(short *)(DATA + VideoOffset) = pa_clut[FG_COLOR]; VideoOffset += PA_BPP; }
909                         else
910                         {    *(short *)(DATA + VideoOffset) = pa_clut[BG_COLOR]; VideoOffset += PA_BPP; }
911                         BitMask >>= 1;
912                                         }
913                                 }
914
915                 VideoOffset += PA_BPP * (spacing-width);       //for kerning
916
917                                 text_ptr++;
918                         }
919
920                         VideoOffset1 += ROWSIZE; y++;
921                 }
922
923                 y += skip_lines;
924                 VideoOffset1 += ROWSIZE * skip_lines;
925                 skip_lines = 0;
926         }
927         return 0;
928 }
929
930 int gr_internal_string5m(int x, int y, char *s )
931 {
932         unsigned char * fp;
933         ubyte * text_ptr, * next_row, * text_ptr1;
934         int r, BitMask, i, bits, width, spacing, letter, underline;
935         int     skip_lines = 0;
936
937         unsigned int VideoOffset, VideoOffset1;
938
939     pa_flush();
940     VideoOffset1 = y * ROWSIZE + x * PA_BPP;
941
942         next_row = s;
943
944         while (next_row != NULL )
945         {
946                 text_ptr1 = next_row;
947                 next_row = NULL;
948
949                 if (x==0x8000) {                        //centered
950                         int xx = get_centered_x(text_ptr1);
951             VideoOffset1 = y * ROWSIZE + xx * PA_BPP;
952                 }
953
954                 for (r=0; r<FHEIGHT; r++)
955                 {
956
957                         text_ptr = text_ptr1;
958
959                         VideoOffset = VideoOffset1;
960
961                         while (*text_ptr)
962                         {
963                                 if (*text_ptr == '\n' )
964                                 {
965                                         next_row = &text_ptr[1];
966                                         break;
967                                 }
968
969                                 if (*text_ptr == CC_COLOR) {
970                                         FG_COLOR = *(text_ptr+1);
971                                         text_ptr += 2;
972                                         continue;
973                                 }
974
975                                 if (*text_ptr == CC_LSPACING) {
976                                         skip_lines = *(text_ptr+1) - '0';
977                                         text_ptr += 2;
978                                         continue;
979                                 }
980
981                                 underline = 0;
982                                 if (*text_ptr == CC_UNDERLINE )
983                                 {
984                                         if ((r==FBASELINE+2) || (r==FBASELINE+3))
985                                                 underline = 1;
986                                         text_ptr++;
987                                 }
988
989                                 get_char_width(text_ptr[0],text_ptr[1],&width,&spacing);
990
991                                 letter = *text_ptr-FMINCHAR;
992
993                                 if (!INFONT(letter)) {  //not in font, draw as space
994                     VideoOffset += spacing * PA_BPP;
995                                         text_ptr++;
996                                         continue;
997                                 }
998
999                                 if (FFLAGS & FT_PROPORTIONAL)
1000                                         fp = FCHARS[letter];
1001                                 else
1002                                         fp = FDATA + letter * BITS_TO_BYTES(width)*FHEIGHT;
1003
1004                                 if (underline)
1005                                         for (i=0; i< width; i++ )
1006                     {    *(short *)(DATA + VideoOffset) = pa_clut[FG_COLOR]; VideoOffset += PA_BPP; }
1007                 else
1008                                 {
1009                                         fp += BITS_TO_BYTES(width)*r;
1010
1011                                         BitMask = 0;
1012
1013                                         for (i=0; i< width; i++ )
1014                                         {
1015                                                 if (BitMask==0) {
1016                                                         bits = *fp++;
1017                                                         BitMask = 0x80;
1018                                                 }
1019
1020                                                 if (bits & BitMask)
1021                         {    *(short *)(DATA + VideoOffset) = pa_clut[FG_COLOR]; VideoOffset += PA_BPP; }
1022                         else
1023                             VideoOffset += PA_BPP;
1024                                                 BitMask >>= 1;
1025                                         }
1026                                 }
1027                                 text_ptr++;
1028
1029                 VideoOffset += PA_BPP * (spacing-width);
1030                         }
1031
1032                         VideoOffset1 += ROWSIZE; y++;
1033                 }
1034                 y += skip_lines;
1035                 VideoOffset1 += ROWSIZE * skip_lines;
1036                 skip_lines = 0;
1037         }
1038         return 0;
1039 }
1040 #endif
1041
1042 #ifndef OGL
1043 //a bitmap for the character
1044 grs_bitmap char_bm = {
1045                                 0,0,0,0,                                                //x,y,w,h
1046                                 BM_LINEAR,                                      //type
1047                                 BM_FLAG_TRANSPARENT,            //flags
1048                                 0,                                                              //rowsize
1049                                 NULL,                                                   //data
1050 #ifdef BITMAP_SELECTOR
1051                                 0,                              //selector
1052 #endif
1053                                 0,     //avg_color
1054                                 0      //unused
1055 };
1056
1057 int gr_internal_color_string(int x, int y, char *s )
1058 {
1059         unsigned char * fp;
1060         ubyte * text_ptr, * next_row, * text_ptr1;
1061         int width, spacing,letter;
1062         int xx,yy;
1063
1064         char_bm.bm_h = FHEIGHT;         //set height for chars of this font
1065
1066         next_row = s;
1067
1068         yy = y;
1069
1070
1071         while (next_row != NULL)
1072         {
1073                 text_ptr1 = next_row;
1074                 next_row = NULL;
1075
1076                 text_ptr = text_ptr1;
1077
1078                 xx = x;
1079
1080                 if (xx==0x8000)                 //centered
1081                         xx = get_centered_x(text_ptr);
1082
1083                 while (*text_ptr)
1084                 {
1085                         if (*text_ptr == '\n' )
1086                         {
1087                                 next_row = &text_ptr[1];
1088                                 yy += FHEIGHT;
1089                                 break;
1090                         }
1091
1092                         letter = *text_ptr-FMINCHAR;
1093
1094                         get_char_width(text_ptr[0],text_ptr[1],&width,&spacing);
1095
1096                         if (!INFONT(letter)) {  //not in font, draw as space
1097                                 xx += spacing;
1098                                 text_ptr++;
1099                                 continue;
1100                         }
1101
1102                         if (FFLAGS & FT_PROPORTIONAL)
1103                                 fp = FCHARS[letter];
1104                         else
1105                                 fp = FDATA + letter * BITS_TO_BYTES(width)*FHEIGHT;
1106
1107                         gr_init_bitmap (&char_bm, BM_LINEAR, 0, 0, width, FHEIGHT, width, fp);
1108                         gr_bitmapm(xx,yy,&char_bm);
1109
1110                         xx += spacing;
1111
1112                         text_ptr++;
1113                 }
1114
1115         }
1116         return 0;
1117 }
1118
1119 #else //OGL
1120 #include "../main/inferno.h"
1121 #include "ogl_init.h"
1122 #include "args.h"
1123 //font handling routines for OpenGL - Added 9/25/99 Matthew Mueller - they are here instead of in arch/ogl because they use all these defines
1124
1125 int pow2ize(int x);//from ogl.c
1126
1127 int get_font_total_width(grs_font * font){
1128         if (font->ft_flags & FT_PROPORTIONAL){
1129                 int i,w=0,c=font->ft_minchar;
1130                 for (i=0;c<=font->ft_maxchar;i++,c++){
1131                         if (font->ft_widths[i]<0)
1132                                 Error("heh?\n");
1133                         w+=font->ft_widths[i];
1134                 }
1135                 return w;
1136         }else{
1137                 return font->ft_w*(font->ft_maxchar-font->ft_minchar+1);
1138         }
1139 }
1140 void ogl_font_choose_size(grs_font * font,int gap,int *rw,int *rh){
1141         int     nchars = font->ft_maxchar-font->ft_minchar+1;
1142         int r,x,y,nc=0,smallest=999999,smallr=-1,tries;
1143         int smallprop=10000;
1144         int h,w;
1145         for (h=32;h<=256;h*=2){
1146 //              h=pow2ize(font->ft_h*rows+gap*(rows-1));
1147                 if (font->ft_h>h)continue;
1148                 r=(h/(font->ft_h+gap));
1149                 w=pow2ize((get_font_total_width(font)+(nchars-r)*gap)/r);
1150                 tries=0;
1151                 do {
1152                         if (tries)
1153                                 w=pow2ize(w+1);
1154                         if(tries>3){
1155                                 mprintf((0,"failed to fit (%ix%i, %ic)\n",w,h,nc));
1156                                 break;
1157                         }
1158                         nc=0;
1159                         y=0;
1160                         while(y+font->ft_h<=h){
1161                                 x=0;
1162                                 while (x<w){
1163                                         if (nc==nchars)
1164                                                 break;
1165                                         if (font->ft_flags & FT_PROPORTIONAL){
1166                                                 if (x+font->ft_widths[nc]+gap>w)break;
1167                                                 x+=font->ft_widths[nc++]+gap;
1168                                         }else{
1169                                                 if (x+font->ft_w+gap>w)break;
1170                                                 x+=font->ft_w+gap;
1171                                                 nc++;
1172                                         }
1173                                 }
1174                                 if (nc==nchars)
1175                                         break;
1176                                 y+=font->ft_h+gap;
1177                         }
1178                         
1179                         tries++;
1180                 }while(nc!=nchars);
1181                 if (nc!=nchars)
1182                         continue;
1183                 mprintf((0,"fit: %ix%i  %i tries\n",w,h,tries));
1184
1185                 if (w*h==smallest){//this gives squarer sizes priority (ie, 128x128 would be better than 512*32)
1186                         if (w>=h){
1187                                 if (w/h<smallprop){
1188                                         smallprop=w/h;
1189                                         smallest++;//hack
1190                                 }
1191                         }else{
1192                                 if (h/w<smallprop){
1193                                         smallprop=h/w;
1194                                         smallest++;//hack
1195                                 }
1196                         }
1197                 }
1198                 if (w*h<smallest){
1199                         smallr=1;
1200                         smallest=w*h;
1201                         *rw=w;
1202                         *rh=h;
1203                 }
1204         }
1205         if (smallr<=0)
1206                 Error("couldn't fit font?\n");
1207         mprintf((0,"using %ix%i\n",*rw,*rh));
1208         
1209 }
1210
1211 void ogl_init_font(grs_font * font){
1212         int     nchars = font->ft_maxchar-font->ft_minchar+1;
1213         int i,w,h,tw,th,x,y,curx=0,cury=0;
1214         char *fp;
1215         //      char data[32*32*4];
1216         char *data;
1217         int gap=0;//having a gap just wastes ram, since we don't filter text textures at all.
1218         //      char s[2];
1219         ogl_font_choose_size(font,gap,&tw,&th);
1220         data=d_malloc(tw*th);
1221         gr_init_bitmap(&font->ft_parent_bitmap,BM_LINEAR,0,0,tw,th,tw,data);
1222
1223         font->ft_parent_bitmap.gltexture=ogl_get_free_texture();
1224
1225         font->ft_bitmaps=(grs_bitmap*)d_malloc( nchars * sizeof(grs_bitmap));
1226         mprintf((0,"ogl_init_font %s, %s, nchars=%i, (%ix%i tex)\n",(font->ft_flags & FT_PROPORTIONAL)?"proportional":"fixedwidth",(font->ft_flags & FT_COLOR)?"color":"mono",nchars,tw,th));
1227         //      s[1]=0;
1228         h=font->ft_h;
1229         //      sleep(5);
1230
1231         for(i=0;i<nchars;i++){
1232                 //              s[0]=font->ft_minchar+i;
1233                 //              gr_get_string_size(s,&w,&h,&aw);
1234                 if (font->ft_flags & FT_PROPORTIONAL)
1235                         w=font->ft_widths[i];
1236                 else
1237                         w=font->ft_w;
1238 //              mprintf((0,"char %i(%ix%i): ",i,w,h));
1239                 if (w<1 || w>256){
1240                         mprintf((0,"grr\n"));continue;
1241                 }
1242                 if (curx+w+gap>tw){
1243                         cury+=h+gap;
1244                         curx=0;
1245                 }
1246                 if (cury+h>th)
1247                         Error("font doesn't really fit (%i/%i)?\n",i,nchars);
1248                 if (font->ft_flags & FT_COLOR) {
1249                         if (font->ft_flags & FT_PROPORTIONAL)
1250                                 fp = font->ft_chars[i];
1251                         else
1252                                 fp = font->ft_data + i * w*h;
1253                         for (y=0;y<h;y++)
1254                                 for (x=0;x<w;x++){
1255                                         font->ft_parent_bitmap.bm_data[curx+x+(cury+y)*tw]=fp[x+y*w];
1256                                 }
1257
1258                         //                      gr_init_bitmap(&font->ft_bitmaps[i],BM_LINEAR,0,0,w,h,w,font->);
1259                 }else{
1260                         int BitMask,bits=0,white=gr_find_closest_color(63,63,63);
1261                         //                      if (w*h>sizeof(data))
1262                         //                              Error("ogl_init_font: toobig\n");
1263                         if (font->ft_flags & FT_PROPORTIONAL)
1264                                 fp = font->ft_chars[i];
1265                         else
1266                                 fp = font->ft_data + i * BITS_TO_BYTES(w)*h;
1267                         for (y=0;y<h;y++){
1268                                 BitMask=0;
1269                                 for (x=0; x< w; x++ )
1270                                 {
1271                                         if (BitMask==0) {
1272                                                 bits = *fp++;
1273                                                 BitMask = 0x80;
1274                                         }
1275
1276                                         if (bits & BitMask)
1277                                                 font->ft_parent_bitmap.bm_data[curx+x+(cury+y)*tw]=white;
1278                                         else
1279                                                 font->ft_parent_bitmap.bm_data[curx+x+(cury+y)*tw]=255;
1280                                         BitMask >>= 1;
1281                                 }
1282                         }
1283                 }
1284                 gr_init_sub_bitmap(&font->ft_bitmaps[i],&font->ft_parent_bitmap,curx,cury,w,h);
1285
1286                 curx+=w+gap;
1287         }
1288         if (!(font->ft_flags & FT_COLOR)) {
1289                 //use GL_INTENSITY instead of GL_RGB
1290                 if (ogl_intensity4_ok){
1291                         font->ft_parent_bitmap.gltexture->internalformat=GL_INTENSITY4;
1292                         font->ft_parent_bitmap.gltexture->format=GL_LUMINANCE;
1293                 }else if (ogl_luminance4_alpha4_ok){
1294                         font->ft_parent_bitmap.gltexture->internalformat=GL_LUMINANCE4_ALPHA4;
1295                         font->ft_parent_bitmap.gltexture->format=GL_LUMINANCE_ALPHA;
1296                 }else if (ogl_rgba2_ok){
1297                         font->ft_parent_bitmap.gltexture->internalformat=GL_RGBA2;
1298                         font->ft_parent_bitmap.gltexture->format=GL_RGBA;
1299                 }else{
1300                         font->ft_parent_bitmap.gltexture->internalformat=ogl_rgba_format;
1301                         font->ft_parent_bitmap.gltexture->format=GL_RGBA;
1302                 }
1303         }
1304         ogl_loadbmtexture_m(&font->ft_parent_bitmap,0);
1305 }
1306
1307 int ogl_internal_string(int x, int y, char *s )
1308 {
1309         ubyte * text_ptr, * next_row, * text_ptr1;
1310         int width, spacing,letter;
1311         int xx,yy;
1312         int orig_color=FG_COLOR;//to allow easy reseting to default string color with colored strings -MPM
1313
1314         next_row = s;
1315
1316         yy = y;
1317
1318         if (grd_curscreen->sc_canvas.cv_bitmap.bm_type != BM_OGL)
1319                 Error("carp.\n");
1320         while (next_row != NULL)
1321         {
1322                 text_ptr1 = next_row;
1323                 next_row = NULL;
1324
1325                 text_ptr = text_ptr1;
1326
1327                 xx = x;
1328
1329                 if (xx==0x8000)                 //centered
1330                         xx = get_centered_x(text_ptr);
1331
1332                 while (*text_ptr)
1333                 {
1334                         if (*text_ptr == '\n' )
1335                         {
1336                                 next_row = &text_ptr[1];
1337                                 yy += FHEIGHT;
1338                                 break;
1339                         }
1340
1341                         letter = *text_ptr-FMINCHAR;
1342
1343                         get_char_width(text_ptr[0],text_ptr[1],&width,&spacing);
1344
1345                         if (!INFONT(letter) || *text_ptr<=0x06) {       //not in font, draw as space
1346                                 CHECK_EMBEDDED_COLORS() else{
1347                                         xx += spacing;
1348                                         text_ptr++;
1349                                 }
1350                                 continue;
1351                         }
1352                         
1353 //                      ogl_ubitblt(FONT->ft_bitmaps[letter].bm_w,FONT->ft_bitmaps[letter].bm_h,xx,yy,0,0,&FONT->ft_bitmaps[letter],NULL);
1354 //                      if (*text_ptr>='0' && *text_ptr<='9'){
1355                         if (FFLAGS&FT_COLOR)
1356                                 gr_ubitmapm(xx,yy,&FONT->ft_bitmaps[letter]);
1357                         else{
1358                                 if (grd_curcanv->cv_bitmap.bm_type==BM_OGL)
1359                                         ogl_ubitmapm_c(xx,yy,&FONT->ft_bitmaps[letter],FG_COLOR);
1360                                 else
1361                                         Error("ogl_internal_string: non-color string to non-ogl dest\n");
1362 //                                      gr_ubitmapm(xx,yy,&FONT->ft_bitmaps[letter]);//ignores color..
1363                         }
1364                         //}
1365
1366                         xx += spacing;
1367
1368                         text_ptr++;
1369                 }
1370
1371         }
1372         return 0;
1373 }
1374
1375 int gr_internal_color_string(int x, int y, char *s ){
1376         return ogl_internal_string(x,y,s);
1377 }
1378 #endif //OGL
1379
1380 int gr_string(int x, int y, char *s )
1381 {
1382         int w, h, aw;
1383         int clipped=0;
1384
1385         Assert(FONT != NULL);
1386
1387         if ( x == 0x8000 )      {
1388                 if ( y<0 ) clipped |= 1;
1389                 gr_get_string_size(s, &w, &h, &aw );
1390                 // for x, since this will be centered, only look at
1391                 // width.
1392                 if ( w > grd_curcanv->cv_bitmap.bm_w ) clipped |= 1;
1393                 if ( (y+h) > grd_curcanv->cv_bitmap.bm_h ) clipped |= 1;
1394
1395                 if ( (y+h) < 0 ) clipped |= 2;
1396                 if ( y > grd_curcanv->cv_bitmap.bm_h ) clipped |= 2;
1397
1398         } else {
1399                 if ( (x<0) || (y<0) ) clipped |= 1;
1400                 gr_get_string_size(s, &w, &h, &aw );
1401                 if ( (x+w) > grd_curcanv->cv_bitmap.bm_w ) clipped |= 1;
1402                 if ( (y+h) > grd_curcanv->cv_bitmap.bm_h ) clipped |= 1;
1403                 if ( (x+w) < 0 ) clipped |= 2;
1404                 if ( (y+h) < 0 ) clipped |= 2;
1405                 if ( x > grd_curcanv->cv_bitmap.bm_w ) clipped |= 2;
1406                 if ( y > grd_curcanv->cv_bitmap.bm_h ) clipped |= 2;
1407         }
1408
1409         if ( !clipped )
1410                 return gr_ustring(x, y, s );
1411
1412         if ( clipped & 2 )      {
1413                 // Completely clipped...
1414                 mprintf( (1, "Text '%s' at (%d,%d) is off screen!\n", s, x, y ));
1415                 return 0;
1416         }
1417
1418         if ( clipped & 1 )      {
1419                 // Partially clipped...
1420                 //mprintf( (0, "Text '%s' at (%d,%d) is getting clipped!\n", s, x, y ));
1421         }
1422
1423         // Partially clipped...
1424 #ifdef OGL
1425         if (TYPE==BM_OGL)
1426                 return ogl_internal_string(x,y,s);
1427 #endif
1428
1429         if (FFLAGS & FT_COLOR)
1430                 return gr_internal_color_string( x, y, s);
1431
1432         if ( BG_COLOR == -1)
1433                 return gr_internal_string_clipped_m( x, y, s );
1434
1435         return gr_internal_string_clipped( x, y, s );
1436 }
1437
1438 int gr_ustring(int x, int y, char *s )
1439 {
1440 #ifdef OGL
1441         if (TYPE==BM_OGL)
1442                 return ogl_internal_string(x,y,s);
1443 #endif
1444         
1445         if (FFLAGS & FT_COLOR) {
1446
1447                 return gr_internal_color_string(x,y,s);
1448
1449         }
1450         else
1451                 switch( TYPE )
1452                 {
1453                 case BM_LINEAR:
1454                         if ( BG_COLOR == -1)
1455                                 return gr_internal_string0m(x,y,s);
1456                         else
1457                                 return gr_internal_string0(x,y,s);
1458 #ifdef __MSDOS__
1459                 case BM_SVGA:
1460                         if ( BG_COLOR == -1)
1461                                 return gr_internal_string2m(x,y,s);
1462                         else
1463                                 return gr_internal_string2(x,y,s);
1464 #endif // __MSDOS__
1465 #if defined(POLY_ACC)
1466         case BM_LINEAR15:
1467                         if ( BG_COLOR == -1)
1468                                 return gr_internal_string5m(x,y,s);
1469                         else
1470                                 return gr_internal_string5(x,y,s);
1471 #endif
1472                 }
1473         return 0;
1474 }
1475
1476
1477 void gr_get_string_size(char *s, int *string_width, int *string_height, int *average_width )
1478 {
1479         int i = 0, longest_width = 0;
1480         int width,spacing;
1481
1482         *string_height = FHEIGHT;
1483         *string_width = 0;
1484         *average_width = FWIDTH;
1485
1486         if (s != NULL )
1487         {
1488                 *string_width = 0;
1489                 while (*s)
1490                 {
1491 //                      if (*s == CC_UNDERLINE)
1492 //                              s++;
1493                         while (*s == '\n')
1494                         {
1495                                 s++;
1496                                 *string_height += FHEIGHT;
1497                                 *string_width = 0;
1498                         }
1499
1500                         if (*s == 0) break;
1501
1502                         //      1 = next byte specifies color, so skip the 1 and the color value
1503                         if (*s == CC_COLOR)
1504                                 s += 2;
1505                         else if (*s == CC_LSPACING) {
1506                                 *string_height += *(s+1)-'0';
1507                                 s += 2;
1508                         } else {
1509                                 get_char_width(s[0],s[1],&width,&spacing);
1510
1511                                 *string_width += spacing;
1512
1513                                 if (*string_width > longest_width)
1514                                         longest_width = *string_width;
1515
1516                                 i++;
1517                                 s++;
1518                         }
1519                 }
1520         }
1521         *string_width = longest_width;
1522 }
1523
1524
1525 int gr_uprintf( int x, int y, char * format, ... )
1526 {
1527         char buffer[1000];
1528         va_list args;
1529
1530         va_start(args, format );
1531         vsprintf(buffer,format,args);
1532         return gr_ustring( x, y, buffer );
1533 }
1534
1535 int gr_printf( int x, int y, char * format, ... )
1536 {
1537         char buffer[1000];
1538         va_list args;
1539
1540         va_start(args, format );
1541         vsprintf(buffer,format,args);
1542         return gr_string( x, y, buffer );
1543 }
1544
1545 void gr_close_font( grs_font * font )
1546 {
1547         if (font)
1548         {
1549                 int fontnum;
1550
1551                 //find font in list
1552                 for (fontnum=0;fontnum<MAX_OPEN_FONTS && open_font[fontnum].ptr!=font;fontnum++);
1553                 Assert(fontnum<MAX_OPEN_FONTS); //did we find slot?
1554
1555                 open_font[fontnum].ptr = NULL;
1556
1557                 if ( font->ft_chars )
1558                         d_free( font->ft_chars );
1559                 d_free( font->oldfont );
1560 #ifdef OGL
1561                 if (font->ft_bitmaps)
1562                         d_free( font->ft_bitmaps );
1563                 gr_free_bitmap_data(&font->ft_parent_bitmap);
1564 //              ogl_freebmtexture(&font->ft_parent_bitmap);
1565 #endif
1566                 d_free( font );
1567
1568         }
1569 }
1570
1571 //remap (by re-reading) all the color fonts
1572 void gr_remap_color_fonts()
1573 {
1574         int fontnum;
1575
1576         for (fontnum=0;fontnum<MAX_OPEN_FONTS;fontnum++) {
1577                 grs_font *font;
1578
1579                 font = open_font[fontnum].ptr;
1580                 
1581                 if (font && (font->ft_flags & FT_COLOR))
1582                         gr_remap_font(font,open_font[fontnum].filename);
1583         }
1584 }
1585
1586 void build_colormap_good( ubyte * palette, ubyte * colormap, int * freq );
1587 void decode_data_asm(ubyte *data, int num_pixels, ubyte * colormap, int * count );
1588 #ifdef __WATCOMC__
1589 #pragma aux decode_data_asm parm [esi] [ecx] [edi] [ebx] modify exact [esi edi eax ebx ecx] = \
1590 "again_ddn:"                                                    \
1591         "xor    eax,eax"                                \
1592         "mov    al,[esi]"                       \
1593         "inc    dword ptr [ebx+eax*4]"          \
1594         "mov    al,[edi+eax]"           \
1595         "mov    [esi],al"                       \
1596         "inc    esi"                                    \
1597         "dec    ecx"                                    \
1598         "jne    again_ddn"
1599
1600 #endif
1601
1602 grs_font * gr_init_font( char * fontname )
1603 {
1604         static int first_time=1;
1605         old_grs_font *font;
1606         grs_font *newfont;
1607         int i,fontnum;
1608         unsigned char * ptr;
1609         int nchars;
1610         CFILE *fontfile;
1611         u_int32_t file_id;
1612         int32_t datasize;       //size up to (but not including) palette
1613
1614         if (first_time) {
1615                 int i;
1616                 for (i=0;i<MAX_OPEN_FONTS;i++)
1617                         open_font[i].ptr = NULL;
1618                 first_time=0;
1619         }
1620
1621         //find free font slot
1622         for (fontnum=0;fontnum<MAX_OPEN_FONTS && open_font[fontnum].ptr!=NULL;fontnum++);
1623         Assert(fontnum<MAX_OPEN_FONTS); //did we find one?
1624
1625         strncpy(open_font[fontnum].filename,fontname,FILENAME_LEN);
1626
1627         fontfile = cfopen(fontname, "rb");
1628
1629         if (!fontfile)
1630                 Error( "Can't open font file %s", fontname );
1631
1632         cfread(&file_id,sizeof(file_id),1,fontfile);
1633         file_id=swapint(file_id);
1634         cfread(&datasize,sizeof(datasize),1,fontfile);
1635         datasize=swapint(datasize);
1636
1637         if (file_id != MAKE_SIG('N','F','S','P'))
1638                 Error( "File %s is not a font file", fontname );
1639
1640         font = (old_grs_font *) d_malloc(datasize);
1641         newfont = (grs_font *) d_malloc(sizeof(grs_font));
1642         newfont->oldfont=font;
1643
1644         open_font[fontnum].ptr = newfont;
1645
1646         cfread(font,1,datasize,fontfile);
1647
1648         newfont->ft_flags=swapint(font->ft_flags);
1649         newfont->ft_w=swapshort(font->ft_w);
1650         newfont->ft_h=swapshort(font->ft_h);
1651         newfont->ft_baseline=swapshort(font->ft_baseline);
1652         newfont->ft_maxchar=font->ft_maxchar;
1653         newfont->ft_minchar=font->ft_minchar;
1654         newfont->ft_bytewidth=swapshort(font->ft_bytewidth);
1655
1656         nchars = newfont->ft_maxchar-newfont->ft_minchar+1;
1657
1658         if (newfont->ft_flags & FT_PROPORTIONAL) {
1659
1660                 newfont->ft_widths = (short *) (swapint(font->ft_widths) + ((ubyte *) font));
1661                 newfont->ft_data = (swapint(font->ft_data)) + ((ubyte *) font);
1662                 newfont->ft_chars = (unsigned char **)d_malloc( nchars * sizeof(unsigned char *));
1663
1664                 ptr = newfont->ft_data;
1665
1666                 for (i=0; i< nchars; i++ ) {
1667                         newfont->ft_chars[i] = ptr;
1668                         if (newfont->ft_flags & FT_COLOR)
1669                                 ptr += newfont->ft_widths[i] * newfont->ft_h;
1670                         else
1671                                 ptr += BITS_TO_BYTES(newfont->ft_widths[i]) * newfont->ft_h;
1672                 }
1673
1674         } else  {
1675
1676                 newfont->ft_data   = ((unsigned char *) font) + sizeof(*font);
1677                 newfont->ft_chars  = NULL;
1678                 newfont->ft_widths = NULL;
1679
1680                 ptr = newfont->ft_data + (nchars * newfont->ft_w * newfont->ft_h);
1681         }
1682
1683         if (newfont->ft_flags & FT_KERNED)
1684                 newfont->ft_kerndata = swapint(font->ft_kerndata) + ((ubyte *) font);
1685
1686         if (newfont->ft_flags & FT_COLOR) {             //remap palette
1687                 ubyte palette[256*3];
1688                 ubyte colormap[256];
1689                 int freq[256];
1690
1691                 cfread(palette,3,256,fontfile);         //read the palette
1692
1693 #ifdef MACINTOSH                        // swap the first and last palette entries (black and white)
1694                 {
1695                         int i;
1696                         ubyte c;
1697
1698                         for (i = 0; i < 3; i++) {
1699                                 c = palette[i];
1700                                 palette[i] = palette[765+i];
1701                                 palette[765+i] = c;
1702                         }
1703
1704 //  we also need to swap the data entries as well.  black is white and white is black
1705
1706                         for (i = 0; i < ptr-newfont->ft_data; i++) {
1707                                 if (newfont->ft_data[i] == 0)
1708                                         newfont->ft_data[i] = 255;
1709                                 else if (newfont->ft_data[i] == 255)
1710                                         newfont->ft_data[i] = 0;
1711                         }
1712
1713                 }
1714 #endif
1715
1716                 build_colormap_good( (ubyte *)&palette, colormap, freq );
1717
1718                 colormap[TRANSPARENCY_COLOR] = TRANSPARENCY_COLOR;              // chaged from colormap[255] = 255 to this for macintosh
1719
1720                 decode_data_asm(newfont->ft_data, ptr-newfont->ft_data, colormap, freq );
1721
1722         }
1723
1724         cfclose(fontfile);
1725
1726 //      memcpy(newfont,font,(ubyte*)&newfont->oldfont-(ubyte*)newfont);//fill in newfont data from oldfont struct
1727 //      mprintf((0,"%i %i %i\n",sizeof(grs_font),sizeof(old_grs_font),(ubyte*)&newfont->oldfont-(ubyte*)newfont));
1728
1729         //set curcanv vars
1730
1731         FONT        = newfont;
1732         FG_COLOR    = 0;
1733         BG_COLOR    = 0;
1734
1735         {
1736                 int x,y,aw;
1737                 char tests[]="abcdefghij1234.A";
1738                 gr_get_string_size(tests,&x,&y,&aw);
1739 //              newfont->ft_aw=x/(float)strlen(tests);
1740         }
1741
1742 #ifdef OGL
1743         ogl_init_font(newfont);
1744 #endif
1745
1746         return newfont;
1747
1748 }
1749
1750 //remap a font by re-reading its data & palette
1751 void gr_remap_font( grs_font *font, char * fontname )
1752 {
1753         int i;
1754         int nchars;
1755         CFILE *fontfile;
1756         u_int32_t file_id;
1757         int32_t datasize;        //size up to (but not including) palette
1758         int data_len;
1759
1760         if (! (font->ft_flags & FT_COLOR))
1761                 return;
1762
1763         fontfile = cfopen(fontname, "rb");
1764
1765         if (!fontfile)
1766                 Error( "Can't open font file %s", fontname );
1767
1768         file_id = cfile_read_int(fontfile);
1769         datasize = cfile_read_int(fontfile);
1770
1771         if (file_id != MAKE_SIG('N','F','S','P'))
1772                 Error( "File %s is not a font file", fontname );
1773
1774         nchars = font->ft_maxchar-font->ft_minchar+1;
1775
1776         //compute data length
1777         data_len = 0;
1778         if (font->ft_flags & FT_PROPORTIONAL) {
1779
1780                 for (i=0; i< nchars; i++ ) {
1781                         if (font->ft_flags & FT_COLOR)
1782                                 data_len += font->ft_widths[i] * font->ft_h;
1783                         else
1784                                 data_len += BITS_TO_BYTES(font->ft_widths[i]) * font->ft_h;
1785                 }
1786
1787         } else
1788                 data_len = nchars * font->ft_w * font->ft_h;
1789
1790         cfread(font->oldfont, 1, datasize, fontfile);   //read raw data
1791
1792         if (font->ft_flags & FT_COLOR) {                //remap palette
1793                 ubyte palette[256*3];
1794                 ubyte colormap[256];
1795                 int freq[256];
1796
1797                 cfseek(fontfile,-sizeof(palette),SEEK_END);
1798
1799                 cfread(palette,3,256,fontfile);         //read the palette
1800
1801 #ifdef MACINTOSH                        // swap the first and last palette entries (black and white)
1802                 {
1803                         int i;
1804                         ubyte c;
1805
1806                         for (i = 0; i < 3; i++) {
1807                                 c = palette[i];
1808                                 palette[i] = palette[765+i];
1809                                 palette[765+i] = c;
1810                         }
1811
1812 //  we also need to swap the data entries as well.  black is white and white is black
1813
1814                         for (i = 0; i < data_len; i++) {
1815                                 if (font->ft_data[i] == 0)
1816                                         font->ft_data[i] = 255;
1817                                 else if (font->ft_data[i] == 255)
1818                                         font->ft_data[i] = 0;
1819                         }
1820
1821                 }
1822 #endif
1823
1824                 build_colormap_good( (ubyte *)&palette, colormap, freq );
1825
1826                 colormap[TRANSPARENCY_COLOR] = TRANSPARENCY_COLOR;      // changed from         colormap[255] = 255;
1827
1828                 decode_data_asm(font->ft_data, data_len, colormap, freq );
1829
1830         }
1831
1832         cfclose(fontfile);
1833
1834 #ifdef OGL
1835         if (font->ft_bitmaps)
1836                 d_free( font->ft_bitmaps );
1837         gr_free_bitmap_data(&font->ft_parent_bitmap);
1838 //      ogl_freebmtexture(&font->ft_parent_bitmap);
1839
1840         ogl_init_font(font);
1841 #endif
1842 }
1843
1844
1845 void gr_set_fontcolor( int fg, int bg )
1846 {
1847         FG_COLOR    = fg;
1848         BG_COLOR    = bg;
1849 }
1850
1851 void gr_set_curfont( grs_font * new )
1852 {
1853         FONT = new;
1854 }
1855
1856
1857 int gr_internal_string_clipped(int x, int y, char *s )
1858 {
1859         unsigned char * fp;
1860         char * text_ptr, * next_row, * text_ptr1;
1861         int r, BitMask, i, bits, width, spacing, letter, underline;
1862         int x1 = x, last_x;
1863
1864         bits=0;
1865
1866         next_row = s;
1867
1868         while (next_row != NULL )
1869         {
1870                 text_ptr1 = next_row;
1871                 next_row = NULL;
1872
1873                 x = x1;
1874                 if (x==0x8000)                  //centered
1875                         x = get_centered_x(text_ptr1);
1876
1877                 last_x = x;
1878
1879                 for (r=0; r<FHEIGHT; r++)       {
1880                         text_ptr = text_ptr1;
1881                         x = last_x;
1882
1883                         while (*text_ptr)       {
1884                                 if (*text_ptr == '\n' ) {
1885                                         next_row = &text_ptr[1];
1886                                         break;
1887                                 }
1888
1889                                 if (*text_ptr == CC_COLOR) {
1890                                         FG_COLOR = *(text_ptr+1);
1891                                         text_ptr += 2;
1892                                         continue;
1893                                 }
1894
1895                                 if (*text_ptr == CC_LSPACING) {
1896                                         Int3(); //      Warning: skip lines not supported for clipped strings.
1897                                         text_ptr += 2;
1898                                         continue;
1899                                 }
1900
1901                                 underline = 0;
1902                                 if (*text_ptr == CC_UNDERLINE ) {
1903                                         if ((r==FBASELINE+2) || (r==FBASELINE+3))
1904                                                 underline = 1;
1905                                         text_ptr++;
1906                                 }
1907
1908                                 get_char_width(text_ptr[0],text_ptr[1],&width,&spacing);
1909
1910                                 letter = *text_ptr-FMINCHAR;
1911
1912                                 if (!INFONT(letter)) {  //not in font, draw as space
1913                                         x += spacing;
1914                                         text_ptr++;
1915                                         continue;
1916                                 }
1917
1918                                 if (FFLAGS & FT_PROPORTIONAL)
1919                                         fp = FCHARS[letter];
1920                                 else
1921                                         fp = FDATA + letter * BITS_TO_BYTES(width)*FHEIGHT;
1922
1923                                 if (underline)  {
1924                                         for (i=0; i< width; i++ )       {
1925                                                 gr_setcolor(FG_COLOR);
1926                                                 gr_pixel( x++, y );
1927                                         }
1928                                 } else {
1929                                         fp += BITS_TO_BYTES(width)*r;
1930
1931                                         BitMask = 0;
1932
1933                                         for (i=0; i< width; i++ )       {
1934                                                 if (BitMask==0) {
1935                                                         bits = *fp++;
1936                                                         BitMask = 0x80;
1937                                                 }
1938                                                 if (bits & BitMask)
1939                                                         gr_setcolor(FG_COLOR);
1940                                                 else
1941                                                         gr_setcolor(BG_COLOR);
1942                                                 gr_pixel( x++, y );
1943                                                 BitMask >>= 1;
1944                                         }
1945                                 }
1946
1947                                 x += spacing-width;             //for kerning
1948
1949                                 text_ptr++;
1950                         }
1951                         y++;
1952                 }
1953         }
1954         return 0;
1955 }
1956
1957 int gr_internal_string_clipped_m(int x, int y, char *s )
1958 {
1959         unsigned char * fp;
1960         char * text_ptr, * next_row, * text_ptr1;
1961         int r, BitMask, i, bits, width, spacing, letter, underline;
1962         int x1 = x, last_x;
1963
1964         bits=0;
1965
1966         next_row = s;
1967
1968         while (next_row != NULL )
1969         {
1970                 text_ptr1 = next_row;
1971                 next_row = NULL;
1972
1973                 x = x1;
1974                 if (x==0x8000)                  //centered
1975                         x = get_centered_x(text_ptr1);
1976
1977                 last_x = x;
1978
1979                 for (r=0; r<FHEIGHT; r++)       {
1980                         x = last_x;
1981
1982                         text_ptr = text_ptr1;
1983
1984                         while (*text_ptr)       {
1985                                 if (*text_ptr == '\n' ) {
1986                                         next_row = &text_ptr[1];
1987                                         break;
1988                                 }
1989
1990                                 if (*text_ptr == CC_COLOR) {
1991                                         FG_COLOR = *(text_ptr+1);
1992                                         text_ptr += 2;
1993                                         continue;
1994                                 }
1995
1996                                 if (*text_ptr == CC_LSPACING) {
1997                                         Int3(); //      Warning: skip lines not supported for clipped strings.
1998                                         text_ptr += 2;
1999                                         continue;
2000                                 }
2001
2002                                 underline = 0;
2003                                 if (*text_ptr == CC_UNDERLINE ) {
2004                                         if ((r==FBASELINE+2) || (r==FBASELINE+3))
2005                                                 underline = 1;
2006                                         text_ptr++;
2007                                 }
2008
2009                                 get_char_width(text_ptr[0],text_ptr[1],&width,&spacing);
2010
2011                                 letter = *text_ptr-FMINCHAR;
2012
2013                                 if (!INFONT(letter)) {  //not in font, draw as space
2014                                         x += spacing;
2015                                         text_ptr++;
2016                                         continue;
2017                                 }
2018
2019                                 if (FFLAGS & FT_PROPORTIONAL)
2020                                         fp = FCHARS[letter];
2021                                 else
2022                                         fp = FDATA + letter * BITS_TO_BYTES(width)*FHEIGHT;
2023
2024                                 if (underline)  {
2025                                         for (i=0; i< width; i++ )       {
2026                                                 gr_setcolor(FG_COLOR);
2027                                                 gr_pixel( x++, y );
2028                                         }
2029                                 } else {
2030                                         fp += BITS_TO_BYTES(width)*r;
2031
2032                                         BitMask = 0;
2033
2034                                         for (i=0; i< width; i++ )       {
2035                                                 if (BitMask==0) {
2036                                                         bits = *fp++;
2037                                                         BitMask = 0x80;
2038                                                 }
2039                                                 if (bits & BitMask)     {
2040                                                         gr_setcolor(FG_COLOR);
2041                                                         gr_pixel( x++, y );
2042                                                 } else {
2043                                                         x++;
2044                                                 }
2045                                                 BitMask >>= 1;
2046                                         }
2047                                 }
2048
2049                                 x += spacing-width;             //for kerning
2050
2051                                 text_ptr++;
2052                         }
2053                         y++;
2054                 }
2055         }
2056         return 0;
2057 }