OSDN Git Service

Initial revision
[pf3gnuchains/pf3gnuchains3x.git] / tk / mac / tkMacSend.c
1 /* 
2  * tkMacSend.c --
3  *
4  *      This file provides procedures that implement the "send"
5  *      command, allowing commands to be passed from interpreter
6  *      to interpreter.  This current implementation for the Mac
7  *      has most functionality stubed out.
8  *
9  * Copyright (c) 1989-1994 The Regents of the University of California.
10  * Copyright (c) 1994-1996 Sun Microsystems, Inc.
11  *
12  * See the file "license.terms" for information on usage and redistribution
13  * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
14  *
15  * RCS: @(#) $Id$
16  */
17
18 #include "tkPort.h"
19 #include "tkInt.h"
20
21      /* 
22       * The following structure is used to keep track of the
23       * interpreters registered by this process.
24       */
25
26 typedef struct RegisteredInterp {
27     char *name;                 /* Interpreter's name (malloc-ed). */
28     Tcl_Interp *interp;         /* Interpreter associated with
29                                  * name. */
30     TkWindow *winPtr;           /* Main window for the application. */
31     struct RegisteredInterp *nextPtr;
32     /* Next in list of names associated
33      * with interps in this process.
34      * NULL means end of list. */
35 } RegisteredInterp;
36
37 static RegisteredInterp *registry = NULL;
38 /* List of all interpreters
39  * registered by this process. */
40
41 /*
42  * A registry of all interpreters for a display is kept in a
43  * property "InterpRegistry" on the root window of the display.
44  * It is organized as a series of zero or more concatenated strings
45  * (in no particular order), each of the form
46  *      window space name '\0'
47  * where "window" is the hex id of the comm. window to use to talk
48  * to an interpreter named "name".
49  *
50  * When the registry is being manipulated by an application (e.g. to
51  * add or remove an entry), it is loaded into memory using a structure
52  * of the following type:
53  */
54
55 typedef struct NameRegistry {
56     TkDisplay *dispPtr;         /* Display from which the registry was
57                                  * read. */
58     int locked;                 /* Non-zero means that the display was
59                                  * locked when the property was read in. */
60     int modified;               /* Non-zero means that the property has
61                                  * been modified, so it needs to be written
62                                  * out when the NameRegistry is closed. */
63     unsigned long propLength;   /* Length of the property, in bytes. */
64     char *property;             /* The contents of the property.  See format
65                                  * above;  this is *not* terminated by the
66                                  * first null character.  Dynamically
67                                  * allocated. */
68     int allocedByX;             /* Non-zero means must free property with
69                                  * XFree;  zero means use ckfree. */
70 } NameRegistry;
71
72      /*
73       * When a result is being awaited from a sent command, one of
74       * the following structures is present on a list of all outstanding
75       * sent commands.  The information in the structure is used to
76       * process the result when it arrives.  You're probably wondering
77       * how there could ever be multiple outstanding sent commands.
78       * This could happen if interpreters invoke each other recursively.
79       * It's unlikely, but possible.
80       */
81
82 typedef struct PendingCommand {
83     int serial;                 /* Serial number expected in
84                                  * result. */
85     TkDisplay *dispPtr;         /* Display being used for communication. */
86     char *target;               /* Name of interpreter command is
87                                  * being sent to. */
88     Window commWindow;          /* Target's communication window. */
89     Tk_TimerToken timeout;      /* Token for timer handler used to check
90                                  * up on target during long sends. */
91     Tcl_Interp *interp;         /* Interpreter from which the send
92                                  * was invoked. */
93     int code;                   /* Tcl return code for command
94                                  * will be stored here. */
95     char *result;               /* String result for command (malloc'ed),
96                                  * or NULL. */
97     char *errorInfo;            /* Information for "errorInfo" variable,
98                                  * or NULL (malloc'ed). */
99     char *errorCode;            /* Information for "errorCode" variable,
100                                  * or NULL (malloc'ed). */
101     int gotResponse;            /* 1 means a response has been received,
102                                  * 0 means the command is still outstanding. */
103     struct PendingCommand *nextPtr;
104        /* Next in list of all outstanding
105         * commands.  NULL means end of
106         * list. */
107 } PendingCommand;
108
109 static PendingCommand *pendingCommands = NULL;
110 /* List of all commands currently
111  * being waited for. */
112
113      /*
114       * The information below is used for communication between processes
115       * during "send" commands.  Each process keeps a private window, never
116       * even mapped, with one property, "Comm".  When a command is sent to
117       * an interpreter, the command is appended to the comm property of the
118       * communication window associated with the interp's process.  Similarly,
119       * when a result is returned from a sent command, it is also appended
120       * to the comm property.
121       *
122       * Each command and each result takes the form of ASCII text.  For a
123       * command, the text consists of a zero character followed by several
124       * null-terminated ASCII strings.  The first string consists of the
125       * single letter "c".  Subsequent strings have the form "option value"
126       * where the following options are supported:
127       *
128       * -r commWindow serial
129       *
130       * This option means that a response should be sent to the window
131       * whose X identifier is "commWindow" (in hex), and the response should
132       * be identified with the serial number given by "serial" (in decimal).
133       * If this option isn't specified then the send is asynchronous and
134       * no response is sent.
135       *
136       * -n name
137       * "Name" gives the name of the application for which the command is
138       * intended.  This option must be present.
139       *
140       * -s script
141       *
142       * "Script" is the script to be executed.  This option must be present.
143       *
144       * The options may appear in any order.  The -n and -s options must be
145       * present, but -r may be omitted for asynchronous RPCs.  For compatibility
146       * with future releases that may add new features, there may be additional
147       * options present;  as long as they start with a "-" character, they will
148       * be ignored.
149       *
150       * A result also consists of a zero character followed by several null-
151       * terminated ASCII strings.  The first string consists of the single
152       * letter "r".  Subsequent strings have the form "option value" where
153       * the following options are supported:
154       *
155       * -s serial
156       *
157       * Identifies the command for which this is the result.  It is the
158       * same as the "serial" field from the -s option in the command.  This
159       * option must be present.
160       *
161       * -c code
162       *
163       * "Code" is the completion code for the script, in decimal.  If the
164       * code is omitted it defaults to TCL_OK.
165       *
166       * -r result
167       *
168       * "Result" is the result string for the script, which may be either
169       * a result or an error message.  If this field is omitted then it
170       * defaults to an empty string.
171       *
172       * -i errorInfo
173       *
174       * "ErrorInfo" gives a string with which to initialize the errorInfo
175       * variable.  This option may be omitted;  it is ignored unless the
176       * completion code is TCL_ERROR.
177       *
178       * -e errorCode
179       *
180       * "ErrorCode" gives a string with with to initialize the errorCode
181       * variable.  This option may be omitted;  it is ignored  unless the
182       * completion code is TCL_ERROR.
183       *
184       * Options may appear in any order, and only the -s option must be
185       * present.  As with commands, there may be additional options besides
186       * these;  unknown options are ignored.
187       */
188
189      /*
190       * The following variable is the serial number that was used in the
191       * last "send" command.  It is exported only for testing purposes.
192       */
193
194 int tkSendSerial = 0;
195
196      /*
197       * Maximum size property that can be read at one time by
198       * this module:
199       */
200
201 #define MAX_PROP_WORDS 100000
202
203 /*
204  * Forward declarations for procedures defined later in this file:
205  */
206
207 static int              AppendErrorProc _ANSI_ARGS_((ClientData clientData,
208                                 XErrorEvent *errorPtr));
209 static void             AppendPropCarefully _ANSI_ARGS_((Display *display,
210                                  Window window, Atom property, char *value,
211                                  int length, PendingCommand *pendingPtr));
212 static void             DeleteProc _ANSI_ARGS_((ClientData clientData));
213 static void             RegAddName _ANSI_ARGS_((NameRegistry *regPtr,
214                                 char *name, Window commWindow));
215 static void             RegClose _ANSI_ARGS_((NameRegistry *regPtr));
216 static void             RegDeleteName _ANSI_ARGS_((NameRegistry *regPtr,
217                                 char *name));
218 static Window           RegFindName _ANSI_ARGS_((NameRegistry *regPtr,
219                                 char *name));
220 static NameRegistry *   RegOpen _ANSI_ARGS_((Tcl_Interp *interp,
221                              TkWindow *winPtr, int lock));
222 static void             SendEventProc _ANSI_ARGS_((ClientData clientData,
223                                                            XEvent *eventPtr));
224 static int              SendInit _ANSI_ARGS_((Tcl_Interp *interp,
225                               TkWindow *winPtr));
226 static Bool             SendRestrictProc _ANSI_ARGS_((Display *display,
227                               XEvent *eventPtr, char *arg));
228 static int              ServerSecure _ANSI_ARGS_((TkDisplay *dispPtr));
229 static void             TimeoutProc _ANSI_ARGS_((ClientData clientData));
230 static int              ValidateName _ANSI_ARGS_((TkDisplay *dispPtr,
231                              char *name, Window commWindow, int oldOK));
232 \f
233 /*
234  *--------------------------------------------------------------
235  *
236  * Tk_SetAppName --
237  *
238  *      This procedure is called to associate an ASCII name with a Tk
239  *      application.  If the application has already been named, the
240  *      name replaces the old one.
241  *
242  * Results:
243  *      The return value is the name actually given to the application.
244  *      This will normally be the same as name, but if name was already
245  *      in use for an application then a name of the form "name #2" will
246  *      be chosen,  with a high enough number to make the name unique.
247  *
248  * Side effects:
249  *      Registration info is saved, thereby allowing the "send" command
250  *      to be used later to invoke commands in the application.  In
251  *      addition, the "send" command is created in the application's
252  *      interpreter.  The registration will be removed automatically
253  *      if the interpreter is deleted or the "send" command is removed.
254  *
255  *--------------------------------------------------------------
256  */
257
258 char *
259 Tk_SetAppName(
260     Tk_Window tkwin,            /* Token for any window in the application
261                                  * to be named:  it is just used to identify
262                                  * the application and the display.  */
263     char *name)                 /* The name that will be used to
264                                  * refer to the interpreter in later
265                                  * "send" commands.  Must be globally
266                                  * unique. */
267 {
268     return name;
269 }
270 \f
271 /*
272  *--------------------------------------------------------------
273  *
274  * Tk_SendCmd --
275  *
276  *      This procedure is invoked to process the "send" Tcl command.
277  *      See the user documentation for details on what it does.
278  *
279  * Results:
280  *      A standard Tcl result.
281  *
282  * Side effects:
283  *      See the user documentation.
284  *
285  *--------------------------------------------------------------
286  */
287
288 int
289 Tk_SendCmd(
290     ClientData clientData,              /* Information about sender (only
291                                          * dispPtr field is used). */
292     Tcl_Interp *interp,                 /* Current interpreter. */
293     int argc,                           /* Number of arguments. */
294     char **argv)                        /* Argument strings. */
295 {
296     Tcl_SetResult(interp, "Send not yet implemented", TCL_STATIC);
297     return TCL_ERROR;
298 }
299 \f
300 /*
301  *----------------------------------------------------------------------
302  *
303  * TkGetInterpNames --
304  *
305  *      This procedure is invoked to fetch a list of all the
306  *      interpreter names currently registered for the display
307  *      of a particular window.
308  *
309  * Results:
310  *      A standard Tcl return value.  Interp->result will be set
311  *      to hold a list of all the interpreter names defined for
312  *      tkwin's display.  If an error occurs, then TCL_ERROR
313  *      is returned and interp->result will hold an error message.
314  *
315  * Side effects:
316  *      None.
317  *
318  *----------------------------------------------------------------------
319  */
320
321 int
322 TkGetInterpNames(
323     Tcl_Interp *interp,         /* Interpreter for returning a result. */
324     Tk_Window tkwin)            /* Window whose display is to be used
325                                  * for the lookup. */
326 {
327     Tcl_SetResult(interp, "Send not yet implemented", TCL_STATIC);
328     return TCL_ERROR;
329 }
330 \f
331 /*
332  *--------------------------------------------------------------
333  *
334  * SendInit --
335  *
336  *      This procedure is called to initialize the
337  *      communication channels for sending commands and
338  *      receiving results.
339  *
340  * Results:
341  *      None.
342  *
343  * Side effects:
344  *      Sets up various data structures and windows.
345  *
346  *--------------------------------------------------------------
347  */
348
349 static int
350 SendInit(
351     Tcl_Interp *interp,         /* Interpreter to use for error reporting
352                                  * (no errors are ever returned, but the
353                                  * interpreter is needed anyway). */
354     TkWindow *winPtr)           /* Window that identifies the display to
355                                  * initialize. */
356 {
357     return TCL_OK;
358 }