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