| |
1 /* |
| |
2 * Copyright 2021 Olaf Wintermann |
| |
3 * |
| |
4 * Permission is hereby granted, free of charge, to any person obtaining a |
| |
5 * copy of this software and associated documentation files (the "Software"), |
| |
6 * to deal in the Software without restriction, including without limitation |
| |
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense, |
| |
8 * and/or sell copies of the Software, and to permit persons to whom the |
| |
9 * Software is furnished to do so, subject to the following conditions: |
| |
10 * |
| |
11 * The above copyright notice and this permission notice shall be included in |
| |
12 * all copies or substantial portions of the Software. |
| |
13 * |
| |
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
| |
15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
| |
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL |
| |
17 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
| |
18 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING |
| |
19 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER |
| |
20 * DEALINGS IN THE SOFTWARE. |
| |
21 */ |
| |
22 |
| |
23 //define FSB_ENABLE_DETAIL |
| |
24 |
| |
25 #include "Fsb.h" |
| |
26 #include "FsbP.h" |
| |
27 |
| |
28 #include <stdio.h> |
| |
29 #include <stdlib.h> |
| |
30 #include <string.h> |
| |
31 #include <unistd.h> |
| |
32 #include <time.h> |
| |
33 #include <inttypes.h> |
| |
34 #include <errno.h> |
| |
35 |
| |
36 #include <sys/stat.h> |
| |
37 #include <limits.h> |
| |
38 #include <dirent.h> |
| |
39 #include <fnmatch.h> |
| |
40 |
| |
41 #include <Xm/XmAll.h> |
| |
42 #include <Xm/DropDown.h> |
| |
43 |
| |
44 #include "pathbar.h" |
| |
45 |
| |
46 #include "../common/utils.h" |
| |
47 |
| |
48 #ifdef FSB_ENABLE_DETAIL |
| |
49 #include <XmL/Grid.h> |
| |
50 #endif |
| |
51 |
| |
52 #define WIDGET_SPACING 5 |
| |
53 #define WINDOW_SPACING 8 |
| |
54 |
| |
55 #define BUTTON_EXTRA_SPACE 4 |
| |
56 |
| |
57 #define DATE_FORMAT_SAME_YEAR "%b %d %H:%M" |
| |
58 #define DATE_FORMAT_OTHER_YEAR "%b %d %Y" |
| |
59 |
| |
60 #define KB_SUFFIX "KiB" |
| |
61 #define MB_SUFFIX "MiB" |
| |
62 #define GB_SUFFIX "GiB" |
| |
63 #define TB_SUFFIX "TiB" |
| |
64 |
| |
65 #define FSB_ERROR_TITLE "Error" |
| |
66 #define FSB_ERROR_CHAR "Character '/' is not allowed in file names" |
| |
67 #define FSB_ERROR_RENAME "Cannot rename file: %s" |
| |
68 #define FSB_ERROR_DELETE "Cannot delete file: %s" |
| |
69 #define FSB_ERROR_CREATE_FOLDER "Cannot create folder: %s" |
| |
70 #define FSB_ERROR_OPEN_DIR "Cannot open directory: %s" |
| |
71 |
| |
72 #define FSB_DETAIL_HEADINGS "Name|Size|Last Modified" |
| |
73 |
| |
74 static void fsb_class_init(void); |
| |
75 static void fsb_class_part_init (WidgetClass wc); |
| |
76 static void fsb_init(Widget request, Widget neww, ArgList args, Cardinal *num_args); |
| |
77 static void fsb_resize(Widget widget); |
| |
78 static void fsb_realize(Widget widget, XtValueMask *mask, XSetWindowAttributes *attributes); |
| |
79 static void fsb_destroy(Widget widget); |
| |
80 static Boolean fsb_set_values(Widget old, Widget request, Widget neww, ArgList args, Cardinal *num_args); |
| |
81 static Boolean fsb_acceptfocus(Widget widget, Time *time); |
| |
82 |
| |
83 static void fsb_insert_child(Widget child); |
| |
84 |
| |
85 static void fsb_mapcb(Widget widget, XtPointer u, XtPointer cb); |
| |
86 |
| |
87 static int FSBGlobFilter(const char *a, const char *b); |
| |
88 |
| |
89 static void FSBUpdateTitle(Widget w); |
| |
90 |
| |
91 static void FocusInAP(Widget w, XEvent *event, String *args, Cardinal *nArgs); |
| |
92 |
| |
93 static void ErrDialog(XnFileSelectionBox w, const char *title, const char *errmsg); |
| |
94 |
| |
95 static void FSBRename(XnFileSelectionBox fsb, const char *path); |
| |
96 static void FSBDelete(XnFileSelectionBox fsb, const char *path); |
| |
97 |
| |
98 static void FSBSelectItem(XnFileSelectionBox fsb, const char *item); |
| |
99 |
| |
100 static char* set_selected_path(XnFileSelectionBox data, XmString item); |
| |
101 |
| |
102 static void FileContextMenuCB(Widget item, XtPointer index, XtPointer cd); |
| |
103 |
| |
104 static Widget CreateContextMenu(XnFileSelectionBox fsb, Widget parent, XtCallbackProc callback); |
| |
105 |
| |
106 static void FileListUpdate(Widget fsb, Widget view, FileElm *dirlist, int dircount, FileElm *files, int filecount, const char *filter, int maxnamelen, void *userData); |
| |
107 static void FileListSelect(Widget fsb, Widget view, const char *item); |
| |
108 static void FileListCleanup(Widget fsb, Widget view, void *userData); |
| |
109 static void FileListDestroy(Widget fsb, Widget view, void *userData); |
| |
110 |
| |
111 static void FileListActivateCB(Widget w, XnFileSelectionBox data, XmListCallbackStruct *cb); |
| |
112 static void FileListSelectCB(Widget w, XnFileSelectionBox data, XmListCallbackStruct *cb); |
| |
113 |
| |
114 static void FileListWidgetAdd(XnFileSelectionBox fsb, Widget w, int showHidden, const char *filter, FileElm *ls, int count); |
| |
115 |
| |
116 #ifdef FSB_ENABLE_DETAIL |
| |
117 static void FileListDetailUpdate(Widget fsb, Widget view, FileElm *dirlist, int dircount, FileElm *files, int filecount, const char *filter, int maxnamelen, void *userData); |
| |
118 static void FileListDetailSelect(Widget fsb, Widget view, const char *item); |
| |
119 static void FileListDetailCleanup(Widget fsb, Widget view, void *userData); |
| |
120 static void FileListDetailDestroy(Widget fsb, Widget view, void *userData); |
| |
121 static void FileListDetailAdjustColWidth(Widget grid); |
| |
122 static void FileListDetailAdd(XnFileSelectionBox fsb, Widget grid, int showHidden, const char *filter, FileElm *ls, int count, int maxWidth); |
| |
123 #endif |
| |
124 |
| |
125 static void FSBNewFolder(Widget w, XnFileSelectionBox data, XtPointer u); |
| |
126 |
| |
127 static void FSBHome(Widget w, XnFileSelectionBox data, XtPointer u); |
| |
128 |
| |
129 static void FileSelectionCallback(XnFileSelectionBox fsb, XtCallbackList cb, int reason, const char *value); |
| |
130 |
| |
131 static void CreateUI(XnFileSelectionBox w); |
| |
132 static FSBViewWidgets CreateView(XnFileSelectionBox w, FSBViewCreateProc createProc, void *userData, Boolean useDirList); |
| |
133 static void AddViewMenuItem(XnFileSelectionBox w, const char *name, int viewIndex); |
| |
134 static void SelectView(XnFileSelectionBox f, int view); |
| |
135 |
| |
136 static char* FSBDialogTitle(Widget w); |
| |
137 |
| |
138 static FSBViewWidgets CreateListView(Widget fsb, ArgList args, int n, void *userData); |
| |
139 static FSBViewWidgets CreateDetailView(Widget fsb, ArgList args, int n, void *userData); |
| |
140 |
| |
141 static const char* GetHomeDir(void); |
| |
142 |
| |
143 static char* ConcatPath(const char *parent, const char *name); |
| |
144 static char* FileName(char *path); |
| |
145 static char* ParentPath(const char *path); |
| |
146 //static int CheckFileName(const char *name); |
| |
147 |
| |
148 static int filedialog_update_dir(XnFileSelectionBox data, const char *path); |
| |
149 static void filedialog_cleanup_filedata(XnFileSelectionBox data); |
| |
150 |
| |
151 |
| |
152 static XtResource resources[] = { |
| |
153 {XmNokCallback, XmCCallback, XmRCallback, sizeof(XtCallbackList), XtOffset(XnFileSelectionBox, fsb.okCallback), XmRCallback, NULL}, |
| |
154 {XmNcancelCallback, XmCCallback, XmRCallback, sizeof(XtCallbackList), XtOffset(XnFileSelectionBox, fsb.cancelCallback), XmRCallback, NULL}, |
| |
155 {XnNwidgetSpacing, XmCSpacing, XmRDimension, sizeof(Dimension), XtOffset(XnFileSelectionBox, fsb.widgetSpacing), XmRImmediate, (XtPointer)WIDGET_SPACING}, |
| |
156 {XnNwindowSpacing, XmCSpacing, XmRDimension, sizeof(Dimension), XtOffset(XnFileSelectionBox, fsb.windowSpacing), XmRImmediate, (XtPointer)WINDOW_SPACING}, |
| |
157 {XnNfsbType, XnCfsbType, XmRInt, sizeof(int), XtOffset(XnFileSelectionBox, fsb.type), XmRImmediate, (XtPointer)FILEDIALOG_OPEN}, |
| |
158 {XnNshowHidden, XnCshowHidden, XmRBoolean, sizeof(Boolean), XtOffset(XnFileSelectionBox, fsb.showHidden), XmRImmediate, (XtPointer)False}, |
| |
159 {XnNshowHiddenButton, XnCshowHiddenButton, XmRBoolean, sizeof(Boolean), XtOffset(XnFileSelectionBox, fsb.showHiddenButton), XmRImmediate, (XtPointer)True}, |
| |
160 {XnNshowViewMenu, XnCshowViewMenu, XmRBoolean, sizeof(Boolean), XtOffset(XnFileSelectionBox, fsb.showViewMenu), XmRImmediate, (XtPointer)False}, |
| |
161 {XnNselectedView, XnCselectedView, XmRInt, sizeof(int), XtOffset(XnFileSelectionBox, fsb.selectedview), XmRImmediate, (XtPointer)0}, |
| |
162 |
| |
163 {XnNdirectory, XnCdirectory, XmRString, sizeof(XmString), XtOffset(XnFileSelectionBox, fsb.currentPath), XmRString, NULL}, |
| |
164 {XnNselectedPath, XnCselectedPath, XmRString, sizeof(XmString), XtOffset(XnFileSelectionBox, fsb.selectedPath), XmRString, NULL}, |
| |
165 {XnNhomePath, XnChomePath, XmRString, sizeof(XmString), XtOffset(XnFileSelectionBox, fsb.homePath), XmRString, NULL}, |
| |
166 |
| |
167 {XnNfilter,XnCfilter,XmRString,sizeof(XmString),XtOffset(XnFileSelectionBox, fsb.filterStr), XmRString, "*"}, |
| |
168 {XnNfilterFunc,XnCfilterFunc,XmRFunction,sizeof(FSBFilterFunc),XtOffset(XnFileSelectionBox, fsb.filterFunc), XmRFunction, NULL}, |
| |
169 |
| |
170 {XnNlabelListView,XnClabelListView,XmRString,sizeof(XmString),XtOffset(XnFileSelectionBox, fsb.labelListView), XmRString, "List"}, |
| |
171 {XnNlabelDetailView,XnClabelDetailView,XmRString,sizeof(XmString),XtOffset(XnFileSelectionBox, fsb.labelDetailView), XmRString, "Detail"}, |
| |
172 {XnNlabelOpenFileTitle,XnClabelOpenFileTitle,XmRString,sizeof(XmString),XtOffset(XnFileSelectionBox, fsb.labelOpenFileTitle), XmRString, "Open File"}, |
| |
173 {XnNlabelSaveFileTitle,XnClabelSaveFileTitle,XmRString,sizeof(XmString),XtOffset(XnFileSelectionBox, fsb.labelSaveFileTitle), XmRString, "Save File"}, |
| |
174 {XnNlabelDirUp,XnClabelDirUp,XmRXmString,sizeof(XmString),XtOffset(XnFileSelectionBox, fsb.labelDirUp), XmRString, "Dir Up"}, |
| |
175 {XnNlabelHome,XnClabelHome,XmRXmString,sizeof(XmString),XtOffset(XnFileSelectionBox, fsb.labelHome), XmRString, "Home"}, |
| |
176 {XnNlabelNewFolder,XnClabelNewFolder,XmRXmString,sizeof(XmString),XtOffset(XnFileSelectionBox, fsb.labelNewFolder), XmRString, "New Folder"}, |
| |
177 {XnNlabelFilterButton,XnClabelFilterButton,XmRXmString,sizeof(XmString),XtOffset(XnFileSelectionBox, fsb.labelFilterButton), XmRString, "Filter"}, |
| |
178 {XnNlabelShowHiddenFiles,XnClabelShowHiddenFiles,XmRXmString,sizeof(XmString),XtOffset(XnFileSelectionBox, fsb.labelShowHiddenFiles), XmRString, "Show hiden files"}, |
| |
179 {XnNlabelDirectories,XnClabelDirectories,XmRXmString,sizeof(XmString),XtOffset(XnFileSelectionBox, fsb.labelDirectories), XmRString, "Directories"}, |
| |
180 {XnNlabelFiles,XnClabelFiles,XmRXmString,sizeof(XmString),XtOffset(XnFileSelectionBox, fsb.labelFiles), XmRString, "Files"}, |
| |
181 {XnNlabelRename,XnClabelRename,XmRXmString,sizeof(XmString),XtOffset(XnFileSelectionBox, fsb.labelRename), XmRString, "Rename"}, |
| |
182 {XnNlabelDelete,XnClabelDelete,XmRXmString,sizeof(XmString),XtOffset(XnFileSelectionBox, fsb.labelDelete), XmRString, "Delete"}, |
| |
183 {XnNlabelOpen,XnClabelOpen,XmRXmString,sizeof(XmString),XtOffset(XnFileSelectionBox, fsb.labelOpen), XmRString, "Open"}, |
| |
184 {XnNlabelSave,XnClabelSave,XmRXmString,sizeof(XmString),XtOffset(XnFileSelectionBox, fsb.labelSave), XmRString, "Save"}, |
| |
185 {XnNlabelOk,XnClabelOk,XmRXmString,sizeof(XmString),XtOffset(XnFileSelectionBox, fsb.labelOk), XmRString, "OK"}, |
| |
186 {XnNlabelCancel,XnClabelCancel,XmRXmString,sizeof(XmString),XtOffset(XnFileSelectionBox, fsb.labelCancel), XmRString, "Cancel"}, |
| |
187 {XnNlabelHelp,XnClabelHelp,XmRXmString,sizeof(XmString),XtOffset(XnFileSelectionBox, fsb.labelHelp), XmRString, "Help"}, |
| |
188 {XnNlabelFileName,XnClabelFileName,XmRXmString,sizeof(XmString),XtOffset(XnFileSelectionBox, fsb.labelFileName), XmRString, "New File Name"}, |
| |
189 {XnNlabelDirectoryName,XnClabelDirectoryName,XmRXmString,sizeof(XmString),XtOffset(XnFileSelectionBox, fsb.labelDirectoryName), XmRString, "Directory name:"}, |
| |
190 {XnNlabelNewFileName,XnClabelNewFileName,XmRXmString,sizeof(XmString),XtOffset(XnFileSelectionBox, fsb.labelNewFileName), XmRString, "New file name:"}, |
| |
191 {XnNlabelDeleteFile,XnClabelDeleteFile,XmRString,sizeof(XmString),XtOffset(XnFileSelectionBox, fsb.labelDeleteFile), XmRString, "Delete file '%s'?"}, |
| |
192 {XnNdetailHeadings,XnCdetailHeadings,XmRString,sizeof(XmString),XtOffset(XnFileSelectionBox, fsb.detailHeadings), XmRString,FSB_DETAIL_HEADINGS}, |
| |
193 {XnNdateFormatSameYear,XnCdateFormatSameYear,XmRString,sizeof(XmString),XtOffset(XnFileSelectionBox, fsb.dateFormatSameYear), XmRString,DATE_FORMAT_SAME_YEAR}, |
| |
194 {XnNdateFormatOtherYear,XnNdateFormatOtherYear,XmRString,sizeof(XmString),XtOffset(XnFileSelectionBox, fsb.dateFormatOtherYear), XmRString,DATE_FORMAT_OTHER_YEAR}, |
| |
195 {XnNsuffixBytes,XnCsuffixBytes,XmRString,sizeof(XmString),XtOffset(XnFileSelectionBox, fsb.suffixBytes), XmRString,"bytes"}, |
| |
196 {XnNsuffixKB,XnCsuffixKB,XmRString,sizeof(XmString),XtOffset(XnFileSelectionBox, fsb.suffixKB), XmRString,KB_SUFFIX}, |
| |
197 {XnNsuffixMB,XnCsuffixKB,XmRString,sizeof(XmString),XtOffset(XnFileSelectionBox, fsb.suffixMB), XmRString,MB_SUFFIX}, |
| |
198 {XnNsuffixGB,XnCsuffixKB,XmRString,sizeof(XmString),XtOffset(XnFileSelectionBox, fsb.suffixGB), XmRString,GB_SUFFIX}, |
| |
199 {XnNsuffixTB,XnCsuffixKB,XmRString,sizeof(XmString),XtOffset(XnFileSelectionBox, fsb.suffixTB), XmRString,TB_SUFFIX}, |
| |
200 |
| |
201 {XnNerrorTitle,XnCerrorTitle,XmRString,sizeof(XmString),XtOffset(XnFileSelectionBox, fsb.errorTitle), XmRString,FSB_ERROR_TITLE}, |
| |
202 {XnNerrorIllegalChar,XnCerrorIllegalChar,XmRString,sizeof(XmString),XtOffset(XnFileSelectionBox, fsb.errorIllegalChar), XmRString,FSB_ERROR_CHAR}, |
| |
203 {XnNerrorRename,XnCerrorRename,XmRString,sizeof(XmString),XtOffset(XnFileSelectionBox, fsb.errorRename), XmRString,FSB_ERROR_RENAME}, |
| |
204 {XnNerrorCreateFolder,XnCerrorCreateFolder,XmRString,sizeof(XmString),XtOffset(XnFileSelectionBox, fsb.errorFolder), XmRString,FSB_ERROR_CREATE_FOLDER}, |
| |
205 {XnNerrorDelete,XnCerrorDelete,XmRString,sizeof(XmString),XtOffset(XnFileSelectionBox, fsb.errorDelete), XmRString,FSB_ERROR_DELETE}, |
| |
206 {XnNerrorOpenDir,XnCerrorOpenDir,XmRString,sizeof(XmString),XtOffset(XnFileSelectionBox, fsb.errorOpenDir), XmRString,FSB_ERROR_OPEN_DIR} |
| |
207 }; |
| |
208 |
| |
209 static XtActionsRec actionslist[] = { |
| |
210 {"focusIn", FocusInAP}, |
| |
211 {"NULL", NULL} |
| |
212 }; |
| |
213 |
| |
214 |
| |
215 static char defaultTranslations[] = "<FocusIn>: focusIn()"; |
| |
216 |
| |
217 static XtResource constraints[] = {}; |
| |
218 |
| |
219 FSBClassRec fsbWidgetClassRec = { |
| |
220 // Core Class |
| |
221 { |
| |
222 (WidgetClass)&xmFormClassRec, |
| |
223 "XnFSB", // class_name |
| |
224 sizeof(FSBRec), // widget_size |
| |
225 fsb_class_init, // class_initialize |
| |
226 fsb_class_part_init, // class_part_initialize |
| |
227 FALSE, // class_inited |
| |
228 fsb_init, // initialize |
| |
229 NULL, // initialize_hook |
| |
230 fsb_realize, // realize |
| |
231 actionslist, // actions |
| |
232 XtNumber(actionslist), // num_actions |
| |
233 resources, // resources |
| |
234 XtNumber(resources), // num_resources |
| |
235 NULLQUARK, // xrm_class |
| |
236 True, // compress_motion |
| |
237 True, // compress_exposure |
| |
238 True, // compress_enterleave |
| |
239 False, // visible_interest |
| |
240 fsb_destroy, // destroy |
| |
241 fsb_resize, // resize |
| |
242 XtInheritExpose, // expose |
| |
243 fsb_set_values, // set_values |
| |
244 NULL, // set_values_hook |
| |
245 XtInheritSetValuesAlmost, // set_values_almost |
| |
246 NULL, // get_values_hook |
| |
247 fsb_acceptfocus, // accept_focus |
| |
248 XtVersion, // version |
| |
249 NULL, // callback_offsets |
| |
250 defaultTranslations, // tm_table |
| |
251 XtInheritQueryGeometry, // query_geometry |
| |
252 XtInheritDisplayAccelerator, // display_accelerator |
| |
253 NULL, // extension |
| |
254 }, |
| |
255 // Composite Class |
| |
256 { |
| |
257 XtInheritGeometryManager, // geometry_manager |
| |
258 XtInheritChangeManaged, // change_managed |
| |
259 fsb_insert_child, // insert_child |
| |
260 XtInheritDeleteChild, // delete_child |
| |
261 NULL, // extension |
| |
262 }, |
| |
263 // Constraint Class |
| |
264 { |
| |
265 constraints, // resources |
| |
266 XtNumber(constraints), // num_resources |
| |
267 sizeof(XmFormConstraintRec), // constraint_size |
| |
268 NULL, // initialize |
| |
269 NULL, // destroy |
| |
270 NULL, // set_value |
| |
271 NULL, // extension |
| |
272 }, |
| |
273 // XmManager Class |
| |
274 { |
| |
275 XtInheritTranslations, // translations |
| |
276 NULL, // syn_resources |
| |
277 0, // num_syn_resources |
| |
278 NULL, // syn_constraint_resources |
| |
279 0, // num_syn_constraint_resources |
| |
280 XmInheritParentProcess, // parent_process |
| |
281 NULL // extension |
| |
282 }, |
| |
283 // XmBulletinBoard |
| |
284 { |
| |
285 FALSE, |
| |
286 NULL, |
| |
287 XmInheritFocusMovedProc, |
| |
288 NULL |
| |
289 }, |
| |
290 // XmForm Class |
| |
291 { |
| |
292 NULL |
| |
293 }, |
| |
294 // FSB Class |
| |
295 { |
| |
296 0 |
| |
297 } |
| |
298 }; |
| |
299 |
| |
300 WidgetClass xnFsbWidgetClass = (WidgetClass)&fsbWidgetClassRec; |
| |
301 |
| |
302 |
| |
303 static void fsb_class_init(void) { |
| |
304 |
| |
305 } |
| |
306 |
| |
307 static void fsb_class_part_init (WidgetClass wc) { |
| |
308 FSBClassRec *fsbClass = (FSBClassRec*)wc; |
| |
309 XmFormClassRec *formClass = (XmFormClassRec*)xmFormWidgetClass; |
| |
310 |
| |
311 fsbClass->constraint_class.initialize = formClass->constraint_class.initialize; |
| |
312 fsbClass->constraint_class.set_values = formClass->constraint_class.set_values; |
| |
313 } |
| |
314 |
| |
315 |
| |
316 #define STRDUP_RES(a) if(a) a = strdup(a) |
| |
317 #define XMS_STRDUP_RES(a) if(a) a = XmStringCopy(a) |
| |
318 |
| |
319 static void fsb_init(Widget request, Widget neww, ArgList args, Cardinal *num_args) { |
| |
320 XnFileSelectionBox fsb = (XnFileSelectionBox)neww; |
| |
321 (xmFormClassRec.core_class.initialize)(request, neww, args, num_args); |
| |
322 |
| |
323 fsb->fsb.disable_set_values = 0; |
| |
324 |
| |
325 STRDUP_RES(fsb->fsb.homePath); |
| |
326 STRDUP_RES(fsb->fsb.selectedPath); |
| |
327 STRDUP_RES(fsb->fsb.currentPath); |
| |
328 STRDUP_RES(fsb->fsb.filterStr); |
| |
329 STRDUP_RES(fsb->fsb.labelListView); |
| |
330 STRDUP_RES(fsb->fsb.labelDetailView); |
| |
331 STRDUP_RES(fsb->fsb.labelOpenFileTitle); |
| |
332 STRDUP_RES(fsb->fsb.labelSaveFileTitle); |
| |
333 XMS_STRDUP_RES(fsb->fsb.labelDirUp); |
| |
334 XMS_STRDUP_RES(fsb->fsb.labelHome); |
| |
335 XMS_STRDUP_RES(fsb->fsb.labelNewFolder); |
| |
336 XMS_STRDUP_RES(fsb->fsb.labelFilterButton); |
| |
337 XMS_STRDUP_RES(fsb->fsb.labelShowHiddenFiles); |
| |
338 XMS_STRDUP_RES(fsb->fsb.labelDirectories); |
| |
339 XMS_STRDUP_RES(fsb->fsb.labelFiles); |
| |
340 XMS_STRDUP_RES(fsb->fsb.labelRename); |
| |
341 XMS_STRDUP_RES(fsb->fsb.labelDelete); |
| |
342 XMS_STRDUP_RES(fsb->fsb.labelOpen); |
| |
343 XMS_STRDUP_RES(fsb->fsb.labelSave); |
| |
344 XMS_STRDUP_RES(fsb->fsb.labelCancel); |
| |
345 XMS_STRDUP_RES(fsb->fsb.labelHelp); |
| |
346 XMS_STRDUP_RES(fsb->fsb.labelFileName); |
| |
347 XMS_STRDUP_RES(fsb->fsb.labelDirectoryName); |
| |
348 XMS_STRDUP_RES(fsb->fsb.labelNewFileName); |
| |
349 STRDUP_RES(fsb->fsb.labelDeleteFile); |
| |
350 STRDUP_RES(fsb->fsb.detailHeadings); |
| |
351 STRDUP_RES(fsb->fsb.dateFormatSameYear); |
| |
352 STRDUP_RES(fsb->fsb.dateFormatOtherYear); |
| |
353 STRDUP_RES(fsb->fsb.suffixBytes); |
| |
354 STRDUP_RES(fsb->fsb.suffixKB); |
| |
355 STRDUP_RES(fsb->fsb.suffixMB); |
| |
356 STRDUP_RES(fsb->fsb.suffixGB); |
| |
357 STRDUP_RES(fsb->fsb.suffixTB); |
| |
358 STRDUP_RES(fsb->fsb.errorTitle); |
| |
359 STRDUP_RES(fsb->fsb.errorIllegalChar); |
| |
360 STRDUP_RES(fsb->fsb.errorRename); |
| |
361 STRDUP_RES(fsb->fsb.errorFolder); |
| |
362 STRDUP_RES(fsb->fsb.errorDelete); |
| |
363 STRDUP_RES(fsb->fsb.errorOpenDir); |
| |
364 |
| |
365 CreateUI((XnFileSelectionBox)fsb); |
| |
366 |
| |
367 XtAddCallback(neww, XmNmapCallback, fsb_mapcb, NULL); |
| |
368 } |
| |
369 |
| |
370 #define STR_FREE(a) if(a) free(a) |
| |
371 #define XMSTR_FREE(a) if(a) XmStringFree(a) |
| |
372 |
| |
373 static void fsb_destroy(Widget widget) { |
| |
374 XnFileSelectionBox w = (XnFileSelectionBox)widget; |
| |
375 |
| |
376 // destroy all views |
| |
377 for(int i=0;i<w->fsb.numviews;i++) { |
| |
378 FSBView v = w->fsb.view[i]; |
| |
379 v.destroy(widget, v.widget, v.userData); |
| |
380 } |
| |
381 |
| |
382 STR_FREE(w->fsb.homePath); |
| |
383 |
| |
384 // free filelists |
| |
385 filedialog_cleanup_filedata(w); |
| |
386 STR_FREE(w->fsb.currentPath); |
| |
387 STR_FREE(w->fsb.selectedPath); |
| |
388 STR_FREE(w->fsb.filterStr); |
| |
389 |
| |
390 PathBarDestroy(w->fsb.pathBar); |
| |
391 |
| |
392 // free strings |
| |
393 STR_FREE(w->fsb.labelListView); |
| |
394 STR_FREE(w->fsb.labelDetailView); |
| |
395 STR_FREE(w->fsb.labelOpenFileTitle); |
| |
396 STR_FREE(w->fsb.labelSaveFileTitle); |
| |
397 |
| |
398 XMSTR_FREE(w->fsb.labelDirUp); |
| |
399 XMSTR_FREE(w->fsb.labelHome); |
| |
400 XMSTR_FREE(w->fsb.labelNewFolder); |
| |
401 XMSTR_FREE(w->fsb.labelFilterButton); |
| |
402 XMSTR_FREE(w->fsb.labelShowHiddenFiles); |
| |
403 XMSTR_FREE(w->fsb.labelDirectories); |
| |
404 XMSTR_FREE(w->fsb.labelFiles); |
| |
405 XMSTR_FREE(w->fsb.labelRename); |
| |
406 XMSTR_FREE(w->fsb.labelDelete); |
| |
407 XMSTR_FREE(w->fsb.labelOpen); |
| |
408 XMSTR_FREE(w->fsb.labelSave); |
| |
409 XMSTR_FREE(w->fsb.labelCancel); |
| |
410 XMSTR_FREE(w->fsb.labelHelp); |
| |
411 XMSTR_FREE(w->fsb.labelFileName); |
| |
412 XMSTR_FREE(w->fsb.labelDirectoryName); |
| |
413 XMSTR_FREE(w->fsb.labelNewFileName); |
| |
414 STR_FREE(w->fsb.labelDeleteFile); |
| |
415 STR_FREE(w->fsb.detailHeadings); |
| |
416 |
| |
417 STR_FREE(w->fsb.dateFormatSameYear); |
| |
418 STR_FREE(w->fsb.dateFormatOtherYear); |
| |
419 STR_FREE(w->fsb.suffixBytes); |
| |
420 STR_FREE(w->fsb.suffixKB); |
| |
421 STR_FREE(w->fsb.suffixMB); |
| |
422 STR_FREE(w->fsb.suffixGB); |
| |
423 STR_FREE(w->fsb.suffixTB); |
| |
424 |
| |
425 STR_FREE(w->fsb.errorTitle); |
| |
426 STR_FREE(w->fsb.errorIllegalChar); |
| |
427 STR_FREE(w->fsb.errorRename); |
| |
428 STR_FREE(w->fsb.errorFolder); |
| |
429 STR_FREE(w->fsb.errorDelete); |
| |
430 STR_FREE(w->fsb.errorOpenDir); |
| |
431 } |
| |
432 |
| |
433 static void fsb_resize(Widget widget) { |
| |
434 XnFileSelectionBox w = (XnFileSelectionBox)widget; |
| |
435 (xmFormClassRec.core_class.resize)(widget); |
| |
436 |
| |
437 #ifdef FSB_ENABLE_DETAIL |
| |
438 if(w->fsb.view[w->fsb.selectedview].update == FileListDetailUpdate) { |
| |
439 FileListDetailAdjustColWidth(w->fsb.grid); |
| |
440 } |
| |
441 #endif |
| |
442 } |
| |
443 |
| |
444 static void fsb_realize(Widget widget, XtValueMask *mask, XSetWindowAttributes *attributes) { |
| |
445 XnFileSelectionBox w = (XnFileSelectionBox)widget; |
| |
446 (xmFormClassRec.core_class.realize)(widget, mask, attributes); |
| |
447 |
| |
448 FSBView view = w->fsb.view[w->fsb.selectedview]; |
| |
449 XmProcessTraversal(view.focus, XmTRAVERSE_CURRENT); |
| |
450 |
| |
451 #ifdef FSB_ENABLE_DETAIL |
| |
452 if(w->fsb.view[w->fsb.selectedview].update == FileListDetailUpdate) { |
| |
453 FileListDetailAdjustColWidth(w->fsb.grid); |
| |
454 } |
| |
455 #endif |
| |
456 } |
| |
457 |
| |
458 static void FSBUpdateTitle(Widget w) { |
| |
459 if(XtParent(w)->core.widget_class == xmDialogShellWidgetClass) { |
| |
460 char *title = FSBDialogTitle(w); |
| |
461 XtVaSetValues(XtParent(w), XmNtitle, title, NULL); |
| |
462 } |
| |
463 } |
| |
464 |
| |
465 static Boolean fsb_set_values(Widget old, Widget request, Widget neww, ArgList args, Cardinal *num_args) { |
| |
466 Boolean r = False; |
| |
467 |
| |
468 XnFileSelectionBox o = (XnFileSelectionBox)old; |
| |
469 XnFileSelectionBox n = (XnFileSelectionBox)neww; |
| |
470 |
| |
471 int setOkBtnLabel = 0; |
| |
472 int ismanaged = XtIsManaged(neww); |
| |
473 Dimension width, height; |
| |
474 if(!ismanaged) { |
| |
475 width = n->core.width; |
| |
476 height = n->core.height; |
| |
477 if(n->fsb.pathBar) { |
| |
478 n->fsb.pathBar->disableResize = True; |
| |
479 } |
| |
480 } |
| |
481 |
| |
482 if(o->fsb.selectedview != n->fsb.selectedview) { |
| |
483 int selectedview = n->fsb.selectedview; |
| |
484 n->fsb.selectedview = o->fsb.selectedview; |
| |
485 SelectView(n, selectedview); |
| |
486 } |
| |
487 |
| |
488 char *updateDir = NULL; |
| |
489 int selectItem = 0; |
| |
490 if(o->fsb.selectedPath != n->fsb.selectedPath) { |
| |
491 STR_FREE(o->fsb.selectedPath); |
| |
492 STRDUP_RES(n->fsb.selectedPath); |
| |
493 XmTextFieldSetString(n->fsb.name, FileName(n->fsb.selectedPath)); |
| |
494 // also update current directory |
| |
495 updateDir = ParentPath(n->fsb.selectedPath); |
| |
496 selectItem = 1; |
| |
497 } |
| |
498 if(o->fsb.currentPath != n->fsb.currentPath) { |
| |
499 STR_FREE(o->fsb.currentPath); |
| |
500 updateDir = strdup(n->fsb.currentPath); |
| |
501 n->fsb.currentPath = NULL; |
| |
502 } |
| |
503 |
| |
504 if(o->fsb.filterStr != n->fsb.filterStr) { |
| |
505 STR_FREE(o->fsb.filterStr); |
| |
506 STRDUP_RES(n->fsb.filterStr); |
| |
507 XmTextFieldSetString(XmDropDownGetText(n->fsb.filter), n->fsb.filterStr); |
| |
508 if(!updateDir) { |
| |
509 filedialog_update_dir(n, NULL); |
| |
510 } |
| |
511 } |
| |
512 |
| |
513 if(updateDir) { |
| |
514 filedialog_update_dir(n, updateDir); |
| |
515 PathBarSetPath(n->fsb.pathBar, updateDir); |
| |
516 free(updateDir); |
| |
517 } |
| |
518 |
| |
519 if(o->fsb.type != n->fsb.type) { |
| |
520 if(n->fsb.type == FILEDIALOG_OPEN) { |
| |
521 XtVaSetValues(n->fsb.workarea, XmNbottomWidget, n->fsb.separator, NULL); |
| |
522 XtUnmanageChild(n->fsb.name); |
| |
523 XtUnmanageChild(n->fsb.nameLabel); |
| |
524 } else { |
| |
525 XtManageChild(n->fsb.name); |
| |
526 XtManageChild(n->fsb.nameLabel); |
| |
527 XtVaSetValues(n->fsb.workarea, XmNbottomWidget, n->fsb.nameLabel, NULL); |
| |
528 } |
| |
529 FSBUpdateTitle(neww); |
| |
530 setOkBtnLabel = 1; |
| |
531 } |
| |
532 |
| |
533 // label strings |
| |
534 int updateTitle = 0; |
| |
535 if(o->fsb.labelListView != n->fsb.labelListView) { |
| |
536 STR_FREE(o->fsb.labelListView); |
| |
537 STRDUP_RES(n->fsb.labelListView); |
| |
538 XmString label = XmStringCreateLocalized(n->fsb.labelListView); |
| |
539 XtVaSetValues(n->fsb.viewSelectorList, XmNlabelString, label, NULL); |
| |
540 XmStringFree(label); |
| |
541 } |
| |
542 if(o->fsb.labelDetailView != n->fsb.labelDetailView) { |
| |
543 STR_FREE(o->fsb.labelDetailView); |
| |
544 STRDUP_RES(n->fsb.labelDetailView); |
| |
545 XmString label = XmStringCreateLocalized(n->fsb.labelDetailView); |
| |
546 XtVaSetValues(n->fsb.viewSelectorDetail, XmNlabelString, label, NULL); |
| |
547 if(n->fsb.detailToggleButton) { |
| |
548 XtVaSetValues(n->fsb.detailToggleButton, XmNlabelString, label, NULL); |
| |
549 } |
| |
550 XmStringFree(label); |
| |
551 } |
| |
552 if(o->fsb.labelOpenFileTitle != n->fsb.labelOpenFileTitle) { |
| |
553 STR_FREE(o->fsb.labelOpenFileTitle); |
| |
554 STRDUP_RES(n->fsb.labelOpenFileTitle); |
| |
555 updateTitle = 1; |
| |
556 } |
| |
557 if(o->fsb.labelSaveFileTitle != n->fsb.labelSaveFileTitle) { |
| |
558 STR_FREE(o->fsb.labelSaveFileTitle); |
| |
559 STRDUP_RES(n->fsb.labelSaveFileTitle); |
| |
560 updateTitle = 1; |
| |
561 } |
| |
562 |
| |
563 if(o->fsb.labelDirUp != n->fsb.labelDirUp) { |
| |
564 XMSTR_FREE(o->fsb.labelDirUp); |
| |
565 XMS_STRDUP_RES(n->fsb.labelDirUp); |
| |
566 XtVaSetValues(n->fsb.dirUp, XmNlabelString, n->fsb.labelDirUp, NULL); |
| |
567 } |
| |
568 if(o->fsb.labelHome != n->fsb.labelHome) { |
| |
569 XMSTR_FREE(o->fsb.labelHome); |
| |
570 XMS_STRDUP_RES(n->fsb.labelHome); |
| |
571 XtVaSetValues(n->fsb.dirUp, XmNlabelString, n->fsb.labelHome, NULL); |
| |
572 } |
| |
573 if(o->fsb.labelNewFolder != n->fsb.labelNewFolder) { |
| |
574 XMSTR_FREE(o->fsb.labelNewFolder); |
| |
575 XMS_STRDUP_RES(n->fsb.labelNewFolder); |
| |
576 XtVaSetValues(n->fsb.newFolder, XmNlabelString, n->fsb.labelNewFolder, NULL); |
| |
577 } |
| |
578 if(o->fsb.labelFilterButton != n->fsb.labelFilterButton) { |
| |
579 XMSTR_FREE(o->fsb.labelFilterButton); |
| |
580 XMS_STRDUP_RES(n->fsb.labelFilterButton); |
| |
581 XtVaSetValues(n->fsb.filterButton, XmNlabelString, n->fsb.labelFilterButton, NULL); |
| |
582 } |
| |
583 if(o->fsb.labelShowHiddenFiles != n->fsb.labelShowHiddenFiles) { |
| |
584 XMSTR_FREE(o->fsb.labelShowHiddenFiles); |
| |
585 XMS_STRDUP_RES(n->fsb.labelShowHiddenFiles); |
| |
586 XtVaSetValues(n->fsb.showHiddenButtonW, XmNlabelString, n->fsb.labelShowHiddenFiles, NULL); |
| |
587 } |
| |
588 if(o->fsb.labelDirectories != n->fsb.labelDirectories) { |
| |
589 XMSTR_FREE(o->fsb.labelDirectories); |
| |
590 XMS_STRDUP_RES(n->fsb.labelDirectories); |
| |
591 XtVaSetValues(n->fsb.lsDirLabel, XmNlabelString, n->fsb.labelDirectories, NULL); |
| |
592 } |
| |
593 if(o->fsb.labelFiles != n->fsb.labelFiles) { |
| |
594 XMSTR_FREE(o->fsb.labelFiles); |
| |
595 XMS_STRDUP_RES(n->fsb.labelFiles); |
| |
596 XtVaSetValues(n->fsb.lsFileLabel, XmNlabelString, n->fsb.labelFiles, NULL); |
| |
597 } |
| |
598 int recreateContextMenu = 0; |
| |
599 if(o->fsb.labelRename != n->fsb.labelRename) { |
| |
600 XMSTR_FREE(o->fsb.labelRename); |
| |
601 XMS_STRDUP_RES(n->fsb.labelRename); |
| |
602 recreateContextMenu = 1; |
| |
603 } |
| |
604 if(o->fsb.labelDelete != n->fsb.labelDelete) { |
| |
605 XMSTR_FREE(o->fsb.labelDelete); |
| |
606 XMS_STRDUP_RES(n->fsb.labelDelete); |
| |
607 recreateContextMenu = 1; |
| |
608 } |
| |
609 |
| |
610 if(o->fsb.labelOpen != n->fsb.labelOpen) { |
| |
611 XMSTR_FREE(o->fsb.labelOpen); |
| |
612 XMS_STRDUP_RES(n->fsb.labelOpen); |
| |
613 setOkBtnLabel = 1; |
| |
614 } |
| |
615 if(o->fsb.labelSave != n->fsb.labelSave) { |
| |
616 XMSTR_FREE(o->fsb.labelSave); |
| |
617 XMS_STRDUP_RES(n->fsb.labelSave); |
| |
618 setOkBtnLabel = 1; |
| |
619 } |
| |
620 if(o->fsb.labelCancel != n->fsb.labelCancel) { |
| |
621 XMSTR_FREE(o->fsb.labelCancel); |
| |
622 XMS_STRDUP_RES(n->fsb.labelCancel); |
| |
623 XtVaSetValues(n->fsb.cancelBtn, XmNlabelString, n->fsb.labelCancel, NULL); |
| |
624 } |
| |
625 if(o->fsb.labelHelp != n->fsb.labelHelp) { |
| |
626 XMSTR_FREE(o->fsb.labelHelp); |
| |
627 XMS_STRDUP_RES(n->fsb.labelHelp); |
| |
628 XtVaSetValues(n->fsb.helpBtn, XmNlabelString, n->fsb.labelHelp, NULL); |
| |
629 } |
| |
630 if(o->fsb.labelFileName != n->fsb.labelFileName) { |
| |
631 XMSTR_FREE(o->fsb.labelFileName); |
| |
632 XMS_STRDUP_RES(n->fsb.labelFileName); |
| |
633 XtVaSetValues(n->fsb.nameLabel, XmNlabelString, n->fsb.labelFileName, NULL); |
| |
634 } |
| |
635 if(o->fsb.labelDirectoryName != n->fsb.labelDirectoryName) { |
| |
636 XMSTR_FREE(o->fsb.labelDirectoryName); |
| |
637 XMS_STRDUP_RES(n->fsb.labelDirectoryName); |
| |
638 } |
| |
639 if(o->fsb.labelNewFileName != n->fsb.labelNewFileName) { |
| |
640 XMSTR_FREE(o->fsb.labelNewFileName); |
| |
641 XMS_STRDUP_RES(n->fsb.labelNewFileName); |
| |
642 } |
| |
643 |
| |
644 if(o->fsb.labelDeleteFile != n->fsb.labelDeleteFile) { |
| |
645 STR_FREE(o->fsb.labelDeleteFile); |
| |
646 STRDUP_RES(n->fsb.labelDeleteFile); |
| |
647 } |
| |
648 #ifdef FSB_ENABLE_DETAIL |
| |
649 if(o->fsb.detailHeadings != n->fsb.detailHeadings) { |
| |
650 STR_FREE(o->fsb.detailHeadings); |
| |
651 STRDUP_RES(n->fsb.detailHeadings); |
| |
652 XtVaSetValues(n->fsb.grid, XmNsimpleHeadings, n->fsb.detailHeadings, NULL); |
| |
653 } |
| |
654 #endif |
| |
655 if(o->fsb.dateFormatSameYear != n->fsb.dateFormatSameYear) { |
| |
656 STR_FREE(o->fsb.dateFormatSameYear); |
| |
657 STRDUP_RES(n->fsb.dateFormatSameYear); |
| |
658 } |
| |
659 if(o->fsb.dateFormatOtherYear != n->fsb.dateFormatOtherYear) { |
| |
660 STR_FREE(o->fsb.dateFormatOtherYear); |
| |
661 STRDUP_RES(n->fsb.dateFormatOtherYear); |
| |
662 } |
| |
663 if(o->fsb.suffixBytes != n->fsb.suffixBytes) { |
| |
664 STR_FREE(o->fsb.suffixBytes); |
| |
665 STRDUP_RES(n->fsb.suffixBytes); |
| |
666 } |
| |
667 if(o->fsb.suffixMB != n->fsb.suffixMB) { |
| |
668 STR_FREE(o->fsb.suffixMB); |
| |
669 STRDUP_RES(n->fsb.suffixMB); |
| |
670 } |
| |
671 if(o->fsb.suffixGB != n->fsb.suffixGB) { |
| |
672 STR_FREE(o->fsb.suffixGB); |
| |
673 STRDUP_RES(n->fsb.suffixGB); |
| |
674 } |
| |
675 if(o->fsb.suffixTB != n->fsb.suffixTB) { |
| |
676 STR_FREE(o->fsb.suffixTB); |
| |
677 STRDUP_RES(n->fsb.suffixTB); |
| |
678 } |
| |
679 if(o->fsb.errorTitle != n->fsb.errorTitle) { |
| |
680 STR_FREE(o->fsb.errorTitle); |
| |
681 STRDUP_RES(n->fsb.errorTitle); |
| |
682 } |
| |
683 if(o->fsb.errorIllegalChar != n->fsb.errorIllegalChar) { |
| |
684 STR_FREE(o->fsb.errorIllegalChar); |
| |
685 STRDUP_RES(n->fsb.errorIllegalChar); |
| |
686 } |
| |
687 if(o->fsb.errorRename != n->fsb.errorRename) { |
| |
688 STR_FREE(o->fsb.errorRename); |
| |
689 STRDUP_RES(n->fsb.errorRename); |
| |
690 } |
| |
691 if(o->fsb.errorFolder != n->fsb.errorFolder) { |
| |
692 STR_FREE(o->fsb.errorFolder); |
| |
693 STRDUP_RES(n->fsb.errorFolder); |
| |
694 } |
| |
695 if(o->fsb.errorDelete != n->fsb.errorDelete) { |
| |
696 STR_FREE(o->fsb.errorDelete); |
| |
697 STRDUP_RES(n->fsb.errorDelete); |
| |
698 } |
| |
699 if(o->fsb.errorOpenDir != n->fsb.errorOpenDir) { |
| |
700 STR_FREE(o->fsb.errorOpenDir); |
| |
701 STRDUP_RES(n->fsb.errorOpenDir); |
| |
702 } |
| |
703 |
| |
704 if(updateTitle) { |
| |
705 FSBUpdateTitle(neww); |
| |
706 } |
| |
707 if(recreateContextMenu) { |
| |
708 XtDestroyWidget(n->fsb.listContextMenu); |
| |
709 XtDestroyWidget(n->fsb.gridContextMenu); |
| |
710 n->fsb.listContextMenu = CreateContextMenu(n, n->fsb.filelist, FileContextMenuCB); |
| |
711 n->fsb.gridContextMenu = CreateContextMenu(n, n->fsb.grid, FileContextMenuCB); |
| |
712 } |
| |
713 if(setOkBtnLabel) { |
| |
714 XtVaSetValues(n->fsb.okBtn, XmNlabelString, n->fsb.type == FILEDIALOG_OPEN ? n->fsb.labelOpen : n->fsb.labelSave, NULL); |
| |
715 } |
| |
716 |
| |
717 if(!ismanaged && !n->fsb.disable_set_values) { |
| |
718 n->fsb.disable_set_values = 1; |
| |
719 XtVaSetValues(neww, XmNwidth, width, XmNheight, height, NULL); |
| |
720 n->fsb.disable_set_values = 0; |
| |
721 |
| |
722 if(n->fsb.pathBar) |
| |
723 n->fsb.pathBar->disableResize = False; |
| |
724 } |
| |
725 |
| |
726 if(selectItem) { |
| |
727 if(ismanaged) { |
| |
728 FSBSelectItem(n, FileName(n->fsb.selectedPath)); |
| |
729 } |
| |
730 } |
| |
731 |
| |
732 Boolean fr = (xmFormClassRec.core_class.set_values)(old, request, neww, args, num_args); |
| |
733 return fr ? fr : r; |
| |
734 } |
| |
735 |
| |
736 static void fsb_insert_child(Widget child) { |
| |
737 XnFileSelectionBox p = (XnFileSelectionBox)XtParent(child); |
| |
738 (xmFormClassRec.composite_class.insert_child)(child); |
| |
739 |
| |
740 if(!p->fsb.gui_created) { |
| |
741 return; |
| |
742 } |
| |
743 |
| |
744 // custom child widget insert |
| |
745 XtVaSetValues(child, |
| |
746 XmNbottomAttachment, XmATTACH_WIDGET, |
| |
747 XmNbottomWidget, p->fsb.bottom_widget, |
| |
748 XmNbottomOffset, p->fsb.widgetSpacing, |
| |
749 XmNleftAttachment, XmATTACH_FORM, |
| |
750 XmNleftOffset, p->fsb.windowSpacing, |
| |
751 XmNrightAttachment, XmATTACH_FORM, |
| |
752 XmNrightAttachment, XmATTACH_FORM, |
| |
753 XmNrightOffset, p->fsb.windowSpacing, |
| |
754 NULL); |
| |
755 |
| |
756 |
| |
757 XtVaSetValues(p->fsb.listform, |
| |
758 XmNbottomWidget, child, |
| |
759 XmNbottomOffset, 0, |
| |
760 NULL); |
| |
761 |
| |
762 p->fsb.workarea = child; |
| |
763 } |
| |
764 |
| |
765 Boolean fsb_acceptfocus(Widget widget, Time *time) { |
| |
766 return 0; |
| |
767 } |
| |
768 |
| |
769 static void fsb_mapcb(Widget widget, XtPointer u, XtPointer cb) { |
| |
770 XnFileSelectionBox w = (XnFileSelectionBox)widget; |
| |
771 pathbar_resize(w->fsb.pathBar->widget, w->fsb.pathBar, NULL); |
| |
772 |
| |
773 if(w->fsb.type == FILEDIALOG_OPEN) { |
| |
774 FSBView view = w->fsb.view[w->fsb.selectedview]; |
| |
775 XmProcessTraversal(view.focus, XmTRAVERSE_CURRENT); |
| |
776 } else { |
| |
777 XmProcessTraversal(w->fsb.name, XmTRAVERSE_CURRENT); |
| |
778 } |
| |
779 |
| |
780 |
| |
781 if(w->fsb.selectedPath) { |
| |
782 FSBSelectItem(w, FileName(w->fsb.selectedPath)); |
| |
783 } |
| |
784 } |
| |
785 |
| |
786 static void FocusInAP(Widget w, XEvent *event, String *args, Cardinal *nArgs) { |
| |
787 |
| |
788 } |
| |
789 |
| |
790 static int apply_filter(XnFileSelectionBox w, const char *pattern, const char *string) { |
| |
791 if(!pattern) return 0; |
| |
792 |
| |
793 FSBFilterFunc func = w->fsb.filterFunc ? w->fsb.filterFunc : FSBGlobFilter; |
| |
794 return func(pattern, string); |
| |
795 } |
| |
796 |
| |
797 static int FSBGlobFilter(const char *a, const char *b) { |
| |
798 return fnmatch(a, b, 0); |
| |
799 } |
| |
800 |
| |
801 |
| |
802 static void errCB(Widget w, XtPointer d, XtPointer cbs) { |
| |
803 XtDestroyWidget(w); |
| |
804 } |
| |
805 |
| |
806 static void ErrDialog(XnFileSelectionBox w, const char *title, const char *errmsg) { |
| |
807 Arg args[16]; |
| |
808 int n = 0; |
| |
809 |
| |
810 XmString titleStr = XmStringCreateLocalized((char*)title); |
| |
811 XmString msg = XmStringCreateLocalized((char*)errmsg); |
| |
812 |
| |
813 XtSetArg(args[n], XmNdialogTitle, titleStr); n++; |
| |
814 XtSetArg(args[n], XmNselectionLabelString, msg); n++; |
| |
815 XtSetArg(args[n], XmNokLabelString, w->fsb.labelOk); n++; |
| |
816 XtSetArg(args[n], XmNcancelLabelString, w->fsb.labelCancel); n++; |
| |
817 |
| |
818 Widget dialog = XmCreatePromptDialog ((Widget)w, "NewFolderPrompt", args, n); |
| |
819 |
| |
820 Widget help = XmSelectionBoxGetChild(dialog, XmDIALOG_HELP_BUTTON); |
| |
821 XtUnmanageChild(help); |
| |
822 Widget cancel = XmSelectionBoxGetChild(dialog, XmDIALOG_CANCEL_BUTTON); |
| |
823 XtUnmanageChild(cancel); |
| |
824 Widget text = XmSelectionBoxGetChild(dialog, XmDIALOG_TEXT); |
| |
825 XtUnmanageChild(text); |
| |
826 |
| |
827 XtAddCallback(dialog, XmNokCallback, errCB, NULL); |
| |
828 |
| |
829 XtManageChild(dialog); |
| |
830 |
| |
831 XmStringFree(titleStr); |
| |
832 XmStringFree(msg); |
| |
833 } |
| |
834 |
| |
835 static void rename_file_cb(Widget w, const char *path, XmSelectionBoxCallbackStruct *cb) { |
| |
836 XnFileSelectionBox fsb = NULL; |
| |
837 XtVaGetValues(w, XmNuserData, &fsb, NULL); |
| |
838 |
| |
839 char *fileName = NULL; |
| |
840 XmStringGetLtoR(cb->value, XmSTRING_DEFAULT_CHARSET, &fileName); |
| |
841 |
| |
842 // make sure the new file name doesn't contain a path separator |
| |
843 if(strchr(fileName, '/')) { |
| |
844 ErrDialog(fsb, fsb->fsb.errorTitle, fsb->fsb.errorIllegalChar); |
| |
845 XtFree(fileName); |
| |
846 return; |
| |
847 } |
| |
848 |
| |
849 char *parentPath = ParentPath(path); |
| |
850 char *newPath = ConcatPath(parentPath, fileName); |
| |
851 |
| |
852 if(rename(path, newPath)) { |
| |
853 char errmsg[256]; |
| |
854 snprintf(errmsg, 256, fsb->fsb.errorRename, strerror(errno)); |
| |
855 ErrDialog(fsb, fsb->fsb.errorTitle, errmsg); |
| |
856 } else { |
| |
857 filedialog_update_dir(fsb, parentPath); |
| |
858 } |
| |
859 |
| |
860 free(parentPath); |
| |
861 free(newPath); |
| |
862 XtFree(fileName); |
| |
863 XtDestroyWidget(XtParent(w)); |
| |
864 } |
| |
865 |
| |
866 static void selectionbox_cancel(Widget w, XtPointer data, XtPointer d) { |
| |
867 XtDestroyWidget(XtParent(w)); |
| |
868 } |
| |
869 |
| |
870 static void FSBRename(XnFileSelectionBox fsb, const char *path) { |
| |
871 Arg args[16]; |
| |
872 int n = 0; |
| |
873 Widget w = (Widget)fsb; |
| |
874 |
| |
875 char *name = FileName((char*)path); |
| |
876 |
| |
877 XmString filename = XmStringCreateLocalized(name); |
| |
878 XtSetArg(args[n], XmNselectionLabelString,fsb->fsb.labelNewFileName); n++; |
| |
879 XtSetArg(args[n], XmNtextString, filename); n++; |
| |
880 XtSetArg(args[n], XmNuserData, fsb); n++; |
| |
881 XtSetArg(args[n], XmNdialogTitle, fsb->fsb.labelRename); n++; |
| |
882 XtSetArg(args[n], XmNokLabelString, fsb->fsb.labelOk); n++; |
| |
883 XtSetArg(args[n], XmNcancelLabelString, fsb->fsb.labelCancel); n++; |
| |
884 Widget dialog = XmCreatePromptDialog (w, "RenameFilePrompt", args, n); |
| |
885 |
| |
886 Widget help = XmSelectionBoxGetChild(dialog, XmDIALOG_HELP_BUTTON); |
| |
887 XtUnmanageChild(help); |
| |
888 |
| |
889 XtAddCallback(dialog, XmNokCallback, (XtCallbackProc)rename_file_cb, (char*)path); |
| |
890 XtAddCallback(dialog, XmNcancelCallback, (XtCallbackProc)selectionbox_cancel, NULL); |
| |
891 |
| |
892 XmStringFree(filename); |
| |
893 XtManageChild(dialog); |
| |
894 } |
| |
895 |
| |
896 static void delete_file_cb(Widget w, const char *path, XmSelectionBoxCallbackStruct *cb) { |
| |
897 XnFileSelectionBox fsb = NULL; |
| |
898 XtVaGetValues(w, XmNuserData, &fsb, NULL); |
| |
899 |
| |
900 if(unlink(path)) { |
| |
901 char errmsg[256]; |
| |
902 snprintf(errmsg, 256, fsb->fsb.errorDelete, strerror(errno)); |
| |
903 ErrDialog(fsb, fsb->fsb.errorTitle, errmsg); |
| |
904 } else { |
| |
905 char *parentPath = ParentPath(path); |
| |
906 filedialog_update_dir(fsb, parentPath); |
| |
907 free(parentPath); |
| |
908 } |
| |
909 |
| |
910 XtDestroyWidget(XtParent(w)); |
| |
911 } |
| |
912 |
| |
913 static void FSBDelete(XnFileSelectionBox fsb, const char *path) { |
| |
914 Arg args[16]; |
| |
915 int n = 0; |
| |
916 Widget w = (Widget)fsb; |
| |
917 |
| |
918 char *name = FileName((char*)path); |
| |
919 size_t len = strlen(name); |
| |
920 size_t msglen = len + strlen(fsb->fsb.labelDeleteFile) + 4; |
| |
921 char *msg = malloc(msglen); |
| |
922 snprintf(msg, msglen, fsb->fsb.labelDeleteFile, name); |
| |
923 |
| |
924 XmString prompt = XmStringCreateLocalized(msg); |
| |
925 XtSetArg(args[n], XmNselectionLabelString, prompt); n++; |
| |
926 XtSetArg(args[n], XmNuserData, fsb); n++; |
| |
927 XtSetArg(args[n], XmNdialogTitle, fsb->fsb.labelDelete); n++; |
| |
928 XtSetArg(args[n], XmNokLabelString, fsb->fsb.labelOk); n++; |
| |
929 XtSetArg(args[n], XmNcancelLabelString, fsb->fsb.labelCancel); n++; |
| |
930 Widget dialog = XmCreatePromptDialog (w, "DeleteFilePrompt", args, n); |
| |
931 |
| |
932 Widget help = XmSelectionBoxGetChild(dialog, XmDIALOG_HELP_BUTTON); |
| |
933 XtUnmanageChild(help); |
| |
934 Widget text = XmSelectionBoxGetChild(dialog, XmDIALOG_TEXT); |
| |
935 XtUnmanageChild(text); |
| |
936 |
| |
937 XtAddCallback(dialog, XmNokCallback, (XtCallbackProc)delete_file_cb, (char*)path); |
| |
938 XtAddCallback(dialog, XmNcancelCallback, (XtCallbackProc)selectionbox_cancel, NULL); |
| |
939 |
| |
940 free(msg); |
| |
941 XmStringFree(prompt); |
| |
942 XtManageChild(dialog); |
| |
943 } |
| |
944 |
| |
945 static void FSBSelectItem(XnFileSelectionBox fsb, const char *item) { |
| |
946 FSBView view = fsb->fsb.view[fsb->fsb.selectedview]; |
| |
947 if(view.select) { |
| |
948 view.select((Widget)fsb, view.widget, item); |
| |
949 } |
| |
950 } |
| |
951 |
| |
952 static char* set_selected_path(XnFileSelectionBox data, XmString item) |
| |
953 { |
| |
954 char *name = NULL; |
| |
955 XmStringGetLtoR(item, XmFONTLIST_DEFAULT_TAG, &name); |
| |
956 if(!name) { |
| |
957 return NULL; |
| |
958 } |
| |
959 char *path = ConcatPath(data->fsb.currentPath, name); |
| |
960 XtFree(name); |
| |
961 |
| |
962 if(data->fsb.selectedPath) { |
| |
963 free(data->fsb.selectedPath); |
| |
964 } |
| |
965 data->fsb.selectedPath = path; |
| |
966 |
| |
967 return path; |
| |
968 } |
| |
969 |
| |
970 // item0: rename |
| |
971 // item1: delete |
| |
972 static void FileContextMenuCB(Widget item, XtPointer index, XtPointer cd) { |
| |
973 intptr_t i = (intptr_t)index; |
| |
974 Widget parent = XtParent(item); |
| |
975 XnFileSelectionBox fsb = NULL; |
| |
976 XtVaGetValues(parent, XmNuserData, &fsb, NULL); |
| |
977 |
| |
978 const char *path = fsb->fsb.selectedPath; |
| |
979 if(path) { |
| |
980 if(i == 0) { |
| |
981 FSBRename(fsb, path); |
| |
982 } else if(i == 1) { |
| |
983 FSBDelete(fsb, path); |
| |
984 } |
| |
985 } |
| |
986 } |
| |
987 |
| |
988 static Widget CreateContextMenu(XnFileSelectionBox fsb, Widget parent, XtCallbackProc callback) { |
| |
989 return XmVaCreateSimplePopupMenu( |
| |
990 parent, "popup", callback, XmNpopupEnabled, XmPOPUP_AUTOMATIC, |
| |
991 XmNuserData, fsb, |
| |
992 XmVaPUSHBUTTON, fsb->fsb.labelRename, 'R', NULL, NULL, |
| |
993 XmVaPUSHBUTTON, fsb->fsb.labelDelete, 'D', NULL, NULL, |
| |
994 NULL); |
| |
995 } |
| |
996 |
| |
997 |
| |
998 static void FileListUpdate(Widget fsb, Widget view, FileElm *dirs, int dircount, FileElm *files, int filecount, const char *filter, int maxnamelen, void *userData) { |
| |
999 XnFileSelectionBox data = userData; |
| |
1000 FileListWidgetAdd(data, data->fsb.filelist, data->fsb.showHidden, filter, files, filecount); |
| |
1001 } |
| |
1002 |
| |
1003 static void FileListSelect(Widget fsb, Widget view, const char *item) { |
| |
1004 XnFileSelectionBox w = (XnFileSelectionBox)fsb; |
| |
1005 |
| |
1006 int numItems = 0; |
| |
1007 XmStringTable items = NULL; |
| |
1008 XtVaGetValues(w->fsb.filelist, XmNitemCount, &numItems, XmNitems, &items, NULL); |
| |
1009 |
| |
1010 for(int i=0;i<numItems;i++) { |
| |
1011 char *str = NULL; |
| |
1012 XmStringGetLtoR(items[i], XmFONTLIST_DEFAULT_TAG, &str); |
| |
1013 if(!strcmp(str, item)) { |
| |
1014 XmListSelectPos(w->fsb.filelist, i+1, False); |
| |
1015 break; |
| |
1016 } |
| |
1017 XtFree(str); |
| |
1018 } |
| |
1019 } |
| |
1020 |
| |
1021 static void FileListCleanup(Widget fsb, Widget view, void *userData) { |
| |
1022 XnFileSelectionBox data = userData; |
| |
1023 XmListDeleteAllItems(data->fsb.filelist); |
| |
1024 } |
| |
1025 |
| |
1026 static void FileListDestroy(Widget fsb, Widget view, void *userData) { |
| |
1027 // unused |
| |
1028 } |
| |
1029 |
| |
1030 static void FileListActivateCB(Widget w, XnFileSelectionBox data, XmListCallbackStruct *cb) |
| |
1031 { |
| |
1032 char *path = set_selected_path(data, cb->item); |
| |
1033 if(path) { |
| |
1034 data->fsb.end = True; |
| |
1035 data->fsb.status = FILEDIALOG_OK; |
| |
1036 data->fsb.selIsDir = False; |
| |
1037 FileSelectionCallback(data, data->fsb.okCallback, XmCR_OK, data->fsb.selectedPath); |
| |
1038 } |
| |
1039 } |
| |
1040 |
| |
1041 static void FileListSelectCB(Widget w, XnFileSelectionBox data, XmListCallbackStruct *cb) |
| |
1042 { |
| |
1043 if(data->fsb.type == FILEDIALOG_SAVE) { |
| |
1044 char *name = NULL; |
| |
1045 XmStringGetLtoR(cb->item, XmFONTLIST_DEFAULT_TAG, &name); |
| |
1046 XmTextFieldSetString(data->fsb.name, name); |
| |
1047 XtFree(name); |
| |
1048 } else { |
| |
1049 char *path = set_selected_path(data, cb->item); |
| |
1050 if(path) { |
| |
1051 data->fsb.selIsDir = False; |
| |
1052 } |
| |
1053 } |
| |
1054 } |
| |
1055 |
| |
1056 |
| |
1057 static void FileListWidgetAdd(XnFileSelectionBox fsb, Widget w, int showHidden, const char *filter, FileElm *ls, int count) |
| |
1058 { |
| |
1059 if(count > 0) { |
| |
1060 XmStringTable items = calloc(count, sizeof(XmString)); |
| |
1061 int i = 0; |
| |
1062 |
| |
1063 for(int j=0;j<count;j++) { |
| |
1064 FileElm *e = &ls[j]; |
| |
1065 |
| |
1066 char *name = FileName(e->path); |
| |
1067 if((!showHidden && name[0] == '.') || apply_filter(fsb, filter, name)) { |
| |
1068 continue; |
| |
1069 } |
| |
1070 |
| |
1071 items[i] = XmStringCreateLocalized(name); |
| |
1072 i++; |
| |
1073 } |
| |
1074 XmListAddItems(w, items, i, 0); |
| |
1075 for(i=0;i<count;i++) { |
| |
1076 XmStringFree(items[i]); |
| |
1077 } |
| |
1078 free(items); |
| |
1079 } |
| |
1080 } |
| |
1081 |
| |
1082 #ifdef FSB_ENABLE_DETAIL |
| |
1083 static void FileListDetailUpdate(Widget fsb, Widget view, FileElm *dirs, int dircount, FileElm *files, int filecount, const char *filter, int maxnamelen, void *userData) { |
| |
1084 XnFileSelectionBox data = userData; |
| |
1085 FileListDetailAdd(data, data->fsb.grid, data->fsb.showHidden, filter, files, filecount, maxnamelen); |
| |
1086 } |
| |
1087 #endif |
| |
1088 |
| |
1089 /* |
| |
1090 * create file size string with kb/mb/gb/tb suffix |
| |
1091 */ |
| |
1092 static char* size_str(XnFileSelectionBox fsb, FileElm *f) { |
| |
1093 char *str = malloc(16); |
| |
1094 uint64_t size = f->size; |
| |
1095 |
| |
1096 if(f->isDirectory) { |
| |
1097 str[0] = '\0'; |
| |
1098 } else if(size < 0x400) { |
| |
1099 snprintf(str, 16, "%d %s", (int)size, fsb->fsb.suffixBytes); |
| |
1100 } else if(size < 0x100000) { |
| |
1101 float s = (float)size/0x400; |
| |
1102 int diff = (s*100 - (int)s*100); |
| |
1103 if(diff > 90) { |
| |
1104 diff = 0; |
| |
1105 s += 0.10f; |
| |
1106 } |
| |
1107 if(size < 0x2800 && diff != 0) { |
| |
1108 // size < 10 KiB |
| |
1109 snprintf(str, 16, "%.1f %s", s, fsb->fsb.suffixKB); |
| |
1110 } else { |
| |
1111 snprintf(str, 16, "%.0f %s", s, fsb->fsb.suffixKB); |
| |
1112 } |
| |
1113 } else if(size < 0x40000000) { |
| |
1114 float s = (float)size/0x100000; |
| |
1115 int diff = (s*100 - (int)s*100); |
| |
1116 if(diff > 90) { |
| |
1117 diff = 0; |
| |
1118 s += 0.10f; |
| |
1119 } |
| |
1120 if(size < 0xa00000 && diff != 0) { |
| |
1121 // size < 10 MiB |
| |
1122 snprintf(str, 16, "%.1f %s", s, fsb->fsb.suffixMB); |
| |
1123 } else { |
| |
1124 snprintf(str, 16, "%.0f %s", s, fsb->fsb.suffixMB); |
| |
1125 } |
| |
1126 } else if(size < 0x1000000000ULL) { |
| |
1127 float s = (float)size/0x40000000; |
| |
1128 int diff = (s*100 - (int)s*100); |
| |
1129 if(diff > 90) { |
| |
1130 diff = 0; |
| |
1131 s += 0.10f; |
| |
1132 } |
| |
1133 if(size < 0x280000000 && diff != 0) { |
| |
1134 // size < 10 GiB |
| |
1135 snprintf(str, 16, "%.1f %s", s, fsb->fsb.suffixGB); |
| |
1136 } else { |
| |
1137 snprintf(str, 16, "%.0f %s", s, fsb->fsb.suffixGB); |
| |
1138 } |
| |
1139 } else { |
| |
1140 size /= 1024; |
| |
1141 float s = (float)size/0x40000000; |
| |
1142 int diff = (s*100 - (int)s*100); |
| |
1143 if(diff > 90) { |
| |
1144 diff = 0; |
| |
1145 s += 0.10f; |
| |
1146 } |
| |
1147 if(size < 0x280000000 && diff != 0) { |
| |
1148 // size < 10 TiB |
| |
1149 snprintf(str, 16, "%.1f %s", s, fsb->fsb.suffixTB); |
| |
1150 } else { |
| |
1151 snprintf(str, 16, "%.0f %s", s, fsb->fsb.suffixTB); |
| |
1152 } |
| |
1153 } |
| |
1154 return str; |
| |
1155 } |
| |
1156 |
| |
1157 static char* date_str(XnFileSelectionBox fsb, time_t tm) { |
| |
1158 struct tm t; |
| |
1159 struct tm n; |
| |
1160 time_t now = time(NULL); |
| |
1161 |
| |
1162 localtime_r(&tm, &t); |
| |
1163 localtime_r(&now, &n); |
| |
1164 |
| |
1165 char *str = malloc(24); |
| |
1166 if(t.tm_year == n.tm_year) { |
| |
1167 strftime(str, 24, fsb->fsb.dateFormatSameYear, &t); |
| |
1168 } else { |
| |
1169 strftime(str, 24, fsb->fsb.dateFormatOtherYear, &t); |
| |
1170 } |
| |
1171 return str; |
| |
1172 } |
| |
1173 |
| |
1174 #ifdef FSB_ENABLE_DETAIL |
| |
1175 static void FileListDetailAdjustColWidth(Widget grid) { |
| |
1176 XmLGridColumn column0 = XmLGridGetColumn(grid, XmCONTENT, 0); |
| |
1177 XmLGridColumn column1 = XmLGridGetColumn(grid, XmCONTENT, 1); |
| |
1178 XmLGridColumn column2 = XmLGridGetColumn(grid, XmCONTENT, 2); |
| |
1179 |
| |
1180 Dimension col0Width = XmLGridColumnWidthInPixels(column0); |
| |
1181 Dimension col1Width = XmLGridColumnWidthInPixels(column1); |
| |
1182 Dimension col2Width = XmLGridColumnWidthInPixels(column2); |
| |
1183 |
| |
1184 Dimension totalWidth = col0Width + col1Width + col2Width; |
| |
1185 |
| |
1186 Dimension gridWidth = 0; |
| |
1187 Dimension gridShadow = 0; |
| |
1188 XtVaGetValues(grid, XmNwidth, &gridWidth, XmNshadowThickness, &gridShadow, NULL); |
| |
1189 |
| |
1190 Dimension widthDiff = gridWidth - totalWidth - gridShadow - gridShadow; |
| |
1191 |
| |
1192 if(gridWidth > totalWidth) { |
| |
1193 XtVaSetValues(grid, |
| |
1194 XmNcolumnRangeStart, 0, |
| |
1195 XmNcolumnRangeEnd, 0, |
| |
1196 XmNcolumnWidth, col0Width + widthDiff - XmLGridVSBWidth(grid) - 2, |
| |
1197 XmNcolumnSizePolicy, XmCONSTANT, |
| |
1198 NULL); |
| |
1199 } |
| |
1200 } |
| |
1201 |
| |
1202 static void FileListDetailAdd(XnFileSelectionBox fsb, Widget grid, int showHidden, const char *filter, FileElm *ls, int count, int maxWidth) |
| |
1203 { |
| |
1204 XmLGridAddRows(grid, XmCONTENT, 1, count); |
| |
1205 |
| |
1206 int row = 0; |
| |
1207 for(int i=0;i<count;i++) { |
| |
1208 FileElm *e = &ls[i]; |
| |
1209 |
| |
1210 char *name = FileName(e->path); |
| |
1211 if((!showHidden && name[0] == '.') || (!e->isDirectory && apply_filter(fsb, filter, name))) { |
| |
1212 continue; |
| |
1213 } |
| |
1214 |
| |
1215 // name |
| |
1216 XmString str = XmStringCreateLocalized(name); |
| |
1217 XtVaSetValues(grid, |
| |
1218 XmNcolumn, 0, |
| |
1219 XmNrow, row, |
| |
1220 XmNcellString, str, NULL); |
| |
1221 XmStringFree(str); |
| |
1222 // size |
| |
1223 char *szbuf = size_str(fsb, e); |
| |
1224 str = XmStringCreateLocalized(szbuf); |
| |
1225 XtVaSetValues(grid, |
| |
1226 XmNcolumn, 1, |
| |
1227 XmNrow, row, |
| |
1228 XmNcellString, str, NULL); |
| |
1229 free(szbuf); |
| |
1230 XmStringFree(str); |
| |
1231 // date |
| |
1232 char *datebuf = date_str(fsb, e->lastModified); |
| |
1233 str = XmStringCreateLocalized(datebuf); |
| |
1234 XtVaSetValues(grid, |
| |
1235 XmNcolumn, 2, |
| |
1236 XmNrow, row, |
| |
1237 XmNcellString, str, NULL); |
| |
1238 free(datebuf); |
| |
1239 XmStringFree(str); |
| |
1240 |
| |
1241 XtVaSetValues(grid, XmNrow, row, XmNrowUserData, e, NULL); |
| |
1242 row++; |
| |
1243 } |
| |
1244 |
| |
1245 // remove unused rows |
| |
1246 if(count > row) { |
| |
1247 XmLGridDeleteRows(grid, XmCONTENT, row, count-row); |
| |
1248 } |
| |
1249 |
| |
1250 if(maxWidth < 16) { |
| |
1251 maxWidth = 16; |
| |
1252 } |
| |
1253 |
| |
1254 XtVaSetValues(grid, |
| |
1255 XmNcolumnRangeStart, 0, |
| |
1256 XmNcolumnRangeEnd, 0, |
| |
1257 XmNcolumnWidth, maxWidth, |
| |
1258 XmNcellAlignment, XmALIGNMENT_LEFT, |
| |
1259 XmNcolumnSizePolicy, XmVARIABLE, |
| |
1260 NULL); |
| |
1261 XtVaSetValues(grid, |
| |
1262 XmNcolumnRangeStart, 1, |
| |
1263 XmNcolumnRangeEnd, 1, |
| |
1264 XmNcolumnWidth, 9, |
| |
1265 XmNcellAlignment, XmALIGNMENT_LEFT, |
| |
1266 XmNcolumnSizePolicy, XmVARIABLE, |
| |
1267 NULL); |
| |
1268 XtVaSetValues(grid, |
| |
1269 XmNcolumnRangeStart, 2, |
| |
1270 XmNcolumnRangeEnd, 2, |
| |
1271 XmNcolumnWidth, 16, |
| |
1272 XmNcellAlignment, XmALIGNMENT_RIGHT, |
| |
1273 XmNcolumnSizePolicy, XmVARIABLE, |
| |
1274 NULL); |
| |
1275 |
| |
1276 FileListDetailAdjustColWidth(grid); |
| |
1277 } |
| |
1278 |
| |
1279 static void FileListDetailSelect(Widget fsb, Widget view, const char *item) { |
| |
1280 XnFileSelectionBox w = (XnFileSelectionBox)fsb; |
| |
1281 |
| |
1282 int numRows = 0; |
| |
1283 XtVaGetValues(w->fsb.grid, XmNrows, &numRows, NULL); |
| |
1284 |
| |
1285 XmLGridColumn col = XmLGridGetColumn(w->fsb.grid, XmCONTENT, 0); |
| |
1286 for(int i=0;i<numRows;i++) { |
| |
1287 XmLGridRow row = XmLGridGetRow(w->fsb.grid, XmCONTENT, i); |
| |
1288 FileElm *elm = NULL; |
| |
1289 XtVaGetValues(w->fsb.grid, XmNrowPtr, row, XmNcolumnPtr, col, XmNrowUserData, &elm, NULL); |
| |
1290 if(elm) { |
| |
1291 if(!strcmp(item, FileName(elm->path))) { |
| |
1292 XmLGridSelectRow(w->fsb.grid, i, False); |
| |
1293 XmLGridFocusAndShowRow(w->fsb.grid, i+1); |
| |
1294 break; |
| |
1295 } |
| |
1296 } |
| |
1297 } |
| |
1298 } |
| |
1299 |
| |
1300 static void FileListDetailCleanup(Widget fsb, Widget view, void *userData) { |
| |
1301 XnFileSelectionBox data = userData; |
| |
1302 // cleanup grid |
| |
1303 Cardinal rows = 0; |
| |
1304 XtVaGetValues(data->fsb.grid, XmNrows, &rows, NULL); |
| |
1305 XmLGridDeleteRows(data->fsb.grid, XmCONTENT, 0, rows); |
| |
1306 } |
| |
1307 |
| |
1308 static void FileListDetailDestroy(Widget fsb, Widget view, void *userData) { |
| |
1309 // unused |
| |
1310 } |
| |
1311 #endif |
| |
1312 |
| |
1313 static void create_folder(Widget w, XnFileSelectionBox data, XmSelectionBoxCallbackStruct *cbs) { |
| |
1314 char *fileName = NULL; |
| |
1315 XmStringGetLtoR(cbs->value, XmSTRING_DEFAULT_CHARSET, &fileName); |
| |
1316 |
| |
1317 char *newFolder = ConcatPath(data->fsb.currentPath ? data->fsb.currentPath : "", fileName); |
| |
1318 if(mkdir(newFolder, S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH)) { |
| |
1319 char errmsg[256]; |
| |
1320 snprintf(errmsg, 256, data->fsb.errorFolder, strerror(errno)); |
| |
1321 ErrDialog(data, data->fsb.errorTitle, errmsg); |
| |
1322 } else { |
| |
1323 char *p = strdup(data->fsb.currentPath); |
| |
1324 filedialog_update_dir(data, p); |
| |
1325 free(p); |
| |
1326 } |
| |
1327 free(newFolder); |
| |
1328 |
| |
1329 XtDestroyWidget(XtParent(w)); |
| |
1330 } |
| |
1331 |
| |
1332 static void new_folder_cancel(Widget w, XnFileSelectionBox data, XtPointer d) { |
| |
1333 XtDestroyWidget(XtParent(w)); |
| |
1334 } |
| |
1335 |
| |
1336 static void FSBNewFolder(Widget w, XnFileSelectionBox data, XtPointer u) |
| |
1337 { |
| |
1338 Arg args[16]; |
| |
1339 int n = 0; |
| |
1340 |
| |
1341 XtSetArg(args[n], XmNdialogTitle, data->fsb.labelNewFolder); n++; |
| |
1342 XtSetArg (args[n], XmNselectionLabelString, data->fsb.labelDirectoryName); n++; |
| |
1343 XtSetArg(args[n], XmNokLabelString, data->fsb.labelOk); n++; |
| |
1344 XtSetArg(args[n], XmNcancelLabelString, data->fsb.labelCancel); n++; |
| |
1345 Widget dialog = XmCreatePromptDialog (w, "NewFolderPrompt", args, n); |
| |
1346 |
| |
1347 Widget help = XmSelectionBoxGetChild(dialog, XmDIALOG_HELP_BUTTON); |
| |
1348 XtUnmanageChild(help); |
| |
1349 |
| |
1350 XtAddCallback(dialog, XmNokCallback, (XtCallbackProc)create_folder, data); |
| |
1351 XtAddCallback(dialog, XmNcancelCallback, (XtCallbackProc)new_folder_cancel, data); |
| |
1352 |
| |
1353 XtManageChild(dialog); |
| |
1354 |
| |
1355 } |
| |
1356 |
| |
1357 static void FSBHome(Widget w, XnFileSelectionBox data, XtPointer u) { |
| |
1358 const char *homePath = data->fsb.homePath ? data->fsb.homePath : GetHomeDir(); |
| |
1359 filedialog_update_dir(data, homePath); |
| |
1360 PathBarSetPath(data->fsb.pathBar, homePath); |
| |
1361 } |
| |
1362 |
| |
1363 |
| |
1364 /* |
| |
1365 * file_cmp_field |
| |
1366 * 0: compare path |
| |
1367 * 1: compare size |
| |
1368 * 2: compare mtime |
| |
1369 */ |
| |
1370 static int file_cmp_field = 0; |
| |
1371 |
| |
1372 /* |
| |
1373 * 1 or -1 |
| |
1374 */ |
| |
1375 static int file_cmp_order = 1; |
| |
1376 |
| |
1377 static int filecmp(const void *f1, const void *f2) |
| |
1378 { |
| |
1379 const FileElm *file1 = f1; |
| |
1380 const FileElm *file2 = f2; |
| |
1381 if(file1->isDirectory != file2->isDirectory) { |
| |
1382 return file1->isDirectory < file2->isDirectory; |
| |
1383 } |
| |
1384 |
| |
1385 int cmp_field = file_cmp_field; |
| |
1386 int cmp_order = file_cmp_order; |
| |
1387 if(file1->isDirectory) { |
| |
1388 cmp_field = 0; |
| |
1389 cmp_order = 1; |
| |
1390 } |
| |
1391 |
| |
1392 int ret = 0; |
| |
1393 switch(cmp_field) { |
| |
1394 case 0: { |
| |
1395 ret = strcmp(FileName(file1->path), FileName(file2->path)); |
| |
1396 break; |
| |
1397 } |
| |
1398 case 1: { |
| |
1399 if(file1->size < file2->size) { |
| |
1400 ret = -1; |
| |
1401 } else if(file1->size == file2->size) { |
| |
1402 ret = 0; |
| |
1403 } else { |
| |
1404 ret = 1; |
| |
1405 } |
| |
1406 break; |
| |
1407 } |
| |
1408 case 2: { |
| |
1409 if(file1->lastModified < file2->lastModified) { |
| |
1410 ret = -1; |
| |
1411 } else if(file1->lastModified == file2->lastModified) { |
| |
1412 ret = 0; |
| |
1413 } else { |
| |
1414 ret = 1; |
| |
1415 } |
| |
1416 break; |
| |
1417 } |
| |
1418 } |
| |
1419 |
| |
1420 return ret * cmp_order; |
| |
1421 } |
| |
1422 |
| |
1423 |
| |
1424 static void free_files(FileElm *ls, int count) |
| |
1425 { |
| |
1426 for(int i=0;i<count;i++) { |
| |
1427 if(ls[i].path) { |
| |
1428 free(ls[i].path); |
| |
1429 } |
| |
1430 } |
| |
1431 free(ls); |
| |
1432 } |
| |
1433 |
| |
1434 static void filedialog_cleanup_filedata(XnFileSelectionBox data) |
| |
1435 { |
| |
1436 free_files(data->fsb.dirs, data->fsb.dircount); |
| |
1437 free_files(data->fsb.files, data->fsb.filecount); |
| |
1438 data->fsb.dirs = NULL; |
| |
1439 data->fsb.files = NULL; |
| |
1440 data->fsb.dircount = 0; |
| |
1441 data->fsb.filecount = 0; |
| |
1442 data->fsb.maxnamelen = 0; |
| |
1443 } |
| |
1444 |
| |
1445 #define FILE_ARRAY_SIZE 1024 |
| |
1446 |
| |
1447 static void file_array_add(FileElm **files, int *alloc, int *count, FileElm elm) { |
| |
1448 int c = *count; |
| |
1449 int a = *alloc; |
| |
1450 if(c >= a) { |
| |
1451 a *= 2; |
| |
1452 FileElm *newarray = realloc(*files, sizeof(FileElm) * a); |
| |
1453 |
| |
1454 *files = newarray; |
| |
1455 *alloc = a; |
| |
1456 } |
| |
1457 |
| |
1458 (*files)[c] = elm; |
| |
1459 c++; |
| |
1460 *count = c; |
| |
1461 } |
| |
1462 |
| |
1463 static int filedialog_update_dir(XnFileSelectionBox data, const char *path) |
| |
1464 { |
| |
1465 DIR *dir = NULL; |
| |
1466 if(path) { |
| |
1467 // try to check first, if we can open the path |
| |
1468 dir = opendir(path); |
| |
1469 if(!dir) { |
| |
1470 char errmsg[256]; |
| |
1471 snprintf(errmsg, 256, data->fsb.errorOpenDir, strerror(errno)); |
| |
1472 |
| |
1473 ErrDialog(data, data->fsb.errorTitle, errmsg); |
| |
1474 return 1; |
| |
1475 } |
| |
1476 } |
| |
1477 |
| |
1478 FSBView view = data->fsb.view[data->fsb.selectedview]; |
| |
1479 view.cleanup((Widget)data, view.widget, view.userData); |
| |
1480 |
| |
1481 if(view.useDirList) { |
| |
1482 XmListDeleteAllItems(data->fsb.dirlist); |
| |
1483 } |
| |
1484 |
| |
1485 /* read dir and insert items */ |
| |
1486 if(path) { |
| |
1487 int dircount = 0; |
| |
1488 int filecount = 0; |
| |
1489 size_t maxNameLen = 0; |
| |
1490 |
| |
1491 FileElm *dirs = calloc(sizeof(FileElm), FILE_ARRAY_SIZE); |
| |
1492 FileElm *files = calloc(sizeof(FileElm), FILE_ARRAY_SIZE); |
| |
1493 int dirs_alloc = FILE_ARRAY_SIZE; |
| |
1494 int files_alloc = FILE_ARRAY_SIZE; |
| |
1495 |
| |
1496 filedialog_cleanup_filedata(data); |
| |
1497 |
| |
1498 /* dir reading complete - set the path textfield */ |
| |
1499 XmTextFieldSetString(data->fsb.path, (char*)path); |
| |
1500 char *oldPath = data->fsb.currentPath; |
| |
1501 data->fsb.currentPath = strdup(path); |
| |
1502 if(oldPath) { |
| |
1503 free(oldPath); |
| |
1504 } |
| |
1505 path = data->fsb.currentPath; |
| |
1506 |
| |
1507 struct dirent *ent; |
| |
1508 while((ent = readdir(dir)) != NULL) { |
| |
1509 if(!strcmp(ent->d_name, ".") || !strcmp(ent->d_name, "..")) { |
| |
1510 continue; |
| |
1511 } |
| |
1512 |
| |
1513 char *entpath = ConcatPath(path, ent->d_name); |
| |
1514 |
| |
1515 struct stat s; |
| |
1516 if(stat(entpath, &s)) { |
| |
1517 free(entpath); |
| |
1518 continue; |
| |
1519 } |
| |
1520 |
| |
1521 FileElm new_entry; |
| |
1522 new_entry.path = entpath; |
| |
1523 new_entry.isDirectory = S_ISDIR(s.st_mode); |
| |
1524 new_entry.size = (uint64_t)s.st_size; |
| |
1525 new_entry.lastModified = s.st_mtime; |
| |
1526 |
| |
1527 size_t nameLen = strlen(ent->d_name); |
| |
1528 if(nameLen > maxNameLen) { |
| |
1529 maxNameLen = nameLen; |
| |
1530 } |
| |
1531 |
| |
1532 if(new_entry.isDirectory) { |
| |
1533 file_array_add(&dirs, &dirs_alloc, &dircount, new_entry); |
| |
1534 } else { |
| |
1535 file_array_add(&files, &files_alloc, &filecount, new_entry); |
| |
1536 } |
| |
1537 } |
| |
1538 closedir(dir); |
| |
1539 |
| |
1540 data->fsb.dirs = dirs; |
| |
1541 data->fsb.files = files; |
| |
1542 data->fsb.dircount = dircount; |
| |
1543 data->fsb.filecount = filecount; |
| |
1544 data->fsb.maxnamelen = maxNameLen; |
| |
1545 |
| |
1546 // sort file arrays |
| |
1547 qsort(dirs, dircount, sizeof(FileElm), filecmp); |
| |
1548 qsort(files, filecount, sizeof(FileElm), filecmp); |
| |
1549 } |
| |
1550 |
| |
1551 Widget filterTF = XmDropDownGetText(data->fsb.filter); |
| |
1552 char *filter = XmTextFieldGetString(filterTF); |
| |
1553 char *filterStr = filter; |
| |
1554 if(!filter || strlen(filter) == 0) { |
| |
1555 filterStr = "*"; |
| |
1556 } |
| |
1557 |
| |
1558 if(view.useDirList) { |
| |
1559 FileListWidgetAdd(data, data->fsb.dirlist, data->fsb.showHidden, NULL, data->fsb.dirs, data->fsb.dircount); |
| |
1560 view.update( |
| |
1561 (Widget)data, |
| |
1562 view.widget, |
| |
1563 NULL, |
| |
1564 0, |
| |
1565 data->fsb.files, |
| |
1566 data->fsb.filecount, |
| |
1567 filterStr, |
| |
1568 data->fsb.maxnamelen, |
| |
1569 view.userData); |
| |
1570 } else { |
| |
1571 view.update( |
| |
1572 (Widget)data, |
| |
1573 view.widget, |
| |
1574 data->fsb.dirs, |
| |
1575 data->fsb.dircount, |
| |
1576 data->fsb.files, |
| |
1577 data->fsb.filecount, |
| |
1578 filterStr, |
| |
1579 data->fsb.maxnamelen, |
| |
1580 view.userData); |
| |
1581 } |
| |
1582 |
| |
1583 if(filter) { |
| |
1584 XtFree(filter); |
| |
1585 } |
| |
1586 |
| |
1587 return 0; |
| |
1588 } |
| |
1589 |
| |
1590 |
| |
1591 static void dirlist_activate(Widget w, XnFileSelectionBox data, XmListCallbackStruct *cb) |
| |
1592 { |
| |
1593 char *path = set_selected_path(data, cb->item); |
| |
1594 if(path) { |
| |
1595 if(!filedialog_update_dir(data, path)) { |
| |
1596 PathBarSetPath(data->fsb.pathBar, path); |
| |
1597 data->fsb.selIsDir = TRUE; |
| |
1598 } |
| |
1599 } |
| |
1600 } |
| |
1601 |
| |
1602 static void dirlist_select(Widget w, XnFileSelectionBox data, XmListCallbackStruct *cb) |
| |
1603 { |
| |
1604 char *path = set_selected_path(data, cb->item); |
| |
1605 if(path) { |
| |
1606 data->fsb.selIsDir = TRUE; |
| |
1607 } |
| |
1608 } |
| |
1609 |
| |
1610 static void filedialog_enable_detailview(Widget w, XnFileSelectionBox data, XmToggleButtonCallbackStruct *tb) { |
| |
1611 SelectView(data, tb->set); // 0: list, 1: detail |
| |
1612 } |
| |
1613 |
| |
1614 |
| |
1615 static void filedialog_setshowhidden( |
| |
1616 Widget w, |
| |
1617 XnFileSelectionBox data, |
| |
1618 XmToggleButtonCallbackStruct *tb) |
| |
1619 { |
| |
1620 data->fsb.showHidden = tb->set; |
| |
1621 filedialog_update_dir(data, NULL); |
| |
1622 } |
| |
1623 |
| |
1624 static void filedialog_filter(Widget w, XnFileSelectionBox data, XtPointer c) |
| |
1625 { |
| |
1626 filedialog_update_dir(data, NULL); |
| |
1627 } |
| |
1628 |
| |
1629 static void filedialog_update_filter(Widget w, XnFileSelectionBox data, XtPointer c) |
| |
1630 { |
| |
1631 filedialog_update_dir(data, NULL); |
| |
1632 |
| |
1633 } |
| |
1634 |
| |
1635 static void filedialog_goup(Widget w, XnFileSelectionBox data, XtPointer d) |
| |
1636 { |
| |
1637 char *newPath = ParentPath(data->fsb.currentPath); |
| |
1638 filedialog_update_dir(data, newPath); |
| |
1639 PathBarSetPath(data->fsb.pathBar, newPath); |
| |
1640 free(newPath); |
| |
1641 } |
| |
1642 |
| |
1643 static void filedialog_ok(Widget w, XnFileSelectionBox data, XtPointer d) |
| |
1644 { |
| |
1645 if(data->fsb.type == FILEDIALOG_SAVE) { |
| |
1646 char *newName = XmTextFieldGetString(data->fsb.name); |
| |
1647 if(newName) { |
| |
1648 if(strchr(newName, '/')) { |
| |
1649 ErrDialog(data, data->fsb.errorTitle, data->fsb.errorIllegalChar); |
| |
1650 XtFree(newName); |
| |
1651 return; |
| |
1652 } |
| |
1653 |
| |
1654 if(strlen(newName) > 0) { |
| |
1655 char *selPath = ConcatPath(data->fsb.currentPath, newName); |
| |
1656 if(data->fsb.selectedPath) free(data->fsb.selectedPath); |
| |
1657 data->fsb.selectedPath = selPath; |
| |
1658 } |
| |
1659 XtFree(newName); |
| |
1660 |
| |
1661 data->fsb.selIsDir = False; |
| |
1662 } |
| |
1663 } |
| |
1664 |
| |
1665 if(data->fsb.selectedPath) { |
| |
1666 if(!data->fsb.selIsDir) { |
| |
1667 data->fsb.status = FILEDIALOG_OK; |
| |
1668 data->fsb.end = True; |
| |
1669 FileSelectionCallback(data, data->fsb.okCallback, XmCR_OK, data->fsb.selectedPath); |
| |
1670 } |
| |
1671 } |
| |
1672 } |
| |
1673 |
| |
1674 static void filedialog_cancel(Widget w, XnFileSelectionBox data, XtPointer d) |
| |
1675 { |
| |
1676 data->fsb.end = 1; |
| |
1677 data->fsb.status = FILEDIALOG_CANCEL; |
| |
1678 FileSelectionCallback(data, data->fsb.cancelCallback, XmCR_CANCEL, data->fsb.currentPath); |
| |
1679 } |
| |
1680 |
| |
1681 static void filedialog_help(Widget w, XnFileSelectionBox data, XtPointer d) |
| |
1682 { |
| |
1683 FileSelectionCallback(data, data->manager.help_callback, XmCR_HELP, data->fsb.currentPath); |
| |
1684 } |
| |
1685 |
| |
1686 static void FileSelectionCallback(XnFileSelectionBox fsb, XtCallbackList cb, int reason, const char *value) { |
| |
1687 XmFileSelectionBoxCallbackStruct cbs; |
| |
1688 memset(&cbs, 0, sizeof(XmFileSelectionBoxCallbackStruct)); |
| |
1689 |
| |
1690 char *dir = fsb->fsb.currentPath; |
| |
1691 size_t dirlen = dir ? strlen(dir) : 0; |
| |
1692 if(dir && dirlen > 0) { |
| |
1693 char *dir2 = NULL; |
| |
1694 if(dir[dirlen-1] != '/') { |
| |
1695 // add a trailing / to the dir string |
| |
1696 dir2 = malloc(dirlen+2); |
| |
1697 memcpy(dir2, dir, dirlen); |
| |
1698 dir2[dirlen] = '/'; |
| |
1699 dir2[dirlen+1] = '\0'; |
| |
1700 dirlen++; |
| |
1701 dir = dir2; |
| |
1702 } |
| |
1703 cbs.dir = XmStringCreateLocalized(dir); |
| |
1704 cbs.dir_length = dirlen; |
| |
1705 if(dir2) { |
| |
1706 free(dir2); |
| |
1707 } |
| |
1708 } else { |
| |
1709 cbs.dir = XmStringCreateLocalized(""); |
| |
1710 cbs.dir_length = 0; |
| |
1711 } |
| |
1712 cbs.reason = reason; |
| |
1713 |
| |
1714 cbs.value = XmStringCreateLocalized((char*)value); |
| |
1715 cbs.length = strlen(value); |
| |
1716 |
| |
1717 XtCallCallbackList((Widget)fsb, cb, (XtPointer)&cbs); |
| |
1718 |
| |
1719 XmStringFree(cbs.dir); |
| |
1720 XmStringFree(cbs.value); |
| |
1721 } |
| |
1722 |
| |
1723 static void CreateUI(XnFileSelectionBox w) { |
| |
1724 Arg args[32]; |
| |
1725 int n = 0; |
| |
1726 XmString str; |
| |
1727 |
| |
1728 int widget_spacing = w->fsb.widgetSpacing; |
| |
1729 int window_spacing = w->fsb.windowSpacing; |
| |
1730 |
| |
1731 Widget form = (Widget)w; |
| |
1732 int type = w->fsb.type; |
| |
1733 |
| |
1734 XtVaSetValues((Widget)w, XmNautoUnmanage, False, NULL); |
| |
1735 |
| |
1736 /* upper part of the gui */ |
| |
1737 |
| |
1738 n = 0; |
| |
1739 XtSetArg(args[n], XmNlabelString, w->fsb.labelDirUp); n++; |
| |
1740 XtSetArg(args[n], XmNtopAttachment, XmATTACH_FORM); n++; |
| |
1741 XtSetArg(args[n], XmNtopOffset, window_spacing); n++; |
| |
1742 XtSetArg(args[n], XmNleftAttachment, XmATTACH_FORM); n++; |
| |
1743 XtSetArg(args[n], XmNleftOffset, window_spacing); n++; |
| |
1744 XtSetArg(args[n], XmNresizable, True); n++; |
| |
1745 XtSetArg(args[n], XmNarrowDirection, XmARROW_UP); n++; |
| |
1746 w->fsb.dirUp = XmCreatePushButton(form, "DirUp", args, n); |
| |
1747 XtManageChild(w->fsb.dirUp); |
| |
1748 XtAddCallback(w->fsb.dirUp, XmNactivateCallback, |
| |
1749 (XtCallbackProc)filedialog_goup, w); |
| |
1750 |
| |
1751 // View Option Menu |
| |
1752 n = 0; |
| |
1753 XtSetArg(args[n], XmNtopAttachment, XmATTACH_FORM); n++; |
| |
1754 XtSetArg(args[n], XmNtopOffset, window_spacing); n++; |
| |
1755 XtSetArg(args[n], XmNrightAttachment, XmATTACH_FORM); n++; |
| |
1756 XtSetArg(args[n], XmNrightOffset, window_spacing); n++; |
| |
1757 XtSetArg(args[n], XmNshadowThickness, 0); n++; |
| |
1758 Widget viewframe = XmCreateForm(form, "vframe", args, n); |
| |
1759 XtManageChild(viewframe); |
| |
1760 |
| |
1761 w->fsb.viewMenu = XmCreatePulldownMenu(viewframe, "menu", NULL, 0); |
| |
1762 |
| |
1763 Widget view; |
| |
1764 if(w->fsb.showViewMenu) { |
| |
1765 n = 0; |
| |
1766 XtSetArg(args[n], XmNsubMenuId, w->fsb.viewMenu); n++; |
| |
1767 XtSetArg(args[n], XmNrightAttachment, XmATTACH_FORM); n++; |
| |
1768 XtSetArg(args[n], XmNmarginHeight, 0); n++; |
| |
1769 XtSetArg(args[n], XmNmarginWidth, 0); n++; |
| |
1770 view = XmCreateOptionMenu(viewframe, "option_menu", args, n); |
| |
1771 XtManageChild(view); |
| |
1772 w->fsb.viewOption = view; |
| |
1773 w->fsb.detailToggleButton = NULL; |
| |
1774 } else { |
| |
1775 n = 0; |
| |
1776 str = XmStringCreateLocalized(w->fsb.labelDetailView); |
| |
1777 XtSetArg(args[n], XmNlabelString, str); n++; |
| |
1778 XtSetArg(args[n], XmNfillOnSelect, True); n++; |
| |
1779 XtSetArg(args[n], XmNindicatorOn, False); n++; |
| |
1780 XtSetArg(args[n], XmNrightAttachment, XmATTACH_FORM); n++; |
| |
1781 XtSetArg(args[n], XmNbottomAttachment, XmATTACH_FORM); n++; |
| |
1782 XtSetArg(args[n], XmNtopAttachment, XmATTACH_FORM); n++; |
| |
1783 if(w->fsb.selectedview == 1) { |
| |
1784 XtSetArg(args[n], XmNset, 1); n++; |
| |
1785 } |
| |
1786 w->fsb.detailToggleButton = XmCreateToggleButton(viewframe, "ToggleDetailView", args, n); |
| |
1787 XtManageChild(w->fsb.detailToggleButton); |
| |
1788 view = w->fsb.detailToggleButton; |
| |
1789 XmStringFree(str); |
| |
1790 |
| |
1791 XtAddCallback( |
| |
1792 w->fsb.detailToggleButton, |
| |
1793 XmNvalueChangedCallback, |
| |
1794 (XtCallbackProc)filedialog_enable_detailview, |
| |
1795 w); |
| |
1796 |
| |
1797 w->fsb.viewOption = NULL; |
| |
1798 } |
| |
1799 |
| |
1800 n = 0; |
| |
1801 XtSetArg(args[n], XmNrightAttachment, XmATTACH_WIDGET); n++; |
| |
1802 XtSetArg(args[n], XmNbottomAttachment, XmATTACH_FORM); n++; |
| |
1803 XtSetArg(args[n], XmNtopAttachment, XmATTACH_FORM); n++; |
| |
1804 XtSetArg(args[n], XmNrightWidget, view); n++; |
| |
1805 XtSetArg(args[n], XmNmarginHeight, 0); n++; |
| |
1806 XtSetArg(args[n], XmNorientation, XmHORIZONTAL); n++; |
| |
1807 XtSetArg(args[n], XmNlabelString, w->fsb.labelNewFolder); n++; |
| |
1808 w->fsb.newFolder = XmCreatePushButton(viewframe, "NewFolder", args, n); |
| |
1809 XtManageChild(w->fsb.newFolder); |
| |
1810 XtAddCallback( |
| |
1811 w->fsb.newFolder, |
| |
1812 XmNactivateCallback, |
| |
1813 (XtCallbackProc)FSBNewFolder, |
| |
1814 w); |
| |
1815 |
| |
1816 |
| |
1817 n = 0; |
| |
1818 XtSetArg(args[n], XmNlabelString, w->fsb.labelHome); n++; |
| |
1819 XtSetArg(args[n], XmNleftAttachment, XmATTACH_FORM); n++; |
| |
1820 XtSetArg(args[n], XmNrightAttachment, XmATTACH_WIDGET); n++; |
| |
1821 XtSetArg(args[n], XmNrightWidget, w->fsb.newFolder); n++; |
| |
1822 XtSetArg(args[n], XmNbottomAttachment, XmATTACH_FORM); n++; |
| |
1823 XtSetArg(args[n], XmNtopAttachment, XmATTACH_FORM); n++; |
| |
1824 w->fsb.home = XmCreatePushButton(viewframe, "Home", args, n); |
| |
1825 XtManageChild(w->fsb.home); |
| |
1826 XtAddCallback( |
| |
1827 w->fsb.home, |
| |
1828 XmNactivateCallback, |
| |
1829 (XtCallbackProc)FSBHome, |
| |
1830 w); |
| |
1831 |
| |
1832 // match visual appearance of detailToggleButton with the other buttons |
| |
1833 if(w->fsb.detailToggleButton) { |
| |
1834 Dimension highlight, shadow; |
| |
1835 XtVaGetValues(w->fsb.newFolder, XmNshadowThickness, &shadow, XmNhighlightThickness, &highlight, NULL); |
| |
1836 XtVaSetValues(w->fsb.detailToggleButton, XmNshadowThickness, shadow, XmNhighlightThickness, highlight, NULL); |
| |
1837 } |
| |
1838 |
| |
1839 // pathbar |
| |
1840 n = 0; |
| |
1841 XtSetArg(args[n], XmNtopAttachment, XmATTACH_FORM); n++; |
| |
1842 XtSetArg(args[n], XmNtopOffset, window_spacing); n++; |
| |
1843 XtSetArg(args[n], XmNleftAttachment, XmATTACH_WIDGET); n++; |
| |
1844 XtSetArg(args[n], XmNleftWidget, w->fsb.dirUp); n++; |
| |
1845 XtSetArg(args[n], XmNleftOffset, widget_spacing); n++; |
| |
1846 XtSetArg(args[n], XmNrightAttachment, XmATTACH_WIDGET); n++; |
| |
1847 XtSetArg(args[n], XmNrightWidget, viewframe); n++; |
| |
1848 XtSetArg(args[n], XmNrightOffset, widget_spacing); n++; |
| |
1849 XtSetArg(args[n], XmNshadowType, XmSHADOW_IN); n++; |
| |
1850 Widget pathBarFrame = XmCreateFrame(form, "pathbar_frame", args, n); |
| |
1851 XtManageChild(pathBarFrame); |
| |
1852 w->fsb.pathBar = CreatePathBar(pathBarFrame, args, 0); |
| |
1853 w->fsb.pathBar->getpathelm = ui_default_pathelm_func; |
| |
1854 w->fsb.pathBar->updateDir = (updatedir_callback)filedialog_update_dir; |
| |
1855 w->fsb.pathBar->updateDirData = w; |
| |
1856 XtManageChild(w->fsb.pathBar->widget); |
| |
1857 w->fsb.path = XmCreateTextField(form, "textfield", args, 0); |
| |
1858 |
| |
1859 XtVaSetValues(w->fsb.dirUp, XmNbottomAttachment, XmATTACH_OPPOSITE_WIDGET, XmNbottomWidget, pathBarFrame, NULL); |
| |
1860 if(!w->fsb.showViewMenu) { |
| |
1861 XtVaSetValues(viewframe, XmNbottomAttachment, XmATTACH_OPPOSITE_WIDGET, XmNbottomWidget, pathBarFrame, NULL); |
| |
1862 } |
| |
1863 |
| |
1864 n = 0; |
| |
1865 XtSetArg(args[n], XmNleftAttachment, XmATTACH_FORM); n++; |
| |
1866 XtSetArg(args[n], XmNleftOffset, window_spacing); n++; |
| |
1867 XtSetArg(args[n], XmNtopAttachment, XmATTACH_WIDGET); n++; |
| |
1868 XtSetArg(args[n], XmNtopWidget, pathBarFrame); n++; |
| |
1869 XtSetArg(args[n], XmNtopOffset, 2*widget_spacing); n++; |
| |
1870 XtSetArg(args[n], XmNrightAttachment, XmATTACH_FORM); n++; |
| |
1871 XtSetArg(args[n], XmNrightOffset, window_spacing); n++; |
| |
1872 w->fsb.filterForm = XmCreateForm(form, "filterform", args, n); |
| |
1873 XtManageChild(w->fsb.filterForm); |
| |
1874 |
| |
1875 n = 0; |
| |
1876 XtSetArg(args[n], XmNbottomAttachment, XmATTACH_FORM); n++; |
| |
1877 XtSetArg(args[n], XmNleftAttachment, XmATTACH_FORM); n++; |
| |
1878 XtSetArg(args[n], XmNlabelString, w->fsb.labelDirectories); n++; |
| |
1879 w->fsb.lsDirLabel = XmCreateLabel(w->fsb.filterForm, "labelDirs", args, n); |
| |
1880 XtManageChild(w->fsb.lsDirLabel); |
| |
1881 |
| |
1882 n = 0; |
| |
1883 XtSetArg(args[n], XmNbottomAttachment, XmATTACH_FORM); n++; |
| |
1884 XtSetArg(args[n], XmNleftAttachment, XmATTACH_POSITION); n++; |
| |
1885 XtSetArg(args[n], XmNleftPosition, 35); n++; |
| |
1886 XtSetArg(args[n], XmNleftOffset, widget_spacing); n++; |
| |
1887 XtSetArg(args[n], XmNlabelString, w->fsb.labelFiles); n++; |
| |
1888 w->fsb.lsFileLabel = XmCreateLabel(w->fsb.filterForm, "labelFiles", args, n); |
| |
1889 XtManageChild(w->fsb.lsFileLabel); |
| |
1890 |
| |
1891 if(w->fsb.showHiddenButton) { |
| |
1892 n = 0; |
| |
1893 XtSetArg(args[n], XmNtopAttachment, XmATTACH_FORM); n++; |
| |
1894 XtSetArg(args[n], XmNrightAttachment, XmATTACH_FORM); n++; |
| |
1895 XtSetArg(args[n], XmNbottomAttachment, XmATTACH_FORM); n++; |
| |
1896 XtSetArg(args[n], XmNlabelString, w->fsb.labelShowHiddenFiles); n++; |
| |
1897 XtSetArg(args[n], XmNset, w->fsb.showHidden); n++; |
| |
1898 w->fsb.showHiddenButtonW = XmCreateToggleButton(w->fsb.filterForm, "showHidden", args, n); |
| |
1899 XtManageChild(w->fsb.showHiddenButtonW); |
| |
1900 XtAddCallback(w->fsb.showHiddenButtonW, XmNvalueChangedCallback, |
| |
1901 (XtCallbackProc)filedialog_setshowhidden, w); |
| |
1902 } |
| |
1903 |
| |
1904 n = 0; |
| |
1905 XtSetArg(args[n], XmNtopAttachment, XmATTACH_FORM); n++; |
| |
1906 XtSetArg(args[n], XmNbottomAttachment, XmATTACH_FORM); n++; |
| |
1907 XtSetArg(args[n], XmNlabelString, w->fsb.labelFilterButton); n++; |
| |
1908 if(w->fsb.showHiddenButton) { |
| |
1909 XtSetArg(args[n], XmNrightAttachment, XmATTACH_WIDGET); n++; |
| |
1910 XtSetArg(args[n], XmNrightWidget, w->fsb.showHiddenButtonW); n++; |
| |
1911 } else { |
| |
1912 XtSetArg(args[n], XmNrightAttachment, XmATTACH_FORM); n++; |
| |
1913 } |
| |
1914 w->fsb.filterButton = XmCreatePushButton(w->fsb.filterForm, "filedialog_filter", args, n); |
| |
1915 XtManageChild(w->fsb.filterButton); |
| |
1916 XtAddCallback(w->fsb.filterButton, XmNactivateCallback, |
| |
1917 (XtCallbackProc)filedialog_filter, w); |
| |
1918 |
| |
1919 n = 0; |
| |
1920 XtSetArg(args[n], XmNtopAttachment, XmATTACH_FORM); n++; |
| |
1921 XtSetArg(args[n], XmNbottomAttachment, XmATTACH_FORM); n++; |
| |
1922 XtSetArg(args[n], XmNleftAttachment, XmATTACH_WIDGET); n++; |
| |
1923 XtSetArg(args[n], XmNleftWidget, w->fsb.lsFileLabel); n++; |
| |
1924 XtSetArg(args[n], XmNleftOffset, widget_spacing); n++; |
| |
1925 XtSetArg(args[n], XmNrightAttachment, XmATTACH_WIDGET); n++; |
| |
1926 XtSetArg(args[n], XmNrightWidget, w->fsb.filterButton); n++; |
| |
1927 XtSetArg(args[n], XmNrightOffset, widget_spacing); n++; |
| |
1928 XtSetArg(args[n], XmNshowLabel, False); n++; |
| |
1929 XtSetArg(args[n], XmNuseTextField, True); n++; |
| |
1930 XtSetArg(args[n], XmNverify, False); n++; |
| |
1931 w->fsb.filter = XmCreateDropDown(w->fsb.filterForm, "filedialog_filter_textfield", args, n); |
| |
1932 XtManageChild(w->fsb.filter); |
| |
1933 XmTextFieldSetString(XmDropDownGetText(w->fsb.filter), w->fsb.filterStr); |
| |
1934 XtAddCallback(XmDropDownGetText(w->fsb.filter), XmNactivateCallback, |
| |
1935 (XtCallbackProc)filedialog_filter, w); |
| |
1936 XtAddCallback(w->fsb.filter, XmNupdateTextCallback, |
| |
1937 (XtCallbackProc)filedialog_update_filter, w); |
| |
1938 Widget filterList = XmDropDownGetList(w->fsb.filter); |
| |
1939 str = XmStringCreateSimple("*"); |
| |
1940 XmListAddItem(filterList, str, 0); |
| |
1941 XmStringFree(str); |
| |
1942 |
| |
1943 /* lower part */ |
| |
1944 n = 0; |
| |
1945 XtSetArg(args[n], XmNbottomAttachment, XmATTACH_FORM); n++; |
| |
1946 XtSetArg(args[n], XmNbottomOffset, window_spacing); n++; |
| |
1947 XtSetArg(args[n], XmNleftAttachment, XmATTACH_FORM); n++; |
| |
1948 XtSetArg(args[n], XmNleftOffset, window_spacing); n++; |
| |
1949 XtSetArg(args[n], XmNrightAttachment, XmATTACH_FORM); n++; |
| |
1950 XtSetArg(args[n], XmNrightOffset, window_spacing); n++; |
| |
1951 XtSetArg(args[n], XmNtopOffset, widget_spacing * 2); n++; |
| |
1952 Widget buttons = XmCreateForm(form, "buttons", args, n); |
| |
1953 XtManageChild(buttons); |
| |
1954 |
| |
1955 n = 0; |
| |
1956 str = type == FILEDIALOG_OPEN ? w->fsb.labelOpen : w->fsb.labelSave; |
| |
1957 XtSetArg(args[n], XmNtopAttachment, XmATTACH_FORM); n++; |
| |
1958 XtSetArg(args[n], XmNbottomAttachment, XmATTACH_FORM); n++; |
| |
1959 XtSetArg(args[n], XmNlabelString, str); n++; |
| |
1960 XtSetArg(args[n], XmNleftAttachment, XmATTACH_FORM); n++; |
| |
1961 XtSetArg(args[n], XmNrightAttachment, XmATTACH_POSITION); n++; |
| |
1962 XtSetArg(args[n], XmNrightPosition, 14); n++; |
| |
1963 w->fsb.okBtn = XmCreatePushButton(buttons, "filedialog_open", args, n); |
| |
1964 XtManageChild(w->fsb.okBtn); |
| |
1965 XmStringFree(str); |
| |
1966 XtAddCallback(w->fsb.okBtn, XmNactivateCallback, |
| |
1967 (XtCallbackProc)filedialog_ok, w); |
| |
1968 |
| |
1969 n = 0; |
| |
1970 XtSetArg(args[n], XmNtopAttachment, XmATTACH_FORM); n++; |
| |
1971 XtSetArg(args[n], XmNbottomAttachment, XmATTACH_FORM); n++; |
| |
1972 XtSetArg(args[n], XmNlabelString, w->fsb.labelHelp); n++; |
| |
1973 XtSetArg(args[n], XmNrightAttachment, XmATTACH_FORM); n++; |
| |
1974 XtSetArg(args[n], XmNleftAttachment, XmATTACH_POSITION); n++; |
| |
1975 XtSetArg(args[n], XmNleftPosition, 86); n++; |
| |
1976 w->fsb.helpBtn = XmCreatePushButton(buttons, "filedialog_help", args, n); |
| |
1977 XtManageChild(w->fsb.helpBtn); |
| |
1978 XtAddCallback(w->fsb.helpBtn, XmNactivateCallback, |
| |
1979 (XtCallbackProc)filedialog_help, w); |
| |
1980 |
| |
1981 n = 0; |
| |
1982 XtSetArg(args[n], XmNtopAttachment, XmATTACH_FORM); n++; |
| |
1983 XtSetArg(args[n], XmNbottomAttachment, XmATTACH_FORM); n++; |
| |
1984 XtSetArg(args[n], XmNleftAttachment, XmATTACH_POSITION); n++; |
| |
1985 XtSetArg(args[n], XmNleftPosition, 43); n++; |
| |
1986 XtSetArg(args[n], XmNrightAttachment, XmATTACH_POSITION); n++; |
| |
1987 XtSetArg(args[n], XmNrightPosition, 57); n++; |
| |
1988 XtSetArg(args[n], XmNlabelString, w->fsb.labelCancel); n++; |
| |
1989 w->fsb.cancelBtn = XmCreatePushButton(buttons, "filedialog_cancel", args, n); |
| |
1990 XtManageChild(w->fsb.cancelBtn); |
| |
1991 XtAddCallback(w->fsb.cancelBtn, XmNactivateCallback, |
| |
1992 (XtCallbackProc)filedialog_cancel, w); |
| |
1993 |
| |
1994 n = 0; |
| |
1995 XtSetArg(args[n], XmNbottomAttachment, XmATTACH_WIDGET); n++; |
| |
1996 XtSetArg(args[n], XmNbottomWidget, buttons); n++; |
| |
1997 XtSetArg(args[n], XmNbottomOffset, widget_spacing); n++; |
| |
1998 XtSetArg(args[n], XmNleftAttachment, XmATTACH_FORM); n++; |
| |
1999 XtSetArg(args[n], XmNleftOffset, 1); n++; |
| |
2000 XtSetArg(args[n], XmNrightAttachment, XmATTACH_FORM); n++; |
| |
2001 XtSetArg(args[n], XmNrightOffset, 1); n++; |
| |
2002 w->fsb.separator = XmCreateSeparator(form, "ofd_separator", args, n); |
| |
2003 XtManageChild(w->fsb.separator); |
| |
2004 |
| |
2005 Widget bottomWidget = w->fsb.separator; |
| |
2006 |
| |
2007 n = 0; |
| |
2008 XtSetArg(args[n], XmNbottomAttachment, XmATTACH_WIDGET); n++; |
| |
2009 XtSetArg(args[n], XmNbottomWidget, w->fsb.separator); n++; |
| |
2010 XtSetArg(args[n], XmNbottomOffset, widget_spacing); n++; |
| |
2011 XtSetArg(args[n], XmNleftAttachment, XmATTACH_FORM); n++; |
| |
2012 XtSetArg(args[n], XmNleftOffset, window_spacing); n++; |
| |
2013 XtSetArg(args[n], XmNrightAttachment, XmATTACH_FORM); n++; |
| |
2014 XtSetArg(args[n], XmNrightOffset, window_spacing); n++; |
| |
2015 w->fsb.name = XmCreateTextField(form, "textfield", args, n); |
| |
2016 XtAddCallback(w->fsb.name, XmNactivateCallback, |
| |
2017 (XtCallbackProc)filedialog_ok, w); |
| |
2018 |
| |
2019 n = 0; |
| |
2020 XtSetArg(args[n], XmNbottomAttachment, XmATTACH_WIDGET); n++; |
| |
2021 XtSetArg(args[n], XmNbottomWidget, w->fsb.name); n++; |
| |
2022 XtSetArg(args[n], XmNbottomOffset, widget_spacing); n++; |
| |
2023 XtSetArg(args[n], XmNleftAttachment, XmATTACH_FORM); n++; |
| |
2024 XtSetArg(args[n], XmNleftOffset, window_spacing); n++; |
| |
2025 XtSetArg(args[n], XmNlabelString, w->fsb.labelFileName); n++; |
| |
2026 w->fsb.nameLabel = XmCreateLabel(form, "label", args, n); |
| |
2027 |
| |
2028 if(type == FILEDIALOG_SAVE) { |
| |
2029 bottomWidget = w->fsb.nameLabel; |
| |
2030 XtManageChild(w->fsb.name); |
| |
2031 XtManageChild(w->fsb.nameLabel); |
| |
2032 } |
| |
2033 w->fsb.bottom_widget = bottomWidget; |
| |
2034 |
| |
2035 |
| |
2036 // middle |
| |
2037 // form for dir/file lists |
| |
2038 n = 0; |
| |
2039 XtSetArg(args[n], XmNleftAttachment, XmATTACH_FORM); n++; |
| |
2040 XtSetArg(args[n], XmNtopAttachment, XmATTACH_WIDGET); n++; |
| |
2041 XtSetArg(args[n], XmNtopWidget, w->fsb.filterForm); n++; |
| |
2042 XtSetArg(args[n], XmNtopOffset, widget_spacing); n++; |
| |
2043 XtSetArg(args[n], XmNrightAttachment, XmATTACH_FORM); n++; |
| |
2044 XtSetArg(args[n], XmNbottomAttachment, XmATTACH_WIDGET); n++; |
| |
2045 XtSetArg(args[n], XmNbottomWidget, bottomWidget); n++; |
| |
2046 XtSetArg(args[n], XmNleftOffset, window_spacing); n++; |
| |
2047 XtSetArg(args[n], XmNrightOffset, window_spacing); n++; |
| |
2048 XtSetArg(args[n], XmNbottomOffset, widget_spacing); n++; |
| |
2049 XtSetArg(args[n], XmNwidth, 580); n++; |
| |
2050 XtSetArg(args[n], XmNheight, 400); n++; |
| |
2051 w->fsb.listform = XmCreateForm(form, "fds_listform", args, n); |
| |
2052 |
| |
2053 // dir/file lists |
| |
2054 |
| |
2055 n = 0; |
| |
2056 XtSetArg(args[n], XmNleftAttachment, XmATTACH_FORM); n++; |
| |
2057 XtSetArg(args[n], XmNtopAttachment, XmATTACH_FORM); n++; |
| |
2058 XtSetArg(args[n], XmNtopWidget, w->fsb.lsDirLabel); n++; |
| |
2059 XtSetArg(args[n], XmNbottomAttachment, XmATTACH_FORM); n++; |
| |
2060 XtSetArg(args[n], XmNrightAttachment, XmATTACH_POSITION); n++; |
| |
2061 XtSetArg(args[n], XmNrightPosition, 35); n++; |
| |
2062 w->fsb.dirlist = XmCreateScrolledList(w->fsb.listform, "dirlist", args, n); |
| |
2063 Dimension width, height; |
| |
2064 XtMakeResizeRequest(w->fsb.dirlist, 150, 200, &width, &height); |
| |
2065 XtManageChild(w->fsb.dirlist); |
| |
2066 |
| |
2067 XtAddCallback( |
| |
2068 w->fsb.dirlist, |
| |
2069 XmNdefaultActionCallback, |
| |
2070 (XtCallbackProc)dirlist_activate, |
| |
2071 w); |
| |
2072 XtAddCallback( |
| |
2073 w->fsb.dirlist, |
| |
2074 XmNbrowseSelectionCallback, |
| |
2075 (XtCallbackProc)dirlist_select, |
| |
2076 w); |
| |
2077 |
| |
2078 // FileList |
| |
2079 XnFileSelectionBoxAddView( |
| |
2080 (Widget)w, |
| |
2081 w->fsb.labelListView, |
| |
2082 CreateListView, |
| |
2083 FileListUpdate, |
| |
2084 FileListSelect, |
| |
2085 FileListCleanup, |
| |
2086 FileListDestroy, |
| |
2087 True, |
| |
2088 w); |
| |
2089 |
| |
2090 // Detail FileList |
| |
2091 #ifdef FSB_ENABLE_DETAIL |
| |
2092 XnFileSelectionBoxAddView( |
| |
2093 (Widget)w, |
| |
2094 w->fsb.labelDetailView, |
| |
2095 CreateDetailView, |
| |
2096 FileListDetailUpdate, |
| |
2097 FileListDetailSelect, |
| |
2098 FileListDetailCleanup, |
| |
2099 FileListDetailDestroy, |
| |
2100 True, |
| |
2101 w); |
| |
2102 #endif |
| |
2103 |
| |
2104 /* |
| |
2105 n = 0; |
| |
2106 XtSetArg(args[n], XmNleftAttachment, XmATTACH_WIDGET); n++; |
| |
2107 XtSetArg(args[n], XmNleftWidget, w->fsb.dirlist); n++; |
| |
2108 XtSetArg(args[n], XmNleftOffset, widget_spacing); n++; |
| |
2109 //XtSetArg(args[n], XmNbottomAttachment, XmATTACH_WIDGET); n++; |
| |
2110 //XtSetArg(args[n], XmNbottomWidget, w->fsb.filelist); n++; |
| |
2111 XtSetArg(args[n], XmNbottomOffset, widget_spacing); n++; |
| |
2112 XtSetArg(args[n], XmNtopAttachment, XmATTACH_FORM); n++; |
| |
2113 XtSetArg(args[n], XmNlabelString, w->fsb.labelFiles); n++; |
| |
2114 w->fsb.lsFileLabel = XmCreateLabel(w->fsb.listform, "label", args, n); |
| |
2115 XtManageChild(w->fsb.lsFileLabel); |
| |
2116 */ |
| |
2117 |
| |
2118 XtManageChild(w->fsb.listform); |
| |
2119 |
| |
2120 int selview = w->fsb.selectedview; |
| |
2121 if(selview < 2) { |
| |
2122 XtManageChild(w->fsb.view[selview].widget); |
| |
2123 } else { |
| |
2124 w->fsb.selectedview = 0; |
| |
2125 } |
| |
2126 |
| |
2127 |
| |
2128 if(w->fsb.selectedPath) { |
| |
2129 char *parentPath = ParentPath(w->fsb.selectedPath); |
| |
2130 filedialog_update_dir(w, parentPath); |
| |
2131 PathBarSetPath(w->fsb.pathBar, parentPath); |
| |
2132 free(parentPath); |
| |
2133 |
| |
2134 if(w->fsb.type == FILEDIALOG_SAVE) { |
| |
2135 XmTextFieldSetString(w->fsb.name, FileName(w->fsb.selectedPath)); |
| |
2136 } |
| |
2137 } else { |
| |
2138 char cwd[PATH_MAX]; |
| |
2139 const char *currentPath = w->fsb.currentPath; |
| |
2140 if(!currentPath) { |
| |
2141 if(getcwd(cwd, PATH_MAX)) { |
| |
2142 currentPath = cwd; |
| |
2143 } else { |
| |
2144 currentPath = GetHomeDir(); |
| |
2145 } |
| |
2146 } |
| |
2147 |
| |
2148 filedialog_update_dir(w, currentPath); |
| |
2149 PathBarSetPath(w->fsb.pathBar, w->fsb.currentPath); |
| |
2150 } |
| |
2151 |
| |
2152 |
| |
2153 w->fsb.selectedview = selview; |
| |
2154 |
| |
2155 XtVaSetValues((Widget)w, XmNcancelButton, w->fsb.cancelBtn, NULL); |
| |
2156 |
| |
2157 w->fsb.gui_created = 1; |
| |
2158 } |
| |
2159 |
| |
2160 static char* FSBDialogTitle(Widget widget) { |
| |
2161 XnFileSelectionBox w = (XnFileSelectionBox)widget; |
| |
2162 if(w->fsb.type == FILEDIALOG_OPEN) { |
| |
2163 return w->fsb.labelOpenFileTitle; |
| |
2164 } else { |
| |
2165 return w->fsb.labelSaveFileTitle; |
| |
2166 } |
| |
2167 } |
| |
2168 |
| |
2169 static FSBViewWidgets CreateView(XnFileSelectionBox w, FSBViewCreateProc create, void *userData, Boolean useDirList) { |
| |
2170 Arg args[64]; |
| |
2171 int n = 0; |
| |
2172 |
| |
2173 XtSetArg(args[n], XmNrightAttachment, XmATTACH_FORM); n++; |
| |
2174 XtSetArg(args[n], XmNbottomAttachment, XmATTACH_FORM); n++; |
| |
2175 if(useDirList) { |
| |
2176 XtSetArg(args[n], XmNtopAttachment, XmATTACH_FORM); n++; |
| |
2177 XtSetArg(args[n], XmNleftAttachment, XmATTACH_WIDGET); n++; |
| |
2178 XtSetArg(args[n], XmNleftWidget, w->fsb.dirlist); n++; |
| |
2179 XtSetArg(args[n], XmNleftOffset, w->fsb.widgetSpacing); n++; |
| |
2180 } else { |
| |
2181 XtSetArg(args[n], XmNtopAttachment, XmATTACH_FORM); n++; |
| |
2182 XtSetArg(args[n], XmNtopOffset, w->fsb.widgetSpacing); n++; |
| |
2183 XtSetArg(args[n], XmNleftAttachment, XmATTACH_FORM); n++; |
| |
2184 } |
| |
2185 |
| |
2186 return create(w->fsb.listform, args, n, userData); |
| |
2187 } |
| |
2188 |
| |
2189 |
| |
2190 typedef struct FSBViewSelection { |
| |
2191 XnFileSelectionBox fsb; |
| |
2192 int index; |
| |
2193 } FSBViewSelection; |
| |
2194 |
| |
2195 static void SelectView(XnFileSelectionBox f, int view) { |
| |
2196 FSBView current = f->fsb.view[f->fsb.selectedview]; |
| |
2197 FSBView newview = f->fsb.view[view]; |
| |
2198 |
| |
2199 XtUnmanageChild(current.widget); |
| |
2200 if(newview.useDirList != current.useDirList) { |
| |
2201 if(current.useDirList) { |
| |
2202 XtUnmanageChild(f->fsb.listform); |
| |
2203 } else { |
| |
2204 XtManageChild(f->fsb.listform); |
| |
2205 } |
| |
2206 } |
| |
2207 |
| |
2208 current.cleanup((Widget)f, current.widget, current.userData); |
| |
2209 XtManageChild(newview.widget); |
| |
2210 |
| |
2211 f->fsb.selectedview = view; |
| |
2212 |
| |
2213 filedialog_update_dir(f, NULL); |
| |
2214 XmProcessTraversal(newview.focus, XmTRAVERSE_CURRENT); |
| |
2215 } |
| |
2216 |
| |
2217 static void SelectViewCallback(Widget w, FSBViewSelection *data, XtPointer u) { |
| |
2218 SelectView(data->fsb, data->index); |
| |
2219 } |
| |
2220 |
| |
2221 static void SelectViewItemDestroy(Widget w, FSBViewSelection *data, XtPointer u) { |
| |
2222 free(data); |
| |
2223 } |
| |
2224 |
| |
2225 static void AddViewMenuItem(XnFileSelectionBox w, const char *name, int viewIndex) { |
| |
2226 Arg args[4]; |
| |
2227 int n = 0; |
| |
2228 |
| |
2229 XmString label = XmStringCreateLocalized((char*)name); |
| |
2230 |
| |
2231 XtSetArg(args[n], XmNlabelString, label); n++; |
| |
2232 XtSetArg(args[1], XmNpositionIndex, w->fsb.selectedview == w->fsb.numviews ? 0 : w->fsb.numviews+1); n++; |
| |
2233 Widget item = XmCreatePushButton(w->fsb.viewMenu, "menuitem", args, n); |
| |
2234 |
| |
2235 if(viewIndex == 0) { |
| |
2236 w->fsb.viewSelectorList = item; |
| |
2237 } else if(viewIndex == 1) { |
| |
2238 w->fsb.viewSelectorDetail = item; |
| |
2239 } |
| |
2240 |
| |
2241 XtManageChild(item); |
| |
2242 XmStringFree(label); |
| |
2243 |
| |
2244 FSBViewSelection *data = malloc(sizeof(FSBViewSelection)); |
| |
2245 data->fsb = w; |
| |
2246 data->index = viewIndex; |
| |
2247 |
| |
2248 XtAddCallback( |
| |
2249 item, |
| |
2250 XmNactivateCallback, |
| |
2251 (XtCallbackProc)SelectViewCallback, |
| |
2252 data); |
| |
2253 XtAddCallback( |
| |
2254 item, |
| |
2255 XmNdestroyCallback, |
| |
2256 (XtCallbackProc)SelectViewItemDestroy, |
| |
2257 data); |
| |
2258 } |
| |
2259 |
| |
2260 static FSBViewWidgets CreateListView(Widget parent, ArgList args, int n, void *userData) { |
| |
2261 XnFileSelectionBox fsb = (XnFileSelectionBox)userData; |
| |
2262 |
| |
2263 XtSetArg(args[n], XmNshadowThickness, 0); n++; |
| |
2264 Widget frame = XmCreateFrame(parent, "filelistframe", args, n); |
| |
2265 |
| |
2266 fsb->fsb.filelist = XmCreateScrolledList(frame, "filelist", NULL, 0); |
| |
2267 XtManageChild(fsb->fsb.filelist); |
| |
2268 |
| |
2269 XtAddCallback( |
| |
2270 fsb->fsb.filelist, |
| |
2271 XmNdefaultActionCallback, |
| |
2272 (XtCallbackProc)FileListActivateCB, |
| |
2273 userData); |
| |
2274 XtAddCallback( |
| |
2275 fsb->fsb.filelist, |
| |
2276 XmNbrowseSelectionCallback, |
| |
2277 (XtCallbackProc)FileListSelectCB, |
| |
2278 userData); |
| |
2279 |
| |
2280 fsb->fsb.listContextMenu = CreateContextMenu(fsb, fsb->fsb.filelist, FileContextMenuCB); |
| |
2281 |
| |
2282 FSBViewWidgets widgets; |
| |
2283 widgets.view = frame; |
| |
2284 widgets.focus = fsb->fsb.filelist; |
| |
2285 return widgets; |
| |
2286 } |
| |
2287 |
| |
2288 #ifdef FSB_ENABLE_DETAIL |
| |
2289 static void set_path_from_row(XnFileSelectionBox data, int row) { |
| |
2290 FileElm *elm = NULL; |
| |
2291 XmLGridRow rowPtr = XmLGridGetRow(data->fsb.grid, XmCONTENT, row); |
| |
2292 XtVaGetValues(data->fsb.grid, XmNrowPtr, rowPtr, XmNrowUserData, &elm, NULL); |
| |
2293 if(!elm) { |
| |
2294 fprintf(stderr, "error: no row data\n"); |
| |
2295 return; |
| |
2296 } |
| |
2297 |
| |
2298 char *path = strdup(elm->path); |
| |
2299 |
| |
2300 data->fsb.selIsDir = False; |
| |
2301 if(data->fsb.type == FILEDIALOG_SAVE) { |
| |
2302 XmTextFieldSetString(data->fsb.name, FileName(path)); |
| |
2303 } |
| |
2304 |
| |
2305 if(data->fsb.selectedPath) { |
| |
2306 free(data->fsb.selectedPath); |
| |
2307 } |
| |
2308 data->fsb.selectedPath = path; |
| |
2309 } |
| |
2310 |
| |
2311 static void grid_select(Widget w, XnFileSelectionBox data, XmLGridCallbackStruct *cb) { |
| |
2312 set_path_from_row(data, cb->row); |
| |
2313 } |
| |
2314 |
| |
2315 static void grid_activate(Widget w, XnFileSelectionBox data, XmLGridCallbackStruct *cb) { |
| |
2316 set_path_from_row(data, cb->row); |
| |
2317 data->fsb.end = True; |
| |
2318 data->fsb.status = FILEDIALOG_OK; |
| |
2319 |
| |
2320 FileSelectionCallback(data, data->fsb.okCallback, XmCR_OK, data->fsb.selectedPath); |
| |
2321 } |
| |
2322 |
| |
2323 static void grid_key_pressed(Widget w, XnFileSelectionBox data, XmLGridCallbackStruct *cb) { |
| |
2324 char chars[16]; |
| |
2325 KeySym keysym; |
| |
2326 int nchars; |
| |
2327 |
| |
2328 nchars = XLookupString(&cb->event->xkey, chars, 15, &keysym, NULL); |
| |
2329 |
| |
2330 if(nchars == 0) return; |
| |
2331 |
| |
2332 // if data->showHidden is 0, data->files contains more items than the grid |
| |
2333 // this means SelectedRow might not be the correct index for data->files |
| |
2334 // we have to count files manually and increase 'row', if the file |
| |
2335 // is actually displayed in the grid |
| |
2336 int row = 0; |
| |
2337 int selectedRow = XmLGridGetSelectedRow(w); |
| |
2338 |
| |
2339 int match = -1; |
| |
2340 |
| |
2341 for(int i=0;i<data->fsb.filecount;i++) { |
| |
2342 const char *name = FileName(data->fsb.files[i].path); |
| |
2343 if(!data->fsb.showHidden && name[0] == '.') continue; |
| |
2344 |
| |
2345 size_t namelen = strlen(name); |
| |
2346 |
| |
2347 size_t cmplen = namelen < nchars ? namelen : nchars; |
| |
2348 if(!memcmp(name, chars, cmplen)) { |
| |
2349 if(row <= selectedRow) { |
| |
2350 if(match == -1) { |
| |
2351 match = row; |
| |
2352 } |
| |
2353 } else { |
| |
2354 match = row; |
| |
2355 break; |
| |
2356 } |
| |
2357 } |
| |
2358 |
| |
2359 row++; |
| |
2360 } |
| |
2361 |
| |
2362 if(match > -1) { |
| |
2363 XmLGridSelectRow(w, match, True); |
| |
2364 XmLGridFocusAndShowRow(w, match+1); |
| |
2365 } else { |
| |
2366 XBell(XtDisplay(w), 0); |
| |
2367 } |
| |
2368 } |
| |
2369 |
| |
2370 static void grid_header_clicked(Widget w, XnFileSelectionBox data, XmLGridCallbackStruct *cb) { |
| |
2371 int new_cmp_field = 0; |
| |
2372 switch(cb->column) { |
| |
2373 case 0: { |
| |
2374 new_cmp_field = 0; |
| |
2375 break; |
| |
2376 } |
| |
2377 case 1: { |
| |
2378 new_cmp_field = 1; |
| |
2379 break; |
| |
2380 } |
| |
2381 case 2: { |
| |
2382 new_cmp_field = 2; |
| |
2383 break; |
| |
2384 } |
| |
2385 } |
| |
2386 |
| |
2387 if(new_cmp_field == file_cmp_field) { |
| |
2388 file_cmp_order = -file_cmp_order; // revert sort order |
| |
2389 } else { |
| |
2390 file_cmp_field = new_cmp_field; // change file cmp order to new field |
| |
2391 file_cmp_order = 1; |
| |
2392 } |
| |
2393 |
| |
2394 int sort_type = file_cmp_order == 1 ? XmSORT_ASCENDING : XmSORT_DESCENDING; |
| |
2395 XmLGridSetSort(data->fsb.grid, file_cmp_field, sort_type); |
| |
2396 |
| |
2397 qsort(data->fsb.files, data->fsb.filecount, sizeof(FileElm), filecmp); |
| |
2398 |
| |
2399 // refresh widget |
| |
2400 filedialog_update_dir(data, NULL); |
| |
2401 } |
| |
2402 |
| |
2403 static FSBViewWidgets CreateDetailView(Widget parent, ArgList args, int n, void *userData) { |
| |
2404 XnFileSelectionBox w = userData; |
| |
2405 |
| |
2406 XtSetArg(args[n], XmNshadowThickness, 0); n++; |
| |
2407 Widget gridcontainer = XmCreateFrame(parent, "gridcontainer", args, n); |
| |
2408 XtManageChild(gridcontainer); |
| |
2409 |
| |
2410 n = 0; |
| |
2411 XtSetArg(args[n], XmNcolumns, 3); n++; |
| |
2412 XtSetArg(args[n], XmNheadingColumns, 0); n++; |
| |
2413 XtSetArg(args[n], XmNheadingRows, 1); n++; |
| |
2414 XtSetArg(args[n], XmNallowColumnResize, 1); n++; |
| |
2415 XtSetArg(args[n], XmNsimpleHeadings, w->fsb.detailHeadings); n++; |
| |
2416 XtSetArg(args[n], XmNhorizontalSizePolicy, XmCONSTANT); n++; |
| |
2417 |
| |
2418 w->fsb.grid = XmLCreateGrid(gridcontainer, "grid", args, n); |
| |
2419 XmLGridSetIgnoreModifyVerify(w->fsb.grid, True); |
| |
2420 XtManageChild(w->fsb.grid); |
| |
2421 |
| |
2422 XtVaSetValues( |
| |
2423 w->fsb.grid, |
| |
2424 XmNcellDefaults, True, |
| |
2425 XtVaTypedArg, XmNblankBackground, XmRString, "white", 6, |
| |
2426 XtVaTypedArg, XmNcellBackground, XmRString, "white", 6, |
| |
2427 NULL); |
| |
2428 |
| |
2429 XtAddCallback(w->fsb.grid, XmNselectCallback, (XtCallbackProc)grid_select, w); |
| |
2430 XtAddCallback(w->fsb.grid, XmNactivateCallback, (XtCallbackProc)grid_activate, w); |
| |
2431 XtAddCallback(w->fsb.grid, XmNheaderClickCallback, (XtCallbackProc)grid_header_clicked, w); |
| |
2432 XtAddCallback(w->fsb.grid, XmNgridKeyPressedCallback, (XtCallbackProc)grid_key_pressed, w); |
| |
2433 |
| |
2434 // context menu |
| |
2435 w->fsb.gridContextMenu = CreateContextMenu(w, w->fsb.grid, FileContextMenuCB); |
| |
2436 |
| |
2437 FSBViewWidgets widgets; |
| |
2438 widgets.view = gridcontainer; |
| |
2439 widgets.focus = w->fsb.grid; |
| |
2440 return widgets; |
| |
2441 } |
| |
2442 #endif |
| |
2443 |
| |
2444 |
| |
2445 /* ------------------------------ Path Utils ------------------------------ */ |
| |
2446 |
| |
2447 const char* GetHomeDir(void) { |
| |
2448 char *home = getenv("HOME"); |
| |
2449 if(!home) { |
| |
2450 home = getenv("USERPROFILE"); |
| |
2451 if(!home) { |
| |
2452 home = "/"; |
| |
2453 } |
| |
2454 } |
| |
2455 return home; |
| |
2456 } |
| |
2457 |
| |
2458 static char* ConcatPath(const char *parent, const char *name) |
| |
2459 { |
| |
2460 size_t parentlen = strlen(parent); |
| |
2461 size_t namelen = strlen(name); |
| |
2462 |
| |
2463 size_t pathlen = parentlen + namelen + 2; |
| |
2464 char *path = malloc(pathlen); |
| |
2465 |
| |
2466 memcpy(path, parent, parentlen); |
| |
2467 if(parentlen > 0 && parent[parentlen-1] != '/') { |
| |
2468 path[parentlen] = '/'; |
| |
2469 parentlen++; |
| |
2470 } |
| |
2471 if(name[0] == '/') { |
| |
2472 name++; |
| |
2473 namelen--; |
| |
2474 } |
| |
2475 memcpy(path+parentlen, name, namelen); |
| |
2476 path[parentlen+namelen] = '\0'; |
| |
2477 return path; |
| |
2478 } |
| |
2479 |
| |
2480 static char* FileName(char *path) { |
| |
2481 int si = 0; |
| |
2482 int osi = 0; |
| |
2483 int i = 0; |
| |
2484 int p = 0; |
| |
2485 char c; |
| |
2486 while((c = path[i]) != 0) { |
| |
2487 if(c == '/') { |
| |
2488 osi = si; |
| |
2489 si = i; |
| |
2490 p = 1; |
| |
2491 } |
| |
2492 i++; |
| |
2493 } |
| |
2494 |
| |
2495 char *name = path + si + p; |
| |
2496 if(name[0] == 0) { |
| |
2497 name = path + osi + p; |
| |
2498 if(name[0] == 0) { |
| |
2499 return path; |
| |
2500 } |
| |
2501 } |
| |
2502 |
| |
2503 return name; |
| |
2504 } |
| |
2505 |
| |
2506 static char* ParentPath(const char *path) { |
| |
2507 char *name = FileName((char*)path); |
| |
2508 size_t namelen = strlen(name); |
| |
2509 size_t pathlen = strlen(path); |
| |
2510 size_t parentlen = pathlen - namelen; |
| |
2511 if(parentlen == 0) { |
| |
2512 parentlen++; |
| |
2513 } |
| |
2514 char *parent = malloc(parentlen + 1); |
| |
2515 memcpy(parent, path, parentlen); |
| |
2516 parent[parentlen] = '\0'; |
| |
2517 return parent; |
| |
2518 } |
| |
2519 |
| |
2520 // unused at the moment, maybe reactivate if more illegal characters |
| |
2521 // are defined |
| |
2522 /* |
| |
2523 static int CheckFileName(const char *fileName) { |
| |
2524 size_t len = strlen(fileName); |
| |
2525 for(int i=0;i<len;i++) { |
| |
2526 if(fileName[i] == '/') { |
| |
2527 return 0; |
| |
2528 } |
| |
2529 } |
| |
2530 return 1; |
| |
2531 } |
| |
2532 */ |
| |
2533 |
| |
2534 |
| |
2535 /* ------------------------------ public API ------------------------------ */ |
| |
2536 |
| |
2537 Widget XnCreateFileSelectionDialog( |
| |
2538 Widget parent, |
| |
2539 String name, |
| |
2540 ArgList arglist, |
| |
2541 Cardinal argcount) |
| |
2542 { |
| |
2543 Widget dialog = XmCreateDialogShell(parent, "FileDialog", NULL, 0); |
| |
2544 Widget fsb = XnCreateFileSelectionBox(dialog, name, arglist, argcount); |
| |
2545 char *title = FSBDialogTitle(fsb); |
| |
2546 XtVaSetValues(dialog, XmNtitle, title, NULL); |
| |
2547 return fsb; |
| |
2548 } |
| |
2549 |
| |
2550 Widget XnCreateFileSelectionBox( |
| |
2551 Widget parent, |
| |
2552 String name, |
| |
2553 ArgList arglist, |
| |
2554 Cardinal argcount) |
| |
2555 { |
| |
2556 Widget fsb = XtCreateWidget(name, xnFsbWidgetClass, parent, arglist, argcount); |
| |
2557 return fsb; |
| |
2558 } |
| |
2559 |
| |
2560 void XnFileSelectionBoxAddView( |
| |
2561 Widget fsb, |
| |
2562 const char *name, |
| |
2563 FSBViewCreateProc create, |
| |
2564 FSBViewUpdateProc update, |
| |
2565 FSBViewSelectProc select, |
| |
2566 FSBViewCleanupProc cleanup, |
| |
2567 FSBViewDestroyProc destroy, |
| |
2568 Boolean useDirList, |
| |
2569 void *userData) |
| |
2570 { |
| |
2571 XnFileSelectionBox f = (XnFileSelectionBox)fsb; |
| |
2572 if(f->fsb.numviews >= FSB_MAX_VIEWS) { |
| |
2573 fprintf(stderr, "XnFileSelectionBox: too many views\n"); |
| |
2574 return; |
| |
2575 } |
| |
2576 |
| |
2577 FSBView view; |
| |
2578 view.update = update; |
| |
2579 view.select = select; |
| |
2580 view.cleanup = cleanup; |
| |
2581 view.destroy = destroy; |
| |
2582 view.useDirList = useDirList; |
| |
2583 view.userData = userData; |
| |
2584 |
| |
2585 FSBViewWidgets widgets = CreateView(f, create, userData, useDirList); |
| |
2586 view.widget = widgets.view; |
| |
2587 view.focus = widgets.focus; |
| |
2588 |
| |
2589 AddViewMenuItem(f, name, f->fsb.numviews); |
| |
2590 |
| |
2591 f->fsb.view[f->fsb.numviews++] = view; |
| |
2592 } |
| |
2593 |
| |
2594 /* |
| |
2595 void XnFileSelectionBoxSetDirList(Widget fsb, const char **dirlist, size_t nelm) { |
| |
2596 XnFileSelectionBox f = (XnFileSelectionBox)fsb; |
| |
2597 PathBarSetDirList(f->fsb.pathBar, dirlist, nelm); |
| |
2598 } |
| |
2599 */ |
| |
2600 |
| |
2601 Widget XnFileSelectionBoxWorkArea(Widget fsb) { |
| |
2602 XnFileSelectionBox f = (XnFileSelectionBox)fsb; |
| |
2603 return f->fsb.workarea; |
| |
2604 } |
| |
2605 |
| |
2606 Widget XnFileSelectionBoxGetChild(Widget fsb, enum XnFSBChild child) { |
| |
2607 XnFileSelectionBox w = (XnFileSelectionBox)fsb; |
| |
2608 switch(child) { |
| |
2609 case XnFSB_DIR_UP_BUTTON: return w->fsb.dirUp; |
| |
2610 case XnFSB_HOME_BUTTON: return w->fsb.home; |
| |
2611 case XnFSB_NEW_FOLDER_BUTTON: return w->fsb.newFolder; |
| |
2612 case XnFSB_DETAIL_TOGGLE_BUTTON: return w->fsb.detailToggleButton; |
| |
2613 case XnFSB_VIEW_OPTION_BUTTON: return w->fsb.viewOption; |
| |
2614 case XnFSB_FILTER_DROPDOWN: return w->fsb.filter; |
| |
2615 case XnFSB_FILTER_BUTTON: return w->fsb.filterButton; |
| |
2616 case XnFSB_SHOW_HIDDEN_TOGGLE_BUTTON: return w->fsb.showHiddenButtonW; |
| |
2617 case XnFSB_DIRECTORIES_LABEL: return w->fsb.lsDirLabel; |
| |
2618 case XnFSB_FILES_LABEL: return w->fsb.lsFileLabel; |
| |
2619 case XnFSB_DIRLIST: return w->fsb.dirlist; |
| |
2620 case XnFSB_FILELIST: return w->fsb.filelist; |
| |
2621 case XnFSB_GRID: return w->fsb.grid; |
| |
2622 case XnFSB_OK_BUTTON: return w->fsb.okBtn; |
| |
2623 case XnFSB_CANCEL_BUTTON: return w->fsb.cancelBtn; |
| |
2624 case XnFSB_HELP_BUTTON: return w->fsb.helpBtn; |
| |
2625 } |
| |
2626 return NULL; |
| |
2627 } |
| |
2628 |
| |
2629 void XnFileSelectionBoxDeleteFilters(Widget fsb) { |
| |
2630 XnFileSelectionBox w = (XnFileSelectionBox)fsb; |
| |
2631 Widget filterList = XmDropDownGetList(w->fsb.filter); |
| |
2632 XmListDeleteAllItems(filterList); |
| |
2633 } |
| |
2634 |
| |
2635 void XnFileSelectionBoxAddFilter(Widget fsb, const char *filter) { |
| |
2636 XnFileSelectionBox w = (XnFileSelectionBox)fsb; |
| |
2637 Widget filterList = XmDropDownGetList(w->fsb.filter); |
| |
2638 |
| |
2639 XmString str = XmStringCreateSimple((char*)filter); |
| |
2640 XmListAddItem(filterList, str, 0); |
| |
2641 XmStringFree(str); |
| |
2642 } |