1 /*
2 * Example program for the Allegro library, by Eric Botcazou.
3 *
4 * This program demonstrates the use of the 16-bit Unicode text
5 * encoding format with Allegro. The example displays a message
6 * translated to different languages scrolling on the screen
7 * using an external font containing the required characters to
8 * display those messages.
9 *
10 * Note how the Allegro unicode string functions resemble the
11 * functions you can find in the standard C library, only these
12 * handle Unicode on all platforms.
13 */
14
15
16 #include <stdlib.h>
17 #include <allegro.h>
18
19 #define DATAFILE_NAME "unifont.dat"
20
21 #define NLANGUAGES 12
22
23
24 /* Animation timer. */
25 volatile int ticks = 0;
ticker(void)26 void ticker(void)
27 {
28 ticks++;
29 }
30
31 #if defined ALLEGRO_LITTLE_ENDIAN
32
33 /* UTF-16LE */
34 char message_en[] = "\x57\x00\x65\x00\x6c\x00\x63\x00\x6f\x00\x6d\x00\x65\x00\x20\x00\x74\x00\x6f\x00\x20\x00\x00\x00";
35
36 char message_fr[] = "\x42\x00\x69\x00\x65\x00\x6e\x00\x76\x00\x65\x00\x6e\x00\x75\x00\x65\x00\x20\x00\xE0\x00\x20\x00\x00\x00";
37
38 char message_es[] = "\x42\x00\x69\x00\x65\x00\x6e\x00\x76\x00\x65\x00\x6e\x00\x69\x00\x64\x00\x6f\x00\x20\x00\x61\x00\x20\x00\x00\x00";
39
40 char message_it[] = "\x42\x00\x65\x00\x6e\x00\x76\x00\x65\x00\x6e\x00\x75\x00\x74\x00\x69\x00\x20\x00\x61\x00\x64\x00\x20\x00\x00\x00";
41
42 char message_el[] = "\x9A\x03\xB1\x03\xBB\x03\xCE\x03\xC2\x03\x20\x00\xAE\x03\xC1\x03\xB8\x03\xB1\x03\xC4\x03\xB5\x03\x20\x00\xC3\x03\xC4\x03\xBF\x03\x20\x00\x00\x00";
43
44 char message_ru[] = "\x14\x04\x3e\x04\x31\x04\x40\x04\x3e\x04\x20\x00\x3f\x04\x3e\x04\x36\x04\x30\x04\x3b\x04\x3e\x04\x32\x04\x30\x04\x42\x04\x4c\x04\x20\x00\x32\x04\x20\x00\x00\x00";
45
46 char message_he[] = "\x20\x00\xDC\x05\xD0\x05\x20\x00\xDD\x05\xD9\x05\xD0\x05\xD1\x05\xD4\x05\x20\x00\xDD\x05\xD9\x05\xDB\x05\xD5\x05\xE8\x05\xD1\x05\x00\x00";
47
48 char message_ja[] = "\x78\x30\x88\x30\x46\x30\x53\x30\x5d\x30\x00\x00";
49
50 char message_ka[] = "\x20\x00\xa8\x0C\xbf\x0C\xae\x0C\x97\x0C\xc6\x0C\x20\x00\xb8\x0C\xc1\x0C\xb8\x0C\xcd\x0C\xb5\x0C\xbe\x0C\x97\x0C\xa4\x0C";
51
52 char message_ta[] = "\x20\x00\x89\x0B\x99\x0B\x82\x0B\x95\x0B\xC8\x0B\xB3\x0B\x20\x00\xB5\x0B\xB0\x0B\xC7\x0B\xB5\x0B\xB1\x0B\x82\x0B\x95\x0B\xBF\x0B\xB1\x0B\xA5\x0B\x00\x00";
53
54 char message_zh[] = "\x22\x6b\xCE\x8F\x7F\x4f\x28\x75\x20\x00\x00\x00";
55
56 char message_de[] = "\x57\x00\x69\x00\x6c\x00\x6c\x00\x6b\x00\x6f\x00\x6d\x00\x6d\x00\x65\x00\x6e\x00\x20\x00\x62\x00\x65\x00\x69\x00\x20\x00\x00\x00";
57
58 char allegro_str[] = "\x41\x00\x6c\x00\x6c\x00\x65\x00\x67\x00\x72\x00\x6f\x00\x00\x00";
59
60 #elif defined ALLEGRO_BIG_ENDIAN
61
62 /* UTF-16BE */
63 char message_en[] = "\x00\x57\x00\x65\x00\x6c\x00\x63\x00\x6f\x00\x6d\x00\x65\x00\x20\x00\x74\x00\x6f\x00\x20\x00\x00";
64
65 char message_fr[] = "\x00\x42\x00\x69\x00\x65\x00\x6e\x00\x76\x00\x65\x00\x6e\x00\x75\x00\x65\x00\x20\x00\xE0\x00\x20\x00\x00";
66
67 char message_es[] = "\x00\x42\x00\x69\x00\x65\x00\x6e\x00\x76\x00\x65\x00\x6e\x00\x69\x00\x64\x00\x6f\x00\x20\x00\x61\x00\x20\x00\x00";
68
69 char message_it[] = "\x00\x42\x00\x65\x00\x6e\x00\x76\x00\x65\x00\x6e\x00\x75\x00\x74\x00\x69\x00\x20\x00\x61\x00\x64\x00\x20\x00\x00";
70
71 char message_el[] = "\x03\x9A\x03\xB1\x03\xBB\x03\xCE\x03\xC2\x00\x20\x03\xAE\x03\xC1\x03\xB8\x03\xB1\x03\xC4\x03\xB5\x00\x20\x03\xC3\x03\xC4\x03\xBF\x00\x20\x00\x00";
72
73 char message_ru[] = "\x04\x14\x04\x3e\x04\x31\x04\x40\x04\x3e\x00\x20\x04\x3f\x04\x3e\x04\x36\x04\x30\x04\x3b\x04\x3e\x04\x32\x04\x30\x04\x42\x04\x4c\x00\x20\x04\x32\x00\x20\x00\x00";
74
75 char message_he[] = "\x00\x20\x05\xDC\x05\xD0\x00\x20\x05\xDD\x05\xD9\x05\xD0\x05\xD1\x05\xD4\x00\x20\x05\xDD\x05\xD9\x05\xDB\x05\xD5\x05\xE8\x05\xD1\x00\x00";
76
77 char message_ja[] = "\x30\x78\x30\x88\x30\x46\x30\x53\x30\x5d\x00\x00";
78
79 char message_ka[] = "\x20\x00\x0C\xa8\x0C\xbf\x0C\xae\x0C\x97\x0C\xc6\x20\x00\x0C\xb8\x0C\xc1\x0C\xb8\x0C\xcd\x0C\xb5\x0C\xbe\x0C\x97\xa4\x0C";
80
81 char message_ta[] = "\x00\x20\x0B\x89\x0B\x99\x0B\x82\x0B\x95\x0B\xC8\x0B\xB3\x00\x20\x0B\xB5\x0B\xB0\x0B\xC7\x0B\xB5\x0B\xB1\x0B\x82\x0B\x95\x0B\xBF\x0B\xB1\x0B\xA5\x00\x00";
82
83 char message_zh[] = "\x6b\x22\x8F\xCE\x4f\x7F\x75\x28\x00\x20\x00\x00";
84
85 char message_de[] = "\x00\x57\x00\x69\x00\x6c\x00\x6c\x00\x6b\x00\x6f\x00\x6d\x00\x6d\x00\x65\x00\x6e\x00\x20\x00\x62\x00\x65\x00\x69\x00\x20\x00\x00";
86
87 char allegro_str[] = "\x00\x41\x00\x6c\x00\x6c\x00\x65\x00\x67\x00\x72\x00\x6f\x00\x00";
88
89 #elif !defined SCAN_DEPEND
90 #error endianess not defined
91 #endif
92
93
94 struct MESSAGE {
95 char *data, *str;
96 int prefix_allegro;
97 int dx, dy;
98 int x, y, w, h;
99 int c;
100 };
101
102
103 struct MESSAGE message[] = { {message_en, NULL, FALSE, -1, 0, 0, 0, 0, 0, 0},
104 {message_fr, NULL, FALSE, -1, 0, 0, 0, 0, 0, 0},
105 {message_es, NULL, FALSE, -1, 0, 0, 0, 0, 0, 0},
106 {message_it, NULL, FALSE, -1, 0, 0, 0, 0, 0, 0},
107 {message_el, NULL, FALSE, -1, 0, 0, 0, 0, 0, 0},
108 {message_ru, NULL, FALSE, -1, 0, 0, 0, 0, 0, 0},
109 {message_he, NULL, TRUE, 1, 0, 0, 0, 0, 0, 0},
110 {message_ja, NULL, TRUE, -1, 0, 0, 0, 0, 0, 0},
111 {message_ka, NULL, TRUE, -1, 0, 0, 0, 0, 0, 0},
112 {message_ta, NULL, TRUE, -1, 0, 0, 0, 0, 0, 0},
113 {message_zh, NULL, FALSE, -1, 0, 0, 0, 0, 0, 0},
114 {message_de, NULL, FALSE, -1, 0, 0, 0, 0, 0, 0}
115 };
116
117
overlap(int i,int j,int pad)118 static int overlap(int i, int j, int pad)
119 {
120 return message[i].x - pad < message[j].x + message[j].w + pad &&
121 message[j].x - pad < message[i].x + message[i].w + pad &&
122 message[i].y - pad < message[j].y + message[j].h + pad &&
123 message[j].y - pad < message[i].y + message[i].h + pad;
124 }
125
126
main(int argc,char * argv[])127 int main(int argc, char *argv[])
128 {
129 DATAFILE *data;
130 FONT *f;
131 BITMAP *buffer;
132 int i, j, k, height;
133 char buf[256], tmp[256], tmp2[256];
134 int counter = 0, drawn = 0;
135 int scroll_w, scroll_h;
136 int background_color;
137
138 /* set the text encoding format BEFORE initializing the library */
139 set_uformat(U_UNICODE);
140
141 /* past this point, every string that we pass to or retrieve
142 * from any Allegro API call must be in 16-bit Unicode format
143 */
144
145 srand(time(NULL));
146 if (allegro_init() != 0)
147 return 1;
148 install_keyboard();
149 install_timer();
150
151 /* load the datafile containing the Unicode font */
152 replace_filename(buf, uconvert_ascii(argv[0], tmp), uconvert_ascii(DATAFILE_NAME, tmp2), sizeof(buf));
153 data = load_datafile(buf);
154 if (!data) {
155 allegro_message(uconvert_ascii("Unable to load %s\n", tmp), buf);
156 return -1;
157 }
158
159 /* set the graphics mode */
160 if (set_gfx_mode(GFX_AUTODETECT, 640, 480, 0, 0) != 0) {
161 if (set_gfx_mode(GFX_SAFE, 640, 480, 0, 0) != 0) {
162 set_gfx_mode(GFX_TEXT, 0, 0, 0, 0);
163 allegro_message(uconvert_ascii("Unable to set any graphic mode\n%s\n", tmp), allegro_error);
164 return 1;
165 }
166 }
167
168 /* set the window title for windowed modes */
169 set_window_title(uconvert_ascii("Unicode example program", tmp));
170
171 /* create a buffer for drawing */
172 buffer = create_bitmap(SCREEN_W, SCREEN_H);
173
174 /* get a handle to the Unicode font */
175 f = data[0].dat;
176 height = text_height(f);
177
178 /* The are for the text messages. If it gets too crowded once we have more
179 * languages, this can be increased.
180 */
181 scroll_w = SCREEN_W * 2;
182 scroll_h = SCREEN_H + height;
183
184 /* one of the bright colors in the default palette */
185 background_color = 56 + AL_RAND() % 48;
186
187 /* prepare the messages */
188 for (i = 0; i < NLANGUAGES; i++) {
189
190 /* the regular Standard C string manipulation functions don't work
191 * with 16-bit Unicode, so we use the Allegro Unicode API
192 */
193 message[i].str = malloc(ustrsize(message[i].data) + ustrsizez(allegro_str));
194
195 if (message[i].prefix_allegro) {
196 ustrcpy(message[i].str, allegro_str);
197 ustrcat(message[i].str, message[i].data);
198 }
199 else {
200 ustrcpy(message[i].str, message[i].data);
201 ustrcat(message[i].str, allegro_str);
202 }
203
204 message[i].w = text_length(f, message[i].str);
205 message[i].h = text_height(f);
206
207 /* one of the dark colors in the default palette */
208 message[i].c = 104 + AL_RAND() % 144;
209
210 message[i].dx *= 1 + AL_RAND() % 4;
211 message[i].dy = AL_RAND() % 3 - 1;
212
213 /* find not-overlapped position, try 1000 times */
214 for (k = 0; k < 1000; k++) {
215 message[i].x = AL_RAND() % scroll_w;
216 /* make sure the message is not sliced by a screen edge */
217 message[i].y = 10 + AL_RAND() % (SCREEN_H - height - 20);
218 for (j = 0; j < i; j++) {
219 if (overlap(i, j, 10))
220 break;
221 }
222 if (j == i)
223 break;
224 }
225 }
226
227 install_int_ex(ticker, BPS_TO_TIMER(30));
228 /* do the scrolling */
229 while (!keypressed()) {
230 /* Animation. */
231 while (counter <= ticks) {
232 for (i = 0; i < NLANGUAGES; i++) {
233 message[i].x += message[i].dx;
234 if (message[i].x >= scroll_w)
235 message[i].x -= scroll_w;
236 if (message[i].x < 0)
237 message[i].x += scroll_w;
238 message[i].y += message[i].dy;
239 if (message[i].y >= scroll_h)
240 message[i].y -= scroll_h;
241 if (message[i].y < 0)
242 message[i].y += scroll_h;
243 }
244 counter++;
245 }
246
247 /* Draw current frame. */
248 if (drawn < counter) {
249 clear_to_color(buffer, background_color);
250 for (i = 0; i < NLANGUAGES; i++) {
251 char *str = message[i].str;
252 int x = message[i].x;
253 int y = message[i].y;
254 int c = message[i].c;
255 /* draw it 4 times to get the wrap-around effect */
256 textout_ex(buffer, f, str, x, y, c, -1);
257 textout_ex(buffer, f, str, x - scroll_w, y, c, -1);
258 textout_ex(buffer, f, str, x, y - scroll_h, c, -1);
259 textout_ex(buffer, f, str, x - scroll_w, y - scroll_h, c, -1);
260 }
261 blit(buffer, screen, 0, 0, 0, 0, SCREEN_W, SCREEN_H);
262 drawn = counter;
263 }
264 else {
265 rest(10); /* We are too fast, give time to the OS. */
266 }
267 }
268
269 destroy_bitmap(buffer);
270
271 unload_datafile(data);
272
273 return 0;
274 }
275 END_OF_MAIN()
276