1 /**
2  * @file sprites_string.c
3  * @brief  handle the strings fonts of sprites
4  * @created 2006-12-18
5  * @date 2012-08-25
6  * @author Bruno Ethvignot
7  */
8 /*
9  * copyright (c) 1998-2015 TLK Games all rights reserved
10  * $Id: sprites_string.c,v 1.31 2012/08/25 15:55:00 gurumeditation Exp $
11  *
12  * Powermanga is free software; you can redistribute it and/or modify
13  * it under the terms of the GNU General Public License as published by
14  * the Free Software Foundation; either version 3 of the License, or
15  * (at your option) any later version.
16  *
17  * Powermanga is distributed in the hope that it will be useful, but
18  * WITHOUT ANY WARRANTY; without even the implied warranty of
19  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20  * GNU General Public License for more details.
21  *
22  * You should have received a copy of the GNU General Public License
23  * along with this program; if not, write to the Free Software
24  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
25  * MA  02110-1301, USA.
26  */
27 #include "config.h"
28 #include "powermanga.h"
29 #include "tools.h"
30 #include "images.h"
31 #include "config_file.h"
32 #include "display.h"
33 #include "electrical_shock.h"
34 #include "gfx_wrapper.h"
35 #include "log_recorder.h"
36 #include "scrolltext.h"
37 #include "sprites_string.h"
38 
39 #define FONT_SCORE_MAXOF_CHARS 10
40 #define FONT_BIG_MAXOF_CHARS 27
41 #define FONT_GAME_MAXOF_CHARS 90
42 
43 bitmap fnt_game[FONT_GAME_MAXOF_CHARS][FONTS_MAX_OF_IMAGES];
44 bitmap fnt_big[FONT_BIG_MAXOF_CHARS][FONTS_MAX_OF_IMAGES];
45 bitmap fnt_score[FONT_SCORE_MAXOF_CHARS][FONTS_MAX_OF_IMAGES];
46 
47 const Uint32 MAX_OF_STRINGS = 100;
48 static sprite_string_struct **strings_list = NULL;
49 static Uint32 num_of_sprites_strings = 0;
50 
51 static Uint32 keycode_down_prev = 0;
52 static Uint32 keycode_down = 0;
53 static Sint32 input_delay = 0;
54 static Uint32 keycode_up = 0;
55 static Uint32 keysym_up = 0;
56 static Uint32 keysym_down = 0;
57 
58 static Uint32 joy_code_down = 0;
59 static Uint32 joy_code_down_prev = 0;
60 static Uint32 joy_up;
61 static Sint32 input_joy_tempo = 0;
62 
63 static unsigned char cycling_table[] = {
64   64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 78,
65   77, 76, 75, 74, 73, 72, 71, 70, 69, 68, 67, 66, 65, 64, 0
66 };
67 
68 static Uint32 cycling_delay = 0;
69 static Uint32 cycling_index = 0;
70 
71 /**
72  * Color cycling, return new color
73  * @return: color index
74  */
75 static unsigned char
get_next_color()76 get_next_color ()
77 {
78   unsigned char color;
79   /* change color? */
80   if (cycling_delay++ > 1)
81     {
82       cycling_delay = 0;
83       cycling_index++;
84     }
85   color = cycling_table[cycling_index];
86   /* end of table? */
87   if (color == 0)
88     {
89       color = cycling_table[0];
90       cycling_index = 0;
91     }
92   return color;
93 }
94 
95 /**
96  * Allocating memory for the list of sprites strings structures
97  * @return TRUE if it completed successfully or FALSE otherwise
98  */
99 bool
sprites_string_once_init(void)100 sprites_string_once_init (void)
101 {
102   /* allocate list of sprite_char_struct */
103   if (strings_list == NULL)
104     {
105       strings_list =
106         (sprite_string_struct **) memory_allocation (MAX_OF_STRINGS *
107                                                      sizeof
108                                                      (sprite_string_struct
109                                                       *));
110       if (strings_list == NULL)
111         {
112           LOG_ERR ("not enough memory to allocate 'strings_list'");
113           return FALSE;
114         }
115     }
116   num_of_sprites_strings = 0;
117 
118 
119   /* 159,654 bytes */
120   if (!bitmap_load
121       ("graphics/bitmap/fonts/font_game.spr", &fnt_game[0][0],
122        FONT_GAME_MAXOF_CHARS, FONTS_MAX_OF_IMAGES))
123     {
124       return FALSE;
125     }
126   /* 149 950 bytes */
127   if (!bitmap_load
128       ("graphics/bitmap/fonts/font_big.spr", &fnt_big[0][0],
129        FONT_BIG_MAXOF_CHARS, FONTS_MAX_OF_IMAGES))
130     {
131       return FALSE;
132     }
133   /* 52 480 bytes */
134   if (!bitmap_load
135       ("graphics/bitmap/fonts/font_score.spr", &fnt_score[0][0],
136        FONT_SCORE_MAXOF_CHARS, FONTS_MAX_OF_IMAGES))
137     {
138       return FALSE;
139     }
140   return TRUE;
141 }
142 
143 /**
144  * Convert fonts from data bitmaps to PNG file
145  * @return TRUE if successful
146  */
147 #ifdef PNG_EXPORT_ENABLE
148 bool
sprites_font_extract(void)149 sprites_font_extract (void)
150 {
151   Uint32 i, frame;
152   const char *model = EXPORT_DIR "/fonts/xxxxx/xx/xx.png";
153   char *filename = memory_allocation (strlen (model) + 1);
154   if (filename == NULL)
155     {
156       LOG_ERR ("not enough memory to allocate %i bytes\n",
157                (Uint32) (strlen (model) + 1));
158       return FALSE;
159     }
160   if (!create_dir (EXPORT_DIR "/fonts"))
161     {
162       free_memory (filename);
163       return FALSE;
164     }
165 
166   if (!create_dir (EXPORT_DIR "/fonts/game"))
167     {
168       free_memory (filename);
169       return FALSE;
170     }
171   for (i = 0; i < FONT_GAME_MAXOF_CHARS; i++)
172     {
173       sprintf (filename, EXPORT_DIR "/fonts/game/%02d", i + 1);
174       if (!create_dir (filename))
175         {
176           free_memory (filename);
177           return FALSE;
178         }
179       for (frame = 0; frame < FONTS_MAX_OF_IMAGES; frame++)
180         {
181           sprintf (filename,
182                    EXPORT_DIR "/fonts/game/%02d/%02d.png", i + 1, frame);
183           if (!bitmap_to_png
184               (&fnt_game[i][frame], filename, 16, 16, offscreen_pitch))
185             {
186               free_memory (filename);
187               return FALSE;
188             }
189         }
190     }
191 
192   if (!create_dir (EXPORT_DIR "/fonts/big"))
193     {
194       free_memory (filename);
195       return FALSE;
196     }
197   for (i = 0; i < FONT_BIG_MAXOF_CHARS; i++)
198     {
199       sprintf (filename, EXPORT_DIR "/fonts/big/%02d", i + 1);
200       if (!create_dir (filename))
201         {
202           free_memory (filename);
203           return FALSE;
204         }
205       for (frame = 0; frame < FONTS_MAX_OF_IMAGES; frame++)
206         {
207           sprintf (filename,
208                    EXPORT_DIR "/fonts/big/%02d/%02d.png", i + 1, frame);
209           if (!bitmap_to_png
210               (&fnt_big[i][frame], filename, 32, 26, offscreen_pitch))
211             {
212               free_memory (filename);
213               return FALSE;
214             }
215         }
216     }
217 
218   if (!create_dir (EXPORT_DIR "/fonts/score"))
219     {
220       free_memory (filename);
221       return FALSE;
222     }
223   for (i = 0; i < FONT_SCORE_MAXOF_CHARS; i++)
224     {
225       sprintf (filename, EXPORT_DIR "/fonts/score/%02d", i + 1);
226       if (!create_dir (filename))
227         {
228           free_memory (filename);
229           return FALSE;
230         }
231       for (frame = 0; frame < FONTS_MAX_OF_IMAGES; frame++)
232         {
233           sprintf (filename,
234                    EXPORT_DIR "/fonts/score/%02d/%02d.png", i + 1, frame);
235           if (!bitmap_to_png
236               (&fnt_score[i][frame], filename, 16, 16, score_offscreen_pitch))
237             {
238               free_memory (filename);
239               return FALSE;
240             }
241         }
242     }
243   free_memory (filename);
244   return TRUE;
245 }
246 #endif
247 
248 /**
249  * Release all sprites strings structures
250  */
251 void
sprites_string_free(void)252 sprites_string_free (void)
253 {
254   Uint32 i;
255   LOG_DBG ("deallocates the memory used by the bitmap");
256   if (strings_list == NULL)
257     {
258       return;
259     }
260   for (i = 0; i < MAX_OF_STRINGS; i++)
261     {
262       if (strings_list[i] == NULL)
263         {
264           continue;
265         }
266       sprites_string_delete (strings_list[i]);
267       strings_list[i] = NULL;
268     }
269   free_memory ((char *) strings_list);
270   strings_list = NULL;
271   bitmap_free (&fnt_game[0][0], FONT_GAME_MAXOF_CHARS, FONTS_MAX_OF_IMAGES,
272                FONTS_MAX_OF_IMAGES);
273   bitmap_free (&fnt_big[0][0], FONT_BIG_MAXOF_CHARS, FONTS_MAX_OF_IMAGES,
274                FONTS_MAX_OF_IMAGES);
275   bitmap_free (&fnt_score[0][0], FONT_SCORE_MAXOF_CHARS, FONTS_MAX_OF_IMAGES,
276                FONTS_MAX_OF_IMAGES);
277 }
278 
279 /**
280  * Create a new string of sprites characters
281  * @param string A simple string
282  * @param more_chars Additional chars to allow
283  * @param type type of font (FONT_BIG, FONT_SCROLL, FONT_SCROLL, or FONT_SCORE)
284  * @param coordx x coordinate in pixels
285  * @param coordy y coordinate in pixels
286  * @return pointer to a sprites string structure
287  */
288 sprite_string_struct *
sprites_string_new(const char * const string,Uint32 more_chars,Uint32 type,float coordx,float coordy)289 sprites_string_new (const char *const string, Uint32 more_chars, Uint32 type,
290                     float coordx, float coordy)
291 {
292   Uint32 i;
293   sprite_string_struct *sprite_str;
294   char *string_allocated;
295   Uint32 numof_chars, maxof_chars;
296 
297   if (string != NULL)
298     {
299       numof_chars = strlen (string);
300       maxof_chars = strlen (string) + more_chars;
301     }
302   else
303     {
304       numof_chars = maxof_chars = more_chars;
305     }
306   if (maxof_chars == 0)
307     {
308       LOG_ERR ("The string's lenght is null!");
309       return NULL;
310     }
311 
312   /* allocate the string */
313   string_allocated = memory_allocation (maxof_chars + 1);
314   if (string_allocated == NULL)
315     {
316       LOG_ERR ("not enough memory to allocate a string!");
317       return NULL;
318     }
319   if (string != NULL)
320     {
321       strcpy (string_allocated, string);
322     }
323   else
324     {
325       for (i = 0; i < maxof_chars; i++)
326         {
327           string_allocated[i] = ' ';
328         }
329     }
330 
331   sprite_str =
332     sprites_string_create (string_allocated, maxof_chars, type, coordx,
333                            coordy);
334   if (sprite_str == NULL)
335     {
336       free_memory (string_allocated);
337       LOG_ERR ("sprites_string_create() failed!");
338       return NULL;
339     }
340   sprite_str->num_of_chars = numof_chars;
341   sprite_str->max_of_chars = maxof_chars;
342   sprite_str->is_string_allocated = TRUE;
343   return sprite_str;
344 }
345 
346 /**
347  * Create a new string of sprites characters
348  * @param string A simple string
349  * @param size Length of the string
350  * @param type Type of font (FONT_BIG, FONT_SCROLL, FONT_SCROLL, or FONT_SCORE)
351  * @param coordx X coordinate in pixels
352  * @param coordy Y coordinate in pixels
353  * @return Pointer to a sprites string structure
354  */
355 sprite_string_struct *
sprites_string_create(char * string,Uint32 size,Uint32 type,float coordx,float coordy)356 sprites_string_create (char *string, Uint32 size, Uint32 type, float coordx,
357                        float coordy)
358 {
359   Uint32 i;
360   sprite_char_struct *sprite_char;
361   sprite_string_struct *sprite_str;
362   if (num_of_sprites_strings >= MAX_OF_STRINGS)
363     {
364       LOG_ERR ("maximum number of sprites string reached!");
365       return NULL;
366     }
367 
368   /* allocate the sprite string structure */
369   sprite_str =
370     (sprite_string_struct *)
371     memory_allocation (sizeof (sprite_string_struct));
372   if (sprite_str == NULL)
373     {
374       LOG_ERR ("not enough memory to allocate 'sprite_string_struct'!");
375       return NULL;
376     }
377   sprite_str->string = string;
378   sprite_str->is_string_allocated = FALSE;
379   sprite_str->num_of_chars = size;
380   sprite_str->max_of_chars = size;
381   sprite_str->coord_x = coordx;
382   sprite_str->coord_y = coordy;
383   sprite_str->center_x = (Sint32) coordx;
384   sprite_str->center_y = (Sint32) coordy;
385   sprite_str->delay_next_char = 50;
386   sprite_str->delay_next_char_count = 0;
387   sprite_str->delay_add_to_last = 200;
388   sprite_str->current_char = 0;
389   sprite_str->at_least_one_char_changed = FALSE;
390   sprite_str->cursor_pos = 0;
391   sprite_str->cursor_status = 0;
392 
393   /* allocate sprites chars structures */
394   sprite_str->sprites_chars =
395     (sprite_char_struct *) memory_allocation (sprite_str->max_of_chars *
396                                               sizeof (sprite_char_struct));
397   if (sprite_str->sprites_chars == NULL)
398     {
399       free_memory ((char *) sprite_str);
400       LOG_ERR ("not enough memory to allocate 'sprite_char_struct'!");
401       return NULL;
402     }
403   for (i = 0; i < sprite_str->max_of_chars; i++)
404     {
405       sprite_char = &sprite_str->sprites_chars[i];
406       sprite_char->anim_speed_inc = 500;
407       sprite_char->anim_speed = 1000;
408       sprite_char_initialize (sprite_char, sprite_str->string[i],
409                               (Sint32) coordx, (Sint32) coordy, type);
410     }
411   sprite_str->space = sprite_str->sprites_chars[0].font_size;
412   sprite_chars_to_image (sprite_str);
413   strings_list[num_of_sprites_strings] = sprite_str;
414   num_of_sprites_strings++;
415   return sprite_str;
416 }
417 
418 /**
419  * Release a sprites string structure
420  * @param a pointer to a sprites string structure
421  */
422 void
sprites_string_delete(sprite_string_struct * sprite_str)423 sprites_string_delete (sprite_string_struct * sprite_str)
424 {
425   Uint32 i, j;
426   for (i = 0; i < num_of_sprites_strings; i++)
427     {
428       if (strings_list[i] != sprite_str)
429         {
430           continue;
431         }
432       if (sprite_str->sprites_chars != NULL)
433         {
434           free_memory ((char *) sprite_str->sprites_chars);
435           sprite_str->sprites_chars = NULL;
436         }
437       if (sprite_str->string != NULL && sprite_str->is_string_allocated)
438         {
439           free_memory (sprite_str->string);
440           sprite_str->string = NULL;
441           sprite_str->is_string_allocated = FALSE;
442         }
443       free_memory ((char *) sprite_str);
444       for (j = i; j < MAX_OF_STRINGS - 1; j++)
445         {
446           strings_list[j] = strings_list[j + 1];
447         }
448       strings_list[j] = NULL;
449       return;
450     }
451   LOG_ERR ("sprite_string_struct not found");
452 }
453 
454 
455 /**
456  * Initialize a char sprite
457  * @param sprite_char a pointer to a char sprite structure
458  * @param code char ascii code
459  * @param xcoord x-coordinate of char and rotate center
460  * @param ycoord y-coordinate of char and rotate center
461 *  @param type type of font
462  */
463 void
sprite_char_initialize(sprite_char_struct * sprite_char,char code,Sint32 xcoord,Sint32 ycoord,Uint32 type)464 sprite_char_initialize (sprite_char_struct * sprite_char, char code,
465                         Sint32 xcoord, Sint32 ycoord, Uint32 type)
466 {
467   sprite_char->type_of_font = type;
468   switch (sprite_char->type_of_font)
469     {
470     case FONT_GAME:
471       sprite_char->font_size = 16;
472       break;
473     case FONT_BIG:
474       sprite_char->font_size = 32;
475       break;
476     case FONT_SCROLL:
477       sprite_char->font_size = 32;
478       break;
479     case FONT_SCORE:
480       sprite_char->font_size = 16;
481       break;
482     default:
483       sprite_char->type_of_font = FONT_BIG;
484       sprite_char->font_size = 32;
485       break;
486     }
487   sprite_char->coord_x = xcoord;
488   sprite_char->coord_y = ycoord;
489   sprite_char->center_x = xcoord;
490   sprite_char->center_y = ycoord;
491   sprite_char->current_image = 0;
492 
493   switch (sprite_char->type_of_font)
494     {
495     case FONT_SCORE:
496       sprite_char->which_offscreen = FONT_DRAW_TOP_PANEL;
497       sprite_char->xmin = 0;
498       sprite_char->ymin = 0;
499       sprite_char->xmax = score_offscreen_width - sprite_char->font_size;
500       sprite_char->ymax = score_offscreen_height - sprite_char->font_size;
501       break;
502     default:
503       sprite_char->which_offscreen = FONT_DRAW_OFFSCREEN;
504       sprite_char->xmin = offscreen_clipsize - sprite_char->font_size + 1;
505       sprite_char->ymin = offscreen_clipsize - sprite_char->font_size + 1;
506       sprite_char->xmax = offscreen_width - offscreen_clipsize - 1;
507       sprite_char->ymax = offscreen_height - offscreen_clipsize - 1;
508       break;
509     }
510   sprite_set_char (sprite_char, code);
511 }
512 
513 /**
514  * Initialize the char of  sprite
515  * @param sprite_char a pointer to a char sprite structure
516  * @param code char ascii code
517  */
518 void
sprite_set_char(sprite_char_struct * sprite_char,char code)519 sprite_set_char (sprite_char_struct * sprite_char, char code)
520 {
521   if (code == 32)
522     {
523       sprite_char->is_display = FALSE;
524     }
525   else
526     {
527       sprite_char->is_display = TRUE;
528       switch (sprite_char->type_of_font)
529         {
530         case FONT_BIG:
531           sprite_char->current_char = (Sint32) (code - 65);
532           break;
533         case FONT_SCORE:
534           sprite_char->current_char = (Sint32) (code - 48);
535           break;
536         default:
537           sprite_char->current_char = (Sint32) (code - 33);
538           break;
539         }
540     }
541 }
542 
543 /**
544  * Initialize values for rotate a char sprite
545  * @param sprite_char a pointer to a char sprite structure
546  * @param angle
547  * @param angle_inc
548  * @param radius_x
549  * @param radius_y
550  */
551 void
sprite_char_init_rotate(sprite_char_struct * sprite_char,Uint32 angle,Sint32 angle_inc,Uint32 radius_x,Uint32 radius_y)552 sprite_char_init_rotate (sprite_char_struct * sprite_char, Uint32 angle,
553                          Sint32 angle_inc, Uint32 radius_x, Uint32 radius_y)
554 {
555   sprite_char->angle = angle;
556   sprite_char->angle_inc = angle_inc;
557   sprite_char->radius_x = radius_x;
558   sprite_char->radius_y = radius_y;
559 }
560 
561 /* Play animation for a single character
562  * @param sprite_char a pointer to a char sprite structure
563  * @param restart TRUE if the animation of char restarts
564  *        when it is finished
565  * return TRUE if char finished animation
566  */
567 bool
sprite_char_anim(sprite_char_struct * sprite_char,bool restart)568 sprite_char_anim (sprite_char_struct * sprite_char, bool restart)
569 {
570   if (!sprite_char->is_anim)
571     {
572       return FALSE;
573     }
574   sprite_char->anim_speed_count += sprite_char->anim_speed_inc;
575   if (sprite_char->anim_speed_count < sprite_char->anim_speed)
576     {
577       return FALSE;
578     }
579   sprite_char->anim_speed_count -= sprite_char->anim_speed;
580   sprite_char->current_image++;
581   if (sprite_char->current_image >= FONTS_MAX_OF_IMAGES)
582     {
583       sprite_char->current_image = 0;
584       sprite_char->is_anim = restart;
585       return TRUE;
586     }
587   else
588     {
589       return FALSE;
590     }
591 }
592 
593 /* Rotate a single character and reduce radius
594  * @param sprite_char a pointer to a char sprite structure
595  * @param decx value to decrease x radius
596  * @param decy value to decrease y radius
597  * @param min radius minimum in pixels
598  * return TRUE if rotation is finish
599  */
600 bool
sprite_char_rotate(sprite_char_struct * sprite_char,Sint32 decx,Sint32 decy,Sint32 min)601 sprite_char_rotate (sprite_char_struct * sprite_char, Sint32 decx,
602                     Sint32 decy, Sint32 min)
603 {
604   float sin_value, cos_value;
605   bool is_finished = FALSE;
606   sprite_char->angle =
607     (sprite_char->angle + sprite_char->angle_inc) & MAX_ANGLE;
608   if (sprite_char->radius_x > min)
609     {
610       sprite_char->radius_x -= decx;
611     }
612   if (sprite_char->radius_y > min)
613     {
614       sprite_char->radius_y -= decy;
615     }
616   if (sprite_char->radius_x < min)
617     {
618       sprite_char->radius_x = min;
619     }
620   if (sprite_char->radius_y < min)
621     {
622       sprite_char->radius_y = min;
623     }
624   if (sprite_char->radius_x == min && sprite_char->radius_y == min)
625     {
626       is_finished = TRUE;
627     }
628   sin_value = precalc_sin128[sprite_char->angle];
629   cos_value = precalc_cos128[sprite_char->angle];
630   sprite_char->coord_x =
631     (Sint32) (sin_value * sprite_char->radius_x) + sprite_char->center_x;
632   sprite_char->coord_y =
633     (Sint32) (cos_value * sprite_char->radius_y) + sprite_char->center_y;
634   return is_finished;
635 }
636 
637 /* Rotate a single character and enlarge radius
638  * @param sprite_char a pointer to a char sprite structure
639  * @param incx value to decrease x radius
640  * @param incy value to decrease y radius
641  * @param max_x radius max_ximum in pixels
642  * return TRUE if rotation is finish
643  */
644 bool
sprite_char_rotate_enlarge(sprite_char_struct * sprite_char,Sint32 incx,Sint32 incy,Sint32 max_x,Sint32 max_y)645 sprite_char_rotate_enlarge (sprite_char_struct * sprite_char, Sint32 incx,
646                             Sint32 incy, Sint32 max_x, Sint32 max_y)
647 {
648   float sin_value, cos_value;
649   bool is_finished = FALSE;
650   sprite_char->angle =
651     (sprite_char->angle + sprite_char->angle_inc) & MAX_ANGLE;
652   sin_value = precalc_sin128[sprite_char->angle];
653   cos_value = precalc_cos128[sprite_char->angle];
654   if (sprite_char->radius_x < max_x)
655     {
656       sprite_char->radius_x += incx;
657     }
658   if (sprite_char->radius_y < max_y)
659     {
660       sprite_char->radius_y += incy;
661     }
662   if (sprite_char->radius_x > max_x)
663     {
664       sprite_char->radius_x = max_x;
665     }
666   if (sprite_char->radius_y > max_y)
667     {
668       sprite_char->radius_y = max_x;
669     }
670   if (sprite_char->radius_x == max_x && sprite_char->radius_y == max_y)
671     {
672       is_finished = TRUE;
673     }
674   sprite_char->coord_x =
675     (Sint32) (sin_value * sprite_char->radius_x) + sprite_char->center_x;
676   sprite_char->coord_y =
677     (Sint32) (cos_value * sprite_char->radius_y) + sprite_char->center_y;
678   return is_finished;
679 }
680 
681 /**
682  * Initialize a new string
683  * @param sprite_str a pointer to a sprites string structure
684  * @param str a simple string
685  */
686 bool
sprite_string_set_char(sprite_string_struct * sprite_str,const char * str)687 sprite_string_set_char (sprite_string_struct * sprite_str, const char *str)
688 {
689   if (strlen (str) > sprite_str->max_of_chars)
690     {
691       LOG_ERR ("string too long");
692       return FALSE;
693     }
694   strcpy (sprite_str->string, str);
695   sprite_str->num_of_chars = strlen (sprite_str->string);
696   /* convert ASCII code to pointer to the bitmap structure of the font */
697   sprite_chars_to_image (sprite_str);
698   return TRUE;
699 }
700 
701 /**
702  * Initialize values for chars rotation
703  * @param sprite_str a pointer to a sprites string structure
704  * @param angle
705  * @param angle_increment
706  * @radius_x
707  * @radius_y
708  */
709 void
sprite_string_init_rotation(sprite_string_struct * sprite_str,Uint32 angle,Uint32 angle_increment,Uint32 radius_x,Uint32 radius_y)710 sprite_string_init_rotation (sprite_string_struct * sprite_str, Uint32 angle,
711                              Uint32 angle_increment, Uint32 radius_x,
712                              Uint32 radius_y)
713 {
714   sprite_str->angle = angle;
715   sprite_str->angle_increment = angle_increment;
716   sprite_str->radius_x = radius_x;
717   sprite_str->radius_y = radius_y;
718 }
719 
720 /**
721  * Center the string horizontally at the screen
722  * @param sprite_str a pointer to a sprites string structure
723  * @param coordy y-coordinate
724  * @param offsetx horizontal offset to add to the x-coordinate
725  */
726 void
sprite_string_centerx(sprite_string_struct * sprite_str,float coordy,Uint32 offsetx)727 sprite_string_centerx (sprite_string_struct * sprite_str, float coordy,
728                        Uint32 offsetx)
729 {
730   Uint32 i, coordx, width;
731   width = sprite_str->space;
732   coordx =
733     (offscreen_width_visible - sprite_str->num_of_chars * width) / 2 +
734     offscreen_startx + offsetx;
735   sprite_str->coord_x = (float) coordx;
736   sprite_str->coord_y = coordy + offscreen_starty;
737   for (i = 0; i < sprite_str->num_of_chars; i++)
738     {
739       sprite_str->sprites_chars[i].coord_x = coordx;
740       sprite_str->sprites_chars[i].coord_y = (Uint32) sprite_str->coord_y;
741       coordx += width;
742     }
743 }
744 
745 /**
746  * Center string horizontally and vertically at the screen
747  * @param sprite_str a pointer to a sprites string structure
748  */
749 void
sprite_string_center(sprite_string_struct * sprite_str)750 sprite_string_center (sprite_string_struct * sprite_str)
751 {
752   Uint32 i, coordx, coordy, width;
753   width = sprite_str->space;
754   coordx =
755     (offscreen_width_visible - sprite_str->num_of_chars * width) / 2 +
756     offscreen_startx;
757   coordy = (offscreen_height_visible - width) / 2 + offscreen_starty;
758   sprite_str->coord_x = (float) coordx;
759   sprite_str->coord_y = (float) coordy;
760   for (i = 0; i < sprite_str->num_of_chars; i++)
761     {
762       sprite_str->sprites_chars[i].coord_x = coordx;
763       sprite_str->sprites_chars[i].coord_y = coordy;
764       coordx += width;
765     }
766 }
767 
768 /**
769  * Initialize radius center for chars rotation
770  * @param sprite_str a pointer to a sprites string structure
771  * @param centerx center x-coordinate, -1 if center in middle of screen vertically
772  * @param centery center y-coordinate, -1 if center in middle of screen horizontally
773  */
774 void
sprite_string_set_center(sprite_string_struct * sprite_str,Sint32 centerx,Sint32 centery)775 sprite_string_set_center (sprite_string_struct * sprite_str, Sint32 centerx,
776                           Sint32 centery)
777 {
778   if (centerx == -1)
779     {
780       sprite_str->center_x =
781         (offscreen_width_visible -
782          sprite_str->num_of_chars * sprite_str->space) / 2 + offscreen_startx;
783     }
784   else
785     {
786       sprite_str->center_x = centerx;
787     }
788   if (centery == -1)
789     {
790       sprite_str->center_y =
791         (offscreen_height_visible - sprite_str->space) / 2 + offscreen_starty;
792     }
793   else
794     {
795       sprite_str->center_y = centery;
796     }
797 }
798 
799 /**
800  * Decrease radius for chars rotations
801  * @param sprite_str a pointer to a sprites string structure
802  * @param dec_x
803  * @param dec_y
804  * @param min_pos
805  */
806 bool
sprites_string_rotation_dec(sprite_string_struct * sprite_str,Uint32 dec_x,Uint32 dec_y,Sint32 min_pos)807 sprites_string_rotation_dec (sprite_string_struct * sprite_str, Uint32 dec_x,
808                              Uint32 dec_y, Sint32 min_pos)
809 {
810   float sin, cos;
811   sprite_str->angle =
812     (sprite_str->angle + sprite_str->angle_increment) & MAX_ANGLE;
813   sin = precalc_sin128[sprite_str->angle];
814   cos = precalc_cos128[sprite_str->angle];
815   sprite_str->coord_x = (sin * sprite_str->radius_x) + sprite_str->center_x;
816   sprite_str->coord_y = (cos * sprite_str->radius_y) + sprite_str->center_y;
817   sprite_str->radius_x -= dec_x;
818   sprite_str->radius_y -= dec_y;
819   if (sprite_str->radius_x < min_pos)
820     {
821       sprite_str->radius_x = min_pos;
822     }
823   if (sprite_str->radius_y < min_pos)
824     {
825       sprite_str->radius_y = min_pos;
826     }
827   if (sprite_str->radius_x == min_pos && sprite_str->radius_y == min_pos)
828     {
829       return TRUE;
830     }
831   else
832     {
833       return FALSE;
834     }
835 }
836 
837 /**
838  * Increase radius for chars rotations
839  * @param sprite_str a pointer to a sprites string structure
840  * @param inc_x
841  * @param inc_y
842  * @param xmax_pos
843  * @param ymax_pos
844  */
845 bool
sprites_string_rotation_inc(sprite_string_struct * sprite_str,Uint32 inc_x,Uint32 inc_y,Sint32 xmax_pos,Sint32 ymax_pos)846 sprites_string_rotation_inc (sprite_string_struct * sprite_str, Uint32 inc_x,
847                              Uint32 inc_y, Sint32 xmax_pos, Sint32 ymax_pos)
848 {
849   float sin, cos;
850   sprite_str->angle =
851     (sprite_str->angle + sprite_str->angle_increment) & MAX_ANGLE;
852   sin = precalc_sin128[sprite_str->angle];
853   cos = precalc_cos128[sprite_str->angle];
854   sprite_str->coord_x = (sin * sprite_str->radius_x) + sprite_str->center_x;
855   sprite_str->coord_y = (cos * sprite_str->radius_y) + sprite_str->center_y;
856   sprite_str->radius_x += inc_x;
857   sprite_str->radius_y += inc_y;
858   if (sprite_str->radius_x > xmax_pos)
859     {
860       sprite_str->radius_x = xmax_pos;
861     }
862   if (sprite_str->radius_y > ymax_pos)
863     {
864       sprite_str->radius_y = ymax_pos;
865     }
866   if (sprite_str->radius_x == xmax_pos && sprite_str->radius_y == ymax_pos)
867     {
868       return TRUE;
869     }
870   else
871     {
872       return FALSE;
873     }
874 }
875 
876 /**
877  * Initialize coordinates of each char
878  * @param sprite_str pointer to a sprites string structure
879  */
880 void
sprite_string_coords(sprite_string_struct * sprite_str)881 sprite_string_coords (sprite_string_struct * sprite_str)
882 {
883   Uint32 i, coordx, coordy;
884   sprite_char_struct *sprite_char;
885   coordx = (Uint32) (sprite_str->coord_x + sprite_str->offset_x);
886   coordy = (Uint32) (sprite_str->coord_y + sprite_str->offset_y);
887   for (i = 0; i < sprite_str->num_of_chars; i++)
888     {
889       sprite_char = &sprite_str->sprites_chars[i];
890       sprite_char->coord_x = coordx;
891       sprite_char->coord_y = coordy;
892       coordx += sprite_str->space;
893     }
894 }
895 
896 /**
897  * Initialization of the speed of animation of each char
898  * @param sprite_str pointer to a sprites string structure
899  * @param anim_speed_inc
900  * @param anim_speed
901  * @param is_anim
902  * @pram anim_speed_count
903  */
904 void
sprite_string_init_anim(sprite_string_struct * sprite_str,Uint32 anim_speed_inc,Uint32 anim_speed,bool is_anim,Uint32 anim_speed_count)905 sprite_string_init_anim (sprite_string_struct * sprite_str,
906                          Uint32 anim_speed_inc, Uint32 anim_speed,
907                          bool is_anim, Uint32 anim_speed_count)
908 {
909   Uint32 i;
910   sprite_char_struct *sprite_char;
911   for (i = 0; i < sprite_str->num_of_chars; i++)
912     {
913       sprite_char = &sprite_str->sprites_chars[i];
914       sprite_char->anim_speed_count = anim_speed_count;
915       sprite_char->anim_speed_inc = anim_speed_inc;
916       sprite_char->anim_speed = anim_speed;
917       sprite_char->is_anim = is_anim;
918     }
919 }
920 
921 /**
922  * Convert ASCII code char to pointer to the bitmap structure of the char
923  * @param sprite_str pointer to a sprites string structure
924  */
925 void
sprite_chars_to_image(sprite_string_struct * sprite_str)926 sprite_chars_to_image (sprite_string_struct * sprite_str)
927 {
928   Uint32 i;
929   for (i = 0; i < sprite_str->num_of_chars; i++)
930     {
931       sprite_set_char (&sprite_str->sprites_chars[i], sprite_str->string[i]);
932     }
933 }
934 
935 /**
936  * Set the first image of each char
937  * @param sprite_str pointer to a sprites string structure
938  */
939 void
sprite_string_restart_anim(sprite_string_struct * sprite_str)940 sprite_string_restart_anim (sprite_string_struct * sprite_str)
941 {
942   Uint32 i;
943 
944   /* clear current image */
945   for (i = 0; i < sprite_str->num_of_chars; i++)
946     {
947       sprite_str->sprites_chars[i].current_image = 0;
948     }
949 }
950 
951 /**
952  * Enable animation of each char
953  * @param sprite_str pointer to a sprites string structure
954  */
955 void
sprite_string_set_anim(sprite_string_struct * sprite_str)956 sprite_string_set_anim (sprite_string_struct * sprite_str)
957 {
958   Uint32 i;
959 
960   /* enable char animation */
961   for (i = 0; i < sprite_str->num_of_chars; i++)
962     {
963       sprite_str->sprites_chars[i].is_anim = TRUE;
964     }
965 }
966 
967 /**
968  * Handle animation of each char
969  * @param sprite_str pointer to a sprites string structure
970  * @param restart TRUE if the animation of a char restarts
971  *        when it is finished
972  * return index of the last char updated, otherwise -1
973  */
974 Sint32
sprite_string_anim(sprite_string_struct * sprite_str,bool restart)975 sprite_string_anim (sprite_string_struct * sprite_str, bool restart)
976 {
977   Uint32 i;
978   sprite_char_struct *sprite_char;
979   Sint32 char_num = -1;
980   sprite_str->at_least_one_char_changed = FALSE;
981   sprite_str->none_char_animated = TRUE;
982 
983   /* animation of the chars */
984   for (i = 0; i < sprite_str->num_of_chars; i++)
985     {
986       sprite_char = &sprite_str->sprites_chars[i];
987       if (!sprite_char->is_anim)
988         {
989           continue;
990         }
991       sprite_str->none_char_animated = FALSE;
992       sprite_char->anim_speed_count += sprite_char->anim_speed_inc;
993       if (sprite_char->anim_speed_count < sprite_char->anim_speed)
994         {
995           continue;
996         }
997       sprite_str->at_least_one_char_changed = TRUE;
998       sprite_char->anim_speed_count -= sprite_char->anim_speed;
999       sprite_char->current_image++;
1000       if (sprite_char->current_image >= FONTS_MAX_OF_IMAGES)
1001         {
1002           sprite_char->current_image = 0;
1003           sprite_char->is_anim = restart;
1004           char_num = i;
1005         }
1006     }
1007   return char_num;
1008 }
1009 
1010 /**
1011  * Animation of each char separately, one by one
1012  * (like PAUSE text)
1013  * @param sprite_str pointer to a sprites string structure
1014  */
1015 bool
sprite_string_anim_one(sprite_string_struct * sprite_str)1016 sprite_string_anim_one (sprite_string_struct * sprite_str)
1017 {
1018   Uint32 count;
1019   bool is_display, is_last;
1020   is_last = FALSE;
1021   if (sprite_string_anim (sprite_str, FALSE) >=
1022       (Sint32) (sprite_str->num_of_chars - 1))
1023     {
1024       is_last = TRUE;
1025     }
1026 
1027   /* enable animation of the next char */
1028   sprite_str->delay_next_char_count++;
1029   if (sprite_str->delay_next_char_count > sprite_str->delay_next_char)
1030     {
1031       sprite_str->delay_next_char_count = 0;
1032       count = sprite_str->num_of_chars;
1033       do
1034         {
1035           count--;
1036           is_display =
1037             sprite_str->sprites_chars[sprite_str->current_char].is_display;
1038           if (is_display)
1039             {
1040               sprite_str->sprites_chars[sprite_str->current_char].is_anim =
1041                 TRUE;
1042             }
1043           sprite_str->current_char++;
1044           if (sprite_str->current_char >= sprite_str->num_of_chars)
1045             {
1046               sprite_str->current_char = 0;
1047               sprite_str->delay_next_char_count -=
1048                 sprite_str->delay_add_to_last;
1049             }
1050         }
1051       while (!is_display && count > 0);
1052     }
1053   return is_last;
1054 }
1055 
1056 /**
1057  * Draw the chars sprites
1058  * @param sprite_str pointer to a sprites string structure
1059  */
1060 void
sprite_string_draw(sprite_string_struct * sprite_str)1061 sprite_string_draw (sprite_string_struct * sprite_str)
1062 {
1063   Uint32 i;
1064   sprite_char_struct *sprite_char;
1065   bitmap *img;
1066 
1067   for (i = 0; i < sprite_str->num_of_chars; i++)
1068     {
1069       sprite_char = &sprite_str->sprites_chars[i];
1070       if (!sprite_char->is_display)
1071         {
1072           continue;
1073         }
1074       if (sprite_char->coord_x < sprite_char->xmin
1075           || sprite_char->coord_x > sprite_char->xmax
1076           || sprite_char->coord_y < sprite_char->ymin
1077           || sprite_char->coord_y > sprite_char->ymax)
1078         {
1079           continue;
1080         }
1081       switch (sprite_char->type_of_font)
1082         {
1083         case FONT_GAME:
1084           img =
1085             &fnt_game[sprite_char->current_char][sprite_char->current_image];
1086           break;
1087         default:
1088         case FONT_BIG:
1089           img =
1090             &fnt_big[sprite_char->current_char][sprite_char->current_image];
1091           break;
1092         case FONT_SCROLL:
1093           img = &fnt_scroll[sprite_char->current_char];
1094           break;
1095         case FONT_SCORE:
1096           img =
1097             &fnt_score[sprite_char->current_char][sprite_char->current_image];
1098           break;
1099         }
1100       switch (sprite_char->which_offscreen)
1101         {
1102         case FONT_DRAW_TOP_PANEL:
1103           draw_bitmap_in_score (img, sprite_char->coord_x,
1104                                 sprite_char->coord_y);
1105           break;
1106         default:
1107           draw_bitmap (img, sprite_char->coord_x, sprite_char->coord_y);
1108           break;
1109         }
1110     }
1111 }
1112 
1113 /**
1114  * Input string from keyboard and joystick
1115  * @param sprite_str pointer to a sprites string structure
1116  * @return keycode pressed
1117  */
1118 Sint32
sprites_string_input(sprite_string_struct * sprite_str)1119 sprites_string_input (sprite_string_struct * sprite_str)
1120 {
1121   sprite_char_struct *sprite_char;
1122   char c;
1123   Sint32 joycode;
1124   Sint32 keycode = 0;
1125   if (input_delay < 1)
1126     {
1127       keycode = keycode_down;
1128       if (keycode_down > 0)
1129         {
1130           /* key pressed for the first time? */
1131           if (keycode_down_prev != keycode_down)
1132             {
1133               keycode_down_prev = keycode_down;
1134               input_delay = 40;
1135             }
1136           else
1137             {
1138               input_delay = 5;
1139             }
1140         }
1141     }
1142   else
1143     {
1144       keycode = 0;
1145       input_delay--;
1146     }
1147   sprites_string_input_code (sprite_str, keycode);
1148 
1149   /* input string with the joystick */
1150   joycode = 0;
1151   if (input_joy_tempo < 1)
1152     {
1153       joycode = joy_code_down;
1154       if (joy_code_down > 0)
1155         {
1156           /* button pressed for the first time? */
1157           if (joy_code_down_prev != joy_code_down)
1158             {
1159               joy_code_down_prev = joy_code_down;
1160               input_joy_tempo = 40;
1161             }
1162           else
1163             {
1164               input_joy_tempo = 5;
1165             }
1166         }
1167     }
1168   else
1169     {
1170       joycode = 0;
1171       input_joy_tempo--;
1172     }
1173   if (joycode > 0)
1174     {
1175       switch (joycode)
1176         {
1177         case IJOY_FIRE:
1178 #ifdef POWERMANGA_SDL
1179           keycode = SDLK_RETURN;
1180 #else
1181           keycode = XK_Return;
1182 #endif
1183           sprites_string_input_code (sprite_str, keycode);
1184           break;
1185         case IJOY_OPT:
1186           sprite_str->string[sprite_str->cursor_pos] = ' ';
1187           sprite_chars_to_image (sprite_str);
1188           break;
1189         case IJOY_LEFT:
1190 #ifdef POWERMANGA_SDL
1191           sprites_string_input_code (sprite_str, SDLK_LEFT);
1192 #else
1193           sprites_string_input_code (sprite_str, XK_Left);
1194 #endif
1195           break;
1196         case IJOY_RIGHT:
1197 #ifdef POWERMANGA_SDL
1198           sprites_string_input_code (sprite_str, SDLK_RIGHT);
1199 #else
1200           sprites_string_input_code (sprite_str, XK_Right);
1201 #endif
1202           break;
1203         case IJOY_TOP:
1204           {
1205             c = sprite_str->string[sprite_str->cursor_pos] + 1;
1206             if (c > 90 && c < 97)
1207               {
1208                 c = 97;
1209               }
1210             else if (c > 122)
1211               {
1212                 c = 32;
1213               }
1214             sprite_str->string[sprite_str->cursor_pos] = c;
1215             sprite_chars_to_image (sprite_str);
1216             sprite_char = &sprite_str->sprites_chars[sprite_str->cursor_pos];
1217             sprite_char->is_anim = TRUE;
1218           }
1219           break;
1220         case IJOY_DOWN:
1221           c = sprite_str->string[sprite_str->cursor_pos] - 1;
1222           if (c > 90 && c < 97)
1223             {
1224               c = 90;
1225             }
1226           else if (c < 32)
1227             {
1228               c = 122;
1229             }
1230           sprite_str->string[sprite_str->cursor_pos] = c;
1231           sprite_chars_to_image (sprite_str);
1232           sprite_char = &sprite_str->sprites_chars[sprite_str->cursor_pos];
1233           sprite_char->is_anim = TRUE;
1234           break;
1235         }
1236 
1237     }
1238   return keycode;
1239 }
1240 
1241 /**
1242  * Input string from keyboard
1243  * @param sprite_str pointer to a sprites string structure
1244  * @param keycode the keycode pressed
1245  */
1246 void
sprites_string_input_code(sprite_string_struct * sprite_str,Sint32 keycode)1247 sprites_string_input_code (sprite_string_struct * sprite_str, Sint32 keycode)
1248 {
1249   Uint32 i, j;
1250   Sint32 xcoord, ycoord, cursor_size;
1251   unsigned char color;
1252   float sin_val;
1253   sprite_char_struct *sprite_char;
1254   sprite_str->cursor_status = 0;
1255 
1256   /* display blink cursor */
1257   color = get_next_color ();
1258   sprite_str->angle = (sprite_str->angle + 1) & MAX_ANGLE;
1259   sin_val = precalc_sin128[sprite_str->angle];
1260   cursor_size = (Sint32) (sin_val * sprite_str->space / 2);
1261   if (cursor_size < 0)
1262     {
1263       cursor_size = -cursor_size;
1264     }
1265   cursor_size++;
1266   xcoord =
1267     (Sint32) sprite_str->coord_x +
1268     (sprite_str->cursor_pos * sprite_str->space) + sprite_str->space / 2 -
1269     cursor_size;
1270   ycoord = (Sint32) sprite_str->coord_y + sprite_str->space / 2 - cursor_size;
1271   cursor_size += cursor_size;
1272   if (ycoord + cursor_size >= offscreen_starty)
1273     {
1274       draw_empty_rectangle (game_offscreen, xcoord, ycoord - 2, color,
1275                             cursor_size, cursor_size);
1276     }
1277 
1278   /* check key code */
1279   switch (keycode)
1280     {
1281 #ifdef POWERMANGA_SDL
1282     case SDLK_LEFT:
1283 #else
1284     case XK_Left:
1285 #endif
1286       sprite_str->cursor_pos--;
1287       break;
1288 #ifdef POWERMANGA_SDL
1289     case SDLK_RIGHT:
1290 #else
1291     case XK_Right:
1292 #endif
1293       sprite_str->cursor_pos++;
1294       break;
1295 #ifdef POWERMANGA_SDL
1296     case SDLK_BACKSPACE:
1297 #else
1298     case XK_BackSpace:
1299 #endif
1300       if (sprite_str->cursor_pos > 0)
1301         {
1302           j = sprite_str->cursor_pos;
1303         }
1304       else
1305         {
1306           j = 1;
1307         }
1308       for (i = j; i < sprite_str->num_of_chars; i++)
1309         {
1310           sprite_str->string[i - 1] = sprite_str->string[i];
1311         }
1312       sprite_str->string[sprite_str->num_of_chars - 1] = ' ';
1313       sprite_str->cursor_pos--;
1314       sprite_chars_to_image (sprite_str);
1315       break;
1316 #ifdef POWERMANGA_SDL
1317     case SDLK_DELETE:
1318 #else
1319     case XK_Delete:
1320 #endif
1321       for (i = sprite_str->cursor_pos; i <= sprite_str->num_of_chars - 2; i++)
1322         {
1323           sprite_str->string[i] = sprite_str->string[i + 1];
1324         }
1325       sprite_str->string[sprite_str->num_of_chars - 1] = ' ';
1326       sprite_chars_to_image (sprite_str);
1327       break;
1328 #ifdef POWERMANGA_SDL
1329     case SDLK_RETURN:
1330       break;
1331     case SDLK_UP:
1332       break;
1333     case SDLK_DOWN:
1334       break;
1335     case SDLK_LSHIFT:
1336       break;
1337     case SDLK_RSHIFT:
1338       break;
1339     case SDLK_LCTRL:
1340       break;
1341     case SDLK_RCTRL:
1342       break;
1343     case SDLK_F1:
1344       break;
1345     case SDLK_F2:
1346       break;
1347     case SDLK_F3:
1348       break;
1349     case SDLK_F4:
1350       break;
1351     case SDLK_F5:
1352       break;
1353     case SDLK_F6:
1354       break;
1355     case SDLK_F7:
1356       break;
1357     case SDLK_F8:
1358       break;
1359     case SDLK_F9:
1360       break;
1361     case SDLK_F10:
1362       break;
1363     case SDLK_F11:
1364       break;
1365     case SDLK_F12:
1366       break;
1367 #else
1368     case XK_Return:
1369       break;
1370     case XK_Up:
1371       break;
1372     case XK_Down:
1373       break;
1374     case XK_Shift_L:
1375       break;
1376     case XK_Shift_R:
1377       break;
1378     case XK_Control_L:
1379       break;
1380     case XK_Control_R:
1381       break;
1382     case XK_F1:
1383       break;
1384     case XK_F2:
1385       break;
1386     case XK_F3:
1387       break;
1388     case XK_F4:
1389       break;
1390     case XK_F5:
1391       break;
1392     case XK_F6:
1393       break;
1394     case XK_F7:
1395       break;
1396     case XK_F8:
1397       break;
1398     case XK_F9:
1399       break;
1400     case XK_F10:
1401       break;
1402     case XK_F11:
1403       break;
1404     case XK_F12:
1405       break;
1406 #endif
1407     default:
1408       keycode = keycode & 127;
1409       if (keycode >= ' ' && keycode <= 'z')
1410         {
1411           for (i = sprite_str->num_of_chars - 1;
1412                i > (Uint32) sprite_str->cursor_pos; i--)
1413             {
1414               sprite_str->string[i] = sprite_str->string[i - 1];
1415             }
1416           sprite_str->string[sprite_str->cursor_pos] = (char) keycode;
1417           sprite_char = &sprite_str->sprites_chars[sprite_str->cursor_pos];
1418           sprite_str->cursor_pos++;
1419           sprite_chars_to_image (sprite_str);
1420         }
1421     }
1422 
1423   /* checks the cursor position */
1424   if (sprite_str->cursor_pos < 0)
1425     {
1426       sprite_str->cursor_pos = 0;
1427       sprite_str->cursor_status = 1;
1428     }
1429   if ((Uint32) sprite_str->cursor_pos > sprite_str->num_of_chars - 1)
1430     {
1431       sprite_str->cursor_pos = sprite_str->num_of_chars - 1;
1432       sprite_str->cursor_status = 2;
1433     }
1434   sprite_char = &sprite_str->sprites_chars[sprite_str->cursor_pos];
1435   sprite_char->is_anim = TRUE;
1436 }
1437 
1438 
1439 /**
1440  * Set a joystick code
1441  * @param code A joystick code, a buttom is down
1442  */
1443 void
sprites_string_set_joy(Uint32 code)1444 sprites_string_set_joy (Uint32 code)
1445 {
1446   joy_code_down = code;
1447   input_joy_tempo = 0;
1448 }
1449 
1450 /**
1451  * Clear a joystick code, a button is up
1452  * @param code A joystick code
1453  */
1454 void
sprites_string_clr_joy(Uint32 code)1455 sprites_string_clr_joy (Uint32 code)
1456 {
1457   joy_up = code;
1458   if (joy_up == joy_code_down)
1459     {
1460       joy_code_down = 0;
1461       input_joy_tempo = 0;
1462       input_delay = 0;
1463       joy_code_down_prev = 0;
1464     }
1465 }
1466 
1467 /**
1468  * Set the code of the pressed key
1469  * @param code
1470  * @param sym
1471  */
1472 void
sprites_string_key_down(Uint32 code,Uint32 sym)1473 sprites_string_key_down (Uint32 code, Uint32 sym)
1474 {
1475   keycode_down = code;
1476   keysym_down = sym;
1477   input_delay = 0;
1478 }
1479 
1480 /**
1481  * Set the code of the released key
1482  * @param code
1483  * @param sym
1484  */
1485 void
sprites_string_key_up(Uint32 code,Uint32 sym)1486 sprites_string_key_up (Uint32 code, Uint32 sym)
1487 {
1488   keycode_up = code;
1489   keysym_up = sym;
1490   if (keysym_up == keysym_down)
1491     {
1492       keycode_down = 0;
1493       keysym_down = 0;
1494       input_delay = 0;
1495       keycode_down_prev = 0;
1496     }
1497 }
1498 
1499 /**
1500  * Set the cursor position
1501  * @param sprite_str Pointer to a sprites string structure
1502  * @param cursor_pos The cursor position
1503  */
1504 void
sprites_string_set_cursor_pos(sprite_string_struct * sprite_str,Sint32 cursor_pos)1505 sprites_string_set_cursor_pos (sprite_string_struct * sprite_str,
1506                                Sint32 cursor_pos)
1507 {
1508   sprite_str->cursor_pos = cursor_pos;
1509   if (sprite_str->cursor_pos < 0)
1510     {
1511       sprite_str->cursor_pos = 0;
1512     }
1513   if ((Uint32) sprite_str->cursor_pos > sprite_str->num_of_chars)
1514     {
1515       sprite_str->cursor_pos = sprite_str->num_of_chars;
1516     }
1517 }
1518