1 /*
2 * Copyright (c) 2001-2004 Marcin Dalecki and others
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a copy
5 * of this software and associated documentation files (the "Software"), to
6 * deal in the Software without restriction, including without limitation the
7 * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
8 * sell copies of the Software, and to permit persons to whom the Software is
9 * 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 * PAUL VOJTA OR ANY OTHER AUTHOR OF THIS SOFTWARE BE LIABLE FOR ANY CLAIM,
18 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20 * OTHER DEALINGS IN THE SOFTWARE.
21 *
22 */
23
24 /*
25 * Implementation of the File selection dialogue for the Motif GUI.
26 */
27
28 #include "xdvi-config.h"
29 #include "xdvi.h"
30 #include "sfSelFile.h"
31
32 #include "dvi.h"
33 #include "string-utils.h"
34 #include "util.h"
35 #include "events.h"
36 #include "message-window.h"
37 #include "dvi-init.h" /* for dviErrFlagT */
38 #include "x_util.h"
39
40 #if defined(MOTIF) /* entire file */
41
42 #include <Xm/FileSB.h>
43 #include <Xm/Form.h>
44 #include <Xm/ToggleBG.h>
45
46 #if HAVE_XKB_BELL_EXT
47 # include <X11/XKBlib.h>
48 # define XdviBell(display, window, percent) \
49 XkbBell(display, window, percent, (Atom) None)
50 #else
51 # define XdviBell(display, window, percent) XBell(display, percent)
52 #endif
53
54 /* static Widget dialog = NULL; */
55 /* static char *browse_fname = NULL; */
56
57 /*
58 * Process callback from Dialog cancel actions.
59 */
60 static void
cancel_callback(Widget w,XtPointer client_data,XtPointer call_data)61 cancel_callback(Widget w,
62 XtPointer client_data,
63 XtPointer call_data)
64 {
65 struct filesel_callback *callback = (struct filesel_callback *)client_data;
66
67 UNUSED(w);
68 UNUSED(call_data);
69 #if 0
70 /* DON'T reset browse_fname, so that user gets the current
71 value as default next time when he cancels now */
72 if (callback->browse_fname != NULL)
73 {
74 XtFree(callback->browse_fname);
75 callback->browse_fname = NULL;
76 }
77 #endif
78
79 XtUnmanageChild(callback->shell);
80 if (callback->exit_on_cancel) {
81 exit(0);
82 }
83 }
84
85 /*
86 * Process callback from Dialog actions.
87 */
88
89 static void
accept_callback(Widget w,XtPointer client_data,XtPointer call_data)90 accept_callback(Widget w,
91 XtPointer client_data,
92 XtPointer call_data)
93 {
94 XmFileSelectionBoxCallbackStruct *fcb;
95 struct filesel_callback *callback;
96
97 UNUSED(w);
98
99 ASSERT(client_data != NULL, "struct filesel_callback pointer expected in client data");
100 callback = (struct filesel_callback *)client_data;
101
102 /* get the filename from the file selection box */
103 fcb = (XmFileSelectionBoxCallbackStruct *)call_data;
104 if (callback->browse_fname != NULL) {
105 XtFree(callback->browse_fname);
106 callback->browse_fname = NULL;
107 }
108 XmStringGetLtoR(fcb->value, G_charset, &callback->browse_fname);
109
110 if (0 && callback->must_exist) {
111 FILE *tmp_fp = XFOPEN(callback->browse_fname, "r");
112 dviErrFlagT errflag = NO_ERROR;
113 if (tmp_fp == NULL) {
114 popup_message(XtParent(callback->shell),
115 MSG_ERR, NULL, "Could not open %s: %s.\n",
116 callback->browse_fname, strerror(errno));
117 /* leave file selection box open */
118 return;
119 }
120 else if (!process_preamble(tmp_fp, &errflag)
121 || !find_postamble(tmp_fp, &errflag)
122 || !read_postamble(tmp_fp, &errflag, True
123 #if DELAYED_MKTEXPK
124 , False
125 #endif
126 )) {
127 popup_message(XtParent(callback->shell),
128 MSG_ERR, NULL, "Error opening %s:\n%s.",
129 callback->browse_fname, get_dvi_error(errflag));
130 fclose(tmp_fp);
131 /* leave file selection box open */
132 return;
133 }
134 else { /* file is OK */
135 fclose(tmp_fp);
136 }
137 }
138
139 /* success; close dialog, and call our callback */
140 XtUnmanageChild(callback->shell);
141 callback->func_ptr(callback->browse_fname, callback->data);
142 }
143
144 static void
cb_open_new_window(Widget w,XtPointer client_data,XtPointer call_data)145 cb_open_new_window(Widget w, XtPointer client_data, XtPointer call_data)
146 {
147 UNUSED(client_data);
148 UNUSED(call_data);
149
150 if (XmToggleButtonGadgetGetState(w))
151 resource.filesel_open_new_window = True;
152 else
153 resource.filesel_open_new_window = False;
154 store_preference(NULL, "fileselOpenNewWindow", "%d", resource.filesel_open_new_window);
155 }
156
raise_file_selector(void)157 void raise_file_selector(void)
158 {
159 /* dummy */
160 return;
161 }
162
163 void
XsraSelFilePopup(struct filesel_callback * callback)164 XsraSelFilePopup(struct filesel_callback *callback)
165 {
166 if (XtIsManaged(callback->shell)) {
167 XdviBell(DISP, XtWindow(callback->shell), 10);
168 XRaiseWindow(DISP, XtWindow(callback->shell));
169 return;
170 }
171 else {
172 #define ARG_CNT 4
173 XmString filemask = NULL;
174 XmString directory = NULL;
175 Arg args[ARG_CNT];
176 int i = 0;
177 char *path, *ptr;
178
179 /* only show files matching our mask */
180 filemask = XmStringCreateLtoR((char *)callback->filemask, G_charset);
181 XtSetArg(args[i], XmNpattern, filemask); i++;
182
183 /* set directory to last directory used */
184 if (callback->browse_fname == NULL) {
185 ASSERT(callback->init_path != NULL, "callback->init_path mustn't be NULL!");
186 callback->browse_fname = xt_strdup(callback->init_path);
187 }
188 path = xstrdup(callback->browse_fname);
189 ptr = strrchr(path, '/');
190 if (ptr != NULL)
191 *ptr = '\0';
192 directory = XmStringCreateLtoR(path, G_charset);
193 XtSetArg(args[i], XmNdirectory, directory); i++;
194 free(path);
195
196
197 ASSERT(i < ARG_CNT, "args list too short");
198 XtSetValues(callback->shell, args, (Cardinal)i);
199
200 free(filemask);
201 free(directory);
202
203 XtManageChild(callback->shell);
204 #undef ARG_CNT
205 }
206 }
207
208 Widget
XsraSelFile(Widget parent,struct filesel_callback * callback)209 XsraSelFile(Widget parent, struct filesel_callback *callback)
210 {
211 Widget dialog = XmCreateFileSelectionDialog(parent, "file", NULL, 0);
212
213 XtVaSetValues(XtParent(dialog), XmNtitle, callback->title, NULL);
214
215 XtAddCallback(dialog, XmNokCallback, accept_callback, (XtPointer)callback);
216 XtAddCallback(dialog, XmNcancelCallback, cancel_callback, (XtPointer)callback);
217
218 /* When opening a DVI file, offer to open in new window */
219 if (callback->must_exist) {
220 Widget form, button;
221 XmString test;
222 form = XtVaCreateManagedWidget("new_window_form", xmFormWidgetClass, dialog, NULL);
223 test = XmStringCreateLocalized("Open file in new window");
224 button = XtVaCreateManagedWidget(Xdvi_NEW_WINDOW_RADIO_NAME, xmToggleButtonGadgetClass, form,
225 XmNlabelString, test,
226 XmNindicatorType, XmN_OF_MANY,
227 XmNset, resource.filesel_open_new_window,
228 NULL);
229 XmStringFree(test);
230 XtAddCallback(button, XmNvalueChangedCallback, cb_open_new_window, (XtPointer)NULL);
231 }
232
233
234 /* We have no help in this window, so hide help button */
235 XtUnmanageChild(XmFileSelectionBoxGetChild(dialog, (unsigned char)XmDIALOG_HELP_BUTTON));
236
237 return dialog;
238 }
239
240 #else
241 /* silence `empty compilation unit' warnings */
bar(void)242 static void bar(void); static void foo(void) { bar(); } static void bar(void) { foo(); }
243 #endif /* defined(MOTIF) */
244