Fix typo in license headers
[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 libraries 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         errfmt = 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
242     tt_free( default_session );
243     status = tt_pattern_class_add(notice_pattern, TT_NOTICE);
244     if (status != TT_OK) {
245         ToolTalkError(toplevel, errfmt, status);
246         return;
247     }
248     status = tt_pattern_state_add(notice_pattern, TT_SENT);
249     if (status != TT_OK) {
250         ToolTalkError(toplevel, errfmt, status);
251         return;
252     }
253     status = tt_pattern_class_add(request_pattern, TT_REQUEST);
254     if (status != TT_OK) {
255         ToolTalkError(toplevel, errfmt, status);
256         return;
257     }
258     status = tt_pattern_state_add(request_pattern, TT_SENT);
259     if (status != TT_OK) {
260         ToolTalkError(toplevel, errfmt, status);
261         return;
262     }
263
264
265     /*
266      * Ops handled by the notice_pattern
267      */
268     status = tt_pattern_op_add(notice_pattern, "DtActivity_Beginning");
269     if (status != TT_OK) {
270         ToolTalkError(toplevel, errfmt, status);
271         return;
272     }
273     status = tt_pattern_op_add(notice_pattern, "DtActivity_Began");
274     if (status != TT_OK) {
275         ToolTalkError(toplevel, errfmt, status);
276         return;
277     }
278     status = tt_pattern_op_add(notice_pattern, "DtTypes_Reloaded");
279     if (status != TT_OK) {
280         ToolTalkError(toplevel, errfmt, status);
281         return;
282     }
283
284     /*
285      * Ops handled by the request_pattern
286      */
287     status = tt_pattern_op_add(request_pattern, "DtPanel_Restore");
288     if (status != TT_OK) {
289         ToolTalkError(toplevel, errfmt, status);
290         return;
291     }
292     status = tt_pattern_op_add(request_pattern, "DtWorkspace_SetCurrent");
293     if (status != TT_OK) {
294         ToolTalkError(toplevel, errfmt, status);
295         return;
296     }
297     status = tt_pattern_op_add(request_pattern, "DtWorkspace_Title_Set");
298     if (status != TT_OK) {
299         ToolTalkError(toplevel, errfmt, status);
300         return;
301     }
302     status = tt_pattern_op_add(request_pattern, "DtWorkspace_Add");
303     if (status != TT_OK) {
304         ToolTalkError(toplevel, errfmt, status);
305         return;
306     }
307     status = tt_pattern_op_add(request_pattern, "DtWorkspace_Delete");
308     if (status != TT_OK) {
309         ToolTalkError(toplevel, errfmt, status);
310         return;
311     }
312     status = tt_pattern_op_add(request_pattern, "GetWsmClients");
313     if (status != TT_OK) {
314         ToolTalkError(toplevel, errfmt, status);
315         return;
316     }
317
318     /*
319      * Register callback for the notice_pattern
320      */
321     status = tt_pattern_callback_add(notice_pattern, NoticeMsgCB);
322     if (status != TT_OK) {
323         ToolTalkError(toplevel, errfmt, status);
324         return;
325     }
326
327     /*
328      * Register callback for the request_pattern
329      */
330     status = tt_pattern_callback_add(request_pattern, RequestMsgCB);
331     if (status != TT_OK) {
332         ToolTalkError(toplevel, errfmt, status);
333         return;
334     }
335
336     status = tt_pattern_register(notice_pattern);
337     if (status != TT_OK) {
338         ToolTalkError(toplevel, errfmt, status);
339         return;
340     }
341     status = tt_pattern_register(request_pattern);
342     if (status != TT_OK) {
343         ToolTalkError(toplevel, errfmt, status);
344         return;
345     }
346
347 } /* END OF FUNCTION dtInitializeMessaging */
348
349 \f
350 /******************************<->*************************************
351  *
352  *  dtCloseIPC ()
353  *
354  *  Description:
355  *  -----------
356  *  Shuts down the messaging mechanism
357  *
358  *  Inputs:
359  *  ------
360  *
361  *  Outputs:
362  *  -------
363  *
364  *  Comments:
365  *  --------
366  *  Should be done before exiting
367  *
368  ******************************<->***********************************/
369 void 
370 dtCloseIPC( void )
371 {
372 } /* END OF FUNCTION dtCloseIPC */
373
374
375 \f
376 /******************************<->*************************************
377  *  
378  * void dtReadyNotification()
379  *  
380  *  Description:
381  *  -----------
382  *  Tells the world that we're up and ready.
383  *
384  *  Inputs:
385  *  ------
386  * 
387  *  Outputs:
388  *  -------
389  *
390  *  Comments:
391  *  --------
392  *  Invoked as the fitting culmination of dtwm initialization
393  *
394  ******************************<->***********************************/
395 void 
396 dtReadyNotification( void )
397 {
398     SendClientMsg( wmGD.dtSmWindow,
399                   (long) wmGD.xa_DT_SM_WM_PROTOCOL,
400                   (long) wmGD.xa_DT_WM_READY,
401                   CurrentTime, NULL, 0);
402
403 } /* END OF FUNCTION dtReadyNotification */
404
405 \f
406 /******************************<->*************************************
407  *
408  *  WmStopWaiting ()
409  *
410  *  Description:
411  *  -----------
412  *  This is called to turn off "system busy" activity
413  *
414  *  Inputs:
415  *  ------
416  * 
417  *  Outputs:
418  *  -------
419  *  None
420  *
421  *  Comments:
422  *  ---------
423  *  This routine relies on two globals, blinkerPCW and dtSD,
424  *  on the major assumptions that:
425  *     - there is just one DT Screen, with the front panel enabled
426  *     - there is just one dtwmbusy control in that front panel
427  ******************************<->***********************************/
428 void 
429 WmStopWaiting( void )
430 {
431 #ifdef PANELIST 
432      if (wmGD.dtSD)
433      {
434          WmFrontPanelSetBusy (False);
435      }
436 #endif /* PANELIST */
437 } /* END OF FUNCTION WmStopWaiting */
438
439
440 \f
441 /******************************<->*************************************
442  *
443  *  dtSendWorkspaceModifyNotification ()
444  *
445  *  Description:
446  *  -----------
447  *  This is called to announce that the workspace set has been
448  *  modified
449  *
450  *  Inputs:
451  *  ------
452  *  pSD         - pointer to screen data
453  *  aWs         - id of workspace just modified
454  *  iType       - type of modification
455  * 
456  *  Outputs:
457  *  -------
458  *  None
459  *
460  *  Comments:
461  *  ---------
462  *  Sends the message:
463  *
464  *    "MODIFY_WORKSPACE"  "<atom_for_wsname>" "<modify_type>"
465  *
466  *    <modify_type> is one of:
467  *                              ADD
468  *                              DELETE
469  *                              BACKDROP
470  *                              TITLE
471  ******************************<->***********************************/
472 void
473 dtSendWorkspaceModifyNotification(
474         WmScreenData *pSD,
475         Atom aWs,
476         int iType)
477 {
478     char        sNum[40];
479     char        pch[40];
480     char        pchType[40];
481     Tt_message  msg;
482     Tt_status   status;
483
484     msg = tt_pnotice_create(TT_SESSION, "DtWorkspace_Modified");
485     status = tt_ptr_error(msg);
486     if (status != TT_OK) {
487         return;
488     }
489     sprintf(sNum, "%d", pSD->screen);
490     status = tt_message_arg_add(msg, TT_IN, Tttk_string, sNum);
491     if (status != TT_OK) {
492         return;
493     }
494     sprintf (pch, "%ld", aWs);
495     status = tt_message_arg_add(msg, TT_IN, Tttk_string, pch);
496     if (status != TT_OK) {
497         return;
498     }
499     sprintf (pchType, "%d", iType);
500     status = tt_message_arg_add(msg, TT_IN, Tttk_string, pchType);
501     if (status != TT_OK) {
502         return;
503     }
504     status = tt_message_send(msg);
505     if (status != TT_OK) {
506         return;
507     }
508     tt_message_destroy(msg);
509 }
510
511 \f
512 /******************************<->*************************************
513  *
514  *  dtSendMarqueeSelectionNotification ()
515  *
516  *  Description:
517  *  -----------
518  *  This is called to announce marquee selection state
519  *
520  *  Inputs:
521  *  ------
522  *  pSD         - pointer to screen data
523  *  type        - id of workspace just modified
524  *  x           - x position of UL corner of rectangle
525  *  y           - y position of UL corner of rectangle
526  *  width       - width of rectangle
527  *  heigth      - height of rectangle
528  * 
529  *  Outputs:
530  *  -------
531  *  None
532  *
533  *  Comments:
534  *  ---------
535  *  Sends the message:
536  *
537  *    "MARQUEE_SELECTION"  "<type>" "<x>" "<y>" "<width>" "<height>"
538  *
539  *    <modify_type> is one of:
540  *                              BEGIN
541  *                              END
542  *                              CONTINUE
543  *                              CANCEL
544  ******************************<->***********************************/
545 void
546 dtSendMarqueeSelectionNotification(
547         WmScreenData *pSD,
548         int     type,
549         Position x,
550         Position y,
551         Dimension width,
552         Dimension height)
553 {
554     Tt_message  msg;
555     Tt_status   status;
556     char        sNum[40];
557
558     msg = tt_pnotice_create(TT_SESSION, "DtMarquee_Selection");
559     status = tt_ptr_error(msg);
560     if (status != TT_OK) {
561         return;
562     }
563
564     sprintf(sNum, "%d", pSD->screen);
565     status = tt_message_arg_add(msg, TT_IN, Tttk_string, sNum);
566     if (status != TT_OK) {
567         return;
568     }
569     if (tt_message_arg_add(msg, TT_IN, "integer", NULL) != TT_OK) {
570         return;
571     }
572     if (tt_message_arg_ival_set(msg, 1, type) != TT_OK) {
573         return;
574     }
575     if (tt_message_arg_add(msg, TT_IN, "integer", NULL) != TT_OK) {
576         return;
577     }
578     if (tt_message_arg_ival_set(msg, 2, x) != TT_OK) {
579         return;
580     }
581     if (tt_message_arg_add(msg, TT_IN, "integer", NULL) != TT_OK) {
582         return;
583     }
584     if (tt_message_arg_ival_set(msg, 3, y) != TT_OK) {
585         return;
586     }
587     if (tt_message_arg_add(msg, TT_IN, "integer", NULL) != TT_OK) {
588         return;
589     }
590     if (tt_message_arg_ival_set(msg, 4, width) != TT_OK) {
591         return;
592     }
593     if (tt_message_arg_add(msg, TT_IN, "integer", NULL) != TT_OK) {
594         return;
595     }
596     if (tt_message_arg_ival_set(msg, 5, height) != TT_OK) {
597         return;
598     }
599     status = tt_message_send(msg);
600     if (status != TT_OK) {
601         return;
602     }
603     tt_message_destroy(msg);
604 }
605
606 \f
607 /******************************<->*************************************
608  *
609  *  NoticeMsgCB ()
610  *
611  *
612  *  Description:
613  *  -----------
614  *  This is called to handle busy and stopbusy message
615  *
616  *  Inputs:
617  *  ------
618  *  m = ToolTalk message
619  *  p = ToolTalk pattern
620  * 
621  *  Outputs:
622  *  -------
623  *  TT_CALLBACK_PROCESSED
624  *  TT_CALLBACK_CINTINUE
625  *
626  *  Comments:
627  *  ---------
628  ******************************<->***********************************/
629 Tt_callback_action
630 NoticeMsgCB(Tt_message m, Tt_pattern p)
631 {
632     char        *op;
633     Tt_status   status;
634
635     if (tt_message_state(m) != TT_SENT) {
636         return TT_CALLBACK_CONTINUE;
637     }
638     op = tt_message_op(m);
639     status = tt_ptr_error(op);
640     if (status != TT_OK) {
641         return TT_CALLBACK_CONTINUE;
642     }
643     if (!strcmp(op, "DtActivity_Began")) {
644         WmStopWaiting();
645
646         /* CDExc21081 */
647         tt_message_destroy(m);
648     }
649 #ifdef PANELIST 
650     else if (!strcmp(op, "DtActivity_Beginning")) {
651         if (wmGD.dtSD) {
652            WmFrontPanelSetBusy (True);
653         }
654
655         /* CDExc21081 */
656         tt_message_destroy(m);
657     }
658 #endif /* PANELIST */
659     else if (!strcmp(op, "DtTypes_Reloaded")) {
660         /*
661          * Blink busy light during reload.
662          */
663         WmFrontPanelSetBusy (True);
664
665         /* 
666          * Load action definitions from the action database.
667          */
668         DtDbLoad(); 
669
670         UpdateFileTypeControlFields();
671
672         /*
673          * Turn off busy light.
674          */
675         WmFrontPanelSetBusy (False);
676
677         /* CDExc21081 */
678         tt_message_destroy(m);
679     }
680
681     tt_free(op);
682     return TT_CALLBACK_PROCESSED;
683
684 } /* END OF FUNCTION NoticeMsgCB */
685
686 \f
687 /******************************<->*************************************
688  *
689  *  RequestMsgCB ()
690  *
691  *
692  *  Description:
693  *  -----------
694  *  This is called to handle busy and stopbusy message
695  *
696  *  Inputs:
697  *  ------
698  *  m = ToolTalk message
699  *  p = ToolTalk pattern
700  * 
701  *  Outputs:
702  *  -------
703  *  TT_CALLBACK_PROCESSED
704  *  TT_CALLBACK_CINTINUE
705  *
706  *  Comments:
707  *  ---------
708  ******************************<->***********************************/
709 Tt_callback_action
710 RequestMsgCB(Tt_message m, Tt_pattern p)
711 {
712     char        *op;
713     Tt_status   status;
714
715     int                 screen_num;
716     WmScreenData        *pSD;
717     WmWorkspaceData     *pWS = NULL;
718     Atom                aWs;
719     char                *pch;
720     String              sName;
721
722     if (tt_message_state(m) != TT_SENT) {
723         return TT_CALLBACK_CONTINUE;
724     }
725     op = tt_message_op(m);
726     status = tt_ptr_error(op);
727     if (status != TT_OK) {
728         return TT_CALLBACK_CONTINUE;
729     }
730     if (!strcmp(op, "DtPanel_Restore")) {
731         tt_message_reply(m);
732         tt_message_destroy(m);
733
734         SessionDeleteAll();
735
736         F_Restart( DTWM_REQP_NO_CONFIRM, NULL, NULL );
737     }
738     else if (!strcmp(op, "DtWorkspace_SetCurrent")) {
739         /*
740          * 1st arg: integer, screen number
741          * 2nd arg: string, atom of workspace name
742          */
743
744         /* get the first arg from the message */
745         tt_message_arg_ival(m, 0, &screen_num);
746         pSD = &wmGD.Screens[screen_num];
747
748         /* get the second arg from the message */
749         pch = tt_message_arg_val(m, 1);
750
751         /* retrieve the selected workspace */
752         aWs = strtoul (pch, (char **) NULL, 0);
753         tt_free( pch );
754         pWS = GetWorkspaceData (pSD, aWs);
755
756         if (pWS) {
757             ChangeToWorkspace (pWS);
758         }
759
760         tt_message_reply(m);
761         tt_message_destroy(m);
762     }
763     else if (!strcmp(op, "DtWorkspace_Title_Set")) {
764         /*
765          * 1st arg: integer, screen number
766          * 2nd arg: string, atom of workspace name
767          * 3rd arg: string, new name for the workspace
768          */
769
770         /* get the first arg from the message */
771         tt_message_arg_ival(m, 0, &screen_num);
772         pSD = &wmGD.Screens[screen_num];
773
774         /* get the second arg from the message */
775         pch = tt_message_arg_val(m, 1);
776
777         /* retrieve the selected workspace */
778         aWs = strtoul (pch, (char **) NULL, 0);
779         tt_free( pch );
780         pWS = GetWorkspaceData (pSD, aWs);
781
782         /* get the third arg from the message */
783         pch = tt_message_arg_val(m, 2);
784
785         if (pWS) {
786             ChangeWorkspaceTitle (pWS, pch);
787         }
788         tt_free( pch );
789
790         tt_message_reply(m);
791         tt_message_destroy(m);
792     }
793     else if (!strcmp(op, "DtWorkspace_Add")) {
794         /*
795          * 1st arg: string, user-visible title of the workspace
796          */
797         pch = tt_message_arg_val(m, 0);
798
799         F_CreateWorkspace( pch, NULL, NULL );
800         tt_free( pch );
801
802         tt_message_reply(m);
803         tt_message_destroy(m);
804     }
805     else if (!strcmp(op, "DtWorkspace_Delete")) {
806         /*
807          * 1st arg: string, atom of workspace name
808          */
809         pch = tt_message_arg_val(m, 0);
810
811         /* retrieve the selected workspace */
812         aWs = strtoul (pch, (char **) NULL, 0);
813         tt_free( pch );
814         sName = (String) XmGetAtomName (DISPLAY1, aWs);
815
816         F_DeleteWorkspace( sName, NULL, NULL );
817
818         tt_message_reply(m);
819         tt_message_destroy(m);
820
821         XtFree(sName);
822     }
823     else if (!strcmp(op, "GetWsmClients")) {
824         /* No TT_IN args. */
825         ClientData **clients;
826         int nClients;
827
828         if (GetSmClientIdClientList(&clients, &nClients))
829         {
830             char *clientIds = (char *)NULL;
831             int *clientWorkspaces = (int *)NULL;
832             int clientIdLen = 0;
833
834             SortClientListByWorkspace(clients, nClients);
835
836             tt_message_arg_ival_set(m, 0, nClients);
837             if (nClients > 0)
838             {
839                 int i;
840                 char *ptr;
841                 ClientData *pCD;
842
843                 clientIdLen = 0;
844                 for (i = 0; i < nClients; i++)
845                     clientIdLen += strlen(clients[i]->smClientID) + 1;
846
847                 if (((clientIds =
848                       (char *)XtMalloc(clientIdLen * sizeof(char)))
849                      == (char *)NULL) ||
850                     ((clientWorkspaces =
851                       (int *)XtMalloc(nClients * sizeof(int)))
852                      == (int *)NULL))
853                 {
854                     if (clientIds != (char *)NULL)
855                         XtFree(clientIds);
856
857                     /* LATER - Right way to handle errors? */
858                     tt_message_fail(m);
859                     tt_message_destroy(m);
860                     tt_free(op);
861                     return TT_CALLBACK_PROCESSED;
862                 }
863                 else
864                 {
865                     for (i = 0, ptr = clientIds;
866                          i < nClients;
867                          ptr += strlen(pCD->smClientID) + 1, i++)
868                     {
869                         pCD = clients[i];
870                         strcpy(ptr, pCD->smClientID);
871                         clientWorkspaces[i] =
872 #ifdef WSM
873                             pCD->pWsList[pCD->currentWsc].wsID;
874 #else
875                             pCD->pSD->pWS->id;
876 #endif
877                     }
878                 }
879             }
880             tt_message_arg_bval_set(m, 1, (unsigned char *)clientIds,
881                                     clientIdLen * sizeof(char));
882             tt_message_arg_bval_set(m, 2, (unsigned char *)clientWorkspaces,
883                                     nClients * sizeof(int));
884
885             if (clientIds != (char *)NULL)
886                 XtFree(clientIds);
887             if (clientWorkspaces != (int *)NULL)
888                 XtFree((char *)clientWorkspaces);
889             XtFree((char *)clients);
890         }
891
892         tt_message_reply(m);
893         tt_message_destroy(m);
894     } else {
895         tt_free( op );
896         return TT_CALLBACK_CONTINUE;
897     }
898
899     tt_free(op);
900     return TT_CALLBACK_PROCESSED;
901
902 } /* END OF FUNCTION RequestMsgCB */
903
904
905 \f
906 /******************************<->*************************************
907  *
908  *  ToolTalkError ()
909  *
910  *
911  *  Description:
912  *  -----------
913  *
914  *  Inputs:
915  *  ------
916  * 
917  *  Outputs:
918  *  -------
919  *
920  *  Comments:
921  *  ---------
922  ******************************<->***********************************/
923 #define GETXMSTRING(s, m, d)    XmStringCreateLocalized(GETMESSAGE(s,m,d))
924
925 static void
926 OKCB (Widget dialog, XtPointer client_data, XtPointer call_data)
927 {
928     XtUnmanageChild((Widget) client_data);
929 }
930
931 static void
932 ToolTalkError(Widget parent, char *errfmt, Tt_status status)
933 {
934     Arg          args[10];
935     Widget       dialog, dialogShell;
936     char        *errmsg, *statmsg, *title;
937     XmString     xms_errmsg, xms_ok, xms_title;
938     int          n;
939
940     if (! tt_is_err(status)) return;
941
942     statmsg = tt_status_message(status);
943     errmsg = XtMalloc(strlen(errfmt) + strlen(statmsg) + 2);
944     sprintf(errmsg, errfmt, statmsg);
945
946     xms_ok = GETXMSTRING(2, 3, "OK");
947     xms_errmsg = XmStringCreateLocalized(errmsg);
948     xms_title = GETXMSTRING(2, 1, "Dtwm - Error");
949
950     n = 0;
951     XtSetArg(args[n], XmNautoUnmanage, False); n++;
952     XtSetArg(args[n], XmNokLabelString, xms_ok); n++;
953     XtSetArg(args[n], XmNdialogTitle, xms_title); n++;
954     XtSetArg(args[n], XmNmessageString, xms_errmsg); n++;
955     XtSetArg(args[n], XmNdialogStyle, XmDIALOG_FULL_APPLICATION_MODAL); n++;
956
957     dialog = XmCreateErrorDialog(parent, "IconEditorError", args, n);
958     XtAddCallback(dialog, XmNokCallback, OKCB, (XtPointer) dialog);
959     XtUnmanageChild(XmMessageBoxGetChild(dialog, XmDIALOG_CANCEL_BUTTON));
960     XtUnmanageChild(XmMessageBoxGetChild(dialog, XmDIALOG_HELP_BUTTON));
961
962     /*
963      * Disable the frame menu from dialog since we don't want the user
964      * to be able to close dialogs with the frame menu
965      */
966     dialogShell = XtParent(dialog);
967     n = 0;
968     XtSetArg(args[n], XmNmwmDecorations, MWM_DECOR_BORDER | MWM_DECOR_TITLE); n++;
969     XtSetValues(dialogShell, args, n);
970     XtManageChild(dialog);
971     XtRealizeWidget(dialogShell);
972
973     _DtSimpleError("Dtwm", DtFatalError, NULL, errmsg);
974
975     XtFree(errmsg);
976     XmStringFree(xms_ok);
977     XmStringFree(xms_errmsg);
978     XmStringFree(xms_title);
979 }
980 /****************************   eof    ***************************/