/**
    Replace font family leaving style alone (if possible).
    @param fontSpec the given font
    @param newFamily
    @return the changed fontspec, if the property can not be set return an empty string
    The routine first searches for an exact match.
    If no exact match found, calls FontSpecificationBestMatch().
*/
Glib::ustring font_factory::ReplaceFontSpecificationFamily(const Glib::ustring & fontSpec, const Glib::ustring & newFamily)
{
    Glib::ustring newFontSpec;

    // Although we are using the string from pango_font_description_to_string for the
    // font specification, we definitely cannot just set the new family in the
    // PangoFontDescription structure and ask for a new string.  This is because
    // what constitutes a "family" in our own UI may be different from how Pango
    // sees it.

    // Find the PangoFontDescription associated with the old font specification string.
    PangoStringToDescrMap::iterator it = fontInstanceMap.find(fontSpec);


    if (it != fontInstanceMap.end()) {
        // Description found!

        // Make copy
        PangoFontDescription *descr = pango_font_description_copy((*it).second);

        // Grab the old UI Family string from the descr
        Glib::ustring uiFamily = GetUIFamilyString(descr);

        // Replace the UI Family name with the new family name
        std::size_t found = fontSpec.find(uiFamily);
        if (found != Glib::ustring::npos) {

            // Add comma to end of newFamily... commas at end don't hurt but are
            // required if the last part of a family name is a valid font style
            // (e.g. "Arial Black").
            Glib::ustring newFamilyComma = newFamily;
            if( *newFamilyComma.rbegin() != ',' ) {
                newFamilyComma += ",";
            }
            newFontSpec = fontSpec;
            newFontSpec.erase(found, uiFamily.size());
            newFontSpec.insert(found, newFamilyComma);

            // If the new font specification does not exist in the reference maps,
            // search for the next best match for the faces in that style
            it = fontInstanceMap.find(newFontSpec);
            if (it == fontInstanceMap.end()) {

                // Search for best match, empty string returned if not found.
                newFontSpec = FontSpecificationBestMatch( newFontSpec );

            }
        }

        pango_font_description_free(descr);
    }

    return newFontSpec;
}
/**
 * Save window position related details under provided path
 */
void jobManWindow::savePosition(const Glib::ustring &windowConfPath) {
	Gnome::Conf::init();

	Glib::RefPtr<Gnome::Conf::Client> gConfClient(Gnome::Conf::Client::get_default_client());

	gConfClient->add_dir(windowConfPath, Gnome::Conf::CLIENT_PRELOAD_ONELEVEL);

	Glib::ustring key;

	key.erase().append(windowConfPath).append("/size_height");
	gConfClient->set(key, size_height);

	key.erase().append(windowConfPath).append("/size_width");
	gConfClient->set(key, size_width);

	key.erase().append(windowConfPath).append("/pos_x");
	gConfClient->set(key, pos_x);

	key.erase().append(windowConfPath).append("/pos_y");
	gConfClient->set(key, pos_y);

	key.erase().append(windowConfPath).append("/isMaximized");
	gConfClient->set(key, isMaximized);

	key.erase().append(windowConfPath).append("/panelSeparator");
	gConfClient->set(key, paned.get_position());

}
    /* compressed utf-8 table */
        0x20ac, /* 80 Euro. CP1252 from here on... */
        0x81,   /* 81 NA */
        0x201a, /* 82 */
        0x192,  /* 83 */
        0x201e, /* 84 */
        0x2026, /* 85 */
        0x2020, /* 86 */
        0x2021, /* 87 */
        0x2c6,  /* 88 */
        0x2030, /* 89 */
        0x160,  /* 8a */
        0x2039, /* 8b */
        0x152,  /* 8c */
        0x8d,   /* 8d NA */
        0x17d,  /* 8e */
        0x8f,   /* 8f NA */
        0x90,   /* 90 NA */
        0x2018, /* 91 */
        0x2019, /* 92 */
        0x201c, /* 93 */
        0x201d, /* 94 */
        0x2022, /* 95 */
        0x2013, /* 96 */
        0x2014, /* 97 */
        0x2dc,  /* 98 */
        0x2122, /* 99 */
        0x161,  /* 9a */
        0x203a, /* 9b */
        0x153,  /* 9c */
        0x9d,   /* 9d NA */
        0x17e,  /* 9e */
        0x178,  /* 9f */
        0xa0,   /* a0 */
        0xa1,   /* a1 */
        0xa2,   /* a2 */
        0xa3,   /* a3 */
        0x20ac  /* a4 ISO-8859-15 Euro. */
    };

    while (len) {
        if (G_UNLIKELY(*text >= 0x80) && G_UNLIKELY(*text <= 0xa4)) {
            int idx = *text - 0x80;
            output += lowtable[idx];
        } else {
            output += (gunichar)*text;    /* ascii/iso88591 maps directly */
        }

        text++;
        len--;
    }
    return output;
}/*}}}*/
void set_charset(Glib::ustring charset) {/*{{{*/
    charset = charset.uppercase();

    if (charset.find(' ') != Glib::ustring::npos)
        charset = charset.erase(charset.find(' '));

    if (charset.empty() || !charset.compare("SYSTEM")) {
        charset.clear();
    } else {
        try {
            Glib::IConv test("UTF-8", charset);
        } catch (...) {
            fprintf(stderr, "Charset '%s' isn't supported by your system - using system locale\n", charset.c_str());
            charset.clear();
        }
    }

    serverCharset = charset;
}/*}}}*/
void ColorNotebook::_rgbaEntryChanged(GtkEntry* entry)
{
    if (_updating) return;
    if (_updatingrgba) return;

    const gchar *t = gtk_entry_get_text( entry );

    if (t) {
        Glib::ustring text = t;
        bool changed = false;
        if (!text.empty() && text[0] == '#') {
            changed = true;
            text.erase(0,1);
            if (text.size() == 6) {
                // it was a standard RGB hex
                unsigned int alph = SP_COLOR_F_TO_U(_alpha);
                gchar* tmp = g_strdup_printf("%02x", alph);
                text += tmp;
                g_free(tmp);
            }
        }
        gchar* str = g_strdup(text.c_str());
        gchar* end = 0;
        guint64 rgba = g_ascii_strtoull( str, &end, 16 );
        if ( end != str ) {
            ptrdiff_t len = end - str;
            if ( len < 8 ) {
                rgba = rgba << ( 4 * ( 8 - len ) );
            }
            _updatingrgba = TRUE;
            if ( changed ) {
                gtk_entry_set_text( entry, str );
            }
            SPColor color( rgba );
            setColorAlpha( color, SP_RGBA32_A_F(rgba), true );
            _updatingrgba = FALSE;
        }
        g_free(str);
    }
}
bool FileManager::OpenFiles(int argc, char **argv)
	{
#ifdef DEBUG
std::cout << "OPENFILES: OpenFiles called \n";
#endif // DEBUG

	// makes sure we're dealing with a clean slate
	filenames.clear();
	numfiles = 0;
	cwd_checked = false;
	initialised = false;
	
	/* //	if we have initialised already we're being called from the file selector and will
	//	accept new files now, let's set initialised and cwd_checked to 'false' and clear our file list
	if( initialised == true )
		{
		numfiles = 0;
		cwd_checked = false;
		initialised = false;
		} // */
		
#ifdef DEBUG
std::cout << "OPENFILES: get_current_dir_name(): " << get_current_dir_name() << std::endl;
#endif // DEBUG
		
	if( argc > 1 )
		{
		for(int i = 1; i < argc; i++)
			{
			if( stat(argv[i], &filemode) != 0 )
				{
				std::cout << GT( "OPENFILES: Stat Error! Level 1 " ) << argv[i] << std::endl;
				}
			else
				{
				Glib::ustring filename;
				
				// Resolve any ".." and double / in the filename and make the filename absolute
				if( Glib::path_is_absolute( argv[i] ) )
					filename = argv[i] ;
				else
					filename = (Glib::ustring)get_current_dir_name() + "/" + (Glib::ustring)argv[i];
				
				while( filename.find("..") != Glib::ustring::npos )
					{
					filename.erase( 
						filename.rfind( '/', filename.find("..")-2), 
						filename.find("..")+2 - filename.rfind( '/', filename.find("..")-2) );
					}
				while( filename.find("//") != Glib::ustring::npos )
					filename.erase(
						filename.find("//"), filename.find("//")+1 );
				if( filename[ filename.length()-1 ] == '/' )
					filename.erase( filename.length()-1, filename.length() );
					
					
				if(filemode.st_mode & S_IFREG )  // if the file is a regular file
					{
					if( filter_filename(filename) ) // and seems to be a supported format
						{
						#ifdef DEBUG
						std::cout << "FILEMANAGER: curent argv: " << filename << std::endl;
						std::cout << "FILEMANAGER: dirname from argv: " << Glib::path_get_dirname( filename ) << std::endl;
						std::cout << "FILEMANAGER: curent dir: " << get_current_dir_name() << std::endl;
						#endif
						  
						filenames.insert( filenames.end(), filename ); // insert into list
						numfiles++;
						}
					}
				else if(filemode.st_mode & S_IFDIR) 			// if the file is a directory
					{
					cwd_checked = true;
					if((currdir = opendir(filename.c_str())) != NULL) 	// open it
						{
						while( (dirinfo = readdir(currdir)) != NULL ) // run through it
							{
							// don't forget, we're doing some string to char* conversions here 
							// here to avoid memory errors.. Glib::ustring is nice!
							Glib::ustring currfile(filename); 				// store the directory name
							currfile += '/'; 							// add a directory dash
							currfile += dirinfo->d_name; 				// add the filename
							if(stat(currfile.c_str(), &filemode) != 0)  // check for filetype
								{
								std::cout << GT( "OPENFILES: Stat Error! Level 2 " ) << currfile << std::endl;
								}
							else
								{
								if( filemode.st_mode & S_IFREG && filter_filename(currfile) ) // as above
									{
					                filenames.insert( filenames.end(), currfile ); // insert into list
									numfiles++;
									}
								}
							}
						closedir(currdir);
						}
					}
				}
			}
		filenames.sort();
		file_iterator = filenames.begin();
		}

	// when only one file was openened, we'll scan through its directory
	// and give the user control over the files
	if ( numfiles == 1 && cwd_checked == false )
		{
			cwd_checked = true;

			Glib::ustring tempfilename = *file_iterator;
			
			// prepare the file's directory name in such a way that we can pass
			// it to OpenFiles() which operates on argc/argv	
			char *dirname = new char[ (Glib::path_get_dirname( *file_iterator )).length() + 1  ];
			strcpy( dirname, (Glib::path_get_dirname( *file_iterator )).c_str() );

			char *arguments[] = { "empty" , dirname };

			// we erase the list of filenames as otherwise we would have one file twice
			filenames.clear();
			numfiles = 0;

			// now let's open the file's directory and check its contents
			OpenFiles( 2, arguments );

			// now we have a new set of files in the list, we have to find the file that
			// the user actually wanted to open!

			std::list<Glib::ustring>::iterator end = filenames.end();
			while( file_iterator != end )
				{
				#ifdef DEBUG
				std::cout << "OPENFILES: Looking for " << tempfilename << " in " << (*file_iterator) << std::endl;
				#endif
				if( (*file_iterator).find( tempfilename ) != Glib::ustring::npos )
					{
					break; // break out of the while loop if we find the filename
					}
				file_iterator++;
				}
			// when we have reached the end while looking, let's just load the first image!
			// as that means that either we didn't recognize the filename in our search above
			// or there was only one file in the directory after all!
			if( file_iterator == end )
				file_iterator = filenames.begin();

			#ifdef DEBUG
			std::cout << "OPENFILES: Deleting temporary dirname. \n";
			#endif
			
			delete[] dirname;
		}	
		
	// everything seems to have worked out alright, let's return true
	if ( numfiles > 0 )
		{
		#ifdef DEBUG
		std::cout << "OPENFILES: We're all set to go and we have " << numfiles << " files." << std::endl; 
		#endif // DEBUG
		return true;
		}
		// we did not have sufficient arguments or we have made some mistake, return false
	else
		{
		#ifdef DEBUG
		std::cout << "OPENFILES: We have " << numfiles << " files." << std::endl;
		#endif
		return false;
		}	

	}