1122 |
/*********************************************************************** |
/*********************************************************************** |
1123 |
File dialog functions |
File dialog functions |
1124 |
***********************************************************************/ |
***********************************************************************/ |
|
enum |
|
|
{ |
|
|
XG_FILE_NOT_DONE, |
|
|
XG_FILE_OK, |
|
|
XG_FILE_CANCEL, |
|
|
XG_FILE_DESTROYED, |
|
|
}; |
|
|
|
|
1125 |
#ifdef HAVE_GTK_FILE_BOTH |
#ifdef HAVE_GTK_FILE_BOTH |
1126 |
int use_old_gtk_file_dialog; |
int use_old_gtk_file_dialog; |
1127 |
#endif |
#endif |
1128 |
|
|
1129 |
|
/* Function that is called when the file dialog pops down. |
1130 |
|
W is the dialog widget, RESPONSE is the response code. |
1131 |
|
USER_DATA is what we passed in to g_signal_connect (pointer to int). */ |
1132 |
|
|
1133 |
|
static void |
1134 |
|
xg_file_response_cb (w, |
1135 |
|
response, |
1136 |
|
user_data) |
1137 |
|
GtkDialog *w; |
1138 |
|
gint response; |
1139 |
|
gpointer user_data; |
1140 |
|
{ |
1141 |
|
int *ptr = (int *) user_data; |
1142 |
|
*ptr = response; |
1143 |
|
} |
1144 |
|
|
1145 |
|
|
1146 |
|
/* Destroy the dialog. This makes it pop down. */ |
1147 |
|
|
1148 |
|
static Lisp_Object |
1149 |
|
pop_down_file_dialog (arg) |
1150 |
|
Lisp_Object arg; |
1151 |
|
{ |
1152 |
|
struct Lisp_Save_Value *p = XSAVE_VALUE (arg); |
1153 |
|
BLOCK_INPUT; |
1154 |
|
gtk_widget_destroy (GTK_WIDGET (p->pointer)); |
1155 |
|
UNBLOCK_INPUT; |
1156 |
|
return Qnil; |
1157 |
|
} |
1158 |
|
|
1159 |
|
typedef char * (*xg_get_file_func) P_ ((GtkWidget *)); |
1160 |
|
|
1161 |
#ifdef HAVE_GTK_FILE_CHOOSER_DIALOG_NEW |
#ifdef HAVE_GTK_FILE_CHOOSER_DIALOG_NEW |
1162 |
|
|
1163 |
|
/* Return the selected file for file chooser dialog W. |
1164 |
|
The returned string must be free:d. */ |
1165 |
|
|
1166 |
|
static char * |
1167 |
|
xg_get_file_name_from_chooser (w) |
1168 |
|
GtkWidget *w; |
1169 |
|
{ |
1170 |
|
return gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (w)); |
1171 |
|
} |
1172 |
|
|
1173 |
/* Read a file name from the user using a file chooser dialog. |
/* Read a file name from the user using a file chooser dialog. |
1174 |
F is the current frame. |
F is the current frame. |
1175 |
PROMPT is a prompt to show to the user. May not be NULL. |
PROMPT is a prompt to show to the user. May not be NULL. |
1176 |
DEFAULT_FILENAME is a default selection to be displayed. May be NULL. |
DEFAULT_FILENAME is a default selection to be displayed. May be NULL. |
1177 |
If MUSTMATCH_P is non-zero, the returned file name must be an existing |
If MUSTMATCH_P is non-zero, the returned file name must be an existing |
1178 |
file. |
file. *FUNC is set to a function that can be used to retrieve the |
1179 |
|
selected file name from the returned widget. |
1180 |
|
|
1181 |
Returns a file name or NULL if no file was selected. |
Returns the created widget. */ |
|
The returned string must be freed by the caller. */ |
|
1182 |
|
|
1183 |
static char * |
static GtkWidget * |
1184 |
xg_get_file_with_chooser (f, prompt, default_filename, mustmatch_p, only_dir_p) |
xg_get_file_with_chooser (f, prompt, default_filename, |
1185 |
|
mustmatch_p, only_dir_p, func) |
1186 |
FRAME_PTR f; |
FRAME_PTR f; |
1187 |
char *prompt; |
char *prompt; |
1188 |
char *default_filename; |
char *default_filename; |
1189 |
int mustmatch_p, only_dir_p; |
int mustmatch_p, only_dir_p; |
1190 |
|
xg_get_file_func *func; |
1191 |
{ |
{ |
1192 |
GtkWidget *filewin; |
GtkWidget *filewin; |
1193 |
GtkWindow *gwin = GTK_WINDOW (FRAME_GTK_OUTER_WIDGET (f)); |
GtkWindow *gwin = GTK_WINDOW (FRAME_GTK_OUTER_WIDGET (f)); |
|
|
|
|
char *fn = 0; |
|
1194 |
GtkFileChooserAction action = (mustmatch_p ? |
GtkFileChooserAction action = (mustmatch_p ? |
1195 |
GTK_FILE_CHOOSER_ACTION_OPEN : |
GTK_FILE_CHOOSER_ACTION_OPEN : |
1196 |
GTK_FILE_CHOOSER_ACTION_SAVE); |
GTK_FILE_CHOOSER_ACTION_SAVE); |
1205 |
GTK_RESPONSE_OK, |
GTK_RESPONSE_OK, |
1206 |
NULL); |
NULL); |
1207 |
|
|
|
xg_set_screen (filewin, f); |
|
|
gtk_widget_set_name (filewin, "emacs-filedialog"); |
|
|
gtk_window_set_transient_for (GTK_WINDOW (filewin), gwin); |
|
|
gtk_window_set_destroy_with_parent (GTK_WINDOW (filewin), TRUE); |
|
|
|
|
|
|
|
1208 |
if (default_filename) |
if (default_filename) |
1209 |
{ |
{ |
1210 |
Lisp_Object file; |
Lisp_Object file; |
1225 |
UNGCPRO; |
UNGCPRO; |
1226 |
} |
} |
1227 |
|
|
1228 |
gtk_widget_show (filewin); |
*func = xg_get_file_name_from_chooser; |
1229 |
|
return filewin; |
|
if (gtk_dialog_run (GTK_DIALOG (filewin)) == GTK_RESPONSE_OK) |
|
|
fn = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (filewin)); |
|
|
|
|
|
gtk_widget_destroy (filewin); |
|
|
|
|
|
return fn; |
|
1230 |
} |
} |
1231 |
#endif /* HAVE_GTK_FILE_CHOOSER_DIALOG_NEW */ |
#endif /* HAVE_GTK_FILE_CHOOSER_DIALOG_NEW */ |
1232 |
|
|
1233 |
#ifdef HAVE_GTK_FILE_SELECTION_NEW |
#ifdef HAVE_GTK_FILE_SELECTION_NEW |
|
/* Callback function invoked when the Ok button is pressed in |
|
|
a file dialog. |
|
|
W is the file dialog widget, |
|
|
ARG points to an integer where we record what has happend. */ |
|
1234 |
|
|
1235 |
static void |
/* Return the selected file for file selector dialog W. |
1236 |
xg_file_sel_ok (w, arg) |
The returned string must be free:d. */ |
|
GtkWidget *w; |
|
|
gpointer arg; |
|
|
{ |
|
|
*(int*)arg = XG_FILE_OK; |
|
|
} |
|
|
|
|
|
/* Callback function invoked when the Cancel button is pressed in |
|
|
a file dialog. |
|
|
W is the file dialog widget, |
|
|
ARG points to an integer where we record what has happend. */ |
|
|
|
|
|
static void |
|
|
xg_file_sel_cancel (w, arg) |
|
|
GtkWidget *w; |
|
|
gpointer arg; |
|
|
{ |
|
|
*(int*)arg = XG_FILE_CANCEL; |
|
|
} |
|
1237 |
|
|
1238 |
/* Callback function invoked when the file dialog is destroyed (i.e. |
static char * |
1239 |
popped down). We must keep track of this, because if this |
xg_get_file_name_from_selector (w) |
|
happens, GTK destroys the widget. But if for example, Ok is pressed, |
|
|
the dialog is popped down, but the dialog widget is not destroyed. |
|
|
W is the file dialog widget, |
|
|
ARG points to an integer where we record what has happend. */ |
|
|
|
|
|
static void |
|
|
xg_file_sel_destroy (w, arg) |
|
1240 |
GtkWidget *w; |
GtkWidget *w; |
|
gpointer arg; |
|
1241 |
{ |
{ |
1242 |
*(int*)arg = XG_FILE_DESTROYED; |
GtkFileSelection *filesel = GTK_FILE_SELECTION (w); |
1243 |
|
return xstrdup ((char*) gtk_file_selection_get_filename (filesel)); |
1244 |
} |
} |
1245 |
|
|
1246 |
/* Read a file name from the user using a file selection dialog. |
/* Create a file selection dialog. |
1247 |
F is the current frame. |
F is the current frame. |
1248 |
PROMPT is a prompt to show to the user. May not be NULL. |
PROMPT is a prompt to show to the user. May not be NULL. |
1249 |
DEFAULT_FILENAME is a default selection to be displayed. May be NULL. |
DEFAULT_FILENAME is a default selection to be displayed. May be NULL. |
1250 |
If MUSTMATCH_P is non-zero, the returned file name must be an existing |
If MUSTMATCH_P is non-zero, the returned file name must be an existing |
1251 |
file. |
file. *FUNC is set to a function that can be used to retrieve the |
1252 |
|
selected file name from the returned widget. |
1253 |
|
|
1254 |
Returns a file name or NULL if no file was selected. |
Returns the created widget. */ |
|
The returned string must be freed by the caller. */ |
|
1255 |
|
|
1256 |
static char * |
static GtkWidget * |
1257 |
xg_get_file_with_selection (f, prompt, default_filename, |
xg_get_file_with_selection (f, prompt, default_filename, |
1258 |
mustmatch_p, only_dir_p) |
mustmatch_p, only_dir_p, func) |
1259 |
FRAME_PTR f; |
FRAME_PTR f; |
1260 |
char *prompt; |
char *prompt; |
1261 |
char *default_filename; |
char *default_filename; |
1262 |
int mustmatch_p, only_dir_p; |
int mustmatch_p, only_dir_p; |
1263 |
|
xg_get_file_func *func; |
1264 |
{ |
{ |
1265 |
GtkWidget *filewin; |
GtkWidget *filewin; |
1266 |
GtkFileSelection *filesel; |
GtkFileSelection *filesel; |
|
int filesel_done = XG_FILE_NOT_DONE; |
|
|
char *fn = 0; |
|
1267 |
|
|
1268 |
filewin = gtk_file_selection_new (prompt); |
filewin = gtk_file_selection_new (prompt); |
1269 |
filesel = GTK_FILE_SELECTION (filewin); |
filesel = GTK_FILE_SELECTION (filewin); |
1270 |
|
|
|
xg_set_screen (filewin, f); |
|
|
gtk_widget_set_name (filewin, "emacs-filedialog"); |
|
|
gtk_window_set_transient_for (GTK_WINDOW (filewin), |
|
|
GTK_WINDOW (FRAME_GTK_OUTER_WIDGET (f))); |
|
|
gtk_window_set_destroy_with_parent (GTK_WINDOW (filewin), TRUE); |
|
|
|
|
|
g_signal_connect (G_OBJECT (filesel->ok_button), |
|
|
"clicked", |
|
|
G_CALLBACK (xg_file_sel_ok), |
|
|
&filesel_done); |
|
|
g_signal_connect (G_OBJECT (filesel->cancel_button), |
|
|
"clicked", |
|
|
G_CALLBACK (xg_file_sel_cancel), |
|
|
&filesel_done); |
|
|
g_signal_connect (G_OBJECT (filesel), |
|
|
"destroy", |
|
|
G_CALLBACK (xg_file_sel_destroy), |
|
|
&filesel_done); |
|
|
|
|
1271 |
if (default_filename) |
if (default_filename) |
1272 |
gtk_file_selection_set_filename (filesel, default_filename); |
gtk_file_selection_set_filename (filesel, default_filename); |
1273 |
|
|
1278 |
gtk_file_selection_hide_fileop_buttons (filesel); |
gtk_file_selection_hide_fileop_buttons (filesel); |
1279 |
} |
} |
1280 |
|
|
1281 |
|
*func = xg_get_file_name_from_selector; |
1282 |
|
|
1283 |
gtk_widget_show_all (filewin); |
return filewin; |
|
|
|
|
while (filesel_done == XG_FILE_NOT_DONE) |
|
|
gtk_main_iteration (); |
|
|
|
|
|
if (filesel_done == XG_FILE_OK) |
|
|
fn = xstrdup ((char*) gtk_file_selection_get_filename (filesel)); |
|
|
|
|
|
if (filesel_done != XG_FILE_DESTROYED) |
|
|
gtk_widget_destroy (filewin); |
|
|
|
|
|
return fn; |
|
1284 |
} |
} |
1285 |
#endif /* HAVE_GTK_FILE_SELECTION_NEW */ |
#endif /* HAVE_GTK_FILE_SELECTION_NEW */ |
1286 |
|
|
1304 |
char *default_filename; |
char *default_filename; |
1305 |
int mustmatch_p, only_dir_p; |
int mustmatch_p, only_dir_p; |
1306 |
{ |
{ |
1307 |
|
GtkWidget *w = 0; |
1308 |
|
int count = SPECPDL_INDEX (); |
1309 |
|
char *fn = 0; |
1310 |
|
int filesel_done = 0; |
1311 |
|
xg_get_file_func func; |
1312 |
|
|
1313 |
#ifdef HAVE_GTK_FILE_BOTH |
#ifdef HAVE_GTK_FILE_BOTH |
1314 |
if (use_old_gtk_file_dialog) |
if (use_old_gtk_file_dialog) |
1315 |
return xg_get_file_with_selection (f, prompt, default_filename, |
w = xg_get_file_with_selection (f, prompt, default_filename, |
1316 |
mustmatch_p, only_dir_p); |
mustmatch_p, only_dir_p, &func); |
1317 |
return xg_get_file_with_chooser (f, prompt, default_filename, |
else |
1318 |
mustmatch_p, only_dir_p); |
w = xg_get_file_with_chooser (f, prompt, default_filename, |
1319 |
|
mustmatch_p, only_dir_p, &func); |
1320 |
|
|
1321 |
#else /* not HAVE_GTK_FILE_BOTH */ |
#else /* not HAVE_GTK_FILE_BOTH */ |
1322 |
|
|
1323 |
#ifdef HAVE_GTK_FILE_SELECTION_DIALOG_NEW |
#ifdef HAVE_GTK_FILE_SELECTION_NEW |
1324 |
return xg_get_file_with_selection (f, prompt, default_filename, |
w = xg_get_file_with_selection (f, prompt, default_filename, |
1325 |
mustmatch_p, only_dir_p); |
mustmatch_p, only_dir_p, &func); |
1326 |
#endif |
#endif |
1327 |
#ifdef HAVE_GTK_FILE_CHOOSER_DIALOG_NEW |
#ifdef HAVE_GTK_FILE_CHOOSER_DIALOG_NEW |
1328 |
return xg_get_file_with_chooser (f, prompt, default_filename, |
w = xg_get_file_with_chooser (f, prompt, default_filename, |
1329 |
mustmatch_p, only_dir_p); |
mustmatch_p, only_dir_p, &func); |
1330 |
#endif |
#endif |
1331 |
|
|
1332 |
#endif /* HAVE_GTK_FILE_BOTH */ |
#endif /* HAVE_GTK_FILE_BOTH */ |
1333 |
return 0; |
|
1334 |
|
xg_set_screen (w, f); |
1335 |
|
gtk_widget_set_name (w, "emacs-filedialog"); |
1336 |
|
gtk_window_set_transient_for (GTK_WINDOW (w), |
1337 |
|
GTK_WINDOW (FRAME_GTK_OUTER_WIDGET (f))); |
1338 |
|
gtk_window_set_destroy_with_parent (GTK_WINDOW (w), TRUE); |
1339 |
|
gtk_window_set_modal (GTK_WINDOW (w), TRUE); |
1340 |
|
|
1341 |
|
g_signal_connect (G_OBJECT (w), |
1342 |
|
"response", |
1343 |
|
G_CALLBACK (xg_file_response_cb), |
1344 |
|
&filesel_done); |
1345 |
|
|
1346 |
|
/* Don't destroy the widget if closed by the window manager close button. */ |
1347 |
|
g_signal_connect (G_OBJECT (w), "delete-event", G_CALLBACK (gtk_true), NULL); |
1348 |
|
|
1349 |
|
gtk_widget_show (w); |
1350 |
|
|
1351 |
|
record_unwind_protect (pop_down_file_dialog, make_save_value (w, 0)); |
1352 |
|
while (! filesel_done) |
1353 |
|
{ |
1354 |
|
x_menu_wait_for_event (0); |
1355 |
|
gtk_main_iteration (); |
1356 |
|
} |
1357 |
|
|
1358 |
|
if (filesel_done == GTK_RESPONSE_OK) |
1359 |
|
fn = (*func) (w); |
1360 |
|
|
1361 |
|
unbind_to (count, Qnil); |
1362 |
|
|
1363 |
|
return fn; |
1364 |
} |
} |
1365 |
|
|
1366 |
|
|
1999 |
GTK_WINDOW (FRAME_GTK_OUTER_WIDGET (f))); |
GTK_WINDOW (FRAME_GTK_OUTER_WIDGET (f))); |
2000 |
gtk_window_set_destroy_with_parent (GTK_WINDOW (w), TRUE); |
gtk_window_set_destroy_with_parent (GTK_WINDOW (w), TRUE); |
2001 |
gtk_widget_set_name (w, "emacs-dialog"); |
gtk_widget_set_name (w, "emacs-dialog"); |
2002 |
|
gtk_window_set_modal (GTK_WINDOW (w), TRUE); |
2003 |
} |
} |
2004 |
else if (menu_bar_p || pop_up_p) |
else if (menu_bar_p || pop_up_p) |
2005 |
{ |
{ |