pcb 4.1.1
An interactive printed circuit board layout editor.

gui-dialog.c

Go to the documentation of this file.
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