SDL-1.2.14
[sdl_omap.git] / src / video / riscos / SDL_riscostask.c
1 /*
2     SDL - Simple DirectMedia Layer
3     Copyright (C) 1997-2009 Sam Lantinga
4
5     This library is free software; you can redistribute it and/or
6     modify it under the terms of the GNU Library General Public
7     License as published by the Free Software Foundation; either
8     version 2 of the License, or (at your option) any later version.
9
10     This library is distributed in the hope that it will be useful,
11     but WITHOUT ANY WARRANTY; without even the implied warranty of
12     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13     Library General Public License for more details.
14
15     You should have received a copy of the GNU Library General Public
16     License along with this library; if not, write to the Free
17     Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
18
19     Sam Lantinga
20     slouken@libsdl.org
21 */
22 #include "SDL_config.h"
23
24 /*
25     This file added by Alan Buckley (alan_baa@hotmail.com) to support RISC OS 
26         26 March 2003
27
28         File includes routines for:
29           Setting up as a WIMP Task
30           Reading information about the current desktop
31           Storing information before a switch to full screen
32           Restoring desktop after switching to full screen
33 */
34
35 #include "kernel.h"
36 #include "swis.h"
37
38 #include "SDL_stdinc.h"
39 #include "SDL_riscostask.h"
40
41 #if !SDL_THREADS_DISABLED
42 #include <pthread.h>
43 pthread_t main_thread;
44 #endif
45
46 /* RISC OS variables */
47
48 static int task_handle = 0;
49 static int wimp_version = 0;
50
51 /* RISC OS variables to help compatability with certain programs */
52 int riscos_backbuffer = 0; /* Create a back buffer in system memory for full screen mode */
53 int riscos_closeaction = 1; /* Close icon action */
54
55 static int stored_mode = -1; /* -1 when in desktop, mode number or pointer when full screen */
56
57 extern int mouseInWindow; /* Mouse is in WIMP window */
58
59 /* Local function */
60
61 static int RISCOS_GetTaskName(char *task_name, size_t maxlen);
62
63 /* Uncomment next line to copy mode changes/restores to stderr */
64 /* #define DUMP_MODE */
65 #ifdef DUMP_MODE
66 #include "stdio.h"
67 static void dump_mode()
68 {
69     fprintf(stderr, "mode %d\n", stored_mode);
70     if (stored_mode < -1 || stored_mode >= 256)
71     {
72         int blockSize = 0;
73                 int *storeBlock = (int *)stored_mode;
74
75         while(blockSize < 5 || storeBlock[blockSize] != -1)
76         {
77            fprintf(stderr, "   %d\n", storeBlock[blockSize++]);
78         }
79     }
80 }
81 #endif
82
83 /******************************************************************
84
85  Initialise as RISC OS Wimp task
86
87 *******************************************************************/
88
89 int RISCOS_InitTask()
90 {
91    char task_name[32];
92    _kernel_swi_regs regs;
93    int messages[4];
94
95    if (RISCOS_GetTaskName(task_name, SDL_arraysize(task_name)) == 0) return 0;
96
97    messages[0] = 9;       /* Palette changed */
98    messages[1] = 0x400c1; /* Mode changed */
99    messages[2] = 8;       /* Pre quit */
100    messages[2] = 0;
101    
102         regs.r[0] = (unsigned int)360; /* Minimum version 3.6 */
103         regs.r[1] = (unsigned int)0x4b534154;
104         regs.r[2] = (unsigned int)task_name;
105         regs.r[3] = (unsigned int)messages;
106
107    if (_kernel_swi(Wimp_Initialise, &regs, &regs) == 0)
108    {
109            wimp_version = regs.r[0];
110            task_handle = regs.r[1];
111            return 1;
112    }
113
114 #if !SDL_THREADS_DISABLED
115    main_thread = pthread_self();
116 #endif
117
118    return 0;
119 }
120
121 /*********************************************************************
122
123   Close down application on exit.
124
125 **********************************************************************/
126
127 void RISCOS_ExitTask()
128 {
129         _kernel_swi_regs regs;
130
131     if (stored_mode == -1)
132     {
133        /* Ensure cursor is put back to standard pointer shape if
134           we have been running in a window */
135        _kernel_osbyte(106,1,0);
136     }
137
138         /* Ensure we end up back in the wimp */
139         RISCOS_RestoreWimpMode();
140
141         /* Neatly exit the task */
142         regs.r[0] = task_handle;
143         regs.r[1] = (unsigned int)0x4b534154;
144         _kernel_swi(Wimp_CloseDown, &regs, &regs);
145         task_handle = 0;
146 }
147
148 /**************************************************************************
149
150   Get the name of the task for the desktop.
151
152   Param:   task_name - name of task 32 characters.
153
154   Returns: 1 is successful, otherwise 0
155
156   Notes:   Works by getting using OS_GetEnv to get the command line
157                    used to run the program and then parsing a name from it
158                    as follows.
159
160                    1. Use name after final period if not !RunImage
161                    2. If name is !RunImage then process item before the period
162                       in front of !RunImage.
163                    3. If directory name use that
164                    4. if in form <XXX$Dir> use the XXX.
165
166                    Finally once this value has been retrieved use it unless
167                    there is a variable set up in the form SDL$<name>$TaskName
168                    in which case the value of this variable will be used.
169
170                    Now also gets other RISC OS configuration varibles
171                 SDL$<name>$BackBuffer - set to 1 to use a system memory backbuffer in fullscreen mode
172                                                     so updates wait until a call to SDL_UpdateRects. (default 0)
173                                                     This is required for programmes where they have assumed this is
174                                                     always the case which is contrary to the documentation.
175                SDL$<name>$CloseAction
176                     0 Don't show close icon
177                     1 Show close icon
178
179 ***************************************************************************/
180
181 int RISCOS_GetTaskName(char *task_name, size_t maxlen)
182 {
183         _kernel_swi_regs regs;
184
185    task_name[0] = 0;
186
187    /* Figure out a sensible task name */
188    if (_kernel_swi(OS_GetEnv, &regs, &regs) == 0)
189    {
190            char *command_line = (char *)regs.r[0];
191            size_t len = SDL_strlen(command_line)+1;
192            char *buffer = SDL_stack_alloc(char, len);
193            char *env_var;
194            char *p;
195
196            SDL_strlcpy(buffer, command_line, len);
197            p = SDL_strchr(buffer, ' ');
198            if (p) *p = 0;
199            p = SDL_strrchr(buffer, '.');
200            if (p == 0) p = buffer;
201            if (stricmp(p+1,"!RunImage") == 0)
202            {
203                    *p = 0;
204                    p = SDL_strrchr(buffer, '.');
205                    if (p == 0) p = buffer;
206            }
207            if (*p == '.') p++;
208            if (*p == '!') p++; /* Skip "!" at beginning of application directories */
209
210        if (*p == '<')
211        {
212           // Probably in the form <appname$Dir>
213           char *q = SDL_strchr(p, '$');
214           if (q == 0) q = SDL_strchr(p,'>'); /* Use variable name if not */
215           if (q) *q = 0;
216           p++; /* Move over the < */
217        }
218
219            if (*p)
220            {
221                    /* Read variables that effect the RISC OS SDL engine for this task */
222                    len = SDL_strlen(p) + 18; /* 18 is larger than the biggest variable name */
223                    env_var = SDL_stack_alloc(char, len);
224                    if (env_var)
225                    {
226                            char *env_val;
227
228                            /* See if a variable of form SDL$<dirname>$TaskName exists */
229
230                            SDL_strlcpy(env_var, "SDL$", len);
231                            SDL_strlcat(env_var, p, len);
232                            SDL_strlcat(env_var, "$TaskName", len);
233
234                            env_val = SDL_getenv(env_var);
235                            if (env_val) SDL_strlcpy(task_name, env_val, maxlen);
236
237                            SDL_strlcpy(env_var, "SDL$", len);
238                            SDL_strlcat(env_var, p, len);
239                            SDL_strlcat(env_var, "$BackBuffer", len);
240
241                            env_val = SDL_getenv(env_var);
242                            if (env_val) riscos_backbuffer = atoi(env_val);
243
244                            SDL_strlcpy(env_var, "SDL$", len);
245                            SDL_strlcat(env_var, p, len);
246                            SDL_strlcat(env_var, "$CloseAction", len);
247
248                            env_val = SDL_getenv(env_var);
249                            if (env_val && SDL_strcmp(env_val,"0") == 0) riscos_closeaction = 0;
250
251                            SDL_stack_free(env_var);
252                    }
253                    
254                    if (!*task_name) SDL_strlcpy(task_name, p, maxlen);
255            }
256
257            SDL_stack_free(buffer);
258    }
259
260    if (task_name[0] == 0) SDL_strlcpy(task_name, "SDL Task", maxlen);
261
262    return 1;
263 }
264
265 /*****************************************************************
266
267   Store the current desktop screen mode if we are in the desktop.
268
269 ******************************************************************/
270
271 void RISCOS_StoreWimpMode()
272 {
273      _kernel_swi_regs regs;
274
275         /* Don't store if in full screen mode */
276         if (stored_mode != -1) return;
277
278     regs.r[0] = 1;
279     _kernel_swi(OS_ScreenMode, &regs, &regs);
280     if (regs.r[1] >= 0 && regs.r[1] < 256) stored_mode = regs.r[1];
281     else
282     {
283         int blockSize = 0;
284         int *retBlock = (int *)regs.r[1];
285                 int *storeBlock;
286         int j;
287
288         while(blockSize < 5 || retBlock[blockSize] != -1) blockSize++;
289         blockSize++;
290         storeBlock = (int *)SDL_malloc(blockSize * sizeof(int));
291         retBlock = (int *)regs.r[1];
292         for ( j = 0; j < blockSize; j++)
293            storeBlock[j] = retBlock[j];
294
295                 stored_mode = (int)storeBlock;
296      }
297 #if DUMP_MODE
298     fprintf(stderr, "Stored "); dump_mode();
299 #endif
300 }
301
302 /*****************************************************************
303
304   Restore desktop screen mode if we are in full screen mode.
305
306 *****************************************************************/
307
308 void RISCOS_RestoreWimpMode()
309 {
310     _kernel_swi_regs regs;
311
312         /* Only need to restore if we are in full screen mode */
313         if (stored_mode == -1) return;
314
315 #if DUMP_MODE
316    fprintf(stderr, "Restored"); dump_mode();
317 #endif
318
319     regs.r[0] = stored_mode;
320     _kernel_swi(Wimp_SetMode, &regs, &regs);
321     if (stored_mode < 0 || stored_mode > 256)
322     {
323        SDL_free((int *)stored_mode);
324     }
325     stored_mode = -1;
326
327     /* Flush keyboard buffer to dump the keystrokes we've already polled */
328     regs.r[0] = 21;
329     regs.r[1] = 0; /* Keyboard buffer number */
330     _kernel_swi(OS_Byte, &regs, &regs);
331
332     mouseInWindow = 0;
333
334 }
335
336 /*********************************************************************
337
338   Get version of Wimp running when task was initialised.
339
340 *********************************************************************/
341
342 int RISCOS_GetWimpVersion()
343 {
344         return wimp_version;
345 }
346
347 int RISCOS_GetTaskHandle()
348 {
349         return task_handle;
350 }