blob.c: Implement pattern matching.
[paraslash.git] / SFont.c
1 /*
2  * Copyright (C) Karl Bartel <karlb@gmx.net> WWW: http://www.linux-games.com
3  *
4  * Licensed under the GPL v2. For licencing details see COPYING.
5  */
6
7 /*Modified 2003, 2006 by Andre Noll */
8
9 #include <SDL/SDL.h>
10 #include "SFont.h"
11 #include <stdlib.h> /* exit */
12 #include <string.h> /* strlen */
13 SFont_FontInfo InternalFont;
14
15 static Uint32 GetPixel(SDL_Surface *Surface, Sint32 X, Sint32 Y)
16 {
17
18         Uint8 *bits;
19         Uint32 Bpp;
20
21         if (X < 0)
22                 puts("SFONT ERROR: x too small in GetPixel. Report this "
23                         "to <karlb@gmx.net>");
24         if (X >= Surface->w)
25                 puts("SFONT ERROR: x too big in GetPixel. Report this to "
26                         "<karlb@gmx.net>");
27         Bpp = Surface->format->BytesPerPixel;
28         bits = ((Uint8 *) Surface->pixels) + Y * Surface->pitch + X * Bpp;
29
30         /* Get the pixel */
31         switch (Bpp) {
32         case 1:
33                 return *((Uint8 *) Surface->pixels + Y * Surface->pitch + X);
34                 break;
35         case 2:
36                 return *((Uint16 *) Surface->pixels + Y * Surface->pitch / 2 + X);
37                 break;
38         case 3:{        /* Format/endian independent  */
39                         Uint8 r, g, b;
40                         r = *((bits) + Surface->format->Rshift / 8);
41                         g = *((bits) + Surface->format->Gshift / 8);
42                         b = *((bits) + Surface->format->Bshift / 8);
43                         return SDL_MapRGB(Surface->format, r, g, b);
44                 }
45                 break;
46         case 4:
47                 return *((Uint32 *) Surface->pixels + Y * Surface->pitch / 4 + X);
48                 break;
49         }
50
51         return -1;
52 }
53
54 void InitFont2(SFont_FontInfo * Font)
55 {
56         int x = 0, i = 0;
57
58         if (!Font->Surface) {
59                 printf("The font has not been loaded!\n");
60                 exit(EXIT_FAILURE);
61         }
62
63         if (SDL_MUSTLOCK(Font->Surface))
64                 SDL_LockSurface(Font->Surface);
65
66         while (x < Font->Surface->w) {
67                 if (GetPixel(Font->Surface, x, 0) ==
68                         SDL_MapRGB(Font->Surface->format, 255, 0, 255)) {
69                         Font->CharPos[i++] = x;
70                         while ((x < Font->Surface->w - 1) &&
71                                 (GetPixel(Font->Surface, x, 0) ==
72                                 SDL_MapRGB(Font->Surface->format, 255, 0, 255)))
73                                 x++;
74                         Font->CharPos[i++] = x;
75                 }
76                 x++;
77         }
78         if (SDL_MUSTLOCK(Font->Surface))
79                 SDL_UnlockSurface(Font->Surface);
80
81         Font->h = Font->Surface->h;
82         SDL_SetColorKey(Font->Surface, SDL_SRCCOLORKEY,
83                         GetPixel(Font->Surface, 0, Font->Surface->h - 1));
84 }
85
86 void PutString2(SDL_Surface * Surface, SFont_FontInfo * Font, int x, int y,
87                 const char *text)
88 {
89         int ofs;
90         int i = 0;
91         SDL_Rect srcrect, dstrect;
92
93         while (text[i] != '\0') {
94                 if (text[i] == ' ') {
95                         x += Font->CharPos[2] - Font->CharPos[1];
96                         i++;
97                 } else {
98                         ofs = ((unsigned char) text[i] - 33) * 2 + 1;
99                         srcrect.w = dstrect.w = (Font->CharPos[ofs + 2]
100                                 + Font->CharPos[ofs + 1]) / 2
101                                 - (Font->CharPos[ofs]
102                                 + Font->CharPos[ofs - 1]) / 2;
103                         srcrect.h = dstrect.h = Font->Surface->h - 1;
104                         srcrect.x = (Font->CharPos[ofs]
105                                 + Font->CharPos[ofs - 1]) / 2;
106                         srcrect.y = 1;
107                         dstrect.x = x - (float) (Font->CharPos[ofs]
108                                 - Font->CharPos[ofs - 1]) / 2;
109                         dstrect.y = y;
110                         SDL_BlitSurface(Font->Surface, &srcrect, Surface,
111                                         &dstrect);
112                         x += Font->CharPos[ofs + 1] - Font->CharPos[ofs];
113                         i++;
114                 }
115         }
116 }
117
118 int TextWidth2(SFont_FontInfo * Font, char *text)
119 {
120         int ofs = 0;
121         int i = 0, x = 0;
122
123         while (text[i] != '\0') {
124                 if (text[i] == ' ') {
125                         x += Font->CharPos[2] - Font->CharPos[1];
126                         i++;
127                 } else {
128                         ofs = ((unsigned char) text[i] - 33) * 2 + 1;
129                         x += Font->CharPos[ofs + 1] - Font->CharPos[ofs];
130                         i++;
131                 }
132         }
133         return x;
134 }
135
136 static void SFont_InternalInput(SDL_Surface * Dest, SFont_FontInfo * Font, int x,
137                 int y, int PixelWidth, char *text)
138 {
139         SDL_Event event;
140         int ch = -1, blink = 0;
141         long blinktimer = 0;
142         SDL_Surface *Back;
143         SDL_Rect rect;
144         int previous;
145
146         Back = SDL_AllocSurface(Dest->flags,
147                 Dest->w,
148                 Font->h,
149                 Dest->format->BitsPerPixel,
150                 Dest->format->Rmask,
151                 Dest->format->Gmask, Dest->format->Bmask, 0);
152         rect.x = 0;
153         rect.y = y;
154         rect.w = Dest->w;
155         rect.h = Font->Surface->h;
156         SDL_BlitSurface(Dest, &rect, Back, NULL);
157         PutString2(Dest, Font, x, y, text);
158         SDL_UpdateRects(Dest, 1, &rect);
159
160         /* start input */
161         previous = SDL_EnableUNICODE(1);
162         blinktimer = SDL_GetTicks();
163         while (ch != SDLK_RETURN) {
164                 if (event.type == SDL_KEYDOWN) {
165                         ch = event.key.keysym.unicode;
166                         if (((ch > 31) || (ch == '\b')) && (ch < 128)) {
167                                 if ((ch == '\b') && (strlen(text) > 0))
168                                         text[strlen(text) - 1] = '\0';
169                                 else if (ch != '\b')
170                                         sprintf(text, "%s%c", text, ch);
171                                 if (TextWidth2(Font, text) > PixelWidth)
172                                         text[strlen(text) - 1] = '\0';
173                                 SDL_BlitSurface(Back, NULL, Dest, &rect);
174                                 PutString2(Dest, Font, x, y, text);
175                                 SDL_UpdateRects(Dest, 1, &rect);
176                                 SDL_WaitEvent(&event);
177                         }
178                 }
179                 if (SDL_GetTicks() > blinktimer) {
180                         blink = 1 - blink;
181                         blinktimer = SDL_GetTicks() + 500;
182                         if (blink) {
183                                 PutString2(Dest, Font,
184                                         x + TextWidth2(Font, text), y, "|");
185                                 SDL_UpdateRects(Dest, 1, &rect);
186                         } else {
187                                 SDL_BlitSurface(Back, NULL, Dest, &rect);
188                                 PutString2(Dest, Font, x, y, text);
189                                 SDL_UpdateRects(Dest, 1, &rect);
190                         }
191                 }
192                 SDL_Delay(1);
193                 SDL_PollEvent(&event);
194         }
195         text[strlen(text)] = '\0';
196         SDL_FreeSurface(Back);
197         /* restore the previous state */
198         SDL_EnableUNICODE(previous);
199 }
200
201 void SFont_Input2(SDL_Surface * Dest, SFont_FontInfo * Font, int x, int y,
202                 int PixelWidth, char *text)
203 {
204         SFont_InternalInput(Dest, Font, x, y, PixelWidth, text);
205 }