dtcm: Coverity 88353
[oweals/cde.git] / cde / programs / dtwm / WmWrkspace.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 /* 
24  * (c) Copyright 1987,1988,1989,1990,1992,1993,1994 HEWLETT-PACKARD COMPANY 
25  * (c) Copyright 1993, 1994 International Business Machines Corp.
26  * (c) Copyright 1993, 1994 Sun Microsystems, Inc.
27  * (c) Copyright 1993, 1994 Novell, Inc.
28  * ALL RIGHTS RESERVED 
29 */ 
30
31 /*
32  * Included Files:
33  */
34
35 #include "WmGlobal.h"
36 #include "WmHelp.h"
37 #include "WmResNames.h"
38 #include "WmIPlace.h"
39 #include "WmInitWs.h"
40 #include <X11/Xutil.h>
41 #include "WmICCC.h"
42 #include <Xm/Xm.h>
43 #include <Xm/AtomMgr.h>
44 #include <Dt/DtP.h>
45 #include <Dt/WsmM.h>
46 #include <stdio.h>
47 #include "WmPanelP.h"
48 #include "WmIPC.h"              /* must be after DtP.h */
49 #include "WmPresence.h"
50
51 /* local macros */
52 #ifndef MIN
53 #define MIN(a,b) ((a)<=(b)?(a):(b))
54 #endif 
55
56 #ifndef MAX
57 #define MAX(a,b) ((a)>=(b)?(a):(b))
58 #endif 
59
60
61 /* internally defined functions */
62
63 #include "WmWrkspace.h"
64
65 /********    Static Function Declarations    ********/
66
67 static void InsureUniqueWorkspaceHints( 
68                         ClientData *pCD) ;
69
70 /********    End Static Function Declarations    ********/
71
72 /* FindDtSessionMatch () put in WmResParse.h */
73
74 /* external functions */
75 #include "WmBackdrop.h"
76 #include "WmError.h"
77 #include "WmFunction.h"
78 #include "WmIDecor.h"
79 #include "WmIconBox.h"
80 #include "WmMenu.h"
81 #include "WmProperty.h"
82 #include "WmResParse.h"
83 #include "WmWinInfo.h"
84 #include "WmWinList.h"
85 #include "WmWinState.h"
86 #include "WmXSMP.h"
87
88 /*
89  * Global Variables:
90  */
91
92 /* a dynamically allocated list of workspaces used
93  * by F_AddToAllWorkspaces
94  */
95 static int numResIDs = 0;
96 static WorkspaceID *pResIDs = NULL;
97
98
99 \f
100 /*************************************<->*************************************
101  *
102  *  ChangeToWorkspace (pNewWS)
103  *
104  *
105  *  Description:
106  *  -----------
107  *  This function changes to a new workspace.
108  *
109  *  Inputs:
110  *  ------
111  *  pNewWS =  pointer to workspace data
112  *
113  * 
114  *************************************<->***********************************/
115
116 void 
117 ChangeToWorkspace(
118         WmWorkspaceData *pNewWS )
119
120 {
121     ClientData *pCD;
122     int i;
123     WmScreenData *pSD = pNewWS->pSD;
124
125     ClientData *pWsPCD;
126     Context   wsContext = F_CONTEXT_NONE;
127
128     if (pNewWS == pSD->pActiveWS)
129         return;                         /* already there */
130
131     pSD->pLastWS = pSD->pActiveWS;
132
133     /*
134      * Go through client list of old workspace and hide windows
135      * that shouldn't appear in new workspace.
136      */
137
138     if (pSD->presence.shellW && 
139         pSD->presence.onScreen &&
140         pSD->presence.contextForClient == F_CONTEXT_ICON)
141     {
142         pWsPCD = pSD->presence.pCDforClient;
143         wsContext = pSD->presence.contextForClient;
144         HidePresenceBox (pSD, False);
145     }
146
147     for (i = 0; i < pSD->pActiveWS->numClients; i++)
148     {
149         pCD = pSD->pActiveWS->ppClients[i];
150         if (!ClientInWorkspace (pNewWS, pCD))
151         {
152            SetClientWsIndex(pCD);
153            SetClientState (pCD, pCD->clientState | UNSEEN_STATE,
154                  CurrentTime);
155         }
156     }
157
158     /*
159      * Hide active icon text label
160      */
161      if ((pSD->iconDecoration & ICON_ACTIVE_LABEL_PART) &&
162          wmGD.activeIconTextDisplayed)
163      {
164          HideActiveIconText(pSD);
165      }
166     
167     /*
168      * Unmap old icon box
169      */
170     if (pSD->useIconBox)
171     {
172         UnmapIconBoxes (pSD->pLastWS);
173     }
174     
175     /* 
176      * Set new active workspace 
177      */
178     pSD->pActiveWS = pNewWS;
179     ChangeBackdrop (pNewWS);
180
181     /*
182      * Go through client list of new workspace and show windows
183      * that should appear.
184      */
185     for (i = 0; i < pNewWS->numClients; i++)
186     {
187         pCD = pNewWS->ppClients[i];
188         SetClientWsIndex(pCD);
189         if (pCD->clientState & UNSEEN_STATE)
190         {
191             SetClientState (pCD, 
192                 (pCD->clientState & ~UNSEEN_STATE), CurrentTime);
193         }
194         if ((pCD->clientState == MINIMIZED_STATE) &&
195                          ((!pCD->pSD->useIconBox) || 
196                           (!P_ICON_BOX(pCD))))
197         {
198             XMoveWindow (DISPLAY, ICON_FRAME_WIN(pCD), 
199                         ICON_X(pCD), ICON_Y(pCD));
200         }
201
202         if (pCD->iconWindow)
203         {
204             unsigned int xOffset, yOffset;
205
206             /*
207              * Adjust for icons in the box
208              */
209
210             if (pNewWS->pIconBox)
211             {
212                 xOffset = IB_MARGIN_WIDTH;
213                 yOffset = IB_MARGIN_HEIGHT;
214             }
215             else
216             {
217                 xOffset = 0;
218                 yOffset = 0;
219             }
220
221             /*
222              * reparent icon window to frame in this workspace
223              */
224             if ((ICON_DECORATION(pCD) & ICON_IMAGE_PART) && 
225                 (pCD->iconWindow))
226             {
227                 ReparentIconWindow (pCD, xOffset, yOffset);
228             }
229         }
230     }
231
232     if ( (wsContext == F_CONTEXT_ICON &&
233           ClientInWorkspace (ACTIVE_WS, pWsPCD)) ||
234         
235          (pSD->presence.shellW && 
236           ! pSD->presence.userDismissed &&
237           ClientInWorkspace (ACTIVE_WS, pSD->presence.pCDforClient) &&
238           pSD->presence.contextForClient == F_CONTEXT_ICON))
239     {
240         ShowPresenceBox(pSD->presence.pCDforClient, F_CONTEXT_ICON);
241     }
242
243 #ifdef HP_VUE
244     /* sync up workspace info property with current state */
245     UpdateWorkspaceInfoProperty (pSD);
246 #endif /* HP_VUE */
247     SetCurrentWorkspaceProperty (pSD);
248
249     /* send workspace change broadcast message */
250     dtSendWorkspaceModifyNotification(pSD, (Atom) pNewWS->id,
251                                 DtWSM_REASON_CURRENT);
252
253 } /* END OF FUNCTION ChangeToWorkspace */
254
255 /******************************<->*************************************
256  *
257  *  ChangeWorkspaceTitle (pWS, pchTitle)
258  *
259  *  Description:
260  *  -----------
261  *  Set the title for a workspace.
262  *
263  *  Inputs:
264  *  ------
265  *  pWS = pointer to workspace data
266  *  pchTitle = new title to assign to this workspace
267  *
268  *  Outputs:
269  *  -------
270  *  none
271  * 
272  *  Comments:
273  *  --------
274  *  
275  ******************************<->***********************************/
276
277 void 
278 ChangeWorkspaceTitle(
279         WmWorkspaceData *pWS,
280         char * pchTitle)
281 {
282     XmString xmstr;
283
284     /*
285      * Convert string to XmString
286      */
287     xmstr = XmStringCreateLocalized (pchTitle);
288
289     /*
290      * Validate title ?
291      */
292
293     /*
294      * Replace title in workspace data
295      */
296     XmStringFree (pWS->title);
297     pWS->title = xmstr;
298
299     /*
300      * Save changes to resource database
301      */
302     SaveWorkspaceResources (pWS, (WM_RES_WORKSPACE_TITLE));
303
304     /*
305      * Replace old workspace in info property
306      */
307     SetWorkspaceInfoProperty (pWS);
308 #ifdef HP_VUE
309     UpdateWorkspaceInfoProperty (pWS->pSD);
310 #endif /* HP_VUE */
311     XFlush (DISPLAY);
312
313     /*
314      * Inform the world of the new workspace title
315      */
316     dtSendWorkspaceModifyNotification(pWS->pSD, pWS->id, DtWSM_REASON_TITLE);
317
318 } /* END OF FUNCTION ChangeWorkspaceTitle */
319
320 \f
321 /*************************************<->*************************************
322  *
323  *  UpdateWorkspacePresenceProperty (pCD)
324  *
325  *
326  *  Description:
327  *  -----------
328  *  This function updates the _DT_WORKSPACE_PRESENCE property for a
329  *  client window
330  *
331  *  Inputs:
332  *  ------
333  *  pCD  =  pointer to client data
334  *
335  * 
336  *************************************<->***********************************/
337
338 void 
339 UpdateWorkspacePresenceProperty(
340         ClientData *pCD )
341
342 {
343     static Atom         *pPresence = NULL;
344     static unsigned long   cPresence = 0;
345     unsigned long i;
346
347     if (wmGD.useStandardBehavior)
348     {
349         /*
350          * Don't change any workspace properties in standard behavior
351          * mode.
352          */
353         return;
354     }
355
356     if (!pPresence)
357     {
358         /* allocate initial list */
359         if (!(pPresence = (Atom *) 
360                     XtMalloc (pCD->pSD->numWorkspaces * sizeof(Atom))))
361         {
362             Warning (((char *)GETMESSAGE(76, 1, "Insufficient memory for workspace presence property")));
363         }
364         else
365         {
366             cPresence = pCD->pSD->numWorkspaces;
367         }
368     }
369
370     if (cPresence < pCD->numInhabited)
371     {
372         /* allocate bigger list */
373         if (!(pPresence = (Atom *) 
374                 XtRealloc ((char *)pPresence, pCD->numInhabited * sizeof(Atom))))
375         {
376             Warning (((char *)GETMESSAGE(76, 2, "Insufficient memory for workspace presence property")));
377         }
378         else
379         {
380             cPresence = pCD->numInhabited;
381         }
382     }
383
384     for (i = 0; (i < pCD->numInhabited) && (i < cPresence) ; i++)
385     {
386         pPresence[i] = pCD->pWsList[i].wsID;
387     }
388
389     SetWorkspacePresence (pCD->client, pPresence,
390                                 MIN(pCD->numInhabited, cPresence));
391
392 } /* END OF FUNCTION UpdateWorkspacePresenceProperty */
393
394 #ifdef HP_VUE
395 \f
396 /*************************************<->*************************************
397  *
398  *  UpdateWorkspaceInfoProperty (pSD)
399  *
400  *
401  *  Description:
402  *  -----------
403  *  This function updates the _DT_WORKSPACE_INFO property for the
404  *  screen
405  *
406  *  Inputs:
407  *  ------
408  *  pSD  =  pointer to screen data
409  *
410  * 
411  *************************************<->***********************************/
412
413 void 
414 UpdateWorkspaceInfoProperty(
415         WmScreenData *pSD )
416
417 {
418     WorkspaceInfo *pWsInfo;
419     WmWorkspaceData *pws;
420     int count;
421
422     if (wmGD.useStandardBehavior)
423     {
424         /*
425          * Don't change any workspace properties in standard behavior
426          * mode.
427          */
428         return;
429     }
430
431     if (pWsInfo = (WorkspaceInfo *) 
432                   XtMalloc (pSD->numWorkspaces * sizeof(WorkspaceInfo)))
433     {
434         /* put current workspace at top of list */
435         pWsInfo[0].workspace = pSD->pActiveWS->id;
436         pWsInfo[0].backgroundWindow = pSD->pActiveWS->backdrop.window;
437         pWsInfo[0].bg = pSD->pActiveWS->backdrop.background;
438         pWsInfo[0].fg = pSD->pActiveWS->backdrop.foreground;
439         pWsInfo[0].backdropName = pSD->pActiveWS->backdrop.nameAtom;
440
441         /* add in the rest of the workspaces */
442         pws = pSD->pWS;
443         for (count = 1; count < pSD->numWorkspaces; count++)
444         {
445             if (pWsInfo[0].workspace == pws->id)
446                 pws++;  /* already at top, skip this one */
447             
448             pWsInfo[count].workspace = pws->id;
449             pWsInfo[count].backgroundWindow = pws->backdrop.window;
450             pWsInfo[count].bg = pws->backdrop.background;
451             pWsInfo[count].fg = pws->backdrop.foreground;
452             pWsInfo[count].backdropName = pws->backdrop.nameAtom;
453             pws++;
454         }
455
456         /* set the property */
457         SetWorkspaceInfo (pSD->wmWorkspaceWin, pWsInfo,
458                                             pSD->numWorkspaces);
459
460         XtFree ((char *)pWsInfo);
461     }
462     else
463     {
464         Warning (((char *)GETMESSAGE(76, 3, "Insufficient memory to update workspace info")));
465     }
466
467 } /* END OF FUNCTION UpdateWorkspaceInfoProperty */
468 #endif /* HP_VUE */
469
470 \f
471 /*************************************<->*************************************
472  *
473  *  AddPersistentWindow (pWS)
474  *
475  *
476  *  Description:
477  *  -----------
478  *  This function adds windows that want to be in all workspaces to
479  *  the workspace passed in.
480  *
481  *  Inputs:
482  *  ------
483  *  pWS  =  pointer to workspace data
484  *
485  *  Outputs:
486  *  --------
487  * 
488  *************************************<->***********************************/
489
490 void
491 AddPersistentWindows(
492         WmWorkspaceData *pWS)
493
494 {
495     WmScreenData *pSD = pWS->pSD;
496     int i;
497     ClientListEntry *pCLE;
498
499     /*
500      * For all the windows managed for this screen, see if they
501      * want to be in all workspaces and add them to this workspace.
502      */
503     pCLE = pSD->clientList;
504
505     while (1)
506     {
507         /*
508          * Process all the non-icon client list entries 
509          */
510         if ((pCLE->type == NORMAL_STATE) &&
511             (pCLE->pCD->putInAll))
512         {
513             AddClientToWorkspaces( pCLE->pCD, &(pWS->id), 1 );
514         }
515         
516         /*
517          * Test for exit condition and advance client list pointer
518          */
519         if (pCLE == pSD->lastClient) 
520             break;
521         else
522             pCLE = pCLE->nextSibling;
523     }
524
525 } /* END OF FUNCTION AddPersistentWindows */
526
527 \f
528 /*************************************<->*************************************
529  *
530  *  CreateWorkspace (pSD, pchTitle)
531  *
532  *
533  *  Description:
534  *  -----------
535  *  This function creates a new workspace.
536  *
537  *  Inputs:
538  *  ------
539  *  pSD  =  pointer to screen data
540  *  pchTitle = user-visible title for the workspace (may be NULL)
541  *
542  *  Outputs:
543  *  --------
544  *  Returns pointer to workspace data if successful.
545  * 
546  *************************************<->***********************************/
547
548 WmWorkspaceData * 
549 CreateWorkspace(
550         WmScreenData *pSD,
551         unsigned char *pchTitle )
552
553 {
554     WmWorkspaceData *pWS = NULL;
555     String string;
556     int iActiveWS;
557
558     /*
559      * Allocate more workspace datas if we have no spares
560      */
561     if (pSD->numWsDataAllocated <= pSD->numWorkspaces)
562     {
563         iActiveWS = (pSD->pActiveWS - pSD->pWS) / sizeof (WmWorkspaceData);
564         pSD->numWsDataAllocated += WS_ALLOC_AMOUNT;
565         pSD->pWS = (WmWorkspaceData *) XtRealloc ((char *)pSD->pWS,
566                     pSD->numWsDataAllocated * sizeof(WmWorkspaceData));
567         pSD->pActiveWS = &(pSD->pWS[iActiveWS]);
568     }
569
570     /*
571      * Give this workspace a name
572      */
573     pWS = &pSD->pWS[pSD->numWorkspaces];
574     string = (String) GenerateWorkspaceName (pSD, pSD->numWorkspaces);
575     pWS->name = XtNewString (string);
576
577     /*
578      * Initialize the workspace data structure
579      */
580     InitWmWorkspace (pWS, pSD);
581     if (pchTitle) 
582     {
583         if (pWS->title)
584             XmStringFree (pWS->title);
585         pWS->title = XmStringCreateLocalized ((char *)pchTitle);
586     }
587
588     /*
589      * bump workspace count
590      */
591     pSD->numWorkspaces++;
592
593     /*
594      * update the properties that announce workspace info
595      */
596     SetWorkspaceInfoProperty (pWS);
597     SetWorkspaceListProperty (pSD);
598
599     SaveWorkspaceResources(pWS, (WM_RES_WORKSPACE_LIST  | 
600                                  WM_RES_WORKSPACE_COUNT |
601                                  WM_RES_WORKSPACE_TITLE));
602     dtSendWorkspaceModifyNotification(pSD, pWS->id, DtWSM_REASON_ADD);
603
604     /*
605      * Insure there's an iconbox for this workspace
606      */
607     if (pSD->useIconBox)
608     {
609         AddIconBoxForWorkspace (pWS);
610     }
611
612     /*
613      * Add windows to this workspaces that want to be in "all"
614      * workspaces.
615      */
616     AddPersistentWindows (pWS);
617
618     /*
619      * Update workspace presence dialog data
620      */
621     UpdatePresenceWorkspaces(pSD);
622
623     return (pWS);
624 } /* END OF FUNCTION CreateWorkspace */
625
626 \f
627 /*************************************<->*************************************
628  *
629  *  DeleteWorkspace (pWS)
630  *
631  *
632  *  Description:
633  *  -----------
634  *  This function deletes a workspace.
635  *
636  *  Inputs:
637  *  ------
638  *  pWS  =  pointer to screen data
639  *
640  *  Outputs:
641  *  --------
642  *  Returns pointer to workspace data if successful.
643  * 
644  *************************************<->***********************************/
645
646 void 
647 DeleteWorkspace(
648         WmWorkspaceData *pWS )
649
650 {
651     WmWorkspaceData *pWSdest;           /* destination WS */
652     int i, iNextWs;
653     ClientData *pCD;
654     WmScreenData *pSD = pWS->pSD;
655     Atom aOldId;
656
657     if (pSD->numWorkspaces > 1)
658     {
659         /*
660          * Find index for "next" workspace
661          */
662         for (iNextWs = 0; iNextWs < pSD->numWorkspaces; iNextWs++)
663         {
664             if (pSD->pWS[iNextWs].id == pWS->id)
665             {
666                 iNextWs++;
667                 break;
668             }
669         }
670
671         /* check bounds and wrap */
672         if (iNextWs >= pSD->numWorkspaces)
673             iNextWs = 0;
674
675         /*
676          * Determine default destination for clients that exist
677          * only in the workspace being deleted.
678          */
679         if (pWS == ACTIVE_WS)
680         {
681             pWSdest = &(pSD->pWS[iNextWs]);
682         }
683         else
684         {
685             /*
686              * Use the "current" workspace as the default destination
687              */
688             pWSdest = ACTIVE_WS;
689         }
690
691         /*
692          * Move all clients out of this workspace
693          */
694         while (pWS->numClients > 0)
695         {
696             /* repeatedly remove the first one until all are gone */
697             pCD = pWS->ppClients[0];
698
699
700             if (pCD->numInhabited == 1)
701             {
702                 if (!(pCD->clientFlags & (ICON_BOX)))
703                 {
704                     AddClientToWorkspaces (pCD, &(pWSdest->id), 1);
705                 }
706             }
707
708             RemoveClientFromWorkspaces (pCD, &(pWS->id), 1);
709         }
710
711         /*
712          * If we're deleting the current workspace, 
713          * then change to another workspace.
714          */
715         if (pWS == ACTIVE_WS)
716         {
717             ChangeToWorkspace (pWSdest);
718         }
719
720         /*
721          * Save the workspace ID for the notification message.
722          */
723         aOldId = pWS->id;
724
725         /*
726          * Destroy the icon box for the workspace if one was used
727          */
728         if (pSD->useIconBox)
729         {
730             DestroyIconBox (pWS);
731         }
732
733         /*
734          * Delete the property containing information on this workspace
735          */
736         DeleteWorkspaceInfoProperty (pWS);
737
738         /*
739          * Delete the workspace data structures
740          */
741         if (pWS->backdrop.imagePixmap)
742         {
743             if (!XmDestroyPixmap (XtScreen(pWS->workspaceTopLevelW),
744                             pWS->backdrop.imagePixmap))
745             {
746                 /* not in Xm pixmap cache */
747             }
748         }
749
750         /* free pWS->backdrop.image */
751         if ((pWS->backdrop.flags & BACKDROP_IMAGE_ALLOCED) &&
752             (pWS->backdrop.image))
753         {
754             free (pWS->backdrop.image);
755         }
756
757         /* 
758          * Free up icon placement data
759          */
760         if (wmGD.iconAutoPlace)
761         {
762            if (pWS->IPData.placeList != NULL)
763                XtFree ((char *) pWS->IPData.placeList);
764            if (pWS->IPData.placementRowY != NULL)
765                XtFree ((char *) pWS->IPData.placementRowY);
766            if (pWS->IPData.placementColX != NULL)
767                XtFree ((char *) pWS->IPData.placementColX);
768         }
769
770         XtFree ((char *) pWS->name);
771         XmStringFree (pWS->title);
772         XtFree ((char *) pWS->ppClients);
773         if (pWS->iconBoxGeometry) XtFree ((char *) pWS->iconBoxGeometry);
774         XtDestroyWidget (pWS->workspaceTopLevelW);
775
776         /*
777          * Compress the list of workspaces if we're not deleting
778          * the last one. (Do piece-wise to avoid overlapping copy
779          * problems).
780          */
781         if (iNextWs > 0)
782         {
783             WmWorkspaceData *pWSdest;
784             WmWorkspaceData *pWSsrc;
785             int j;
786
787             pWSdest = pWS;
788             pWSsrc = &(pSD->pWS[iNextWs]);
789
790             for (j=iNextWs; j < pSD->numWorkspaces; j++)
791             {
792                 memcpy (pWSdest, pWSsrc, sizeof(WmWorkspaceData));
793                 if (pSD->pActiveWS == pWSsrc)
794                 {
795                     pSD->pActiveWS = pWSdest;
796                 }
797                 pWSdest++;
798                 pWSsrc++;
799             }
800         }
801
802         /*
803          * We now have one less workspace.
804          */
805         pSD->numWorkspaces--;
806
807         /*
808          * Update the properties that announce workspace info.
809          */
810         SetWorkspaceListProperty (pSD);
811
812         SaveWorkspaceResources(pWSdest,
813                 (WM_RES_WORKSPACE_LIST | WM_RES_WORKSPACE_COUNT));
814
815         dtSendWorkspaceModifyNotification(pSD, aOldId, DtWSM_REASON_DELETE);
816
817         /*
818          * Update workspace presence dialog data
819          */
820         UpdatePresenceWorkspaces(pSD);
821     }
822 } /* END OF FUNCTION DeleteWorkspace */
823
824 \f
825 /*************************************<->*************************************
826  *
827  *  ProcessDtWmHints (pCD)
828  *
829  *
830  *  Description:
831  *  -----------
832  *  Process the _DT_WM_HINTS property on the window (if any).  
833  *
834  *
835  *  Inputs:
836  *  ------
837  *  pCD = pointer to client data
838  *
839  * 
840  *  Outputs:
841  *  -------
842  *  pCD = may be changed.
843  *
844  *************************************<->***********************************/
845
846 void 
847 ProcessDtWmHints (ClientData *pCD)
848 {
849     DtWmHints *pHints;
850     Atom        property;
851 #ifdef HP_VUE
852     Atom        propertyVUE;
853 #endif /* HP_VUE */
854     long        saveFunctions;
855
856     /*
857      * Retrieve the _DT_WM_HINTS property if it exists.
858      */
859
860     property = XmInternAtom(DISPLAY, _XA_DT_WM_HINTS, False);
861 #ifdef HP_VUE
862     propertyVUE = XmInternAtom(DISPLAY, _XA_VUE_WM_HINTS, False);
863 #endif /* HP_VUE */
864
865     if (
866 #ifdef HP_VUE
867         ((HasProperty (pCD, property)) || (HasProperty (pCD, propertyVUE))) 
868 #else /* HP_VUE */
869         (HasProperty (pCD, property)) 
870 #endif /* HP_VUE */
871         && (_DtWsmGetDtWmHints (DISPLAY, pCD->client, &pHints) == Success))
872     {
873         pCD->clientFlags |= GOT_DT_WM_HINTS;
874         if (pHints->flags & DtWM_HINTS_FUNCTIONS)
875         {
876             if (pHints->functions & DtWM_FUNCTION_ALL)
877             {
878                 /* client indicating inapplicable functions */
879                 pCD->dtwmFunctions &= ~(pHints->functions);
880             }
881             else
882             {
883                 /* client indicating applicable functions */
884                 pCD->dtwmFunctions &= pHints->functions;
885             }
886         }
887
888         if (pHints->flags & DtWM_HINTS_BEHAVIORS)
889         {
890             /* set applicable behaviors */
891             pCD->dtwmBehaviors = pHints->behaviors;
892             if (pCD->dtwmBehaviors & DtWM_BEHAVIOR_SUB_RESTORED)
893             {
894                 /*
895                  * if this is a restored subpanel, remove the
896                  * DtWM_BEHAVIOR_SUB_RESTORED bit so the next
897                  * time through the subpanel will behave as an
898                  * existing subpanel
899                  */
900                 pHints->behaviors &= ~DtWM_BEHAVIOR_SUB_RESTORED;
901                 _DtWsmSetDtWmHints (DISPLAY, pCD->client, pHints);
902             }
903         }
904
905         XFree ((char*)pHints);
906     }
907
908     if (pCD->dtwmBehaviors & DtWM_BEHAVIOR_PANEL)
909     {
910         /* put it in all workspaces */
911         saveFunctions = pCD->dtwmFunctions;
912         pCD->dtwmFunctions |= DtWM_FUNCTION_OCCUPY_WS;
913
914         F_AddToAllWorkspaces (NULL, pCD, NULL);
915
916         pCD->dtwmFunctions = saveFunctions;
917         pCD->clientFlags |= FRONT_PANEL_BOX ;
918     }
919 } /* END OF ProcessDtWmHints */
920
921 \f
922 /*************************************<->*************************************
923  *
924  *  GetClientWorkspaceInfo (pCD, manageFlags);
925  *
926  *
927  *  Description:
928  *  -----------
929  *  This function sets up the portion of client data that has to
930  *  do with workspaces 
931  *
932  *  Inputs:
933  *  ------
934  *  pCD  =  pointer to client data (only partly initialized!!)
935  *  manageFlags = tells us, in particular, if we're restarting.
936  *
937  *  Outputs:
938  *  --------
939  *  pCD  = updated client data
940  *
941  *************************************<->***********************************/
942
943 Boolean 
944 GetClientWorkspaceInfo(
945         ClientData *pCD,
946         long manageFlags )
947
948 {
949     Atom *pIDs;
950     int i;
951     unsigned int numIDs = 0;
952     Boolean bAll;
953
954     /* 
955      * Allocate initial workspace ID list 
956      * fill with NULL IDs
957      */
958     if ((pCD->pWsList = (WsClientData *) 
959             XtMalloc(pCD->pSD->numWorkspaces * sizeof(WsClientData))) == NULL)
960     {
961         Warning (((char *)GETMESSAGE(76, 4, "Insufficient memory for client data")));
962         return (False);
963     }
964     pCD->currentWsc = 0;
965     pCD->pWorkspaceHints = NULL;
966     pCD->sizeWsList = pCD->pSD->numWorkspaces;
967     pCD->numInhabited = 0;              /* no valid ones yet */
968     for (i = 0; i < pCD->pSD->numWorkspaces; i++)
969     {
970         pCD->pWsList[i].wsID = None;
971         pCD->pWsList[i].iconPlace = NO_ICON_PLACE;
972         pCD->pWsList[i].iconX = 0;
973         pCD->pWsList[i].iconY = 0;
974         pCD->pWsList[i].iconFrameWin = None;
975         pCD->pWsList[i].pIconBox = NULL;
976     }
977     pCD->putInAll = bAll = False;
978
979     /* 
980      * Determine initial workspace set.
981      *
982      * If this is a secondary window, use the hints from the
983      * transient tree leader.
984      *
985      * Else if we're restarting, then use our own workspace presence.
986      *
987      * Else if a command line option is specified, use that.
988      *
989      * Else, if workspace hints are on the window, then use them.
990      *
991      * If none of the above work out, the window will be put into
992      * the current workspace.
993      */
994     if (pCD->client &&
995         ((pCD->transientLeader && GetLeaderPresence(pCD, &pIDs, &numIDs)) ||
996          ((manageFlags & MANAGEW_WM_RESTART) && 
997            GetMyOwnPresence (pCD, &pIDs, &numIDs)) ||
998          (WorkspaceIsInCommand (DISPLAY, pCD, &pIDs, &numIDs)) ||
999          (
1000 #ifdef HP_VUE
1001           (HasProperty (pCD, wmGD.xa_DT_WORKSPACE_HINTS) ||
1002            HasProperty (pCD, 
1003                         XmInternAtom (DISPLAY, _XA_VUE_WORKSPACE_HINTS,
1004                         False)))
1005 #else /* HP_VUE */
1006           HasProperty (pCD, wmGD.xa_DT_WORKSPACE_HINTS) 
1007 #endif /* HP_VUE */
1008           && (GetWorkspaceHints (DISPLAY, pCD->client, &pIDs, &numIDs, &bAll) == 
1009                  Success))) &&
1010          numIDs)
1011     {
1012         /*
1013          * Got some workspace hints! 
1014          */
1015         pCD->putInAll = bAll;
1016         ProcessWorkspaceHintList (pCD, pIDs, numIDs);
1017     }
1018
1019     if (pCD->numInhabited == 0)
1020     {
1021         /*
1022          * If not in any workspaces, then put the client into
1023          * the current one.
1024          */
1025         PutClientIntoWorkspace (pCD->pSD->pActiveWS, pCD);
1026     }
1027
1028     return (True);
1029
1030 } /* END OF FUNCTION GetClientWorkspaceInfo */
1031
1032 \f
1033 /*************************************<->*************************************
1034  *
1035  *  WorkspaceIsInCommand (dpy, pCD, ppIDs, pNumIDs)
1036  *
1037  *
1038  *  Description:
1039  *  -----------
1040  *  Determine if workspace specification is in command line for client
1041  *
1042  *
1043  *  Inputs:
1044  *  ------
1045  *  dpy         - pointer to display structure
1046  *  pCD         - ptr to client data
1047  *  ppIDs       - pointer for returning list of IDs
1048  *  pNumIDs     - number of IDs being returned
1049  * 
1050  *  Outputs:
1051  *  -------
1052  *  ppIDs       - returned list of IDs
1053  *  pNumIDs     - number of IDs being returned
1054  *
1055  *  Return      - True if workspace option found, false otherwise
1056  *
1057  *
1058  *  Comments:
1059  *  --------
1060  *  Malloc's memory that must be freed
1061  * 
1062  *************************************<->***********************************/
1063
1064 Boolean 
1065 WorkspaceIsInCommand(
1066         Display *dpy,
1067         ClientData *pCD,
1068         WorkspaceID **ppIDs,
1069         unsigned int *pNumIDs )
1070 {
1071     int wmcArgc;
1072     char **wmcArgv = NULL;
1073     Boolean rval = False;
1074     unsigned char *pch = NULL;
1075     XTextProperty clientMachineProp;
1076
1077     if (FindClientDBMatch(pCD, (char **)&pch))
1078     {
1079         if (pch)
1080         {
1081             if (ConvertNamesToIDs (pCD->pSD, pch, ppIDs, pNumIDs))
1082             {
1083                 rval = True;
1084             }
1085             XtFree((char *)pch);
1086         }
1087     }
1088     else if (HasProperty (pCD, XA_WM_COMMAND) &&
1089              XGetCommand (dpy, pCD->client, &wmcArgv, &wmcArgc) &&
1090              (wmcArgv != NULL))
1091     {
1092         if (pCD->pSD->remainingSessionItems)
1093         {
1094             if(!(XGetWMClientMachine(dpy, pCD->client, &clientMachineProp)))
1095             {
1096                 clientMachineProp.value = NULL;
1097             }
1098             if (FindDtSessionMatch(wmcArgc, wmcArgv, pCD, pCD->pSD, 
1099                                     (char **)&pch, 
1100                                     (char *)clientMachineProp.value))
1101             {
1102                 /*
1103                  * If we found a match to a client description
1104                  * in the DtSessionHints, use the information from
1105                  * the Hints instead of the command line
1106                  */
1107                 if (pch)
1108                 {
1109                     if (ConvertNamesToIDs (pCD->pSD, pch, ppIDs, pNumIDs))
1110                     {
1111                         rval = True;
1112                     }
1113                     /*
1114                      * free malloced memory containing workspace list
1115                      */
1116                     XtFree ((char *)pch);
1117                 }
1118                     
1119             }
1120             if (clientMachineProp.value)
1121             {
1122                 XFree ((char*)clientMachineProp.value);
1123             }
1124         }
1125
1126         if (!rval && FindWsNameInCommand (wmcArgc, wmcArgv, &pch))
1127         {
1128             if (ConvertNamesToIDs (pCD->pSD, pch, ppIDs, pNumIDs))
1129             {
1130                 rval = True;
1131             }
1132         }
1133
1134         if (wmcArgv != NULL)
1135         {
1136             XFreeStringList (wmcArgv);
1137         }
1138     }
1139
1140     return (rval);
1141 } /* END OF FUNCTION WorkspaceIsInCommand */
1142
1143 \f
1144 /*************************************<->*************************************
1145  *
1146  *  ConvertNamesToIDs (pSD, pch, ppAtoms, pNumAtoms)
1147  *
1148  *
1149  *  Description:
1150  *  -----------
1151  *  Takes a string containing a list of names separated by white space
1152  *  and converts it to a list of workspace IDs.
1153  * 
1154  *  Inputs:
1155  *  ------
1156  *  pSD         - pointer to screen data
1157  *  pchIn       - pointer to original string
1158  *  ppAtoms     - pointer to an atom pointer (for returning list pointer)
1159  *  pNumAtoms   - pointer to the number of atoms being returned.
1160  * 
1161  *  Outputs:
1162  *  -------
1163  *  *ppAtoms    - points to a list of atoms returned.
1164  *  *pNumAtoms  - the number of atoms being returned.
1165  *
1166  *  Return      - True if some Atoms are being returned
1167  *
1168  *  Comments:
1169  *  --------
1170  *  Processes local copy of string so that pch is not modified.
1171  *
1172  *  The list of atoms returned has been dynamically allocated. 
1173  *  Please XtFree() it when you're done.
1174  *
1175  *************************************<->***********************************/
1176
1177 Boolean 
1178 ConvertNamesToIDs(
1179         WmScreenData *pSD,
1180         unsigned char *pchIn,
1181         WorkspaceID **ppAtoms,
1182         unsigned int *pNumAtoms )
1183
1184 {
1185     unsigned char *pchLocal, *pch, *pchName;
1186     int num = 0;
1187     int numLocalIDs;
1188     WorkspaceID *pLocalIDs;
1189
1190     if ((pLocalIDs = (WorkspaceID *) XtMalloc (WS_ALLOC_AMOUNT *
1191         sizeof(WorkspaceID))) == NULL)
1192     {
1193         Warning (((char *)GETMESSAGE(76, 5, "Insufficient Memory (ConvertNamesToIDs)")));
1194         ExitWM (WM_ERROR_EXIT_VALUE);
1195     }
1196     numLocalIDs = WS_ALLOC_AMOUNT;
1197
1198    if (pchIn && (pchLocal = (unsigned char *) XtMalloc(1+strlen((char *)pchIn))))
1199    {
1200         strcpy ((char *)pchLocal, (char *)pchIn);
1201         pch = pchLocal;
1202
1203         while ((pchName = GetSmartString (&pch)))
1204         {
1205             int iwsx;
1206             XmString xms;
1207
1208             /*
1209              * Check workspace for workspace titles; map to 
1210              * workspace names.
1211              */
1212             xms = XmStringCreateLocalized ((char *)pchName);
1213             for (iwsx = 0; iwsx < pSD->numWorkspaces; iwsx++)
1214             {
1215                 if (XmStringCompare (xms, pSD->pWS[iwsx].title))
1216                 {
1217                     break;
1218                 }
1219             }
1220             XmStringFree (xms);
1221
1222             if (iwsx < pSD->numWorkspaces)
1223             {
1224                /*
1225                 * Found a workspace title we've got,
1226                 * use id for workspace name
1227                 */
1228                 pLocalIDs[num] = pSD->pWS[iwsx].id;
1229                 num++;
1230             }
1231             else 
1232             {
1233                 /*
1234                  * Try for match on workspace name
1235                  */
1236                 pLocalIDs[num] = (WorkspaceID) 
1237                             XInternAtom (DISPLAY, (char *)pchName, False);
1238                 num++;
1239             }
1240
1241             if (num >= numLocalIDs)
1242             {
1243                 /* list too small */
1244                 numLocalIDs += WS_ALLOC_AMOUNT;
1245                 if ((pLocalIDs = (WorkspaceID *) XtRealloc ((char *)pLocalIDs,
1246                             numLocalIDs * sizeof(WorkspaceID))) == NULL)
1247                 {
1248                     Warning (((char *)GETMESSAGE(76, 6, "Insufficient Memory (ConvertNamesToIDs)")));
1249                     ExitWM (WM_ERROR_EXIT_VALUE);
1250                 }
1251             }
1252         }
1253
1254         XtFree ((char *)pchLocal);
1255     }
1256
1257     *ppAtoms = pLocalIDs;
1258     *pNumAtoms = num;
1259     return (num != 0);
1260     
1261 } /* END OF FUNCTION ConvertNamesToIDs */
1262
1263 \f
1264 /*************************************<->*************************************
1265  *
1266  *  CheckForPutInAllRequest (pCD, pIDs, numIDs)
1267  *
1268  *
1269  *  Description:
1270  *  -----------
1271  *  Tests for the presence of the "all" atom in the atom list
1272  *  and sets the "putInAll" flag on the client.
1273  * 
1274  *  Inputs:
1275  *  ------
1276  *  pCD         - pointer to client data
1277  *  pIDs        - pointer to ID list
1278  *  numIDs      - number of IDs in list
1279  * 
1280  *  Outputs:
1281  *  -------
1282  *  pCD         - putInAll member may be set
1283  *
1284  *************************************<->***********************************/
1285
1286 void 
1287 CheckForPutInAllRequest(
1288         ClientData *pCD,
1289         Atom *pIDs,
1290         unsigned int numIDs )
1291
1292 {
1293     unsigned int i;
1294
1295     for (i = 0; (i < numIDs) && !(pCD->putInAll); i++)
1296     {
1297         if (pIDs[i] == wmGD.xa_ALL_WORKSPACES)
1298         {
1299             pCD->putInAll = True;
1300             break;
1301         }
1302     }
1303     
1304 } /* END OF FUNCTION CheckForPutInAllRequest */
1305
1306 \f
1307 /*************************************<->*************************************
1308  *
1309  *  FindWsNameInCommand (argc, argv, ppch)
1310  *
1311  *
1312  *  Description:
1313  *  -----------
1314  *  Finds and returns the workspace name option in the command line 
1315  *  (if any)
1316  *
1317  *  Inputs:
1318  *  ------
1319  *  argc        - argument count
1320  *  argv        - argument list
1321  *  ppch        - string pointer to return
1322  *
1323  * 
1324  *  Outputs:
1325  *  -------
1326  *  *ppch       - points to ws name (if found)
1327  *
1328  *  Return      - True if wsname found
1329  *
1330  *
1331  *  Comments:
1332  *  --------
1333  *************************************<->***********************************/
1334
1335 Boolean 
1336 FindWsNameInCommand(
1337         int argc,
1338         char *argv[],
1339         unsigned char **ppch )
1340
1341 {
1342
1343 #define XRM_OPT         "-xrm"
1344 #define WSLIST          "*workspaceList:"
1345 #define WSLIST_LEN      14
1346
1347     int i = 1;
1348     Boolean rval = False;
1349     unsigned char *pch, *pchTmp, *pch0;
1350     unsigned char *pchRes, *pchValue;
1351     
1352     if (argc > 0)
1353     {
1354         while (--argc && !rval)
1355         {
1356             if (!strcmp(argv[i], XRM_OPT) && (argc > 1))
1357             {
1358                 /* 
1359                  * found "-xrm", now look at resource spec
1360                  */
1361                 pch0 = (unsigned char *) strdup (argv[i+1]);
1362                 if (!pch0)
1363                 {
1364                     Warning (((char *)GETMESSAGE(76, 7, "Insufficient memory")));
1365                     ExitWM (WM_ERROR_EXIT_VALUE);
1366                 }
1367                 pch = pch0;
1368
1369                 /* strip off quotes ,
1370                  * separate two halve of resource spec
1371                  */
1372                 pchRes = GetSmartString (&pch);
1373                 pchValue = pch;
1374
1375                 if ((*pchRes) && (*pch))
1376                 {
1377                     /* Erase colon at end of resource name */
1378
1379                     pch = (unsigned char *) strrchr((char *)pchRes, ':');
1380                     if (pch)
1381                     {
1382                         *pch = '\0';
1383                     }
1384
1385                     /* find beginning of last component of resource
1386                      * spec
1387                      */
1388                     pch = (unsigned char *) strrchr ((char *)pchRes, '*');
1389                     pchTmp = (unsigned char *) strrchr ((char *)pchRes, '.');
1390                     if (pchTmp > pch)
1391                     {
1392                         pch = pchTmp;
1393                     }
1394
1395                     if (pch && *pch && *(pch+1))
1396                     {
1397                         pch += 1;
1398                     }
1399
1400                     /* compare resource with our resource */
1401
1402                     if ( (!strcmp ((char *)pch, WmNworkspaceList)) ||
1403                          (!strcmp ((char *)pch, WmCWorkspaceList)))
1404                     {
1405                         /* match, compute return position in
1406                            passed in string */
1407
1408                         *ppch = (unsigned char *) 
1409                                 (argv[i+1] + (pchValue - pch0));
1410                         rval = True;
1411                         XtFree ((char *)pch0);
1412                         pch0 = NULL;
1413                     }
1414                 }
1415
1416                 i++;            /* skip next arg */
1417                 argc--;
1418
1419                 if (pch0)
1420                 {
1421                     XtFree ((char *)pch0);
1422                 }
1423             }
1424             i++;
1425         }
1426     }
1427     return (rval);
1428 } /* END OF FUNCTION FindWsNameInCommand */
1429
1430
1431 \f
1432 /*************************************<->*************************************
1433  *
1434  *  PutClientIntoWorkspace (pWS, pCD)
1435  *
1436  *
1437  *  Description:
1438  *  -----------
1439  *  This function updates the data for the client and workspace to
1440  *  reflect the presence of the client in the workspace.
1441  *
1442  *  Inputs:
1443  *  ------
1444  *  pWS = pointer to workspace data
1445  *  pCD = pointer to client data
1446  *
1447  *  Outputs:
1448  *  --------
1449  *
1450  *************************************<->***********************************/
1451
1452 void 
1453 PutClientIntoWorkspace(
1454         WmWorkspaceData *pWS,
1455         ClientData *pCD )
1456
1457 {
1458     int i = pCD->numInhabited;
1459     int iAdded, j, k;
1460
1461     /* insure the client's got enough workspace data */
1462     if (pCD->sizeWsList < pCD->pSD->numWorkspaces)
1463     {
1464         iAdded = pCD->pSD->numWorkspaces - pCD->sizeWsList;
1465
1466         pCD->sizeWsList = pCD->pSD->numWorkspaces;
1467         pCD->pWsList = (WsClientData *) 
1468                 XtRealloc((char *)pCD->pWsList, 
1469                     (pCD->pSD->numWorkspaces * sizeof(WsClientData)));
1470
1471         /* intialized new data */
1472         j = pCD->sizeWsList - 1;
1473         for (j=1; j <= iAdded; j++)
1474         {
1475             k = pCD->sizeWsList - j;
1476             pCD->pWsList[k].iconPlace = NO_ICON_PLACE;
1477             pCD->pWsList[k].iconX = 0;
1478             pCD->pWsList[k].iconY = 0;
1479             pCD->pWsList[k].iconFrameWin = (Window) 0;
1480             pCD->pWsList[k].pIconBox = NULL;
1481         }
1482     }
1483
1484
1485     /* update the client's list of workspace data */
1486     pCD->pWsList[i].wsID = pWS->id; 
1487     pCD->numInhabited++;
1488
1489     if (!(pCD->clientFlags & WM_INITIALIZATION))
1490     {
1491         /* 
1492          * Make sure there's an icon 
1493          * (Don't do this during initialization, the pCD not
1494          * ready for icon making yet).
1495          */
1496         InsureIconForWorkspace (pWS, pCD);
1497     }
1498
1499     /* update the workspace list of clients */
1500     AddClientToWsList (pWS, pCD);
1501
1502 } /* END OF FUNCTION PutClientIntoWorkspace */
1503
1504 \f
1505 /*************************************<->*************************************
1506  *
1507  *  TakeClientOutOfWorkspace (pWS, pCD)
1508  *
1509  *
1510  *  Description:
1511  *  -----------
1512  *  This function updates the data for the client and the workspace
1513  *  to reflect the removal of the client from the workspace.
1514  *
1515  *  Inputs:
1516  *  ------
1517  *  pWS = pointer to workspace data
1518  *  pCD = pointer to client data
1519  *
1520  *  Outputs:
1521  *  --------
1522  *
1523  *************************************<->***********************************/
1524
1525 void 
1526 TakeClientOutOfWorkspace(
1527         WmWorkspaceData *pWS,
1528         ClientData *pCD )
1529
1530 {
1531     int ixA;
1532     Boolean Copying = False;
1533     WsClientData *pWsc;
1534
1535     if (pWS && pCD && ClientInWorkspace(pWS, pCD))
1536     {
1537         /*
1538          * Clean up icon
1539          */
1540         if (!pCD->transientLeader)
1541         {
1542             pWsc = GetWsClientData (pWS, pCD);
1543
1544             if ((pCD->pSD->useIconBox) && 
1545                 (pWsc->pIconBox) &&
1546                 (pCD->clientFunctions & MWM_FUNC_MINIMIZE))
1547             {
1548                 DeleteIconFromBox (pWS->pIconBox, pCD);
1549             }
1550             else if (wmGD.iconAutoPlace)
1551             {
1552                 /* 
1553                  * Free up root icon spot 
1554                  */
1555
1556                 if ((pWsc->iconPlace != NO_ICON_PLACE) &&
1557                     (pWS->IPData.placeList[pWsc->iconPlace].pCD == pCD))
1558                 {
1559                     pWS->IPData.placeList[pWsc->iconPlace].pCD = NULL;
1560                     pWsc->iconPlace = NO_ICON_PLACE;
1561                 }
1562             }
1563         }
1564
1565         /* 
1566          *  Remove the selected workspace and copy the remaining ones
1567          *  up. (Do piece-wise to avoid overlapping copy.)
1568          */
1569         for (ixA = 0; ixA < pCD->numInhabited; ixA++)
1570         {
1571             if (Copying)
1572             {
1573                 memcpy (&pCD->pWsList[ixA-1], &pCD->pWsList[ixA], 
1574                         sizeof(WsClientData));
1575             }
1576             else if (pCD->pWsList[ixA].wsID == pWS->id)
1577             {
1578                 /* 
1579                  *  This is the one we're removing, start copying here.
1580                  */
1581                 Copying = True;
1582             }
1583         }
1584
1585         /* 
1586          * Decrement the number of workspaces inhabited.
1587          */
1588         pCD->numInhabited--;
1589
1590         /* update the workspaces list of clients */
1591         RemoveClientFromWsList (pWS, pCD);
1592     }
1593 #ifdef DEBUG
1594     else
1595     {
1596         Warning("TakeClientOutOfWorkspace: null workspace passed in.");
1597     }
1598 #endif /* DEBUG */
1599
1600
1601 } /* END OF FUNCTION TakeClientOutOfWorkspace */
1602
1603 \f
1604 /*************************************<->*************************************
1605  *
1606  *  GetWorkspaceData (pSD, wsID)
1607  *
1608  *
1609  *  Description:
1610  *  -----------
1611  *  This function finds the data that is associated with a workspace ID.
1612  *
1613  *  Inputs:
1614  *  ------
1615  *  pSD   = pointer to screen data
1616  *  wsID  =  workspace ID
1617  *
1618  *  Outputs:
1619  *  --------
1620  *  Function returns a pointer to the workspace data if successful,
1621  *  or NULL if unsuccessful.
1622  *
1623  *************************************<->***********************************/
1624
1625 WmWorkspaceData * 
1626 GetWorkspaceData(
1627         WmScreenData *pSD,
1628         WorkspaceID wsID )
1629
1630 {
1631     WmWorkspaceData *pWS = NULL;
1632     int i;
1633
1634     for (i=0; i < pSD->numWorkspaces; i++)
1635     {
1636         if (pSD->pWS[i].id == wsID) 
1637         {
1638             pWS = &pSD->pWS[i];
1639             break;
1640         }
1641     }
1642
1643 #ifdef DEBUG
1644     if (!pWS)
1645     {
1646         /* failed to find one */
1647         Warning ("Failed to find workspace data");
1648     }
1649 #endif
1650
1651     return (pWS);
1652
1653 }  /* END OF FUNCTION GetWorkspaceData */
1654
1655
1656 \f
1657 /*************************************<->*************************************
1658  *
1659  *  GenerateWorkspaceName (pSD, wsnum)
1660  *
1661  *
1662  *  Description:
1663  *  -----------
1664  *  This function generates and returns a workspace string name from
1665  *  a small number passed in.
1666  *
1667  *  Inputs:
1668  *  ------
1669  *  pSD = pointer to screen data
1670  *  wsNum  =  number for workspace
1671  *
1672  * 
1673  *  Outputs:
1674  *  -------
1675  *  returns pointer to statically allocated data. You must copy it
1676  *  to your local buffer.
1677  *
1678  *  Comments:
1679  *  ---------
1680  *  Name is of the form ws<n> where <n> is a number.
1681  * 
1682  *************************************<->***********************************/
1683
1684 unsigned char * 
1685 GenerateWorkspaceName(
1686         WmScreenData *pSD,
1687         int wsnum )
1688
1689 {
1690     static unsigned char nameReturned[13];
1691     int i, j;
1692
1693     /*
1694      * Nice n-squared algorithm...
1695      * (This should be OK for small number of workspaces)
1696      */
1697     for (i=0; i <= pSD->numWorkspaces; i++)
1698     {
1699         /* generate a name */
1700         sprintf ((char *)nameReturned, "ws%d", i);
1701         if (!DuplicateWorkspaceName (pSD, nameReturned, wsnum))
1702             break;
1703     }
1704
1705     return (nameReturned);
1706
1707 }  /* END OF FUNCTION GenerateWorkspaceName */
1708
1709
1710 \f
1711 /*************************************<->*************************************
1712  *
1713  *  InWindowList (w, wl, num)
1714  *
1715  *
1716  *  Description:
1717  *  -----------
1718  *  This function determines if a window is in a list of windows
1719  *
1720  *  Inputs:
1721  *  ------
1722  *  w = window of interest
1723  *  wl = list of windows
1724  *  num = number of windows in wl
1725  *
1726  * 
1727  *  Outputs:
1728  *  -------
1729  *  The function returns "True" if "w" appears in "wl"
1730  *
1731  *************************************<->***********************************/
1732
1733 Boolean 
1734 InWindowList(
1735         Window w,
1736         Window wl[],
1737         int num )
1738
1739 {
1740     int i;
1741     Boolean rval = False;
1742
1743     for (i = 0; (i < num) && !rval; i++)
1744     {
1745         if (w == wl[i])
1746         {
1747             rval = True;
1748         }
1749     }
1750
1751     return (rval);
1752
1753 }   /* END OF FUNCTION InWindowList */
1754
1755 \f
1756 /*************************************<->*************************************
1757  *
1758  *  ClientInWorkspace (pWS, pCD)
1759  *
1760  *
1761  *  Description:
1762  *  -----------
1763  *  This function determines if a client is in a workspace
1764  *
1765  *  Inputs:
1766  *  ------
1767  *  pWS = pointer to workspace data
1768  *  pCD = pointer to client data
1769  * 
1770  *  Outputs:
1771  *  -------
1772  *  The function returns "True" if client pCD is in workspace pWS
1773  *
1774  *************************************<->***********************************/
1775
1776 Boolean 
1777 ClientInWorkspace(
1778         WmWorkspaceData *pWS,
1779         ClientData *pCD )
1780
1781 {
1782     int i;
1783     Boolean rval = False;
1784
1785     for (i = 0; (i < pCD->numInhabited) && !rval; i++)
1786     {
1787         if (pWS->id == pCD->pWsList[i].wsID)
1788         {
1789             rval = True;
1790         }
1791     }
1792
1793     return (rval);
1794
1795 }   /* END OF FUNCTION ClientInWorkspace */
1796
1797 \f
1798 /*************************************<->*************************************
1799  *
1800  *  GetWsClientData (pWS, pCD)
1801  *
1802  *
1803  *  Description:
1804  *  -----------
1805  *  This function returns a pointer to the client's specific data for
1806  *  this workspace
1807  *
1808  *  Inputs:
1809  *  ------
1810  *  pWS = pointer to workspace data
1811  *  pCD = pointer to client data
1812  * 
1813  *  Outputs:
1814  *  -------
1815  *  The function returns a pointer to the client's data for this
1816  *  workspace. If the client isn't in the workspace, an error is 
1817  *  printed and the first datum in the workspace list is returned.
1818  *
1819  *************************************<->***********************************/
1820
1821 WsClientData * 
1822 GetWsClientData(
1823         WmWorkspaceData *pWS,
1824         ClientData *pCD )
1825
1826 {
1827     int i;
1828     WsClientData *pWsc = NULL;
1829
1830     for (i = 0; (i < pCD->numInhabited) && !pWsc; i++)
1831     {
1832         if (pWS->id == pCD->pWsList[i].wsID)
1833         {
1834             pWsc = &pCD->pWsList[i];
1835         }
1836     }
1837
1838     if (!pWsc)
1839     {
1840         pWsc = &pCD->pWsList[0];
1841     }
1842
1843     return (pWsc);
1844
1845 }   /* END OF FUNCTION GetWsClientData */
1846
1847 \f
1848 /*************************************<->*************************************
1849  *
1850  *  SetClientWsIndex (pCD)
1851  *
1852  *
1853  *  Description:
1854  *  -----------
1855  *  This function sets the index into the client's array of workspace
1856  *  specific data. This index points to the data to be used for the
1857  *  currently active workspace.
1858  *
1859  *  Inputs:
1860  *  ------
1861  *  pCD = pointer to client data
1862  * 
1863  *  Outputs:
1864  *  -------
1865  *  The function returns an index as described above. If the client is
1866  *  not in the currently active workspace, then the index returned is 0.
1867  *
1868  *************************************<->***********************************/
1869
1870 void 
1871 SetClientWsIndex(
1872         ClientData *pCD )
1873
1874 {
1875     int i;
1876     WmWorkspaceData *pWS = pCD->pSD->pActiveWS;
1877
1878     for (i = 0; (i < pCD->numInhabited); i++)
1879     {
1880         if (pWS->id == pCD->pWsList[i].wsID)
1881         {
1882             break;
1883         }
1884     }
1885
1886     if (i >= pCD->numInhabited)
1887     {
1888         i = 0;
1889     }
1890
1891     pCD->currentWsc = i;
1892
1893 }   /* END OF FUNCTION SetClientWsIndex */
1894
1895
1896 \f
1897 /*************************************<->*************************************
1898  *
1899  *  ProcessWmWorkspaceHints (pCD)
1900  *
1901  *
1902  *  Description:
1903  *  -----------
1904  *  This function processes a change to the _DT_WORKSPACE_HINTS property
1905  *  on a window that we manage.
1906  *
1907  *  Inputs:
1908  *  ------
1909  *  pCD = pointer to client data
1910  * 
1911  *  Outputs:
1912  *  -------
1913  *  Returns False if we ran out of memory or no hints.
1914  *  Returns True on success.
1915  *
1916  *************************************<->***********************************/
1917
1918 Boolean 
1919 ProcessWorkspaceHints(
1920         ClientData *pCD )
1921
1922 {
1923     Atom *pIDs;
1924     int i, j;
1925     unsigned int numIDs;
1926     WmScreenData *pSD = PSD_FOR_CLIENT(pCD);
1927     Boolean rval = False;
1928     Boolean InBoth;
1929     Boolean bAll;
1930     int numOld;
1931     WorkspaceID *pDiff = NULL;
1932     int numDiff;
1933
1934     numOld = pCD->numInhabited;
1935     ReserveIdListSpace (numOld);
1936     for (i = 0; i < numOld; i++)
1937     {
1938         pResIDs[i] = pCD->pWsList[i].wsID;
1939     }
1940
1941     if ((pCD->client) && 
1942         (GetWorkspaceHints (DISPLAY, pCD->client, 
1943                             &pIDs, &numIDs, &bAll) == Success) &&
1944         (bAll || (numIDs && (pDiff = (WorkspaceID *) 
1945                   XtMalloc (sizeof(WorkspaceID) * MAX(numIDs, numOld))))))
1946     {
1947         /*
1948          *  Process request to put window in all workspaces
1949          */
1950         pCD->putInAll = bAll;
1951         CheckForPutInAllRequest (pCD, pIDs, numIDs);
1952
1953         if (!pCD->putInAll)
1954         {
1955             /*
1956              * Compute the ids to be removed.
1957              */
1958             numDiff = 0;
1959
1960             for (i=0; i < numOld; i++)
1961             {
1962                 InBoth = False;
1963                 for (j=0; j < numIDs; j++)
1964                 {
1965                     if (pIDs[j] == pResIDs[i])
1966                     {
1967                         InBoth = True;
1968                         break;
1969                     }
1970                 }
1971
1972                 if (!InBoth)
1973                 {
1974                     pDiff[numDiff++] = pResIDs[i];
1975                 }
1976             }
1977
1978             /*
1979              * Remove the client from the set of workspaces
1980              */
1981             if (numDiff)
1982             {
1983                 RemoveClientFromWorkspaces (pCD, pDiff, numDiff);
1984             }
1985         }
1986
1987         /*
1988          *  Process request to put window in all workspaces
1989          */
1990
1991         if (pCD->putInAll)
1992         {
1993             for (i=0; i<pCD->pSD->numWorkspaces; i++)
1994             {
1995                 if (!ClientInWorkspace(&pCD->pSD->pWS[i], pCD))
1996                 {
1997                     AddClientToWorkspaces (pCD, &pCD->pSD->pWS[i].id, 1);
1998                 }
1999             }
2000         }
2001         else
2002         {
2003             /*
2004              * Compute the ids to be added.
2005              */
2006
2007             numDiff = 0;
2008             for (i=0; i < numIDs; i++)
2009             {
2010                 InBoth = False;
2011                 for (j=0; j < numOld; j++)
2012                 {
2013                     if (pResIDs[j] == pIDs[i])
2014                     {
2015                         InBoth = True;
2016                         break;
2017                     }
2018                 }
2019
2020                 if (!InBoth)
2021                 {
2022                     pDiff[numDiff++] = pIDs[i];
2023                 }
2024             }
2025
2026             /*
2027              * Add the client to the set of workspaces
2028              */
2029             if (numDiff) 
2030             {
2031                 AddClientToWorkspaces (pCD, pDiff, numDiff);
2032             }
2033         }
2034
2035         /*
2036          * If the client is not in any workspaces, then
2037          * put it in the current one 
2038          *
2039          * !!! Is this right? !!!
2040          */
2041         if (pCD->numInhabited == 0)
2042         {
2043             AddClientToWorkspaces (pCD, &pSD->pActiveWS->id, 1);
2044         }
2045
2046         /*
2047          * Free up the old list of hints
2048          */
2049         if (pCD->pWorkspaceHints)
2050         {
2051             XFree ((char *)pCD->pWorkspaceHints);
2052         }
2053         if (pDiff)
2054         {
2055             XtFree ((char *)pDiff);
2056         }
2057
2058         /* 
2059          * Save the new hints
2060          */
2061         pCD->pWorkspaceHints = pIDs;
2062         pCD->numWorkspaceHints = numIDs;
2063
2064         /* 
2065          * Update the presence property
2066          */
2067         UpdateWorkspacePresenceProperty (pCD);
2068
2069         rval = True;
2070     }
2071     return (rval);
2072
2073 }   /* END OF FUNCTION ProcessWorkspaceHints */
2074
2075 \f
2076 /*************************************<->*************************************
2077  *
2078  *  InsureUniqueWorkspaceHints (pCD)
2079  *
2080  *
2081  *  Description:
2082  *  -----------
2083  *  This function processes the workspace hints and removes duplicates.
2084  *
2085  *  Inputs:
2086  *  ------
2087  *  pCD = pointer to client data
2088  * 
2089  *  Outputs:
2090  *  -------
2091  *  May modify *pWorkspaceHints and numWorkspaceHints
2092  *
2093  *************************************<->***********************************/
2094
2095 static void 
2096 InsureUniqueWorkspaceHints(
2097         ClientData *pCD )
2098
2099 {
2100     int next, trail, i;
2101     WorkspaceID *pID;
2102     Boolean  duplicate;
2103
2104
2105     if (pCD->numWorkspaceHints < 2) return;
2106
2107     pID = pCD->pWorkspaceHints;
2108
2109     trail = 0;
2110     next = 1;
2111
2112     while (next < pCD->numWorkspaceHints)
2113     {
2114         duplicate = False;
2115         for (i = 0; i < next; i++)
2116         {
2117             if (pID [next] == pID [i])
2118             {
2119                 /* duplicate found! */
2120                 duplicate = True;
2121                 break;
2122             }
2123         }
2124
2125         if (duplicate)
2126         {
2127             /* skip duplicates */
2128             next++;
2129         }
2130         else
2131         {
2132             /* not a duplicate */
2133             trail++;
2134             if (next > trail)
2135             {
2136                 /*
2137                  * We need to copy up over an old duplicate
2138                  */
2139                 pID [trail] = pID [next];
2140             }
2141         }
2142         next++;
2143     }
2144
2145     pCD->numWorkspaceHints = trail+1;
2146
2147 }   /* END OF FUNCTION InsureUniqueWorkspaceHints */
2148
2149
2150 \f
2151 /*************************************<->*************************************
2152  *
2153  *  ProcessWorkspaceHintList (pCD, pIDs, numIDs)
2154  *
2155  *
2156  *  Description:
2157  *  -----------
2158  *  This function processes a list of workspace hints for a client.
2159  *
2160  *  Inputs:
2161  *  ------
2162  *  pCD = pointer to client data
2163  *  pIDs = pointer to a list of workspace IDs
2164  *  numIDs = number of IDs in the list
2165  * 
2166  *  Outputs:
2167  *  -------
2168  *
2169  *************************************<->***********************************/
2170
2171 void 
2172 ProcessWorkspaceHintList(
2173         ClientData *pCD,
2174         WorkspaceID *pIDs,
2175         unsigned int numIDs )
2176
2177 {
2178     int i;
2179     WmWorkspaceData *pWS;
2180
2181
2182     if (numIDs > 0)
2183     {
2184         /*
2185          * Keep these hints; make sure there are no duplicate
2186          * workspace requests.
2187          */
2188         pCD->pWorkspaceHints = pIDs;
2189         pCD->numWorkspaceHints = numIDs;
2190         InsureUniqueWorkspaceHints (pCD);
2191         numIDs = pCD->numWorkspaceHints;
2192
2193         if (pCD->pWorkspaceHints)
2194         {
2195             /*
2196              *  Process request to put window in all workspaces
2197              */
2198             CheckForPutInAllRequest (pCD, pIDs, numIDs);
2199
2200             if (pCD->putInAll)
2201             {
2202                 for (i=0; i<pCD->pSD->numWorkspaces; i++)
2203                 {
2204                     PutClientIntoWorkspace (&pCD->pSD->pWS[i], pCD);
2205                 }
2206             }
2207             else
2208             {
2209                 for (i=0; i<numIDs; i++)
2210                 {
2211                     /*
2212                      * Put the client into requested workspaces that
2213                      * exist.
2214                      */
2215                     if ((pWS = GetWorkspaceData (pCD->pSD, 
2216                                                 pCD->pWorkspaceHints[i])))
2217                     {
2218                         PutClientIntoWorkspace (pWS, pCD);
2219                     }
2220                 }
2221             }
2222         }
2223     }
2224
2225 }   /* END OF FUNCTION ProcessWorkspaceHintList */
2226
2227 \f
2228 /*************************************<->*************************************
2229  *
2230  *  RemoveSingleClientFromWorkspaces (pCD, pIDs, numIDs)
2231  *
2232  *
2233  *  Description:
2234  *  -----------
2235  *  This function removes a single client from a list of workspaces
2236  *
2237  *  Inputs:
2238  *  ------
2239  *  pCD = pointer to client data
2240  *  pIDs = pointer to a list of workspace IDs
2241  *  numIDs = number of workspace IDs
2242  * 
2243  *  Outputs:
2244  *  -------
2245  *
2246  *************************************<->***********************************/
2247
2248 void 
2249 RemoveSingleClientFromWorkspaces(
2250         ClientData *pCD,
2251         WorkspaceID *pIDs,
2252         unsigned int numIDs )
2253
2254 {
2255     int i;
2256     WmWorkspaceData *pWS;
2257
2258     for (i=0; i < numIDs; i++)
2259     {
2260         /*
2261          *  Remove the client from the specified workspaces 
2262          */
2263         if ((pWS = GetWorkspaceData (pCD->pSD, pIDs[i])) &&
2264             (ClientInWorkspace (pWS, pCD)))
2265         {
2266             /*
2267              * If this workspace is active, then make the
2268              * window unseen.  We only need to call
2269              * SetClientState on the main window, the
2270              * transients will get taken care of in there.
2271              */
2272             if ((pWS == pCD->pSD->pActiveWS) &&
2273                 (pCD->transientLeader == NULL) &&
2274                 !(pCD->clientState & UNSEEN_STATE))
2275             {
2276                 SetClientState (pCD, 
2277                     (pCD->clientState | UNSEEN_STATE), CurrentTime);
2278             }
2279             TakeClientOutOfWorkspace (pWS, pCD);
2280
2281             /* 
2282              * Update the presence property
2283              */
2284             UpdateWorkspacePresenceProperty (pCD);
2285         }
2286     }
2287
2288 }   /* END OF FUNCTION RemoveSingleClientFromWorkspaces */
2289 \f
2290 /*************************************<->*************************************
2291  *
2292  *  RemoveSubtreeFromWorkspaces (pCD, pIDs, numIDs)
2293  *
2294  *
2295  *  Description:
2296  *  -----------
2297  *  This function removes a transient subtree from a list of workspaces
2298  *
2299  *  Inputs:
2300  *  ------
2301  *  pCD = pointer to client data
2302  *  pIDs = pointer to a list of workspace IDs
2303  *  numIDs = number of workspace IDs
2304  * 
2305  *  Outputs:
2306  *  -------
2307  *
2308  *************************************<->***********************************/
2309
2310 void 
2311 RemoveSubtreeFromWorkspaces(
2312         ClientData *pCD,
2313         WorkspaceID *pIDs,
2314         unsigned int numIDs )
2315
2316 {
2317     ClientData *pNext;
2318
2319     pNext = pCD->transientChildren;
2320     while (pNext)
2321     {
2322         /* process all children first */
2323         if (pNext->transientChildren)
2324         {
2325             RemoveSubtreeFromWorkspaces (pNext, pIDs, numIDs);
2326         }
2327         else
2328         {
2329             RemoveSingleClientFromWorkspaces (pNext, pIDs, numIDs);
2330         }
2331         pNext = pNext->transientSiblings;
2332     }
2333
2334     /* process the primary window */
2335     RemoveSingleClientFromWorkspaces (pCD, pIDs, numIDs);
2336
2337
2338 }   /* END OF FUNCTION RemoveSubtreeFromWorkspaces */
2339
2340
2341 \f
2342 /******************************<->*************************************
2343  *
2344  *  pIDs = GetListOfOccupiedWorkspaces (pCD, numIDs)
2345  *
2346  *
2347  *  Description:
2348  *  -----------
2349  *  This function creates a list of occupied workspaces of a particular
2350  *  client, EXCLUDING the current workspace.
2351  *
2352  *  Inputs:
2353  *  ------
2354  *  pCD = pointer to client data
2355  * 
2356  *  Outputs:
2357  *  -------
2358  *  pIDs = pointer to a list of workspace IDs
2359  *  numIDs = number of workspace IDs
2360  *
2361  *  Comment
2362  *  -------
2363  *  memory for pIDs is allocated with XtMalloc and should be 
2364  *  freed with XtFree.
2365  *
2366  *
2367  ******************************<->***********************************/
2368 WorkspaceID * 
2369 GetListOfOccupiedWorkspaces(
2370         ClientData *pCD,
2371         int *numIDs )
2372 {
2373     int i;
2374
2375     WorkspaceID *pLocalIDs = NULL;
2376
2377     WorkspaceID activeWsID = pCD->pSD->pActiveWS->id;
2378
2379     *numIDs = 0;
2380
2381     if ((pLocalIDs = (WorkspaceID *) XtMalloc (pCD->numInhabited *
2382         sizeof(WorkspaceID))) == NULL)
2383     {
2384         Warning (((char *)GETMESSAGE(76, 7, "Insufficient memory")));
2385         return (NULL);
2386     }
2387
2388     for (i = 0; i < pCD->numInhabited; i++)
2389     {
2390         if (activeWsID != pCD->pWsList[i].wsID)
2391         {
2392               pLocalIDs[(*numIDs)++] = pCD->pWsList[i].wsID;
2393         }
2394     }
2395
2396     return(pLocalIDs);
2397
2398 }   /* END OF FUNCTION GetListOfOccupiedWorkspaces */
2399
2400 \f
2401 /******************************<->*************************************
2402  *
2403  *   HonorAbsentMapBehavior(pCD)
2404  *
2405  *
2406  *  Description:
2407  *  -----------
2408  *  This function adds a client to the current workspace and
2409  *   if (pCD->absentMapBehavior == AMAP_BEHAVIOR_MOVE)
2410  *  removes the client from the other  workspaces 
2411  *
2412  *
2413  *  Inputs:
2414  *  ------
2415  *  pCD = pointer to client data
2416  * 
2417  *  Outputs:
2418  *  -------
2419  *
2420  ******************************<->***********************************/
2421
2422 void 
2423 HonorAbsentMapBehavior(
2424         ClientData *pCD)
2425 {
2426     int inWorkspace = 0;
2427
2428     if (pCD->absentMapBehavior == AMAP_BEHAVIOR_MOVE)
2429     {
2430         int wsCnt;
2431
2432         /* 
2433          * Remove from other workspaces
2434          */
2435         for (wsCnt = 0; wsCnt < pCD->numInhabited; wsCnt = inWorkspace)
2436         {
2437             if (pCD->pWsList[wsCnt].wsID != pCD->pSD->pActiveWS->id)
2438             {
2439                 RemoveClientFromWorkspaces (pCD, 
2440                                             &pCD->pWsList[wsCnt].wsID, 1);
2441             }
2442             else inWorkspace++;
2443         }
2444     }
2445
2446     if (inWorkspace == 0)
2447         AddClientToWorkspaces (pCD, &ACTIVE_WS->id, 1);
2448
2449 }   /* END OF FUNCTION HonorAbsentMapBehavior */
2450
2451
2452 \f
2453 /******************************<->*************************************
2454  *
2455  *  RemoveClientFromWorkspaces (pCD, pIDs, numIDs)
2456  *
2457  *
2458  *  Description:
2459  *  -----------
2460  *  This function removes a client from a list of workspaces
2461  *
2462  *  Inputs:
2463  *  ------
2464  *  pCD = pointer to client data
2465  *  pIDs = pointer to a list of workspace IDs
2466  *  numIDs = number of workspace IDs
2467  * 
2468  *  Outputs:
2469  *  -------
2470  *
2471  ******************************<->***********************************/
2472
2473 void 
2474 RemoveClientFromWorkspaces(
2475         ClientData *pCD,
2476         WorkspaceID *pIDs,
2477         unsigned int numIDs )
2478
2479 {
2480     ClientData *pcdLeader;
2481
2482     pcdLeader = (pCD->transientLeader) ? FindTransientTreeLeader (pCD) : pCD;
2483
2484     RemoveSubtreeFromWorkspaces (pcdLeader, pIDs, numIDs);
2485
2486
2487 }   /* END OF FUNCTION RemoveClientFromWorkspaces */
2488
2489 \f
2490 /*************************************<->*************************************
2491  *
2492  *  AddSingleClientToWorkspaces (pCD, pIDs, numIDs)
2493  *
2494  *
2495  *  Description:
2496  *  -----------
2497  *  This function adds a single client to a list of workspaces
2498  *
2499  *  Inputs:
2500  *  ------
2501  *  pCD = pointer to client data
2502  *  pIDs = pointer to a list of workspace IDs
2503  *  numIDs = number of workspace IDs
2504  * 
2505  *  Outputs:
2506  *  -------
2507  *
2508  *************************************<->***********************************/
2509
2510 void 
2511 AddSingleClientToWorkspaces(
2512         ClientData *pCD,
2513         WorkspaceID *pIDs,
2514         unsigned int numIDs )
2515
2516 {
2517     int i;
2518     WmWorkspaceData *pWS;
2519
2520     for (i=0; i < numIDs; i++)
2521     {
2522         /*
2523          *  Add the client to the specified workspaces if 
2524          *  it is not already there.
2525          */
2526         if ((pWS = GetWorkspaceData (pCD->pSD, pIDs[i])) &&
2527             (!ClientInWorkspace (pWS, pCD)))
2528         {
2529             PutClientIntoWorkspace (pWS, pCD);
2530
2531             if ((pWS == PSD_FOR_CLIENT(pCD)->pActiveWS) &&
2532                 (pCD->transientLeader == NULL) &&
2533                 (pCD->clientState & UNSEEN_STATE))
2534             {
2535                 SetClientState (pCD, 
2536                     (pCD->clientState & ~UNSEEN_STATE), CurrentTime);
2537             }
2538
2539             /* 
2540              * Update the presence property (only on transient leader)
2541              */
2542             UpdateWorkspacePresenceProperty (pCD);
2543
2544         }
2545     }
2546 } /* END OF FUNCTION AddSingleClientToWorkspace */
2547
2548 \f
2549 /*************************************<->*************************************
2550  *
2551  *  AddSubtreeToWorkspaces (pCD, pIDs, numIDs)
2552  *
2553  *
2554  *  Description:
2555  *  -----------
2556  *  This function adds a client subtree to a list of workspaces
2557  *
2558  *  Inputs:
2559  *  ------
2560  *  pCD = pointer to client data (head of subtree)
2561  *  pIDs = pointer to a list of workspace IDs
2562  *  numIDs = number of workspace IDs
2563  * 
2564  *  Outputs:
2565  *  -------
2566  *
2567  *************************************<->***********************************/
2568
2569 void 
2570 AddSubtreeToWorkspaces(
2571         ClientData *pCD,
2572         WorkspaceID *pIDs,
2573         unsigned int numIDs )
2574
2575 {
2576     ClientData *pNext;
2577
2578     pNext = pCD->transientChildren;
2579     while (pNext)
2580     {
2581         /* process all children first */
2582         if (pNext->transientChildren)
2583         {
2584             AddSubtreeToWorkspaces (pNext, pIDs, numIDs);
2585         }
2586         else
2587         {
2588             AddSingleClientToWorkspaces (pNext, pIDs, numIDs);
2589         }
2590         pNext = pNext->transientSiblings;
2591     }
2592
2593     /* process the primary window */
2594     AddSingleClientToWorkspaces (pCD, pIDs, numIDs);
2595
2596
2597 }   /* END OF FUNCTION AddSubtreeToWorkspaces */
2598
2599 \f
2600 /*************************************<->*************************************
2601  *
2602  *  AddClientToWorkspaces (pCD, pIDs, numIDs)
2603  *
2604  *
2605  *  Description:
2606  *  -----------
2607  *  This function adds a transient tree to a list of workspaces
2608  *
2609  *  Inputs:
2610  *  ------
2611  *  pCD = pointer to client data
2612  *  pIDs = pointer to a list of workspace IDs
2613  *  numIDs = number of workspace IDs
2614  * 
2615  *  Outputs:
2616  *  -------
2617  *
2618  *************************************<->***********************************/
2619
2620 void 
2621 AddClientToWorkspaces(
2622         ClientData *pCD,
2623         WorkspaceID *pIDs,
2624         unsigned int numIDs )
2625
2626 {
2627     ClientData *pcdLeader;
2628
2629     pcdLeader = (pCD->transientLeader) ? FindTransientTreeLeader (pCD) : pCD;
2630
2631     AddSubtreeToWorkspaces (pcdLeader, pIDs, numIDs);
2632
2633 }   /* END OF FUNCTION AddClientToWorkspaces */
2634
2635
2636 \f
2637 /*************************************<->*************************************
2638  *
2639  *  AddClientToWsList (pWS, pCD)
2640  *
2641  *
2642  *  Description:
2643  *  -----------
2644  *  This function adds a client to a list of clients in a workspace
2645  *
2646  *  Inputs:
2647  *  ------
2648  *  pCD = pointer to client data
2649  *  pWS = pointer to workspace data
2650  * 
2651  *  Outputs:
2652  *  -------
2653  *  none
2654  *
2655  *************************************<->***********************************/
2656
2657 void 
2658 AddClientToWsList(
2659         WmWorkspaceData *pWS,
2660         ClientData *pCD )
2661
2662 {
2663     if (pWS->numClients >= pWS->sizeClientList)
2664     {
2665         if (pWS->sizeClientList == 0)
2666         {
2667             pWS->ppClients = (ClientData **) 
2668                 XtMalloc (WINDOW_ALLOC_AMOUNT * sizeof(ClientData *));
2669         }
2670         else
2671         {
2672             pWS->ppClients = (ClientData **) 
2673                 XtRealloc ((char *)pWS->ppClients, 
2674                          (pWS->sizeClientList + WINDOW_ALLOC_AMOUNT) * 
2675                          sizeof(ClientData *));
2676         }
2677
2678         if (!pWS->ppClients)
2679         {
2680             Warning (((char *)GETMESSAGE(76, 9, "Insufficient memory to add window to workspace")));
2681             ExitWM(WM_ERROR_EXIT_VALUE);
2682         }
2683
2684         pWS->sizeClientList += WINDOW_ALLOC_AMOUNT;
2685     }
2686
2687     if (pWS->numClients < pWS->sizeClientList)
2688     {
2689         pWS->ppClients[pWS->numClients] = pCD;
2690         pWS->numClients++;
2691     }
2692 }   /* END OF FUNCTION AddClientToWsList */
2693
2694 \f
2695 /*************************************<->*************************************
2696  *
2697  *  RemoveClientFromWsList (pWS, pCD)
2698  *
2699  *
2700  *  Description:
2701  *  -----------
2702  *  This function removes a client from a list of clients in a workspace
2703  *
2704  *  Inputs:
2705  *  ------
2706  *  pCD = pointer to client data
2707  *  pWS = pointer to workspace data
2708  * 
2709  *  Outputs:
2710  *  -------
2711  *  none
2712  *
2713  *************************************<->***********************************/
2714
2715 void 
2716 RemoveClientFromWsList(
2717         WmWorkspaceData *pWS,
2718         ClientData *pCD )
2719
2720 {
2721     int src, dest;
2722
2723     for (dest = 0; dest < pWS->numClients; dest++)
2724     {
2725         if (pWS->ppClients[dest] == pCD)
2726         {
2727             break;
2728         }
2729     }
2730
2731     for (src = dest+1; src < pWS->numClients; src++, dest++)
2732     {
2733         pWS->ppClients[dest] = pWS->ppClients[src];
2734     }
2735
2736     pWS->numClients--;
2737
2738 }   /* END OF FUNCTION RemoveClientFromWsList */
2739
2740 \f
2741 /*************************************<->*************************************
2742  *
2743  *  Boolean
2744  *  F_CreateWorkspace (args, pCD, event)
2745  *
2746  *  Description:
2747  *  -----------
2748  *
2749  *  Inputs:
2750  *  ------
2751  *  args = ...
2752  *  pCD = ...
2753  *  event = ...
2754  * 
2755  *  Outputs:
2756  *  -------
2757  *  Return = ...
2758  *
2759  *  Comments:
2760  *  --------
2761  * 
2762  *************************************<->***********************************/
2763
2764 Boolean 
2765 F_CreateWorkspace(
2766         String args,
2767         ClientData *pCD,
2768         XEvent *event )
2769
2770 {
2771     WmScreenData *pSD = ACTIVE_PSD;
2772
2773     if (pSD->numWorkspaces >= MAX_WORKSPACE_COUNT)
2774     {
2775         char buffer[MAXWMPATH];
2776         /*
2777          * At the maximum number of allowed workspaces.
2778          */
2779         sprintf (buffer, 
2780         ((char *)GETMESSAGE(76, 14, "Maximum number of workspaces is %d. New workspace was not created.")), MAX_WORKSPACE_COUNT);
2781         Warning (buffer);
2782     }
2783     else
2784     {
2785         CreateWorkspace (ACTIVE_PSD, (unsigned char *)args);
2786     }
2787
2788     return (TRUE);
2789
2790 } /* END OF FUNCTION F_CreateWorkspace */
2791
2792 \f
2793 /*************************************<->*************************************
2794  *
2795  *  Boolean
2796  *  F_DeleteWorkspace (args, pCD, event)
2797  *
2798  *  Description:
2799  *  -----------
2800  *
2801  *  Inputs:
2802  *  ------
2803  *  args = ...
2804  *  pCD = ...
2805  *  event = ...
2806  * 
2807  *  Outputs:
2808  *  -------
2809  *  Return = ...
2810  *
2811  *  Comments:
2812  *  --------
2813  * 
2814  *************************************<->***********************************/
2815
2816 Boolean 
2817 F_DeleteWorkspace(
2818         String args,
2819         ClientData *pCD,
2820         XEvent *event )
2821
2822 {
2823     WmScreenData *pSD = ACTIVE_PSD;
2824     WmWorkspaceData *pWS = NULL;
2825     int i;
2826
2827     if (args == NULL)
2828     {
2829         pWS= ACTIVE_WS;
2830     } 
2831     else
2832     {
2833         for (i=0; i<pSD->numWorkspaces; i++)
2834         {
2835             if (!strcmp(pSD->pWS[i].name, args))
2836             {
2837                 pWS = &(pSD->pWS[i]);
2838                 break;
2839             }
2840         }
2841     }
2842
2843     if (pWS)
2844         DeleteWorkspace (pWS);
2845
2846     return (TRUE);
2847
2848 } /* END OF FUNCTION F_DeleteWorkspace */
2849
2850 \f
2851 /*************************************<->*************************************
2852  *
2853  *  Boolean
2854  *  F_GotoWorkspace (args, pCD, event)
2855  *
2856  *  Description:
2857  *  -----------
2858  *
2859  *  Inputs:
2860  *  ------
2861  *  args = ...
2862  *  pCD = ...
2863  *  event = ...
2864  * 
2865  *  Outputs:
2866  *  -------
2867  *  Return = ...
2868  *
2869  *  Comments:
2870  *  --------
2871  * 
2872  *************************************<->***********************************/
2873
2874 Boolean 
2875 F_GotoWorkspace(
2876         String args,
2877         ClientData *pCD,
2878         XEvent *event )
2879
2880 {
2881     WorkspaceID wsID;
2882     WmWorkspaceData *pWS;
2883
2884     wsID = XInternAtom (DISPLAY, args, False);
2885     pWS = GetWorkspaceData (ACTIVE_PSD, wsID);
2886
2887     if (pWS)
2888     {
2889         ChangeToWorkspace (pWS);
2890     }
2891     return (TRUE);
2892
2893 } /* END OF FUNCTION F_GotoWorkspace */
2894
2895
2896
2897 \f
2898 /*************************************<->*************************************
2899  *
2900  *  Boolean
2901  *  F_AddToAllWorkspaces (args, pCD, event)
2902  *
2903  *
2904  *  Description:
2905  *  -----------
2906  *  Puts a client into all workspaces
2907  *
2908  *
2909  *  Inputs:
2910  *  ------
2911  *  args = ...
2912  *  pCD = pointer to client data
2913  *  event = ...
2914  *
2915  * 
2916  *  Outputs:
2917  *  -------
2918  *  Return = True
2919  *
2920  *
2921  *  Comments:
2922  *  --------
2923  *  The list of Ids returned has been privately allocated. Copy
2924  *  if you want to save or do anything with it.
2925  * 
2926  *************************************<->***********************************/
2927
2928 Boolean 
2929 F_AddToAllWorkspaces(
2930         String args,
2931         ClientData *pCD,
2932         XEvent *event )
2933
2934 {
2935     WmScreenData *pSD;
2936     int i;
2937
2938     if (pCD && (pCD->dtwmFunctions & DtWM_FUNCTION_OCCUPY_WS))
2939     {
2940         pSD = pCD->pSD;
2941
2942         ReserveIdListSpace (pSD->numWorkspaces);
2943
2944         for (i = 0; i < pSD->numWorkspaces; i++)
2945         {
2946             pResIDs[i] = pSD->pWS[i].id;
2947         }
2948
2949         AddClientToWorkspaces (pCD, pResIDs, pSD->numWorkspaces);
2950
2951         pCD->putInAll = True;
2952     }
2953
2954     return (True);
2955
2956 } /* END OF FUNCTION F_AddToAllWorkspaces */
2957
2958 \f
2959 /*************************************<->*************************************
2960  *
2961  *  Boolean
2962  *  F_Remove (args, pCD, event)
2963  *
2964  *
2965  *  Description:
2966  *  -----------
2967  *  Removes a client from the current workspace
2968  *
2969  *
2970  *  Inputs:
2971  *  ------
2972  *  args = ...
2973  *  pCD = pointer to client data
2974  *  event = ...
2975  *
2976  * 
2977  *  Outputs:
2978  *  -------
2979  *  Return = True
2980  *
2981  *
2982  *  Comments:
2983  *  --------
2984  * 
2985  *************************************<->***********************************/
2986
2987 Boolean 
2988 F_Remove(
2989         String args,
2990         ClientData *pCD,
2991         XEvent *event )
2992
2993 {
2994     Boolean rval = False;
2995
2996     /*
2997      * Only remove if in more than one workspace.
2998      */
2999     if ((pCD && (pCD->dtwmFunctions & DtWM_FUNCTION_OCCUPY_WS)) &&
3000         (pCD->numInhabited > 1))
3001     {
3002         if (ClientInWorkspace (ACTIVE_WS, pCD))
3003         {
3004             RemoveClientFromWorkspaces (pCD, &ACTIVE_WS->id, 1);
3005             pCD->putInAll = False;
3006         }
3007     }
3008
3009     return (rval);
3010
3011 } /* END OF FUNCTION F_Remove */
3012
3013
3014 \f
3015 /*************************************<->*************************************
3016  *
3017  *  GetCurrentWorkspaceIndex (pSD)
3018  *
3019  *
3020  *  Description:
3021  *  -----------
3022  *  Returns an index into the screens array of workspace structures
3023  *  for the current workspace.
3024  *
3025  *
3026  *  Inputs:
3027  *  ------
3028  *
3029  * 
3030  *  Outputs:
3031  *  -------
3032  *
3033  *
3034  *  Comments:
3035  *  --------
3036  *************************************<->***********************************/
3037 int 
3038 GetCurrentWorkspaceIndex(
3039         WmScreenData *pSD )
3040 {
3041
3042     int i;
3043
3044     for (i = 0 ; i < pSD->numWorkspaces; i++)
3045     {
3046         if (pSD->pWS[i].id == pSD->pActiveWS->id)
3047         break;
3048     }
3049
3050     if (i >= pSD->numWorkspaces)
3051     {
3052         /* failed to find workspace!!! How did that happen??? */
3053         i = 0;
3054 #ifdef DEBUG
3055         Warning ("Failed to find workspace index");
3056 #endif /* DEBUG */
3057     }
3058
3059     return(i);
3060 } /* END OF FUNCTION GetCurrentWorkspaceIndex */
3061
3062 \f
3063 /*************************************<->*************************************
3064  *
3065  *  void
3066  *  InsureIconForWorkspace (pWS, pCD)
3067  *
3068  *
3069  *  Description:
3070  *  -----------
3071  *  Makes sure an icon exists for the workspace
3072  *
3073  *
3074  *  Inputs:
3075  *  ------
3076  *
3077  * 
3078  *  Outputs:
3079  *  -------
3080  *
3081  *  Comments:
3082  *  --------
3083  * 
3084  *************************************<->***********************************/
3085
3086 void 
3087 InsureIconForWorkspace(
3088         WmWorkspaceData *pWS,
3089         ClientData *pCD )
3090
3091 {
3092     WsClientData *pWsc;
3093
3094     if (pCD->clientFunctions & MWM_FUNC_MINIMIZE)
3095     {
3096         pWsc = GetWsClientData (pWS, pCD);
3097
3098         if ((pCD->pSD->useIconBox) && 
3099             (!(pCD->clientFlags & (CLIENT_WM_CLIENTS | FRONT_PANEL_BOX))))
3100         {
3101             /*
3102              * Create a new widget for the icon box
3103              */
3104             if (MakeIcon (pWS, pCD)) 
3105             {
3106                 XSaveContext (DISPLAY, pWsc->iconFrameWin, 
3107                         wmGD.windowContextType, (caddr_t)pCD);
3108
3109                 if (pCD->iconWindow && pWsc->iconFrameWin)
3110                 {
3111                     XGrabButton (DISPLAY, AnyButton, AnyModifier, 
3112                         pWsc->iconFrameWin, True,
3113                         ButtonPressMask|ButtonReleaseMask|
3114                             ButtonMotionMask,
3115                         GrabModeAsync, GrabModeAsync, None, 
3116                         wmGD.workspaceCursor);
3117                 }
3118
3119                 ShowClientIconState (pCD, (pCD->clientState & ~UNSEEN_STATE));
3120             }
3121         }
3122         else
3123         {
3124             /* 
3125              * Reuse existing icon in new workspaces. Suggest
3126              * icon position in current WS as position of icon
3127              * in new WS.
3128              */
3129             pWsc->iconFrameWin = pCD->pWsList[0].iconFrameWin;
3130             pWsc->iconX = ICON_X(pCD); 
3131             pWsc->iconY = ICON_Y(pCD);
3132
3133             if ((pCD->clientState & ~UNSEEN_STATE) != MINIMIZED_STATE)
3134             {
3135                 pWsc->iconPlace = NO_ICON_PLACE;
3136             }
3137             else if (!wmGD.iconAutoPlace)
3138             {
3139                 if (wmGD.positionIsFrame)
3140                 {
3141                     pWsc->iconX -= pCD->clientOffset.x;
3142                     pWsc->iconY -= pCD->clientOffset.y;
3143                 }
3144                 PlaceIconOnScreen (pCD, &pWsc->iconX, &pWsc->iconY);
3145             }
3146             else        /* icon auto placement */
3147             {
3148                 pWsc->iconPlace = 
3149                 CvtIconPositionToPlace (&pWS->IPData,
3150                                         pWsc->iconX, pWsc->iconY);
3151                 if (pWS->IPData.placeList[pWsc->iconPlace].pCD)
3152                 {
3153                     /* The spot is already occupied!  Find a 
3154                        spot nearby. */
3155                     pWsc->iconPlace = 
3156                     FindIconPlace (pCD, &pWS->IPData, pWsc->iconX,
3157                                 pWsc->iconY);
3158
3159                     if (pWsc->iconPlace == NO_ICON_PLACE)
3160                     {
3161                         /* Can't find a spot close by. Use the
3162                            next available slot */
3163                         pWsc->iconPlace = GetNextIconPlace (&pWS->IPData);
3164                         if (pWsc->iconPlace == NO_ICON_PLACE)
3165                         {
3166                             pWsc->iconPlace =
3167                                 CvtIconPositionToPlace (&pWS->IPData,
3168                                                 pCD->clientX,
3169                                                 pCD->clientY);
3170                         }
3171                     }
3172                 }
3173                 CvtIconPlaceToPosition (&pWS->IPData, pWsc->iconPlace, 
3174                                         &pWsc->iconX, &pWsc->iconY);
3175
3176                 
3177                 if (!(pWS->IPData.placeList[pWsc->iconPlace].pCD))
3178                 {
3179                     pWS->IPData.placeList[pWsc->iconPlace].pCD = pCD;
3180                 }
3181             }
3182         }
3183     }
3184 } /* END OF FUNCTION InsureIconForWorkspace */
3185
3186 \f
3187 /*************************************<->*************************************
3188  *
3189  *  Boolean
3190  *  GetLeaderPresence (pCD, pIDs, pnumIDs)
3191  *
3192  *
3193  *  Description:
3194  *  -----------
3195  *  Gets the workspace presence of the transient tree leader for a
3196  *  client.
3197  *
3198  *
3199  *  Inputs:
3200  *  ------
3201  *  pCD = pointer to client data
3202  *  ppIDs = pointer to pointer to list of workspace ids
3203  *  pnumIDs = pointer to number of workspace ids
3204  *
3205  * 
3206  *  Outputs:
3207  *  -------
3208  *  *ppIDS = list of workspace IDs
3209  *  *pnumIDs = number of workspace IDs in list
3210  *
3211  *  Return = true on success
3212  *
3213  *
3214  *  Comments:
3215  *  --------
3216  *  ID list is dynamically allocated, please XtFree() it when you're
3217  *  done.
3218  * 
3219  *************************************<->***********************************/
3220
3221 Boolean 
3222 GetLeaderPresence(
3223         ClientData *pCD,
3224         WorkspaceID **ppIDs,
3225         unsigned int *pnumIDs )
3226
3227 {
3228     ClientData *pcdLeader;
3229     int i;
3230     Boolean rval = False;
3231     WorkspaceID *pLocalIDs;
3232
3233     if ((pLocalIDs = (WorkspaceID *) XtMalloc (pCD->pSD->numWorkspaces *
3234         sizeof(WorkspaceID))) == NULL)
3235     {
3236         Warning (((char *)GETMESSAGE(76, 10, "Insufficient Memory (GetLeaderPresence)")));
3237         ExitWM (WM_ERROR_EXIT_VALUE);
3238     }
3239
3240     /*
3241      * Make up list of workspaces for primary window
3242      */
3243     if (pCD->transientLeader)
3244     {
3245         pcdLeader = FindTransientTreeLeader (pCD);
3246
3247         for (i = 0; i < pcdLeader->numInhabited; i++)
3248         {
3249             pLocalIDs[i] = pcdLeader->pWsList[i].wsID;
3250         }
3251
3252         *ppIDs = pLocalIDs;
3253         *pnumIDs = pcdLeader->numInhabited;
3254         rval = True;
3255     }
3256
3257     return (rval);
3258
3259 } /* END OF FUNCTION GetLeaderPresence */
3260
3261 \f
3262 /*************************************<->*************************************
3263  *
3264  *  Boolean
3265  *  GetMyOwnPresence (pCD, pIDs, pnumIDs)
3266  *
3267  *
3268  *  Description:
3269  *  -----------
3270  *  Returns the current workspace presence for the client
3271  *
3272  *
3273  *  Inputs:
3274  *  ------
3275  *  pCD = pointer to client data
3276  *  ppIDs = pointer to pointer to list of workspace ids
3277  *  pnumIDs = pointer to number of workspace ids
3278  *
3279  * 
3280  *  Outputs:
3281  *  -------
3282  *  *ppIDS = list of workspace IDs
3283  *  *pnumIDs = number of workspace IDs in list
3284  *
3285  *  Return = true on success
3286  *
3287  *
3288  *  Comments:
3289  *  --------
3290  *  ID list is dynamically allocated (by DtWsmGetWorkspacesOccupied).
3291  *  Please XtFree() it when you're done.
3292  * 
3293  *************************************<->***********************************/
3294
3295 Boolean 
3296 GetMyOwnPresence(
3297         ClientData *pCD,
3298         WorkspaceID **ppIDs,
3299         unsigned int *pnumIDs )
3300
3301 {
3302     Boolean rval = False;
3303     unsigned long nIDs = (unsigned long)*pnumIDs;
3304
3305     /*
3306      * Get the workspace presence property 
3307      */
3308     if (
3309 #ifdef HP_VUE
3310         (HasProperty (pCD, wmGD.xa_DT_WORKSPACE_PRESENCE) ||
3311          HasProperty (pCD, 
3312                       XmInternAtom (DISPLAY, _XA_VUE_WORKSPACE_PRESENCE, 
3313                       False)))
3314 #else /* HP_VUE */
3315         HasProperty (pCD, wmGD.xa_DT_WORKSPACE_PRESENCE) 
3316 #endif /* HP_VUE */
3317         && (DtWsmGetWorkspacesOccupied (DISPLAY, pCD->client, ppIDs,
3318                                        &nIDs) == Success))
3319     {
3320         if (nIDs)
3321         {
3322             rval = True;
3323         }
3324     }
3325     *pnumIDs = (unsigned int)nIDs;
3326
3327     return (rval);
3328
3329 } /* END OF FUNCTION GetMyOwnPresence */
3330
3331
3332 \f
3333 /*************************************<->*************************************
3334  *
3335  *  void
3336  *  ReserveIdListSpace (numIDs)
3337  *
3338  *
3339  *  Description:
3340  *  -----------
3341  *  Insures that there is enough room in our privately allocated
3342  *  list of workspace IDs
3343  *
3344  *
3345  *  Inputs:
3346  *  ------
3347  *  numIDs = number of workspace ids
3348  * 
3349  *  Outputs:
3350  *  -------
3351  *
3352  *  Comments:
3353  *  --------
3354  *************************************<->***********************************/
3355
3356 void 
3357 ReserveIdListSpace(
3358         int numIDs )
3359
3360 {
3361     if (numResIDs == 0)
3362     {
3363         pResIDs = (WorkspaceID *) 
3364                     XtMalloc (numIDs * sizeof (WorkspaceID));
3365         if (pResIDs)
3366         {
3367             numResIDs = numIDs;
3368         }
3369     }
3370     else if (numResIDs < numIDs)
3371     {
3372         pResIDs = (WorkspaceID *) XtRealloc ((char *)pResIDs, 
3373                                         numIDs * sizeof (WorkspaceID));
3374
3375         numResIDs = (pResIDs)? numIDs : 0;
3376     }
3377
3378     if (pResIDs == NULL)
3379     {
3380         Warning (((char *)GETMESSAGE(76, 11, "Insufficient memory")));
3381         ExitWM (WM_ERROR_EXIT_VALUE);
3382     }
3383
3384 } /* END OF FUNCTION ReserveIdListSpace */
3385
3386
3387
3388 \f
3389 /******************************<->*************************************
3390  *
3391  *  SaveResources (pSD)
3392  *
3393  *  Description:
3394  *  -----------
3395  *  Saves dtwm resources to restore session
3396  *
3397  *  Inputs:
3398  *  ------
3399  *  pSD = pointer to screen data
3400  *
3401  *  Outputs:
3402  *  -------
3403  *  None
3404  *
3405  *  Comments:
3406  *  ---------
3407  *
3408  *************************************<->***********************************/
3409 void
3410 SaveResources( WmScreenData *pSD)
3411 {
3412     int wsCnt;
3413     WmPanelistObject  pPanelist;
3414
3415     if(pSD)
3416     {
3417         if (pSD->pActiveWS)
3418         {
3419             SaveWorkspaceResources(pSD->pActiveWS, 
3420                                    (WM_RES_INITIAL_WORKSPACE |
3421                                     WM_RES_WORKSPACE_COUNT));
3422         }
3423
3424         pPanelist = (WmPanelistObject) pSD->wPanelist;
3425         if (pPanelist && O_Shell(pPanelist))
3426         {
3427             /* This is the front panel for the screen */
3428             SaveWorkspaceResources(pSD->pActiveWS, 
3429                                    WM_RES_FP_POSITION);
3430
3431
3432             /*  Call the fronto panel function to save its resources  */
3433             
3434             WmFrontPanelSessionSaveData();
3435         }
3436
3437
3438
3439         for (wsCnt = 0; wsCnt < pSD->numWorkspaces; wsCnt++)
3440         {
3441             if(pSD->useIconBox)
3442             {
3443                 SaveWorkspaceResources(&pSD->pWS[wsCnt], 
3444                                        WM_RES_ICONBOX_GEOMETRY);
3445             }
3446         } /* for wsCnt */
3447
3448         SaveHelpResources(pSD);
3449
3450     } /* if pSD */
3451
3452 } /* END OF FUNCTION SaveResources */
3453
3454 \f
3455 /******************************<->*************************************
3456  *
3457  *  SaveWorkspaceResource (pWS, flags)
3458  *
3459  *  Description:
3460  *  -----------
3461  *  Modifies the RESOURCE_MANAGER property to add update versions
3462  *  of the requested resources.
3463  *
3464  *  Inputs:
3465  *  ------
3466  *  pWS = pointer to workspace data
3467  *  
3468  *  Outputs:
3469  *  -------
3470  *  None
3471  *
3472  *  Comments:
3473  *  ---------
3474  *
3475  *************************************<->***********************************/
3476 void 
3477 SaveWorkspaceResources(
3478         WmWorkspaceData *pWS,
3479         unsigned long flags)
3480 {
3481     char *buffer = NULL;
3482     int bufferLength = 0;
3483     char *res_class;
3484     char *data;
3485     int cum_len;
3486
3487     char screenName[1024];
3488     char tmpScreenName[10];
3489
3490     Position clientX;
3491     Position clientY;
3492     Dimension clientWidth;
3493     Dimension clientHeight;
3494     int xoff, yoff;
3495     WmPanelistObject  pPanelist = (WmPanelistObject) pWS->pSD->wPanelist;
3496     ClientData *pCD_Panel ;
3497     char tmpBuffer[MAXWMPATH+1];
3498     int iLen;
3499
3500     /* allocate initial data space */
3501     if ((data = (char *) XtMalloc (MAXWMPATH+1)) == NULL)
3502     {
3503         Warning (((char *)
3504                   GETMESSAGE(76,12,"Insufficient memory to save resources")));
3505         Do_Quit_Mwm (False);
3506     }
3507     cum_len = 1;
3508     *data = '\0';
3509
3510     if (bufferLength == 0)
3511     {
3512         buffer = (char *) XtMalloc (MAXWMPATH+1);
3513         bufferLength = MAXWMPATH;
3514     }
3515     *buffer = '\0';
3516
3517     /* Get our current resource class */
3518
3519     if (MwmBehavior)
3520     {
3521         res_class = WM_RESOURCE_CLASS;
3522     }
3523     else 
3524     {
3525         res_class = DT_WM_RESOURCE_CLASS;
3526     }
3527
3528     strcpy(screenName, "*");
3529     strcat(screenName,XtName (pWS->pSD->screenTopLevelW)); 
3530
3531     /* construct and write out the resources specification */
3532
3533     if (flags & WM_RES_BACKDROP_IMAGE)
3534     {
3535         iLen = (strlen (res_class) + strlen (screenName) +
3536              strlen (pWS->name) + strlen (WmNbackdrop) +
3537              strlen (WmNimage) + strlen (pWS->backdrop.image) + 20);
3538             
3539         if (iLen > bufferLength)
3540         {
3541             bufferLength += iLen;
3542             buffer = (char *) 
3543                 XtRealloc (buffer, bufferLength * sizeof(char));
3544         }
3545
3546         sprintf (buffer, "%s%s*%s*%s*%s:  %s\n", res_class,
3547                 screenName, pWS->name, 
3548                 WmNbackdrop, WmNimage, pWS->backdrop.image);
3549
3550         AddStringToResourceData (buffer, &data, &cum_len);
3551     }
3552
3553
3554     if (flags & WM_RES_WORKSPACE_TITLE)
3555     {
3556         String asciiName;
3557
3558         asciiName = WmXmStringToString (pWS->title);
3559
3560         iLen = strlen (res_class) + strlen (screenName) +
3561                strlen (pWS->name) + strlen (WmNtitle) +
3562                strlen (asciiName) + 16;
3563
3564         if (iLen > bufferLength)
3565         {
3566             bufferLength += iLen;
3567             buffer = (char *) 
3568                 XtRealloc (buffer, bufferLength * sizeof(char));
3569         }
3570
3571         sprintf (buffer, "%s%s*%s*%s:  %s\n", res_class,
3572                 screenName, pWS->name, 
3573                 WmNtitle, asciiName);
3574
3575         AddStringToResourceData (buffer, &data, &cum_len);
3576
3577         XtFree (asciiName);
3578     }
3579
3580     if ((flags & WM_RES_INITIAL_WORKSPACE) &&
3581         (!wmGD.useStandardBehavior))
3582     {
3583         iLen = strlen (res_class) + strlen (screenName) +
3584                strlen (WmNinitialWorkspace) + strlen (pWS->name) + 14;
3585
3586         if (iLen > bufferLength)
3587         {
3588             bufferLength += iLen;
3589             buffer = (char *) 
3590                 XtRealloc (buffer, bufferLength * sizeof(char));
3591         }
3592
3593         sprintf (buffer, "%s%s*%s:  %s\n", res_class,
3594                 screenName, 
3595                 WmNinitialWorkspace, pWS->name);
3596
3597         AddStringToResourceData (buffer, &data, &cum_len);
3598     }
3599
3600     if ((flags & WM_RES_WORKSPACE_LIST) &&
3601         (!wmGD.useStandardBehavior))
3602     {
3603         WmWorkspaceData *pWSi;
3604         char *pchQname;
3605         int i;
3606
3607         pWSi = pWS->pSD->pWS;
3608
3609         pchQname = (char *) _DtWmParseMakeQuotedString (
3610                                         (unsigned char *)pWSi->name);
3611         strcpy ((char *)wmGD.tmpBuffer, pchQname);
3612         XtFree (pchQname);
3613         pWSi++;
3614
3615
3616         for (i=1; i<pWS->pSD->numWorkspaces; i++, pWSi++)
3617         {
3618             strcat ((char *)wmGD.tmpBuffer, " ");
3619             pchQname = (char *) _DtWmParseMakeQuotedString (
3620                                         (unsigned char *)pWSi->name);
3621             strcat ((char *)wmGD.tmpBuffer, pchQname);
3622             XtFree (pchQname);
3623         }
3624
3625         sprintf (buffer, "%s%s*%s:  %s\n", res_class,
3626                 screenName, 
3627                 WmNworkspaceList, wmGD.tmpBuffer);
3628
3629         AddStringToResourceData (buffer, &data, &cum_len);
3630     }
3631
3632     if ((flags & WM_RES_WORKSPACE_COUNT) &&
3633         (!wmGD.useStandardBehavior))
3634     {
3635         char pchNumWs[20];
3636
3637         sprintf (pchNumWs, "%d", pWS->pSD->numWorkspaces);
3638
3639         iLen = strlen (res_class) + strlen (screenName) +
3640                strlen (WmNworkspaceCount) + strlen (pchNumWs) + 14;
3641
3642         if (iLen > bufferLength)
3643         {
3644             bufferLength += iLen;
3645             buffer = (char *) 
3646                 XtRealloc (buffer, bufferLength * sizeof(char));
3647         }
3648
3649         sprintf (buffer, "%s%s*%s:  %s\n", res_class,
3650                 screenName, 
3651                 WmNworkspaceCount, pchNumWs);
3652
3653         AddStringToResourceData (buffer, &data, &cum_len);
3654     }
3655
3656     if ((flags & WM_RES_FP_POSITION) &&
3657         (O_Shell(pPanelist)) && 
3658         (!wmGD.useStandardBehavior) &&
3659         (!XFindContext (DISPLAY, XtWindow(O_Shell(pPanelist)),
3660                                           wmGD.windowContextType, 
3661                                           (XtPointer)&pCD_Panel)))
3662     {
3663         Position midX, midY, tmpX, tmpY;
3664         Dimension screenWidth, screenHeight;
3665
3666         clientX = pCD_Panel->clientX;
3667         clientY = pCD_Panel->clientY;
3668
3669         /*
3670          *  Determine quadrant that the front panel midpoint is
3671          *  in and save front panel with appropriate gravity.
3672          */
3673
3674         /* find panel midpoint */
3675
3676         midX = clientX+(pCD_Panel->clientWidth >> 1);
3677         midY = clientY+(pCD_Panel->clientHeight >> 1);
3678
3679         /* get screen dimensions */
3680
3681         screenWidth = XDisplayWidth (DISPLAY, pCD_Panel->pSD->screen);
3682         screenHeight = XDisplayHeight (DISPLAY, pCD_Panel->pSD->screen);
3683
3684         /*
3685          * Determine midpoint quadrant and set up client geometry
3686          * relative to that corner. Adjust if positionIsFrame 
3687          * is being used.
3688          */
3689         if (midX <= (Position) screenWidth/2)
3690         {
3691             if(wmGD.positionIsFrame)
3692             {
3693                 clientX -= pCD_Panel->frameInfo.upperBorderWidth;
3694             }
3695
3696             /* West */
3697             if (midY <= (Position) screenHeight/2)
3698             {
3699                 /* NorthWest */
3700                 if(wmGD.positionIsFrame)
3701                 {
3702                     clientY -= (pCD_Panel->frameInfo.upperBorderWidth +
3703                                 pCD_Panel->frameInfo.titleBarHeight);
3704                 }
3705                 sprintf (tmpBuffer, "+%d+%d", clientX, clientY);
3706             }
3707             else
3708             {
3709                 /* SouthWest */
3710                 clientY = screenHeight - clientY - pCD_Panel->clientHeight;
3711                 if(wmGD.positionIsFrame)
3712                 {
3713                     clientY -= pCD_Panel->frameInfo.lowerBorderWidth;
3714                 }
3715
3716                 sprintf (tmpBuffer, "+%d-%d", clientX, clientY);
3717             }
3718         }
3719         else
3720         {
3721             clientX = screenWidth - clientX - pCD_Panel->clientWidth;
3722             if (wmGD.positionIsFrame)
3723             {
3724                 clientX -= pCD_Panel->frameInfo.lowerBorderWidth;
3725             }
3726
3727             /* East */
3728             if (midY <= (Position) screenHeight/2)
3729             {
3730                 /* NorthEast */
3731                 if(wmGD.positionIsFrame)
3732                 {
3733                     clientY -= (pCD_Panel->frameInfo.upperBorderWidth +
3734                                 pCD_Panel->frameInfo.titleBarHeight);
3735                 }
3736                 sprintf (tmpBuffer, "-%d+%d", clientX, clientY);
3737             }
3738             else
3739             {
3740                 /* SouthEast */
3741                 clientY = screenHeight - clientY - pCD_Panel->clientHeight;
3742                 if(wmGD.positionIsFrame)
3743                 {
3744                     clientY -= pCD_Panel->frameInfo.lowerBorderWidth;
3745                 }
3746                 sprintf (tmpBuffer, "-%d-%d", clientX, clientY);
3747             }
3748         }
3749
3750         iLen = strlen (res_class) + strlen (screenName) +
3751                strlen (XtName(O_Shell(pPanelist))) + 
3752                strlen (WmNgeometry) + strlen (tmpBuffer) + 18;
3753
3754         if (iLen > bufferLength)
3755         {
3756             bufferLength += iLen;
3757             buffer = (char *) 
3758                 XtRealloc (buffer, bufferLength * sizeof(char));
3759         }
3760
3761         sprintf (buffer, "%s%s*%s*%s:  %s\n", res_class,
3762                  screenName, 
3763                  XtName (O_Shell(pPanelist)), 
3764                  WmNgeometry, tmpBuffer);
3765
3766         AddStringToResourceData (buffer, &data, &cum_len);
3767     }
3768
3769     if ((flags & WM_RES_ICONBOX_GEOMETRY) &&
3770         (!wmGD.useStandardBehavior))
3771     {
3772         /* update iconbox geometry string */
3773
3774         if (pWS->iconBoxGeometry)
3775         {
3776             XtFree((char *) (pWS->iconBoxGeometry));
3777             pWS->iconBoxGeometry = NULL;
3778         }
3779
3780         clientWidth = (pWS->pIconBox->pCD_iconBox->clientWidth - 
3781                        pWS->pIconBox->pCD_iconBox->baseWidth) /
3782                            pWS->pIconBox->pCD_iconBox->widthInc;
3783
3784         clientHeight = (pWS->pIconBox->pCD_iconBox->clientHeight - 
3785                         pWS->pIconBox->pCD_iconBox->baseHeight) /
3786                             pWS->pIconBox->pCD_iconBox->heightInc ;
3787
3788         if(wmGD.positionIsFrame)
3789         {
3790             CalculateGravityOffset (pWS->pIconBox->pCD_iconBox, &xoff, &yoff);
3791             clientX = pWS->pIconBox->pCD_iconBox->clientX - xoff;
3792             clientY = pWS->pIconBox->pCD_iconBox->clientY - yoff;
3793         }
3794         else
3795         {
3796             clientX = pWS->pIconBox->pCD_iconBox->clientX;
3797             clientY = pWS->pIconBox->pCD_iconBox->clientY;
3798         }
3799
3800         sprintf (buffer, "%dx%d+%d+%d", clientWidth, clientHeight,
3801                  clientX, clientY);
3802
3803         pWS->iconBoxGeometry  = strdup( buffer);
3804
3805         iLen = strlen (res_class) + strlen (screenName) +
3806                strlen (pWS->name) + strlen (WmNiconBoxGeometry) + 
3807                strlen (pWS->iconBoxGeometry) + 18;
3808
3809         if (iLen > bufferLength)
3810         {
3811             bufferLength += iLen;
3812             buffer = (char *) 
3813                 XtRealloc (buffer, bufferLength * sizeof(char));
3814         }
3815
3816         sprintf (buffer, "%s%s*%s*%s:  %s\n", res_class,
3817                 screenName, pWS->name, 
3818                 WmNiconBoxGeometry, pWS->iconBoxGeometry);
3819
3820         AddStringToResourceData (buffer, &data, &cum_len);
3821     }
3822
3823
3824    if (data)
3825    {
3826         /*
3827          * Merge in the resource(s)
3828          */
3829         _DtAddToResource (DISPLAY, data);
3830        XtFree(data);
3831    }
3832
3833    XtFree(buffer);
3834
3835 } /* END OF FUNCTION SaveWorkspaceResources */
3836
3837 \f
3838 /******************************<->*************************************
3839  *
3840  *  AddStringToResourceData (string, pdata, plen)
3841  *
3842  *  Description:
3843  *  -----------
3844  *  Adds a string to a growing buffer of strings. 
3845  *
3846  *  Inputs:
3847  *  ------
3848  *  string - string to add
3849  *  pdata - pointer to data pointer 
3850  *  plen - number of bytes used in *pdata already 
3851  * 
3852  *  Outputs:
3853  *  -------
3854  *  *pdata - data pointer  (may be changed by XtRealloc)
3855  *  *plen - number of bytes used in *pdata  (old value plus length 
3856  *          of string
3857  *
3858  *  Comments:
3859  *  ---------
3860  *
3861  *************************************<->***********************************/
3862 void 
3863 AddStringToResourceData(
3864         char *string,
3865         char **pdata,
3866         int *plen )
3867 {
3868     if ((*pdata = (char *) XtRealloc(*pdata, *plen+strlen(string)+1)) == NULL)
3869     {
3870         Warning (((char *)GETMESSAGE(76, 13, "Insufficient memory to save resources.")));
3871         Do_Quit_Mwm (False);
3872     }
3873
3874     strcat (*pdata, string);
3875     *plen += strlen(string);
3876 } /* END OF FUNCTION AddStringToResourceData */
3877
3878 \f
3879 /*************************************<->*************************************
3880  *
3881  *  DuplicateWorkspaceName (pSD, name, num)
3882  *
3883  *
3884  *  Description:
3885  *  -----------
3886  *  This function searches the first "num" workspace names to see if the
3887  *  passed "name" duplicates any workspace name defined so far.
3888  *
3889  *
3890  *  Inputs:
3891  *  ------
3892  *  pSD = pointer to screen data
3893  *  name = potential string name for workspace
3894  *  num = number of workspaces to check against
3895  * 
3896  *  Outputs:
3897  *  -------
3898  *  Return = True if a dupicate was found
3899  *
3900  *  Comments:
3901  *  --------
3902  * 
3903  *************************************<->***********************************/
3904 Boolean
3905 DuplicateWorkspaceName (WmScreenData *pSD, unsigned char *name, int num)
3906 {
3907     int i;
3908     Boolean duplicate = False;
3909
3910     if (pSD && pSD->pWS)
3911     {
3912         for (i = 0; (i < num) && !duplicate; i++)
3913         {
3914             if (!strcmp (pSD->pWS[i].name, (char *)name))
3915             {
3916                 duplicate = True;
3917             }
3918         }
3919     }
3920
3921     return (duplicate);
3922 }
3923
3924 #ifdef DEBUG
3925 int PrintWorkspaceList (pSD)
3926     WmScreenData *pSD;
3927 {
3928     int i, j, k;
3929     WmWorkspaceData *pWS;
3930     ClientData *pCD;
3931     ClientData *pClients[500];
3932     int numSaved = 0;
3933     Boolean Saved;
3934
3935     fprintf (stderr, "Screen: %d\n", pSD->screen);
3936
3937     for (i =0; i < pSD->numWorkspaces; i++)
3938     {
3939         pWS = &pSD->pWS[i];
3940
3941         fprintf (stderr, "\nWorkspace %s contains: \n", pWS->name);
3942
3943         for (j = 0; j < pWS->numClients; j++)
3944         {
3945             pCD = pWS->ppClients[j];
3946             fprintf (stderr, "\t%s\n", pCD->clientName);
3947
3948             Saved = False;
3949             for (k = 0; k < numSaved; k++)
3950             {
3951                 if (pCD == pClients[k]) 
3952                 {
3953                     Saved = True;
3954                     break;
3955                 }
3956             }
3957
3958             if (!Saved)
3959             {
3960                 pClients[numSaved++] = pCD;
3961             }
3962         }
3963     }
3964
3965     for (i = 0; i < numSaved; i++)
3966     {
3967         pCD = pClients[i];
3968         fprintf (stderr, "\nClient %s is in: \n", pCD->clientName);
3969         for (j = 0; j < pCD->numInhabited; j++)
3970         {
3971             pWS = GetWorkspaceData (pCD->pSD, pCD->pWsList[j].wsID);
3972             fprintf (stderr, "\t%s\n", pWS->name);
3973         }
3974
3975     }
3976 } /* END OF FUNCTION PrintWorkspaceList */
3977 #endif /* DEBUG */
3978