]> git.xonotic.org Git - xonotic/darkplaces.git/blob - sys_sdl.c
deduplicate main()
[xonotic/darkplaces.git] / sys_sdl.c
1 #ifdef WIN32
2 #include <io.h> // Include this BEFORE darkplaces.h because it uses strncpy which trips DP_STATIC_ASSERT
3 #include "conio.h"
4 #else
5 #include <unistd.h>
6 #include <fcntl.h>
7 #include <sys/time.h>
8 #endif
9
10 #ifdef __ANDROID__
11 #include <android/log.h>
12 #endif
13
14 /*
15  * Include this BEFORE darkplaces.h because it breaks wrapping
16  * _Static_assert. Cloudwalk has no idea how or why so don't ask.
17  */
18 #include <SDL.h>
19
20 #include "darkplaces.h"
21
22 #ifdef WIN32
23 #ifdef _MSC_VER
24 #pragma comment(lib, "sdl2.lib")
25 #pragma comment(lib, "sdl2main.lib")
26 #endif
27 #endif
28
29 sys_t sys;
30
31 // =======================================================================
32 // General routines
33 // =======================================================================
34
35 void Sys_Shutdown (void)
36 {
37 #ifdef __ANDROID__
38         Sys_AllowProfiling(false);
39 #endif
40 #ifndef WIN32
41         fcntl (0, F_SETFL, fcntl (0, F_GETFL, 0) & ~O_NONBLOCK);
42 #endif
43         fflush(stdout);
44         SDL_Quit();
45 }
46
47 // Sys_Error early in startup might screw with automated
48 // workflows or something if we show the dialog by default.
49 static qbool nocrashdialog = true;
50 void Sys_Error (const char *error, ...)
51 {
52         va_list argptr;
53         char string[MAX_INPUTLINE];
54
55 // change stdin to non blocking
56 #ifndef WIN32
57         fcntl (0, F_SETFL, fcntl (0, F_GETFL, 0) & ~O_NONBLOCK);
58 #endif
59
60         va_start (argptr,error);
61         dpvsnprintf (string, sizeof (string), error, argptr);
62         va_end (argptr);
63
64         Con_Printf(CON_ERROR "Engine Error: %s\n", string);
65         
66         // don't want a dead window left blocking the OS UI or the crash dialog
67         Host_Shutdown();
68
69         if(!nocrashdialog)
70                 SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR, "Engine Error", string, NULL);
71
72         exit (1);
73 }
74
75 void Sys_Print(const char *text)
76 {
77 #ifdef __ANDROID__
78         if (developer.integer > 0)
79         {
80                 __android_log_write(ANDROID_LOG_DEBUG, sys.argv[0], text);
81         }
82 #else
83         if(sys.outfd < 0)
84                 return;
85 #ifndef WIN32
86         // BUG: for some reason, NDELAY also affects stdout (1) when used on stdin (0).
87         // this is because both go to /dev/tty by default!
88         {
89                 int origflags = fcntl (sys.outfd, F_GETFL, 0);
90                 fcntl (sys.outfd, F_SETFL, origflags & ~O_NONBLOCK);
91 #endif
92 #ifdef WIN32
93 #define write _write
94 #endif
95                 while(*text)
96                 {
97                         fs_offset_t written = (fs_offset_t)write(sys.outfd, text, (int)strlen(text));
98                         if(written <= 0)
99                                 break; // sorry, I cannot do anything about this error - without an output
100                         text += written;
101                 }
102 #ifndef WIN32
103                 fcntl (sys.outfd, F_SETFL, origflags);
104         }
105 #endif
106         //fprintf(stdout, "%s", text);
107 #endif
108 }
109
110 char *Sys_ConsoleInput(void)
111 {
112         static char text[MAX_INPUTLINE];
113         int len = 0;
114 #ifdef WIN32
115         int c;
116
117         // read a line out
118         while (_kbhit ())
119         {
120                 c = _getch ();
121                 _putch (c);
122                 if (c == '\r')
123                 {
124                         text[len] = 0;
125                         _putch ('\n');
126                         len = 0;
127                         return text;
128                 }
129                 if (c == 8)
130                 {
131                         if (len)
132                         {
133                                 _putch (' ');
134                                 _putch (c);
135                                 len--;
136                                 text[len] = 0;
137                         }
138                         continue;
139                 }
140                 text[len] = c;
141                 len++;
142                 text[len] = 0;
143                 if (len == sizeof (text))
144                         len = 0;
145         }
146 #else
147         fd_set fdset;
148         struct timeval timeout;
149         FD_ZERO(&fdset);
150         FD_SET(0, &fdset); // stdin
151         timeout.tv_sec = 0;
152         timeout.tv_usec = 0;
153         if (select (1, &fdset, NULL, NULL, &timeout) != -1 && FD_ISSET(0, &fdset))
154         {
155                 len = read (0, text, sizeof(text));
156                 if (len >= 1)
157                 {
158                         // rip off the \n and terminate
159                         text[len-1] = 0;
160                         return text;
161                 }
162         }
163 #endif
164         return NULL;
165 }
166
167 char *Sys_GetClipboardData (void)
168 {
169         char *data = NULL;
170         char *cliptext;
171
172         cliptext = SDL_GetClipboardText();
173         if (cliptext != NULL) {
174                 size_t allocsize;
175                 allocsize = min(MAX_INPUTLINE, strlen(cliptext) + 1);
176                 data = (char *)Z_Malloc (allocsize);
177                 strlcpy (data, cliptext, allocsize);
178                 SDL_free(cliptext);
179         }
180
181         return data;
182 }
183
184 void Sys_SDL_Init(void)
185 {
186         // we don't know which systems we'll want to init, yet...
187         if (SDL_Init(0) < 0)
188                 Sys_Error("SDL_Init failed: %s\n", SDL_GetError());
189
190         // COMMANDLINEOPTION: sdl: -nocrashdialog disables "Engine Error" crash dialog boxes
191         if(!Sys_CheckParm("-nocrashdialog"))
192                 nocrashdialog = false;
193 }
194
195 qbool sys_supportsdlgetticks = true;
196 unsigned int Sys_SDL_GetTicks (void)
197 {
198         return SDL_GetTicks();
199 }
200 void Sys_SDL_Delay (unsigned int milliseconds)
201 {
202         SDL_Delay(milliseconds);
203 }