Initial revision
authortomo <tomo>
Wed, 25 Sep 2002 12:04:01 +0000 (12:04 +0000)
committertomo <tomo>
Wed, 25 Sep 2002 12:04:01 +0000 (12:04 +0000)
lib-src/winclient.c [new file with mode: 0644]
netinstall/desktop.h [new file with mode: 0644]

diff --git a/lib-src/winclient.c b/lib-src/winclient.c
new file mode 100644 (file)
index 0000000..0399d99
--- /dev/null
@@ -0,0 +1,490 @@
+/* DDE client for XEmacs.\r
+   Copyright (C) 2002 Alastair J. Houghton\r
+\r
+   This file is part of XEmacs.\r
+\r
+   XEmacs is free software; you can redistribute it and/or modify it\r
+   under the terms of the GNU General Public License as published by the\r
+   Free Software Foundation; either version 2, or (at your option) any\r
+   later version.\r
+\r
+   XEmacs is distributed in the hope that it will be useful, but WITHOUT\r
+   ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or\r
+   FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License\r
+   for more details.\r
+\r
+   You should have received a copy of the GNU General Public License\r
+   along with XEmacs; see the file COPYING.  If not, write to\r
+   the Free Software Foundation, Inc., 59 Temple Place - Suite 330,\r
+   Boston, MA 02111-1307, USA.  */\r
+\r
+/* Synched up with: Not in FSF. */\r
+\r
+/* -- Pre-Include Defines --------------------------------------------------- */\r
+\r
+#define STRICT\r
+\r
+/* -- Includes -------------------------------------------------------------- */\r
+\r
+#include <windows.h>\r
+#ifdef HAVE_CONFIG_H\r
+# include <config.h>\r
+#endif\r
+#include <stdlib.h>\r
+#include <stdio.h>\r
+#include <ctype.h>\r
+#include <errno.h>\r
+\r
+static void error (const char* s1, const char* s2);\r
+static void fatal (const char *s1, const char *s2);\r
+static void * xmalloc (size_t size);\r
+static char * getNextArg (const char **ptr, unsigned *len);\r
+\r
+/* -- Post-Include Defines -------------------------------------------------- */\r
+\r
+/* Timeouts & delays */\r
+#define CONNECT_DELAY          500             /* ms */\r
+#define TRANSACTION_TIMEOUT    5000            /* ms */\r
+#define MAX_INPUT_IDLE_WAIT     INFINITE       /* ms */\r
+\r
+/* DDE Strings */\r
+#define SERVICE_NAME   "XEmacs"\r
+#define TOPIC_NAME     "System"\r
+#define COMMAND_FORMAT "[open(\"%s%s\")]"\r
+\r
+/* XEmacs program name */\r
+#define PROGRAM_TO_RUN "xemacs.exe"\r
+\r
+/* -- Constants ------------------------------------------------------------- */\r
+\r
+/* -- Global Variables ------------------------------------------------------ */\r
+\r
+HINSTANCE hInstance;\r
+DWORD     idInst = 0;\r
+\r
+/* -- Function Declarations ------------------------------------------------- */\r
+\r
+HDDEDATA CALLBACK ddeCallback (UINT uType, UINT uFmt, HCONV hconv,\r
+                              HSZ hsz1, HSZ hsz2, HDDEDATA hdata,\r
+                              DWORD dwData1, DWORD dwData2);\r
+\r
+int WINAPI WinMain (HINSTANCE hInst,\r
+                   HINSTANCE hPrev,\r
+                   LPSTR     lpCmdLine,\r
+                   int       nCmdShow);\r
+\r
+static HCONV openConversation (void);\r
+static void closeConversation (HCONV hConv);\r
+static int doFile (HCONV hConv, LPSTR lpszFileName1, LPSTR lpszFileName2);\r
+static int parseCommandLine (HCONV hConv, LPSTR lpszCommandLine);\r
+\r
+/* -- Function Definitions -------------------------------------------------- */\r
+\r
+/*\r
+ * Name    : ddeCallback\r
+ * Function: Gets called by DDEML.\r
+ *\r
+ */\r
+\r
+HDDEDATA CALLBACK\r
+ddeCallback (UINT uType, UINT uFmt, HCONV hconv,\r
+            HSZ hsz1, HSZ hsz2, HDDEDATA hdata,\r
+            DWORD dwData1, DWORD dwData2)\r
+{\r
+  return (HDDEDATA) NULL;\r
+}\r
+\r
+/*\r
+ * Name    : WinMain\r
+ * Function: The program's entry point function.\r
+ *\r
+ */\r
+\r
+int WINAPI\r
+WinMain (HINSTANCE hInst,\r
+        HINSTANCE hPrev,\r
+        LPSTR     lpCmdLine,\r
+        int       nCmdShow)\r
+{\r
+  HCONV hConv;\r
+  int   ret = 0;\r
+  UINT  uiRet;\r
+  \r
+  /* Initialise the DDEML library */\r
+  uiRet = DdeInitialize (&idInst,\r
+                        (PFNCALLBACK) ddeCallback,\r
+                        APPCMD_CLIENTONLY\r
+                        |CBF_FAIL_ALLSVRXACTIONS,\r
+                        0);\r
+\r
+  if (uiRet != DMLERR_NO_ERROR)\r
+    {\r
+      MessageBox (NULL, "Could not initialise DDE management library.",\r
+                 "winclient", MB_ICONEXCLAMATION | MB_OK);\r
+\r
+      return 1;\r
+    }\r
+\r
+  /* Open a conversation */\r
+  hConv = openConversation ();\r
+\r
+  if (hConv)\r
+    {\r
+      /* OK. Next, we need to parse the command line. */\r
+      ret = parseCommandLine (hConv, lpCmdLine);\r
+\r
+      /* Close the conversation */\r
+      closeConversation (hConv);\r
+    }\r
+  \r
+  DdeUninitialize (idInst);\r
+\r
+  return ret;\r
+}\r
+\r
+/*\r
+ * Name    : openConversation\r
+ * Function: Start a conversation.\r
+ *\r
+ */\r
+\r
+static HCONV\r
+openConversation (void)\r
+{\r
+  HSZ             hszService = NULL, hszTopic = NULL;\r
+  HCONV           hConv = NULL;\r
+\r
+  /* Get the application (service) name */\r
+  hszService = DdeCreateStringHandle (idInst,\r
+                                     SERVICE_NAME,\r
+                                     CP_WINANSI);\r
+\r
+  if (!hszService)\r
+    {\r
+      MessageBox (NULL, "Could not create string handle for service.",\r
+                 "winclient", MB_ICONEXCLAMATION | MB_OK);\r
+\r
+      goto error;\r
+    }\r
+  \r
+  /* Get the topic name */\r
+  hszTopic = DdeCreateStringHandle (idInst,\r
+                                   TOPIC_NAME,\r
+                                   CP_WINANSI);\r
+\r
+  if (!hszTopic)\r
+    {\r
+      MessageBox (NULL, "Could not create string handle for topic.",\r
+                 "winclient", MB_ICONEXCLAMATION | MB_OK);\r
+\r
+      goto error;\r
+    }\r
+\r
+  /* Try to connect */\r
+  hConv = DdeConnect (idInst, hszService, hszTopic, NULL);\r
+\r
+  if (!hConv)\r
+    {\r
+      STARTUPINFO         sti;\r
+      PROCESS_INFORMATION pi;\r
+      int                 n;\r
+      \r
+      /* Try to start the program */\r
+      ZeroMemory (&sti, sizeof (sti));\r
+      sti.cb = sizeof (sti);\r
+      if (!CreateProcess (NULL, PROGRAM_TO_RUN, NULL, NULL, FALSE, 0,\r
+                         NULL, NULL, &sti, &pi))\r
+       {\r
+         MessageBox (NULL, "Could not start process.",\r
+                     "winclient", MB_ICONEXCLAMATION | MB_OK);\r
+\r
+         goto error;\r
+       }\r
+\r
+      /* Wait for the process to enter an idle state */\r
+      WaitForInputIdle (pi.hProcess, MAX_INPUT_IDLE_WAIT);\r
+\r
+      /* Close the handles */\r
+      CloseHandle (pi.hThread);\r
+      CloseHandle (pi.hProcess);\r
+      \r
+      /* Try to connect */\r
+      for (n = 0; n < 5; n++)\r
+       {\r
+         Sleep (CONNECT_DELAY);\r
+         \r
+         hConv = DdeConnect (idInst, hszService, hszTopic, NULL);\r
+\r
+         if (hConv)\r
+           break;\r
+       }\r
+\r
+      if (!hConv)\r
+       {\r
+         /* Still couldn't connect. */\r
+         MessageBox (NULL, "Could not connect to DDE server.",\r
+                     "winclient", MB_ICONEXCLAMATION | MB_OK);\r
+\r
+         goto error;\r
+       }\r
+    }\r
+\r
+  /* Release the string handles */\r
+  DdeFreeStringHandle (idInst, hszService);\r
+  DdeFreeStringHandle (idInst, hszTopic);\r
+\r
+  return hConv;\r
+  \r
+ error:\r
+  if (hConv)\r
+    DdeDisconnect (hConv);\r
+  if (hszService)\r
+    DdeFreeStringHandle (idInst, hszService);\r
+  if (hszTopic)\r
+    DdeFreeStringHandle (idInst, hszTopic);\r
+\r
+  return NULL;\r
+}\r
+\r
+/*\r
+ * Name    : closeConversation\r
+ * Function: Close a conversation.\r
+ *\r
+ */\r
+\r
+static void\r
+closeConversation (HCONV hConv)\r
+{\r
+  /* Shut down */\r
+  DdeDisconnect (hConv);\r
+}\r
+\r
+/*\r
+ * Name    : doFile\r
+ * Function: Process a file.\r
+ *\r
+ */\r
+\r
+int\r
+doFile (HCONV hConv, LPSTR lpszFileName1, LPSTR lpszFileName2)\r
+{\r
+  char            *buf = NULL;\r
+  unsigned        len;\r
+  \r
+  /* Calculate the buffer length */\r
+  len = strlen (lpszFileName1) + strlen (lpszFileName2)\r
+    + strlen (COMMAND_FORMAT);\r
+  \r
+  /* Allocate a buffer */\r
+  buf = (char *) xmalloc (len);\r
+\r
+  if (!buf)\r
+    {\r
+      MessageBox (NULL, "Not enough memory.",\r
+                 "winclient", MB_ICONEXCLAMATION | MB_OK);\r
+\r
+      return 1;\r
+    }\r
+\r
+  /* Build the command */\r
+  len = wsprintf (buf, COMMAND_FORMAT, lpszFileName1, lpszFileName2);\r
+\r
+  len++;\r
+  \r
+  /* OK. We're connected. Send the message. */\r
+  DdeClientTransaction (buf, len, hConv, NULL,\r
+                       0, XTYP_EXECUTE, TRANSACTION_TIMEOUT, NULL);\r
+\r
+  free (buf);\r
+  \r
+  return 0;\r
+}\r
+\r
+/*\r
+ * Name    : getNextArg\r
+ * Function: Retrieve the next command line argument.\r
+ *\r
+ */\r
+\r
+static char *\r
+getNextArg (const char **ptr, unsigned *len)\r
+{\r
+  int        in_quotes = 0, quit = 0, all_in_quotes = 0;\r
+  const char *p = *ptr, *start;\r
+  char       *buf = NULL;\r
+  unsigned   length = 0;\r
+\r
+  /* Skip whitespace */\r
+  while (*p && isspace (*p))\r
+    p++;\r
+\r
+  /* If this is the end, return NULL */\r
+  if (!*p)\r
+    return NULL;\r
+  \r
+  /* Remember where we are */\r
+  start = p;\r
+  \r
+  /* Find the next whitespace character outside quotes */\r
+  if (*p == '"')\r
+    all_in_quotes = 1;\r
+  \r
+  while (*p && !quit)\r
+    {\r
+      switch (*p)\r
+       {\r
+       case '"':\r
+         in_quotes = 1 - in_quotes;\r
+         p++;\r
+         break;\r
+\r
+       case '\\':\r
+         if (!in_quotes)\r
+           all_in_quotes = 0;\r
+         \r
+         p++;\r
+\r
+         if (!*p)\r
+           break;\r
+\r
+         p++;\r
+         break;\r
+\r
+       default:\r
+         if (isspace (*p) && !in_quotes)\r
+           quit = 1;\r
+         else if (!in_quotes)\r
+           all_in_quotes = 0;\r
+\r
+         if (!quit)\r
+           p++;\r
+       }\r
+    }\r
+\r
+  /* Work out the length */\r
+  length = p - start;\r
+\r
+  /* Strip quotes if the argument is completely quoted */\r
+  if (all_in_quotes)\r
+    {\r
+      start++;\r
+      length -= 2;\r
+    }\r
+  \r
+  /* Copy */\r
+  buf = (char *) xmalloc (length + 1);\r
+\r
+  if (!buf)\r
+    return NULL;\r
+  \r
+  strncpy (buf, start, length);\r
+  buf[length] = '\0';\r
+\r
+  /* Return the pointer and length */\r
+  *ptr = p;\r
+  *len = length;\r
+\r
+  return buf;\r
+}\r
+\r
+/*\r
+ * Name    : parseCommandLine\r
+ * Function: Process the command line. This program accepts a list of strings\r
+ *         : (which may contain wildcards) representing filenames.\r
+ *\r
+ */\r
+\r
+int\r
+parseCommandLine (HCONV hConv, LPSTR lpszCommandLine)\r
+{\r
+  char            *fullpath, *filepart;\r
+  char            *arg;\r
+  unsigned        len, pathlen;\r
+  int             ret = 0;\r
+  HANDLE          hFindFile = NULL;\r
+  WIN32_FIND_DATA wfd;\r
+\r
+  /* Retrieve arguments */\r
+  while ((arg = getNextArg ((const char**)&lpszCommandLine, &len)) != NULL)\r
+    {\r
+      /* First find the canonical path name */\r
+      fullpath = filepart = NULL;\r
+      pathlen = GetFullPathName (arg, 0, fullpath, &filepart);\r
+\r
+      fullpath = (char *) xmalloc (pathlen);\r
+\r
+      if (!fullpath)\r
+       {\r
+         MessageBox (NULL, "Not enough memory.", "winclient",\r
+                     MB_ICONEXCLAMATION | MB_OK);\r
+         \r
+         ret = 1;\r
+         free (arg);\r
+         \r
+         break;\r
+       }\r
+\r
+      GetFullPathName (arg, pathlen, fullpath, &filepart);\r
+\r
+      /* Find the first matching file */\r
+      hFindFile = FindFirstFile (arg, &wfd);\r
+\r
+      if (hFindFile == INVALID_HANDLE_VALUE)\r
+       ret = doFile (hConv, fullpath, "");\r
+      else\r
+       {\r
+         /* Chop off the file part from the full path name */\r
+         if (filepart)\r
+           *filepart = '\0';\r
+\r
+         /* For each matching file */\r
+         do\r
+           {\r
+             /* Process it */\r
+             ret = doFile (hConv, fullpath, wfd.cFileName);\r
+\r
+             if (ret)\r
+               break;\r
+           }\r
+         while (FindNextFile (hFindFile, &wfd));\r
+\r
+         FindClose (hFindFile);\r
+       }\r
+\r
+      /* Release the path name buffers */\r
+      free (fullpath);\r
+      free (arg);\r
+\r
+      if (ret)\r
+       break;\r
+    }\r
+\r
+  return ret;\r
+}\r
+\r
+static void\r
+fatal (const char *s1, const char *s2)\r
+{\r
+  error (s1, s2);\r
+  exit (1);\r
+}\r
+\r
+/* Print error message.  `s1' is printf control string, `s2' is arg for it. */\r
+static void\r
+error (const char* s1, const char* s2)\r
+{\r
+  fprintf (stderr, "winclient: ");\r
+  fprintf (stderr, s1, s2);\r
+  fprintf (stderr, "\n");\r
+}\r
+\r
+/* Like malloc but get fatal error if memory is exhausted.  */\r
+\r
+static void *\r
+xmalloc (size_t size)\r
+{\r
+  void *result = malloc (size);\r
+  if (result == NULL)\r
+    fatal ("virtual memory exhausted", (char *) 0);\r
+  return result;\r
+}\r
diff --git a/netinstall/desktop.h b/netinstall/desktop.h
new file mode 100644 (file)
index 0000000..e37c4e8
--- /dev/null
@@ -0,0 +1,23 @@
+/* 
+   Copyright (C) 2001 Andy Piper.
+
+This file is part of XEmacs.
+
+XEmacs is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by the
+Free Software Foundation; either version 2, or (at your option) any
+later version.
+
+XEmacs is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License
+along with XEmacs; see the file COPYING.  If not, write to
+the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA.  */
+
+extern void remove_desktop_setup ();
+extern void remove_xemacs_setup ();
+extern char* find_xemacs_exe_name();