void XAP_UnixDialog_FileOpenSaveAs::fileTypeChanged(GtkWidget * w)
{
    if (!m_bSave)
        return;

    UT_sint32 nFileType = XAP_comboBoxGetActiveInt(GTK_COMBO_BOX(w));
    UT_DEBUGMSG(("File type widget is %p filetype number is %d \n",w,nFileType));
    // I have no idea for 0, but XAP_DIALOG_FILEOPENSAVEAS_FILE_TYPE_AUTO
    // definitely means "skip this"
    if((nFileType == 0) || (nFileType == XAP_DIALOG_FILEOPENSAVEAS_FILE_TYPE_AUTO))
    {
        return;
    }

    gchar * filename = gtk_file_chooser_get_filename(m_FC);
    UT_String sFileName = filename;
    FREEP(filename);

    UT_String sSuffix = m_szSuffixes[nFileType-1];
    sSuffix = sSuffix.substr(1,sSuffix.length()-1);
    UT_sint32 i = 0;
    bool bFoundComma = false;
    for(i=0; i< static_cast<UT_sint32>(sSuffix.length()); i++)
    {
        if(sSuffix[i] == ';')
        {
            bFoundComma = true;
            break;
        }
    }
    if(bFoundComma)
    {
        sSuffix = sSuffix.substr(0,i);
    }

//
// Hard code a suffix
//
    if(strstr(sSuffix.c_str(),"gz") != NULL)
    {
        sSuffix = ".zabw";
    }
    bool bFoundSuffix = false;
    for(i= sFileName.length()-1; i> 0; i--)
    {
        if(sFileName[i] == '.')
        {
            bFoundSuffix = true;
            break;
        }
    }
    if(!bFoundSuffix)
    {
        return;
    }
    sFileName = sFileName.substr(0,i);
    sFileName += sSuffix;

    gtk_file_chooser_set_current_name(m_FC, UT_basename(sFileName.c_str()));
}
void AP_UnixDialog_PageSetup::event_MarginUnitsChanged (void)
{
	UT_Dimension mu =  (UT_Dimension)XAP_comboBoxGetActiveInt(GTK_COMBO_BOX(m_optionMarginUnits));

	float top, bottom, left, right, header, footer;

	top    = gtk_spin_button_get_value (GTK_SPIN_BUTTON (m_spinMarginTop));
	bottom = gtk_spin_button_get_value (GTK_SPIN_BUTTON (m_spinMarginBottom));
	left   = gtk_spin_button_get_value (GTK_SPIN_BUTTON (m_spinMarginLeft));
	right  = gtk_spin_button_get_value (GTK_SPIN_BUTTON (m_spinMarginRight));
	header = gtk_spin_button_get_value (GTK_SPIN_BUTTON (m_spinMarginHeader));
	footer = gtk_spin_button_get_value (GTK_SPIN_BUTTON (m_spinMarginFooter));

	top = UT_convertDimensions (top,    last_margin_unit, mu);
	bottom = UT_convertDimensions (bottom, last_margin_unit, mu);
	left = UT_convertDimensions (left,   last_margin_unit, mu);
	right = UT_convertDimensions (right,  last_margin_unit, mu);
	header = UT_convertDimensions (header, last_margin_unit, mu);
	footer = UT_convertDimensions (footer, last_margin_unit, mu);

	last_margin_unit = mu;

	gtk_spin_button_set_value (GTK_SPIN_BUTTON (m_spinMarginTop), top);
	gtk_spin_button_set_value (GTK_SPIN_BUTTON (m_spinMarginBottom), bottom);
	gtk_spin_button_set_value (GTK_SPIN_BUTTON (m_spinMarginLeft), left);
	gtk_spin_button_set_value (GTK_SPIN_BUTTON (m_spinMarginRight), right);
	gtk_spin_button_set_value (GTK_SPIN_BUTTON (m_spinMarginHeader), header);
	gtk_spin_button_set_value (GTK_SPIN_BUTTON (m_spinMarginFooter), footer);
}
void AP_UnixDialog_Paragraph::event_ComboBoxChanged(GtkWidget * widget)
{
	UT_ASSERT(widget && GTK_IS_COMBO_BOX(widget));

	
	tControl id = (tControl) GPOINTER_TO_INT(g_object_get_data(G_OBJECT(widget),
								   WIDGET_ID_TAG));

	UT_uint32 value = (UT_uint32)XAP_comboBoxGetActiveInt(GTK_COMBO_BOX(widget));

	_setMenuItemValue(id, value);
}
void AP_UnixDialog_PageSetup::event_PageSizeChanged (fp_PageSize::Predefined pd)
{
	fp_PageSize ps(pd);
	if( TRUE != gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (m_radioPagePortrait)))
	{
		ps.setLandscape();
	}
	m_PageSize = ps;

	// change the units in the dialog, too.
	UT_Dimension new_units = ps.getDims();
	setPageUnits(new_units);
	XAP_comboBoxSetActiveFromIntCol(GTK_COMBO_BOX (m_optionPageUnits), 1, new_units);

	float w, h;

	w = ps.Width (new_units);
	h = ps.Height (new_units);
//  if( !ps.isPortrait())
//  {
//	  h = ps.Width (new_units);
//	  w = ps.Height (new_units);
//  }

  if (true /* fp_PageSize::psCustom != pd */)
  {
	  // set entry values for a non-custom pagesize
	  gchar * val;
	  XAP_GtkSignalBlocker b(G_OBJECT(m_entryPageWidth), m_iEntryPageWidthID);
	  XAP_GtkSignalBlocker c(G_OBJECT(m_entryPageHeight), m_iEntryPageHeightID);
	  val = g_strdup_printf (FMT_STRING, w);
 	  _setWidth(val);
	  gtk_entry_set_text (GTK_ENTRY (m_entryPageWidth), val);
	  g_free (val);

	  val = g_strdup_printf (FMT_STRING, h);
	  _setHeight(val);
	  gtk_entry_set_text (GTK_ENTRY (m_entryPageHeight), val);
	  g_free (val);
  }
  else
  {																	
	  UT_Dimension dim = (UT_Dimension)XAP_comboBoxGetActiveInt(GTK_COMBO_BOX(m_optionPageUnits));
	  ps.Set(atof(gtk_entry_get_text(GTK_ENTRY(m_entryPageWidth))),
			 atof(gtk_entry_get_text(GTK_ENTRY(m_entryPageHeight))),
			 dim);
  }
}
void AP_UnixDialog_PageSetup::event_PageUnitsChanged (void)
{
	UT_Dimension pu = static_cast<UT_Dimension>(XAP_comboBoxGetActiveInt(
													GTK_COMBO_BOX(m_optionPageUnits)));

	double width, height;

	fp_PageSize ps = m_PageSize;

	// convert values  
	width  = static_cast<double>(ps.Width (pu));
	height = static_cast<double>(ps.Height (pu));

	if(m_PageSize.isPortrait())
	{
	    m_PageSize.Set(width, height, pu);
	}
	else
	{
	    m_PageSize.Set(height,width, pu);
	}
	// set values
	gchar * val;
	{
	  XAP_GtkSignalBlocker b(G_OBJECT(m_entryPageWidth), m_iEntryPageWidthID);
	  val = g_strdup_printf (FMT_STRING, static_cast<float>(width));
	  gtk_entry_set_text (GTK_ENTRY (m_entryPageWidth), val);
	  g_free (val);
	}
	{
	  XAP_GtkSignalBlocker C(G_OBJECT(m_entryPageHeight), m_iEntryPageHeightID);
	  val = g_strdup_printf (FMT_STRING, static_cast<float>(height));
	  gtk_entry_set_text (GTK_ENTRY (m_entryPageHeight), val);
	  g_free (val);
	}
	setPageUnits(pu);
}
static void s_MainLevel_changed(GtkWidget * wid, AP_UnixDialog_FormatTOC * me )
{
	UT_sint32 iLevel = XAP_comboBoxGetActiveInt(GTK_COMBO_BOX(wid));
	me->setMainLevel(iLevel);
}
void XAP_UnixDialog_FileOpenSaveAs::runModal(XAP_Frame * pFrame)
{
    const XAP_StringSet * pSS = m_pApp->getStringSet();
    std::string szTitle;
    std::string szFileTypeLabel;

    switch (m_id)
    {
    case XAP_DIALOG_ID_INSERT_PICTURE:
    {
        pSS->getValueUTF8(XAP_STRING_ID_DLG_IP_Title, szTitle);
        pSS->getValueUTF8(XAP_STRING_ID_DLG_FOSA_FileOpenTypeLabel, szFileTypeLabel);
        m_bSave = false;
        break;
    }
    case XAP_DIALOG_ID_FILE_OPEN:
    {
        pSS->getValueUTF8(XAP_STRING_ID_DLG_FOSA_OpenTitle,szTitle);
        pSS->getValueUTF8(XAP_STRING_ID_DLG_FOSA_FileOpenTypeLabel,szFileTypeLabel);
        m_bSave = false;
        break;
    }
    case XAP_DIALOG_ID_FILE_IMPORT:
    {
        pSS->getValueUTF8(XAP_STRING_ID_DLG_FOSA_ImportTitle,szTitle);
        pSS->getValueUTF8(XAP_STRING_ID_DLG_FOSA_FileOpenTypeLabel,szFileTypeLabel);
        m_bSave = false;
        break;
    }
    case XAP_DIALOG_ID_INSERTMATHML:
    {
        pSS->getValueUTF8(XAP_STRING_ID_DLG_FOSA_InsertMath,szTitle);
        pSS->getValueUTF8(XAP_STRING_ID_DLG_FOSA_FileInsertMath,szFileTypeLabel);
        m_bSave = false;
        break;
    }
    case XAP_DIALOG_ID_INSERTOBJECT:
    {
        pSS->getValueUTF8(XAP_STRING_ID_DLG_FOSA_InsertObject,szTitle);
        pSS->getValueUTF8(XAP_STRING_ID_DLG_FOSA_FileInsertObject,szFileTypeLabel);
        m_bSave = false;
        break;
    }
    case XAP_DIALOG_ID_INSERT_FILE:
    {
        pSS->getValueUTF8(XAP_STRING_ID_DLG_FOSA_InsertTitle,szTitle);
        pSS->getValueUTF8(XAP_STRING_ID_DLG_FOSA_FileOpenTypeLabel,szFileTypeLabel);
        m_bSave = false;
        break;
    }
    case XAP_DIALOG_ID_FILE_SAVEAS:
    case XAP_DIALOG_ID_FILE_SAVE_IMAGE:
    {
        pSS->getValueUTF8(XAP_STRING_ID_DLG_FOSA_SaveAsTitle,szTitle);
        pSS->getValueUTF8(XAP_STRING_ID_DLG_FOSA_FileSaveTypeLabel,szFileTypeLabel);
        m_bSave = true;
        break;
    }
    case XAP_DIALOG_ID_FILE_EXPORT:
    {
        pSS->getValueUTF8(XAP_STRING_ID_DLG_FOSA_ExportTitle,szTitle);
        pSS->getValueUTF8(XAP_STRING_ID_DLG_FOSA_FileSaveTypeLabel,szFileTypeLabel);
        m_bSave = true;
        break;
    }
    case XAP_DIALOG_ID_PRINTTOFILE:
    {
        pSS->getValueUTF8(XAP_STRING_ID_DLG_FOSA_PrintToFileTitle,szTitle);
        pSS->getValueUTF8(XAP_STRING_ID_DLG_FOSA_FilePrintTypeLabel,szFileTypeLabel);
        m_bSave = true;
        break;
    }
    case XAP_DIALOG_ID_RECORDTOFILE:
    {
        pSS->getValueUTF8(XAP_STRING_ID_DLG_FOSA_RecordToFileTitle,szTitle);
        pSS->getValueUTF8(XAP_STRING_ID_DLG_FOSA_RecordToFileLabel,szFileTypeLabel);
        m_bSave = true;
        break;
    }
    case XAP_DIALOG_ID_REPLAYFROMFILE:
    {
        pSS->getValueUTF8(XAP_STRING_ID_DLG_FOSA_ReplayFromFileTitle,szTitle);
        pSS->getValueUTF8(XAP_STRING_ID_DLG_FOSA_ReplayFromFileLabel,szFileTypeLabel);
        m_bSave = false;
        break;
    }
    default:
        UT_ASSERT(UT_SHOULD_NOT_HAPPEN);
        m_bSave = false;
        break;
    }

    // NOTE: we use our string mechanism to localize the dialog's
    // NOTE: title and the error/confirmation message boxes.  we
    // NOTE: let GTK take care of the localization of the actual
    // NOTE: buttons and labels on the FileSelection dialog.

    // Get the GtkWindow of the parent frame
    XAP_UnixFrameImpl * pUnixFrameImpl = static_cast<XAP_UnixFrameImpl *>(pFrame->getFrameImpl());
    GtkWidget * parent = pUnixFrameImpl->getTopLevelWindow();

    if(parent && (GTK_WIDGET_TOPLEVEL(parent) != TRUE))
    {
        parent = gtk_widget_get_toplevel (parent);
    }

#if defined(EMBEDDED_TARGET) && EMBEDDED_TARGET == EMBEDDED_TARGET_HILDON
    m_FC = GTK_FILE_CHOOSER( hildon_file_chooser_dialog_new(GTK_WINDOW(parent),
                             (!m_bSave ? GTK_FILE_CHOOSER_ACTION_OPEN : GTK_FILE_CHOOSER_ACTION_SAVE))
                           );
#else
    m_FC = GTK_FILE_CHOOSER( gtk_file_chooser_dialog_new (szTitle.c_str(),
                             GTK_WINDOW(parent),
                             (!m_bSave ? GTK_FILE_CHOOSER_ACTION_OPEN : GTK_FILE_CHOOSER_ACTION_SAVE),
                             GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
                             (m_bSave ? GTK_STOCK_SAVE : GTK_STOCK_OPEN), GTK_RESPONSE_ACCEPT,
                             (gchar*)NULL)
                           );
#endif

    gtk_file_chooser_set_local_only(m_FC, FALSE);

    abiSetupModalDialog(GTK_DIALOG(m_FC), pFrame, this, GTK_RESPONSE_ACCEPT);
    GtkWidget * filetypes_pulldown = NULL;

    std::string s;

    /*
      Add a drop-down list of known types to facilitate a file-types selection.
      We store an indexer in the user data for each menu item in the popup, so
      we can read the type we need to return.
    */

    if (m_id == XAP_DIALOG_ID_INSERT_PICTURE)
    {
        GtkWidget * preview = createDrawingArea ();
        gtk_widget_show (preview);
        m_preview = preview;
        gtk_widget_set_size_request (preview, PREVIEW_WIDTH, PREVIEW_HEIGHT);

        // place the preview area inside a container to get a nice border
        GtkWidget * preview_hbox = gtk_hbox_new(FALSE, 0);
        gtk_container_set_border_width  (GTK_CONTAINER(preview_hbox), 4);
        gtk_box_pack_start(GTK_BOX(preview_hbox), preview, TRUE, TRUE, 0);

        // attach the preview area to the dialog
        gtk_file_chooser_set_preview_widget (m_FC, preview_hbox);
        gtk_file_chooser_set_preview_widget_active (m_FC, true);

        // connect some signals
        g_signal_connect (m_FC, "update_preview",
                          G_CALLBACK (file_selection_changed), static_cast<gpointer>(this));

        g_signal_connect (preview, "expose_event",
                          G_CALLBACK (s_preview_exposed), static_cast<gpointer>(this));
    }

#if defined(EMBEDDED_TARGET) && EMBEDDED_TARGET == EMBEDDED_TARGET_HILDON
    filetypes_pulldown = gtk_combo_box_new();
    gtk_widget_show(filetypes_pulldown);
    GtkWidget * pulldown_hbox = filetypes_pulldown;
#else
    // hbox for our pulldown menu (GTK does its pulldown this way */
    GtkWidget * pulldown_hbox = gtk_hbox_new(FALSE, 15);
    gtk_widget_show(pulldown_hbox);

    // pulldown label
    GtkWidget * filetypes_label = gtk_label_new_with_mnemonic(convertMnemonics(szFileTypeLabel).c_str());
    gtk_label_set_justify(GTK_LABEL(filetypes_label), GTK_JUSTIFY_RIGHT);
    gtk_misc_set_alignment(GTK_MISC(filetypes_label), 1.0, 0.5);
    gtk_widget_show(filetypes_label);
    gtk_box_pack_start(GTK_BOX(pulldown_hbox), filetypes_label, TRUE, TRUE, 0);

    // pulldown menu
    filetypes_pulldown = gtk_combo_box_new();
    gtk_widget_show(filetypes_pulldown);
    gtk_box_pack_end(GTK_BOX(pulldown_hbox), filetypes_pulldown, TRUE, TRUE, 0);
    gtk_label_set_mnemonic_widget(GTK_LABEL(filetypes_label), filetypes_pulldown);
#endif
    //
    // add the filters to the dropdown list
    //
    GtkComboBox* combo = GTK_COMBO_BOX(filetypes_pulldown);
    XAP_makeGtkComboBoxText(combo, G_TYPE_INT);

    // Auto-detect is always an option, but a special one, so we use
    // a pre-defined constant for the type, and don't use the user-supplied
    // types yet.
    pSS->getValueUTF8(XAP_STRING_ID_DLG_FOSA_FileTypeAutoDetect,s);
    XAP_appendComboBoxTextAndInt(combo, s.c_str(), XAP_DIALOG_FILEOPENSAVEAS_FILE_TYPE_AUTO);

    UT_sint32 activeItemIndex = -1;

    // add list items
    {
        UT_ASSERT(g_strv_length((gchar **) m_szSuffixes) == g_strv_length((gchar **) m_szDescriptions));

        // measure one list, they should all be the same length
        UT_uint32 end = g_strv_length((gchar **) m_szDescriptions);

        for (UT_uint32 i = 0; i < end; i++)
        {
            // If this type is default, save its index (i) for later use
            if (m_nTypeList[i] == m_nDefaultFileType)
                activeItemIndex = i;

            XAP_appendComboBoxTextAndInt(combo, m_szDescriptions[i], m_nTypeList[i]);
//
// Attach a callback when it is activated to change the file suffix
//
//			g_signal_connect(G_OBJECT(thismenuitem), "activate",
//							 G_CALLBACK(s_filetypechanged),
//							 reinterpret_cast<gpointer>(this));
        }
    }

    m_wFileTypes_PullDown = filetypes_pulldown;
    // dialog; open dialog always does auto-detect
    // TODO: should this also apply to the open dialog?
    if (m_id == XAP_DIALOG_ID_FILE_SAVEAS || m_id == XAP_DIALOG_ID_FILE_SAVE_IMAGE)
    {
        gtk_combo_box_set_active(combo, activeItemIndex + 1);
    }
    else
    {
        gtk_combo_box_set_active(combo, 0);
    }

#if defined(EMBEDDED_TARGET) && EMBEDDED_TARGET == EMBEDDED_TARGET_HILDON
    hildon_file_chooser_dialog_add_extra ((HildonFileChooserDialog*)m_FC,
                                          pulldown_hbox);
#else
    gtk_file_chooser_set_extra_widget (GTK_FILE_CHOOSER(m_FC), pulldown_hbox);
#endif

    // connect the signals for OK and CANCEL and the requisite clean-close signals
    g_signal_connect(G_OBJECT(m_FC),
                     "delete-event",
                     G_CALLBACK(s_delete_clicked),
                     this);

    g_signal_connect(G_OBJECT(m_FC),
                     "key_press_event",
                     G_CALLBACK(fsel_key_event), &m_answer);

    g_signal_connect (G_OBJECT (m_FC),
                      "response",
                      G_CALLBACK(dialog_response), &m_answer);

    g_signal_connect (G_OBJECT (m_FC),
                      "file-activated",
                      G_CALLBACK(s_file_activated), &m_answer);

    g_signal_connect(G_OBJECT(filetypes_pulldown), "changed",
                     G_CALLBACK(s_filetypechanged),
                     reinterpret_cast<gpointer>(this));

    // use the persistence info and/or the suggested filename
    // to properly seed the dialog.

    gchar * szPersistDirectory = NULL;	// we must g_free this

    if (!m_szInitialPathname || !*m_szInitialPathname)
    {
        // the caller did not supply initial pathname
        // (or supplied an empty one).  see if we have
        // some persistent info.

        UT_ASSERT(!m_bSuggestName);
        if (m_szPersistPathname)
        {
            // we have a pathname from a previous use,
            // extract the directory portion and start
            // the dialog there (but without a filename).

            szPersistDirectory = UT_go_dirname_from_uri(m_szPersistPathname, FALSE);
            gtk_file_chooser_set_current_folder_uri(m_FC, szPersistDirectory);
        }
        else
        {
            // no initial pathname given and we don't have
            // a pathname from a previous use, so just let
            // it come up in the current working directory.
        }
    }
    else
    {
        // we have an initial pathname (the name of the document
        // in the frame that we were invoked on).  if the caller
        // wanted us to suggest a filename, use the initial
        // pathname as is.  if not, use the directory portion of
        // it.

        if (m_bSuggestName)
        {
            xxx_UT_DEBUGMSG(("Iniitial filename is %s \n",m_szInitialPathname));
#if 0
            if (!g_path_is_absolute (m_szInitialPathname)) { // DAL: todo: is this correct?
                gchar *dir = g_get_current_dir ();
                gchar *file = m_szInitialPathname;
                gchar *filename = g_build_filename (dir, file, (gchar *)NULL);
                m_szInitialPathname = UT_go_filename_to_uri(filename);
                g_free(filename);
                g_free (dir);
                g_free (file);
            }
#endif
            if(m_id == XAP_DIALOG_ID_FILE_SAVEAS)
            {
                std::string szInitialSuffix = UT_pathSuffix(m_szInitialPathname);
                std::string szSaveTypeSuffix = IE_Exp::preferredSuffixForFileType(m_nDefaultFileType).utf8_str();
                if(!szInitialSuffix.empty() && !szSaveTypeSuffix.empty()
                        && (szSaveTypeSuffix != szInitialSuffix))
                {
                    std::string sFileName = m_szInitialPathname;
                    std::string::size_type i = sFileName.find_last_of('.');

                    if(i != std::string::npos)
                    {
                        // erase to the end()
                        sFileName.erase(i);
                        sFileName += szSaveTypeSuffix;
                        FREEP(m_szInitialPathname);
                        m_szInitialPathname = g_strdup(sFileName.c_str());
                    }
                }
            }
            if (UT_go_path_is_uri(m_szInitialPathname) || UT_go_path_is_path(m_szInitialPathname))
            {
                gtk_file_chooser_set_uri(m_FC, m_szInitialPathname);
            }
        }
        else
        {
            if (UT_go_path_is_uri(m_szInitialPathname) || UT_go_path_is_path(m_szInitialPathname))
            {
                szPersistDirectory = UT_go_dirname_from_uri(m_szInitialPathname, FALSE);
                gtk_file_chooser_set_current_folder_uri(m_FC, szPersistDirectory);
            }
            else
            {
                // we are dealing with a plain filename, not an URI or path, so
                // just let it come up in the current working directory.
            }
        }
    }

    // center the dialog
    xxx_UT_DEBUGMSG(("before center IS WIDGET_TOP_LEVL %d \n",(GTK_WIDGET_TOPLEVEL(parent))));
    xxx_UT_DEBUGMSG(("before center IS WIDGET WINDOW %d \n",(GTK_IS_WINDOW(parent))));
    centerDialog(parent, GTK_WIDGET(m_FC));
    xxx_UT_DEBUGMSG(("After center IS WIDGET WINDOW %d \n",(GTK_IS_WINDOW(parent))));

    gtk_widget_show(GTK_WIDGET(m_FC));
    gtk_grab_add(GTK_WIDGET(m_FC));

    bool bResult = _run_gtk_main(pFrame,filetypes_pulldown);

    if (bResult)
    {
        UT_ASSERT(m_szFinalPathnameCandidate);

        // store final path name and file type
        m_szFinalPathname = g_strdup(m_szFinalPathnameCandidate);

        FREEP(m_szFinalPathnameCandidate);

        // what a long ugly line of code
        m_nFileType = XAP_comboBoxGetActiveInt(GTK_COMBO_BOX(filetypes_pulldown));
    }

    if (m_FC != NULL) {
        gtk_grab_remove (GTK_WIDGET(m_FC));
        gtk_widget_destroy (GTK_WIDGET(m_FC));
        m_FC = NULL;
        FREEP(szPersistDirectory);
    }

    return;
}
bool XAP_UnixDialog_FileOpenSaveAs::_run_gtk_main(XAP_Frame * pFrame,
        GtkWidget * filetypes_pulldown)
{
    /*
      Run the dialog in a loop to catch bad filenames.
      The location of this check being in this dialog loop
      could be considered temporary.  Doing this matches the Windows
      common control behavior (where the dialog checks everything
      for the programmer), but lacks flexibility for different
      uses of this dialog (file export, print export, directory
      (not file) selection).

      This check might need to be moved into the ap code which calls
      this dialog, and certain interfaces exposed so that the
      dialog is displayed throughout the verification.

      For right now you can signal this check on and off with
      bCheckWritePermission.
    */

    char * szDialogFilename = NULL;		// this is the file name returned from the dialog
    char * szFinalPathname = NULL;		// this is the file name after suffix addition, if any
    char * szFinalPathnameCopy = NULL;	// one to mangle when looking for dirs, etc.

    char * pLastSlash;

    // if m_bSave is not set, we're looking to OPEN a file.
    // otherwise we are looking to SAVE a file.
    if (!m_bSave)
    {
        while (1)
        {
            gtk_main();
            if (m_answer == a_CANCEL)			// The easy way out
                return false;

            m_szFinalPathnameCandidate = gtk_file_chooser_get_uri(m_FC);
            UT_ASSERT(m_szFinalPathnameCandidate);
            return (m_answer == a_OK);
        }
    }
    else
    {
        while(1)
        {
            gtk_main();
            if (m_answer == a_CANCEL)			// The easy way out
                return false;

            // Give us a filename we can mangle

            szDialogFilename = gtk_file_chooser_get_uri(m_FC);
            if (!szDialogFilename)
                continue;

            // We append the suffix of the default type, so the user doesn't
            // have to.  This is adapted from the Windows front-end code
            // (xap_Win32Dlg_FileOpenSaveAs.cpp), since it should act the same.
            // If, however, the user doesn't want suffixes, they don't have to have them.
            {
                //UT_uint32 end = g_strv_length(m_szSuffixes);
                UT_sint32 nFileType = XAP_comboBoxGetActiveInt(GTK_COMBO_BOX(filetypes_pulldown));

                // set to first item, which should probably be auto detect
                // TODO : "probably" isn't very good.
                UT_uint32 nIndex = 0;

                // the index in the types table will match the index in the suffix
                // table.  nFileType is the data we are searching for.
                if(m_nTypeList != NULL)
                {
                    for (UT_uint32 i = 0; m_nTypeList[i]; i++)
                    {
                        if (m_nTypeList[i] == nFileType)
                        {
                            nIndex = i;
                            break;
                        }
                    }
                }

                bool wantSuffix = true;
                XAP_Prefs *pPrefs= XAP_App::getApp()->getPrefs();
                pPrefs->getPrefsValueBool(static_cast<const gchar *>(XAP_PREF_KEY_UseSuffix), &wantSuffix);
                UT_DEBUGMSG(("UseSuffix: %d\n", wantSuffix));

                if (nFileType > 0 && getDialogId() != XAP_DIALOG_ID_FILE_SAVE_IMAGE) // 0 means autodetect
                {
                    if (!UT_pathSuffix(szDialogFilename).empty())
                    {
                        // warn if we have a suffix that doesn't match the selected file type
                        IE_ExpSniffer* pSniffer = IE_Exp::snifferForFileType(m_nTypeList[nIndex]);
                        if (pSniffer && !pSniffer->recognizeSuffix(UT_pathSuffix(szDialogFilename).c_str()))
                        {
                            UT_UTF8String msg;
                            const XAP_StringSet * pSS = m_pApp->getStringSet();
                            pSS->getValueUTF8(XAP_STRING_ID_DLG_FOSA_ExtensionDoesNotMatch, msg);
                            if (pFrame->showMessageBox(msg.utf8_str(), XAP_Dialog_MessageBox::b_YN, XAP_Dialog_MessageBox::a_NO) != XAP_Dialog_MessageBox::a_YES)
                                goto ContinueLoop;
                        }
                        szFinalPathname = g_strdup(szDialogFilename);
                    }
                    else if (wantSuffix)
                    {
                        // if the file doesn't have a suffix already, and the file type
                        // is normal (special types are negative, like auto detect),
                        // and the user wants extensions, slap a suffix on it.
                        // add suffix based on selected file type
                        UT_UTF8String suffix (IE_Exp::preferredSuffixForFileType(m_nTypeList[nIndex]));
                        UT_uint32 length = strlen(szDialogFilename) + suffix.size() + 1;

                        szFinalPathname = static_cast<char *>(UT_calloc(length,sizeof(char)));

                        if (szFinalPathname)
                        {
                            char * p = szFinalPathname;
                            strcpy(p,szDialogFilename);
                            strcat(p,suffix.utf8_str());
                        }
                    }
                    else
                        szFinalPathname = g_strdup(szDialogFilename);
                }
                else
                {
                    // the file type is special (auto detect)
                    // set to plain name, and let the auto detector in the
                    // exporter figure it out
                    szFinalPathname = g_strdup(szDialogFilename);
                }

                // g_free szDialogFilename since it's been put into szFinalPathname (with
                // or without changes) and it's invalid (missing an extension which
                // might have been appended)

                FREEP(szDialogFilename);
            }

            szFinalPathnameCopy = g_strdup(szFinalPathname);

            if (UT_go_file_exists(szFinalPathnameCopy))
            {
                // we have an existing file, ask to overwrite
                if (_askOverwrite_YesNo(pFrame, szFinalPathname))
                {
                    m_szFinalPathnameCandidate = g_strdup(szFinalPathname);
                    goto ReturnTrue;
                }

                goto ContinueLoop;
            }

            // We have a string that may contain a path, and may have a file
            // at the end.  First, strip off a file (if it exists), and test
            // for a matching directory.  We can then proceed with the file
            // if another stat of that dir passes.

            if (szFinalPathnameCopy && strlen(szFinalPathnameCopy))
                pLastSlash = strrchr(szFinalPathnameCopy,'/');
            else
                pLastSlash = NULL;

            if (!pLastSlash)
            {
                _notifyError_OKOnly(pFrame,XAP_STRING_ID_DLG_InvalidPathname);
                goto ContinueLoop;
            }

            m_szFinalPathnameCandidate = g_strdup(szFinalPathname);
            goto ReturnTrue;

            // complain about write permission on the directory.
            // lop off ugly trailing slash only if we don't have
            // the root dir ('/') for a path

            if (pLastSlash > szFinalPathnameCopy)
                *pLastSlash = 0;

            _notifyError_OKOnly(pFrame,XAP_STRING_ID_DLG_NoSaveFile_DirNotWriteable,
                                szFinalPathname);
ContinueLoop:
            FREEP(szFinalPathnameCopy);
        }
    } /* if m_bSave */

    /*NOTREACHED*/

ReturnTrue:
    FREEP(szFinalPathnameCopy);
    FREEP(szFinalPathname);
    return true;
}