update to autoconf-2.60
[paraslash.git] / SFont.c
1 /*
2  * Copyright (C) Karl Bartel <karlb@gmx.net> WWW: http://www.linux-games.com
3  *
4  *     This program is free software; you can redistribute it and/or modify
5  *     it under the terms of the GNU General Public License as published by
6  *     the Free Software Foundation; either version 2 of the License, or
7  *     (at your option) any later version.
8  *
9  *     This program is distributed in the hope that it will be useful,
10  *     but WITHOUT ANY WARRANTY; without even the implied warranty of
11  *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  *     GNU General Public License for more details.
13  *
14  *     You should have received a copy of the GNU General Public License
15  *     along with this program; if not, write to the Free Software
16  *     Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
17  */
18
19 /*Modified 2003, 2006 by Andre Noll */
20
21 #include <SDL/SDL.h>
22 #include "SFont.h"
23 #include <stdlib.h> /* exit */
24 #include <string.h> /* strlen */
25 SFont_FontInfo InternalFont;
26
27 Uint32 GetPixel(SDL_Surface * Surface, Sint32 X, Sint32 Y)
28 {
29
30         Uint8 *bits;
31         Uint32 Bpp;
32
33         if (X < 0)
34                 puts("SFONT ERROR: x too small in GetPixel. Report this "
35                         "to <karlb@gmx.net>");
36         if (X >= Surface->w)
37                 puts("SFONT ERROR: x too big in GetPixel. Report this to "
38                         "<karlb@gmx.net>");
39         Bpp = Surface->format->BytesPerPixel;
40         bits = ((Uint8 *) Surface->pixels) + Y * Surface->pitch + X * Bpp;
41
42         /* Get the pixel */
43         switch (Bpp) {
44         case 1:
45                 return *((Uint8 *) Surface->pixels + Y * Surface->pitch + X);
46                 break;
47         case 2:
48                 return *((Uint16 *) Surface->pixels + Y * Surface->pitch / 2 +
49                          X);
50                 break;
51         case 3:{        /* Format/endian independent  */
52                         Uint8 r, g, b;
53                         r = *((bits) + Surface->format->Rshift / 8);
54                         g = *((bits) + Surface->format->Gshift / 8);
55                         b = *((bits) + Surface->format->Bshift / 8);
56                         return SDL_MapRGB(Surface->format, r, g, b);
57                 }
58                 break;
59         case 4:
60                 return *((Uint32 *) Surface->pixels + Y * Surface->pitch / 4 +
61                          X);
62                 break;
63         }
64
65         return -1;
66 }
67
68 void InitFont2(SFont_FontInfo * Font)
69 {
70         int x = 0, i = 0;
71
72         if (!Font->Surface) {
73                 printf("The font has not been loaded!\n");
74                 exit(EXIT_FAILURE);
75         }
76
77         if (SDL_MUSTLOCK(Font->Surface))
78                 SDL_LockSurface(Font->Surface);
79
80         while (x < Font->Surface->w) {
81                 if (GetPixel(Font->Surface, x, 0) ==
82                     SDL_MapRGB(Font->Surface->format, 255, 0, 255)) {
83                         Font->CharPos[i++] = x;
84                         while ((x < Font->Surface->w - 1)
85                                && (GetPixel(Font->Surface, x, 0) ==
86                                    SDL_MapRGB(Font->Surface->format, 255, 0,
87                                               255)))
88                                 x++;
89                         Font->CharPos[i++] = x;
90                 }
91                 x++;
92         }
93         if (SDL_MUSTLOCK(Font->Surface))
94                 SDL_UnlockSurface(Font->Surface);
95
96         Font->h = Font->Surface->h;
97         SDL_SetColorKey(Font->Surface, SDL_SRCCOLORKEY,
98                         GetPixel(Font->Surface, 0, Font->Surface->h - 1));
99 }
100
101 #if 0
102 void InitFont(SDL_Surface * Font)
103 {
104         InternalFont.Surface = Font;
105         InitFont2(&InternalFont);
106 }
107
108 #endif
109
110
111
112 void PutString2(SDL_Surface * Surface, SFont_FontInfo * Font, int x, int y,
113                 const char *text)
114 {
115         int ofs;
116         int i = 0;
117         SDL_Rect srcrect, dstrect;
118
119         while (text[i] != '\0') {
120                 if (text[i] == ' ') {
121                         x += Font->CharPos[2] - Font->CharPos[1];
122                         i++;
123                 } else {
124                         ofs = ((unsigned char) text[i] - 33) * 2 + 1;
125                         srcrect.w = dstrect.w = (Font->CharPos[ofs + 2]
126                                 + Font->CharPos[ofs + 1]) / 2
127                                 - (Font->CharPos[ofs] + Font->CharPos[ofs - 1])
128                                          / 2;
129                         srcrect.h = dstrect.h = Font->Surface->h - 1;
130                         srcrect.x =
131                             (Font->CharPos[ofs] + Font->CharPos[ofs - 1]) / 2;
132                         srcrect.y = 1;
133                         dstrect.x =
134                             x - (float) (Font->CharPos[ofs] -
135                                          Font->CharPos[ofs - 1]) / 2;
136                         dstrect.y = y;
137                         SDL_BlitSurface(Font->Surface, &srcrect, Surface,
138                                         &dstrect);
139                         x += Font->CharPos[ofs + 1] - Font->CharPos[ofs];
140                         i++;
141                 }
142         }
143 }
144
145 int TextWidth2(SFont_FontInfo * Font, char *text)
146 {
147         int ofs = 0;
148         int i = 0, x = 0;
149
150         while (text[i] != '\0') {
151                 if (text[i] == ' ') {
152                         x += Font->CharPos[2] - Font->CharPos[1];
153                         i++;
154                 } else {
155                         ofs = ((unsigned char) text[i] - 33) * 2 + 1;
156                         x += Font->CharPos[ofs + 1] - Font->CharPos[ofs];
157                         i++;
158                 }
159         }
160         return x;
161 }
162
163 void SFont_InternalInput(SDL_Surface * Dest, SFont_FontInfo * Font, int x,
164                 int y, int PixelWidth, char *text)
165 {
166         SDL_Event event;
167         int ch = -1, blink = 0;
168         long blinktimer = 0;
169         SDL_Surface *Back;
170         SDL_Rect rect;
171         int previous;
172
173         Back = SDL_AllocSurface(Dest->flags,
174                 Dest->w,
175                 Font->h,
176                 Dest->format->BitsPerPixel,
177                 Dest->format->Rmask,
178                 Dest->format->Gmask, Dest->format->Bmask, 0);
179         rect.x = 0;
180         rect.y = y;
181         rect.w = Dest->w;
182         rect.h = Font->Surface->h;
183         SDL_BlitSurface(Dest, &rect, Back, NULL);
184         PutString2(Dest, Font, x, y, text);
185         SDL_UpdateRects(Dest, 1, &rect);
186
187         /* start input */
188         previous = SDL_EnableUNICODE(1);
189         blinktimer = SDL_GetTicks();
190         while (ch != SDLK_RETURN) {
191                 if (event.type == SDL_KEYDOWN) {
192                         ch = event.key.keysym.unicode;
193                         if (((ch > 31) || (ch == '\b')) && (ch < 128)) {
194                                 if ((ch == '\b') && (strlen(text) > 0))
195                                         text[strlen(text) - 1] = '\0';
196                                 else if (ch != '\b')
197                                         sprintf(text, "%s%c", text, ch);
198                                 if (TextWidth2(Font, text) > PixelWidth)
199                                         text[strlen(text) - 1] = '\0';
200                                 SDL_BlitSurface(Back, NULL, Dest, &rect);
201                                 PutString2(Dest, Font, x, y, text);
202                                 SDL_UpdateRects(Dest, 1, &rect);
203                                 SDL_WaitEvent(&event);
204                         }
205                 }
206                 if (SDL_GetTicks() > blinktimer) {
207                         blink = 1 - blink;
208                         blinktimer = SDL_GetTicks() + 500;
209                         if (blink) {
210                                 PutString2(Dest, Font,
211                                            x + TextWidth2(Font, text), y, "|");
212                                 SDL_UpdateRects(Dest, 1, &rect);
213                         } else {
214                                 SDL_BlitSurface(Back, NULL, Dest, &rect);
215                                 PutString2(Dest, Font, x, y, text);
216                                 SDL_UpdateRects(Dest, 1, &rect);
217                         }
218                 }
219                 SDL_Delay(1);
220                 SDL_PollEvent(&event);
221         }
222         text[strlen(text)] = '\0';
223         SDL_FreeSurface(Back);
224         /* restore the previous state */
225         SDL_EnableUNICODE(previous);
226 }
227
228 void SFont_Input2(SDL_Surface * Dest, SFont_FontInfo * Font, int x, int y,
229                   int PixelWidth, char *text)
230 {
231         SFont_InternalInput(Dest, Font, x, y, PixelWidth, text);
232 }