Fix dttypes for BSD systems
[oweals/cde.git] / cde / programs / dtwm / WmIPC.c
1 /*
2  * CDE - Common Desktop Environment
3  *
4  * Copyright (c) 1993-2012, The Open Group. All rights reserved.
5  *
6  * These libraries and programs are free software; you can
7  * redistribute them and/or modify them under the terms of the GNU
8  * Lesser General Public License as published by the Free Software
9  * Foundation; either version 2 of the License, or (at your option)
10  * any later version.
11  *
12  * These libraries and programs are distributed in the hope that
13  * they will be useful, but WITHOUT ANY WARRANTY; without even the
14  * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
15  * PURPOSE. See the GNU Lesser General Public License for more
16  * details.
17  *
18  * You should have received a copy of the GNU Lesser General Public
19  * License along with these librararies and programs; if not, write
20  * to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
21  * Floor, Boston, MA 02110-1301 USA
22  */
23 /* $TOG: WmIPC.c /main/11 1999/09/20 15:17:25 mgreess $ */
24 /* 
25  * (c) Copyright 1997, The Open Group 
26  */
27 /* 
28  * (c) Copyright 1987, 1988, 1989, 1990, 1992, 1993 HEWLETT-PACKARD COMPANY 
29  * ALL RIGHTS RESERVED 
30 */ 
31 #ifdef REV_INFO
32 #ifndef lint
33 static char rcsid[] = ""
34 #endif
35 #endif
36
37 /*
38  * Included Files:
39  */
40 #include "WmGlobal.h"
41 #include "WmProtocol.h"
42 #include <Xm/XmAll.h>
43 #include <Dt/Dt.h>
44 #include <Dt/DtP.h>
45 #include <Dt/Action.h>
46 #include <Dt/WsmM.h>
47 #include <Dt/IndicatorM.h>
48 #include <Dt/UserMsg.h>
49 #include <Dt/Icon.h>
50
51 #include "WmBackdrop.h"
52 #include "WmError.h"
53 #include "WmFunction.h"
54 #include "WmWrkspace.h"
55 #include "WmIPC.h"
56 #include "WmXSMP.h"
57 #include "WmPanelP.h"
58 #include "DataBaseLoad.h"
59
60
61 /*
62  * include extern functions and definitions
63  */
64
65 extern void UpdateFileTypeControlFields ( void );
66 extern WmScreenData * GetScreenForWindow (Window);
67
68 static void ToolTalkError(Widget, char*, Tt_status);
69
70
71 /*
72  *   data for the "DT screen"
73  */
74
75
76 /*
77  * globals
78  */
79 Const char *szWM_TOOL_CLASS = DtWM_TOOL_CLASS;
80
81
82 \f
83 /******************************<->*************************************
84  *
85  *  dtInitialize (char * program_name, XtAppContext appContext)
86  *
87  *  Description:
88  *  -----------
89  *  Initialize the messaging mechanism
90  *
91  *  Inputs:
92  *  ------
93  *  program_name - argv[0]
94  *  appContext   - used throughout the WM
95  *
96  *  Outputs:
97  *  -------
98  *
99  *  Comments:
100  *  --------
101  *
102  ******************************<->***********************************/
103 void 
104 dtInitialize(
105         char *program_name,
106         XtAppContext appContext )
107 {
108     
109     (void) DtAppInitialize(appContext, DISPLAY1, wmGD.topLevelW1, 
110                                 program_name, (char *)szWM_TOOL_CLASS);
111
112     /* 
113      * Load action definitions from the action database.
114      */
115 #ifdef DT_PERFORMANCE
116 _DtPerfChkpntMsgSend("Begin action database load");
117 #endif
118
119     DtDbLoad(); 
120
121 #ifdef DT_PERFORMANCE
122 _DtPerfChkpntMsgSend("End   action database load");
123 #endif
124
125 } /* END OF FUNCTION dtInitialize */
126
127 /******************************<->*************************************
128  *
129  *  dtInitializeMessaging (Widget)
130  *
131  *  Description:
132  *  -----------
133  *  Initialize the messaging mechanisms
134  *
135  *  Inputs:
136  *  ------
137  *
138  *  Outputs:
139  *  -------
140  *
141  *  Comments:
142  *  --------
143  *
144  ******************************<->***********************************/
145
146 void
147 dtInitializeMessaging(Widget toplevel)
148 {
149     int                 i;
150     WmScreenData *      pSD;
151     String              sName;
152
153     Tt_status           status;
154     Tt_pattern          notice_pattern, request_pattern;
155     char                *default_session;
156
157     int                 fd;
158     char                *procId;
159     char                *errfmt;
160
161     Tt_callback_action NoticeMsgCB(
162         Tt_message m,
163         Tt_pattern p);
164     Tt_callback_action RequestMsgCB(
165         Tt_message m,
166         Tt_pattern p);
167
168     /*
169      * Makef sure we have a ToolTalk connection
170      */
171     procId = tt_open();
172     status = tt_ptr_error(procId);
173     if (status != TT_OK) {
174         errfmt =
175           GETMESSAGE(2, 2, "Could not connect to ToolTalk:\n%s\n");
176         ToolTalkError(toplevel, errfmt, status);
177         return;
178     }
179     fd = tt_fd();
180     status = tt_int_error(fd);
181     if (status == TT_OK) {
182         XtAppAddInput(XtWidgetToApplicationContext(wmGD.topLevelW), fd,
183                 (XtPointer)XtInputReadMask, tttk_Xt_input_handler, procId);
184     } else {
185         ToolTalkError(toplevel, "tt_fd()", status);
186     }
187
188
189     default_session = tt_default_session();
190     status = tt_ptr_error(default_session);
191     if (status != TT_OK) {
192         GETMESSAGE(2, 4, "Could not get default ToolTalk session:\n%s\n");
193         ToolTalkError(toplevel, errfmt, status);
194         return;
195     }
196
197     errfmt = GETMESSAGE(2, 5, "Error constructing ToolTalk pattern:\n%s\n");
198     notice_pattern = tt_pattern_create();
199     status = tt_ptr_error(notice_pattern);
200     if (status != TT_OK) {
201         ToolTalkError(toplevel, errfmt, status);
202         return;
203     }
204     request_pattern = tt_pattern_create();
205     status = tt_ptr_error(request_pattern);
206     if (status != TT_OK) {
207         ToolTalkError(toplevel, errfmt, status);
208         return;
209     }
210
211     status = tt_pattern_category_set(notice_pattern, TT_OBSERVE);
212     if (status != TT_OK) {
213         ToolTalkError(toplevel, errfmt, status);
214         return;
215     }
216     status = tt_pattern_category_set(request_pattern, TT_HANDLE);
217     if (status != TT_OK) {
218         ToolTalkError(toplevel, errfmt, status);
219         return;
220     }
221     status = tt_pattern_scope_add(notice_pattern, TT_SESSION);
222     if (status != TT_OK) {
223         ToolTalkError(toplevel, errfmt, status);
224         return;
225     }
226     status = tt_pattern_scope_add(request_pattern, TT_SESSION);
227     if (status != TT_OK) {
228         ToolTalkError(toplevel, errfmt, status);
229         return;
230     }
231     status = tt_pattern_session_add(notice_pattern, default_session);
232     if (status != TT_OK) {
233         ToolTalkError(toplevel, errfmt, status);
234         return;
235     }
236     status = tt_pattern_session_add(request_pattern, default_session);
237     if (status != TT_OK) {
238         ToolTalkError(toplevel, errfmt, status);
239         return;
240     }
241     tt_free( default_session );
242     status = tt_pattern_class_add(notice_pattern, TT_NOTICE);
243     if (status != TT_OK) {
244         ToolTalkError(toplevel, errfmt, status);
245         return;
246     }
247     status = tt_pattern_state_add(notice_pattern, TT_SENT);
248     if (status != TT_OK) {
249         ToolTalkError(toplevel, errfmt, status);
250         return;
251     }
252     status = tt_pattern_class_add(request_pattern, TT_REQUEST);
253     if (status != TT_OK) {
254         ToolTalkError(toplevel, errfmt, status);
255         return;
256     }
257     status = tt_pattern_state_add(request_pattern, TT_SENT);
258     if (status != TT_OK) {
259         ToolTalkError(toplevel, errfmt, status);
260         return;
261     }
262
263
264     /*
265      * Ops handled by the notice_pattern
266      */
267     status = tt_pattern_op_add(notice_pattern, "DtActivity_Beginning");
268     if (status != TT_OK) {
269         ToolTalkError(toplevel, errfmt, status);
270         return;
271     }
272     status = tt_pattern_op_add(notice_pattern, "DtActivity_Began");
273     if (status != TT_OK) {
274         ToolTalkError(toplevel, errfmt, status);
275         return;
276     }
277     status = tt_pattern_op_add(notice_pattern, "DtTypes_Reloaded");
278     if (status != TT_OK) {
279         ToolTalkError(toplevel, errfmt, status);
280         return;
281     }
282
283     /*
284      * Ops handled by the request_pattern
285      */
286     status = tt_pattern_op_add(request_pattern, "DtPanel_Restore");
287     if (status != TT_OK) {
288         ToolTalkError(toplevel, errfmt, status);
289         return;
290     }
291     status = tt_pattern_op_add(request_pattern, "DtWorkspace_SetCurrent");
292     if (status != TT_OK) {
293         ToolTalkError(toplevel, errfmt, status);
294         return;
295     }
296     status = tt_pattern_op_add(request_pattern, "DtWorkspace_Title_Set");
297     if (status != TT_OK) {
298         ToolTalkError(toplevel, errfmt, status);
299         return;
300     }
301     status = tt_pattern_op_add(request_pattern, "DtWorkspace_Add");
302     if (status != TT_OK) {
303         ToolTalkError(toplevel, errfmt, status);
304         return;
305     }
306     status = tt_pattern_op_add(request_pattern, "DtWorkspace_Delete");
307     if (status != TT_OK) {
308         ToolTalkError(toplevel, errfmt, status);
309         return;
310     }
311     status = tt_pattern_op_add(request_pattern, "GetWsmClients");
312     if (status != TT_OK) {
313         ToolTalkError(toplevel, errfmt, status);
314         return;
315     }
316
317     /*
318      * Register callback for the notice_pattern
319      */
320     status = tt_pattern_callback_add(notice_pattern, NoticeMsgCB);
321     if (status != TT_OK) {
322         ToolTalkError(toplevel, errfmt, status);
323         return;
324     }
325
326     /*
327      * Register callback for the request_pattern
328      */
329     status = tt_pattern_callback_add(request_pattern, RequestMsgCB);
330     if (status != TT_OK) {
331         ToolTalkError(toplevel, errfmt, status);
332         return;
333     }
334
335     status = tt_pattern_register(notice_pattern);
336     if (status != TT_OK) {
337         ToolTalkError(toplevel, errfmt, status);
338         return;
339     }
340     status = tt_pattern_register(request_pattern);
341     if (status != TT_OK) {
342         ToolTalkError(toplevel, errfmt, status);
343         return;
344     }
345
346 } /* END OF FUNCTION dtInitializeMessaging */
347
348 \f
349 /******************************<->*************************************
350  *
351  *  dtCloseIPC ()
352  *
353  *  Description:
354  *  -----------
355  *  Shuts down the messaging mechanism
356  *
357  *  Inputs:
358  *  ------
359  *
360  *  Outputs:
361  *  -------
362  *
363  *  Comments:
364  *  --------
365  *  Should be done before exiting
366  *
367  ******************************<->***********************************/
368 void 
369 dtCloseIPC( void )
370 {
371 } /* END OF FUNCTION dtCloseIPC */
372
373
374 \f
375 /******************************<->*************************************
376  *  
377  * void dtReadyNotification()
378  *  
379  *  Description:
380  *  -----------
381  *  Tells the world that we're up and ready.
382  *
383  *  Inputs:
384  *  ------
385  * 
386  *  Outputs:
387  *  -------
388  *
389  *  Comments:
390  *  --------
391  *  Invoked as the fitting culmination of dtwm initialization
392  *
393  ******************************<->***********************************/
394 void 
395 dtReadyNotification( void )
396 {
397     SendClientMsg( wmGD.dtSmWindow,
398                   (long) wmGD.xa_DT_SM_WM_PROTOCOL,
399                   (long) wmGD.xa_DT_WM_READY,
400                   CurrentTime, NULL, 0);
401
402 } /* END OF FUNCTION dtReadyNotification */
403
404 \f
405 /******************************<->*************************************
406  *
407  *  WmStopWaiting ()
408  *
409  *  Description:
410  *  -----------
411  *  This is called to turn off "system busy" activity
412  *
413  *  Inputs:
414  *  ------
415  * 
416  *  Outputs:
417  *  -------
418  *  None
419  *
420  *  Comments:
421  *  ---------
422  *  This routine relies on two globals, blinkerPCW and dtSD,
423  *  on the major assumptions that:
424  *     - there is just one DT Screen, with the front panel enabled
425  *     - there is just one dtwmbusy control in that front panel
426  ******************************<->***********************************/
427 void 
428 WmStopWaiting( void )
429 {
430 #ifdef PANELIST 
431      if (wmGD.dtSD)
432      {
433          WmFrontPanelSetBusy (False);
434      }
435 #endif /* PANELIST */
436 } /* END OF FUNCTION WmStopWaiting */
437
438
439 \f
440 /******************************<->*************************************
441  *
442  *  dtSendWorkspaceModifyNotification ()
443  *
444  *  Description:
445  *  -----------
446  *  This is called to announce that the workspace set has been
447  *  modified
448  *
449  *  Inputs:
450  *  ------
451  *  pSD         - pointer to screen data
452  *  aWs         - id of workspace just modified
453  *  iType       - type of modification
454  * 
455  *  Outputs:
456  *  -------
457  *  None
458  *
459  *  Comments:
460  *  ---------
461  *  Sends the message:
462  *
463  *    "MODIFY_WORKSPACE"  "<atom_for_wsname>" "<modify_type>"
464  *
465  *    <modify_type> is one of:
466  *                              ADD
467  *                              DELETE
468  *                              BACKDROP
469  *                              TITLE
470  ******************************<->***********************************/
471 void
472 dtSendWorkspaceModifyNotification(
473         WmScreenData *pSD,
474         Atom aWs,
475         int iType)
476 {
477     char        sNum[40];
478     char        pch[40];
479     char        pchType[40];
480     Tt_message  msg;
481     Tt_status   status;
482
483     msg = tt_pnotice_create(TT_SESSION, "DtWorkspace_Modified");
484     status = tt_ptr_error(msg);
485     if (status != TT_OK) {
486         return;
487     }
488     sprintf(sNum, "%d", pSD->screen);
489     status = tt_message_arg_add(msg, TT_IN, Tttk_string, sNum);
490     if (status != TT_OK) {
491         return;
492     }
493     sprintf (pch, "%ld", aWs);
494     status = tt_message_arg_add(msg, TT_IN, Tttk_string, pch);
495     if (status != TT_OK) {
496         return;
497     }
498     sprintf (pchType, "%d", iType);
499     status = tt_message_arg_add(msg, TT_IN, Tttk_string, pchType);
500     if (status != TT_OK) {
501         return;
502     }
503     status = tt_message_send(msg);
504     if (status != TT_OK) {
505         return;
506     }
507     tt_message_destroy(msg);
508 }
509
510 \f
511 /******************************<->*************************************
512  *
513  *  dtSendMarqueeSelectionNotification ()
514  *
515  *  Description:
516  *  -----------
517  *  This is called to announce marquee selection state
518  *
519  *  Inputs:
520  *  ------
521  *  pSD         - pointer to screen data
522  *  type        - id of workspace just modified
523  *  x           - x position of UL corner of rectangle
524  *  y           - y position of UL corner of rectangle
525  *  width       - width of rectangle
526  *  heigth      - height of rectangle
527  * 
528  *  Outputs:
529  *  -------
530  *  None
531  *
532  *  Comments:
533  *  ---------
534  *  Sends the message:
535  *
536  *    "MARQUEE_SELECTION"  "<type>" "<x>" "<y>" "<width>" "<height>"
537  *
538  *    <modify_type> is one of:
539  *                              BEGIN
540  *                              END
541  *                              CONTINUE
542  *                              CANCEL
543  ******************************<->***********************************/
544 void
545 dtSendMarqueeSelectionNotification(
546         WmScreenData *pSD,
547         int     type,
548         Position x,
549         Position y,
550         Dimension width,
551         Dimension height)
552 {
553     Tt_message  msg;
554     Tt_status   status;
555     char        sNum[40];
556
557     msg = tt_pnotice_create(TT_SESSION, "DtMarquee_Selection");
558     status = tt_ptr_error(msg);
559     if (status != TT_OK) {
560         return;
561     }
562
563     sprintf(sNum, "%d", pSD->screen);
564     status = tt_message_arg_add(msg, TT_IN, Tttk_string, sNum);
565     if (status != TT_OK) {
566         return;
567     }
568     if (tt_message_arg_add(msg, TT_IN, "integer", NULL) != TT_OK) {
569         return;
570     }
571     if (tt_message_arg_ival_set(msg, 1, type) != TT_OK) {
572         return;
573     }
574     if (tt_message_arg_add(msg, TT_IN, "integer", NULL) != TT_OK) {
575         return;
576     }
577     if (tt_message_arg_ival_set(msg, 2, x) != TT_OK) {
578         return;
579     }
580     if (tt_message_arg_add(msg, TT_IN, "integer", NULL) != TT_OK) {
581         return;
582     }
583     if (tt_message_arg_ival_set(msg, 3, y) != TT_OK) {
584         return;
585     }
586     if (tt_message_arg_add(msg, TT_IN, "integer", NULL) != TT_OK) {
587         return;
588     }
589     if (tt_message_arg_ival_set(msg, 4, width) != TT_OK) {
590         return;
591     }
592     if (tt_message_arg_add(msg, TT_IN, "integer", NULL) != TT_OK) {
593         return;
594     }
595     if (tt_message_arg_ival_set(msg, 5, height) != TT_OK) {
596         return;
597     }
598     status = tt_message_send(msg);
599     if (status != TT_OK) {
600         return;
601     }
602     tt_message_destroy(msg);
603 }
604
605 \f
606 /******************************<->*************************************
607  *
608  *  NoticeMsgCB ()
609  *
610  *
611  *  Description:
612  *  -----------
613  *  This is called to handle busy and stopbusy message
614  *
615  *  Inputs:
616  *  ------
617  *  m = ToolTalk message
618  *  p = ToolTalk pattern
619  * 
620  *  Outputs:
621  *  -------
622  *  TT_CALLBACK_PROCESSED
623  *  TT_CALLBACK_CINTINUE
624  *
625  *  Comments:
626  *  ---------
627  ******************************<->***********************************/
628 Tt_callback_action
629 NoticeMsgCB(Tt_message m, Tt_pattern p)
630 {
631     char        *op;
632     Tt_status   status;
633
634     if (tt_message_state(m) != TT_SENT) {
635         return TT_CALLBACK_CONTINUE;
636     }
637     op = tt_message_op(m);
638     status = tt_ptr_error(op);
639     if (status != TT_OK) {
640         return TT_CALLBACK_CONTINUE;
641     }
642     if (!strcmp(op, "DtActivity_Began")) {
643         WmStopWaiting();
644
645         /* CDExc21081 */
646         tt_message_destroy(m);
647     }
648 #ifdef PANELIST 
649     else if (!strcmp(op, "DtActivity_Beginning")) {
650         if (wmGD.dtSD) {
651            WmFrontPanelSetBusy (True);
652         }
653
654         /* CDExc21081 */
655         tt_message_destroy(m);
656     }
657 #endif /* PANELIST */
658     else if (!strcmp(op, "DtTypes_Reloaded")) {
659         /*
660          * Blink busy light during reload.
661          */
662         WmFrontPanelSetBusy (True);
663
664         /* 
665          * Load action definitions from the action database.
666          */
667         DtDbLoad(); 
668
669         UpdateFileTypeControlFields();
670
671         /*
672          * Turn off busy light.
673          */
674         WmFrontPanelSetBusy (False);
675
676         /* CDExc21081 */
677         tt_message_destroy(m);
678     }
679
680     tt_free(op);
681     return TT_CALLBACK_PROCESSED;
682
683 } /* END OF FUNCTION NoticeMsgCB */
684
685 \f
686 /******************************<->*************************************
687  *
688  *  RequestMsgCB ()
689  *
690  *
691  *  Description:
692  *  -----------
693  *  This is called to handle busy and stopbusy message
694  *
695  *  Inputs:
696  *  ------
697  *  m = ToolTalk message
698  *  p = ToolTalk pattern
699  * 
700  *  Outputs:
701  *  -------
702  *  TT_CALLBACK_PROCESSED
703  *  TT_CALLBACK_CINTINUE
704  *
705  *  Comments:
706  *  ---------
707  ******************************<->***********************************/
708 Tt_callback_action
709 RequestMsgCB(Tt_message m, Tt_pattern p)
710 {
711     char        *op;
712     Tt_status   status;
713
714     int                 screen_num;
715     WmScreenData        *pSD;
716     WmWorkspaceData     *pWS = NULL;
717     Atom                aWs;
718     char                *pch;
719     String              sName;
720
721     if (tt_message_state(m) != TT_SENT) {
722         return TT_CALLBACK_CONTINUE;
723     }
724     op = tt_message_op(m);
725     status = tt_ptr_error(op);
726     if (status != TT_OK) {
727         return TT_CALLBACK_CONTINUE;
728     }
729     if (!strcmp(op, "DtPanel_Restore")) {
730         tt_message_reply(m);
731         tt_message_destroy(m);
732
733         SessionDeleteAll();
734
735         F_Restart( DTWM_REQP_NO_CONFIRM, NULL, NULL );
736     }
737     else if (!strcmp(op, "DtWorkspace_SetCurrent")) {
738         /*
739          * 1st arg: integer, screen number
740          * 2nd arg: string, atom of workspace name
741          */
742
743         /* get the first arg from the message */
744         tt_message_arg_ival(m, 0, &screen_num);
745         pSD = &wmGD.Screens[screen_num];
746
747         /* get the second arg from the message */
748         pch = tt_message_arg_val(m, 1);
749
750         /* retrieve the selected workspace */
751         aWs = strtoul (pch, (char **) NULL, 0);
752         tt_free( pch );
753         pWS = GetWorkspaceData (pSD, aWs);
754
755         if (pWS) {
756             ChangeToWorkspace (pWS);
757         }
758
759         tt_message_reply(m);
760         tt_message_destroy(m);
761     }
762     else if (!strcmp(op, "DtWorkspace_Title_Set")) {
763         /*
764          * 1st arg: integer, screen number
765          * 2nd arg: string, atom of workspace name
766          * 3rd arg: string, new name for the workspace
767          */
768
769         /* get the first arg from the message */
770         tt_message_arg_ival(m, 0, &screen_num);
771         pSD = &wmGD.Screens[screen_num];
772
773         /* get the second arg from the message */
774         pch = tt_message_arg_val(m, 1);
775
776         /* retrieve the selected workspace */
777         aWs = strtoul (pch, (char **) NULL, 0);
778         tt_free( pch );
779         pWS = GetWorkspaceData (pSD, aWs);
780
781         /* get the third arg from the message */
782         pch = tt_message_arg_val(m, 2);
783
784         if (pWS) {
785             ChangeWorkspaceTitle (pWS, pch);
786         }
787         tt_free( pch );
788
789         tt_message_reply(m);
790         tt_message_destroy(m);
791     }
792     else if (!strcmp(op, "DtWorkspace_Add")) {
793         /*
794          * 1st arg: string, user-visible title of the workspace
795          */
796         pch = tt_message_arg_val(m, 0);
797
798         F_CreateWorkspace( pch, NULL, NULL );
799         tt_free( pch );
800
801         tt_message_reply(m);
802         tt_message_destroy(m);
803     }
804     else if (!strcmp(op, "DtWorkspace_Delete")) {
805         /*
806          * 1st arg: string, atom of workspace name
807          */
808         pch = tt_message_arg_val(m, 0);
809
810         /* retrieve the selected workspace */
811         aWs = strtoul (pch, (char **) NULL, 0);
812         tt_free( pch );
813         sName = (String) XmGetAtomName (DISPLAY1, aWs);
814
815         F_DeleteWorkspace( sName, NULL, NULL );
816
817         tt_message_reply(m);
818         tt_message_destroy(m);
819
820         XtFree(sName);
821     }
822     else if (!strcmp(op, "GetWsmClients")) {
823         /* No TT_IN args. */
824         ClientData **clients;
825         int nClients;
826
827         if (GetSmClientIdClientList(&clients, &nClients))
828         {
829             char *clientIds = (char *)NULL;
830             int *clientWorkspaces = (int *)NULL;
831             int clientIdLen = 0;
832
833             SortClientListByWorkspace(clients, nClients);
834
835             tt_message_arg_ival_set(m, 0, nClients);
836             if (nClients > 0)
837             {
838                 int i;
839                 char *ptr;
840                 ClientData *pCD;
841
842                 clientIdLen = 0;
843                 for (i = 0; i < nClients; i++)
844                     clientIdLen += strlen(clients[i]->smClientID) + 1;
845
846                 if (((clientIds =
847                       (char *)XtMalloc(clientIdLen * sizeof(char)))
848                      == (char *)NULL) ||
849                     ((clientWorkspaces =
850                       (int *)XtMalloc(nClients * sizeof(int)))
851                      == (int *)NULL))
852                 {
853                     if (clientIds != (char *)NULL)
854                         XtFree(clientIds);
855
856                     /* LATER - Right way to handle errors? */
857                     tt_message_fail(m);
858                     tt_message_destroy(m);
859                     tt_free(op);
860                     return TT_CALLBACK_PROCESSED;
861                 }
862                 else
863                 {
864                     for (i = 0, ptr = clientIds;
865                          i < nClients;
866                          ptr += strlen(pCD->smClientID) + 1, i++)
867                     {
868                         pCD = clients[i];
869                         strcpy(ptr, pCD->smClientID);
870                         clientWorkspaces[i] =
871 #ifdef WSM
872                             pCD->pWsList[pCD->currentWsc].wsID;
873 #else
874                             pCD->pSD->pWS->id;
875 #endif
876                     }
877                 }
878             }
879             tt_message_arg_bval_set(m, 1, (unsigned char *)clientIds,
880                                     clientIdLen * sizeof(char));
881             tt_message_arg_bval_set(m, 2, (unsigned char *)clientWorkspaces,
882                                     nClients * sizeof(int));
883
884             if (clientIds != (char *)NULL)
885                 XtFree(clientIds);
886             if (clientWorkspaces != (int *)NULL)
887                 XtFree((char *)clientWorkspaces);
888             XtFree((char *)clients);
889         }
890
891         tt_message_reply(m);
892         tt_message_destroy(m);
893     } else {
894         tt_free( op );
895         return TT_CALLBACK_CONTINUE;
896     }
897
898     tt_free(op);
899     return TT_CALLBACK_PROCESSED;
900
901 } /* END OF FUNCTION RequestMsgCB */
902
903
904 \f
905 /******************************<->*************************************
906  *
907  *  ToolTalkError ()
908  *
909  *
910  *  Description:
911  *  -----------
912  *
913  *  Inputs:
914  *  ------
915  * 
916  *  Outputs:
917  *  -------
918  *
919  *  Comments:
920  *  ---------
921  ******************************<->***********************************/
922 #define GETXMSTRING(s, m, d)    XmStringCreateLocalized(GETMESSAGE(s,m,d))
923
924 static void
925 OKCB (Widget dialog, XtPointer client_data, XtPointer call_data)
926 {
927     XtUnmanageChild((Widget) client_data);
928 }
929
930 static void
931 ToolTalkError(Widget parent, char *errfmt, Tt_status status)
932 {
933     Arg          args[10];
934     Widget       dialog, dialogShell;
935     char        *errmsg, *statmsg, *title;
936     XmString     xms_errmsg, xms_ok, xms_title;
937     int          n;
938
939     if (! tt_is_err(status)) return;
940
941     statmsg = tt_status_message(status);
942     errmsg = XtMalloc(strlen(errfmt) + strlen(statmsg) + 2);
943     sprintf(errmsg, errfmt, statmsg);
944
945     xms_ok = GETXMSTRING(2, 3, "OK");
946     xms_errmsg = XmStringCreateLocalized(errmsg);
947     xms_title = GETXMSTRING(2, 1, "Dtwm - Error");
948
949     n = 0;
950     XtSetArg(args[n], XmNautoUnmanage, False); n++;
951     XtSetArg(args[n], XmNokLabelString, xms_ok); n++;
952     XtSetArg(args[n], XmNdialogTitle, xms_title); n++;
953     XtSetArg(args[n], XmNmessageString, xms_errmsg); n++;
954     XtSetArg(args[n], XmNdialogStyle, XmDIALOG_FULL_APPLICATION_MODAL); n++;
955
956     dialog = XmCreateErrorDialog(parent, "IconEditorError", args, n);
957     XtAddCallback(dialog, XmNokCallback, OKCB, (XtPointer) dialog);
958     XtUnmanageChild(XmMessageBoxGetChild(dialog, XmDIALOG_CANCEL_BUTTON));
959     XtUnmanageChild(XmMessageBoxGetChild(dialog, XmDIALOG_HELP_BUTTON));
960
961     /*
962      * Disable the frame menu from dialog since we don't want the user
963      * to be able to close dialogs with the frame menu
964      */
965     dialogShell = XtParent(dialog);
966     n = 0;
967     XtSetArg(args[n], XmNmwmDecorations, MWM_DECOR_BORDER | MWM_DECOR_TITLE); n++;
968     XtSetValues(dialogShell, args, n);
969     XtManageChild(dialog);
970     XtRealizeWidget(dialogShell);
971
972     _DtSimpleError("Dtwm", DtFatalError, NULL, errmsg);
973
974     XtFree(errmsg);
975     XmStringFree(xms_ok);
976     XmStringFree(xms_errmsg);
977     XmStringFree(xms_title);
978 }
979 /****************************   eof    ***************************/