array: avoid crash on unset variable
[jimtcl.git] / jim-sdl.c
blob27e49c4c92c8d826724b1d6532d3dfafb112177d
1 /*
2 * Jim - SDL extension
4 * Copyright 2005 Salvatore Sanfilippo <antirez@invece.org>
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above
13 * copyright notice, this list of conditions and the following
14 * disclaimer in the documentation and/or other materials
15 * provided with the distribution.
17 * THIS SOFTWARE IS PROVIDED BY THE JIM TCL PROJECT ``AS IS'' AND ANY
18 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
19 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
20 * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
21 * JIM TCL PROJECT OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
22 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
23 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
24 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
26 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
27 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
28 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 * The views and conclusions contained in the software and documentation
31 * are those of the authors and should not be interpreted as representing
32 * official policies, either expressed or implied, of the Jim Tcl Project.
35 #include <stdio.h>
36 #include <stdlib.h>
37 #include <string.h>
38 #include <errno.h>
39 #include <SDL/SDL.h>
40 #include <SDL/SDL_gfxPrimitives.h>
42 #include <jim.h>
44 #define AIO_CMD_LEN 128
46 typedef struct JimSdlSurface
48 SDL_Surface *screen;
49 } JimSdlSurface;
51 static void JimSdlSetError(Jim_Interp *interp)
53 Jim_SetResultString(interp, SDL_GetError(), -1);
56 static void JimSdlDelProc(Jim_Interp *interp, void *privData)
58 JimSdlSurface *jss = privData;
60 JIM_NOTUSED(interp);
62 SDL_FreeSurface(jss->screen);
63 Jim_Free(jss);
66 /* Calls to commands created via [sdl.surface] are implemented by this
67 * C command. */
68 static int JimSdlHandlerCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
70 JimSdlSurface *jss = Jim_CmdPrivData(interp);
71 int option;
72 static const char * const options[] = {
73 "free", "flip", "pixel", "rectangle", "box", "line", "aaline",
74 "circle", "aacircle", "fcircle", NULL
76 enum
77 { OPT_FREE, OPT_FLIP, OPT_PIXEL, OPT_RECTANGLE, OPT_BOX, OPT_LINE,
78 OPT_AALINE, OPT_CIRCLE, OPT_AACIRCLE, OPT_FCIRCLE
81 if (argc < 2) {
82 Jim_WrongNumArgs(interp, 1, argv, "method ?args ...?");
83 return JIM_ERR;
85 if (Jim_GetEnum(interp, argv[1], options, &option, "SDL surface method", JIM_ERRMSG) != JIM_OK)
86 return JIM_ERR;
87 if (option == OPT_PIXEL) {
88 /* PIXEL */
89 long x, y, red, green, blue, alpha = 255;
91 if (argc != 7 && argc != 8) {
92 Jim_WrongNumArgs(interp, 2, argv, "x y red green blue ?alpha?");
93 return JIM_ERR;
95 if (Jim_GetLong(interp, argv[2], &x) != JIM_OK ||
96 Jim_GetLong(interp, argv[3], &y) != JIM_OK ||
97 Jim_GetLong(interp, argv[4], &red) != JIM_OK ||
98 Jim_GetLong(interp, argv[5], &green) != JIM_OK ||
99 Jim_GetLong(interp, argv[6], &blue) != JIM_OK) {
100 return JIM_ERR;
102 if (argc == 8 && Jim_GetLong(interp, argv[7], &alpha) != JIM_OK)
103 return JIM_ERR;
104 pixelRGBA(jss->screen, x, y, red, green, blue, alpha);
105 return JIM_OK;
107 else if (option == OPT_RECTANGLE || option == OPT_BOX ||
108 option == OPT_LINE || option == OPT_AALINE) {
109 /* RECTANGLE, BOX, LINE, AALINE */
110 long x1, y1, x2, y2, red, green, blue, alpha = 255;
112 if (argc != 9 && argc != 10) {
113 Jim_WrongNumArgs(interp, 2, argv, "x y red green blue ?alpha?");
114 return JIM_ERR;
116 if (Jim_GetLong(interp, argv[2], &x1) != JIM_OK ||
117 Jim_GetLong(interp, argv[3], &y1) != JIM_OK ||
118 Jim_GetLong(interp, argv[4], &x2) != JIM_OK ||
119 Jim_GetLong(interp, argv[5], &y2) != JIM_OK ||
120 Jim_GetLong(interp, argv[6], &red) != JIM_OK ||
121 Jim_GetLong(interp, argv[7], &green) != JIM_OK ||
122 Jim_GetLong(interp, argv[8], &blue) != JIM_OK) {
123 return JIM_ERR;
125 if (argc == 10 && Jim_GetLong(interp, argv[9], &alpha) != JIM_OK)
126 return JIM_ERR;
127 switch (option) {
128 case OPT_RECTANGLE:
129 rectangleRGBA(jss->screen, x1, y1, x2, y2, red, green, blue, alpha);
130 break;
131 case OPT_BOX:
132 boxRGBA(jss->screen, x1, y1, x2, y2, red, green, blue, alpha);
133 break;
134 case OPT_LINE:
135 lineRGBA(jss->screen, x1, y1, x2, y2, red, green, blue, alpha);
136 break;
137 case OPT_AALINE:
138 aalineRGBA(jss->screen, x1, y1, x2, y2, red, green, blue, alpha);
139 break;
141 return JIM_OK;
143 else if (option == OPT_CIRCLE || option == OPT_AACIRCLE || option == OPT_FCIRCLE) {
144 /* CIRCLE, AACIRCLE, FCIRCLE */
145 long x, y, radius, red, green, blue, alpha = 255;
147 if (argc != 8 && argc != 9) {
148 Jim_WrongNumArgs(interp, 2, argv, "x y radius red green blue ?alpha?");
149 return JIM_ERR;
151 if (Jim_GetLong(interp, argv[2], &x) != JIM_OK ||
152 Jim_GetLong(interp, argv[3], &y) != JIM_OK ||
153 Jim_GetLong(interp, argv[4], &radius) != JIM_OK ||
154 Jim_GetLong(interp, argv[5], &red) != JIM_OK ||
155 Jim_GetLong(interp, argv[6], &green) != JIM_OK ||
156 Jim_GetLong(interp, argv[7], &blue) != JIM_OK) {
157 return JIM_ERR;
159 if (argc == 9 && Jim_GetLong(interp, argv[8], &alpha) != JIM_OK)
160 return JIM_ERR;
161 switch (option) {
162 case OPT_CIRCLE:
163 circleRGBA(jss->screen, x, y, radius, red, green, blue, alpha);
164 break;
165 case OPT_AACIRCLE:
166 aacircleRGBA(jss->screen, x, y, radius, red, green, blue, alpha);
167 break;
168 case OPT_FCIRCLE:
169 filledCircleRGBA(jss->screen, x, y, radius, red, green, blue, alpha);
170 break;
172 return JIM_OK;
174 else if (option == OPT_FREE) {
175 /* FREE */
176 if (argc != 2) {
177 Jim_WrongNumArgs(interp, 2, argv, "");
178 return JIM_ERR;
180 Jim_DeleteCommand(interp, Jim_String(argv[0]));
181 return JIM_OK;
183 else if (option == OPT_FLIP) {
184 /* FLIP */
185 if (argc != 2) {
186 Jim_WrongNumArgs(interp, 2, argv, "");
187 return JIM_ERR;
189 SDL_Flip(jss->screen);
190 return JIM_OK;
192 return JIM_OK;
195 static int JimSdlSurfaceCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
197 JimSdlSurface *jss;
198 char buf[AIO_CMD_LEN];
199 Jim_Obj *objPtr;
200 long screenId, xres, yres;
201 SDL_Surface *screen;
203 if (argc != 3) {
204 Jim_WrongNumArgs(interp, 1, argv, "xres yres");
205 return JIM_ERR;
207 if (Jim_GetLong(interp, argv[1], &xres) != JIM_OK ||
208 Jim_GetLong(interp, argv[2], &yres) != JIM_OK)
209 return JIM_ERR;
211 /* Try to create the surface */
212 screen = SDL_SetVideoMode(xres, yres, 32, SDL_SWSURFACE | SDL_ANYFORMAT);
213 if (screen == NULL) {
214 JimSdlSetError(interp);
215 return JIM_ERR;
217 /* Get the next file id */
218 if (Jim_EvalGlobal(interp, "if {[catch {incr sdl.surfaceId}]} {set sdl.surfaceId 0}") != JIM_OK)
219 return JIM_ERR;
220 objPtr = Jim_GetVariableStr(interp, "sdl.surfaceId", JIM_ERRMSG);
221 if (objPtr == NULL)
222 return JIM_ERR;
223 if (Jim_GetLong(interp, objPtr, &screenId) != JIM_OK)
224 return JIM_ERR;
226 /* Create the SDL screen command */
227 jss = Jim_Alloc(sizeof(*jss));
228 jss->screen = screen;
229 sprintf(buf, "sdl.surface%ld", screenId);
230 Jim_CreateCommand(interp, buf, JimSdlHandlerCommand, jss, JimSdlDelProc);
231 Jim_SetResult(interp, Jim_MakeGlobalNamespaceName(interp, Jim_NewStringObj(interp, buf, -1)));
232 return JIM_OK;
235 int Jim_sdlInit(Jim_Interp *interp)
237 if (Jim_PackageProvide(interp, "sdl", "1.0", JIM_ERRMSG))
238 return JIM_ERR;
240 if (SDL_Init(SDL_INIT_VIDEO) < 0) {
241 JimSdlSetError(interp);
242 return JIM_ERR;
244 atexit(SDL_Quit);
245 Jim_CreateCommand(interp, "sdl.screen", JimSdlSurfaceCommand, NULL, NULL);
246 return JIM_OK;