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