1 /*
2   Copyright (C) 1997-2021 Sam Lantinga <slouken@libsdl.org>
3 
4   This software is provided 'as-is', without any express or implied
5   warranty.  In no event will the authors be held liable for any damages
6   arising from the use of this software.
7 
8   Permission is granted to anyone to use this software for any purpose,
9   including commercial applications, and to alter it and redistribute it
10   freely.
11 */
12 
13 #include <stdlib.h>
14 #include <stdio.h>
15 
16 #ifdef __EMSCRIPTEN__
17 #include <emscripten/emscripten.h>
18 #endif
19 
20 #include "SDL_test_common.h"
21 
22 /* Stolen from the mailing list */
23 /* Creates a new mouse cursor from an XPM */
24 
25 
26 /* XPM */
27 static const char *arrow[] = {
28   /* width height num_colors chars_per_pixel */
29   "    32    32        3            1",
30   /* colors */
31   "X c #000000",
32   ". c #ffffff",
33   "  c None",
34   /* pixels */
35   "X                               ",
36   "XX                              ",
37   "X.X                             ",
38   "X..X                            ",
39   "X...X                           ",
40   "X....X                          ",
41   "X.....X                         ",
42   "X......X                        ",
43   "X.......X                       ",
44   "X........X                      ",
45   "X.....XXXXX                     ",
46   "X..X..X                         ",
47   "X.X X..X                        ",
48   "XX  X..X                        ",
49   "X    X..X                       ",
50   "     X..X                       ",
51   "      X..X                      ",
52   "      X..X                      ",
53   "       XX                       ",
54   "                                ",
55   "                                ",
56   "                                ",
57   "                                ",
58   "                                ",
59   "                                ",
60   "                                ",
61   "                                ",
62   "                                ",
63   "                                ",
64   "                                ",
65   "                                ",
66   "                                ",
67   "0,0"
68 };
69 
70 static SDL_Cursor*
init_color_cursor(const char * file)71 init_color_cursor(const char *file)
72 {
73     SDL_Cursor *cursor = NULL;
74     SDL_Surface *surface = SDL_LoadBMP(file);
75     if (surface) {
76         if (surface->format->palette) {
77             SDL_SetColorKey(surface, 1, *(Uint8 *) surface->pixels);
78         } else {
79             switch (surface->format->BitsPerPixel) {
80             case 15:
81                 SDL_SetColorKey(surface, 1, (*(Uint16 *)surface->pixels) & 0x00007FFF);
82                 break;
83             case 16:
84                 SDL_SetColorKey(surface, 1, *(Uint16 *)surface->pixels);
85                 break;
86             case 24:
87                 SDL_SetColorKey(surface, 1, (*(Uint32 *)surface->pixels) & 0x00FFFFFF);
88                 break;
89             case 32:
90                 SDL_SetColorKey(surface, 1, *(Uint32 *)surface->pixels);
91                 break;
92             }
93         }
94         cursor = SDL_CreateColorCursor(surface, 0, 0);
95         SDL_FreeSurface(surface);
96     }
97     return cursor;
98 }
99 
100 static SDL_Cursor*
init_system_cursor(const char * image[])101 init_system_cursor(const char *image[])
102 {
103   int i, row, col;
104   Uint8 data[4*32];
105   Uint8 mask[4*32];
106   int hot_x, hot_y;
107 
108   i = -1;
109   for (row=0; row<32; ++row) {
110     for (col=0; col<32; ++col) {
111       if (col % 8) {
112         data[i] <<= 1;
113         mask[i] <<= 1;
114       } else {
115         ++i;
116         data[i] = mask[i] = 0;
117       }
118       switch (image[4+row][col]) {
119         case 'X':
120           data[i] |= 0x01;
121           mask[i] |= 0x01;
122           break;
123         case '.':
124           mask[i] |= 0x01;
125           break;
126         case ' ':
127           break;
128       }
129     }
130   }
131   SDL_sscanf(image[4+row], "%d,%d", &hot_x, &hot_y);
132   return SDL_CreateCursor(data, mask, 32, 32, hot_x, hot_y);
133 }
134 
135 static SDLTest_CommonState *state;
136 int done;
137 static SDL_Cursor *cursors[1+SDL_NUM_SYSTEM_CURSORS];
138 static int current_cursor;
139 static int show_cursor;
140 
141 /* Call this instead of exit(), so we can clean up SDL: atexit() is evil. */
142 static void
quit(int rc)143 quit(int rc)
144 {
145     SDLTest_CommonQuit(state);
146     exit(rc);
147 }
148 
149 void
loop()150 loop()
151 {
152     int i;
153     SDL_Event event;
154     /* Check for events */
155     while (SDL_PollEvent(&event)) {
156         SDLTest_CommonEvent(state, &event, &done);
157         if (event.type == SDL_MOUSEBUTTONDOWN) {
158             if (event.button.button == SDL_BUTTON_LEFT) {
159                 ++current_cursor;
160                 if (current_cursor == SDL_arraysize(cursors)) {
161                     current_cursor = 0;
162                 }
163                 SDL_SetCursor(cursors[current_cursor]);
164             } else {
165                 show_cursor = !show_cursor;
166                 SDL_ShowCursor(show_cursor);
167             }
168         }
169     }
170 
171     for (i = 0; i < state->num_windows; ++i) {
172         SDL_Renderer *renderer = state->renderers[i];
173         SDL_RenderClear(renderer);
174         SDL_RenderPresent(renderer);
175     }
176 #ifdef __EMSCRIPTEN__
177     if (done) {
178         emscripten_cancel_main_loop();
179     }
180 #endif
181 }
182 
183 int
main(int argc,char * argv[])184 main(int argc, char *argv[])
185 {
186     int i;
187     const char *color_cursor = NULL;
188 
189     /* Enable standard application logging */
190     SDL_LogSetPriority(SDL_LOG_CATEGORY_APPLICATION, SDL_LOG_PRIORITY_INFO);
191 
192     /* Initialize test framework */
193     state = SDLTest_CommonCreateState(argv, SDL_INIT_VIDEO);
194     if (!state) {
195         return 1;
196     }
197     for (i = 1; i < argc;) {
198         int consumed;
199 
200         consumed = SDLTest_CommonArg(state, i);
201         if (consumed == 0) {
202             color_cursor = argv[i];
203             break;
204         }
205         if (consumed < 0) {
206             SDLTest_CommonLogUsage(state, argv[0], NULL);
207             quit(1);
208         }
209         i += consumed;
210     }
211 
212     if (!SDLTest_CommonInit(state)) {
213         quit(2);
214     }
215 
216     for (i = 0; i < state->num_windows; ++i) {
217         SDL_Renderer *renderer = state->renderers[i];
218         SDL_SetRenderDrawColor(renderer, 0xA0, 0xA0, 0xA0, 0xFF);
219         SDL_RenderClear(renderer);
220     }
221 
222     if (color_cursor) {
223         cursors[0] = init_color_cursor(color_cursor);
224     } else {
225         cursors[0] = init_system_cursor(arrow);
226     }
227     if (!cursors[0]) {
228         SDL_Log("Error, couldn't create cursor\n");
229         quit(2);
230     }
231     for (i = 0; i < SDL_NUM_SYSTEM_CURSORS; ++i) {
232         cursors[1+i] = SDL_CreateSystemCursor((SDL_SystemCursor)i);
233         if (!cursors[1+i]) {
234             SDL_Log("Error, couldn't create system cursor %d\n", i);
235             quit(2);
236         }
237     }
238     SDL_SetCursor(cursors[0]);
239 
240     /* Main render loop */
241     done = 0;
242 #ifdef __EMSCRIPTEN__
243     emscripten_set_main_loop(loop, 0, 1);
244 #else
245     while (!done) {
246         loop();
247     }
248 #endif
249 
250     for (i = 0; i < SDL_arraysize(cursors); ++i) {
251         SDL_FreeCursor(cursors[i]);
252     }
253     quit(0);
254 
255     /* keep the compiler happy ... */
256     return(0);
257 }
258 
259 /* vi: set ts=4 sw=4 expandtab: */
260