1 /*
2  * Draws fretwork
3  *
4  * Last updated: 2019-08-29
5  */
6 
7 #include "tp_magic_api.h"
8 #include "SDL_image.h"
9 #include "SDL_mixer.h"
10 #include <stdbool.h>
11 
12 #define SEG_NONE 0
13 
14 #define SEG_LEFT 1
15 #define SEG_RIGHT 2
16 #define SEG_TOP 4
17 #define SEG_BOTTOM 8
18 
19 #define SEG_LEFT_RIGHT (SEG_LEFT | SEG_RIGHT)
20 #define SEG_TOP_BOTTOM (SEG_TOP | SEG_BOTTOM)
21 #define SEG_RIGHT_TOP (SEG_RIGHT | SEG_TOP)
22 #define SEG_RIGHT_BOTTOM (SEG_RIGHT | SEG_BOTTOM)
23 #define SEG_LEFT_TOP (SEG_LEFT | SEG_TOP)
24 #define SEG_LEFT_BOTTOM (SEG_LEFT | SEG_BOTTOM)
25 #define SEG_LEFT_RIGHT_TOP (SEG_LEFT | SEG_RIGHT | SEG_TOP)
26 #define SEG_LEFT_RIGHT_BOTTOM (SEG_LEFT | SEG_RIGHT | SEG_BOTTOM)
27 #define SEG_LEFT_TOP_BOTTOM (SEG_LEFT | SEG_TOP | SEG_BOTTOM)
28 #define SEG_RIGHT_TOP_BOTTOM (SEG_RIGHT | SEG_TOP | SEG_BOTTOM)
29 #define SEG_LEFT_RIGHT_TOP_BOTTOM (SEG_LEFT | SEG_RIGHT | SEG_TOP | SEG_BOTTOM)
30 
31 Mix_Chunk *fretwork_snd;
32 unsigned int img_w, img_h;
33 unsigned int fretwork_segments_x, fretwork_segments_y;  //how many segments do we have?
34 inline int fretwork_math_ceil(int x, int y);    //ceil() in cstdlib returns float and is relative slow, so we'll use our one
35 static Uint8 *fretwork_status_of_segments;      //a place to store an info about bitmap used for selected segment
36 static char **fretwork_images;  //the pathes to all the images needed
37 static unsigned int fretwork_segment_modified;  //which segment was modified this time?
38 static unsigned int fretwork_segment_modified_last = 0; //which segment was last modified
39 static unsigned int fretwork_segment_to_add = 0;        //a segment that should be added to solve corner joint
40 static unsigned int fretwork_segment_last_clicked;
41 static Uint8 fretwork_r, fretwork_g, fretwork_b;
42 static unsigned int fretwork_full_runs; //The count of the clicks in full mode
43 static unsigned int fretwork_segment_start_rectangle;   //the segment were the update_rectangle will start
44 static unsigned int fretwork_update_rectangle_width;    //the width of the update_rectangle
45 static unsigned int fretwork_update_rectangle_height;   //the height of the update_rectangle
46 static SDL_Rect modification_rect;
47 static SDL_Surface *canvas_backup;
48 static SDL_Surface *fretwork_one_back, *fretwork_three_back, *fretwork_four_back, *fretwork_corner_back;
49 
50 
51 //                              Housekeeping functions
52 
53 Uint32 fretwork_api_version(void);
54 int fretwork_modes(magic_api * api, int which);
55 void fretwork_set_color(magic_api * api, Uint8 r, Uint8 g, Uint8 b);
56 static void fretwork_colorize(magic_api * api, SDL_Surface * dest, SDL_Surface * src);
57 int fretwork_init(magic_api * api);
58 int fretwork_get_tool_count(magic_api * api);
59 SDL_Surface *fretwork_get_icon(magic_api * api, int which);
60 char *fretwork_get_name(magic_api * api, int which);
61 char *fretwork_get_description(magic_api * api, int which, int mode);
62 int fretwork_requires_colors(magic_api * api, int which);
63 void fretwork_release(magic_api * api, int which,
64                       SDL_Surface * canvas, SDL_Surface * snapshot, int x, int y, SDL_Rect * update_rect);
65 void fretwork_shutdown(magic_api * api);
66 void fretwork_switchin(magic_api * api, int which, int mode, SDL_Surface * canvas, SDL_Surface * snapshot);
67 void fretwork_switchout(magic_api * api, int which, int mode, SDL_Surface * canvas, SDL_Surface * snapshot);
68 inline void fretwork_extract_coords_from_segment(unsigned int segment, Sint16 * x, Sint16 * y);
69 void fretwork_click(magic_api * api, int which, int mode,
70                     SDL_Surface * canvas, SDL_Surface * snapshot, int x, int y, SDL_Rect * update_rect);
71 
72 
73 
74 void fretwork_drag(magic_api * api, int which, SDL_Surface * canvas,
75                    SDL_Surface * snapshot, int ox, int oy, int x, int y, SDL_Rect * update_rect);
76 static void fretwork_draw_wrapper(void *ptr, int which, SDL_Surface * canvas, SDL_Surface * last, int x, int y);
77 inline unsigned int fretwork_get_segment(int x, int y);
78 
79 
80 SDL_Surface *fretwork_one, *fretwork_three, *fretwork_four, *fretwork_corner;
81 
fretwork_api_version(void)82 Uint32 fretwork_api_version(void)
83 {
84   return (TP_MAGIC_API_VERSION);
85 }
86 
fretwork_modes(magic_api * api ATTRIBUTE_UNUSED,int which ATTRIBUTE_UNUSED)87 int fretwork_modes(magic_api * api ATTRIBUTE_UNUSED, int which ATTRIBUTE_UNUSED)
88 {
89   return (MODE_PAINT | MODE_FULLSCREEN);
90 }
91 
fretwork_set_color(magic_api * api,Uint8 r,Uint8 g,Uint8 b)92 void fretwork_set_color(magic_api * api, Uint8 r, Uint8 g, Uint8 b)
93 {
94   fretwork_r = r;
95   fretwork_g = g;
96   fretwork_b = b;
97   fretwork_colorize(api, fretwork_one, fretwork_one_back);
98   fretwork_colorize(api, fretwork_three, fretwork_three_back);
99   fretwork_colorize(api, fretwork_four, fretwork_four_back);
100   fretwork_colorize(api, fretwork_corner, fretwork_corner_back);
101 }
102 
103 /* Adapted from flower.c */
fretwork_colorize(magic_api * api,SDL_Surface * dest,SDL_Surface * src)104 static void fretwork_colorize(magic_api * api, SDL_Surface * dest, SDL_Surface * src)
105 {
106   int x, y;
107   Uint8 r, g, b, a;
108 
109   SDL_LockSurface(src);
110   SDL_LockSurface(dest);
111 
112   for (y = 0; y < src->h; y++)
113     {
114       for (x = 0; x < src->w; x++)
115         {
116           SDL_GetRGBA(api->getpixel(src, x, y), src->format, &r, &g, &b, &a);
117 
118           api->putpixel(dest, x, y, SDL_MapRGBA(dest->format, fretwork_r, fretwork_g, fretwork_b, a));
119         }
120     }
121 
122   SDL_UnlockSurface(src);
123   SDL_UnlockSurface(dest);
124 }
125 
126 
fretwork_init(magic_api * api)127 int fretwork_init(magic_api * api)
128 {
129   char fname[1024];
130   Uint8 i;                      //is always < 4, so Uint8 seems to be a good idea
131 
132   fretwork_images = (char **)malloc(sizeof(char *) * 4);
133 
134   for (i = 0; i < 4; i++)
135     fretwork_images[i] = (char *)malloc(sizeof(char) * 1024);
136 
137   snprintf(fretwork_images[0], 1024 * sizeof(char), "%s/images/magic/fretwork_one.png", api->data_directory);
138   snprintf(fretwork_images[1], 1024 * sizeof(char), "%s/images/magic/fretwork_three.png", api->data_directory);
139   snprintf(fretwork_images[2], 1024 * sizeof(char), "%s/images/magic/fretwork_four.png", api->data_directory);
140   snprintf(fretwork_images[3], 1024 * sizeof(char), "%s/images/magic/fretwork_corner.png", api->data_directory);
141 
142   fretwork_one = IMG_Load(fretwork_images[0]);
143   fretwork_three = IMG_Load(fretwork_images[1]);
144   fretwork_four = IMG_Load(fretwork_images[2]);
145   fretwork_corner = IMG_Load(fretwork_images[3]);
146   fretwork_one_back = IMG_Load(fretwork_images[0]);
147   fretwork_three_back = IMG_Load(fretwork_images[1]);
148   fretwork_four_back = IMG_Load(fretwork_images[2]);
149   fretwork_corner_back = IMG_Load(fretwork_images[3]);
150 
151   img_w = fretwork_one->w;
152   img_h = fretwork_one->h;
153 
154   snprintf(fname, sizeof(fname), "%s/sounds/magic/fretwork.ogg", api->data_directory);
155   fretwork_snd = Mix_LoadWAV(fname);
156 
157   return (1);
158 }
159 
fretwork_get_tool_count(magic_api * api ATTRIBUTE_UNUSED)160 int fretwork_get_tool_count(magic_api * api ATTRIBUTE_UNUSED)
161 {
162   return 1;
163 }
164 
fretwork_get_icon(magic_api * api,int which ATTRIBUTE_UNUSED)165 SDL_Surface *fretwork_get_icon(magic_api * api, int which ATTRIBUTE_UNUSED)
166 {
167   char fname[1024];
168 
169   snprintf(fname, sizeof(fname), "%s/images/magic/fretwork.png", api->data_directory);
170 
171   return (IMG_Load(fname));
172 }
173 
fretwork_get_name(magic_api * api ATTRIBUTE_UNUSED,int which ATTRIBUTE_UNUSED)174 char *fretwork_get_name(magic_api * api ATTRIBUTE_UNUSED, int which ATTRIBUTE_UNUSED)
175 {
176   return strdup(gettext_noop("Fretwork"));
177 }
178 
fretwork_get_description(magic_api * api ATTRIBUTE_UNUSED,int which ATTRIBUTE_UNUSED,int mode)179 char *fretwork_get_description(magic_api * api ATTRIBUTE_UNUSED, int which ATTRIBUTE_UNUSED, int mode)
180 {
181   if (mode == MODE_PAINT)
182     return strdup(gettext_noop("Click and drag to draw repetitive patterns. "));
183   else
184     return strdup(gettext_noop("Click to surround your picture with repetitive patterns."));
185 }
186 
fretwork_requires_colors(magic_api * api ATTRIBUTE_UNUSED,int which ATTRIBUTE_UNUSED)187 int fretwork_requires_colors(magic_api * api ATTRIBUTE_UNUSED, int which ATTRIBUTE_UNUSED)
188 {
189   return 1;
190 }
191 
fretwork_release(magic_api * api ATTRIBUTE_UNUSED,int which ATTRIBUTE_UNUSED,SDL_Surface * canvas ATTRIBUTE_UNUSED,SDL_Surface * snapshot ATTRIBUTE_UNUSED,int x ATTRIBUTE_UNUSED,int y ATTRIBUTE_UNUSED,SDL_Rect * update_rect ATTRIBUTE_UNUSED)192 void fretwork_release(magic_api * api ATTRIBUTE_UNUSED, int which ATTRIBUTE_UNUSED,
193                       SDL_Surface * canvas ATTRIBUTE_UNUSED, SDL_Surface * snapshot ATTRIBUTE_UNUSED,
194                       int x ATTRIBUTE_UNUSED, int y ATTRIBUTE_UNUSED, SDL_Rect * update_rect ATTRIBUTE_UNUSED)
195 {
196 }
197 
fretwork_shutdown(magic_api * api ATTRIBUTE_UNUSED)198 void fretwork_shutdown(magic_api * api ATTRIBUTE_UNUSED)
199 {
200   Uint8 i;
201 
202   if (fretwork_snd != NULL)
203     Mix_FreeChunk(fretwork_snd);
204   SDL_FreeSurface(fretwork_one);
205   SDL_FreeSurface(fretwork_three);
206   SDL_FreeSurface(fretwork_four);
207   SDL_FreeSurface(fretwork_corner);
208   SDL_FreeSurface(fretwork_one_back);
209   SDL_FreeSurface(fretwork_three_back);
210   SDL_FreeSurface(fretwork_four_back);
211   SDL_FreeSurface(fretwork_corner_back);
212   SDL_FreeSurface(canvas_backup);
213 
214   for (i = 0; i < 4; i++)
215     free(fretwork_images[i]);
216   free(fretwork_images);
217   if (fretwork_status_of_segments != NULL)
218     free(fretwork_status_of_segments);
219 }
220 
fretwork_switchin(magic_api * api ATTRIBUTE_UNUSED,int which ATTRIBUTE_UNUSED,int mode ATTRIBUTE_UNUSED,SDL_Surface * canvas,SDL_Surface * snapshot ATTRIBUTE_UNUSED)221 void fretwork_switchin(magic_api * api ATTRIBUTE_UNUSED, int which ATTRIBUTE_UNUSED, int mode ATTRIBUTE_UNUSED,
222                        SDL_Surface * canvas, SDL_Surface * snapshot ATTRIBUTE_UNUSED)
223 {
224   //we've to compute the quantity of segments in each direction
225 
226   canvas_backup = SDL_CreateRGBSurface(SDL_ANYFORMAT, canvas->w, canvas->h, canvas->format->BitsPerPixel,
227                                        canvas->format->Rmask, canvas->format->Gmask, canvas->format->Bmask,
228                                        canvas->format->Amask);
229 
230   SDL_BlitSurface(canvas, NULL, canvas_backup, NULL);
231   fretwork_segments_x = fretwork_math_ceil(canvas->w, img_w);
232   fretwork_segments_y = fretwork_math_ceil(canvas->h, img_h);
233   fretwork_status_of_segments = (Uint8 *) calloc(fretwork_segments_x * fretwork_segments_y + 1, sizeof(Uint8)); //segments starts at 1, while fretwork_status_of_segments[] starts at 0
234   fretwork_full_runs = 1;
235 }
236 
237 
fretwork_switchout(magic_api * api ATTRIBUTE_UNUSED,int which ATTRIBUTE_UNUSED,int mode ATTRIBUTE_UNUSED,SDL_Surface * canvas ATTRIBUTE_UNUSED,SDL_Surface * snapshot ATTRIBUTE_UNUSED)238 void fretwork_switchout(magic_api * api ATTRIBUTE_UNUSED, int which ATTRIBUTE_UNUSED, int mode ATTRIBUTE_UNUSED,
239                         SDL_Surface * canvas ATTRIBUTE_UNUSED, SDL_Surface * snapshot ATTRIBUTE_UNUSED)
240 {
241   free(fretwork_status_of_segments);
242   fretwork_status_of_segments = NULL;
243 }
244 
245 // Interactivity functions
246 
247 
fretwork_math_ceil(int x,int y)248 inline int fretwork_math_ceil(int x, int y)
249 {
250   int temp;
251 
252   temp = (int)x / y;
253   if (x % y)
254     return temp + 1;
255   else
256     return temp;
257 }
258 
fretwork_get_segment(int x,int y)259 inline unsigned int fretwork_get_segment(int x, int y)
260 {
261   int xx;                       //segments are numerated just like pixels
262   int yy;                       //in computer graphics: left upper (=1), ... ,right upper,
263 
264   //left bottom, ... , right bottom
265   xx = fretwork_math_ceil(x, img_w);
266   yy = fretwork_math_ceil(y, img_h);
267 
268   return (yy - 1) * fretwork_segments_x + xx;
269 }
270 
fretwork_extract_coords_from_segment(unsigned int segment,Sint16 * x,Sint16 * y)271 inline void fretwork_extract_coords_from_segment(unsigned int segment, Sint16 * x, Sint16 * y)
272 {
273   *x = ((segment % fretwork_segments_x) - 1) * img_w;   //useful to set update_rect as small as possible
274   *y = (int)(segment / fretwork_segments_x) * img_h;
275 }
276 
277 /* static void fretwork_flip(void * ptr, SDL_Surface * dest, SDL_Surface * src) */
278 /* { */
279 /*   magic_api * api = (magic_api *) ptr; */
280 
281 /*   Sint16 x, y; */
282 
283 /*   for (x=0; x<dest->w; x++) */
284 /*     for (y=0; y<dest->h; y++) */
285 /*       api->putpixel(dest, x, y, api->getpixel(src, x, src->h-y)); */
286 /* } */
287 
fretwork_flip_flop(void * ptr,SDL_Surface * dest,SDL_Surface * src)288 static void fretwork_flip_flop(void *ptr, SDL_Surface * dest, SDL_Surface * src)
289 {
290   magic_api *api = (magic_api *) ptr;
291   Sint16 x, y;
292 
293   for (x = 0; x < dest->w; x++)
294     for (y = 0; y < dest->h; y++)
295       api->putpixel(dest, dest->w - 1 - x, dest->h - 1 - y, api->getpixel(src, x, y));
296 }
297 
fretwork_rotate(void * ptr,SDL_Surface * dest,SDL_Surface * src,_Bool direction)298 static void fretwork_rotate(void *ptr, SDL_Surface * dest, SDL_Surface * src, _Bool direction)
299      //src and dest must have same size
300 {
301   magic_api *api = (magic_api *) ptr;
302   Sint16 x, y;
303 
304   if (direction)                //rotate -90 degs
305     {
306       for (x = 0; x < dest->w; x++)
307         for (y = 0; y < dest->h; y++)
308           api->putpixel(dest, x, y, api->getpixel(src, y, src->h - 1 - x));
309     }
310   else                          //rotate +90 degs
311     {
312       for (x = 0; x < dest->w; x++)
313         for (y = 0; y < dest->h; y++)
314           api->putpixel(dest, x, y, api->getpixel(src, src->h - y - 1, x));
315     }
316 
317 }
318 
319 
fretwork_click(magic_api * api,int which,int mode,SDL_Surface * canvas,SDL_Surface * snapshot,int x,int y,SDL_Rect * update_rect)320 void fretwork_click(magic_api * api, int which, int mode,
321                     SDL_Surface * canvas, SDL_Surface * snapshot, int x, int y, SDL_Rect * update_rect)
322 {
323   int left_x, right_x, top_y, bottom_y;
324 
325   fretwork_segment_modified_last = 0;
326   if (mode == MODE_PAINT)
327     {
328       fretwork_segment_last_clicked = fretwork_get_segment(x, y);
329       fretwork_drag(api, which, canvas, snapshot, x, y, x, y, update_rect);
330     }
331   else
332     {
333       if (fretwork_full_runs <= min(fretwork_segments_x, fretwork_segments_y) / 2)
334         {
335           left_x = img_w * fretwork_full_runs;
336           right_x = img_w * fretwork_segments_x - img_w * fretwork_full_runs;
337           top_y = img_h * fretwork_full_runs;
338           bottom_y = img_h * fretwork_segments_y - img_h * (fretwork_full_runs - 1);
339 
340           //left line
341           api->line((void *)api, which, canvas, snapshot, left_x, top_y, left_x, bottom_y, img_w / 2,
342                     fretwork_draw_wrapper);
343 
344           //top line
345           api->line((void *)api, which, canvas, snapshot, left_x, top_y, right_x, top_y, img_w / 2,
346                     fretwork_draw_wrapper);
347 
348           //bottom line
349           api->line((void *)api, which, canvas, snapshot, left_x, bottom_y, right_x, bottom_y, img_w / 2,
350                     fretwork_draw_wrapper);
351 
352           //right line
353           api->line((void *)api, which, canvas, snapshot, right_x, top_y, right_x, bottom_y, img_w / 2,
354                     fretwork_draw_wrapper);
355 
356           fretwork_full_runs += 1;
357           update_rect->x = 0;
358           update_rect->y = 0;
359           update_rect->w = canvas->w;
360           update_rect->h = canvas->h;
361         }
362     }
363 }
364 
fretwork_select_image(Uint16 segment)365 static Uint8 fretwork_select_image(Uint16 segment)
366 {
367   int take_up, take_down;
368   int val_up, val_down, val_left, val_right;
369   int from_top = 0, from_bottom = 0, from_left = 0, from_right = 0;
370   int from_top_right = 0, from_top_left = 0, from_bottom_right = 0, from_bottom_left = 0;
371   int TOP = 0, BOTTOM = 0, LEFT = 0, RIGHT = 0;
372 
373   //Checking from were we come...
374   if (fretwork_segment_modified_last > 0)
375     {
376       if (segment == fretwork_segment_modified_last + 1)
377         from_left = 1;
378       else if (segment == fretwork_segment_modified_last - 1)
379         from_right = 1;
380       else if (segment == fretwork_segment_modified_last - fretwork_segments_x)
381         from_bottom = 1;
382       else if (segment == fretwork_segment_modified_last + fretwork_segments_x)
383         from_top = 1;
384 
385       // Very very few cases will reach this, segments are joining by the corner
386       // We need to add a new segment to join by side, adding clockwise
387       else if (segment == fretwork_segment_modified_last + fretwork_segments_x + 1)
388         {
389           from_top_left = 1;
390           fretwork_segment_to_add = segment - fretwork_segments_x;
391         }
392       else if (segment == fretwork_segment_modified_last + fretwork_segments_x - 1)
393         {
394           from_top_right = 1;
395           fretwork_segment_to_add = segment + 1;
396         }
397       else if (segment == fretwork_segment_modified_last - fretwork_segments_x - 1)
398         {
399           from_bottom_right = 1;
400           fretwork_segment_to_add = segment + fretwork_segments_x;
401         }
402       else if (segment == fretwork_segment_modified_last - fretwork_segments_x + 1)
403         {
404           from_bottom_left = 1;
405           fretwork_segment_to_add = segment - 1;
406         }
407     }
408 
409   take_up = segment - fretwork_segments_x;
410   if (take_up <= 0)
411     val_up = SEG_NONE;
412   else
413     val_up = fretwork_status_of_segments[take_up];
414 
415   take_down = segment + fretwork_segments_x;
416   if (take_down > (signed)(fretwork_segments_x * fretwork_segments_y))
417     val_down = SEG_NONE;
418   else
419     val_down = fretwork_status_of_segments[take_down];
420 
421   if ((segment % fretwork_segments_x) == 1)
422     val_left = SEG_NONE;
423   else
424     val_left = fretwork_status_of_segments[segment - 1];
425 
426   if ((segment % fretwork_segments_x) == 0)
427     val_right = SEG_NONE;
428   else
429     val_right = fretwork_status_of_segments[segment + 1];
430 
431   if (from_left || (val_left & SEG_RIGHT) || from_bottom_left)
432     {
433       LEFT = 1;
434     }
435   if (from_right || (val_right & SEG_LEFT) || from_top_right)
436     RIGHT = 1;
437   if (from_top || (val_up & SEG_BOTTOM) || from_top_left)
438     TOP = 1;
439   if (from_bottom || (val_down & SEG_TOP) || from_bottom_right)
440     BOTTOM = 1;
441 
442 
443   if (TOP && BOTTOM && LEFT && RIGHT)
444     return SEG_LEFT_RIGHT_TOP_BOTTOM;
445   if (LEFT && RIGHT && TOP)
446     return SEG_LEFT_RIGHT_TOP;
447   if (LEFT && RIGHT && BOTTOM)
448     return SEG_LEFT_RIGHT_BOTTOM;
449   if (TOP && BOTTOM && LEFT)
450     return SEG_LEFT_TOP_BOTTOM;
451   if (TOP && BOTTOM && RIGHT)
452     return SEG_RIGHT_TOP_BOTTOM;
453   if (LEFT && RIGHT)
454     return SEG_LEFT_RIGHT;
455   if (TOP && BOTTOM)
456     return SEG_TOP_BOTTOM;
457   if (LEFT && TOP)
458     return SEG_LEFT_TOP;
459   if (LEFT && BOTTOM)
460     return SEG_LEFT_BOTTOM;
461   if (RIGHT && TOP)
462     return SEG_RIGHT_TOP;
463   if (RIGHT && BOTTOM)
464     return SEG_RIGHT_BOTTOM;
465   if (LEFT | RIGHT)
466     return SEG_LEFT_RIGHT;
467   //if (TOP||BOTTOM)
468   return SEG_TOP_BOTTOM;
469 }
470 
471 
fretwork_draw(void * ptr,int which ATTRIBUTE_UNUSED,SDL_Surface * canvas,SDL_Surface * last ATTRIBUTE_UNUSED,int x,int y ATTRIBUTE_UNUSED,unsigned int segment)472 static void fretwork_draw(void *ptr, int which ATTRIBUTE_UNUSED, SDL_Surface * canvas,
473                           SDL_Surface * last ATTRIBUTE_UNUSED, int x, int y ATTRIBUTE_UNUSED, unsigned int segment)
474 {
475   magic_api *api = (magic_api *) ptr;
476   SDL_Surface *result, *temp;
477   Uint8 image;
478   _Bool use_temp;
479 
480   use_temp = 0;
481   if ((segment < 1) | (segment > fretwork_segments_x * fretwork_segments_y))
482     return;
483   fretwork_extract_coords_from_segment(segment, &modification_rect.x, &modification_rect.y);
484   modification_rect.h = img_w;
485   modification_rect.w = img_h;
486 
487   image = fretwork_select_image(segment);       //select the image to display
488 
489   if (fretwork_status_of_segments[segment] == image)
490     return;
491 
492   fretwork_status_of_segments[segment] = image; //and write it to global table
493 
494   result = SDL_CreateRGBSurface(SDL_ANYFORMAT, img_w, img_h, fretwork_one->format->BitsPerPixel,
495                                 fretwork_one->format->Rmask, fretwork_one->format->Gmask, fretwork_one->format->Bmask,
496                                 fretwork_one->format->Amask);
497 
498   temp = SDL_CreateRGBSurface(SDL_ANYFORMAT, img_w, img_h, fretwork_one->format->BitsPerPixel,
499                               fretwork_one->format->Rmask, fretwork_one->format->Gmask, fretwork_one->format->Bmask,
500                               fretwork_one->format->Amask);
501 
502   SDL_BlitSurface(canvas_backup, &modification_rect, result, NULL);
503 
504   switch (image)
505     {
506     case 0:
507     case SEG_TOP_BOTTOM:
508       SDL_BlitSurface(canvas_backup, &modification_rect, result, NULL);
509       SDL_BlitSurface(fretwork_one, NULL, result, NULL);
510       break;
511 
512     case SEG_LEFT_RIGHT:
513       SDL_BlitSurface(canvas_backup, &modification_rect, result, NULL);
514       fretwork_rotate(api, temp, fretwork_one, 1);
515       use_temp = 1;
516       break;
517 
518     case SEG_LEFT_RIGHT_TOP_BOTTOM:
519       SDL_BlitSurface(canvas_backup, &modification_rect, result, NULL);
520       SDL_BlitSurface(fretwork_four, NULL, result, NULL);
521       break;
522 
523     case SEG_LEFT_RIGHT_TOP:
524       SDL_BlitSurface(fretwork_three, NULL, result, NULL);
525       break;
526 
527     case SEG_LEFT_RIGHT_BOTTOM:
528       fretwork_flip_flop(api, temp, fretwork_three);
529       use_temp = 1;
530       break;
531 
532     case SEG_LEFT_TOP_BOTTOM:
533       fretwork_rotate(api, temp, fretwork_three, 0);
534       use_temp = 1;
535       break;
536 
537     case SEG_RIGHT_TOP_BOTTOM:
538       fretwork_rotate(api, temp, fretwork_three, 1);
539       use_temp = 1;
540       break;
541 
542     case SEG_RIGHT_TOP:
543       SDL_BlitSurface(fretwork_corner, NULL, result, NULL);
544       break;
545 
546     case SEG_RIGHT_BOTTOM:
547       fretwork_rotate(api, temp, fretwork_corner, 1);
548       use_temp = 1;
549       break;
550 
551     case SEG_LEFT_TOP:
552       fretwork_rotate(api, temp, fretwork_corner, 0);
553       use_temp = 1;
554       break;
555 
556     case SEG_LEFT_BOTTOM:
557       fretwork_flip_flop(api, temp, fretwork_corner);
558       use_temp = 1;
559       break;
560     }
561 
562   if (use_temp)
563     SDL_BlitSurface(temp, NULL, result, NULL);
564 
565   SDL_FreeSurface(temp);
566   SDL_BlitSurface(result, NULL, canvas, &modification_rect);
567   SDL_FreeSurface(result);
568   api->playsound(fretwork_snd, (x * 255) / canvas->w, 255);
569 }
570 
571 
fretwork_draw_wrapper(void * ptr,int which,SDL_Surface * canvas,SDL_Surface * last,int x,int y)572 static void fretwork_draw_wrapper(void *ptr, int which, SDL_Surface * canvas, SDL_Surface * last, int x, int y)
573 {
574   fretwork_segment_modified = fretwork_get_segment(x, y);
575 
576   fretwork_draw((void *)ptr, which, canvas, last, x, y, fretwork_segment_modified);
577 
578   if (fretwork_segment_modified_last > 0)
579 
580     {
581       fretwork_draw((void *)ptr, which, canvas, last, x, y, fretwork_segment_modified_last);
582       fretwork_extract_coords_from_segment(fretwork_segment_start_rectangle, &modification_rect.x,
583                                            &modification_rect.y);
584       modification_rect.w = fretwork_update_rectangle_width * img_w;
585       modification_rect.h = fretwork_update_rectangle_height * img_h;
586     }
587 
588   if (fretwork_segment_to_add > 0)
589     {
590       fretwork_draw((void *)ptr, which, canvas, last, x, y, fretwork_segment_to_add);
591       fretwork_draw((void *)ptr, which, canvas, last, x, y, fretwork_segment_modified_last);
592       fretwork_segment_to_add = 0;
593     }
594 
595   fretwork_segment_modified_last = fretwork_segment_modified;
596 }
597 
fretwork_drag(magic_api * api,int which,SDL_Surface * canvas,SDL_Surface * snapshot,int ox,int oy,int x,int y,SDL_Rect * update_rect)598 void fretwork_drag(magic_api * api, int which,
599                    SDL_Surface * canvas, SDL_Surface * snapshot, int ox, int oy, int x, int y, SDL_Rect * update_rect)
600 {
601   int start_x, end_x, start_y, end_y, segment_start, segment_end, w, h;
602 
603   if ((x < canvas->w) && (y < canvas->h) && (ox < canvas->w) && (oy < canvas->h) && ((signed)x > 0) && ((signed)y > 0)
604       && ((signed)ox > 0) && ((signed)oy > 0))
605     {
606       api->line((void *)api, which, canvas, snapshot, ox, oy, x, y, img_w / 2, fretwork_draw_wrapper);
607       // This should be improved, maybe passed to fretwork_draw()
608       start_x = min(ox, x);
609       end_x = max(ox, x);
610       start_y = min(oy, y);
611       end_y = max(oy, y);
612       segment_start = fretwork_get_segment(start_x - img_w, start_y - img_h);
613       segment_end = fretwork_get_segment(end_x + img_w, end_y + img_h);
614 
615       x = ((segment_start % fretwork_segments_x) - 1) * img_w;
616       y = (int)(segment_start / fretwork_segments_x) * img_h;
617       w = ((segment_end % fretwork_segments_x) - 1) * img_w - x + img_w;
618       h = (int)(segment_end / fretwork_segments_x) * img_h - y + img_h;
619 
620       update_rect->x = x;
621       update_rect->y = y;
622       update_rect->w = w;
623       update_rect->h = h;
624     }
625 
626 }
627