1 /*
2 *	SDL Graphics Extension
3 *	Text/TrueType font functions
4 *
5 *	Started 990815
6 *
7 *	License: LGPL v2+ (see the file LICENSE)
8 *	(c)1999-2001 Anders Lindstr�m
9 *
10 *	Uses the excellent FreeType 2 library, available at:
11 *	http://www.freetype.org/
12 */
13 
14 /*********************************************************************
15  *  This library is free software; you can redistribute it and/or    *
16  *  modify it under the terms of the GNU Library General Public      *
17  *  License as published by the Free Software Foundation; either     *
18  *  version 2 of the License, or (at your option) any later version. *
19  *********************************************************************/
20 
21 /*
22 *  Most of this code is taken from the SDL ttf lib by Sam Lantinga
23 *  <slouken@devolution.com>
24 */
25 
26 
27 #include "SDL.h"
28 #include <stdlib.h>
29 #include <memory.h>
30 #include <string.h>
31 #include <stdarg.h>
32 #include <math.h>
33 #include "sge_surface.h"
34 #include "sge_primitives.h"
35 #include "sge_tt_text.h"
36 
37 #ifndef _SGE_NOTTF
38 #include <ft2build.h>
39 #include FT_FREETYPE_H
40 #include FT_OUTLINE_H
41 #include FT_TRUETYPE_IDS_H
42 
43 /* The structure used to hold glyph information (cached) */
44 struct glyph {
45 	int stored;
46 	FT_UInt index;
47 	//FT_Bitmap bitmap;
48 	FT_Bitmap pixmap;
49 	int minx;
50 	int maxx;
51 	int miny;
52 	int maxy;
53 	int yoffset;
54 	int advance;
55 	Uint16 cached;
56 };
57 
58 /* the truetype font structure */
59 struct _sge_TTFont{
60 	FT_Face face;
61 
62 	/* Font metrics */
63 	int height;
64 	int ascent;
65 	int descent;
66 	int lineskip;
67 
68 	/* The font style */
69 	Uint8 style;
70 
71 	/* Extra width in glyph bounds for text styles */
72 	int glyph_overhang;
73 	float glyph_italics;
74 
75 	/* Information in the font for underlining */
76 	int underline_offset;
77 	int underline_height;
78 
79 	/* For now, support Latin-1 character set caching */
80 	glyph *current;
81 	glyph cache[256];
82 	glyph scratch;
83 };
84 
85 
86 /* Macro to convert a character to a Unicode value -- assume already Unicode */
87 //Should really make a proper convert algorithm someday
88 #define UNICODE(c)	c
89 
90 /* FIXME: Right now we assume the gray-scale renderer Freetype is using
91    supports 256 shades of gray, but we should instead key off of num_grays
92    in the result FT_Bitmap after the FT_Render_Glyph() call. */
93 #define NUM_GRAYS       256
94 
95 /* Handy routines for converting from fixed point */
96 #define FT_FLOOR(X)	((X & -64) / 64)
97 #define FT_CEIL(X)	(((X + 63) & -64) / 64)
98 
99 #define CACHED_METRICS	0x10
100 #define CACHED_BITMAP	0x01
101 #define CACHED_PIXMAP	0x02
102 
103 /* The FreeType font engine/library */
104 static FT_Library _sge_library;
105 static int _sge_TTF_initialized = 0;
106 
107 Uint8 _sge_TTF_AA=1;     //Rendering mode: 0-OFF, 1-AA, 2-Alpha
108 
109 
110 /**********************************************************************************/
111 /**                          Open/misc font functions                            **/
112 /**********************************************************************************/
113 
114 //==================================================================================
115 // Turns TTF AntiAliasing On/Off or alpha (nice but slow) (Default: On)
116 //==================================================================================
sge_TTF_AAOff(void)117 void sge_TTF_AAOff(void)
118 {
119 	_sge_TTF_AA=0;
120 }
sge_TTF_AAOn(void)121 void sge_TTF_AAOn(void)
122 {
123 	_sge_TTF_AA=1;
124 }
sge_TTF_AA_Alpha(void)125 void sge_TTF_AA_Alpha(void)
126 {
127 	_sge_TTF_AA=2;
128 }
129 
130 
131 //==================================================================================
132 // Closes the ttf engine, done by exit
133 //==================================================================================
sge_TTF_Quit(void)134 void sge_TTF_Quit(void)
135 {
136 	if ( _sge_TTF_initialized ) {
137 		FT_Done_FreeType( _sge_library );
138 	}
139 	_sge_TTF_initialized = 0;
140 }
141 
142 
143 //==================================================================================
144 // Starts the ttf engine, must be called first
145 //==================================================================================
sge_TTF_Init(void)146 int sge_TTF_Init(void)
147 {
148 	FT_Error error;
149 
150 	error = FT_Init_FreeType( &_sge_library );
151 	if ( error ) {
152 		SDL_SetError("SGE - Couldn't init FreeType engine");
153 		return(-1);
154 	} else {
155 		_sge_TTF_initialized = 1;
156 	}
157 	atexit(sge_TTF_Quit); //dont't trust the user...
158 	return(0);
159 }
160 
161 
162 //==================================================================================
163 // Some helper functions
164 //==================================================================================
Flush_Glyph(glyph * glyph)165 void Flush_Glyph(glyph *glyph)
166 {
167 	glyph->stored = 0;
168 	glyph->index = 0;
169 	//if( glyph->bitmap.buffer ) {
170 	//	free( glyph->bitmap.buffer );
171 	//	glyph->bitmap.buffer = 0;
172 	//}
173 	if( glyph->pixmap.buffer ) {
174 		free( glyph->pixmap.buffer );
175 		glyph->pixmap.buffer = 0;
176 	}
177 	glyph->cached = 0;
178 }
179 
Flush_Cache(sge_TTFont * font)180 void Flush_Cache(sge_TTFont *font)
181 {
182 	int i;
183 	int size = sizeof( font->cache ) / sizeof( font->cache[0] );
184 
185 	for( i = 0; i < size; ++i ) {
186 		if( font->cache[i].cached ) {
187 			Flush_Glyph( &font->cache[i] );
188 		}
189 
190 	}
191 	if( font->scratch.cached ) {
192 		Flush_Glyph( &font->scratch );
193 	}
194 }
195 
196 
197 //==================================================================================
198 // Remove font from memory
199 //==================================================================================
sge_TTF_CloseFont(sge_TTFont * font)200 void sge_TTF_CloseFont(sge_TTFont *font)
201 {
202 	Flush_Cache( font );
203 	FT_Done_Face( font->face );
204 	free( font );
205 }
206 
207 
208 //==================================================================================
209 // Open the TT font file and returns the font with pt size
210 //==================================================================================
sge_TTF_OpenFont(const char * file,int ptsize)211 sge_TTFont *sge_TTF_OpenFont(const char *file, int ptsize)
212 {
213 	sge_TTFont *font;
214 	FT_Error error;
215 	FT_Face face;
216 	FT_Fixed scale;
217 
218 	font = (sge_TTFont *)malloc(sizeof(*font));
219 	if ( font == NULL ) {
220 		SDL_SetError("SGE - Out of memory");
221 		return(NULL);
222 	}
223 	memset(font, 0, sizeof(*font));
224 
225 	/* Open the font and create ancillary data */
226 	error = FT_New_Face( _sge_library, file, 0, &font->face );
227 	if ( error ) {
228 		sge_SetError("SGE - Couldn't load font file: %s",file);
229 		free(font);
230 		return(NULL);
231 	}
232 	face = font->face;
233 
234 	/* Make sure that our font face is scalable (global metrics) */
235 	if ( ! FT_IS_SCALABLE(face) ) {
236 		sge_SetError("SGE - Font face is not scalable: %s",file);
237 		sge_TTF_CloseFont( font );
238 		return NULL;
239 	}
240 
241 	/* Set the character size and use 96 DPI */
242 	error = FT_Set_Char_Size( font->face, 0, ptsize * 64, 96, 96 );
243 	//error = FT_Set_Pixel_Sizes( font->face, 0, ptsize );
244 	if( error ) {
245 		sge_SetError("SGE - Couldn't set font size: %s",file);
246 		sge_TTF_CloseFont( font );
247 		return NULL;
248 	}
249 
250 	/* Get the scalable font metrics for this font */
251 	scale = face->size->metrics.y_scale;
252 	font->ascent  = FT_CEIL(FT_MulFix(face->bbox.yMax, scale));
253 	font->descent = FT_CEIL(FT_MulFix(face->bbox.yMin, scale));
254 	font->height  = font->ascent - font->descent + /* baseline */ 1;
255 	font->lineskip = FT_CEIL(FT_MulFix(face->height, scale));
256 	font->underline_offset = FT_FLOOR(FT_MulFix(face->underline_position, scale));
257 	font->underline_height = FT_FLOOR(FT_MulFix(face->underline_thickness, scale));
258 	if ( font->underline_height < 1 ) {
259 		font->underline_height = 1;
260 	}
261 
262 	/* Set the default font style */
263 	font->style = SGE_TTF_NORMAL;
264 	font->glyph_overhang = face->size->metrics.y_ppem / 10;
265 	/* x offset = cos(((90.0-12)/360)*2*M_PI), or 12 degree angle */
266 	font->glyph_italics = 0.207f;
267 	font->glyph_italics *= font->height;
268 
269 	return font;
270 }
271 
272 
273 //==================================================================================
274 // Load a glyph
275 //==================================================================================
Load_Glyph(sge_TTFont * font,Uint16 ch,glyph * cached,int want)276 FT_Error Load_Glyph(sge_TTFont *font, Uint16 ch, glyph *cached, int want )
277 {
278 	FT_Face face;
279 	FT_Error error;
280 	FT_GlyphSlot glyph;
281 	FT_Glyph_Metrics* metrics;
282 	FT_Outline* outline;
283 
284 	//assert( font );
285 	//assert( font->face );
286 
287 	face = font->face;
288 
289 	/* Load the glyph */
290 	if ( ! cached->index ) {
291 		cached->index = FT_Get_Char_Index( face, ch );
292 	}
293 	error = FT_Load_Glyph( face, cached->index, FT_LOAD_DEFAULT );
294 	if( error ) {
295 		return error;
296 	}
297 
298 	/* Get our glyph shortcuts */
299 	glyph = face->glyph;
300 	metrics = &glyph->metrics;
301 	outline = &glyph->outline;
302 
303 	/* Get the glyph metrics if desired */
304 	if ( (want & CACHED_METRICS) && !(cached->stored & CACHED_METRICS) ) {
305 		/* Get the bounding box */
306 		cached->minx = FT_FLOOR(metrics->horiBearingX);
307 		cached->maxx = cached->minx + FT_CEIL(metrics->width);
308 		cached->maxy = FT_FLOOR(metrics->horiBearingY);
309 		cached->miny = cached->maxy - FT_CEIL(metrics->height);
310 		cached->yoffset = font->ascent - cached->maxy;
311 		cached->advance = FT_CEIL(metrics->horiAdvance);
312 
313 		/* Adjust for bold and italic text */
314 		if ( font->style & SGE_TTF_BOLD ) {
315 			cached->maxx += font->glyph_overhang;
316 		}
317 		if ( font->style & SGE_TTF_ITALIC ) {
318 			cached->maxx += (int)ceil(font->glyph_italics);
319 		}
320 		cached->stored |= CACHED_METRICS;
321 	}
322 
323 	if ( ((want & CACHED_BITMAP) && !(cached->stored & CACHED_BITMAP)) ||
324 	     ((want & CACHED_PIXMAP) && !(cached->stored & CACHED_PIXMAP)) ) {
325 		//int mono = (want & CACHED_BITMAP);
326 		int i;
327 		FT_Bitmap* src;
328 		FT_Bitmap* dst;
329 
330 		/* Handle the italic style */
331 		if( font->style & SGE_TTF_ITALIC ) {
332 			FT_Matrix shear;
333 
334 			shear.xx = 1 << 16;
335 			shear.xy = (int) ( font->glyph_italics * ( 1 << 16 ) ) / font->height;
336 			shear.yx = 0;
337 			shear.yy = 1 << 16;
338 
339 			FT_Outline_Transform( outline, &shear );
340 		}
341 
342 		/* Render the glyph */
343 		//if ( mono ) {
344 		//	error = FT_Render_Glyph( glyph, ft_render_mode_mono );
345 		//} else {
346 			error = FT_Render_Glyph( glyph, ft_render_mode_normal );
347 		//}
348 		if( error ) {
349 			return error;
350 		}
351 
352 		/* Copy over information to cache */
353 		src = &glyph->bitmap;
354 		//if ( mono ) {
355 		//	dst = &cached->bitmap;
356 		//} else {
357 			dst = &cached->pixmap;
358 		//}
359 		memcpy( dst, src, sizeof( *dst ) );
360 		//if ( mono ) {
361 		//	dst->pitch *= 8;
362 		//}
363 
364 		/* Adjust for bold and italic text */
365 		if( font->style & SGE_TTF_BOLD ) {
366 			int bump = font->glyph_overhang;
367 			dst->pitch += bump;
368 			dst->width += bump;
369 		}
370 		if( font->style & SGE_TTF_ITALIC ) {
371 			int bump = (int)ceil(font->glyph_italics);
372 			dst->pitch += bump;
373 			dst->width += bump;
374 		}
375 
376 		dst->buffer = (unsigned char *)malloc( dst->pitch * dst->rows );
377 		if( !dst->buffer ) {
378 			return FT_Err_Out_Of_Memory;
379 		}
380 		memset( dst->buffer, 0, dst->pitch * dst->rows );
381 
382 		for( i = 0; i < src->rows; i++ ) {
383 			int soffset = i * src->pitch;
384 			int doffset = i * dst->pitch;
385 			/*if ( mono ) {
386 				unsigned char *srcp = src->buffer + soffset;
387 				unsigned char *dstp = dst->buffer + doffset;
388 				int j;
389 				for ( j = 0; j < src->width; j += 8 ) {
390 					unsigned char ch = *srcp++;
391 					*dstp++ = (ch&0x80) >> 7;
392 					ch <<= 1;
393 					*dstp++ = (ch&0x80) >> 7;
394 					ch <<= 1;
395 					*dstp++ = (ch&0x80) >> 7;
396 					ch <<= 1;
397 					*dstp++ = (ch&0x80) >> 7;
398 					ch <<= 1;
399 					*dstp++ = (ch&0x80) >> 7;
400 					ch <<= 1;
401 					*dstp++ = (ch&0x80) >> 7;
402 					ch <<= 1;
403 					*dstp++ = (ch&0x80) >> 7;
404 					ch <<= 1;
405 					*dstp++ = (ch&0x80) >> 7;
406 				}
407 			} else {*/
408 				memcpy(dst->buffer+doffset,
409 				       src->buffer+soffset, src->pitch);
410 			//}
411 		}
412 
413 		/* Handle the bold style */
414 		if ( font->style & SGE_TTF_BOLD ) {
415 			int row;
416 			int col;
417 			int offset;
418 			int pixel;
419 			Uint8* pixmap;
420 
421 			/* The pixmap is a little hard, we have to add and clamp */
422 			for( row = dst->rows - 1; row >= 0; --row ) {
423 				pixmap = (Uint8*) dst->buffer + row * dst->pitch;
424 				for( offset=1; offset <= font->glyph_overhang; ++offset ) {
425 					for( col = dst->width - 1; col > 0; --col ) {
426 						pixel = (pixmap[col] + pixmap[col-1]);
427 						if( pixel > NUM_GRAYS - 1 ) {
428 							pixel = NUM_GRAYS - 1;
429 						}
430 						pixmap[col] = (Uint8) pixel;
431 					}
432 				}
433 			}
434 		}
435 
436 		/* Mark that we rendered this format */
437 		//if ( mono ) {
438 		//	cached->stored |= CACHED_BITMAP;
439 		//} else {
440 			cached->stored |= CACHED_PIXMAP;
441 		//}
442 	}
443 
444 	/* We're done, mark this glyph cached */
445 	cached->cached = ch;
446 
447 	return 0;
448 }
449 
450 
451 //==================================================================================
452 // Find glyph
453 //==================================================================================
Find_Glyph(sge_TTFont * font,Uint16 ch,int want)454 FT_Error Find_Glyph(sge_TTFont *font, Uint16 ch, int want)
455 {
456 	int retval = 0;
457 
458 	if( ch < 256 ) {
459 		font->current = &font->cache[ch];
460 	} else {
461 		if ( font->scratch.cached != ch ) {
462 			Flush_Glyph( &font->scratch );
463 		}
464 		font->current = &font->scratch;
465 	}
466 	if ( (font->current->stored & want) != want ) {
467 		retval = Load_Glyph( font, ch, font->current, want );
468 	}
469 	return retval;
470 }
471 
472 
473 //==================================================================================
474 // Change the size of font
475 //==================================================================================
sge_TTF_SetFontSize(sge_TTFont * font,int ptsize)476 int sge_TTF_SetFontSize(sge_TTFont *font, int ptsize)
477 {
478 	FT_Error error;
479 	FT_Fixed scale;
480 	FT_Face face;
481 
482 	/* Set the character size and use 96 DPI */
483 	error = FT_Set_Char_Size( font->face, 0, ptsize * 64, 96, 96 );
484 	//error = FT_Set_Pixel_Sizes( font->face, 0, ptsize );
485 	if( error ) {
486 		sge_SetError("SGE - Couldn't set font size");
487 		sge_TTF_CloseFont( font );
488 		return -1;
489 	}
490 
491 	Flush_Cache(font);
492 	face = font->face;
493 
494 	/* Get the scalable font metrics for this font */
495 	scale = face->size->metrics.y_scale;
496 	font->ascent  = FT_CEIL(FT_MulFix(face->bbox.yMax, scale));
497 	font->descent = FT_CEIL(FT_MulFix(face->bbox.yMin, scale));
498 	font->height  = font->ascent - font->descent + /* baseline */ 1;
499 	font->lineskip = FT_CEIL(FT_MulFix(face->height, scale));
500 	font->underline_offset = FT_FLOOR(FT_MulFix(face->underline_position, scale));
501 	font->underline_height = FT_FLOOR(FT_MulFix(face->underline_thickness, scale));
502 	if ( font->underline_height < 1 ) {
503 		font->underline_height = 1;
504 	}
505 
506 	/* Set the default font style */
507 	//font->style = SGE_TTF_NORMAL;
508 	font->glyph_overhang = face->size->metrics.y_ppem / 10;
509 	/* x offset = cos(((90.0-12)/360)*2*M_PI), or 12 degree angle */
510 	font->glyph_italics = 0.207f;
511 	font->glyph_italics *= font->height;
512 
513 	return 0;
514 }
515 
516 
517 //==================================================================================
518 // Get font geometrics
519 //==================================================================================
sge_TTF_FontHeight(sge_TTFont * font)520 int sge_TTF_FontHeight(sge_TTFont *font)
521 {
522 	return(font->height);
523 }
sge_TTF_FontAscent(sge_TTFont * font)524 int sge_TTF_FontAscent(sge_TTFont *font)
525 {
526 	return(font->ascent);
527 }
sge_TTF_FontDescent(sge_TTFont * font)528 int sge_TTF_FontDescent(sge_TTFont *font)
529 {
530 	return(font->descent);
531 }
sge_TTF_FontLineSkip(sge_TTFont * font)532 int sge_TTF_FontLineSkip(sge_TTFont *font)
533 {
534 	return(font->lineskip);
535 }
sge_TTF_GlyphMetrics(sge_TTFont * font,Uint16 ch,int * minx,int * maxx,int * miny,int * maxy,int * advance)536 int sge_TTF_GlyphMetrics(sge_TTFont *font, Uint16 ch, int* minx, int* maxx, int* miny, int* maxy, int* advance)
537 {
538 	FT_Error error;
539 
540 	error = Find_Glyph(font, ch, CACHED_METRICS);
541 
542 	if ( error ) {
543 		return -1;
544 	}
545 
546 	if ( minx ) {
547 		*minx = font->current->minx;
548 	}
549 	if ( maxx ) {
550 		*maxx = font->current->maxx;
551 	}
552 	if ( miny ) {
553 		*miny = font->current->miny;
554 	}
555 	if ( maxy ) {
556 		*maxy = font->current->maxy;
557 	}
558 	if ( advance ) {
559 		*advance = font->current->advance;
560 	}
561 	return 0;
562 }
563 
564 
565 //==================================================================================
566 // Set font style
567 //==================================================================================
sge_TTF_SetFontStyle(sge_TTFont * font,Uint8 style)568 void sge_TTF_SetFontStyle(sge_TTFont *font, Uint8 style)
569 {
570 	font->style = style;
571 	Flush_Cache(font);
572 }
573 
574 
575 //==================================================================================
576 // Get font style
577 //==================================================================================
sge_TTF_GetFontStyle(sge_TTFont * font)578 Uint8 sge_TTF_GetFontStyle(sge_TTFont *font)
579 {
580 	return(font->style);
581 }
582 #endif /* _SGE_NOTTF */
583 
584 
585 //==================================================================================
586 // Convert the Latin-1 text to UNICODE
587 //==================================================================================
ASCII_to_UNICODE(Uint16 * unicode,const char * text,int len)588 Uint16 *ASCII_to_UNICODE(Uint16 *unicode, const char *text, int len)
589 {
590 	int i;
591 
592 	for ( i=0; i < len; ++i ) {
593 		unicode[i] = ((const unsigned char *)text)[i];
594 	}
595 	unicode[i] = 0;
596 
597 	return unicode;
598 }
599 
sge_Latin1_Uni(const char * text)600 Uint16 *sge_Latin1_Uni(const char *text)
601 {
602 	Uint16 *unicode_text;
603 	int i, unicode_len;
604 
605 	/* Copy the Latin-1 text to a UNICODE text buffer */
606 	unicode_len = strlen(text);
607 	unicode_text = (Uint16 *)malloc((unicode_len+1)*(sizeof *unicode_text));
608 	if ( unicode_text == NULL ) {
609 		SDL_SetError("SGE - Out of memory");
610 		return(NULL);
611 	}
612 	for ( i=0; i < unicode_len; ++i ) {
613 		unicode_text[i] = ((const unsigned char *)text)[i];
614 	}
615 	unicode_text[i] = 0;
616 
617 	return(unicode_text);
618 }
619 
620 //==================================================================================
621 // Convert the UTF-8 text to UNICODE
622 //==================================================================================
UTF8_to_UNICODE(Uint16 * unicode,const char * utf8,int len)623 Uint16 *UTF8_to_UNICODE(Uint16 *unicode, const char *utf8, int len)
624 {
625 	int i, j;
626 	Uint16 ch;
627 
628 	for ( i=0, j=0; i < len; ++i, ++j ) {
629 		ch = ((const unsigned char *)utf8)[i];
630 		if ( ch >= 0xF0 ) {
631 			ch  =  (Uint16)(utf8[i]&0x07) << 18;
632 			ch |=  (Uint16)(utf8[++i]&0x3F) << 12;
633 			ch |=  (Uint16)(utf8[++i]&0x3F) << 6;
634 			ch |=  (Uint16)(utf8[++i]&0x3F);
635 		} else
636 		if ( ch >= 0xE0 ) {
637 			ch  =  (Uint16)(utf8[i]&0x3F) << 12;
638 			ch |=  (Uint16)(utf8[++i]&0x3F) << 6;
639 			ch |=  (Uint16)(utf8[++i]&0x3F);
640 		} else
641 		if ( ch >= 0xC0 ) {
642 			ch  =  (Uint16)(utf8[i]&0x3F) << 6;
643 			ch |=  (Uint16)(utf8[++i]&0x3F);
644 		}
645 		unicode[j] = ch;
646 	}
647 	unicode[j] = 0;
648 
649 	return unicode;
650 }
651 
sge_UTF8_Uni(const char * text)652 Uint16 *sge_UTF8_Uni(const char *text)
653 {
654 	Uint16 *unicode_text;
655 	int unicode_len;
656 
657 	/* Copy the UTF-8 text to a UNICODE text buffer */
658 	unicode_len = strlen(text);
659 	unicode_text = (Uint16 *)malloc((unicode_len+1)*(sizeof *unicode_text));
660 	if ( unicode_text == NULL ) {
661 		SDL_SetError("SGE - Out of memory");
662 		return(NULL);
663 	}
664 
665 	return UTF8_to_UNICODE(unicode_text, text, unicode_len);
666 }
667 
668 #ifndef _SGE_NOTTF
669 //==================================================================================
670 // Get the width of the text with the given font
671 //==================================================================================
sge_TTF_TextSizeUNI(sge_TTFont * font,const Uint16 * text)672 SDL_Rect sge_TTF_TextSizeUNI(sge_TTFont *font, const Uint16 *text)
673 {
674 	SDL_Rect ret; ret.x=0; ret.y=0, ret.w=0, ret.h=0;
675 	const Uint16 *ch;
676 	int x, z;
677 	int minx, maxx;
678 	int miny, maxy;
679 	glyph *glyph;
680 	FT_Error error;
681 
682 	/* Initialize everything to 0 */
683 	if ( ! _sge_TTF_initialized ) {
684 		return ret;
685 	}
686 
687 	minx = miny = 0;
688 	maxx = maxy = 0;
689 
690 	/* Load each character and sum it's bounding box */
691 	x= 0;
692 	for ( ch=text; *ch; ++ch ) {
693 		error = Find_Glyph(font, *ch, CACHED_METRICS);
694 		if ( error ) {
695 			return ret;
696 		}
697 		glyph = font->current;
698 
699 		z = x + glyph->minx;
700 		if ( minx > z ) {
701 			minx = z;
702 		}
703 		if ( font->style & SGE_TTF_BOLD ) {
704 			x += font->glyph_overhang;
705 		}
706 		if ( glyph->advance > glyph->maxx ) {
707 			z = x + glyph->advance;
708 		} else {
709 			z = x + glyph->maxx;
710 		}
711 		if ( maxx < z ) {
712 			maxx = z;
713 		}
714 		x += glyph->advance;
715 
716 		if ( glyph->miny < miny ) {
717 			miny = glyph->miny;
718 		}
719 		if ( glyph->maxy > maxy ) {
720 			maxy = glyph->maxy;
721 		}
722 	}
723 
724 	/* Fill the bounds rectangle */
725 	ret.w = (maxx - minx);
726 	//ret.h = (maxy - miny); /* This is correct, but breaks many applications */
727 	ret.h = font->height;
728 
729 	return ret;
730 }
731 
sge_TTF_TextSize(sge_TTFont * font,const char * text,int a_iMaxLength)732 SDL_Rect sge_TTF_TextSize(sge_TTFont *font, const char *text, int a_iMaxLength)
733 {
734 	SDL_Rect ret; ret.x=ret.y=ret.w=ret.y=0;
735 	Uint16 *unicode_text;
736 	int unicode_len;
737 
738 	/* Copy the Latin-1 text to a UNICODE text buffer */
739 	unicode_len = strlen(text);
740 	if ( unicode_len > a_iMaxLength
741 		&& a_iMaxLength>=0 )
742 	{
743 		unicode_len = a_iMaxLength;
744 	}
745 	unicode_text = (Uint16 *)malloc((unicode_len+1)*(sizeof *unicode_text));
746 	if ( unicode_text == NULL ) {
747 		SDL_SetError("SGE - Out of memory");
748 		return ret;
749 	}
750 	ASCII_to_UNICODE( unicode_text, text, unicode_len );
751 
752 	/* Render the new text */
753 	ret = sge_TTF_TextSizeUNI(font, unicode_text);
754 
755 	/* Free the text buffer and return */
756 	free(unicode_text);
757 
758 	return ret;
759 }
760 
761 
762 
763 /**********************************************************************************/
764 /**                           TTF output functions                               **/
765 /**********************************************************************************/
766 
767 //==================================================================================
768 // TT Render (unicode)
769 // Returns an 8bit or 32bit(8/8/8/8-alpha) surface with TT text
770 //==================================================================================
sge_TTF_RenderUNICODE(sge_TTFont * font,const Uint16 * text,SDL_Color fg,SDL_Color bg)771 SDL_Surface *sge_TTF_RenderUNICODE(sge_TTFont *font,const Uint16 *text, SDL_Color fg, SDL_Color bg)
772 {
773 	int xstart, width;
774 	int w, h;
775 	SDL_Surface *textbuf;
776 	SDL_Palette *palette;
777 	int index;
778 	int rdiff, gdiff, bdiff;
779 	const Uint16 *ch;
780 	Uint8 *src, *dst;
781 	Uint32 *dst32;
782 	Uint32 alpha=0;
783 	Uint32 pixel=0;
784 	Uint32 Rmask=0, Gmask=0, Bmask=0, Amask=0;
785 	int row, col;
786 	FT_Error error;
787 
788 	/* Get the dimensions of the text surface */
789 	SDL_Rect ret=sge_TTF_TextSizeUNI(font, text);
790 	w=ret.w; h=ret.h;
791 	if ( !w ) {
792 		SDL_SetError("SGE - Text has zero width");
793 		return(NULL);
794 	}
795 
796 	/* Create the target surface */
797 	width = w;
798 	if(_sge_TTF_AA!=2) /* Allocate an 8-bit pixmap */
799 		textbuf = SDL_AllocSurface(SDL_SWSURFACE, w, h, 8, 0, 0, 0, 0);
800 	else{ /* Allocate an 32-bit alpha pixmap */
801 		if ( SDL_BYTEORDER == SDL_LIL_ENDIAN ) {
802 			Rmask = 0x000000FF;
803 			Gmask = 0x0000FF00;
804 			Bmask = 0x00FF0000;
805 			Amask = 0xFF000000;
806 		} else {
807 			Rmask = 0xFF000000;
808 			Gmask = 0x00FF0000;
809 			Bmask = 0x0000FF00;
810 			Amask = 0x000000FF;
811 		}
812 		textbuf = SDL_AllocSurface(SDL_SWSURFACE, w, h, 32, Rmask, Gmask, Bmask, Amask);
813 	}
814 
815 	if ( textbuf == NULL ) {
816 		SDL_SetError("SGE - Out of memory");
817 		return(NULL);
818 	}
819 
820 
821 	/* Setup our colors */
822 	switch(_sge_TTF_AA){
823 
824 		case 0:{  /* No fancy antialiasing or alpha component */
825 			palette = textbuf->format->palette;
826 
827 			palette->colors[0].r = bg.r;
828 			palette->colors[0].g = bg.g;
829 			palette->colors[0].b = bg.b;
830 			palette->colors[1].r = fg.r;
831 			palette->colors[1].g = fg.g;
832 			palette->colors[1].b = fg.b;
833 		}
834 		break;
835 
836 		case 1:{  /* Fill the palette with NUM_GRAYS levels of shading from bg to fg */
837 			palette = textbuf->format->palette;
838 
839 			rdiff = fg.r - bg.r;
840 			gdiff = fg.g - bg.g;
841 			bdiff = fg.b - bg.b;
842 			for ( index=0; index< NUM_GRAYS; ++index ) {
843 				palette->colors[index].r = bg.r + (index*rdiff)/(NUM_GRAYS-1);
844 				palette->colors[index].g = bg.g + (index*gdiff)/(NUM_GRAYS-1);
845 				palette->colors[index].b = bg.b + (index*bdiff)/(NUM_GRAYS-1);
846 			}
847 		}
848 		break;
849 
850 		case 2:{  /* Alpha component magic */
851 			sge_ClearSurface(textbuf, SDL_MapRGBA(textbuf->format, bg.r,bg.g,bg.b,SDL_ALPHA_TRANSPARENT));
852 			//pixel = (fg.r<<16)|(fg.g<<8)|fg.b;
853 			pixel = (fg.b<<16)|(fg.g<<8)|fg.r;
854 		}
855 		break;
856 	}
857 
858 
859 	/* Load and render each character */
860 	xstart = 0;
861 	for ( ch=text; *ch; ++ch ) {
862 		error = Find_Glyph(font, *ch, CACHED_METRICS|CACHED_PIXMAP);
863 
864 		if ( ! error ) {
865 			w = font->current->pixmap.width;
866 			src = (Uint8 *)font->current->pixmap.buffer;
867 			for ( row = 0; row < font->current->pixmap.rows; ++row ) {
868 				dst = (Uint8 *)textbuf->pixels + (row + font->current->yoffset)* textbuf->pitch + xstart + font->current->minx;
869 
870 				switch(_sge_TTF_AA){
871 
872 					case 0:{  /* Normal */
873 						src = font->current->pixmap.buffer + row * font->current->pixmap.pitch;
874 						for ( col=w; col>0; --col ) {
875 							*dst++ |= (*src++<NUM_GRAYS/2)? 0:1;
876 						}
877 					}
878 					break;
879 					case 1:{  /* Antialiasing */
880 						src = font->current->pixmap.buffer + row * font->current->pixmap.pitch;
881 						for ( col=w; col>0; --col ) {
882 							*dst++ |= *src++;
883 						}
884 					}
885 					break;
886 
887 					case 2:{  /* Alpha */
888 						dst32 = (Uint32 *)textbuf->pixels + (row + font->current->yoffset)* textbuf->pitch/4 + xstart + font->current->minx;
889 						for ( col=w; col>0; --col ) {
890 							alpha = *src++;
891 							*dst32++ |= pixel | (alpha << 24);
892 						}
893 					}
894 					break;
895 				}
896 			}
897 
898 			xstart += font->current->advance;
899 			if ( font->style & SGE_TTF_BOLD ) {
900 				xstart += font->glyph_overhang;
901 			}
902 		}
903 	}
904 
905 	/* Handle the underline style */
906 	if ( font->style & SGE_TTF_UNDERLINE ) {
907 		int row_offset;
908 
909 		row_offset = font->ascent - font->underline_offset - 1;
910 		if ( row_offset > textbuf->h ) {
911 			row_offset = (textbuf->h-1) - font->underline_height;
912 		}
913 
914 		if(_sge_TTF_AA==0){
915 			dst = (Uint8 *)textbuf->pixels + row_offset * textbuf->pitch;
916 			for ( row=font->underline_height; row>0; --row ) {
917 				memset(dst, 1, textbuf->w );
918 				dst += textbuf->pitch;
919 			}
920 		}else if(_sge_TTF_AA==1){
921 			dst = (Uint8 *)textbuf->pixels + row_offset * textbuf->pitch;
922 			for ( row=font->underline_height; row>0; --row ) {
923 				memset(dst, NUM_GRAYS - 1, textbuf->w );
924 				dst += textbuf->pitch;
925 			}
926 		}else{
927 			pixel |= Amask;
928 			dst32 = (Uint32 *)textbuf->pixels+row_offset*textbuf->pitch/4;
929 			for ( row=font->underline_height; row>0; --row ) {
930 				for ( col=0; col < textbuf->w; ++col ) {
931 					dst32[col] = pixel;
932 				}
933 				dst32 += textbuf->pitch/4;
934 			}
935 		}
936 	}
937 	return(textbuf);
938 }
939 
940 
941 //==================================================================================
942 // Renders the Unicode string to TrueType on surface, with the color fcolor.
943 // bcolor is the target color for the antialiasing.
944 // Alpha sets the transparency of the text (255-solid, 0-max).
945 //==================================================================================
sge_tt_textout_UNI(SDL_Surface * Surface,sge_TTFont * font,const Uint16 * uni,Sint16 x,Sint16 y,Uint32 fcolor,Uint32 bcolor,int Alpha)946 SDL_Rect sge_tt_textout_UNI(SDL_Surface *Surface, sge_TTFont *font, const Uint16 *uni, Sint16 x, Sint16 y, Uint32 fcolor, Uint32 bcolor, int Alpha)
947 {
948 	SDL_Rect ret; ret.x=0; ret.y=0; ret.w=0; ret.h=0;
949 
950 	SDL_Color temp;
951 	SDL_Surface *text;
952 
953 	text=sge_TTF_RenderUNICODE(font,uni,sge_GetRGB(Surface,fcolor),sge_GetRGB(Surface,bcolor));
954 	if(text==NULL){return ret;}
955 
956  	/* Align the surface text to the baseline */
957 	Uint16 ascent=font->ascent;
958 
959 	temp=sge_GetRGB(Surface,bcolor);
960 	sge_BlitTransparent(text,Surface,0,0,x,y-ascent,text->w,text->h,SDL_MapRGB(text->format,temp.r,temp.g,temp.b),Alpha);
961 	sge_UpdateRect(Surface,x,y-ascent,text->w,text->h);
962 
963 	ret.x=x; ret.y=y-ascent; ret.w=text->w; ret.h=text->h;
964 
965 	SDL_FreeSurface(text);
966 	return ret;
967 }
968 
969 
970 //==================================================================================
971 // Renders the Unicode string to TrueType on surface, with the color fcolor.
972 // bcolor is the target color for the antialiasing.
973 // Alpha sets the transparency of the text (0-solid, 255-max). (RGB)
974 //==================================================================================
sge_tt_textout_UNI(SDL_Surface * Surface,sge_TTFont * font,const Uint16 * uni,Sint16 x,Sint16 y,Uint8 fR,Uint8 fG,Uint8 fB,Uint8 bR,Uint8 bG,Uint8 bB,int Alpha)975 SDL_Rect sge_tt_textout_UNI(SDL_Surface *Surface, sge_TTFont *font, const Uint16 *uni, Sint16 x, Sint16 y, Uint8 fR, Uint8 fG, Uint8 fB, Uint8 bR, Uint8 bG, Uint8 bB, int Alpha)
976 {
977 	SDL_Rect ret; ret.x=0; ret.y=0; ret.w=0; ret.h=0;
978 	SDL_Surface *text;
979 
980 	text=sge_TTF_RenderUNICODE(font,uni,sge_FillPaletteEntry(fR,fG,fB),sge_FillPaletteEntry(bR,bG,bB));
981 	if(text==NULL){return ret;}
982 
983 	/* Align the surface text to the baseline */
984 	Uint16 ascent=font->ascent;
985 
986 	sge_BlitTransparent(text,Surface,0,0,x,y-ascent,text->w,text->h,SDL_MapRGB(text->format,bR,bG,bB),Alpha);
987 
988 	sge_UpdateRect(Surface,x,y-ascent,text->w,text->h);
989 
990 	ret.x=x; ret.y=y-ascent; ret.w=text->w; ret.h=text->h;
991 
992 	SDL_FreeSurface(text);
993 	return ret;
994 }
995 
996 
997 //==================================================================================
998 // Renders the Latin-1 string to TrueType on surface, with the color fcolor.
999 // bcolor is the target color for the antialiasing.
1000 // Alpha sets the transparency of the text (0-solid, 255-max).
1001 //==================================================================================
sge_tt_textout(SDL_Surface * Surface,sge_TTFont * font,const char * string,Sint16 x,Sint16 y,Uint32 fcolor,Uint32 bcolor,int Alpha)1002 SDL_Rect sge_tt_textout(SDL_Surface *Surface, sge_TTFont *font, const char *string, Sint16 x, Sint16 y, Uint32 fcolor, Uint32 bcolor, int Alpha)
1003 {
1004 	SDL_Rect ret;
1005 	Uint16 *uni;
1006 
1007 	uni=sge_Latin1_Uni(string);
1008 
1009 	ret=sge_tt_textout_UNI(Surface,font,uni,x,y,fcolor,bcolor,Alpha);
1010 	free(uni);
1011 
1012 	return ret;
1013 }
1014 
1015 //==================================================================================
1016 // Renders the Latin-1 string to TrueType on surface, with the color fcolor.
1017 // bcolor is the target color for the antialiasing.
1018 // Alpha sets the transparency of the text (0-solid, 255-max). (RGB)
1019 //==================================================================================
sge_tt_textout(SDL_Surface * Surface,sge_TTFont * font,const char * string,Sint16 x,Sint16 y,Uint8 fR,Uint8 fG,Uint8 fB,Uint8 bR,Uint8 bG,Uint8 bB,int Alpha)1020 SDL_Rect sge_tt_textout(SDL_Surface *Surface, sge_TTFont *font, const char *string, Sint16 x, Sint16 y, Uint8 fR, Uint8 fG, Uint8 fB, Uint8 bR, Uint8 bG, Uint8 bB, int Alpha)
1021 {
1022 	SDL_Rect ret;
1023 	Uint16 *uni;
1024 
1025 	uni=sge_Latin1_Uni(string);
1026 
1027 	ret=sge_tt_textout_UNI(Surface,font,uni,x,y, fR,fG,fB, bR,bG,bB, Alpha);
1028 	free(uni);
1029 
1030 	return ret;
1031 }
1032 
1033 
1034 //==================================================================================
1035 // Renders the UTF-8 string to TrueType on surface, with the color fcolor.
1036 // bcolor is the target color for the antialiasing.
1037 // Alpha sets the transparency of the text (0-solid, 255-max).
1038 //==================================================================================
sge_tt_textout_UTF8(SDL_Surface * Surface,sge_TTFont * font,const char * string,Sint16 x,Sint16 y,Uint32 fcolor,Uint32 bcolor,int Alpha)1039 SDL_Rect sge_tt_textout_UTF8(SDL_Surface *Surface, sge_TTFont *font, const char *string, Sint16 x, Sint16 y, Uint32 fcolor, Uint32 bcolor, int Alpha)
1040 {
1041 	SDL_Rect ret;
1042 	Uint16 *uni;
1043 
1044 	uni=sge_UTF8_Uni(string);
1045 
1046 	ret=sge_tt_textout_UNI(Surface,font,uni,x,y,fcolor,bcolor,Alpha);
1047 	free(uni);
1048 
1049 	return ret;
1050 }
1051 
1052 //==================================================================================
1053 // Renders the UTF-8 string to TrueType on surface, with the color fcolor.
1054 // bcolor is the target color for the antialiasing.
1055 // Alpha sets the transparency of the text (0-solid, 255-max). (RGB)
1056 //==================================================================================
sge_tt_textout_UTF8(SDL_Surface * Surface,sge_TTFont * font,const char * string,Sint16 x,Sint16 y,Uint8 fR,Uint8 fG,Uint8 fB,Uint8 bR,Uint8 bG,Uint8 bB,int Alpha)1057 SDL_Rect sge_tt_textout_UTF8(SDL_Surface *Surface, sge_TTFont *font, const char *string, Sint16 x, Sint16 y, Uint8 fR, Uint8 fG, Uint8 fB, Uint8 bR, Uint8 bG, Uint8 bB, int Alpha)
1058 {
1059 	SDL_Rect ret;
1060 	Uint16 *uni;
1061 
1062 	uni=sge_UTF8_Uni(string);
1063 
1064 	ret=sge_tt_textout_UNI(Surface,font,uni,x,y, fR,fG,fB, bR,bG,bB, Alpha);
1065 	free(uni);
1066 
1067 	return ret;
1068 }
1069 
1070 
1071 //==================================================================================
1072 // Renders the formatet Latin-1 string to TrueType on surface, with the color fcolor.
1073 // bcolor is the target color for the antialiasing.
1074 // Alpha sets the transparency of the text (0-solid, 255-max). (RGB ONLY)
1075 // * just like printf(char *format,...) *
1076 //==================================================================================
sge_tt_textoutf(SDL_Surface * Surface,sge_TTFont * font,Sint16 x,Sint16 y,Uint8 fR,Uint8 fG,Uint8 fB,Uint8 bR,Uint8 bG,Uint8 bB,int Alpha,const char * format,...)1077 SDL_Rect sge_tt_textoutf(SDL_Surface *Surface, sge_TTFont *font, Sint16 x, Sint16 y, Uint8 fR, Uint8 fG, Uint8 fB, Uint8 bR, Uint8 bG, Uint8 bB, int Alpha ,const char *format,...)
1078 {
1079 	char buf[256];
1080 
1081 	va_list ap;
1082 
1083 	#ifdef __WIN32__
1084 	va_start((va_list*)ap, format); //Stupid win32 crosscompiler
1085 	#else
1086 	va_start(ap, format);
1087 	#endif
1088 
1089 	vsprintf(buf, format, ap);
1090 	va_end(ap);
1091 
1092 	return sge_tt_textout(Surface, font, buf, x,y, fR,fG,fB, bR,bG,bB, Alpha);
1093 }
1094 
1095 
1096 
1097 
1098 /**********************************************************************************/
1099 /**                          TTF 'input' functions                               **/
1100 /**********************************************************************************/
1101 
1102 // First some internel functions for TTF input
1103 
1104 //==================================================================================
1105 // Fast update function for TTF input
1106 //
1107 // type=0 - in ret smaller then out ret
1108 // type=1 - in ret bigger then out ret
1109 // type=3 - safe
1110 //==================================================================================
fast_update(SDL_Surface * Surface,SDL_Surface * buffer,SDL_Rect ret,int type,sge_TTFont * font,Uint16 * string,Sint16 x,Sint16 y,Uint32 fcol,Uint32 bcol,int Alpha)1111 SDL_Rect fast_update(SDL_Surface *Surface,SDL_Surface *buffer,SDL_Rect ret, int type,sge_TTFont *font,Uint16 *string, Sint16 x,Sint16 y, Uint32 fcol, Uint32 bcol,int Alpha)
1112 {
1113 	if(type==0){
1114   	sge_Update_OFF();
1115 		sge_FilledRect(Surface, ret.x, ret.y, ret.x+ret.w, ret.y+ret.h, bcol);
1116 		ret=sge_tt_textout_UNI(Surface,font,string, x,y, fcol, bcol, 0);
1117 		sge_Update_ON();
1118 		sge_UpdateRect(Surface, ret.x, ret.y, ret.w, ret.h);
1119 	}
1120 	else if(type==1){
1121   	SDL_Rect temp;
1122 
1123   	sge_Update_OFF();
1124 		sge_FilledRect(Surface, ret.x, ret.y, ret.x+ret.w, ret.y+ret.h, bcol);
1125 		temp=sge_tt_textout_UNI(Surface,font,string, x,y, fcol, bcol, 0);
1126 		sge_Update_ON();
1127 		sge_UpdateRect(Surface, ret.x, ret.y, ret.w, ret.h);
1128 		ret=temp;
1129 	}
1130 	else{
1131   	SDL_Rect temp;
1132 
1133   	sge_Update_OFF();
1134 		sge_FilledRect(Surface, ret.x, ret.y, ret.x+ret.w, ret.y+ret.h, bcol);
1135 		temp=sge_tt_textout_UNI(Surface,font,string, x,y, fcol, bcol, 0);
1136 		sge_Update_ON();
1137 		if(ret.w>=temp.w){
1138 			sge_UpdateRect(Surface, ret.x, ret.y, ret.w, ret.h);
1139 		}
1140 		else{
1141 			sge_UpdateRect(Surface, temp.x, temp.y, temp.w, temp.h);
1142 		}
1143 		ret=temp;
1144 	}
1145 	return ret;
1146 }
1147 
1148 //==================================================================================
1149 // Update function for TTF input that preserve background
1150 //
1151 // type=0 - in ret smaller then out ret
1152 // type=1 - in ret bigger then out ret
1153 // type=3 - safe
1154 //==================================================================================
nice_update(SDL_Surface * Surface,SDL_Surface * buffer,SDL_Rect ret,int type,sge_TTFont * font,Uint16 * string,Sint16 x,Sint16 y,Uint32 fcol,Uint32 bcol,int Alpha)1155 SDL_Rect nice_update(SDL_Surface *Surface,SDL_Surface *buffer,SDL_Rect ret, int type,sge_TTFont *font,Uint16 *string, Sint16 x,Sint16 y, Uint32 fcol, Uint32 bcol, int Alpha)
1156 {
1157  	if(type==0){
1158   	sge_Update_OFF();
1159 		sge_Blit(buffer,Surface, ret.x, ret.y, ret.x, ret.y, ret.w, ret.h);
1160 		ret=sge_tt_textout_UNI(Surface,font,string, x,y, fcol, bcol, Alpha);
1161 		sge_Update_ON();
1162 		sge_UpdateRect(Surface, ret.x, ret.y, ret.w, ret.h);
1163 	}
1164 	else if(type==1){
1165   	SDL_Rect temp;
1166 
1167   	sge_Update_OFF();
1168 		sge_Blit(buffer,Surface, ret.x, ret.y, ret.x, ret.y, ret.w, ret.h);
1169 		temp=sge_tt_textout_UNI(Surface,font,string, x,y, fcol, bcol, Alpha);
1170 		sge_Update_ON();
1171 		sge_UpdateRect(Surface, ret.x, ret.y, ret.w, ret.h);
1172 		ret=temp;
1173 	}
1174 	else{
1175   	SDL_Rect temp;
1176 
1177   	sge_Update_OFF();
1178 		sge_Blit(buffer,Surface, ret.x, ret.y, ret.x, ret.y, ret.w, ret.h);
1179 		temp=sge_tt_textout_UNI(Surface,font,string, x,y, fcol, bcol, Alpha);
1180 		sge_Update_ON();
1181 		if(ret.w>=temp.w){
1182 			sge_UpdateRect(Surface, ret.x, ret.y, ret.w, ret.h);
1183 		}
1184 		else{
1185 			sge_UpdateRect(Surface, temp.x, temp.y, temp.w, temp.h);
1186 		}
1187 		ret=temp;
1188 	}
1189 
1190 	return ret;
1191 }
1192 #endif /* _SGE_NOTTF */
1193 
1194 
1195 //==================================================================================
1196 // Handle keyrepeats
1197 //==================================================================================
keyrepeat(SDL_Event * event,int wait)1198 int keyrepeat(SDL_Event *event, int wait)
1199 {
1200 	int keydown=1,c=0,ret=0;
1201 	SDL_Event ev;
1202 
1203 	do{
1204 		if(SDL_PollEvent(&ev)==1){
1205  			if(ev.type==SDL_QUIT){ret=-1;keydown=0;}
1206 			if(ev.type==SDL_KEYUP || ev.type==SDL_KEYDOWN){ //Keyrepeat cancelled
1207 				keydown=0;
1208 				if(ev.type==SDL_KEYDOWN){
1209 					SDL_PeepEvents(&ev,1, SDL_ADDEVENT, 0); //Return the newly pressed key to the event queue
1210 				}
1211 			}
1212 		}
1213 		SDL_Delay(10);
1214 		c++;
1215 		if(c>wait && keydown==1){ //trigers keyrepeat
1216 			ret=1;
1217 			SDL_PeepEvents(event,1, SDL_ADDEVENT, 0); //Return the old key to the event queue
1218 			keydown=0;
1219 		}
1220 	}while(keydown==1);
1221 
1222 	return ret;
1223 }
1224 
1225 
1226 //==================================================================================
1227 // Insert a element
1228 //==================================================================================
insert_char(Uint16 * string,Uint16 ch,int pos,int max)1229 void insert_char(Uint16 *string, Uint16 ch, int pos, int max)
1230 {
1231 	if(pos>max || pos<0){return;}
1232 	else if(pos==max){string[pos]=ch;}
1233 	else{
1234   	for(int i=max; i>=pos; i--){
1235 			string[i+1]=string[i];
1236 		}
1237 		string[pos]=ch;
1238 	}
1239 }
1240 
1241 
1242 //==================================================================================
1243 // Delete a element
1244 //==================================================================================
delete_char(Uint16 * string,int pos,int max)1245 void delete_char(Uint16 *string, int pos, int max)
1246 {
1247 	if(pos>max || pos<0){return;}
1248 	else if(pos==max){string[pos]=0;}
1249 	else{
1250   	for(int i=pos; i<=max-1; i++){
1251 			string[i]=string[i+1];
1252 		}
1253 		string[max]=0;
1254 	}
1255 }
1256 
1257 
1258 #ifndef _SGE_NOTTF
1259 // These functions handle keyboard input and shows the result on screen. The text
1260 // can be edited with [Backspace], [Delete], [Left arrow] and [Right arrow].
1261 // Text input is terminated when [Return] or [Enter] is pressed, or if a quit event
1262 // is recived.
1263 // The sge_tt_input functions puts the result in 'string'.
1264 //
1265 // Flags: SGE_IBG   - Keeps background, else bye bye background
1266 //        SGE_IDEL  - Delete text on exit
1267 //        SGE_INOKR - No keyrepeat
1268 // (use OR | to give more than one)
1269 //
1270 // If you want a 'default' text you can copy it to string before call and set pos to
1271 // the first empty element in string - ex. "Hello" => pos=5. If not - zero.
1272 // len is the max numbers of chars editable - ex. if you set the default text to "100"
1273 // and only want 3 digits out, set len to 3. string should have atleast len+1 elements
1274 // allocated
1275 // This is *not* a fast, optimized function - but it gets the job done...
1276 
1277 // Return:
1278 // Zero or above - the lenght of the string
1279 // -1 recieved a quit event (the lenght is lost)
1280 // -2 invalid indata
1281 // -3 out of memory
1282 
1283 //==================================================================================
1284 // Text input UNICODE (the core)
1285 //==================================================================================
sge_tt_input_UNI(SDL_Surface * screen,sge_TTFont * font,Uint16 * string,Uint8 flags,int pos,int len,Sint16 x,Sint16 y,Uint32 fcol,Uint32 bcol,int Alpha)1286 int sge_tt_input_UNI(SDL_Surface *screen,sge_TTFont *font,Uint16 *string, Uint8 flags, int pos,int len,Sint16 x,Sint16 y, Uint32 fcol, Uint32 bcol, int Alpha)
1287 {
1288 	if(len<pos || pos<0 || len<0){return -2;}
1289 
1290 	Uint16 cur=124;//The charactar for the cursor - '|'
1291 	int max;       //The strings size
1292 
1293 	/* Set update function */
1294 	SDL_Rect (*_update)(SDL_Surface *screen,SDL_Surface *buffer,SDL_Rect ret, int type,sge_TTFont *font,Uint16 *string, Sint16 x,Sint16 y, Uint32 fcol, Uint32 bcol, int Alpha);
1295 	SDL_Surface *buffer;
1296 
1297 	if(flags&SGE_FLAG1){   /* Keep background? */
1298 		_update=nice_update;
1299 		buffer=SDL_DisplayFormat(screen); /* Fixme: Yum! Memory! */
1300 		if(buffer==NULL){SDL_SetError("SGE - Out of memory");return -3;}
1301 	}
1302 	else{               /* nope */
1303 	 	_update=fast_update;
1304 		buffer=NULL;
1305 		Alpha=0;
1306 	}
1307 
1308 	SDL_Rect ret;
1309 
1310 	max=pos;
1311 	string[pos+1]=0;
1312 
1313 	SDL_EnableUNICODE(1);
1314 
1315 	/* Init cursor */
1316 	string[pos]=cur;
1317 	ret=sge_tt_textout_UNI(screen,font,string, x,y, fcol, bcol, Alpha);
1318 
1319 	SDL_Event event;
1320 	int quit=0;
1321 	do{
1322 		/* Check events */
1323 		SDL_WaitEvent(&event);
1324 		if(event.type==SDL_QUIT){quit=-1;}
1325 		else if(event.type==SDL_KEYDOWN && event.key.keysym.sym==SDLK_ESCAPE){quit=1;}
1326 		else if(event.type==SDL_KEYDOWN && (event.key.keysym.sym==SDLK_RETURN || event.key.keysym.sym==SDLK_KP_ENTER)){quit=1;}
1327 		else if(event.type==SDL_KEYDOWN && event.key.keysym.sym==SDLK_BACKSPACE){
1328     	if(pos>0){
1329 				/* Delete char cursor-1 */
1330 				delete_char(string,pos-1,max); pos--; max--;
1331 
1332 				ret=_update(screen,buffer,ret,1,font,string, x,y, fcol, bcol, Alpha);
1333 
1334 				/* Handle keyrepeat */
1335 				if(!(flags&SGE_FLAG3))
1336 					if(keyrepeat(&event, 20)==-1){quit=-1;}
1337 			}
1338 		}
1339 		else if(event.type==SDL_KEYDOWN && event.key.keysym.sym==SDLK_RIGHT){
1340 			if(pos!=max && pos!=len){
1341 				/* Move cursor right */
1342 				delete_char(string,pos,max);pos++;
1343 				insert_char(string,cur,pos,max);
1344 
1345 				ret=_update(screen,buffer,ret,3,font,string, x,y, fcol, bcol, Alpha);
1346 
1347 				/* Handle keyrepeat */
1348 				if(!(flags&SGE_FLAG3))
1349 					if(keyrepeat(&event, 20)==-1){quit=-1;}
1350 			}
1351 		}
1352 		else if(event.type==SDL_KEYDOWN && event.key.keysym.sym==SDLK_LEFT){
1353 			if(pos>0){
1354 				/* Move cursor left */
1355 				delete_char(string,pos,max);pos--;
1356 				insert_char(string,cur,pos,max);
1357 
1358 				ret=_update(screen,buffer,ret,3,font,string, x,y, fcol, bcol, Alpha);
1359 
1360 				/* Handle keyrepeat */
1361 				if(!(flags&SGE_FLAG3))
1362 					if(keyrepeat(&event, 20)==-1){quit=-1;}
1363 			}
1364 		}
1365 		else if(event.type==SDL_KEYDOWN && event.key.keysym.sym==SDLK_DELETE){
1366 			/* Delete char cursor+1 */
1367 			if(pos!=max && pos!=len){
1368 				delete_char(string,pos+1,max);max--;
1369 
1370 				ret=_update(screen,buffer,ret,1,font,string, x,y, fcol, bcol, Alpha);
1371 
1372 				/* Handle keyrepeat */
1373 				if(!(flags&SGE_FLAG3))
1374 					if(keyrepeat(&event, 20)==-1){quit=-1;}
1375 			}
1376 		}
1377 		else if(event.type==SDL_KEYDOWN && event.key.keysym.unicode!=0){
1378 			/* Insert new char */
1379 			if(max!=len){
1380 				max++;
1381 				insert_char(string, event.key.keysym.unicode, pos,max); pos++;
1382 
1383 				ret=_update(screen,buffer,ret,0,font,string, x,y, fcol, bcol, Alpha);
1384 
1385 				/* Handle keyrepeat */
1386 				if(!(flags&SGE_FLAG3))
1387 					if(keyrepeat(&event, 40)==-1){quit=-1;}
1388 			}
1389 		}
1390 	}while(quit==0);
1391 
1392 	/* Remove the cursor from string */
1393 	delete_char(string,pos,max);
1394 
1395 	if(flags&SGE_FLAG2){ //Remove the text
1396 		if(flags&SGE_FLAG1){
1397 			sge_Blit(buffer,screen, ret.x, ret.y, ret.x, ret.y, ret.w, ret.h);
1398 			sge_UpdateRect(screen, ret.x, ret.y, ret.w, ret.h);
1399 		}
1400 		else{
1401 			sge_FilledRect(screen,ret.x, ret.y, ret.x+ret.w, ret.y+ret.h,bcol);
1402 		}
1403 	}
1404 	else{ //Draw text without cursor
1405 		ret=_update(screen,buffer,ret,1,font,string, x,y, fcol, bcol, Alpha);
1406 	}
1407 
1408 
1409 	if(flags&SGE_FLAG1){SDL_FreeSurface(buffer);}
1410 
1411 	if(quit==-1){return -1;} //Waaa! The user killed me!
1412 	return max;
1413 }
1414 
1415 
1416 
1417 
CReadline(SDL_Surface * a_poScreen,sge_TTFont * a_poFont,char * a_pcString,int a_iPos,int a_iLen,int a_x,int a_y,int a_w,Uint32 a_iFCol,Uint32 a_iBCol,int a_iAlpha)1418 CReadline::CReadline( SDL_Surface *a_poScreen, sge_TTFont *a_poFont,
1419 		char *a_pcString, int a_iPos, int a_iLen,
1420 		int a_x, int a_y, int a_w, Uint32 a_iFCol, Uint32 a_iBCol, int a_iAlpha )
1421 {
1422 	m_iResult = 0;
1423 	m_poScreen = a_poScreen;
1424 	m_poFont = a_poFont;
1425 	m_piString = 0;
1426 	m_iLen = -1;
1427 	w = a_w;
1428 	x = a_x;
1429 	y = a_y;
1430 
1431 	SDL_EnableUNICODE(1);
1432 
1433 	// Create background copy.
1434 
1435 	m_oWorkArea.x = x;
1436 	m_oWorkArea.y = y - sge_TTF_FontAscent(m_poFont);
1437 	m_oWorkArea.w = w;
1438 	m_oWorkArea.h = sge_TTF_FontHeight(a_poFont);
1439 
1440 	m_poBackground = sge_copy_surface( a_poScreen, m_oWorkArea.x, m_oWorkArea.y, m_oWorkArea.w, m_oWorkArea.h );
1441 
1442 	Restart( a_pcString, a_iPos, a_iLen, a_iFCol, a_iBCol, a_iAlpha );
1443 }
1444 
1445 
Restart(char * a_pcString,int a_iPos,int a_iLen,Uint32 a_iFCol,Uint32 a_iBCol,int a_iAlpha)1446 void CReadline::Restart( char *a_pcString, int a_iPos, int a_iLen,
1447 		Uint32 a_iFCol, Uint32 a_iBCol, int a_iAlpha )
1448 {
1449 	if ( NULL == m_piString
1450 		|| m_iLen <= a_iLen )
1451 	{
1452 		if ( m_piString ) delete[] m_piString;
1453 		m_iLen = a_iLen;
1454 		m_piString = new Uint16[a_iLen+2];
1455 	}
1456 
1457 	m_iResult = 0;
1458 
1459 	m_pcLatin1String = a_pcString;
1460 	m_iPos = a_iPos;
1461 	m_iFCol = a_iFCol;
1462 	m_iBCol = a_iBCol;
1463 	m_iAlpha = a_iAlpha;
1464 
1465 	// Convert the original string into an unicode string
1466 
1467 	int i;
1468 	for(i=0; i<m_iPos; i++)
1469 	{
1470 		m_piString[i]=(unsigned char)m_pcLatin1String[i];
1471 	}
1472 	m_piString[m_iPos]=0;
1473 
1474 	// Insert the cursor at the end
1475 
1476 	m_iCursor = 124;	// '|' character
1477 	m_iMax=m_iPos;
1478 	m_piString[m_iPos+1]=0;
1479 	m_piString[m_iPos]=m_iCursor;
1480 	Redraw();
1481 	SDL_EnableKeyRepeat( SDL_DEFAULT_REPEAT_DELAY/2, SDL_DEFAULT_REPEAT_INTERVAL/2 );
1482 }
1483 
1484 
~CReadline()1485 CReadline::~CReadline()
1486 {
1487 	delete[] m_piString;
1488 	SDL_FreeSurface( m_poBackground );
1489 	m_poBackground = NULL;
1490 
1491 	SDL_EnableKeyRepeat( 0, 0 );
1492 }
1493 
1494 
1495 /** Returns the current state of the line input.
1496 \retval -1	A quit event was encountered.
1497 \retval -2	Escape was pressed
1498 \retval 0	Input is in progress.
1499 \retval 1	Input has finished.
1500 */
GetResult()1501 int CReadline::GetResult()
1502 {
1503 	if ( m_iResult == 0 )
1504 	{
1505 		return m_iResult;
1506 	}
1507 
1508 	SDL_EnableKeyRepeat( 0, 0 );
1509 
1510 	sge_Blit( m_poBackground, m_poScreen, m_oUpdateRect.x, m_oUpdateRect.y,
1511 		m_oUpdateRect.x, m_oUpdateRect.y, m_oUpdateRect.w, m_oUpdateRect.h);
1512 	sge_UpdateRect(m_poScreen, m_oUpdateRect.x, m_oUpdateRect.y, m_oUpdateRect.w, m_oUpdateRect.h);
1513 
1514 	if ( m_iResult < 0 )
1515 	{
1516 		return m_iResult;
1517 	}
1518 
1519 	delete_char( m_piString, m_iPos, m_iMax );
1520 
1521 	memset( m_pcLatin1String, 0, sizeof(char)*(m_iPos+1) );
1522 	for( int i=0; i<=m_iMax; i++)
1523 	{
1524 		m_pcLatin1String[i] = (char)m_piString[i];
1525 	}
1526 
1527 	insert_char( m_piString, m_iCursor, m_iPos, m_iMax );
1528 
1529 	return 1;
1530 }
1531 
1532 
1533 
1534 
1535 /** Internal method for redrawing the string. */
Update(int a_iCode)1536 void CReadline::Update( int a_iCode )
1537 {
1538 	//m_oUpdateRect = nice_update( m_poScreen, m_poBackground, m_oUpdateRect, a_iCode, m_poFont, m_piString,
1539 	//	x, y, m_iFCol, m_iBCol, m_iAlpha );
1540 
1541 	SDL_Rect oOldClipRect;
1542 	SDL_GetClipRect( m_poScreen, &oOldClipRect );
1543 	SDL_SetClipRect( m_poScreen, &m_oWorkArea );
1544 
1545 	sge_Blit( m_poBackground, m_poScreen, 0, 0, m_oWorkArea.x, m_oWorkArea.y, m_oWorkArea.w, m_oWorkArea.h );
1546 	sge_tt_textout_UNI( m_poScreen, m_poFont, m_piString, x, y, m_iFCol, m_iBCol, m_iAlpha );
1547 	sge_UpdateRect( m_poScreen, m_oWorkArea.x, m_oWorkArea.y, m_oWorkArea.w, m_oWorkArea.h );
1548 
1549 	SDL_SetClipRect( m_poScreen, &oOldClipRect );
1550 }
1551 
1552 
Redraw()1553 void CReadline::Redraw()
1554 {
1555 	m_oUpdateRect = sge_tt_textout_UNI( m_poScreen, m_poFont, m_piString, x, y, m_iFCol, m_iBCol, m_iAlpha );
1556 	sge_UpdateRect( m_poScreen, m_oWorkArea.x, m_oWorkArea.y, m_oWorkArea.w, m_oWorkArea.h );
1557 }
1558 
1559 
Clear()1560 void CReadline::Clear()
1561 {
1562 	sge_Blit( m_poBackground, m_poScreen, 0, 0, m_oWorkArea.x, m_oWorkArea.y, m_oWorkArea.w, m_oWorkArea.h );
1563 }
1564 
1565 
1566 /** Runs the event queue until the input is finished.
1567 \see GetResult
1568 */
Execute()1569 int CReadline::Execute()
1570 {
1571 	int iRetval;
1572 	SDL_Event e;
1573 	while ( 1 )
1574 	{
1575 		SDL_WaitEvent( &e );
1576 		HandleKeyEvent( e );
1577 		iRetval = GetResult();
1578 		if ( iRetval )
1579 			break;
1580 	}
1581 
1582 	return iRetval;
1583 }
1584 
1585 
1586 
HandleKeyEvent(SDL_Event & a_roEvent)1587 void CReadline::HandleKeyEvent( SDL_Event& a_roEvent )
1588 {
1589 	if(a_roEvent.type==SDL_QUIT)
1590 	{
1591 		m_iResult = -1;
1592 		return;
1593 	}
1594 
1595 	if ( a_roEvent.type != SDL_KEYDOWN )
1596 	{
1597 		return;
1598 	}
1599 
1600 	if( a_roEvent.key.keysym.sym==SDLK_ESCAPE )
1601 	{
1602 		m_iResult = -2;
1603 		return;
1604 	}
1605 
1606 	if ( a_roEvent.key.keysym.sym==SDLK_RETURN
1607 		|| a_roEvent.key.keysym.sym==SDLK_KP_ENTER )
1608 	{
1609 		m_iResult = 1;
1610 		return;
1611 	}
1612 
1613 	if( a_roEvent.key.keysym.sym==SDLK_BACKSPACE )
1614 	{
1615 		if ( m_iPos == 0 )
1616 		{
1617 			return;
1618 		}
1619 		/* Delete char cursor-1 */
1620 		delete_char(m_piString,m_iPos-1,m_iMax);
1621 		m_iPos--;
1622 		m_iMax--;
1623 		Update( 1 );
1624 		return;
1625 	}
1626 
1627 	if( a_roEvent.key.keysym.sym==SDLK_RIGHT
1628 		&& m_iPos!=m_iMax && m_iPos!=m_iLen )
1629 	{
1630 		/* Move cursor right */
1631 		delete_char(m_piString,m_iPos,m_iMax);
1632 		m_iPos++;
1633 		insert_char(m_piString,m_iCursor,m_iPos,m_iMax);
1634 		Update( 3 );
1635 		return;
1636 	}
1637 
1638 	if ( a_roEvent.key.keysym.sym==SDLK_LEFT
1639 		&& m_iPos>0 )
1640 	{
1641 		/* Move cursor left */
1642 		delete_char(m_piString,m_iPos,m_iMax);
1643 		m_iPos--;
1644 		insert_char(m_piString,m_iCursor,m_iPos,m_iMax);
1645 		Update( 3 );
1646 		return;
1647 	}
1648 
1649 	if( a_roEvent.key.keysym.sym==SDLK_DELETE )
1650 	{
1651 		if ( m_iPos!=m_iMax && m_iPos!=m_iLen )
1652 		{
1653 			delete_char(m_piString,m_iPos+1,m_iMax);
1654 			m_iMax--;
1655 			Update( 1 );
1656 		}
1657 		return;
1658 	}
1659 
1660 	if( a_roEvent.key.keysym.unicode!=0
1661 		&& a_roEvent.key.keysym.unicode >=32
1662 		&& a_roEvent.key.keysym.unicode <=255
1663 		&& m_iMax != m_iLen )
1664 	{
1665 		m_iMax++;
1666 		insert_char(m_piString, a_roEvent.key.keysym.unicode, m_iPos, m_iMax);
1667 		m_iPos++;
1668 		Update( 0 );
1669 	}
1670 }
1671 
1672 
1673 /*
1674 SDL_Rect CReadline::NiceUpdate( SDL_Surface *Surface,SDL_Surface *buffer,
1675 	SDL_Rect ret, int type,sge_TTFont *font,Uint16 *string, Sint16 x,Sint16 y,
1676 	Uint32 fcol, Uint32 bcol, int Alpha )
1677 {
1678 	if(type==0){
1679 		sge_Update_OFF();
1680 		sge_Blit(buffer,Surface, ret.x, ret.y, ret.x, ret.y, ret.w, ret.h);
1681 		ret=sge_tt_textout_UNI(Surface,font,string, x,y, fcol, bcol, Alpha);
1682 		sge_Update_ON();
1683 		sge_UpdateRect(Surface, ret.x, ret.y, ret.w, ret.h);
1684 	}
1685 	else if(type==1){
1686   	SDL_Rect temp;
1687 
1688   	sge_Update_OFF();
1689 		sge_Blit(buffer,Surface, ret.x, ret.y, ret.x, ret.y, ret.w, ret.h);
1690 		temp=sge_tt_textout_UNI(Surface,font,string, x,y, fcol, bcol, Alpha);
1691 		sge_Update_ON();
1692 		sge_UpdateRect(Surface, ret.x, ret.y, ret.w, ret.h);
1693 		ret=temp;
1694 	}
1695 	else{
1696   	SDL_Rect temp;
1697 
1698   	sge_Update_OFF();
1699 		sge_Blit(buffer,Surface, ret.x, ret.y, ret.x, ret.y, ret.w, ret.h);
1700 		temp=sge_tt_textout_UNI(Surface,font,string, x,y, fcol, bcol, Alpha);
1701 		sge_Update_ON();
1702 		if(ret.w>=temp.w){
1703 			sge_UpdateRect(Surface, ret.x, ret.y, ret.w, ret.h);
1704 		}
1705 		else{
1706 			sge_UpdateRect(Surface, temp.x, temp.y, temp.w, temp.h);
1707 		}
1708 		ret=temp;
1709 	}
1710 
1711 	return ret;
1712 }
1713 */
1714 
1715 
1716 
1717 
1718 
1719 //==================================================================================
1720 // Text input UNICODE (RGB)
1721 //==================================================================================
sge_tt_input_UNI(SDL_Surface * screen,sge_TTFont * font,Uint16 * string,Uint8 flags,int pos,int len,Sint16 x,Sint16 y,Uint8 fR,Uint8 fG,Uint8 fB,Uint8 bR,Uint8 bG,Uint8 bB,int Alpha)1722 int sge_tt_input_UNI(SDL_Surface *screen,sge_TTFont *font,Uint16 *string,Uint8 flags, int pos,int len,Sint16 x,Sint16 y, Uint8 fR, Uint8 fG, Uint8 fB, Uint8 bR,Uint8 bG,Uint8 bB, int Alpha)
1723 {
1724 	return sge_tt_input_UNI(screen,font,string,flags,pos,len,x,y,SDL_MapRGB(screen->format, fR,fG,fB),SDL_MapRGB(screen->format, bR,bG,bB),Alpha);
1725 }
1726 
1727 
1728 //==================================================================================
1729 // Text input Latin1
1730 //
1731 // Will fail miserable if ret<0!
1732 //==================================================================================
sge_tt_input(SDL_Surface * screen,sge_TTFont * font,char * string,Uint8 flags,int pos,int len,Sint16 x,Sint16 y,Uint32 fcol,Uint32 bcol,int Alpha)1733 int sge_tt_input(SDL_Surface *screen,sge_TTFont *font,char *string,Uint8 flags, int pos,int len,Sint16 x,Sint16 y, Uint32 fcol, Uint32 bcol, int Alpha)
1734 {
1735 	if(len<pos || pos<0 || len<0){return -2;}
1736 
1737 	#ifndef __GNUC__
1738 	Uint16 *uni=new Uint16[len+2];  //ANSI C++
1739 	#else
1740 	Uint16 uni[len+2];
1741 	#endif
1742 
1743 	int ret;
1744 
1745 	int i;
1746 	if(pos!=0){
1747   	for(i=0; i<pos; i++){ //Convert Latin1 => Uni
1748     	uni[i]=(unsigned char)string[i];
1749 		}
1750 	}
1751 	uni[pos]=0;
1752 
1753 	ret=sge_tt_input_UNI(screen,font,uni,flags,pos,len,x,y,fcol,bcol,Alpha);
1754 
1755 	memset(string,0,sizeof(char)*(pos+1));
1756 	if(ret>0){
1757 		for( i=0; i<=ret; i++){ //Convert Uni => Latin1
1758 			string[i] = (char)uni[i];
1759 		}
1760 	}
1761 
1762 	#ifndef __GNUC__
1763 	delete[] uni;
1764 	#endif
1765 
1766 	return ret;
1767 }
1768 
1769 
1770 //==================================================================================
1771 // Text input Latin1 (RGB)
1772 //==================================================================================
sge_tt_input(SDL_Surface * screen,sge_TTFont * font,char * string,Uint8 flags,int pos,int len,Sint16 x,Sint16 y,Uint8 fR,Uint8 fG,Uint8 fB,Uint8 bR,Uint8 bG,Uint8 bB,int Alpha)1773 int sge_tt_input(SDL_Surface *screen,sge_TTFont *font,char *string,Uint8 flags, int pos,int len,Sint16 x,Sint16 y, Uint8 fR, Uint8 fG, Uint8 fB, Uint8 bR,Uint8 bG,Uint8 bB, int Alpha)
1774 {
1775 	return sge_tt_input(screen,font,string,flags,pos,len,x,y,SDL_MapRGB(screen->format, fR,fG,fB),SDL_MapRGB(screen->format, bR,bG,bB),Alpha);
1776 }
1777 #endif /* _SGE_NOTTF */
1778