From DONOTREPLY at icculus.org Fri Jun 1 03:08:43 2007 From: DONOTREPLY at icculus.org (DONOTREPLY at icculus.org) Date: 1 Jun 2007 03:08:43 -0400 Subject: r320 - trunk Message-ID: <20070601070843.25351.qmail@icculus.org> Author: icculus Date: 2007-06-01 03:08:41 -0400 (Fri, 01 Jun 2007) New Revision: 320 Modified: trunk/mojosetup.c Log: "--logfile" was bothering me, changed it to "--log". Modified: trunk/mojosetup.c =================================================================== --- trunk/mojosetup.c 2007-05-27 19:03:01 UTC (rev 319) +++ trunk/mojosetup.c 2007-06-01 07:08:41 UTC (rev 320) @@ -321,7 +321,7 @@ void MojoLog_initLogging(void) { const char *level = cmdlinestr("loglevel","MOJOSETUP_LOGLEVEL", DEFLOGLEV); - const char *fname = cmdlinestr("logfile", "MOJOSETUP_LOGFILE", NULL); + const char *fname = cmdlinestr("log", "MOJOSETUP_LOG", NULL); if (strcmp(level, "nothing") == 0) MojoLog_logLevel = MOJOSETUP_LOG_NOTHING; From DONOTREPLY at icculus.org Fri Jun 1 06:31:58 2007 From: DONOTREPLY at icculus.org (DONOTREPLY at icculus.org) Date: 1 Jun 2007 06:31:58 -0400 Subject: r321 - trunk Message-ID: <20070601103158.20393.qmail@icculus.org> Author: icculus Date: 2007-06-01 06:31:58 -0400 (Fri, 01 Jun 2007) New Revision: 321 Modified: trunk/universal.h Log: In case I need this later... Modified: trunk/universal.h =================================================================== --- trunk/universal.h 2007-06-01 07:08:41 UTC (rev 320) +++ trunk/universal.h 2007-06-01 10:31:58 UTC (rev 321) @@ -58,6 +58,16 @@ #define ISPRINTF(x,y) #endif +// Compiler-enforced sentinel safety helper. +// This is appended to function declarations that use sentinel-style semantics, +// and will make sure your passed the right params to "..." where a NULL +// is needed at the end of the list. +#ifdef __GNUC__ +#define ISSENTINEL __attribute__((sentinel)) +#else +#define ISSENTINEL +#endif + // Command line access outside of main(). extern int GArgc; extern const char **GArgv; From DONOTREPLY at icculus.org Fri Jun 1 06:33:05 2007 From: DONOTREPLY at icculus.org (DONOTREPLY at icculus.org) Date: 1 Jun 2007 06:33:05 -0400 Subject: r322 - trunk Message-ID: <20070601103305.21118.qmail@icculus.org> Author: icculus Date: 2007-06-01 06:33:05 -0400 (Fri, 01 Jun 2007) New Revision: 322 Modified: trunk/gui_gtkplus2.c Log: Make string match other GUIs, for localization lookup. Modified: trunk/gui_gtkplus2.c =================================================================== --- trunk/gui_gtkplus2.c 2007-06-01 10:31:58 UTC (rev 321) +++ trunk/gui_gtkplus2.c 2007-06-01 10:33:05 UTC (rev 322) @@ -625,7 +625,7 @@ // !!! FIXME: better text. const char *title = entry->_("Media change"); // !!! FIXME: better text. - const char *fmt = entry->_("Please insert %s"); + const char *fmt = entry->_("Please insert '%s'"); size_t len = strlen(fmt) + strlen(medianame) + 1; char *text = (char *) entry->xmalloc(len); snprintf(text, len, fmt, medianame); From DONOTREPLY at icculus.org Fri Jun 1 06:33:34 2007 From: DONOTREPLY at icculus.org (DONOTREPLY at icculus.org) Date: 1 Jun 2007 06:33:34 -0400 Subject: r323 - in trunk: . scripts Message-ID: <20070601103334.21463.qmail@icculus.org> Author: icculus Date: 2007-06-01 06:33:34 -0400 (Fri, 01 Jun 2007) New Revision: 323 Added: trunk/gui_www.c Modified: trunk/CMakeLists.txt trunk/gui.c trunk/gui.h trunk/scripts/localization.lua Log: Initial work on 'www' UI. Incomplete! Modified: trunk/CMakeLists.txt =================================================================== --- trunk/CMakeLists.txt 2007-06-01 10:33:05 UTC (rev 322) +++ trunk/CMakeLists.txt 2007-06-01 10:33:34 UTC (rev 323) @@ -374,7 +374,20 @@ ENDIF(NOT BEOS) ENDIF(UNIX) +# BINARY SIZE += !!! FIXME: check this. +OPTION(MOJOSETUP_GUI_WWW "Enable www GUI" TRUE) +IF(MOJOSETUP_GUI_WWW) + ADD_DEFINITIONS(-DSUPPORT_GUI_WWW=1) + OPTION(MOJOSETUP_GUI_WWW_STATIC "Statically link www GUI" TRUE) + IF(MOJOSETUP_GUI_WWW_STATIC) + ADD_DEFINITIONS(-DGUI_STATIC_LINK_WWW=1) + SET(OPTIONAL_SRCS ${OPTIONAL_SRCS} gui_www.c) + ELSE(MOJOSETUP_GUI_WWW_STATIC) + ADD_LIBRARY(mojosetupgui_www SHARED gui_www.c) + ENDIF(MOJOSETUP_GUI_WWW_STATIC) +ENDIF(MOJOSETUP_GUI_WWW) + # Archivers... # BINARY SIZE += 8 Modified: trunk/gui.c =================================================================== --- trunk/gui.c 2007-06-01 10:33:05 UTC (rev 322) +++ trunk/gui.c 2007-06-01 10:33:34 UTC (rev 323) @@ -32,6 +32,9 @@ #if GUI_STATIC_LINK_GTKPLUS2 MojoGuiPlugin_gtkplus2, #endif +#if GUI_STATIC_LINK_WWW + MojoGuiPlugin_www, +#endif #if GUI_STATIC_LINK_NCURSES MojoGuiPlugin_ncurses, #endif Modified: trunk/gui.h =================================================================== --- trunk/gui.h 2007-06-01 10:33:05 UTC (rev 322) +++ trunk/gui.h 2007-06-01 10:33:34 UTC (rev 323) @@ -169,6 +169,7 @@ const MojoGui *MojoGuiPlugin_stdio(int rev, const MojoSetupEntryPoints *e); const MojoGui *MojoGuiPlugin_ncurses(int rev, const MojoSetupEntryPoints *e); const MojoGui *MojoGuiPlugin_gtkplus2(int rev, const MojoSetupEntryPoints *e); +const MojoGui *MojoGuiPlugin_www(int rev, const MojoSetupEntryPoints *e); const MojoGui *MojoGuiPlugin_macosx(int rev, const MojoSetupEntryPoints *e); // !!! FIXME: Qt? KDE? Gnome? Console? Cocoa? Added: trunk/gui_www.c =================================================================== --- trunk/gui_www.c (rev 0) +++ trunk/gui_www.c 2007-06-01 10:33:34 UTC (rev 323) @@ -0,0 +1,906 @@ +/** + * MojoSetup; a portable, flexible installation application. + * + * Please see the file LICENSE.txt in the source's root directory. + * + * This file written by Ryan C. Gordon. + */ + +#if !SUPPORT_GUI_WWW +#error Something is wrong in the build system. +#endif + +#define BUILDING_EXTERNAL_PLUGIN 1 +#include "gui.h" + +MOJOGUI_PLUGIN(www) + +#if !GUI_STATIC_LINK_WWW +CREATE_MOJOGUI_ENTRY_POINT(www) +#endif + +#include +#include +#include +#include + +#define FREE_AND_NULL(x) { free(x); x = NULL; } + + +// tapdance between things WinSock and BSD Sockets define differently... +#if PLATFORM_WINDOWS + #include + + typedef int socklen_t; + + #define sockErrno() WSAGetLastError() + #define wouldBlockError(err) (err == WSAEWOULDBLOCK) + #define intrError(err) (err == WSAEINTR) + + static inline void setBlocking(SOCKET s, boolean blocking) + { + u_long val = (blocking) ? 0 : 1; + ioctlsocket(s, FIONBIO, &val); + } // setBlocking + + static const char *sockStrErrVal(int val) + { + STUBBED("Windows strerror"); + } // sockStrErrVal + + + static boolean initSocketSupport(void) + { + WSADATA data; + int rc = WSAStartup(MAKEWORD(1, 1), &data); + if (rc != 0) + { + entry->logError("www: WSAStartup() failed: %s", sockStrErrVal(rc)); + return false; + } // if + + entry->logInfo("www: WinSock initialized (want %d.%d, got %d.%d).", + (int) (LOBYTE(data.wVersion)), + (int) (HIBYTE(data.wVersion)), + (int) (LOBYTE(data.wHighVersion)), + (int) (HIBYTE(data.wHighVersion))); + entry->logInfo("www: WinSock description: %s", data.szDescription); + entry->logInfo("www: WinSock system status: %s", data.szSystemStatus); + entry->logInfo("www: WinSock max sockets: %s", (int) data.iMaxSockets); + + return true; + } // initSocketSupport + + #define deinitSocketSupport() WSACleanup() + +#else + #include + #include + #include + #include + #include + #include + #include + #include + #include + + typedef int SOCKET; + + #define SOCKET_ERROR (-1) + #define INVALID_SOCKET (-1) + #define closesocket(x) close(x) + #define sockErrno() (errno) + #define sockStrErrVal(val) strerror(val) + #define intrError(err) (err == EINTR) + #define initSocketSupport() (true) + #define deinitSocketSupport() + + static inline boolean wouldBlockError(int err) + { + return ((err == EWOULDBLOCK) || (err == EAGAIN)); + } // wouldBlockError + + static void setBlocking(SOCKET s, boolean blocking) + { + int flags = fcntl(s, F_GETFL, 0); + if (blocking) + flags &= ~O_NONBLOCK; + else + flags |= O_NONBLOCK; + fcntl(s, F_SETFL, flags); + } // setBlocking + +#endif + +#define sockStrError() (sockStrErrVal(sockErrno())) + + +typedef struct _S_WebRequest +{ + char *key; + char *value; + struct _S_WebRequest *next; +} WebRequest; + + +static char *output = NULL; +static char *lastProgressType = NULL; +static char *lastComponent = NULL; +static char *baseUrl = NULL; +static WebRequest *webRequest = NULL; +static uint32 percentTicks = 0; +static SOCKET listenSocket = INVALID_SOCKET; +static SOCKET clientSocket = INVALID_SOCKET; + + +static uint8 MojoGui_www_priority(void) +{ + return MOJOGUI_PRIORITY_TRY_LAST; +} // MojoGui_www_priority + + +static void freeWebRequest(void) +{ + while (webRequest) + { + WebRequest *next = webRequest->next; + free(webRequest->key); + free(webRequest->value); + free(webRequest); + webRequest = next; + } // while +} // freeWebRequest + + +static void addWebRequest(const char *key, const char *val) +{ + if ((key != NULL) && (*key != '\0')) + { + WebRequest *req = (WebRequest *) entry->xmalloc(sizeof (WebRequest)); + req->key = entry->xstrdup(key); + req->value = entry->xstrdup(val); + req->next = webRequest; + webRequest = req; + entry->logDebug("www: request element '%s' = '%s'", key, val); + } // if +} // addWebRequest + + +static int hexVal(char ch) +{ + if ((ch >= 'a') && (ch <= 'f')) + return (ch - 'a') + 16; + else if ((ch >= 'A') && (ch <= 'F')) + return (ch - 'A') + 16; + else if ((ch >= '0') && (ch <= '9')) + return (ch - '0'); + return -1; +} // hexVal + + +static void unescapeUri(char *uri) +{ + char *ptr = uri; + while ((ptr = strchr(ptr, '%')) != NULL) + { + int a, b; + if ((a = hexVal(ptr[1])) != -1) + { + if ((b = hexVal(ptr[2])) != -1) + { + *(ptr++) = (char) ((a * 16) + b); + memmove(ptr, ptr+2, strlen(ptr+1)); + } // if + else + { + *(ptr++) = '?'; + memmove(ptr, ptr+1, strlen(ptr)); + } // else + } // if + else + { + *(ptr++) = '?'; + } // else + } // while +} // unescapeUri + + +static int strAdd(char **ptr, size_t *len, size_t *alloc, const char *fmt, ...) +{ + int bw = 0; + size_t avail = *alloc - *len; + va_list ap; + va_start(ap, fmt); + bw = vsnprintf(*ptr + *len, avail, fmt, ap); + va_end(ap); + + if (bw >= avail) + { + const size_t add = (*alloc + (bw + 1)); // double plus the new len. + *alloc += add; + avail += add; + *ptr = entry->xrealloc(*ptr, *alloc); + va_start(ap, fmt); + bw = vsnprintf(*ptr + *len, avail, fmt, ap); + va_end(ap); + } // if + + *len += bw; + return bw; +} // strAdd + + +static char *htmlescape(const char *str) +{ + size_t len = 0, alloc = 0; + char *retval = NULL; + char ch; + + for (ch = *str; ch != '\0'; ch = *(str++)) + { + switch (ch) + { + case '&': strAdd(&retval, &len, &alloc, "&"); break; + case '<': strAdd(&retval, &len, &alloc, "<"); break; + case '>': strAdd(&retval, &len, &alloc, ">"); break; + case '"': strAdd(&retval, &len, &alloc, """); break; + case '\'': strAdd(&retval, &len, &alloc, "'"); break; + default: strAdd(&retval, &len, &alloc, "%c", ch); break; + } // switch + } // while + + return retval; +} // htmlescape + + +static const char *standardResponseHeaders = + "Content-Type: text/html; charset=utf-8\n" + "Accept-Ranges: none\n" + "Cache-Control: no-cache\n" + "Connection: close\n\n"; + + +static void setHtmlString(char **str, int responseCode, + const char *responseString, + const char *title, const char *html) +{ + size_t len = 0, alloc = 0; + FREE_AND_NULL(*str); + strAdd(str, &len, &alloc, + "HTTP/1.1 %d %s\n" // responseCode, responseString + "%s" // standardResponseHeaders + "" + "" + "%s" // title + "" + "%s" // html + "\n", + responseCode, responseString, + standardResponseHeaders, + title, html); +} // setHtmlString + + +static void setHtml(const char *title, const char *html) +{ + setHtmlString(&output, 200, "OK", title, html); +} // setHtml + + +static void sendStringAndDrop(SOCKET *_s, const char *str) +{ + SOCKET s = *_s; + int outlen = 0; + if (str == NULL) + str = ""; + else + outlen = strlen(str); + + setBlocking(s, true); + + while (outlen > 0) + { + int rc = send(s, str, outlen, 0); + if (rc != SOCKET_ERROR) + { + str += rc; + outlen -= rc; + } // if + else + { + const int err = sockErrno(); + if (!intrError(err)) + { + entry->logError("www: send() failed: %s", sockStrErrVal(err)); + break; + } // if + } // else + } // while + + closesocket(s); + *_s = INVALID_SOCKET; +} // sendStringAndDrop + + +static void respond404(SOCKET *s) +{ + char *text = htmlescape(entry->_("Not Found")); + char *str = NULL; + size_t len = 0, alloc = 0; + char *html = NULL; + strAdd(&html, &len, &alloc, "

%s

", text); + setHtmlString(&str, 404, text, text, html); + free(html); + free(text); + sendStringAndDrop(s, str); + free(str); +} // respond404 + + +static boolean parseGet(char *get) +{ + char *uri = NULL; + char *ver = NULL; + + uri = strchr(get, ' '); + if (uri == NULL) return false; + *(uri++) = '\0'; + + ver = strchr(uri, ' '); + if (ver == NULL) return false; + *(ver++) = '\0'; + + if (strcmp(get, "GET") != 0) return false; + if (uri[0] != '/') return false; + uri++; // skip dirsep. + + // !!! FIXME: we may want to feed stock files ( tags, etc) + // !!! FIXME: at some point in the future. + if ((uri[0] != '?') && (uri[0] != '\0')) return false; + if (strncmp(ver, "HTTP/", 5) != 0) return false; + + if (*uri == '?') + uri++; // skip initial argsep. + + do + { + char *next = strchr(uri, '&'); + char *val = NULL; + if (next != NULL) + *(next++) = '\0'; + + val = strchr(uri, '='); + if (val == NULL) + val = ""; + else + *(val++) = '\0'; + + unescapeUri(uri); + unescapeUri(val); + addWebRequest(uri, val); + + uri = next; + } while (uri != NULL); + + return true; +} // parseGet + + +static boolean parseRequest(char *reqstr) +{ + do + { + char *next = strchr(reqstr, '\n'); + char *val = NULL; + if (next != NULL) + *(next++) = '\0'; + + val = strchr(reqstr, ':'); + if (val == NULL) + val = ""; + else + { + *(val++) = '\0'; + while (*val == ' ') + val++; + } // else + + if (*reqstr != '\0') + { + size_t len = 0, alloc = 0; + char *buf = NULL; + strAdd(&buf, &len, &alloc, "HTTP-%s", reqstr); + addWebRequest(buf, val); + free(buf); + } // if + + reqstr = next; + } while (reqstr != NULL); + + return true; +} // parseRequest + + + +static WebRequest *servePage(boolean blocking) +{ + int newline = 0; + char ch = 0; + struct sockaddr_in addr; + socklen_t addrlen = 0; + int s = 0; + char *reqstr = NULL; + size_t len = 0, alloc = 0; + int err = 0; + + freeWebRequest(); + + if (listenSocket == INVALID_SOCKET) + return NULL; + + if (clientSocket != INVALID_SOCKET) // response to feed to client. + sendStringAndDrop(&clientSocket, output); + + if (blocking) + setBlocking(listenSocket, true); + + do + { + s = accept(listenSocket, (struct sockaddr *) &addr, &addrlen); + err = sockErrno(); + } while ( (s == INVALID_SOCKET) && (intrError(err)) ); + + if (blocking) + setBlocking(listenSocket, false); // reset what we toggled up there. + + if (s == INVALID_SOCKET) + { + if (wouldBlockError(err)) + assert(!blocking); + else + { + entry->logError("www: accept() failed: %s", sockStrErrVal(err)); + closesocket(listenSocket); // make all future i/o fail too. + listenSocket = INVALID_SOCKET; + } // else + return NULL; + } // if + + setBlocking(s, true); + + // Doing this one char at a time isn't efficient, but it's easy. + + while (1) + { + if (recv(s, &ch, 1, 0) == SOCKET_ERROR) + { + const int err = sockErrno(); + if (!intrError(err)) // just try again on interrupt. + { + entry->logError("www: recv() failed: %s", sockStrErrVal(err)); + FREE_AND_NULL(reqstr); + closesocket(s); + s = INVALID_SOCKET; + break; + } // if + } // if + + else if (ch == '\n') // newline + { + if (++newline == 2) + break; // end of request. + strAdd(&reqstr, &len, &alloc, "\n"); + } // if + + else if (ch != '\r') + { + newline = 0; + strAdd(&reqstr, &len, &alloc, "%c", ch); + } // else if + } // while + + if (reqstr != NULL) + { + char *get = NULL; + char *ptr = strchr(reqstr, '\n'); + if (ptr != NULL) + { + *ptr = '\0'; + ptr++; + } // if + + // reqstr is the GET (or whatever) request, ptr is the rest. + get = entry->xstrdup(reqstr); + if (ptr == NULL) + { + *ptr = '\0'; + len = 0; + } // if + else + { + len = strlen(ptr); + memmove(reqstr, ptr, len+1); + } // else + + entry->logDebug("www: request '%s'", get); + + // okay, now (get) and (reqptr) are separate strings. + // These parse*() functions update (webRequest). + if ( (parseGet(get)) && (parseRequest(reqstr)) ) + entry->logDebug("www: accepted request"); + else + { + entry->logError("www: rejected bogus request"); + freeWebRequest(); + respond404(&s); + } // else + + free(reqstr); + free(get); + } // if + + clientSocket = s; + return webRequest; +} // servePage + + +static SOCKET create_listen_socket(short portnum) +{ + SOCKET s = INVALID_SOCKET; + int protocol = 0; // pray this is right. + struct protoent *prot; + + setprotoent(0); + prot = getprotobyname("tcp"); + if (prot != NULL) + protocol = prot->p_proto; + + s = socket(PF_INET, SOCK_STREAM, protocol); + if (s == INVALID_SOCKET) + entry->logInfo("www: socket() failed ('%s')", sockStrError()); + else + { + boolean success = false; + struct sockaddr_in addr; + addr.sin_family = AF_INET; + addr.sin_port = htons(portnum); + addr.sin_addr.s_addr = INADDR_ANY; // !!! FIXME: bind to localhost. + if (bind(s, (struct sockaddr *) &addr, sizeof (addr)) == SOCKET_ERROR) + entry->logError("www: bind() failed ('%s')", sockStrError()); + else if (listen(s, 5) == SOCKET_ERROR) + entry->logError("www: listen() failed ('%s')", sockStrError()); + else + { + entry->logInfo("www: socket created on port %d", (int) portnum); + success = true; + } // else + + if (!success) + { + closesocket(s); + s = INVALID_SOCKET; + } // if + } // if + + return s; +} // create_listen_socket + + +static boolean MojoGui_www_init(void) +{ + size_t len = 0, alloc = 0; + short portnum = 7341; // !!! FIXME: try some random ports. + percentTicks = 0; + + if (!initSocketSupport()) + { + entry->logInfo("www: socket subsystem init failed, use another UI."); + return false; + } // if + + listenSocket = create_listen_socket(portnum); + if (listenSocket < 0) + { + entry->logInfo("www: no listen socket, use another UI."); + return false; + } // if + + setBlocking(listenSocket, false); + + strAdd(&baseUrl, &len, &alloc, "http://localhost:%d/", (int) portnum); + return true; +} // MojoGui_www_init + + +static void MojoGui_www_deinit(void) +{ + // Catch any waiting browser connections...and tell them to buzz off! :) + char *donetitle = htmlescape(entry->_("Shutting down...")); + char *donetext = htmlescape(entry->_( + "Setup program is shutting down. You can close this browser now.")); + size_t len = 0, alloc = 0; + char *html = NULL; + + strAdd(&html, &len, &alloc, "

%s

", donetext); + setHtml(donetitle, html); + free(html); + free(donetitle); + free(donetext); + while (servePage(false) != NULL) { /* no-op. */ } + + freeWebRequest(); + FREE_AND_NULL(output); + FREE_AND_NULL(lastProgressType); + FREE_AND_NULL(lastComponent); + FREE_AND_NULL(baseUrl); + + if (clientSocket != INVALID_SOCKET) + { + closesocket(clientSocket); + clientSocket = INVALID_SOCKET; + } // if + + if (listenSocket != INVALID_SOCKET) + { + closesocket(listenSocket); + listenSocket = INVALID_SOCKET; + } // if + + deinitSocketSupport(); +} // MojoGui_www_deinit + + +static int doPromptPage(const char *title, const char *text, + const char *pagename, + const char **buttons, const char **localizedButtons, + int bcount) +{ + char *htmltitle = htmlescape(title); + boolean sawPage = false; + int answer = -1; + int i = 0; + char *html = NULL; + size_t len = 0, alloc = 0; + + strAdd(&html, &len, &alloc, + "
" + "
" // pagename + "" // pagename + "" + "" // text + "" + "" + "" + "
%s
", pagename, pagename, text); + + for (i = 0; i < bcount; i++) + { + const char *button = buttons[i]; + const char *loc = localizedButtons[i]; + strAdd(&html, &len, &alloc, + "", button, loc); + } // for + + strAdd(&html, &len, &alloc, + "
" + "
" + "
"); + + setHtml(htmltitle, html); + free(htmltitle); + free(html); + + while ((!sawPage) || (answer == -1)) + { + WebRequest *req = servePage(true); + sawPage = false; + answer = -1; + while (req != NULL) + { + const char *k = req->key; + const char *v = req->value; + if ( (strcmp(k, "page") == 0) && (strcmp(v, pagename) == 0) ) + sawPage = true; + else + { + for (i = 0; i < bcount; i++) + { + if (strcmp(k, buttons[i]) == 0) + { + answer = i; + break; + } // if + } // for + } // else + + req = req->next; + } // for + } // while + + return answer; +} // doPromptPage + + +static void MojoGui_www_msgbox(const char *title, const char *text) +{ + char *buttons[] = { "ok" }; + char *localizedButtons[] = { htmlescape(entry->_("OK")) }; + char *htmltext = htmlescape(text); + doPromptPage(title, htmltext, "msgbox", buttons, localizedButtons, 1); + free(htmltext); + free(localizedButtons[0]); +} // MojoGui_www_msgbox + + +static boolean MojoGui_www_promptyn(const char *title, const char *text) +{ + int i, rc; + char *htmltext = htmlescape(text); + char *buttons[] = { "no", "yes" }; + char *localizedButtons[] = { + htmlescape(entry->_("No")) + htmlescape(entry->_("Yes")), + }; + assert(STATICARRAYLEN(buttons) == STATICARRAYLEN(localizedButtons)); + + rc = doPromptPage(title, htmltext, "promptyn", buttons, localizedButtons, + STATICARRAYLEN(buttons)); + free(htmltext); + + for (i = 0; i < STATICARRAYLEN(localizedButtons); i++) + free(localizedButtons[i]); + + return (rc == 1); +} // MojoGui_www_promptyn + + +static MojoGuiYNAN MojoGui_www_promptynan(const char *title, const char *txt) +{ + int i, rc; + char *htmltext = htmlescape(text); + char *buttons[] = { "no", "yes", "always", "never" }; + char *localizedButtons[] = { + htmlescape(entry->_("No")) + htmlescape(entry->_("Yes")), + htmlescape(entry->_("Always")), + htmlescape(entry->_("Never")), + }; + assert(STATICARRAYLEN(buttons) == STATICARRAYLEN(localizedButtons)); + + rc = doPromptPage(title, htmltext, "promptynan", buttons, localizedButtons, + STATICARRAYLEN(buttons)); + + free(htmltext); + for (i = 0; i < STATICARRAYLEN(localizedButtons); i++) + free(localizedButtons[i]); + + return (MojoGuiYNAN) rc; +} // MojoGui_www_promptynan + + +static boolean MojoGui_www_start(const char *title, const char *splash) +{ + return true; +} // MojoGui_www_start + + +static void MojoGui_www_stop(void) +{ + // no-op. +} // MojoGui_www_stop + + +static int MojoGui_www_readme(const char *name, const uint8 *data, + size_t datalen, boolean can_back, + boolean can_fwd) +{ + char *text = NULL; + size_t len = 0, alloc = 0; + char *htmldata = htmlescape(data); + int i, rc; + int cancelbutton = -1; + int backbutton = -1; + int fwdbutton = -1; + int bcount = 0; + char *buttons[4] = { NULL, NULL, NULL, NULL }; + char *localizedButtons[4] = { NULL, NULL, NULL, NULL }; + assert(STATICARRAYLEN(buttons) == STATICARRAYLEN(localizedButtons)); + + cancelbutton = bcount++; + buttons[cancelbutton] = "next"; + localizedButtons[cancelbutton] = entry->xstrdup(entry->_("Cancel")); + + if (can_back) + { + backbutton = bcount++; + buttons[backbutton] = "back"; + localizedButtons[backbutton] = entry->xstrdup(entry->_("Back")); + } // if + + if (can_fwd) + { + fwdbutton = bcount++; + buttons[fwdbutton] = "next"; + localizedButtons[fwdbutton] = entry->xstrdup(entry->_("Next")); + } // if + + strAdd(&text, &len, &alloc, "
\n%s\n
", htmldata); + free(htmldata); + + rc = doPromptPage(name, text, "readme", buttons, localizedButtons, bcount); + + free(text); + for (i = 0; i < STATICARRAYLEN(localizedButtons); i++) + free(localizedButtons[i]); + + if (rc == backbutton) + return -1; + else if (rc == cancelbutton) + return 0; + return 1; +} // MojoGui_www_readme + + +static int MojoGui_www_options(MojoGuiSetupOptions *opts, + boolean can_back, boolean can_fwd) +{ + return 1; +} // MojoGui_www_options + + +static char *MojoGui_www_destination(const char **recommends, int recnum, + int *command, boolean can_back, + boolean can_fwd) +{ + *command = 0; + return NULL; +} // MojoGui_www_destination + + +static boolean MojoGui_www_insertmedia(const char *medianame) +{ + char *htmltext = NULL; + char *text = NULL; + size_t len = 0, alloc = 0; + + // !!! FIXME: better text. + const char *title = entry->xstrdup(entry->_("Media change")); + // !!! FIXME: better text. + strAdd(&text, &len, &alloc, entry->_("Please insert '%s'"), medianame); + + htmltext = htmlescape(text); + free(text); + + int i, rc; + char *buttons[] = { "cancel", "ok" }; + char *localizedButtons[] = { + htmlescape(entry->_("Cancel")) + htmlescape(entry->_("OK")), + }; + assert(STATICARRAYLEN(buttons) == STATICARRAYLEN(localizedButtons)); + + rc = doPromptPage(title, htmltext, "insertmedia", buttons, + localizedButtons, STATICARRAYLEN(buttons)); + + free(title); + free(htmltext); + for (i = 0; i < STATICARRAYLEN(localizedButtons); i++) + free(localizedButtons[i]); + + return (rc == 1); +} // MojoGui_www_insertmedia + + +static boolean MojoGui_www_progress(const char *type, const char *component, + int percent, const char *item) +{ + return true; +} // MojoGui_www_progress + + +static void MojoGui_www_final(const char *msg) +{ +} // MojoGui_www_final + +// end of gui_www.c ... + Modified: trunk/scripts/localization.lua =================================================================== --- trunk/scripts/localization.lua 2007-06-01 10:33:05 UTC (rev 322) +++ trunk/scripts/localization.lua 2007-06-01 10:33:34 UTC (rev 323) @@ -142,6 +142,17 @@ ["(I want to specify a path.)"] = { }; + + -- as in "404 Not Found" in a web browser. + ["Not Found"] = { + }; + + -- title bar in browser page, used with next item for page's text. + ["Shutting down..."] = { + }; + + ["Setup program is shutting down. You can close this browser now."] = { + }; }; -- end of localization.lua ... From DONOTREPLY at icculus.org Fri Jun 1 07:06:05 2007 From: DONOTREPLY at icculus.org (DONOTREPLY at icculus.org) Date: 1 Jun 2007 07:06:05 -0400 Subject: r324 - trunk Message-ID: <20070601110605.6372.qmail@icculus.org> Author: icculus Date: 2007-06-01 07:06:04 -0400 (Fri, 01 Jun 2007) New Revision: 324 Modified: trunk/gui_www.c Log: www UI: Patched to compile and a bunch of other fixes. Modified: trunk/gui_www.c =================================================================== --- trunk/gui_www.c 2007-06-01 10:33:34 UTC (rev 323) +++ trunk/gui_www.c 2007-06-01 11:06:04 UTC (rev 324) @@ -236,7 +236,7 @@ char *retval = NULL; char ch; - for (ch = *str; ch != '\0'; ch = *(str++)) + while ((ch = *(str++)) != '\0') { switch (ch) { @@ -565,6 +565,15 @@ addr.sin_family = AF_INET; addr.sin_port = htons(portnum); addr.sin_addr.s_addr = INADDR_ANY; // !!! FIXME: bind to localhost. + + // So we can bind this socket over and over in debug runs... + #if ((!defined _NDEBUG) && (!defined NDEBUG)) + { + int on = 1; + setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &on, sizeof (on)); + } + #endif + if (bind(s, (struct sockaddr *) &addr, sizeof (addr)) == SOCKET_ERROR) entry->logError("www: bind() failed ('%s')", sockStrError()); else if (listen(s, 5) == SOCKET_ERROR) @@ -621,7 +630,7 @@ size_t len = 0, alloc = 0; char *html = NULL; - strAdd(&html, &len, &alloc, "

%s

", donetext); + strAdd(&html, &len, &alloc, "
%s

", donetext); setHtml(donetitle, html); free(html); free(donetitle); @@ -650,9 +659,9 @@ } // MojoGui_www_deinit -static int doPromptPage(const char *title, const char *text, +static int doPromptPage(const char *title, const char *text, boolean centertxt, const char *pagename, - const char **buttons, const char **localizedButtons, + const char **buttons, const char **locButtons, int bcount) { char *htmltitle = htmlescape(title); @@ -661,20 +670,21 @@ int i = 0; char *html = NULL; size_t len = 0, alloc = 0; + const char *align = ((centertxt) ? " align='center'" : ""); strAdd(&html, &len, &alloc, "
" "
" // pagename "" // pagename "" - "" // text + "%s" // align, text "" - "
%s
", pagename, pagename, text); + "", pagename, pagename, align, text); for (i = 0; i < bcount; i++) { const char *button = buttons[i]; - const char *loc = localizedButtons[i]; + const char *loc = locButtons[i]; strAdd(&html, &len, &alloc, "", button, loc); } // for @@ -723,12 +733,12 @@ static void MojoGui_www_msgbox(const char *title, const char *text) { - char *buttons[] = { "ok" }; - char *localizedButtons[] = { htmlescape(entry->_("OK")) }; + const char *buttons[] = { "ok" }; + const char *locButtons[] = { htmlescape(entry->_("OK")) }; char *htmltext = htmlescape(text); - doPromptPage(title, htmltext, "msgbox", buttons, localizedButtons, 1); + doPromptPage(title, htmltext, true, "msgbox", buttons, locButtons, 1); free(htmltext); - free(localizedButtons[0]); + free((void *) locButtons[0]); } // MojoGui_www_msgbox @@ -736,43 +746,43 @@ { int i, rc; char *htmltext = htmlescape(text); - char *buttons[] = { "no", "yes" }; - char *localizedButtons[] = { - htmlescape(entry->_("No")) + const char *buttons[] = { "no", "yes" }; + const char *locButtons[] = { + htmlescape(entry->_("No")), htmlescape(entry->_("Yes")), }; - assert(STATICARRAYLEN(buttons) == STATICARRAYLEN(localizedButtons)); + assert(STATICARRAYLEN(buttons) == STATICARRAYLEN(locButtons)); - rc = doPromptPage(title, htmltext, "promptyn", buttons, localizedButtons, + rc = doPromptPage(title, htmltext, true, "promptyn", buttons, locButtons, STATICARRAYLEN(buttons)); free(htmltext); - for (i = 0; i < STATICARRAYLEN(localizedButtons); i++) - free(localizedButtons[i]); + for (i = 0; i < STATICARRAYLEN(locButtons); i++) + free((void *) locButtons[i]); return (rc == 1); } // MojoGui_www_promptyn -static MojoGuiYNAN MojoGui_www_promptynan(const char *title, const char *txt) +static MojoGuiYNAN MojoGui_www_promptynan(const char *title, const char *text) { int i, rc; char *htmltext = htmlescape(text); - char *buttons[] = { "no", "yes", "always", "never" }; - char *localizedButtons[] = { - htmlescape(entry->_("No")) + const char *buttons[] = { "no", "yes", "always", "never" }; + const char *locButtons[] = { + htmlescape(entry->_("No")), htmlescape(entry->_("Yes")), htmlescape(entry->_("Always")), htmlescape(entry->_("Never")), }; - assert(STATICARRAYLEN(buttons) == STATICARRAYLEN(localizedButtons)); + assert(STATICARRAYLEN(buttons) == STATICARRAYLEN(locButtons)); - rc = doPromptPage(title, htmltext, "promptynan", buttons, localizedButtons, + rc = doPromptPage(title, htmltext, true, "promptynan", buttons, locButtons, STATICARRAYLEN(buttons)); free(htmltext); - for (i = 0; i < STATICARRAYLEN(localizedButtons); i++) - free(localizedButtons[i]); + for (i = 0; i < STATICARRAYLEN(locButtons); i++) + free((void *) locButtons[i]); return (MojoGuiYNAN) rc; } // MojoGui_www_promptynan @@ -796,42 +806,42 @@ { char *text = NULL; size_t len = 0, alloc = 0; - char *htmldata = htmlescape(data); + char *htmldata = htmlescape((const char *) data); int i, rc; int cancelbutton = -1; int backbutton = -1; int fwdbutton = -1; int bcount = 0; - char *buttons[4] = { NULL, NULL, NULL, NULL }; - char *localizedButtons[4] = { NULL, NULL, NULL, NULL }; - assert(STATICARRAYLEN(buttons) == STATICARRAYLEN(localizedButtons)); + const char *buttons[4] = { NULL, NULL, NULL, NULL }; + const char *locButtons[4] = { NULL, NULL, NULL, NULL }; + assert(STATICARRAYLEN(buttons) == STATICARRAYLEN(locButtons)); cancelbutton = bcount++; buttons[cancelbutton] = "next"; - localizedButtons[cancelbutton] = entry->xstrdup(entry->_("Cancel")); + locButtons[cancelbutton] = entry->xstrdup(entry->_("Cancel")); if (can_back) { backbutton = bcount++; buttons[backbutton] = "back"; - localizedButtons[backbutton] = entry->xstrdup(entry->_("Back")); + locButtons[backbutton] = entry->xstrdup(entry->_("Back")); } // if if (can_fwd) { fwdbutton = bcount++; buttons[fwdbutton] = "next"; - localizedButtons[fwdbutton] = entry->xstrdup(entry->_("Next")); + locButtons[fwdbutton] = entry->xstrdup(entry->_("Next")); } // if strAdd(&text, &len, &alloc, "
\n%s\n
", htmldata); free(htmldata); - rc = doPromptPage(name, text, "readme", buttons, localizedButtons, bcount); + rc = doPromptPage(name, text, false, "readme", buttons, locButtons, bcount); free(text); - for (i = 0; i < STATICARRAYLEN(localizedButtons); i++) - free(localizedButtons[i]); + for (i = 0; i < STATICARRAYLEN(locButtons); i++) + free((void *) locButtons[i]); if (rc == backbutton) return -1; @@ -864,7 +874,7 @@ size_t len = 0, alloc = 0; // !!! FIXME: better text. - const char *title = entry->xstrdup(entry->_("Media change")); + char *title = entry->xstrdup(entry->_("Media change")); // !!! FIXME: better text. strAdd(&text, &len, &alloc, entry->_("Please insert '%s'"), medianame); @@ -872,20 +882,20 @@ free(text); int i, rc; - char *buttons[] = { "cancel", "ok" }; - char *localizedButtons[] = { - htmlescape(entry->_("Cancel")) + const char *buttons[] = { "cancel", "ok" }; + const char *locButtons[] = { + htmlescape(entry->_("Cancel")), htmlescape(entry->_("OK")), }; - assert(STATICARRAYLEN(buttons) == STATICARRAYLEN(localizedButtons)); + assert(STATICARRAYLEN(buttons) == STATICARRAYLEN(locButtons)); - rc = doPromptPage(title, htmltext, "insertmedia", buttons, - localizedButtons, STATICARRAYLEN(buttons)); + rc = doPromptPage(title, htmltext, true, "insertmedia", buttons, + locButtons, STATICARRAYLEN(buttons)); free(title); free(htmltext); - for (i = 0; i < STATICARRAYLEN(localizedButtons); i++) - free(localizedButtons[i]); + for (i = 0; i < STATICARRAYLEN(locButtons); i++) + free((void *) locButtons[i]); return (rc == 1); } // MojoGui_www_insertmedia From DONOTREPLY at icculus.org Fri Jun 1 07:16:12 2007 From: DONOTREPLY at icculus.org (DONOTREPLY at icculus.org) Date: 1 Jun 2007 07:16:12 -0400 Subject: r325 - trunk Message-ID: <20070601111612.10886.qmail@icculus.org> Author: icculus Date: 2007-06-01 07:16:11 -0400 (Fri, 01 Jun 2007) New Revision: 325 Modified: trunk/gui_www.c Log: Whoops, cut-and-paste issue. Modified: trunk/gui_www.c =================================================================== --- trunk/gui_www.c 2007-06-01 11:06:04 UTC (rev 324) +++ trunk/gui_www.c 2007-06-01 11:16:11 UTC (rev 325) @@ -817,7 +817,7 @@ assert(STATICARRAYLEN(buttons) == STATICARRAYLEN(locButtons)); cancelbutton = bcount++; - buttons[cancelbutton] = "next"; + buttons[cancelbutton] = "cancel"; locButtons[cancelbutton] = entry->xstrdup(entry->_("Cancel")); if (can_back) From DONOTREPLY at icculus.org Fri Jun 1 07:16:50 2007 From: DONOTREPLY at icculus.org (DONOTREPLY at icculus.org) Date: 1 Jun 2007 07:16:50 -0400 Subject: r326 - trunk Message-ID: <20070601111650.11202.qmail@icculus.org> Author: icculus Date: 2007-06-01 07:16:50 -0400 (Fri, 01 Jun 2007) New Revision: 326 Modified: trunk/CMakeLists.txt Log: Disable www UI in build by default for now. Modified: trunk/CMakeLists.txt =================================================================== --- trunk/CMakeLists.txt 2007-06-01 11:16:11 UTC (rev 325) +++ trunk/CMakeLists.txt 2007-06-01 11:16:50 UTC (rev 326) @@ -375,10 +375,10 @@ ENDIF(UNIX) # BINARY SIZE += !!! FIXME: check this. -OPTION(MOJOSETUP_GUI_WWW "Enable www GUI" TRUE) +OPTION(MOJOSETUP_GUI_WWW "Enable www GUI" FALSE) # !!! FIXME: make TRUE IF(MOJOSETUP_GUI_WWW) ADD_DEFINITIONS(-DSUPPORT_GUI_WWW=1) - OPTION(MOJOSETUP_GUI_WWW_STATIC "Statically link www GUI" TRUE) + OPTION(MOJOSETUP_GUI_WWW_STATIC "Statically link www GUI" FALSE) IF(MOJOSETUP_GUI_WWW_STATIC) ADD_DEFINITIONS(-DGUI_STATIC_LINK_WWW=1) SET(OPTIONAL_SRCS ${OPTIONAL_SRCS} gui_www.c) From DONOTREPLY at icculus.org Sat Jun 2 00:55:25 2007 From: DONOTREPLY at icculus.org (DONOTREPLY at icculus.org) Date: 2 Jun 2007 00:55:25 -0400 Subject: r327 - trunk Message-ID: <20070602045525.2002.qmail@icculus.org> Author: icculus Date: 2007-06-02 00:55:25 -0400 (Sat, 02 Jun 2007) New Revision: 327 Modified: trunk/gui_www.c Log: www UI: implemented Destination and Final pages, plus some other fixes. Modified: trunk/gui_www.c =================================================================== --- trunk/gui_www.c 2007-06-01 11:16:50 UTC (rev 326) +++ trunk/gui_www.c 2007-06-02 04:55:25 UTC (rev 327) @@ -169,9 +169,9 @@ static int hexVal(char ch) { if ((ch >= 'a') && (ch <= 'f')) - return (ch - 'a') + 16; + return (ch - 'a') + 10; else if ((ch >= 'A') && (ch <= 'F')) - return (ch - 'A') + 16; + return (ch - 'A') + 10; else if ((ch >= '0') && (ch <= '9')) return (ch - '0'); return -1; @@ -724,7 +724,7 @@ } // else req = req->next; - } // for + } // while } // while return answer; @@ -862,8 +862,109 @@ int *command, boolean can_back, boolean can_fwd) { - *command = 0; - return NULL; + char *retval = NULL; + char *title = entry->xstrdup(entry->_("Destination")); + char *html = NULL; + size_t len = 0, alloc = 0; + boolean checked = true; + int cancelbutton = -1; + int backbutton = -1; + int fwdbutton = -1; + int bcount = 0; + int rc = 0; + int i = 0; + const char *buttons[4] = { NULL, NULL, NULL, NULL }; + const char *locButtons[4] = { NULL, NULL, NULL, NULL }; + assert(STATICARRAYLEN(buttons) == STATICARRAYLEN(locButtons)); + + cancelbutton = bcount++; + buttons[cancelbutton] = "cancel"; + locButtons[cancelbutton] = entry->xstrdup(entry->_("Cancel")); + + if (can_back) + { + backbutton = bcount++; + buttons[backbutton] = "back"; + locButtons[backbutton] = entry->xstrdup(entry->_("Back")); + } // if + + if (can_fwd) + { + fwdbutton = bcount++; + buttons[fwdbutton] = "next"; + locButtons[fwdbutton] = entry->xstrdup(entry->_("Next")); + } // if + + strAdd(&html, &len, &alloc, + "" + ""); + + for (i = 0; i < recnum; i++) + { + strAdd(&html, &len, &alloc, + "" + "" + "", + ((checked) ? "checked='true'" : ""), recommends[i], recommends[i]); + checked = false; + } // for + + strAdd(&html, &len, &alloc, + "" + "" + "" + "
" + "%s" + "
" + "" + "" + "
" + "", ((checked) ? "checked='true'" : "")); + + rc = doPromptPage(title, html, true, "destination", + buttons, locButtons, bcount); + + free(title); + free(html); + for (i = 0; i < STATICARRAYLEN(locButtons); i++) + free((void *) locButtons[i]); + + if (rc == backbutton) + *command = -1; + else if (rc == cancelbutton) + *command = 0; + else + { + const char *dest = NULL; + const char *customdest = NULL; + WebRequest *req = webRequest; + while (req != NULL) + { + const char *k = req->key; + const char *v = req->value; + if (strcmp(k, "dest") == 0) + dest = v; + else if (strcmp(k, "customdest") == 0) + customdest = v; + req = req->next; + } // while + + if (dest != NULL) + { + if (strcmp(dest, "*") == 0) + dest = customdest; + } // if + + if (dest == NULL) + *command = 0; // !!! FIXME: maybe loop with doPromptPage again. + else + { + retval = entry->xstrdup(dest); + *command = 1; + } // else + } // else + + return retval; } // MojoGui_www_destination @@ -910,6 +1011,7 @@ static void MojoGui_www_final(const char *msg) { + MojoGui_www_msgbox(entry->_("Finish"), msg); } // MojoGui_www_final // end of gui_www.c ... From DONOTREPLY at icculus.org Mon Jun 18 15:45:54 2007 From: DONOTREPLY at icculus.org (DONOTREPLY at icculus.org) Date: 18 Jun 2007 15:45:54 -0400 Subject: r328 - trunk Message-ID: <20070618194554.24397.qmail@icculus.org> Author: icculus Date: 2007-06-18 15:45:06 -0400 (Mon, 18 Jun 2007) New Revision: 328 Modified: trunk/universal.h Log: Forcibly #undef things that might be big nasty macros under glibc, so we can redefine them to something that fails the compile if you try to use them. :) Modified: trunk/universal.h =================================================================== --- trunk/universal.h 2007-06-02 04:55:25 UTC (rev 327) +++ trunk/universal.h 2007-06-18 19:45:06 UTC (rev 328) @@ -114,15 +114,53 @@ // strncpy() that promises to null-terminate the string, even on overflow. char *xstrncpy(char *dst, const char *src, size_t len); + +#ifdef malloc +#undef malloc +#endif #define malloc(x) DO_NOT_CALL_MALLOC__USE_XMALLOC_INSTEAD + +#ifdef calloc +#undef calloc +#endif #define calloc(x,y) DO_NOT_CALL_CALLOC__USE_XMALLOC_INSTEAD + +#ifdef realloc +#undef realloc +#endif #define realloc(x,y) DO_NOT_CALL_REALLOC__USE_XREALLOC_INSTEAD + +#ifdef strdup +#undef strdup +#endif #define strdup(x) DO_NOT_CALL_STRDUP__USE_XSTRDUP_INSTEAD + +#ifdef strncpy +#undef strncpy +#endif #define strncpy(x,y,z) DO_NOT_CALL_STRNCPY__USE_XSTRNCPY_INSTEAD -//#define strcasecmp(x,y) DO_NOT_CALL_STRCASECMP__USE_UTF8STRICMP_INSTEAD -//#define stricmp(x,y) DO_NOT_CALL_STRICMP__USE_UTF8STRICMP_INSTEAD -//#define strcmpi(x,y) DO_NOT_CALL_STRCMPI__USE_UTF8STRICMP_INSTEAD +#if 0 // !!! FIXME: write me. +#ifdef strcasecmp +#undef strcasecmp +#endif +#define strcasecmp(x,y) DO_NOT_CALL_STRCASECMP__USE_UTF8STRICMP_INSTEAD +#endif + +#if 0 // !!! FIXME: write me. +#ifdef stricmp +#undef stricmp +#endif +#define stricmp(x,y) DO_NOT_CALL_STRICMP__USE_UTF8STRICMP_INSTEAD +#endif + +#if 0 // !!! FIXME: write me. +#ifdef strcmpi +#undef strcmpi +#endif +#define strcmpi(x,y) DO_NOT_CALL_STRCMPI__USE_UTF8STRICMP_INSTEAD +#endif + // Localization support. const char *translate(const char *str); #ifdef _ From DONOTREPLY at icculus.org Mon Jun 18 17:50:50 2007 From: DONOTREPLY at icculus.org (DONOTREPLY at icculus.org) Date: 18 Jun 2007 17:50:50 -0400 Subject: r329 - in trunk: . misc Message-ID: <20070618215050.15187.qmail@icculus.org> Author: icculus Date: 2007-06-18 17:50:50 -0400 (Mon, 18 Jun 2007) New Revision: 329 Added: trunk/misc/ trunk/misc/cp.cmake trunk/misc/mkdir.cmake trunk/misc/rm_recurse.cmake Modified: trunk/ trunk/CMakeLists.txt Log: First shot at a "make skeleton" target. Property changes on: trunk ___________________________________________________________________ Name: svn:ignore - MojoSetup.xcodeproj MojoSetup.build build Debug Release CMakeScripts CMakeOutput.log CMakeCache.txt CMakeError.log cmake_install.cmake mojosetup mojoluac CMakeTmp CMakeFiles Makefile *.exe *.dll *.so *.dylib + MojoSetup.xcodeproj MojoSetup.build build skeleton Debug Release CMakeScripts CMakeOutput.log CMakeCache.txt CMakeError.log cmake_install.cmake mojosetup mojoluac CMakeTmp CMakeFiles Makefile *.exe *.dll *.so *.dylib Modified: trunk/CMakeLists.txt =================================================================== --- trunk/CMakeLists.txt 2007-06-18 19:45:06 UTC (rev 328) +++ trunk/CMakeLists.txt 2007-06-18 21:50:50 UTC (rev 329) @@ -292,6 +292,12 @@ # GUI plugins... +MACRO(MOJOSETUP_ADD_LIBRARY _TARGET _SRCS) + ADD_LIBRARY(${_TARGET} SHARED ${_SRCS}) + SET(MOJOSETUP_TARGETS "${MOJOSETUP_TARGETS};${_TARGET}") +ENDMACRO(MOJOSETUP_ADD_LIBRARY) + + # BINARY SIZE += 2.5 OPTION(MOJOSETUP_GUI_STDIO "Enable stdio GUI" TRUE) IF(MOJOSETUP_GUI_STDIO) @@ -301,7 +307,7 @@ ADD_DEFINITIONS(-DGUI_STATIC_LINK_STDIO=1) SET(OPTIONAL_SRCS ${OPTIONAL_SRCS} gui_stdio.c) ELSE(MOJOSETUP_GUI_STDIO_STATIC) - ADD_LIBRARY(mojosetupgui_stdio SHARED gui_stdio.c) + MOJOSETUP_ADD_LIBRARY(mojosetupgui_stdio gui_stdio.c) ENDIF(MOJOSETUP_GUI_STDIO_STATIC) ENDIF(MOJOSETUP_GUI_STDIO) @@ -318,7 +324,7 @@ SET(OPTIONAL_SRCS ${OPTIONAL_SRCS} gui_ncurses.c) SET(OPTIONAL_LIBS ${OPTIONAL_LIBS} -lncurses) # !!! FIXME ELSE(MOJOSETUP_GUI_NCURSES_STATIC) - ADD_LIBRARY(mojosetupgui_ncurses SHARED gui_ncurses.c) + MOJOSETUP_ADD_LIBRARY(mojosetupgui_ncurses gui_ncurses.c) TARGET_LINK_LIBRARIES(mojosetupgui_ncurses "-lncurses") # !!! FIXME ENDIF(MOJOSETUP_GUI_NCURSES_STATIC) ENDIF(MOJOSETUP_GUI_NCURSES) @@ -335,7 +341,7 @@ ADD_DEFINITIONS(-DGUI_STATIC_LINK_MACOSX=1) SET(OPTIONAL_SRCS ${OPTIONAL_SRCS} gui_macosx.c) ELSE(MOJOSETUP_GUI_MACOSX_STATIC) - ADD_LIBRARY(mojosetupgui_macosx SHARED gui_macosx.c) + MOJOSETUP_ADD_LIBRARY(mojosetupgui_macosx gui_macosx.c) TARGET_LINK_LIBRARIES(mojosetupgui_macosx "-framework Carbon -mmacosx-version-min=10.2" ) @@ -364,7 +370,7 @@ SET(OPTIONAL_SRCS ${OPTIONAL_SRCS} gui_gtkplus2.c) SET(OPTIONAL_LIBS ${OPTIONAL_LIBS} ${LIBGTK_LINK_FLAGS}) ELSE(MOJOSETUP_GUI_GTKPLUS2_STATIC) - ADD_LIBRARY(mojosetupgui_gtkplus2 SHARED gui_gtkplus2.c) + MOJOSETUP_ADD_LIBRARY(mojosetupgui_gtkplus2 gui_gtkplus2.c) ADD_DEFINITIONS(${LIBGTK_CFLAGS}) TARGET_LINK_LIBRARIES(mojosetupgui_gtkplus2 ${LIBGTK_LINK_FLAGS}) ENDIF(MOJOSETUP_GUI_GTKPLUS2_STATIC) @@ -383,7 +389,7 @@ ADD_DEFINITIONS(-DGUI_STATIC_LINK_WWW=1) SET(OPTIONAL_SRCS ${OPTIONAL_SRCS} gui_www.c) ELSE(MOJOSETUP_GUI_WWW_STATIC) - ADD_LIBRARY(mojosetupgui_www SHARED gui_www.c) + MOJOSETUP_ADD_LIBRARY(mojosetupgui_www gui_www.c) ENDIF(MOJOSETUP_GUI_WWW_STATIC) ENDIF(MOJOSETUP_GUI_WWW) @@ -532,7 +538,25 @@ ENDIF(MOJOSETUP_BUILD_LUAC) ADD_EXECUTABLE(mojosetup ${MOJOSETUP_SRCS} ${OPTIONAL_SRCS}) +GET_TARGET_PROPERTY(MOJOSETUP_BINARY_LOCATION mojosetup LOCATION) TARGET_LINK_LIBRARIES(mojosetup ${OPTIONAL_LIBS}) +SET(MOJOSETUP_TARGETS "${MOJOSETUP_TARGETS};mojosetup") +# For cobbling together a skeleton installer... + +ADD_CUSTOM_TARGET(skeleton + COMMENT "Assembling Skeleton..." + COMMAND ${CMAKE_COMMAND} -DDIR=${CMAKE_BINARY_DIR}/skeleton -P ${CMAKE_SOURCE_DIR}/misc/rm_recurse.cmake + COMMAND ${CMAKE_COMMAND} -DDIR=${CMAKE_BINARY_DIR}/skeleton -P ${CMAKE_SOURCE_DIR}/misc/mkdir.cmake + COMMAND ${CMAKE_COMMAND} -DDIR=${CMAKE_BINARY_DIR}/skeleton/scripts -P ${CMAKE_SOURCE_DIR}/misc/mkdir.cmake + COMMAND ${CMAKE_COMMAND} -DDIR=${CMAKE_BINARY_DIR}/skeleton/guis -P ${CMAKE_SOURCE_DIR}/misc/mkdir.cmake + COMMAND ${CMAKE_COMMAND} -DDIR=${CMAKE_BINARY_DIR}/skeleton/data -P ${CMAKE_SOURCE_DIR}/misc/mkdir.cmake + COMMAND ${CMAKE_COMMAND} -DFROM=${CMAKE_SOURCE_DIR}/scripts/*.lua -DTO=${CMAKE_BINARY_DIR}/skeleton/scripts -P ${CMAKE_SOURCE_DIR}/misc/cp.cmake + COMMAND ${CMAKE_COMMAND} -DFROM=${CMAKE_SOURCE_DIR}/*mojosetupgui*.* -DTO=${CMAKE_BINARY_DIR}/skeleton/guis -P ${CMAKE_SOURCE_DIR}/misc/cp.cmake + COMMAND ${CMAKE_COMMAND} -DFROM=${MOJOSETUP_BINARY_LOCATION} -DTO=${CMAKE_BINARY_DIR}/skeleton -P ${CMAKE_SOURCE_DIR}/misc/cp.cmake +) + +ADD_DEPENDENCIES(skeleton ${MOJOSETUP_TARGETS}) + # end of CMakeLists.txt ... Added: trunk/misc/cp.cmake =================================================================== --- trunk/misc/cp.cmake (rev 0) +++ trunk/misc/cp.cmake 2007-06-18 21:50:50 UTC (rev 329) @@ -0,0 +1,29 @@ +# CMake 2.4.3 lacks a "CMake -E copy" command that handles wildcards. +# +# INPUT: +# +# FROM - absolute pathname with wildcards to copy +# TO - absolute pathname of directory to copy to +# +# TYPICAL USAGE, from inside a custom target or rule: +# +# COMMAND ${CMAKE_COMMAND} +# -D FROM=${mydirectory}/*.dll +# -D TO=${yourdirectory} +# -P ${CMAKE_HOME_DIRECTORY}/cp.cmake + +FILE(GLOB FILELIST "${FROM}") + +FOREACH(LOOPER ${FILELIST}) + MESSAGE(STATUS "Copying ${LOOPER} to ${TO}") + EXEC_PROGRAM("${CMAKE_COMMAND}" ARGS "-E copy '${LOOPER}' '${TO}'" + OUTPUT_VARIABLE EXECOUT + RETURN_VALUE RC + ) + # !!! FIXME: how do you do NOT EQUALS? + IF(NOT RC EQUAL 0) + MESSAGE(STATUS "${EXECOUT}") + MESSAGE(FATAL_ERROR "Copy of '${LOOPER}' failed!") + ENDIF(NOT RC EQUAL 0) +ENDFOREACH(LOOPER) + Added: trunk/misc/mkdir.cmake =================================================================== --- trunk/misc/mkdir.cmake (rev 0) +++ trunk/misc/mkdir.cmake 2007-06-18 21:50:50 UTC (rev 329) @@ -0,0 +1,18 @@ +# CMake 2.4.3 lacks a "CMake -E mkdir" command. +# It does have a MAKE_DIRECTORY command, but we cannot run it from inside +# a custom rule or target. So, we wrap it in a script, which we can then +# call from a custom command or target. +# +# INPUT: +# +# DIR - absolute pathname of directory to be created +# +# TYPICAL USAGE, from inside a custom target or rule: +# +# COMMAND ${CMAKE_COMMAND} +# -D DIR=${mydirectory} +# -P ${CMAKE_HOME_DIRECTORY}/mkdir.cmake + +MESSAGE(STATUS "Creating directory ${DIR}") +FILE(MAKE_DIRECTORY "${DIR}") + Added: trunk/misc/rm_recurse.cmake =================================================================== --- trunk/misc/rm_recurse.cmake (rev 0) +++ trunk/misc/rm_recurse.cmake 2007-06-18 21:50:50 UTC (rev 329) @@ -0,0 +1,18 @@ +# CMake 2.4.5 lacks a "CMake -E 'rm -rf'" command. +# It does have a MAKE_DIRECTORY command, but we cannot run it from inside +# a custom rule or target. So, we wrap it in a script, which we can then +# call from a custom command or target. +# +# INPUT: +# +# DIR - absolute pathname of directory to be created +# +# TYPICAL USAGE, from inside a custom target or rule: +# +# COMMAND ${CMAKE_COMMAND} +# -D DIR=${mydirectory} +# -P ${CMAKE_HOME_DIRECTORY}/rm_recurse.cmake + +MESSAGE(STATUS "Removing directory ${DIR}") +FILE(REMOVE_RECURSE "${DIR}") +