Link with C++ linker
[oweals/cde.git] / cde / programs / dtfile / ChangeDir.c
1 /*
2  * CDE - Common Desktop Environment
3  *
4  * Copyright (c) 1993-2012, The Open Group. All rights reserved.
5  *
6  * These libraries and programs are free software; you can
7  * redistribute them and/or modify them under the terms of the GNU
8  * Lesser General Public License as published by the Free Software
9  * Foundation; either version 2 of the License, or (at your option)
10  * any later version.
11  *
12  * These libraries and programs are distributed in the hope that
13  * they will be useful, but WITHOUT ANY WARRANTY; without even the
14  * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
15  * PURPOSE. See the GNU Lesser General Public License for more
16  * details.
17  *
18  * You should have received a copy of the GNU Lesser General Public
19  * License along with these librararies and programs; if not, write
20  * to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
21  * Floor, Boston, MA 02110-1301 USA
22  */
23 /* $XConsortium: ChangeDir.c /main/7 1996/10/30 11:09:35 drk $ */
24 /************************************<+>*************************************
25  ****************************************************************************
26  *
27  *   FILE:           ChangeDir.c
28  *
29  *   COMPONENT_NAME: Desktop File Manager (dtfile)
30  *
31  *   DESCRIPTION:    Source file for the change directory dialog.
32  *
33  *   FUNCTIONS: ChangeToNewDir
34  *              CheckRestrictedDir
35  *              Create
36  *              Destroy
37  *              DropOnChangeView
38  *              FreeValues
39  *              GetDefaultValues
40  *              GetResourceValues
41  *              GetValues
42  *              GoToNewDir
43  *              InstallChange
44  *              InstallClose
45  *              OkCallback
46  *              SetFocus
47  *              SetValues
48  *              TextChange
49  *              TryToChangeDir
50  *              WriteResourceValues
51  *
52  *   (c) Copyright 1993, 1994, 1995 Hewlett-Packard Company
53  *   (c) Copyright 1993, 1994, 1995 International Business Machines Corp.
54  *   (c) Copyright 1993, 1994, 1995 Sun Microsystems, Inc.
55  *   (c) Copyright 1993, 1994, 1995 Novell, Inc.
56  *
57  ****************************************************************************
58  ************************************<+>*************************************/
59
60 #include <signal.h>
61 #include <stdio.h>
62 #include <sys/types.h>
63 #include <sys/stat.h>
64
65 #ifdef __hpux
66 #include <sys/inode.h>
67 #endif
68
69 #include <ctype.h>
70 #include <pwd.h>
71
72 #include <Xm/XmP.h>
73 #include <Xm/Xm.h>
74 #include <Xm/MessageB.h>
75 #include <Xm/SelectioB.h>
76 #include <Xm/TextF.h>
77 #include <Xm/VendorSEP.h>
78 #include <Xm/List.h>
79 #include <Xm/MwmUtil.h>
80 #include <Xm/Protocols.h>
81
82 #include <X11/ShellP.h>
83 #include <X11/Shell.h>
84 #include <X11/Xatom.h>
85
86 #include <Dt/Action.h>
87 #include <Dt/Connect.h>
88 #include <Dt/DtNlUtils.h>
89
90 #include <Tt/tttk.h>
91
92 #include <Xm/DragIcon.h>
93 #include <Xm/DragC.h>
94 #include <Dt/Dnd.h>
95
96 #include "Encaps.h"
97 #include "SharedProcs.h"
98 #include "FileMgr.h"
99 #include "Desktop.h"
100 #include "Main.h"
101 #include "ChangeDir.h"
102 #include "Help.h"
103 #include "SharedMsgs.h"
104
105
106 #define MAX_PATH 1024
107
108 static char * CHANGEDIRECTORY = "ChangeDirectory";
109
110
111 static DialogResource resources[] =
112 {
113    { "string_path", XmRXmString, sizeof(XmString),
114      XtOffset(ChangeDirDataPtr, string_path), NULL, _DtXmStringToString },
115
116    { "historyList", XmRXmStringTable, sizeof(XmStringTable),
117       XtOffset(ChangeDirDataPtr, history_list), NULL, _DtXmStringTableToString },
118
119    { "visibleCount", XmRInt, sizeof(int),
120       XtOffset(ChangeDirDataPtr, visible_count), (XtPointer) 8, _DtIntToString },
121
122    { "listCount", XmRInt, sizeof(int),
123       XtOffset(ChangeDirDataPtr, list_count), NULL, _DtIntToString },
124 };
125
126
127 /********    Static Function Declarations    ********/
128
129 static void Create(     Display *display,
130                         Widget parent,
131                         Widget *shell,
132                         XtPointer *dialog) ;
133 static void InstallChange( ChangeDirRec *change_dir_rec,
134                            XtCallbackProc callback,
135                            XtPointer client_data) ;
136 static void InstallClose( ChangeDirRec *change_dir_rec,
137                           XtCallbackProc callback,
138                           XtPointer client_data) ;
139 static void Destroy( ChangeDirRec *change_dir_rec) ;
140 static XtPointer GetValues( ChangeDirRec *change_dir_rec) ;
141 static XtPointer GetDefaultValues( void ) ;
142 static XtPointer GetResourceValues( XrmDatabase data_base,
143                                   char **name_list) ;
144 static void SetValues( ChangeDirRec *change_dir_rec,
145                        ChangeDirData *change_dir_data) ;
146 static void WriteResourceValues( DialogData *values,
147                                  int fd,
148                                  char **name_list) ;
149 static void FreeValues( ChangeDirData *change_dir_data) ;
150 static Boolean TryToChangeDir( Boolean isFromDialog,
151                                char * incoming_string,
152                                FileMgrData * file_mgr_data,
153                                FileMgrRec * file_mgr_rec,
154                                ChangeDirData * change_dir_data,
155                                Widget selection_box,
156                                ChangeDirApply * apply_data,
157                                XmSelectionBoxCallbackStruct * callback_data,
158                                void (*callback)()) ;
159 static void OkCallback( Widget selection_box,
160                         ChangeDirApply *apply_data,
161                         XmSelectionBoxCallbackStruct *callback_data) ;
162 static int CheckRestrictedDir ( FileMgrRec * file_mgr_rec,
163                                 FileMgrData * file_mgr_data,
164                                 char ** value,
165                                 Boolean relative_name);
166 static void GoToNewDir ( FileMgrData * file_mgr_data,
167                          char * dir_name) ;
168 static void SetFocus(
169                         ChangeDirRec *change_dir_rec,
170                         ChangeDirData *change_dir_data) ;
171
172
173 /********    End Static Function Declarations    ********/
174
175 extern char *getwd(char *);
176
177 /*
178  *  The Dialog Class structure.
179  */
180
181 static DialogClass changeDirClassRec =
182 {
183    resources,
184    XtNumber(resources),
185    Create,
186    (DialogInstallChangeProc) InstallChange,
187    (DialogInstallCloseProc) InstallClose,
188    (DialogDestroyProc) Destroy,
189    (DialogGetValuesProc) GetValues,
190    GetDefaultValues,
191    GetResourceValues,
192    (DialogSetValuesProc) SetValues,
193    WriteResourceValues,
194    (DialogFreeValuesProc) FreeValues,
195    (DialogMapWindowProc) _DtGenericMapWindow,
196    (DialogSetFocusProc) SetFocus,
197 };
198
199 DialogClass * changeDirClass = (DialogClass *) &changeDirClassRec;
200
201
202
203
204 /************************************************************************
205  *
206  *  Create
207  *
208  ************************************************************************/
209
210 static void
211 Create(
212         Display *display,
213         Widget parent,
214         Widget *shell,
215         XtPointer *dialog )
216 {
217    ChangeDirRec * change_dir_rec;
218    XmString prompt;
219    Widget w;
220    Arg args[8];
221    int n;
222    XtTranslations trans_table;
223    Widget change_dir;
224
225
226    /*  Allocate the change directory dialog instance record.  */
227
228    change_dir_rec = (ChangeDirRec *) XtMalloc (sizeof (ChangeDirRec));
229
230    prompt = XmStringCreateLocalized (((char *)GETMESSAGE(2,14, "Destination Folder:")));
231
232    trans_table = XtParseTranslationTable(translations_space);
233    n = 0;
234    XtSetArg (args[n], XmNselectionLabelString, prompt);         n++;
235    XtSetArg (args[n], XmNokLabelString, okXmString);            n++;
236    XtSetArg (args[n], XmNcancelLabelString, cancelXmString);    n++;
237    XtSetArg (args[n], XmNhelpLabelString, helpXmString);        n++;
238    XtSetArg (args[n], XmNautoUnmanage, False);                  n++;
239    XtSetArg (args[n], XmNtextTranslations, trans_table);        n++;
240    change_dir = change_dir_rec->change_dir =
241       XmCreateSelectionDialog (parent, "change_directory", args, n);
242    change_dir_rec->shell = XtParent(change_dir);
243
244    XmStringFree (prompt);
245
246    /* Add the help callback to each of the important sub-components */
247    XtAddCallback(change_dir, XmNhelpCallback, (XtCallbackProc)HelpRequestCB,
248                  HELP_CHANGEDIR_DIALOG_STR);
249    w = XmSelectionBoxGetChild(change_dir, XmDIALOG_APPLY_BUTTON);
250    XtAddCallback(w, XmNhelpCallback, (XtCallbackProc)HelpRequestCB,
251                  HELP_CHANGEDIR_DIALOG_STR);
252    w = XmSelectionBoxGetChild(change_dir, XmDIALOG_CANCEL_BUTTON);
253    XtAddCallback(w, XmNhelpCallback, (XtCallbackProc)HelpRequestCB,
254                  HELP_CHANGEDIR_DIALOG_STR);
255    w = XmSelectionBoxGetChild(change_dir, XmDIALOG_HELP_BUTTON);
256    XtAddCallback(w, XmNhelpCallback, (XtCallbackProc)HelpRequestCB,
257                  HELP_CHANGEDIR_DIALOG_STR);
258    XtAddCallback(w, XmNactivateCallback, (XtCallbackProc)HelpRequestCB,
259                  HELP_CHANGEDIR_DIALOG_STR);
260    w = XmSelectionBoxGetChild(change_dir, XmDIALOG_OK_BUTTON);
261    XtAddCallback(w, XmNhelpCallback, (XtCallbackProc)HelpRequestCB,
262                  HELP_CHANGEDIR_DIALOG_STR);
263    w = XmSelectionBoxGetChild(change_dir, XmDIALOG_LIST);
264    XtAddCallback(XtParent(w), XmNhelpCallback, (XtCallbackProc)HelpRequestCB,
265                  HELP_CHANGEDIR_DIALOG_STR);
266    w = XmSelectionBoxGetChild(change_dir, XmDIALOG_LIST_LABEL);
267    XtAddCallback(w, XmNhelpCallback, (XtCallbackProc)HelpRequestCB,
268                  HELP_CHANGEDIR_DIALOG_STR);
269    w = XmSelectionBoxGetChild(change_dir, XmDIALOG_SELECTION_LABEL);
270    XtAddCallback(w, XmNhelpCallback, (XtCallbackProc)HelpRequestCB,
271                  HELP_CHANGEDIR_DIALOG_STR);
272    w = XmSelectionBoxGetChild(change_dir, XmDIALOG_TEXT);
273    XtAddCallback(w, XmNhelpCallback, (XtCallbackProc)HelpRequestCB,
274                  HELP_CHANGEDIR_DIALOG_STR);
275
276
277    /*  Adjust the margin widths and heights of each of the buttons  */
278
279    XtSetArg (args[0], XmNmarginWidth, 6);
280    XtSetArg (args[1], XmNmarginHeight, 2);
281
282    w = XmSelectionBoxGetChild (change_dir_rec->change_dir, XmDIALOG_OK_BUTTON);
283    XtSetValues (w, args, 2);
284
285    w = XmSelectionBoxGetChild (change_dir_rec->change_dir,
286                                                          XmDIALOG_HELP_BUTTON);
287    XtSetValues (w, args, 2);
288
289    w = XmSelectionBoxGetChild (change_dir_rec->change_dir,
290                                                        XmDIALOG_CANCEL_BUTTON);
291    XtSetValues (w, args, 2);
292
293    XtUnmanageChild(XmSelectionBoxGetChild (change_dir_rec->change_dir,
294                    XmDIALOG_APPLY_BUTTON));
295
296
297    /*  Adjust the decorations for the dialog shell of the dialog  */
298
299    XtSetArg(args[0], XmNmwmFunctions, MWM_FUNC_MOVE | MWM_FUNC_CLOSE);
300    XtSetArg(args[1], XmNmwmDecorations,
301              MWM_DECOR_BORDER | MWM_DECOR_TITLE);
302    XtSetValues (change_dir_rec->shell, args, 2);
303
304    XtSetArg(args[0], XmNcancelButton, w);
305    XtSetValues (change_dir_rec->change_dir, args, 1);
306
307    /*  Set the return values for the dialog widget and dialog instance.  */
308
309    *shell = change_dir_rec->change_dir;
310    *dialog = (XtPointer) change_dir_rec;
311
312 }
313
314
315
316
317 /************************************************************************
318  *
319  *  InstallChange
320  *
321  ************************************************************************/
322
323 static void
324 InstallChange(
325         ChangeDirRec *change_dir_rec,
326         XtCallbackProc callback,
327         XtPointer client_data )
328 {
329    Widget selection_box = change_dir_rec->change_dir;
330    ChangeDirApply * apply_data;
331
332    /*  Setup the callback data to be sent to the Ok callback.   */
333    /*  This contains the encapsulation callback to invoke upon  */
334    /*  the data within the dialog being changed.                */
335
336    apply_data = (ChangeDirApply *) XtMalloc (sizeof (ChangeDirApply));
337    apply_data->callback = callback;
338    apply_data->client_data = client_data;
339    apply_data->change_dir_rec = (XtPointer) change_dir_rec;
340    change_dir_rec->apply_data = apply_data;
341
342    /*  Add the callbacks for list item insertion and help.  */
343
344    XtAddCallback (selection_box, XmNokCallback, (XtCallbackProc) OkCallback,
345                                                       (XtPointer) apply_data);
346 }
347
348
349
350
351 /************************************************************************
352  *
353  *  InstallClose
354  *
355  ************************************************************************/
356
357 static void
358 InstallClose(
359         ChangeDirRec *change_dir_rec,
360         XtCallbackProc callback,
361         XtPointer client_data )
362 {
363    Widget close_widget;
364    Atom delete_window_atom;
365
366    close_widget =
367       XmSelectionBoxGetChild (change_dir_rec->change_dir,
368                                              XmDIALOG_CANCEL_BUTTON);
369
370    XtAddCallback (close_widget, XmNactivateCallback, callback, client_data);
371
372    delete_window_atom = XmInternAtom (XtDisplay(change_dir_rec->shell),
373                                       "WM_DELETE_WINDOW", True);
374    XmRemoveWMProtocols( change_dir_rec->shell, &delete_window_atom, 1 );
375    XmAddWMProtocolCallback( change_dir_rec->shell, delete_window_atom, callback,
376                             (XtPointer)client_data );
377 }
378
379
380
381
382 /************************************************************************
383  *
384  *  Destroy
385  *
386  ************************************************************************/
387
388 static void
389 Destroy(
390         ChangeDirRec *change_dir_rec )
391 {
392    XtDestroyWidget (change_dir_rec->change_dir);
393    XtFree ((char *) change_dir_rec->apply_data);
394    XtFree ((char *) change_dir_rec);
395 }
396
397
398
399
400 /************************************************************************
401  *
402  *  GetValues
403  *
404  ************************************************************************/
405
406 static XtPointer
407 GetValues(
408         ChangeDirRec *change_dir_rec )
409 {
410    ChangeDirData * change_dir_data;
411    Arg args[8];
412    register int n;
413    XmStringTable history_list;
414    XmString      string_path;
415
416
417    /*  Allocate and initialize the change dir dialog data.  */
418
419    change_dir_data = (ChangeDirData *) XtMalloc (sizeof (ChangeDirData));
420
421    change_dir_data->displayed = True;
422    change_dir_data->host_name = NULL;
423    change_dir_data->file_mgr_rec = NULL;
424
425    n = 0;
426    XtSetArg (args[n], XmNx, &change_dir_data->x);               n++;
427    XtSetArg (args[n], XmNy, &change_dir_data->y);               n++;
428    XtSetArg (args[n], XmNwidth, &change_dir_data->width);               n++;
429    XtSetArg (args[n], XmNheight, &change_dir_data->height);             n++;
430    XtSetArg (args[n], XmNlistItemCount, &change_dir_data->list_count);  n++;
431    XtSetArg (args[n], XmNlistVisibleItemCount, &change_dir_data->visible_count);        n++;
432    XtSetArg (args[n], XmNtextString, &string_path);             n++;
433    XtSetArg (args[n], XmNlistItems, &history_list);             n++;
434    XtGetValues (change_dir_rec->change_dir, args, n);
435
436
437    /*  Extract and make local copies of the XmString data.  */
438
439    change_dir_data->history_list = (XmStringTable)
440       XtMalloc (sizeof(XmStringTable) * (change_dir_data->list_count + 1));
441
442    for (n = 0; n < change_dir_data->list_count; n++)
443       change_dir_data->history_list[n] = XmStringCopy (history_list[n]);
444    change_dir_data->history_list[n] = NULL;
445
446    if(change_dir_data->string_path)
447       XmStringFree (change_dir_data->string_path);
448    change_dir_data->string_path = XmStringCopy (string_path);
449
450    return ((XtPointer) change_dir_data);
451 }
452
453
454
455
456 /************************************************************************
457  *
458  *  GetDefaultValues
459  *
460  ************************************************************************/
461
462 static XtPointer
463 GetDefaultValues( void )
464 {
465    ChangeDirData * change_dir_data;
466
467
468    /*  Allocate and initialize the default change dir dialog data.  */
469
470    change_dir_data = (ChangeDirData *) XtMalloc (sizeof (ChangeDirData));
471
472    change_dir_data->displayed = False;
473    change_dir_data->x = 0;
474    change_dir_data->y = 0;
475    change_dir_data->height = 0;
476    change_dir_data->width = 0;
477    change_dir_data->string_path = NULL;
478
479 /*
480    This will cause users_home_dir to be displayed in
481    Application Manager go to dialog.
482
483    if(restrictMode)
484       change_dir_data->string_path =
485               XmStringCreateLocalized(users_home_dir, XmFONTLIST_DEFAULT_TAG);
486    else
487       change_dir_data->string_path = NULL;
488 */
489    change_dir_data->history_list = NULL;
490    change_dir_data->visible_count = 8;
491    change_dir_data->list_count = 0;
492    change_dir_data->host_name = NULL;
493    change_dir_data->file_mgr_rec = NULL;
494
495
496    return ((XtPointer) change_dir_data);
497 }
498
499
500
501
502 /************************************************************************
503  *
504  *  GetResourceValues
505  *
506  ************************************************************************/
507
508 static XtPointer
509 GetResourceValues(
510         XrmDatabase data_base,
511         char **name_list )
512 {
513    ChangeDirData * change_dir_data;
514    XmStringTable   new_table;
515    int i;
516
517
518    /*  Allocate and get the resources for change dir dialog data.  */
519
520    change_dir_data = (ChangeDirData *) XtMalloc (sizeof (ChangeDirData));
521
522    _DtDialogGetResources (data_base, name_list,
523                        CHANGEDIRECTORY, (char *) change_dir_data,
524                        resources, changeDirClass->resource_count);
525
526    change_dir_data->host_name = NULL;
527
528
529    /*  If the history list is Non-Null, realloc the pointer array  */
530    /*  one element larger and NULL out the new last element        */
531
532    if (change_dir_data->list_count != 0)
533    {
534       new_table = (XmStringTable) XtMalloc (sizeof (XmStringTable) *
535                                             (change_dir_data->list_count + 1));
536
537       for (i = 0; i < change_dir_data->list_count; i++)
538          new_table[i] = change_dir_data->history_list[i];
539
540       new_table[change_dir_data->list_count] = NULL;
541
542 /******************
543   THIS WILL BE A MEMORY HOLE WHEN MOTIF FIXES THE XMSTRINGTABLE
544   CONVERTER.  EITHER REALLOC THE RETURNED TABLE OR COPY AND FREE IT.
545 ******************/
546       change_dir_data->history_list = new_table;
547    }
548
549    return ((XtPointer) change_dir_data);
550 }
551
552
553
554
555 /************************************************************************
556  *
557  *  SetValues
558  *
559  ************************************************************************/
560
561 static void
562 SetValues(
563         ChangeDirRec *change_dir_rec,
564         ChangeDirData *change_dir_data )
565 {
566    Arg args[4];
567    char *tmp_str, *host_name;
568    XmString host_string;
569    DialogData * dialog_data;
570    FileMgrData * file_mgr_data;
571
572    dialog_data = _DtGetInstanceData (change_dir_data->file_mgr_rec);
573    file_mgr_data = (FileMgrData *) dialog_data->data;
574
575    if(change_dir_data->string_path)
576       XmStringFree (change_dir_data->string_path);
577
578    if( restrictMode
579        && file_mgr_data->toolbox == False )
580       change_dir_data->string_path =
581               XmStringCreateLocalized( users_home_dir);
582    else if( file_mgr_data->restricted_directory )
583       change_dir_data->string_path =
584         XmStringCreateLocalized( file_mgr_data->current_directory);
585    else
586       change_dir_data->string_path = NULL;
587
588    XtSetArg (args[0], XmNlistItemCount, change_dir_data->list_count);
589    XtSetArg (args[1], XmNlistVisibleItemCount, change_dir_data->visible_count);
590    XtSetArg (args[2], XmNtextString, change_dir_data->string_path);
591    XtSetArg (args[3], XmNlistItems, change_dir_data->history_list);
592
593    XtSetValues (change_dir_rec->change_dir, args, 4);
594
595    if( change_dir_data->string_path )
596    {
597       Widget text;
598
599       text = XmSelectionBoxGetChild(change_dir_rec->change_dir, XmDIALOG_TEXT);
600       XtAddCallback (text, XmNmodifyVerifyCallback,
601                      (XtCallbackProc)TextChange, (XtPointer)file_mgr_data );
602       XtAddCallback (text, XmNmotionVerifyCallback,
603                      (XtCallbackProc)TextChange, (XtPointer)file_mgr_data );
604       XtAddCallback (text, XmNvalueChangedCallback,
605                      (XtCallbackProc)TextChange, (XtPointer)file_mgr_data );
606    }
607
608    tmp_str = GETMESSAGE(2, 16, "System Name: ");
609    host_name = XtMalloc(strlen(tmp_str) + strlen(change_dir_data->host_name)+1);
610    sprintf(host_name, "%s%s", tmp_str, change_dir_data->host_name);
611    host_string = XmStringCreateLocalized (host_name);
612    XtSetArg (args[0], XmNlabelString, host_string);
613    XtSetValues (XmSelectionBoxGetChild (change_dir_rec->change_dir,
614                                         XmDIALOG_LIST_LABEL), args, 1);
615
616    XtFree(host_name);
617    XmStringFree(host_string);
618 }
619
620
621
622
623 /************************************************************************
624  *
625  *  WriteResourceValues
626  *
627  ************************************************************************/
628
629 static void
630 WriteResourceValues(
631         DialogData *values,
632         int fd,
633         char **name_list )
634 {
635    ChangeDirData * change_dir_data = (ChangeDirData *) values->data;
636    ChangeDirRec * change_dir_rec;
637
638    /*  If the dialog is currently displayed, update the geometry  */
639    /*  fields to their current values.                            */
640
641    if (change_dir_data->displayed == True)
642    {
643       _DtGenericUpdateWindowPosition(values);
644       change_dir_rec = (ChangeDirRec *) _DtGetDialogInstance (values);
645    }
646
647    _DtDialogPutResources (fd, name_list, CHANGEDIRECTORY, values->data,
648                           resources, changeDirClass->resource_count);
649 }
650
651
652
653
654 /************************************************************************
655  *
656  *  FreeValues
657  *
658  ************************************************************************/
659
660 static void
661 FreeValues(
662         ChangeDirData *change_dir_data )
663 {
664    register int i;
665
666    for (i = 0; i < change_dir_data->list_count; i++)
667       XmStringFree (change_dir_data->history_list[i]);
668    XtFree ((char *) change_dir_data->history_list);
669
670    XmStringFree (change_dir_data->string_path);
671    XtFree ((char *) change_dir_data->host_name);
672
673    XtFree ((char *) change_dir_data);
674 }
675
676
677 /************************************************************************
678  ************************************************************************
679  *
680  *   Internal functions used by the ChangeDir dialog
681  *
682  ************************************************************************
683  ************************************************************************/
684
685 /*****************************************************************************
686   TryToChangeDir
687   INPUT:
688   OUTPUT:
689   DESCRIPTION:
690     This function is used both by the ChangeDir dialog, and the FileMgr
691     dialog's text field; it attempts to verify the incoming string, and
692     then change to the indicated directory.
693   NOTE:
694  *****************************************************************************/
695 static Boolean
696 TryToChangeDir(
697        Boolean isFromDialog,
698        char * incoming_string,
699        FileMgrData * file_mgr_data,
700        FileMgrRec * file_mgr_rec,
701        ChangeDirData * change_dir_data,
702        Widget selection_box,
703        ChangeDirApply * apply_data,
704        XmSelectionBoxCallbackStruct * callback_data,
705        void (*callback)())
706 {
707   char * new_directory;
708   char * host;
709   char * path;
710   struct stat stat_buf;
711   Widget list;
712   XmString path_string;
713   XmString host_string;
714   Arg args[1];
715   char * message_buf;
716   char * tmpStr;
717   char * title;
718   char * msg;
719   Boolean rc = True;
720   char *restricted = NULL;
721
722   new_directory = XtNewString(incoming_string);
723
724   if ((new_directory) && (strcmp(new_directory, "") != 0))
725   {
726      _DtPathFromInput(new_directory, file_mgr_data->current_directory,
727                       &host, &path);
728   }
729   else
730   {
731      tmpStr = GetSharedMessage(CHANGE_DIR_ERROR_TITLE);
732      title = XtNewString(tmpStr);
733      tmpStr = GETMESSAGE(2,18, "Destination Folder name is missing.\nType in a folder name or select a folder from the list.");
734      msg = XtNewString(tmpStr);
735
736      if(isFromDialog)
737        _DtMessage(selection_box, title, msg, NULL, HelpRequestCB);
738      else
739        _DtMessage(file_mgr_rec->current_directory_text, title, msg, NULL,
740                   HelpRequestCB);
741
742      XtFree(title);
743      XtFree(msg);
744      return False;
745   }
746
747
748    /* Don't allow access to the desktop directory */
749    if (path)
750    {
751       char *ttpath = (char *) GetTTPath(path);
752       char *dtpath = (char *) GetTTPath(desktop_dir);
753       if( ttpath && strcmp(ttpath, dtpath) == 0)
754       {
755         restricted = ttpath;
756         XtFree(path);
757         path = NULL;
758       }
759    }
760
761    /* Stat the file and see if it is a valid directory.  (If the current view
762       is restricted, make sure that the new directory doesn't violate the
763       directory restrictions. If so, refilter the displayed file set to show
764       the files in this directory.
765    */
766    if ((path)
767        &&(stat(path, &stat_buf) == 0)
768        &&((stat_buf.st_mode & S_IFMT) == S_IFDIR)
769        &&(CheckRestrictedDir(file_mgr_rec, file_mgr_data, &path, False) == 0))
770    {
771      /* Check for read/xcute permission */
772      if (CheckAccess(path, R_OK | X_OK))
773      {
774        tmpStr = GETMESSAGE(9, 6, "Action Error");
775        title = XtNewString(tmpStr);
776        msg = (char *)XtMalloc(strlen(GETMESSAGE(30, 1, "Cannot read from %s"))
777                             + strlen(new_directory)
778                             + 1);
779        sprintf(msg, GETMESSAGE(30, 1, "Cannot read from %s"), new_directory);
780
781        if(isFromDialog)
782          _DtMessage(selection_box, title, msg, NULL, HelpRequestCB);
783        else
784          _DtMessage(file_mgr_rec->current_directory_text, title,
785                     msg, NULL, HelpRequestCB);
786
787        XtFree(title);
788        XtFree(msg);
789        return;
790      }
791      else
792      {
793        if (selection_box)
794        {
795          /* Adjust the selection box elements to add the text item
796           into the list.
797          */
798          list = XmSelectionBoxGetChild(selection_box, XmDIALOG_LIST);
799
800          path_string = XmStringCreateLocalized(path);
801
802          if (XmListItemExists(list, path_string))
803            XmListDeselectAllItems(list);
804          else
805            XmListAddItem(list, path_string, 0);
806
807          XmListSelectItem(list, path_string, False);
808          XmListSetBottomPos(list, 0);
809
810          XmStringFree(path_string);
811        }
812
813        /*  Clear out the text string  */
814        if (isFromDialog)
815        {
816          if(restrictMode)
817            XtSetArg(args[0],
818                     XmNtextString,
819                     XmStringCreateLocalized(users_home_dir));
820          else
821            XtSetArg(args[0], XmNtextString, NULL);
822          XtSetValues(selection_box, args, 1);
823        }
824        else
825        {
826          if(!file_mgr_data || !file_mgr_data->restricted_directory)
827            XmTextFieldSetString(file_mgr_rec->current_directory_text,
828                               incoming_string);
829
830        }
831
832
833        /* Update the change directory host name field
834           and the host name indicator widget in the dialog.
835        */
836        XtFree((char *) change_dir_data->host_name);
837        change_dir_data->host_name = XtNewString(host);
838
839        if (selection_box)
840        {
841          tmpStr = GETMESSAGE(2, 16, "System Name: ");
842          message_buf = XtMalloc(strlen(tmpStr) +
843                                 strlen(change_dir_data->host_name) + 1);
844          sprintf(message_buf, "%s%s", tmpStr, change_dir_data->host_name);
845          host_string =
846            XmStringCreateLocalized(message_buf);
847          XtSetArg(args[0], XmNlabelString, host_string);
848          XtSetValues(XmSelectionBoxGetChild(selection_box,XmDIALOG_LIST_LABEL),
849                      args, 1);
850          XtFree(message_buf);
851          XmStringFree(host_string);
852
853          XmUpdateDisplay (selection_box);
854        }
855
856        /*  Call the encapsulation change data callback  */
857        if (isFromDialog)
858          (*callback)(selection_box, apply_data->client_data, path);
859        else
860          (*callback)(file_mgr_data, path);
861      }
862    }
863    else
864    {
865      tmpStr = GetSharedMessage(CHANGE_DIR_ERROR_TITLE);
866      title = XtNewString(tmpStr);
867      if(restricted)
868      {
869        tmpStr = GETMESSAGE(2,20,"You cannot switch to folder:\n\n%s\n\nYou are not allowed to view  this folder\nbecause it is a restricted folder.");
870        path = restricted;
871      }
872      else
873        tmpStr = GETMESSAGE(2,19,"The following folder name is invalid.\n\n%s");
874      if(path)
875      {
876        message_buf = XtMalloc(strlen(tmpStr) + strlen(path) + 1);
877        sprintf(message_buf, tmpStr, path);
878      }
879      else
880      {
881        message_buf = XtMalloc(strlen(tmpStr) + strlen(new_directory) + 1);
882        sprintf(message_buf, tmpStr, new_directory);
883      }
884
885      if (isFromDialog)
886        _DtMessage(selection_box, title, message_buf, NULL, HelpRequestCB);
887      else
888        _DtMessage(file_mgr_rec->current_directory_text, title, message_buf,
889                   NULL, HelpRequestCB);
890
891      XtFree(title);
892      XtFree(message_buf);
893      rc = False;
894    }
895
896    if (path)
897       XtFree((char *) path);
898    XtFree((char *) host);
899    XtFree((char *) new_directory);
900
901    return rc;
902 }
903
904
905
906 /************************************************************************
907  *
908  *  OkCallback
909  *      This is a callback function called when the Ok button (Apply)
910  *      is pressed.  It adds the string contained within the call data
911  *      into the selection boxes list.
912  *
913  ************************************************************************/
914
915 static void
916 OkCallback(
917         Widget selection_box,
918         ChangeDirApply *apply_data,
919         XmSelectionBoxCallbackStruct *callback_data )
920 {
921    DialogData * dialog_data;
922    ChangeDirData * change_dir_data;
923    FileMgrRec * file_mgr_rec;
924    FileMgrData * file_mgr_data;
925    char *strValue;
926    char *value = NULL;
927    int result;
928    char message_buf[MAX_PATH + 100];
929    char * tmpStr;
930    char * title;
931    char * msg;
932
933
934    /*  Get the change dir data record  */
935
936    dialog_data = _DtGetInstanceData (apply_data->change_dir_rec);
937    change_dir_data = (ChangeDirData *) dialog_data->data;
938
939    file_mgr_rec = (FileMgrRec *) change_dir_data->file_mgr_rec;
940    dialog_data = _DtGetInstanceData ((XtPointer)file_mgr_rec);
941    file_mgr_data = (FileMgrData *) dialog_data->data;
942
943    value = (char *) _XmStringUngenerate((XmString)callback_data->value,
944                                         XmFONTLIST_DEFAULT_TAG,
945                                         XmCHARSET_TEXT, XmCHARSET_TEXT);
946
947    if ( value == NULL)
948    {
949        tmpStr = GetSharedMessage(CHANGE_DIR_ERROR_TITLE);
950       title = XtNewString(tmpStr);
951       tmpStr = (char *) GETMESSAGE(2, 11, "Cannot get the new folder name.");
952       msg = XtNewString(tmpStr);
953
954       _DtMessage(selection_box, title, message_buf, NULL, HelpRequestCB);
955
956       XtFree(title);
957       XtFree(msg);
958       return;
959    }
960
961    strValue = XtNewString(value);
962    if(file_mgr_data->toolbox && strValue[0] != '/')
963       result = CheckRestrictedDir(file_mgr_rec, file_mgr_data, &strValue, True);
964    else
965       result = CheckRestrictedDir(file_mgr_rec, file_mgr_data, &strValue,False);
966
967    /*  Process the string representing a directory to verify  */
968    /*  that it is a valid path.                               */
969    if (result == 0)
970    {
971       TryToChangeDir(True, (char *)strValue, file_mgr_data,
972                      file_mgr_rec, change_dir_data, selection_box, apply_data,
973                      callback_data, apply_data->callback);
974    }
975
976    XtFree(value);
977    XtFree(strValue);
978 }
979
980
981 /************************************************************************
982  *
983  *  CheckRestrictedDir:
984  *    Make sure we stay inside a restricted directory
985  *
986  ************************************************************************/
987
988 static int
989 CheckRestrictedDir (
990         FileMgrRec * file_mgr_rec,
991         FileMgrData * file_mgr_data,
992         char ** value,
993         Boolean relative_name)
994 {
995    char *tmpStr, directory[MAXPATHLEN];
996    int len;
997    char *tmpBuffer, *title, *msg;
998
999    /*  If not in restricte mode, everything is ok.  */
1000    if (file_mgr_data->restricted_directory == NULL && !restrictMode)
1001      return 0;
1002
1003    /* get real file name */
1004    if (relative_name)
1005    {
1006       tmpStr = (char *)XtMalloc(strlen(*value) +
1007                   strlen(file_mgr_data->restricted_directory) + 3);
1008       strcpy(tmpStr, file_mgr_data->restricted_directory);
1009       if(*value[0] != '/')
1010          strcat(tmpStr, "/");
1011       strcat(tmpStr, *value);
1012       XtFree(*value);
1013       *value = tmpStr;
1014    }
1015    *value = (char *) DtEliminateDots (*value);
1016
1017    if( restrictMode
1018        && file_mgr_data->toolbox == False )
1019    {
1020       if( strcmp( users_home_dir, "/" ) == 0 )
1021          return 0;
1022       strcpy( directory, users_home_dir );
1023    }
1024    else
1025       strcpy( directory, file_mgr_data->restricted_directory );
1026
1027    len = strlen(directory);
1028
1029    if( len > 1 && directory[len-1] == '/' )
1030    {
1031       directory[len - 1] = 0x0;
1032       --len;
1033    }
1034
1035    /* check if value is inside the restricted subdir */
1036    len = strlen(directory);
1037    if (strncmp(*value, directory, len) != 0 ||
1038        (*value)[len] != '/' && (*value)[len] != '\0')
1039    {
1040        tmpBuffer = GetSharedMessage(CHANGE_DIR_ERROR_TITLE);
1041        title = XtNewString(tmpBuffer);
1042        if(restrictMode)
1043           tmpBuffer = GETMESSAGE(2,8, "You cannot switch to this folder.  You are\nallowed to view only folders beneath your\ncurrent folder. You cannot specify an absolute\npath to the new folder.");
1044        else
1045           tmpBuffer = GETMESSAGE(2,9, "This view is in restricted mode.  You cannot go\nto the specified folder because it is not in the\nrelative path of the restricted folder.\n");
1046        msg = XtNewString(tmpBuffer);
1047
1048        _DtMessage(file_mgr_rec->current_directory_text, title, msg,
1049                   NULL, HelpRequestCB);
1050
1051        XtFree(title);
1052        XtFree(msg);
1053        return -1;
1054    }
1055
1056    return 0;
1057 }
1058
1059
1060 /************************************************************************
1061  *
1062  *  ChangeToNewDir
1063  *      This is the activate callback for the FileMgr text field provided
1064  *      for quickly changing the current directory being viewed.
1065  *
1066  ************************************************************************/
1067
1068 void
1069 ChangeToNewDir (
1070        Widget text_field,
1071        XtPointer client_data,
1072        XmAnyCallbackStruct * callback_data )
1073 {
1074    DialogData * dialog_data;
1075    ChangeDirData * change_dir_data;
1076    ChangeDirRec * change_dir_rec;
1077    FileMgrRec * file_mgr_rec;
1078    FileMgrData * file_mgr_data;
1079    char * value;
1080    Widget selection_box;
1081    Arg args[1];
1082    char * tmpStr;
1083    int rc;
1084
1085    /*  Get the change dir data record  */
1086
1087    file_mgr_rec = (FileMgrRec *) client_data;
1088    dialog_data = _DtGetInstanceData ((XtPointer)file_mgr_rec);
1089    file_mgr_data = (FileMgrData *) dialog_data->data;
1090    change_dir_data = (ChangeDirData *) file_mgr_data->change_dir->data;
1091    change_dir_rec =(ChangeDirRec *)_DtGetDialogInstance(file_mgr_data->change_dir);
1092
1093    if (change_dir_rec)
1094       selection_box = change_dir_rec->change_dir;
1095    else
1096       selection_box = NULL;
1097
1098    value = (char *)XmTextFieldGetString(text_field);
1099
1100    /* check if user attempts to go outside restricted directory */
1101    rc = CheckRestrictedDir (file_mgr_rec, file_mgr_data, &value, True);
1102
1103 /*
1104    This code will de-activate the text widget.
1105    HCI requests that if the switch is not successful, don't de-activate it
1106    so user has a change to go back and correct it without having to pop it
1107    up again.
1108
1109    XmProcessTraversal(file_mgr_rec->file_window, XmTRAVERSE_CURRENT);
1110    XtSetArg (args[0], XmNallowShellResize, False);
1111    XtSetValues (file_mgr_rec->shell, args, 1);
1112    XtUnmanageChild(file_mgr_rec->current_directory_text);
1113    XtSetArg (args[0], XmNallowShellResize, True);
1114    XtSetValues (file_mgr_rec->shell, args, 1);
1115    file_mgr_data->fast_cd_enabled = False;
1116 */
1117
1118    /*  Process the string representing a directory to verify  */
1119    /*  that it is a valid path.                               */
1120    if (rc == 0)
1121    {
1122      if( TryToChangeDir(False, value, file_mgr_data, file_mgr_rec,
1123                         change_dir_data, selection_box, NULL, NULL,
1124                         GoToNewDir) )
1125        /* de-activate the text widget */
1126        UnpostTextPath( file_mgr_data );
1127    }
1128
1129    XtFree(value);
1130 }
1131
1132
1133 /************************************************************************
1134  *
1135  *  DropOnChangeView
1136  *      This is the drop callback for the change-view icon provided
1137  *      for quickly changing the current directory being viewed.
1138  *
1139  ************************************************************************/
1140
1141 void
1142 DropOnChangeView (
1143      Widget w,
1144      XtPointer client_data,
1145      XtPointer call_data)
1146 {
1147    DtDndDropCallbackStruct *fileList = (DtDndDropCallbackStruct *)call_data;
1148    FileMgrRec *file_mgr_rec;
1149    DialogData * dialog_data;
1150    ChangeDirData * change_dir_data;
1151    ChangeDirRec * change_dir_rec;
1152    FileMgrData * file_mgr_data;
1153    Widget selection_box;
1154    char *full_path_name;
1155    int  numFiles;
1156
1157    numFiles = fileList->dropData->numItems;
1158
1159    /* if multiple selection, ignore all but the last one */
1160
1161    if (numFiles > 0 && fileList->reason == DtCR_DND_DROP_ANIMATE)
1162    {
1163       file_mgr_rec = (FileMgrRec *) client_data;
1164       dialog_data = _DtGetInstanceData ((XtPointer)file_mgr_rec);
1165       file_mgr_data = (FileMgrData *) dialog_data->data;
1166
1167       full_path_name = XtNewString(fileList->dropData->data.files[numFiles-1]);
1168
1169       if (CheckRestrictedDir(file_mgr_rec, file_mgr_data,
1170                              &full_path_name, False) == 0)
1171       {
1172          change_dir_data = (ChangeDirData *) file_mgr_data->change_dir->data;
1173          change_dir_rec =
1174               (ChangeDirRec *)_DtGetDialogInstance(file_mgr_data->change_dir);
1175          if (change_dir_rec)
1176             selection_box = change_dir_rec->change_dir;
1177          else
1178             selection_box = NULL;
1179
1180          TryToChangeDir(False, full_path_name, file_mgr_data, file_mgr_rec,
1181                         change_dir_data, selection_box, NULL, NULL,
1182                         GoToNewDir);
1183       }
1184       XtFree(full_path_name);
1185    }
1186
1187    fileList->status = DtDND_FAILURE;
1188 }
1189
1190
1191 static void
1192 GoToNewDir(
1193        FileMgrData * file_mgr_data,
1194        char * dir_name )
1195 {
1196    ChangeDirData * change_dir_data;
1197    int i;
1198    Boolean found;
1199    XmString xm_dir_name;
1200
1201    /* Clear out any selected portion of the old CWD string */
1202    if (file_mgr_data->cd_select != NULL)
1203    {
1204       XtFree(file_mgr_data->cd_select);
1205       file_mgr_data->cd_select = NULL;
1206    }
1207
1208    /* Update the internal copy of the dialog history list */
1209    if (file_mgr_data->change_dir)
1210    {
1211       change_dir_data = (ChangeDirData *) file_mgr_data->change_dir->data;
1212       xm_dir_name = XmStringCreateLocalized(dir_name);
1213
1214       /* Add the directory only if not already in the list */
1215       for (i = 0, found = False; i < change_dir_data->list_count; i++)
1216       {
1217          if (XmStringCompare(xm_dir_name, change_dir_data->history_list[i]))
1218          {
1219             found = True;
1220             XmStringFree(xm_dir_name);
1221             break;
1222          }
1223       }
1224
1225       if (!found)
1226       {
1227          change_dir_data->list_count++;
1228          change_dir_data->history_list = (XmStringTable)
1229             XtRealloc((char *)change_dir_data->history_list,
1230                    sizeof(XmStringTable) * (change_dir_data->list_count + 1));
1231          change_dir_data->history_list[change_dir_data->list_count - 1] =
1232                 xm_dir_name;
1233          change_dir_data->history_list[change_dir_data->list_count] = NULL;
1234       }
1235
1236       /* Update view to display the new directory */
1237       ShowNewDirectory(file_mgr_data, change_dir_data->host_name, dir_name);
1238    }
1239 }
1240
1241
1242 /*
1243  * Class function for forcing the focus to the text field, each time
1244  * the Change Dir dialog is posted.
1245  */
1246
1247 static void
1248 SetFocus(
1249         ChangeDirRec *change_dir_rec,
1250         ChangeDirData *change_dir_data )
1251 {
1252    Widget text;
1253
1254    /* Force the focus to the text field */
1255    text = XmSelectionBoxGetChild (change_dir_rec->change_dir, XmDIALOG_TEXT);
1256    XmProcessTraversal(text, XmTRAVERSE_CURRENT);
1257 }
1258
1259
1260 /***************************************************************************
1261  *
1262  * TextChange() - callback from editable text widgets when something is
1263  *        typed in the text widget.  Only used when in restricted mode.
1264  *        Used to make sure the users are not going out of their
1265  *        "restricted" space.
1266  *
1267  ****************************************************************************/
1268
1269 void
1270 TextChange(
1271         Widget text,
1272         XtPointer client_data,
1273         XmTextVerifyCallbackStruct * callback_data )
1274 {
1275    char *homeDir, *homeDirBackup;
1276    char *selection;
1277
1278    if (callback_data->reason == XmCR_MODIFYING_TEXT_VALUE ||
1279        callback_data->reason == XmCR_MOVING_INSERT_CURSOR )
1280    {
1281       FileMgrData * file_mgr_data;
1282
1283       file_mgr_data = (FileMgrData *) client_data;
1284
1285       selection = XmTextFieldGetSelection(text);
1286
1287       /* get whats in the text widget */
1288       homeDir = homeDirBackup = XmTextFieldGetString(text);
1289
1290       if(selection != NULL)
1291       {
1292          if(callback_data->event == NULL)
1293             XmTextFieldClearSelection(text, CurrentTime);
1294          else
1295             XmTextFieldClearSelection(text, callback_data->event->xkey.time);
1296          callback_data->doit = False;
1297       }
1298       else if(callback_data->reason == XmCR_MODIFYING_TEXT_VALUE)
1299       {
1300          /* see if the user is trying to back over the 'restricted'
1301           * text, in this case users_home_dir
1302           */
1303          if( strcmp( homeDir, "" ) != 0
1304              && strcmp( homeDir, file_mgr_data->restricted_directory ) <= 0 )
1305          {
1306             if( callback_data->text->length != 0 )
1307             {
1308                if( strncmp( file_mgr_data->restricted_directory,
1309                             callback_data->text->ptr,
1310                             strlen(file_mgr_data->restricted_directory)) != 0)
1311                {
1312                   callback_data->doit = True;
1313                }
1314             }
1315             else
1316             {
1317                callback_data->doit = False;
1318             }
1319          }
1320       }
1321       else
1322       {
1323          int maxlength;
1324
1325          maxlength = strlen( file_mgr_data->restricted_directory );
1326
1327          if(callback_data->newInsert < maxlength)
1328          {
1329             if(callback_data->event == NULL)
1330                _XmTextFieldSetDestination((Widget)text,
1331                             (Position)callback_data->currInsert, CurrentTime);
1332             else
1333             {
1334                _XmTextFieldSetDestination((Widget)text,
1335                                           (Position)callback_data->currInsert,
1336                                           callback_data->event->xkey.time);
1337                callback_data->doit = False;
1338             }
1339          }
1340       }
1341
1342       XtFree(homeDirBackup);
1343       XtFree(selection);
1344    }
1345 }
1346
1347 void
1348 ChangeDirectoryToParent(
1349       FileMgrRec * file_mgr_rec,
1350       char *directory)
1351 {
1352    DialogData * dialog_data;
1353    ChangeDirData * change_dir_data;
1354    ChangeDirRec * change_dir_rec;
1355    FileMgrData * file_mgr_data;
1356    Widget selection_box;
1357    char * tmpStr;
1358    int rc;
1359
1360    /*  Get the change dir data record  */
1361
1362    dialog_data = _DtGetInstanceData ((XtPointer)file_mgr_rec);
1363    file_mgr_data = (FileMgrData *) dialog_data->data;
1364    change_dir_data = (ChangeDirData *) file_mgr_data->change_dir->data;
1365    change_dir_rec =(ChangeDirRec *)_DtGetDialogInstance(file_mgr_data->change_dir);
1366
1367    if (change_dir_rec)
1368       selection_box = change_dir_rec->change_dir;
1369    else
1370       selection_box = NULL;
1371
1372    /* check if user attempts to go outside restricted directory */
1373    rc = CheckRestrictedDir (file_mgr_rec, file_mgr_data, &directory, True);
1374
1375    /*  Process the string representing a directory to verify  */
1376    /*  that it is a valid path.                               */
1377    if (rc == 0)
1378    {
1379       TryToChangeDir(False, directory, file_mgr_data, file_mgr_rec,
1380                      change_dir_data, selection_box, NULL, NULL,
1381                      GoToNewDir);
1382    }
1383
1384 }