pcb 4.1.1
An interactive printed circuit board layout editor.
|
00001 /* 00002 * COPYRIGHT 00003 * 00004 * PCB, interactive printed circuit board design 00005 * Copyright (C) 1994,1995,1996 Thomas Nau 00006 * 00007 * This program is free software; you can redistribute it and/or modify 00008 * it under the terms of the GNU General Public License as published by 00009 * the Free Software Foundation; either version 2 of the License, or 00010 * (at your option) any later version. 00011 * 00012 * This program is distributed in the hope that it will be useful, 00013 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00014 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00015 * GNU General Public License for more details. 00016 * 00017 * You should have received a copy of the GNU General Public License along 00018 * with this program; if not, write to the Free Software Foundation, Inc., 00019 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 00020 * 00021 * Contact addresses for paper mail and Email: 00022 * Thomas Nau, Schlehenweg 15, 88471 Baustetten, Germany 00023 * Thomas.Nau@rz.uni-ulm.de 00024 * 00025 */ 00026 00027 /* This file written by Bill Wilson for the PCB Gtk port. 00028 */ 00029 00030 #ifdef HAVE_CONFIG_H 00031 #include "config.h" 00032 #endif 00033 00034 00035 #include "data.h" 00036 #include "gui.h" 00037 00038 #ifdef HAVE_LIBDMALLOC 00039 #include <dmalloc.h> 00040 #endif 00041 00042 /* ---------------------------------------------- */ 00043 gchar * 00044 ghid_dialog_input (const char * prompt, const char * initial) 00045 { 00046 GtkWidget *dialog; 00047 GtkWidget *content_area; 00048 GtkWidget *vbox, *label, *entry; 00049 gchar *string; 00050 gboolean response; 00051 GHidPort *out = &ghid_port; 00052 00053 dialog = gtk_dialog_new_with_buttons (_("PCB User Input"), 00054 GTK_WINDOW (out->top_window), 00055 GTK_DIALOG_MODAL, 00056 GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, 00057 GTK_STOCK_OK, GTK_RESPONSE_OK, NULL); 00058 00059 gtk_dialog_set_default_response (GTK_DIALOG (dialog), GTK_RESPONSE_OK); 00060 vbox = gtk_vbox_new (FALSE, 4); 00061 gtk_container_set_border_width (GTK_CONTAINER (vbox), 4); 00062 label = gtk_label_new (""); 00063 gtk_box_pack_start (GTK_BOX (vbox), label, TRUE, TRUE, 0); 00064 00065 gtk_label_set_use_markup (GTK_LABEL (label), TRUE); 00066 gtk_label_set_markup (GTK_LABEL (label), 00067 prompt ? prompt : _("Enter something")); 00068 00069 entry = gtk_entry_new (); 00070 if (initial) 00071 gtk_entry_set_text (GTK_ENTRY (entry), initial); 00072 00073 gtk_entry_set_activates_default (GTK_ENTRY (entry), TRUE); 00074 gtk_box_pack_start (GTK_BOX (vbox), entry, TRUE, TRUE, 0); 00075 00076 content_area = gtk_dialog_get_content_area (GTK_DIALOG (dialog)); 00077 gtk_container_add (GTK_CONTAINER (content_area), vbox); 00078 gtk_widget_show_all (dialog); 00079 00080 response = gtk_dialog_run (GTK_DIALOG (dialog)); 00081 if (response != GTK_RESPONSE_OK) 00082 string = g_strdup (initial ? initial : ""); 00083 else 00084 string = gtk_editable_get_chars (GTK_EDITABLE (entry), 0, -1); 00085 00086 gtk_widget_destroy (dialog); 00087 return string; 00088 } 00089 00090 /* ---------------------------------------------- */ 00091 void 00092 ghid_dialog_about (void) 00093 { 00094 GtkWidget *dialog; 00095 GHidPort *out = &ghid_port; 00096 dialog = gtk_message_dialog_new (GTK_WINDOW (out->top_window), 00097 (GtkDialogFlags)(GTK_DIALOG_MODAL 00098 | GTK_DIALOG_DESTROY_WITH_PARENT), 00099 GTK_MESSAGE_INFO, 00100 GTK_BUTTONS_OK, 00101 "%s", GetInfoString ()); 00102 00103 gtk_dialog_run (GTK_DIALOG (dialog)); 00104 gtk_widget_destroy (dialog); 00105 } 00106 00107 /* ---------------------------------------------- */ 00108 gint 00109 ghid_dialog_confirm_all (gchar * all_message) 00110 { 00111 GtkWidget *dialog; 00112 GtkWidget *content_area; 00113 GtkWidget *label, *vbox; 00114 gint response; 00115 GHidPort *out = &ghid_port; 00116 00117 dialog = gtk_dialog_new_with_buttons (_("Confirm"), 00118 GTK_WINDOW (out->top_window), 00119 (GtkDialogFlags)(GTK_DIALOG_MODAL | 00120 GTK_DIALOG_DESTROY_WITH_PARENT), 00121 GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, 00122 GTK_STOCK_OK, GTK_RESPONSE_OK, 00123 _("Sequence OK"), 00124 GUI_DIALOG_RESPONSE_ALL, NULL); 00125 00126 content_area = gtk_dialog_get_content_area (GTK_DIALOG (dialog)); 00127 vbox = ghid_framed_vbox (content_area, NULL, 6, FALSE, 4, 6); 00128 00129 label = gtk_label_new (all_message); 00130 gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, FALSE, 3); 00131 gtk_widget_show_all (dialog); 00132 00133 response = gtk_dialog_run (GTK_DIALOG (dialog)); 00134 gtk_widget_destroy (dialog); 00135 00136 return response; 00137 } 00138 00139 /* ---------------------------------------------- */ 00140 void 00141 ghid_dialog_message (gchar * message) 00142 { 00143 GtkWidget *dialog; 00144 GHidPort *out = &ghid_port; 00145 00146 dialog = gtk_message_dialog_new (GTK_WINDOW (out->top_window), 00147 (GtkDialogFlags)(GTK_DIALOG_MODAL | 00148 GTK_DIALOG_DESTROY_WITH_PARENT), 00149 GTK_MESSAGE_WARNING, GTK_BUTTONS_OK, 00150 "%s", message); 00151 00152 gtk_dialog_run (GTK_DIALOG (dialog)); 00153 gtk_widget_destroy (dialog); 00154 } 00155 00156 /* ---------------------------------------------- */ 00157 gboolean 00158 ghid_dialog_confirm (gchar * message, gchar * cancelmsg, gchar * okmsg) 00159 { 00160 static gint x = -1, y = -1; 00161 GtkWidget *dialog; 00162 gboolean confirm = FALSE; 00163 GHidPort *out = &ghid_port; 00164 00165 if (cancelmsg == NULL) 00166 { 00167 cancelmsg = _("_Cancel"); 00168 } 00169 if (okmsg == NULL) 00170 { 00171 okmsg = _("_OK"); 00172 } 00173 00174 dialog = gtk_message_dialog_new (GTK_WINDOW (out->top_window), 00175 (GtkDialogFlags)(GTK_DIALOG_MODAL | 00176 GTK_DIALOG_DESTROY_WITH_PARENT), 00177 GTK_MESSAGE_QUESTION, 00178 GTK_BUTTONS_NONE, 00179 "%s", message); 00180 gtk_dialog_add_buttons (GTK_DIALOG (dialog), 00181 cancelmsg, GTK_RESPONSE_CANCEL, 00182 okmsg, GTK_RESPONSE_OK, 00183 NULL); 00184 00185 if(x != -1) { 00186 gtk_window_move(GTK_WINDOW (dialog), x, y); 00187 } 00188 00189 if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_OK) 00190 confirm = TRUE; 00191 00192 gtk_window_get_position(GTK_WINDOW (dialog), &x, &y); 00193 00194 gtk_widget_destroy (dialog); 00195 return confirm; 00196 } 00197 00198 /* ---------------------------------------------- */ 00199 gint 00200 ghid_dialog_close_confirm () 00201 { 00202 GtkWidget *dialog; 00203 gint rv; 00204 GHidPort *out = &ghid_port; 00205 gchar *tmp; 00206 gchar *str; 00207 00208 if (PCB->Filename == NULL) 00209 { 00210 tmp = g_strdup_printf ( 00211 _("Save the changes to layout before closing?")); 00212 } else { 00213 tmp = g_strdup_printf ( 00214 _("Save the changes to layout \"%s\" before closing?"), 00215 PCB->Filename); 00216 } 00217 str = g_strconcat ("<big><b>", tmp, "</b></big>", NULL); 00218 g_free (tmp); 00219 tmp = _("If you don't save, all your changes will be permanently lost."); 00220 str = g_strconcat (str, "\n\n", tmp, NULL); 00221 00222 dialog = gtk_message_dialog_new (GTK_WINDOW (out->top_window), 00223 (GtkDialogFlags)(GTK_DIALOG_MODAL | 00224 GTK_DIALOG_DESTROY_WITH_PARENT), 00225 GTK_MESSAGE_WARNING, 00226 GTK_BUTTONS_NONE, NULL); 00227 gtk_message_dialog_set_markup (GTK_MESSAGE_DIALOG (dialog), str); 00228 gtk_dialog_add_buttons (GTK_DIALOG (dialog), 00229 _("Close _without saving"), GTK_RESPONSE_NO, 00230 GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, 00231 GTK_STOCK_SAVE, GTK_RESPONSE_YES, 00232 NULL); 00233 gtk_dialog_set_default_response (GTK_DIALOG (dialog), GTK_RESPONSE_YES); 00234 00235 /* Set the alternative button order (ok, cancel, help) for other systems */ 00236 gtk_dialog_set_alternative_button_order(GTK_DIALOG(dialog), 00237 GTK_RESPONSE_YES, 00238 GTK_RESPONSE_NO, 00239 GTK_RESPONSE_CANCEL, 00240 -1); 00241 00242 switch (gtk_dialog_run (GTK_DIALOG (dialog))) 00243 { 00244 case GTK_RESPONSE_NO: 00245 { 00246 rv = GUI_DIALOG_CLOSE_CONFIRM_NOSAVE; 00247 break; 00248 } 00249 case GTK_RESPONSE_YES: 00250 { 00251 rv = GUI_DIALOG_CLOSE_CONFIRM_SAVE; 00252 break; 00253 } 00254 case GTK_RESPONSE_CANCEL: 00255 default: 00256 { 00257 rv = GUI_DIALOG_CLOSE_CONFIRM_CANCEL; 00258 break; 00259 } 00260 } 00261 gtk_widget_destroy (dialog); 00262 return rv; 00263 } 00264 00265 /* ---------------------------------------------- */ 00266 /* Caller must g_free() the returned filename.*/ 00267 gchar * 00268 ghid_dialog_file_select_open (gchar * title, gchar ** path, gchar * shortcuts) 00269 { 00270 GtkWidget *dialog; 00271 gchar *result = NULL, *folder, *seed; 00272 GHidPort *out = &ghid_port; 00273 GtkFileFilter *no_filter; 00274 00275 dialog = gtk_file_chooser_dialog_new (title, 00276 GTK_WINDOW (out->top_window), 00277 GTK_FILE_CHOOSER_ACTION_OPEN, 00278 GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, 00279 GTK_STOCK_OK, GTK_RESPONSE_OK, 00280 NULL); 00281 00282 gtk_dialog_set_default_response (GTK_DIALOG (dialog), GTK_RESPONSE_OK); 00283 00284 /* add a default filter for not filtering files */ 00285 no_filter = gtk_file_filter_new (); 00286 gtk_file_filter_set_name (no_filter, "all"); 00287 gtk_file_filter_add_pattern (no_filter, "*.*"); 00288 gtk_file_filter_add_pattern (no_filter, "*"); 00289 gtk_file_chooser_add_filter (GTK_FILE_CHOOSER (dialog), no_filter); 00290 00291 /* in case we have a dialog for loading a footprint file */ 00292 if (strcmp (title, _("Load element to buffer")) == 0) 00293 { 00294 /* add a filter for footprint files */ 00295 GtkFileFilter *fp_filter; 00296 fp_filter = gtk_file_filter_new (); 00297 gtk_file_filter_set_name (fp_filter, "fp"); 00298 gtk_file_filter_add_mime_type (fp_filter, "application/x-pcb-footprint"); 00299 gtk_file_filter_add_pattern (fp_filter, "*.fp"); 00300 gtk_file_filter_add_pattern (fp_filter, "*.FP"); 00301 gtk_file_chooser_add_filter (GTK_FILE_CHOOSER (dialog), fp_filter); 00302 } 00303 00304 /* in case we have a dialog for loading a layout file */ 00305 if ((strcmp (title, _("Load layout file")) == 0) 00306 || (strcmp (title, _("Load layout file to buffer")) == 0)) 00307 { 00308 /* add a filter for layout files */ 00309 GtkFileFilter *pcb_filter; 00310 pcb_filter = gtk_file_filter_new (); 00311 gtk_file_filter_set_name (pcb_filter, "pcb"); 00312 gtk_file_filter_add_mime_type (pcb_filter, "application/x-pcb-layout"); 00313 gtk_file_filter_add_pattern (pcb_filter, "*.pcb"); 00314 gtk_file_filter_add_pattern (pcb_filter, "*.PCB"); 00315 gtk_file_chooser_add_filter (GTK_FILE_CHOOSER (dialog), pcb_filter); 00316 } 00317 00318 /* in case we have a dialog for loading a netlist file */ 00319 if (strcmp (title, _("Load netlist file")) == 0) 00320 { 00321 /* add a filter for netlist files */ 00322 GtkFileFilter *net_filter; 00323 net_filter = gtk_file_filter_new (); 00324 gtk_file_filter_set_name (net_filter, "netlist"); 00325 gtk_file_filter_add_mime_type (net_filter, "application/x-pcb-netlist"); 00326 gtk_file_filter_add_pattern (net_filter, "*.net"); 00327 gtk_file_filter_add_pattern (net_filter, "*.NET"); 00328 gtk_file_chooser_add_filter (GTK_FILE_CHOOSER (dialog), net_filter); 00329 } 00330 00331 if (path && *path) 00332 gtk_file_chooser_set_current_folder (GTK_FILE_CHOOSER (dialog), *path); 00333 else 00334 { 00335 gchar *default_path; 00336 default_path = g_get_current_dir(); 00337 gtk_file_chooser_set_current_folder (GTK_FILE_CHOOSER (dialog), default_path); 00338 g_free(default_path); 00339 } 00340 00341 if (shortcuts && *shortcuts) 00342 { 00343 folder = g_strdup (shortcuts); 00344 seed = folder; 00345 while ((folder = strtok (seed, ":")) != NULL) 00346 { 00347 gtk_file_chooser_add_shortcut_folder (GTK_FILE_CHOOSER (dialog), 00348 folder, NULL); 00349 seed = NULL; 00350 } 00351 g_free (folder); 00352 } 00353 00354 if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_OK) 00355 { 00356 result = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (dialog)); 00357 folder = 00358 gtk_file_chooser_get_current_folder (GTK_FILE_CHOOSER (dialog)); 00359 if (folder && path) 00360 { 00361 dup_string (path, folder); 00362 g_free (folder); 00363 } 00364 } 00365 gtk_widget_destroy (dialog); 00366 00367 00368 return result; 00369 } 00370 00371 00372 /* ---------------------------------------------- */ 00373 /* Caller must g_slist_free() the returned list .*/ 00374 GSList * 00375 ghid_dialog_file_select_multiple(gchar * title, gchar ** path, gchar * shortcuts) 00376 { 00377 GtkWidget *dialog; 00378 GSList *result = NULL; 00379 gchar *folder, *seed; 00380 GHidPort *out = &ghid_port; 00381 GtkFileFilter *no_filter; 00382 00383 dialog = gtk_file_chooser_dialog_new (title, 00384 GTK_WINDOW (out->top_window), 00385 GTK_FILE_CHOOSER_ACTION_OPEN, 00386 GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, 00387 GTK_STOCK_OK, GTK_RESPONSE_OK, 00388 NULL); 00389 00390 gtk_dialog_set_default_response (GTK_DIALOG (dialog), GTK_RESPONSE_OK); 00391 00392 gtk_file_chooser_set_select_multiple(GTK_FILE_CHOOSER (dialog), TRUE); 00393 00394 /* add a default filter for not filtering files */ 00395 no_filter = gtk_file_filter_new (); 00396 gtk_file_filter_set_name (no_filter, "all"); 00397 gtk_file_filter_add_pattern (no_filter, "*.*"); 00398 gtk_file_filter_add_pattern (no_filter, "*"); 00399 gtk_file_chooser_add_filter (GTK_FILE_CHOOSER (dialog), no_filter); 00400 00401 /* in case we have a dialog for loading schematic files */ 00402 if (strcmp (title, _("Load schematics")) == 0) 00403 { 00404 /* add a filter for schematic files */ 00405 GtkFileFilter *sch_filter; 00406 sch_filter = gtk_file_filter_new (); 00407 gtk_file_filter_set_name (sch_filter, "sch"); 00408 gtk_file_filter_add_mime_type (sch_filter, "application/x-geda-schematic"); 00409 gtk_file_filter_add_pattern (sch_filter, "*.sch"); 00410 gtk_file_filter_add_pattern (sch_filter, "*.SCH"); 00411 gtk_file_chooser_add_filter (GTK_FILE_CHOOSER (dialog), sch_filter); 00412 } 00413 00414 if (path && *path) 00415 gtk_file_chooser_set_current_folder (GTK_FILE_CHOOSER (dialog), *path); 00416 else 00417 { 00418 gchar *default_path; 00419 default_path = g_get_current_dir(); 00420 gtk_file_chooser_set_current_folder (GTK_FILE_CHOOSER (dialog), default_path); 00421 g_free(default_path); 00422 } 00423 00424 if (shortcuts && *shortcuts) 00425 { 00426 folder = g_strdup (shortcuts); 00427 seed = folder; 00428 while ((folder = strtok (seed, ":")) != NULL) 00429 { 00430 gtk_file_chooser_add_shortcut_folder (GTK_FILE_CHOOSER (dialog), 00431 folder, NULL); 00432 seed = NULL; 00433 } 00434 g_free (folder); 00435 } 00436 00437 if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_OK) 00438 { 00439 result = gtk_file_chooser_get_filenames (GTK_FILE_CHOOSER (dialog)); 00440 folder = 00441 gtk_file_chooser_get_current_folder (GTK_FILE_CHOOSER (dialog)); 00442 if (folder && path) 00443 { 00444 dup_string (path, folder); 00445 g_free (folder); 00446 } 00447 } 00448 gtk_widget_destroy (dialog); 00449 00450 00451 return result; 00452 } 00453 00454 00455 /* ---------------------------------------------- */ 00456 /* Caller must g_free() the returned filename. */ 00457 gchar * 00458 ghid_dialog_file_select_save (gchar * title, gchar ** path, gchar * file, 00459 gchar * shortcuts) 00460 { 00461 GtkWidget *dialog; 00462 gchar *result = NULL, *folder, *seed; 00463 GHidPort *out = &ghid_port; 00464 00465 dialog = gtk_file_chooser_dialog_new (title, 00466 GTK_WINDOW (out->top_window), 00467 GTK_FILE_CHOOSER_ACTION_SAVE, 00468 GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, 00469 GTK_STOCK_OK, GTK_RESPONSE_OK, 00470 NULL); 00471 00472 gtk_file_chooser_set_do_overwrite_confirmation (GTK_FILE_CHOOSER (dialog), 00473 TRUE); 00474 gtk_dialog_set_default_response (GTK_DIALOG (dialog), GTK_RESPONSE_OK); 00475 00476 if (path && *path && **path) 00477 gtk_file_chooser_set_current_folder (GTK_FILE_CHOOSER (dialog), *path); 00478 else 00479 { 00480 gchar *default_path; 00481 default_path = g_get_current_dir(); 00482 gtk_file_chooser_set_current_folder (GTK_FILE_CHOOSER (dialog), default_path); 00483 g_free(default_path); 00484 } 00485 00486 if (file && *file) 00487 { 00488 gtk_file_chooser_set_current_name (GTK_FILE_CHOOSER (dialog), 00489 g_path_get_basename(file)); 00490 gtk_file_chooser_set_current_folder (GTK_FILE_CHOOSER (dialog), 00491 g_path_get_dirname (file)); 00492 } 00493 00494 if (shortcuts && *shortcuts) 00495 { 00496 folder = g_strdup (shortcuts); 00497 seed = folder; 00498 while ((folder = strtok (seed, ":")) != NULL) 00499 { 00500 gtk_file_chooser_add_shortcut_folder (GTK_FILE_CHOOSER (dialog), 00501 folder, NULL); 00502 seed = NULL; 00503 } 00504 g_free (folder); 00505 } 00506 if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_OK) 00507 { 00508 result = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (dialog)); 00509 folder = 00510 gtk_file_chooser_get_current_folder (GTK_FILE_CHOOSER (dialog)); 00511 if (folder && path) 00512 { 00513 dup_string (path, folder); 00514 g_free (folder); 00515 } 00516 } 00517 gtk_widget_destroy (dialog); 00518 00519 00520 return result; 00521 } 00522 00523 00524 /* ---------------------------------------------- */ 00525 /* how many files and directories to keep for the shortcuts */ 00526 #define NHIST 8 00527 typedef struct ghid_file_history_struct 00528 { 00529 /* 00530 * an identifier as to which recent files pool this is. For example 00531 * "boards", "eco", "netlists", etc. 00532 */ 00533 char * id; 00534 00535 /* 00536 * the array of files or directories 00537 */ 00538 char * history[NHIST]; 00539 } ghid_file_history; 00540 00541 static int n_recent_dirs = 0; 00542 static ghid_file_history * recent_dirs = NULL; 00543 00544 /* ---------------------------------------------- */ 00545 /* Caller must g_free() the returned filename. */ 00546 gchar * 00547 ghid_fileselect (const char *title, const char *descr, 00548 char *default_file, char *default_ext, 00549 const char *history_tag, int flags) 00550 { 00551 GtkWidget *dialog; 00552 gchar *result = NULL; 00553 GHidPort *out = &ghid_port; 00554 gchar *path = NULL, *base = NULL; 00555 int history_pool = -1; 00556 int i; 00557 00558 if (history_tag && *history_tag) 00559 { 00560 /* 00561 * I used a simple linear search here because the number of 00562 * entries in the array is likely to be quite small (5, maybe 10 at 00563 * the absolute most) and this function is used when pulling up 00564 * a file dialog box instead of something called over and over 00565 * again as part of moving elements or autorouting. So, keep it 00566 * simple.... 00567 */ 00568 history_pool = 0; 00569 while (history_pool < n_recent_dirs && 00570 strcmp (recent_dirs[history_pool].id, history_tag) != 0) 00571 { 00572 history_pool++; 00573 } 00574 00575 /* 00576 * If we counted all the way to n_recent_dirs, that means we 00577 * didn't find our entry 00578 */ 00579 if (history_pool >= n_recent_dirs) 00580 { 00581 n_recent_dirs++; 00582 00583 recent_dirs = (ghid_file_history *)realloc (recent_dirs, 00584 n_recent_dirs * sizeof (ghid_file_history)); 00585 00586 if (recent_dirs == NULL) 00587 { 00588 fprintf (stderr, "%s(): realloc failed\n", __FUNCTION__); 00589 exit (1); 00590 } 00591 00592 recent_dirs[history_pool].id = strdup (history_tag); 00593 00594 /* Initialize the entries in our history list to all be NULL */ 00595 for (i = 0; i < NHIST; i++) 00596 { 00597 recent_dirs[history_pool].history[i] = NULL; 00598 } 00599 } 00600 } 00601 00602 if (default_file && *default_file) 00603 { 00604 path = g_path_get_dirname (default_file); 00605 base = g_path_get_basename (default_file); 00606 } 00607 00608 dialog = gtk_file_chooser_dialog_new (title, 00609 GTK_WINDOW (out->top_window), 00610 (flags & HID_FILESELECT_READ) ? 00611 GTK_FILE_CHOOSER_ACTION_OPEN : 00612 GTK_FILE_CHOOSER_ACTION_SAVE, 00613 GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, 00614 GTK_STOCK_OK, GTK_RESPONSE_OK, 00615 NULL); 00616 00617 gtk_dialog_set_default_response (GTK_DIALOG (dialog), GTK_RESPONSE_OK); 00618 00619 if (path && *path ) 00620 { 00621 gtk_file_chooser_set_current_folder (GTK_FILE_CHOOSER (dialog), path); 00622 g_free (path); 00623 } 00624 else 00625 { 00626 gchar *default_path; 00627 default_path = g_get_current_dir(); 00628 gtk_file_chooser_set_current_folder (GTK_FILE_CHOOSER (dialog), default_path); 00629 g_free(default_path); 00630 } 00631 00632 if (base && *base) 00633 { 00634 /* default file is only supposed to be for writing, not reading */ 00635 if (!(flags & HID_FILESELECT_READ)) 00636 { 00637 gtk_file_chooser_set_current_name (GTK_FILE_CHOOSER (dialog), base); 00638 } 00639 g_free (base); 00640 } 00641 00642 for (i = 0; i < NHIST && recent_dirs[history_pool].history[i] != NULL ; i++) 00643 { 00644 gtk_file_chooser_add_shortcut_folder (GTK_FILE_CHOOSER (dialog), 00645 recent_dirs[history_pool].history[i], 00646 NULL); 00647 } 00648 00649 if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_OK) 00650 { 00651 result = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (dialog)); 00652 if (result != NULL) 00653 path = g_path_get_dirname (result); 00654 else 00655 path = NULL; 00656 00657 /* update the history list */ 00658 if (path != NULL) 00659 { 00660 char *tmps, *tmps2; 00661 int k = 0; 00662 00663 /* 00664 * Put this at the top of the list and bump everything else 00665 * down but skip any old entry of this directory 00666 * 00667 */ 00668 while ( k < NHIST && 00669 recent_dirs[history_pool].history[k] != NULL && 00670 strcmp ( recent_dirs[history_pool].history[k], path) == 0) 00671 { 00672 k++; 00673 } 00674 tmps = recent_dirs[history_pool].history[k]; 00675 recent_dirs[history_pool].history[0] = path; 00676 for (i = 1 ; i < NHIST ; i++) 00677 { 00678 /* store our current entry, but skip duplicates */ 00679 while (i + k < NHIST && 00680 recent_dirs[history_pool].history[i + k] != NULL && 00681 strcmp ( recent_dirs[history_pool].history[i + k], path) == 0) 00682 { 00683 k++; 00684 } 00685 00686 if (i + k < NHIST) 00687 tmps2 = recent_dirs[history_pool].history[i + k]; 00688 else 00689 tmps2 = NULL; 00690 00691 /* move down the one we stored last time */ 00692 recent_dirs[history_pool].history[i] = tmps; 00693 00694 /* and remember the displace entry */ 00695 tmps = tmps2; 00696 } 00697 00698 /* 00699 * the last one has fallen off the end of the history list 00700 * so we need to free() it. 00701 */ 00702 if (tmps) 00703 { 00704 free (tmps); 00705 } 00706 } 00707 00708 #ifdef DEBUG 00709 printf ("\n\n-----\n\n"); 00710 for (i = 0 ; i < NHIST ; i++) 00711 { 00712 printf ("After update recent_dirs[%d].history[%d] = \"%s\"\n", 00713 history_pool, i, recent_dirs[history_pool].history[i] != NULL ? 00714 recent_dirs[history_pool].history[i] : "NULL"); 00715 } 00716 #endif 00717 00718 } 00719 gtk_widget_destroy (dialog); 00720 00721 00722 return result; 00723 } 00724