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