Merge from emacs-23
[bpt/emacs.git] / src / xsmfns.c
index 8a16f68..561fd5e 100644 (file)
@@ -42,9 +42,8 @@ along with GNU Emacs.  If not, see <http://www.gnu.org/licenses/>.  */
 #include "termopts.h"
 #include "xterm.h"
 
-/* The user login name.  */
-
-extern Lisp_Object Vuser_login_name;
+/* Avoid "differ in sign" warnings */
+#define SSDATA(x)  ((char *) SDATA (x))
 
 /* This is the event used when SAVE_SESSION_EVENT occurs.  */
 
@@ -88,10 +87,14 @@ Lisp_Object Vx_session_previous_id;
 /* The option to start Emacs without the splash screen when
    restarting Emacs.  */
 
-#define NOSPLASH_OPT "--no-splash"
+static char NOSPLASH_OPT[] = "--no-splash";
+
+/* The option to make Emacs start in the given directory.  */
+
+#define CHDIR_OPT "--chdir="
 
 static void
-ice_connection_closed ()
+ice_connection_closed (void)
 {
   if (ice_fd >= 0)
     delete_keyboard_wait_descriptor (ice_fd);
@@ -104,8 +107,7 @@ ice_connection_closed ()
    Otherwise returns 1 if SAVE_SESSION_EVENT is stored in buffer BUFP.  */
 
 int
-x_session_check_input (bufp)
-     struct input_event *bufp;
+x_session_check_input (struct input_event *bufp)
 {
   SELECT_TYPE read_fds;
   EMACS_TIME tmout;
@@ -148,7 +150,7 @@ x_session_check_input (bufp)
   /* Check if smc_interact_CB was called and we shall generate a
      SAVE_SESSION_EVENT.  */
   if (emacs_event.kind != NO_EVENT)
-    bcopy (&emacs_event, bufp, sizeof (struct input_event));
+    memcpy (bufp, &emacs_event, sizeof (struct input_event));
 
   return emacs_event.kind != NO_EVENT ? 1 : 0;
 }
@@ -156,7 +158,7 @@ x_session_check_input (bufp)
 /* Return non-zero if we have a connection to a session manager.  */
 
 int
-x_session_have_connection ()
+x_session_have_connection (void)
 {
   return ice_fd != -1;
 }
@@ -166,9 +168,7 @@ x_session_have_connection ()
    Then lisp code can interact with the user.  */
 
 static void
-smc_interact_CB (smcConn, clientData)
-     SmcConn smcConn;
-     SmPointer clientData;
+smc_interact_CB (SmcConn smcConn, SmPointer clientData)
 {
   doing_interact = True;
   emacs_event.kind = SAVE_SESSION_EVENT;
@@ -184,18 +184,12 @@ smc_interact_CB (smcConn, clientData)
    we do so, because we don't know what the lisp code might do.  */
 
 static void
-smc_save_yourself_CB (smcConn,
-                      clientData,
-                      saveType,
-                      shutdown,
-                      interactStyle,
-                      fast)
-     SmcConn smcConn;
-     SmPointer clientData;
-     int saveType;
-     Bool shutdown;
-     int interactStyle;
-     Bool fast;
+smc_save_yourself_CB (SmcConn smcConn,
+                     SmPointer clientData,
+                     int saveType,
+                     Bool shutdown,
+                     int interactStyle,
+                     Bool fast)
 {
 #define NR_PROPS 5
 
@@ -205,14 +199,14 @@ smc_save_yourself_CB (smcConn,
   SmPropValue values[20];
   int val_idx = 0;
   int props_idx = 0;
-
+  int i;
   char *cwd = NULL;
-  char *smid_opt;
+  char *smid_opt, *chdir_opt = NULL;
 
   /* How to start a new instance of Emacs.  */
   props[props_idx] = &prop_ptr[props_idx];
-  props[props_idx]->name = SmCloneCommand;
-  props[props_idx]->type = SmLISTofARRAY8;
+  props[props_idx]->name = xstrdup (SmCloneCommand);
+  props[props_idx]->type = xstrdup (SmLISTofARRAY8);
   props[props_idx]->num_vals = 1;
   props[props_idx]->vals = &values[val_idx++];
   props[props_idx]->vals[0].length = strlen (emacs_program);
@@ -221,19 +215,20 @@ smc_save_yourself_CB (smcConn,
 
   /* The name of the program.  */
   props[props_idx] = &prop_ptr[props_idx];
-  props[props_idx]->name = SmProgram;
-  props[props_idx]->type = SmARRAY8;
+  props[props_idx]->name = xstrdup (SmProgram);
+  props[props_idx]->type = xstrdup (SmARRAY8);
   props[props_idx]->num_vals = 1;
   props[props_idx]->vals = &values[val_idx++];
-  props[props_idx]->vals[0].length = strlen (SDATA (Vinvocation_name));
+  props[props_idx]->vals[0].length = strlen (SSDATA (Vinvocation_name));
   props[props_idx]->vals[0].value = SDATA (Vinvocation_name);
   ++props_idx;
 
-  /* How to restart Emacs (i.e.: /path/to/emacs --smid=xxxx --no-splash).  */
+  /* How to restart Emacs.  */
   props[props_idx] = &prop_ptr[props_idx];
-  props[props_idx]->name = SmRestartCommand;
-  props[props_idx]->type = SmLISTofARRAY8;
-  props[props_idx]->num_vals = 3; /* /path/to/emacs, --smid=xxx --no-splash  */
+  props[props_idx]->name = xstrdup (SmRestartCommand);
+  props[props_idx]->type = xstrdup (SmLISTofARRAY8);
+  /* /path/to/emacs, --smid=xxx --no-splash --chdir=dir */
+  props[props_idx]->num_vals = 4;
   props[props_idx]->vals = &values[val_idx];
   props[props_idx]->vals[0].length = strlen (emacs_program);
   props[props_idx]->vals[0].value = emacs_program;
@@ -247,26 +242,37 @@ smc_save_yourself_CB (smcConn,
 
   props[props_idx]->vals[2].length = strlen (NOSPLASH_OPT);
   props[props_idx]->vals[2].value = NOSPLASH_OPT;
-  val_idx += 3;
+
+  cwd = get_current_dir_name ();
+  if (cwd) 
+    {
+      chdir_opt = xmalloc (strlen (CHDIR_OPT) + strlen (cwd) + 1);
+      strcpy (chdir_opt, CHDIR_OPT);
+      strcat (chdir_opt, cwd);
+
+      props[props_idx]->vals[3].length = strlen (chdir_opt);
+      props[props_idx]->vals[3].value = chdir_opt;
+    }
+
+  val_idx += cwd ? 4 : 3;
   ++props_idx;
 
   /* User id.  */
   props[props_idx] = &prop_ptr[props_idx];
-  props[props_idx]->name = SmUserID;
-  props[props_idx]->type = SmARRAY8;
+  props[props_idx]->name = xstrdup (SmUserID);
+  props[props_idx]->type = xstrdup (SmARRAY8);
   props[props_idx]->num_vals = 1;
   props[props_idx]->vals = &values[val_idx++];
-  props[props_idx]->vals[0].length = strlen (SDATA (Vuser_login_name));
+  props[props_idx]->vals[0].length = strlen (SSDATA (Vuser_login_name));
   props[props_idx]->vals[0].value = SDATA (Vuser_login_name);
   ++props_idx;
 
-  cwd = get_current_dir_name ();
 
   if (cwd)
     {
       props[props_idx] = &prop_ptr[props_idx];
-      props[props_idx]->name = SmCurrentDirectory;
-      props[props_idx]->type = SmARRAY8;
+      props[props_idx]->name = xstrdup (SmCurrentDirectory);
+      props[props_idx]->type = xstrdup (SmARRAY8);
       props[props_idx]->num_vals = 1;
       props[props_idx]->vals = &values[val_idx++];
       props[props_idx]->vals[0].length = strlen (cwd);
@@ -278,8 +284,14 @@ smc_save_yourself_CB (smcConn,
   SmcSetProperties (smcConn, props_idx, props);
 
   xfree (smid_opt);
+  xfree (chdir_opt);
 
   free (cwd);
+  for (i = 0; i < props_idx; ++i)
+    {
+      xfree (props[i]->type);
+      xfree (props[i]->name);
+    }
 
   /* See if we maybe shall interact with the user.  */
   if (interactStyle != SmInteractStyleAny
@@ -295,9 +307,7 @@ smc_save_yourself_CB (smcConn,
 /* According to the SM specification, this shall close the connection.  */
 
 static void
-smc_die_CB (smcConn, clientData)
-     SmcConn smcConn;
-     SmPointer clientData;
+smc_die_CB (SmcConn smcConn, SmPointer clientData)
 {
   emacs_event.kind = SAVE_SESSION_EVENT;
   emacs_event.arg = Qt;
@@ -310,17 +320,13 @@ smc_die_CB (smcConn, clientData)
    even seem necessary.  */
 
 static void
-smc_save_complete_CB (smcConn, clientData)
-     SmcConn smcConn;
-     SmPointer clientData;
+smc_save_complete_CB (SmcConn smcConn, SmPointer clientData)
 {
   /* Empty */
 }
 
 static void
-smc_shutdown_cancelled_CB (smcConn, clientData)
-     SmcConn smcConn;
-     SmPointer clientData;
+smc_shutdown_cancelled_CB (SmcConn smcConn, SmPointer clientData)
 {
   /* Empty */
 }
@@ -329,47 +335,32 @@ smc_shutdown_cancelled_CB (smcConn, clientData)
    because there is some error in the session management.  */
 
 static void
-smc_error_handler (smcConn,
-                   swap,
-                   offendingMinorOpcode,
-                   offendingSequence,
-                   errorClass,
-                   severity,
-                   values)
-     SmcConn smcConn;
-     Bool swap;
-     int offendingMinorOpcode;
-     unsigned long offendingSequence;
-     int errorClass;
-     int severity;
-     SmPointer values;
+smc_error_handler (SmcConn smcConn,
+                  Bool swap,
+                  int offendingMinorOpcode,
+                  unsigned long offendingSequence,
+                  int errorClass,
+                  int severity,
+                  SmPointer values)
 {
   /* Empty  */
 }
 
 static void
-ice_error_handler (iceConn,
-                   swap,
-                   offendingMinorOpcode,
-                   offendingSequence,
-                   errorClass,
-                   severity,
-                   values)
-     IceConn iceConn;
-     Bool swap;
-     int offendingMinorOpcode;
-     unsigned long offendingSequence;
-     int errorClass;
-     int severity;
-     IcePointer values;
+ice_error_handler (IceConn iceConn,
+                  Bool swap,
+                  int offendingMinorOpcode,
+                  unsigned long offendingSequence,
+                  int errorClass,
+                  int severity,
+                  IcePointer values)
 {
   /* Empty  */
 }
 
 
 static void
-ice_io_error_handler (iceConn)
-     IceConn iceConn;
+ice_io_error_handler (IceConn iceConn)
 {
   /* Connection probably gone.  */
   ice_connection_closed ();
@@ -379,11 +370,7 @@ ice_io_error_handler (iceConn)
    uses ICE as it transport protocol.  */
 
 static void
-ice_conn_watch_CB (iceConn, clientData, opening, watchData)
-     IceConn iceConn;
-     IcePointer clientData;
-     Bool opening;
-     IcePointer *watchData;
+ice_conn_watch_CB (IceConn iceConn, IcePointer clientData, int opening, IcePointer *watchData)
 {
   if (! opening)
     {
@@ -406,10 +393,9 @@ ice_conn_watch_CB (iceConn, clientData, opening, watchData)
 
 /* Create the client leader window.  */
 
+#ifndef USE_GTK
 static void
-create_client_leader_window (dpyinfo, client_id)
-     struct x_display_info *dpyinfo;
-     char *client_id;
+create_client_leader_window (struct x_display_info *dpyinfo, char *client_id)
 {
   Window w;
   XClassHint class_hints;
@@ -425,18 +411,19 @@ create_client_leader_window (dpyinfo, client_id)
   XSetClassHint (dpyinfo->display, w, &class_hints);
   XStoreName (dpyinfo->display, w, class_hints.res_name);
 
-  sm_id = XInternAtom (dpyinfo->display, "SM_CLIENT_ID", False);
-  XChangeProperty (dpyinfo->display, w, sm_id, XA_STRING, 8, PropModeReplace,
-                   client_id, strlen (client_id));
+  XChangeProperty (dpyinfo->display, w, dpyinfo->Xatom_SM_CLIENT_ID,
+                   XA_STRING, 8, PropModeReplace,
+                   (unsigned char *)client_id, strlen (client_id));
 
   dpyinfo->client_leader_window = w;
 }
+#endif /* ! USE_GTK */
+
 
 /* Try to open a connection to the session manager.  */
 
 void
-x_session_initialize (dpyinfo)
-     struct x_display_info *dpyinfo;
+x_session_initialize (struct x_display_info *dpyinfo)
 {
 #define SM_ERRORSTRING_LEN 512
   char errorstring[SM_ERRORSTRING_LEN];
@@ -450,12 +437,12 @@ x_session_initialize (dpyinfo)
   /* Check if we where started by the session manager.  If so, we will
      have a previous id.  */
   if (! EQ (Vx_session_previous_id, Qnil) && STRINGP (Vx_session_previous_id))
-    previous_id = SDATA (Vx_session_previous_id);
+    previous_id = SSDATA (Vx_session_previous_id);
 
   /* Construct the path to the Emacs program.  */
   if (! EQ (Vinvocation_directory, Qnil))
-    name_len += strlen (SDATA (Vinvocation_directory));
-  name_len += strlen (SDATA (Vinvocation_name));
+    name_len += strlen (SSDATA (Vinvocation_directory));
+  name_len += strlen (SSDATA (Vinvocation_name));
 
   /* This malloc will not be freed, but it is only done once, and hopefully
      not very large   */
@@ -463,8 +450,8 @@ x_session_initialize (dpyinfo)
   emacs_program[0] = '\0';
 
   if (! EQ (Vinvocation_directory, Qnil))
-    strcpy (emacs_program, SDATA (Vinvocation_directory));
-  strcat (emacs_program, SDATA (Vinvocation_name));
+    strcpy (emacs_program, SSDATA (Vinvocation_directory));
+  strcat (emacs_program, SSDATA (Vinvocation_name));
 
   /* The SM protocol says all callbacks are mandatory, so set up all
      here and in the mask passed to SmcOpenConnection.  */
@@ -516,7 +503,7 @@ x_session_initialize (dpyinfo)
 /* Ensure that the session manager is not contacted again. */
 
 void
-x_session_close ()
+x_session_close (void)
 {
   ice_connection_closed ();
 }
@@ -534,8 +521,7 @@ from `emacs-session-save'  If the return value is non-nil the session manager
 is told to abort the window system shutdown.
 
 Do not call this function yourself. */)
-     (event)
-     Lisp_Object event;
+  (Lisp_Object event)
 {
   int kill_emacs = CONSP (event) && CONSP (XCDR (event))
     && EQ (Qt, XCAR (XCDR (event)));
@@ -573,7 +559,7 @@ Do not call this function yourself. */)
                            Initialization
  ***********************************************************************/
 void
-syms_of_xsmfns ()
+syms_of_xsmfns (void)
 {
   DEFVAR_LISP ("x-session-id", &Vx_session_id,
     doc: /* The session id Emacs got from the session manager for this session.