Add an in_releaseall command for debugging/working around stuck keys.
[xonotic/darkplaces.git] / sys_sdl.c
1
2 #ifdef WIN32
3 #include <io.h>
4 #include "conio.h"
5 #else
6 #include <unistd.h>
7 #include <fcntl.h>
8 #include <sys/time.h>
9 #endif
10
11 #ifdef __ANDROID__
12 #include <android/log.h>
13
14 #ifndef FNDELAY
15 #define FNDELAY         O_NDELAY
16 #endif
17 #endif
18
19 #include <signal.h>
20
21 #include <SDL.h>
22
23 #ifdef WIN32
24 #ifdef _MSC_VER
25 #if SDL_MAJOR_VERSION == 1
26 #pragma comment(lib, "sdl.lib")
27 #pragma comment(lib, "sdlmain.lib")
28 #else
29 #pragma comment(lib, "sdl2.lib")
30 #pragma comment(lib, "sdl2main.lib")
31 #endif
32 #endif
33 #endif
34
35 #include "quakedef.h"
36
37 // =======================================================================
38 // General routines
39 // =======================================================================
40
41 void Sys_Shutdown (void)
42 {
43 #ifdef __ANDROID__
44         Sys_AllowProfiling(false);
45 #endif
46 #ifndef WIN32
47         fcntl (0, F_SETFL, fcntl (0, F_GETFL, 0) & ~FNDELAY);
48 #endif
49         fflush(stdout);
50         SDL_Quit();
51 }
52
53
54 void Sys_Error (const char *error, ...)
55 {
56         va_list argptr;
57         char string[MAX_INPUTLINE];
58
59 // change stdin to non blocking
60 #ifndef WIN32
61         fcntl (0, F_SETFL, fcntl (0, F_GETFL, 0) & ~FNDELAY);
62 #endif
63
64         va_start (argptr,error);
65         dpvsnprintf (string, sizeof (string), error, argptr);
66         va_end (argptr);
67
68         Con_Printf ("Quake Error: %s\n", string);
69
70 #ifdef WIN32
71         MessageBox(NULL, string, "Quake Error", MB_OK | MB_SETFOREGROUND | MB_ICONSTOP);
72 #endif
73
74         Host_Shutdown ();
75         exit (1);
76 }
77
78 static int outfd = 1;
79 void Sys_PrintToTerminal(const char *text)
80 {
81 #ifdef __ANDROID__
82         if (developer.integer > 0)
83         {
84                 __android_log_write(ANDROID_LOG_DEBUG, com_argv[0], text);
85         }
86 #else
87         if(outfd < 0)
88                 return;
89 #ifdef FNDELAY
90         // BUG: for some reason, NDELAY also affects stdout (1) when used on stdin (0).
91         // this is because both go to /dev/tty by default!
92         {
93                 int origflags = fcntl (outfd, F_GETFL, 0);
94                 fcntl (outfd, F_SETFL, origflags & ~FNDELAY);
95 #endif
96 #ifdef WIN32
97 #define write _write
98 #endif
99                 while(*text)
100                 {
101                         fs_offset_t written = (fs_offset_t)write(outfd, text, (int)strlen(text));
102                         if(written <= 0)
103                                 break; // sorry, I cannot do anything about this error - without an output
104                         text += written;
105                 }
106 #ifdef FNDELAY
107                 fcntl (outfd, F_SETFL, origflags);
108         }
109 #endif
110         //fprintf(stdout, "%s", text);
111 #endif
112 }
113
114 char *Sys_ConsoleInput(void)
115 {
116 //      if (cls.state == ca_dedicated)
117         {
118                 static char text[MAX_INPUTLINE];
119                 int len = 0;
120 #ifdef WIN32
121                 int c;
122
123                 // read a line out
124                 while (_kbhit ())
125                 {
126                         c = _getch ();
127                         _putch (c);
128                         if (c == '\r')
129                         {
130                                 text[len] = 0;
131                                 _putch ('\n');
132                                 len = 0;
133                                 return text;
134                         }
135                         if (c == 8)
136                         {
137                                 if (len)
138                                 {
139                                         _putch (' ');
140                                         _putch (c);
141                                         len--;
142                                         text[len] = 0;
143                                 }
144                                 continue;
145                         }
146                         text[len] = c;
147                         len++;
148                         text[len] = 0;
149                         if (len == sizeof (text))
150                                 len = 0;
151                 }
152 #else
153                 fd_set fdset;
154                 struct timeval timeout;
155                 FD_ZERO(&fdset);
156                 FD_SET(0, &fdset); // stdin
157                 timeout.tv_sec = 0;
158                 timeout.tv_usec = 0;
159                 if (select (1, &fdset, NULL, NULL, &timeout) != -1 && FD_ISSET(0, &fdset))
160                 {
161                         len = read (0, text, sizeof(text));
162                         if (len >= 1)
163                         {
164                                 // rip off the \n and terminate
165                                 text[len-1] = 0;
166                                 return text;
167                         }
168                 }
169 #endif
170         }
171         return NULL;
172 }
173
174 char *Sys_GetClipboardData (void)
175 {
176 #if SDL_MAJOR_VERSION != 1
177         char *data = NULL;
178         char *cliptext;
179
180         cliptext = SDL_GetClipboardText();
181         if (cliptext != NULL) {
182                 size_t allocsize;
183                 allocsize = strlen(cliptext) + 1;
184                 data = (char *)Z_Malloc (allocsize);
185                 strlcpy (data, cliptext, allocsize);
186                 SDL_free(cliptext);
187         }
188
189         return data;
190 #elif defined(WIN32)
191         char *data = NULL;
192         char *cliptext;
193
194         if (OpenClipboard (NULL) != 0)
195         {
196                 HANDLE hClipboardData;
197
198                 if ((hClipboardData = GetClipboardData (CF_TEXT)) != 0)
199                 {
200                         if ((cliptext = (char *)GlobalLock (hClipboardData)) != 0)
201                         {
202                                 size_t allocsize;
203                                 allocsize = GlobalSize (hClipboardData) + 1;
204                                 data = (char *)Z_Malloc (allocsize);
205                                 strlcpy (data, cliptext, allocsize);
206                                 GlobalUnlock (hClipboardData);
207                         }
208                 }
209                 CloseClipboard ();
210         }
211         return data;
212 #else
213         return NULL;
214 #endif
215 }
216
217 void Sys_InitConsole (void)
218 {
219 }
220
221 int main (int argc, char *argv[])
222 {
223         signal(SIGFPE, SIG_IGN);
224
225 #ifdef __ANDROID__
226         Sys_AllowProfiling(true);
227 #endif
228
229         com_argc = argc;
230         com_argv = (const char **)argv;
231         Sys_ProvideSelfFD();
232
233         // COMMANDLINEOPTION: sdl: -noterminal disables console output on stdout
234         if(COM_CheckParm("-noterminal"))
235                 outfd = -1;
236         // COMMANDLINEOPTION: sdl: -stderr moves console output to stderr
237         else if(COM_CheckParm("-stderr"))
238                 outfd = 2;
239         else
240                 outfd = 1;
241
242 #ifndef WIN32
243         fcntl(0, F_SETFL, fcntl (0, F_GETFL, 0) | FNDELAY);
244 #endif
245
246         // we don't know which systems we'll want to init, yet...
247         SDL_Init(0);
248
249         Host_Main();
250
251         return 0;
252 }
253
254 qboolean sys_supportsdlgetticks = true;
255 unsigned int Sys_SDL_GetTicks (void)
256 {
257         return SDL_GetTicks();
258 }
259 void Sys_SDL_Delay (unsigned int milliseconds)
260 {
261         SDL_Delay(milliseconds);
262 }