menu: added new Keywords tag to .desktop files
[barry.git] / wince / wrappers / wrappers.cc
blob35c0ce865444691e3733e26fe856cb22d014760c
1 ///
2 /// \file wrappers.cc
3 /// Wrapper function implementations to aid porting to WinCE
4 ///
6 /*
7 Copyright (C) 2012, RealVNC Ltd.
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 2 of the License, or
12 (at your option) any later version.
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
18 See the GNU General Public License in the COPYING file at the
19 root directory of this project for more details.
22 #include <string.h>
23 #include <unistd.h>
24 #include <sys/time.h>
25 #include <windows.h>
26 #include <locale.h>
27 #include <signal.h>
28 #include <winioctl.h>
29 // Needs to be last as it re-defines any missing errno
30 #include <errno.h>
32 #define MAX_ERR_LEN 128
33 static char errorString[MAX_ERR_LEN];
34 #ifdef WINCE
35 // Various WinCE time functions must be manually implemented, including
36 // the non-reentrant implementations. These variables are for those.
37 static tm gLocalTime;
39 #define MAX_CTIME_LEN 128
40 static char ctimeBuf[MAX_CTIME_LEN];
42 #endif
44 char *strerror(int errnum) {
45 sprintf(errorString, "error number %d", errnum);
46 return errorString;
49 unsigned int sleep(unsigned int seconds) {
50 Sleep(seconds * 1000);
51 return 0;
54 int usleep(useconds_t usec) {
55 Sleep(usec / 1000);
56 return 0;
59 // From http://support.microsoft.com/kb/167296
60 static void UnixTimeToFileTime(time_t t, LPFILETIME pft) {
61 LONGLONG ll;
62 ll = Int32x32To64(t, 10000000) + 116444736000000000;
63 pft->dwLowDateTime = static_cast<DWORD>(ll);
64 pft->dwHighDateTime = static_cast<DWORD>(ll >> 32);
67 static void FileTimeToUnixTime(const LPFILETIME pft, time_t *t) {
68 LONGLONG ll;
69 ll = (static_cast<LONGLONG>(pft->dwHighDateTime) << 32) |
70 static_cast<LONGLONG>(pft->dwLowDateTime);
71 // Adjust the offset to 100ns periods from UNIX epoc
72 ll -= 116444736000000000;
73 // Adjust it to seconds
74 ll /= 10000000;
75 *t = static_cast<time_t>(ll);
78 static BOOL isLeapYear(DWORD year) {
79 if( (year % 400) == 0 )
80 return TRUE;
81 if( (year % 100) == 0 )
82 return FALSE;
83 if( (year % 4) == 0 )
84 return TRUE;
85 return FALSE;
88 /* Static lookup table for how many days in the year each month starts on.
89 * Jan = 0, Feb = 1. */
90 static int monthLookup [] = {
92 31,
93 31 + 28,
94 31 + 28 + 31,
95 31 + 28 + 31 + 30,
96 31 + 28 + 31 + 30 + 31,
97 31 + 28 + 31 + 30 + 31 + 30,
98 31 + 28 + 31 + 30 + 31 + 30 + 31,
99 31 + 28 + 31 + 30 + 31 + 30 + 31 + 31,
100 31 + 28 + 31 + 30 + 31 + 30 + 31 + 31 + 30,
101 31 + 28 + 31 + 30 + 31 + 30 + 31 + 31 + 30 + 31,
102 31 + 28 + 31 + 30 + 31 + 30 + 31 + 31 + 30 + 31 + 30,
105 struct tm *localtime_r(const time_t *timep, struct tm *result) {
106 FILETIME ft;
107 SYSTEMTIME st;
108 UnixTimeToFileTime(*timep, &ft);
109 FileTimeToSystemTime(&ft, &st);
111 result->tm_sec = st.wSecond;
112 result->tm_min = st.wMinute;
113 result->tm_hour = st.wHour;
114 result->tm_mday = st.wDay;
115 result->tm_mon = st.wMonth - 1;
116 result->tm_year = st.wYear - 1900;
117 result->tm_wday = st.wDayOfWeek;
118 result->tm_yday = monthLookup[st.wMonth - 1] +
119 ((isLeapYear(st.wYear) && st.wMonth > 2)? 1 : 0) +
120 st.wDay;
121 result->tm_isdst = false;
123 return result;
126 char *optarg;
127 int optind = 1;
128 int opterr = 1;
129 int optopt = -1;
131 int getopt(int argc, char * const argv[],
132 const char *optstring)
134 if( optind >= argc ||
135 argv[optind][0] == '-' && argv[optind][1] == '-' ) {
136 /* end processing */
137 return -1;
138 } else if( argv[optind][0] == '-' ) {
139 /* Found an option */
140 const char optchar = argv[optind][1];
141 /* Look for it in optstring */
142 while ( *optstring != '\0' ) {
143 if( *optstring == optchar )
144 break;
145 ++optstring;
146 if( *optstring == ':' )
147 ++optstring;
149 if( *optstring == '\0' ) {
150 if( opterr != 0 )
151 fprintf(stderr, "Unknown option '%c'\n", optchar);
152 optopt = optchar;
153 return '?';
155 /* See if it has a parameter */
156 if( optstring[1] == ':' ) {
157 if( optind + 1 >= argc ) {
158 if( opterr != 0 )
159 fprintf(stderr, "No additional parameter for option '%c'\n", optchar);
160 optopt = optchar;
161 return '?';
163 ++optind;
164 optarg = argv[optind];
166 ++optind;
167 return optchar;
168 } else {
169 /* Found a non-option argument, should really move it to the end for complete
170 * compatibility. */
171 /* TODO: move it to the end rather than just giving up */
172 return -1;
177 #define MAX_LOCALE_LEN 128
178 static TCHAR localeStrW[MAX_LOCALE_LEN];
179 static char localeStr[MAX_LOCALE_LEN];
181 char *setlocale(int category, const char *locale)
183 // Non-functional on WinCE
184 return NULL;
187 sighandler_t signal(int signum, sighandler_t handler)
189 if( signum == SIGINT ) {
190 DWORD bytesReturned = 0;
191 if( !DeviceIoControl(
192 _fileno(stdout),
193 /* This is the value of IOCTL_CONSOLE_SETCONTROLCHANDLER */
194 CTL_CODE(FILE_DEVICE_CONSOLE, 8, METHOD_BUFFERED, FILE_ANY_ACCESS),
195 (LPVOID)handler, sizeof(handler),
196 NULL, 0, &bytesReturned, NULL) )
197 return SIG_ERR;
198 else
199 return NULL;
201 // All other signal handling is non-functional on WinCE
202 return SIG_ERR;
205 #ifdef WINCE
206 /* WinCE doesn't provide a getenv */
207 char *getenv(const char *name)
209 // Pretend there are no environment variables
210 return NULL;
212 #endif
214 #ifdef WINCE
215 // WinCE declares various time methods but doesn't provide them
216 // (see http://blogs.msdn.com/b/cenet/archive/2006/04/29/time-h-on-windows-ce.aspx).
217 struct tm *localtime(const time_t *timep) {
218 return localtime_r(timep, &gLocalTime);
221 time_t time(time_t *t) {
222 time_t ret = 0;
224 SYSTEMTIME st;
225 FILETIME ft;
226 GetLocalTime(&st);
227 SystemTimeToFileTime(&st, &ft);
228 FileTimeToUnixTime(&ft, &ret);
230 if (t != NULL)
231 *t = ret;
232 return ret;
235 // This isn't locale friendly, assuming English weeknames and month names,
236 // but it seems to be what the standard says.
237 const static char weekdayStrLookup[7][4] = {
238 "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"
240 const static char monthStrLookup[12][4] = {
241 "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
244 char *ctime(const time_t *timep) {
245 FILETIME ft;
246 SYSTEMTIME st;
247 UnixTimeToFileTime(*timep, &ft);
248 FileTimeToSystemTime(&ft, &st);
249 _snprintf(ctimeBuf, MAX_CTIME_LEN,
250 "%s %s %02d %02d:%02d:%02d %04d\n",
251 weekdayStrLookup[st.wDayOfWeek], monthStrLookup[st.wMonth - 1],
252 st.wDay, st.wHour, st.wMinute, st.wSecond, st.wYear);
253 ctimeBuf[MAX_CTIME_LEN - 1] = 0; // Make sure it's NUL terminated
254 return ctimeBuf;
257 time_t mktime(struct tm *tm) {
258 time_t ret;
259 FILETIME ft;
260 SYSTEMTIME st;
262 // Convert struct tm to a SYSTEMTIME
263 st.wDay = tm->tm_mday;
264 st.wDayOfWeek = 0;
265 st.wHour = tm->tm_hour;
266 st.wMilliseconds = 0;
267 st.wMinute = tm->tm_min;
268 st.wMonth = tm->tm_mon + 1;
269 st.wSecond = tm->tm_sec;
270 st.wYear = tm->tm_year + 1900;
272 // Convert the system time to unix time
273 SystemTimeToFileTime(&st, &ft);
274 FileTimeToUnixTime(&ft, &ret);
275 // Convert the filetime back so we can set tm_wday and tm_yday
276 FileTimeToSystemTime(&ft, &st);
277 tm->tm_wday = st.wDayOfWeek;
278 tm->tm_yday = monthLookup[st.wMonth - 1] +
279 ((isLeapYear(st.wYear) && st.wMonth > 2)? 1 : 0) +
280 st.wDay;
282 return ret;
285 // Currently this only implements the strftime format specifiers
286 // needed by libbarry.
287 size_t strftime(char *s, size_t max, const char *format,
288 const struct tm *tm) {
289 char * curOut = s;
290 const char* curIn = format;
291 while (*curIn != 0 && (size_t)(curOut - s) <= max) {
292 if( *curIn == '%' ) {
293 const int remainingSpace = max - (curOut - s);
294 // Start of format specifier
295 switch (curIn[1]) {
296 case '%':
297 // Escaped %
298 *curOut = '%';
299 ++curOut;
300 curIn += 2;
301 break;
302 case 'Y':
303 // Year as decimal, including century
304 curOut += _snprintf(curOut, remainingSpace,
305 "%04d", tm->tm_year + 1900);
306 curIn += 2;
307 break;
308 case 'm':
309 // Month as a decimal (01-12)
310 curOut += _snprintf(curOut, remainingSpace,
311 "%02d", tm->tm_mon + 1);
312 curIn += 2;
313 break;
314 case 'd':
315 // Day of month in decimal (01-31)
316 curOut += _snprintf(curOut, remainingSpace,
317 "%02d", tm->tm_mday);
318 curIn += 2;
319 break;
320 case 'H':
321 // Hour in decimal (00-23)
322 curOut += _snprintf(curOut, remainingSpace,
323 "%02d", tm->tm_hour);
324 curIn += 2;
325 break;
326 case 'M':
327 // Minutes in decimal (00-59)
328 curOut += _snprintf(curOut, remainingSpace,
329 "%02d", tm->tm_min);
330 curIn += 2;
331 break;
332 case 'S':
333 // Seconds as a decimal (00-60)
334 curOut += _snprintf(curOut, remainingSpace,
335 "%02d", tm->tm_sec);
336 curIn += 2;
337 break;
338 default:
339 // Unsupported format specifier, including NUL
340 // just write it out as is.
341 if( remainingSpace >= 2 ) {
342 *curOut = *curIn;
343 ++curOut;
344 ++curIn;
345 *curOut = *curIn;
346 ++curOut;
347 ++curIn;
349 break;
351 } else {
352 *curOut = *curIn;
353 ++curOut;
354 ++curIn;
357 // NUL terminate if possible
358 if( (size_t)(curOut - s) < max ) {
359 *curOut = 0;
360 ++curOut;
362 return (curOut - s);
366 #endif