2003-02-06 06:15:39 +08:00
|
|
|
/* LIBGIMP - The GIMP Library
|
|
|
|
* Copyright (C) 1995-1997 Spencer Kimball and Peter Mattis
|
|
|
|
*
|
|
|
|
* gimputils.c
|
|
|
|
* Copyright (C) 2003 Sven Neumann <sven@gimp.org>
|
|
|
|
*
|
2009-01-18 06:28:01 +08:00
|
|
|
* This library is free software: you can redistribute it and/or
|
2003-11-23 23:35:27 +08:00
|
|
|
* modify it under the terms of the GNU Lesser General Public
|
|
|
|
* License as published by the Free Software Foundation; either
|
2009-01-18 06:28:01 +08:00
|
|
|
* version 3 of the License, or (at your option) any later version.
|
2003-02-06 06:15:39 +08:00
|
|
|
*
|
2003-11-23 23:35:27 +08:00
|
|
|
* This library is distributed in the hope that it will be useful,
|
2003-02-06 06:15:39 +08:00
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
2003-11-23 23:35:27 +08:00
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
|
|
* Lesser General Public License for more details.
|
2003-02-06 06:15:39 +08:00
|
|
|
*
|
2003-11-23 23:35:27 +08:00
|
|
|
* You should have received a copy of the GNU Lesser General Public
|
2009-01-18 06:28:01 +08:00
|
|
|
* License along with this library. If not, see
|
|
|
|
* <http://www.gnu.org/licenses/>.
|
2003-02-06 06:15:39 +08:00
|
|
|
*/
|
|
|
|
|
|
|
|
#include "config.h"
|
|
|
|
|
|
|
|
#include <string.h>
|
2006-06-28 04:00:03 +08:00
|
|
|
#include <stdio.h>
|
2003-02-06 06:15:39 +08:00
|
|
|
|
2015-02-20 04:39:05 +08:00
|
|
|
#ifdef PLATFORM_OSX
|
|
|
|
#include <AppKit/AppKit.h>
|
|
|
|
#endif
|
|
|
|
|
2013-11-28 07:29:43 +08:00
|
|
|
#include <gio/gio.h>
|
2003-02-06 06:15:39 +08:00
|
|
|
|
2015-02-27 09:48:29 +08:00
|
|
|
#if defined(G_OS_WIN32)
|
|
|
|
/* This is a hack for Windows known directory support.
|
|
|
|
* DATADIR (autotools-generated constant) is a type defined in objidl.h
|
|
|
|
* so we must #undef it before including shlobj.h in order to avoid a
|
|
|
|
* name clash. */
|
|
|
|
#undef DATADIR
|
|
|
|
#include <windows.h>
|
|
|
|
#include <shlobj.h>
|
|
|
|
#endif
|
|
|
|
|
2004-07-29 20:33:15 +08:00
|
|
|
#include "gimpbasetypes.h"
|
2003-02-06 06:15:39 +08:00
|
|
|
#include "gimputils.h"
|
|
|
|
|
2003-04-04 23:11:30 +08:00
|
|
|
#include "libgimp/libgimp-intl.h"
|
|
|
|
|
2003-02-06 06:15:39 +08:00
|
|
|
|
2010-06-30 01:13:40 +08:00
|
|
|
/**
|
|
|
|
* SECTION: gimputils
|
|
|
|
* @title: gimputils
|
|
|
|
* @short_description: Utilities of general interest
|
|
|
|
*
|
|
|
|
* Utilities of general interest
|
|
|
|
**/
|
|
|
|
|
|
|
|
|
2003-02-06 06:15:39 +08:00
|
|
|
/**
|
|
|
|
* gimp_utf8_strtrim:
|
|
|
|
* @str: an UTF-8 encoded string (or %NULL)
|
2003-02-21 00:11:23 +08:00
|
|
|
* @max_chars: the maximum number of characters before the string get
|
|
|
|
* trimmed
|
2003-02-06 06:15:39 +08:00
|
|
|
*
|
2003-02-21 00:11:23 +08:00
|
|
|
* Creates a (possibly trimmed) copy of @str. The string is cut if it
|
|
|
|
* exceeds @max_chars characters or on the first newline. The fact
|
|
|
|
* that the string was trimmed is indicated by appending an ellipsis.
|
2003-10-16 20:24:58 +08:00
|
|
|
*
|
2003-02-21 00:11:23 +08:00
|
|
|
* Returns: A (possibly trimmed) copy of @str which should be freed
|
|
|
|
* using g_free() when it is not needed any longer.
|
2003-02-06 06:15:39 +08:00
|
|
|
**/
|
|
|
|
gchar *
|
|
|
|
gimp_utf8_strtrim (const gchar *str,
|
2006-04-12 18:53:28 +08:00
|
|
|
gint max_chars)
|
2003-02-06 06:15:39 +08:00
|
|
|
{
|
|
|
|
/* FIXME: should we make this translatable? */
|
2006-04-20 15:15:15 +08:00
|
|
|
const gchar ellipsis[] = "...";
|
2006-04-21 17:14:55 +08:00
|
|
|
const gint e_len = strlen (ellipsis);
|
2003-02-06 06:15:39 +08:00
|
|
|
|
|
|
|
if (str)
|
|
|
|
{
|
|
|
|
const gchar *p;
|
|
|
|
const gchar *newline = NULL;
|
|
|
|
gint chars = 0;
|
|
|
|
gunichar unichar;
|
|
|
|
|
2003-02-09 06:04:59 +08:00
|
|
|
for (p = str; *p; p = g_utf8_next_char (p))
|
2003-02-06 06:15:39 +08:00
|
|
|
{
|
|
|
|
if (++chars > max_chars)
|
|
|
|
break;
|
|
|
|
|
|
|
|
unichar = g_utf8_get_char (p);
|
|
|
|
|
|
|
|
switch (g_unichar_break_type (unichar))
|
|
|
|
{
|
|
|
|
case G_UNICODE_BREAK_MANDATORY:
|
|
|
|
case G_UNICODE_BREAK_LINE_FEED:
|
|
|
|
newline = p;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
2006-04-12 18:53:28 +08:00
|
|
|
break;
|
2003-02-06 06:15:39 +08:00
|
|
|
}
|
|
|
|
|
2003-02-21 00:11:23 +08:00
|
|
|
if (*p)
|
2003-02-06 06:15:39 +08:00
|
|
|
{
|
|
|
|
gsize len = p - str;
|
|
|
|
gchar *trimmed = g_new (gchar, len + e_len + 2);
|
|
|
|
|
|
|
|
memcpy (trimmed, str, len);
|
|
|
|
if (newline)
|
|
|
|
trimmed[len++] = ' ';
|
|
|
|
|
|
|
|
g_strlcpy (trimmed + len, ellipsis, e_len + 1);
|
|
|
|
|
|
|
|
return trimmed;
|
|
|
|
}
|
|
|
|
|
|
|
|
return g_strdup (str);
|
|
|
|
}
|
|
|
|
|
|
|
|
return NULL;
|
|
|
|
}
|
2003-04-04 23:11:30 +08:00
|
|
|
|
2003-10-16 20:24:58 +08:00
|
|
|
/**
|
|
|
|
* gimp_any_to_utf8:
|
|
|
|
* @str: The string to be converted to UTF-8.
|
|
|
|
* @len: The length of the string, or -1 if the string
|
|
|
|
* is nul-terminated.
|
|
|
|
* @warning_format: The message format for the warning message if conversion
|
|
|
|
* to UTF-8 fails. See the <function>printf()</function>
|
|
|
|
* documentation.
|
2011-11-26 04:39:55 +08:00
|
|
|
* @...: The parameters to insert into the format string.
|
2003-10-16 20:24:58 +08:00
|
|
|
*
|
|
|
|
* This function takes any string (UTF-8 or not) and always returns a valid
|
|
|
|
* UTF-8 string.
|
|
|
|
*
|
|
|
|
* If @str is valid UTF-8, a copy of the string is returned.
|
|
|
|
*
|
|
|
|
* If UTF-8 validation fails, g_locale_to_utf8() is tried and if it
|
|
|
|
* succeeds the resulting string is returned.
|
|
|
|
*
|
|
|
|
* Otherwise, the portion of @str that is UTF-8, concatenated
|
|
|
|
* with "(invalid UTF-8 string)" is returned. If not even the start
|
|
|
|
* of @str is valid UTF-8, only "(invalid UTF-8 string)" is returned.
|
|
|
|
*
|
|
|
|
* Return value: The UTF-8 string as described above.
|
|
|
|
**/
|
|
|
|
gchar *
|
|
|
|
gimp_any_to_utf8 (const gchar *str,
|
|
|
|
gssize len,
|
|
|
|
const gchar *warning_format,
|
|
|
|
...)
|
|
|
|
{
|
|
|
|
const gchar *start_invalid;
|
|
|
|
gchar *utf8;
|
|
|
|
|
|
|
|
g_return_val_if_fail (str != NULL, NULL);
|
|
|
|
|
|
|
|
if (g_utf8_validate (str, len, &start_invalid))
|
2004-11-22 23:25:50 +08:00
|
|
|
{
|
|
|
|
if (len < 0)
|
|
|
|
utf8 = g_strdup (str);
|
|
|
|
else
|
|
|
|
utf8 = g_strndup (str, len);
|
|
|
|
}
|
2003-10-16 20:24:58 +08:00
|
|
|
else
|
2004-11-22 23:25:50 +08:00
|
|
|
{
|
|
|
|
utf8 = g_locale_to_utf8 (str, len, NULL, NULL, NULL);
|
|
|
|
}
|
2003-10-16 20:24:58 +08:00
|
|
|
|
|
|
|
if (! utf8)
|
|
|
|
{
|
|
|
|
if (warning_format)
|
|
|
|
{
|
|
|
|
va_list warning_args;
|
|
|
|
|
|
|
|
va_start (warning_args, warning_format);
|
|
|
|
|
|
|
|
g_logv (G_LOG_DOMAIN, G_LOG_LEVEL_MESSAGE,
|
|
|
|
warning_format, warning_args);
|
|
|
|
|
|
|
|
va_end (warning_args);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (start_invalid > str)
|
|
|
|
{
|
|
|
|
gchar *tmp;
|
|
|
|
|
|
|
|
tmp = g_strndup (str, start_invalid - str);
|
2007-07-06 18:02:31 +08:00
|
|
|
utf8 = g_strconcat (tmp, " ", _("(invalid UTF-8 string)"), NULL);
|
2003-10-16 20:24:58 +08:00
|
|
|
g_free (tmp);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
utf8 = g_strdup (_("(invalid UTF-8 string)"));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return utf8;
|
|
|
|
}
|
|
|
|
|
2004-01-19 09:08:43 +08:00
|
|
|
/**
|
|
|
|
* gimp_filename_to_utf8:
|
|
|
|
* @filename: The filename to be converted to UTF-8.
|
|
|
|
*
|
|
|
|
* Convert a filename in the filesystem's encoding to UTF-8
|
|
|
|
* temporarily. The return value is a pointer to a string that is
|
|
|
|
* guaranteed to be valid only during the current iteration of the
|
|
|
|
* main loop or until the next call to gimp_filename_to_utf8().
|
|
|
|
*
|
|
|
|
* The only purpose of this function is to provide an easy way to pass
|
|
|
|
* a filename in the filesystem encoding to a function that expects an
|
|
|
|
* UTF-8 encoded filename.
|
|
|
|
*
|
|
|
|
* Return value: A temporarily valid UTF-8 representation of @filename.
|
|
|
|
* This string must not be changed or freed.
|
|
|
|
**/
|
|
|
|
const gchar *
|
|
|
|
gimp_filename_to_utf8 (const gchar *filename)
|
|
|
|
{
|
|
|
|
/* Simpleminded implementation, but at least allocates just one copy
|
|
|
|
* of each translation. Could check if already UTF-8, and if so
|
|
|
|
* return filename as is. Could perhaps (re)use a suitably large
|
|
|
|
* cyclic buffer, but then would have to verify that all calls
|
|
|
|
* really need the return value just for a "short" time.
|
|
|
|
*/
|
|
|
|
|
|
|
|
static GHashTable *ht = NULL;
|
|
|
|
gchar *filename_utf8;
|
|
|
|
|
|
|
|
if (! filename)
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
if (! ht)
|
|
|
|
ht = g_hash_table_new (g_str_hash, g_str_equal);
|
|
|
|
|
|
|
|
filename_utf8 = g_hash_table_lookup (ht, filename);
|
|
|
|
|
|
|
|
if (! filename_utf8)
|
|
|
|
{
|
2005-02-21 05:49:53 +08:00
|
|
|
filename_utf8 = g_filename_display_name (filename);
|
2004-01-19 09:08:43 +08:00
|
|
|
g_hash_table_insert (ht, g_strdup (filename), filename_utf8);
|
|
|
|
}
|
|
|
|
|
|
|
|
return filename_utf8;
|
|
|
|
}
|
|
|
|
|
2014-07-01 19:18:14 +08:00
|
|
|
/**
|
|
|
|
* gimp_file_get_utf8_name:
|
|
|
|
* @file: a #GFile
|
|
|
|
*
|
|
|
|
* This function works like gimp_filename_to_utf8() and returns
|
|
|
|
* a UTF-8 encoded string that does not need to be freed.
|
|
|
|
*
|
|
|
|
* It converts a #GFile's path or uri to UTF-8 temporarily. The
|
|
|
|
* return value is a pointer to a string that is guaranteed to be
|
|
|
|
* valid only during the current iteration of the main loop or until
|
|
|
|
* the next call to gimp_file_get_utf8_name().
|
|
|
|
*
|
|
|
|
* The only purpose of this function is to provide an easy way to pass
|
|
|
|
* a #GFile's name to a function that expects an UTF-8 encoded string.
|
|
|
|
*
|
|
|
|
* See g_file_get_parse_name().
|
|
|
|
*
|
2015-06-01 03:18:09 +08:00
|
|
|
* Since: 2.10
|
2014-07-01 19:18:14 +08:00
|
|
|
*
|
|
|
|
* Return value: A temporarily valid UTF-8 representation of @file's name.
|
|
|
|
* This string must not be changed or freed.
|
|
|
|
**/
|
|
|
|
const gchar *
|
|
|
|
gimp_file_get_utf8_name (GFile *file)
|
|
|
|
{
|
|
|
|
gchar *name;
|
|
|
|
|
|
|
|
g_return_val_if_fail (G_IS_FILE (file), NULL);
|
|
|
|
|
|
|
|
name = g_file_get_parse_name (file);
|
|
|
|
|
|
|
|
g_object_set_data_full (G_OBJECT (file), "gimp-parse-name", name,
|
|
|
|
(GDestroyNotify) g_free);
|
|
|
|
|
|
|
|
return name;
|
|
|
|
}
|
2003-08-12 01:14:32 +08:00
|
|
|
|
2014-08-04 02:46:28 +08:00
|
|
|
/**
|
|
|
|
* gimp_file_has_extension:
|
|
|
|
* @file: a #GFile
|
|
|
|
* @extension: an ASCII extension
|
|
|
|
*
|
|
|
|
* This function checks if @file's URI ends with @extension. It behaves
|
|
|
|
* like g_str_has_suffix() on g_file_get_uri(), except that the string
|
|
|
|
* comparison is done case-insensitively using g_ascii_strcasecmp().
|
|
|
|
*
|
2015-06-01 03:18:09 +08:00
|
|
|
* Since: 2.10
|
2014-08-04 02:46:28 +08:00
|
|
|
*
|
|
|
|
* Return value: %TRUE if @file's URI ends with @extension,
|
|
|
|
* %FALSE otherwise.
|
|
|
|
**/
|
|
|
|
gboolean
|
|
|
|
gimp_file_has_extension (GFile *file,
|
|
|
|
const gchar *extension)
|
|
|
|
{
|
|
|
|
gchar *uri;
|
|
|
|
gint uri_len;
|
|
|
|
gint ext_len;
|
|
|
|
gboolean result = FALSE;
|
|
|
|
|
|
|
|
g_return_val_if_fail (G_IS_FILE (file), FALSE);
|
|
|
|
g_return_val_if_fail (extension != NULL, FALSE);
|
|
|
|
|
|
|
|
uri = g_file_get_uri (file);
|
|
|
|
|
|
|
|
uri_len = strlen (uri);
|
|
|
|
ext_len = strlen (extension);
|
|
|
|
|
|
|
|
if (uri_len && ext_len && (uri_len > ext_len))
|
|
|
|
{
|
|
|
|
if (g_ascii_strcasecmp (uri + uri_len - ext_len, extension) == 0)
|
|
|
|
result = TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
g_free (uri);
|
|
|
|
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
2015-02-17 01:40:26 +08:00
|
|
|
/**
|
|
|
|
* gimp_file_show_in_file_manager:
|
|
|
|
* @file: a #GFile
|
|
|
|
* @error: return location for a #GError
|
|
|
|
*
|
|
|
|
* Shows @file in the system file manager.
|
|
|
|
*
|
2015-06-01 03:18:09 +08:00
|
|
|
* Since: 2.10
|
2015-02-17 01:40:26 +08:00
|
|
|
*
|
2015-06-01 01:44:39 +08:00
|
|
|
* Return value: %TRUE on success, %FALSE otherwise. On %FALSE, @error
|
2015-02-17 01:40:26 +08:00
|
|
|
* is set.
|
|
|
|
**/
|
|
|
|
gboolean
|
|
|
|
gimp_file_show_in_file_manager (GFile *file,
|
|
|
|
GError **error)
|
|
|
|
{
|
|
|
|
g_return_val_if_fail (G_IS_FILE (file), FALSE);
|
|
|
|
g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
|
|
|
|
|
|
|
|
#if defined(G_OS_WIN32)
|
|
|
|
|
|
|
|
{
|
2015-02-27 09:48:29 +08:00
|
|
|
gboolean ret;
|
|
|
|
char *filename;
|
|
|
|
int n;
|
|
|
|
LPWSTR w_filename = NULL;
|
|
|
|
ITEMIDLIST *pidl = NULL;
|
|
|
|
|
|
|
|
ret = FALSE;
|
2015-02-17 01:40:26 +08:00
|
|
|
|
2016-06-26 04:54:10 +08:00
|
|
|
/* Calling this function multiple times should do no harm, but it is
|
2015-02-27 09:48:29 +08:00
|
|
|
easier to put this here as it needs linking against ole32. */
|
|
|
|
CoInitialize (NULL);
|
|
|
|
|
|
|
|
filename = g_file_get_path (file);
|
|
|
|
if (!filename)
|
|
|
|
{
|
|
|
|
g_set_error_literal (error, G_FILE_ERROR, 0,
|
2015-02-27 14:46:02 +08:00
|
|
|
_("File path is NULL"));
|
2015-02-27 09:48:29 +08:00
|
|
|
goto out;
|
|
|
|
}
|
|
|
|
|
|
|
|
n = MultiByteToWideChar (CP_UTF8, MB_ERR_INVALID_CHARS,
|
|
|
|
filename, -1, NULL, 0);
|
|
|
|
if (n == 0)
|
|
|
|
{
|
|
|
|
g_set_error_literal (error, G_FILE_ERROR, 0,
|
2015-02-27 14:46:02 +08:00
|
|
|
_("Error converting UTF-8 filename to wide char"));
|
2015-02-27 09:48:29 +08:00
|
|
|
goto out;
|
|
|
|
}
|
|
|
|
|
|
|
|
w_filename = g_malloc_n (n + 1, sizeof (wchar_t));
|
|
|
|
n = MultiByteToWideChar (CP_UTF8, MB_ERR_INVALID_CHARS,
|
|
|
|
filename, -1,
|
|
|
|
w_filename, (n + 1) * sizeof (wchar_t));
|
|
|
|
if (n == 0)
|
|
|
|
{
|
|
|
|
g_set_error_literal (error, G_FILE_ERROR, 0,
|
2015-02-27 14:46:02 +08:00
|
|
|
_("Error converting UTF-8 filename to wide char"));
|
2015-02-27 09:48:29 +08:00
|
|
|
goto out;
|
|
|
|
}
|
|
|
|
|
|
|
|
pidl = ILCreateFromPathW (w_filename);
|
|
|
|
if (!pidl)
|
|
|
|
{
|
|
|
|
g_set_error_literal (error, G_FILE_ERROR, 0,
|
2015-02-27 14:46:02 +08:00
|
|
|
_("ILCreateFromPath() failed"));
|
2015-02-27 09:48:29 +08:00
|
|
|
goto out;
|
|
|
|
}
|
|
|
|
|
|
|
|
SHOpenFolderAndSelectItems (pidl, 0, NULL, 0);
|
|
|
|
ret = TRUE;
|
|
|
|
|
|
|
|
out:
|
|
|
|
if (pidl)
|
|
|
|
ILFree (pidl);
|
|
|
|
g_free (w_filename);
|
|
|
|
g_free (filename);
|
|
|
|
|
|
|
|
return ret;
|
2015-02-17 01:40:26 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
#elif defined(PLATFORM_OSX)
|
|
|
|
|
|
|
|
{
|
2015-02-20 04:39:05 +08:00
|
|
|
gchar *uri;
|
|
|
|
NSString *filename;
|
|
|
|
NSURL *url;
|
|
|
|
gboolean retval = TRUE;
|
2015-02-17 01:40:26 +08:00
|
|
|
|
2015-02-20 04:39:05 +08:00
|
|
|
uri = g_file_get_uri (file);
|
|
|
|
filename = [NSString stringWithUTF8String:uri];
|
2015-02-17 01:40:26 +08:00
|
|
|
|
2015-02-20 04:39:05 +08:00
|
|
|
url = [NSURL URLWithString:filename];
|
|
|
|
if (url)
|
|
|
|
{
|
|
|
|
NSArray *url_array = [NSArray arrayWithObject:url];
|
|
|
|
|
|
|
|
[[NSWorkspace sharedWorkspace] activateFileViewerSelectingURLs:url_array];
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
g_set_error (error, G_FILE_ERROR, 0,
|
|
|
|
_("Cannot convert '%s' into a valid NSURL."), uri);
|
|
|
|
retval = FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
g_free (uri);
|
|
|
|
|
|
|
|
return retval;
|
2015-02-17 01:40:26 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
#else /* UNIX */
|
|
|
|
|
|
|
|
{
|
|
|
|
GDBusProxy *proxy;
|
|
|
|
GVariant *retval;
|
|
|
|
GVariantBuilder *builder;
|
|
|
|
gchar *uri;
|
|
|
|
|
|
|
|
proxy = g_dbus_proxy_new_for_bus_sync (G_BUS_TYPE_SESSION,
|
|
|
|
G_DBUS_PROXY_FLAGS_NONE,
|
|
|
|
NULL,
|
|
|
|
"org.freedesktop.FileManager1",
|
|
|
|
"/org/freedesktop/FileManager1",
|
|
|
|
"org.freedesktop.FileManager1",
|
|
|
|
NULL, error);
|
|
|
|
|
|
|
|
if (! proxy)
|
|
|
|
{
|
|
|
|
g_prefix_error (error,
|
|
|
|
_("Connecting to org.freedesktop.FileManager1 failed: "));
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
uri = g_file_get_uri (file);
|
|
|
|
|
|
|
|
builder = g_variant_builder_new (G_VARIANT_TYPE ("as"));
|
|
|
|
g_variant_builder_add (builder, "s", uri);
|
|
|
|
|
|
|
|
g_free (uri);
|
|
|
|
|
|
|
|
retval = g_dbus_proxy_call_sync (proxy,
|
|
|
|
"ShowItems",
|
|
|
|
g_variant_new ("(ass)",
|
|
|
|
builder,
|
|
|
|
""),
|
|
|
|
G_DBUS_CALL_FLAGS_NONE,
|
|
|
|
-1, NULL, error);
|
|
|
|
|
|
|
|
g_variant_builder_unref (builder);
|
|
|
|
g_object_unref (proxy);
|
|
|
|
|
|
|
|
if (! retval)
|
|
|
|
{
|
|
|
|
g_prefix_error (error, _("Calling ShowItems failed: "));
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
g_variant_unref (retval);
|
|
|
|
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
2003-08-12 01:14:32 +08:00
|
|
|
/**
|
|
|
|
* gimp_strip_uline:
|
2004-11-13 20:32:01 +08:00
|
|
|
* @str: underline infested string (or %NULL)
|
2003-08-12 01:14:32 +08:00
|
|
|
*
|
|
|
|
* This function returns a copy of @str stripped of underline
|
|
|
|
* characters. This comes in handy when needing to strip mnemonics
|
|
|
|
* from menu paths etc.
|
|
|
|
*
|
2004-11-13 20:32:01 +08:00
|
|
|
* In some languages, mnemonics are handled by adding the mnemonic
|
|
|
|
* character in brackets (like "File (_F)"). This function recognizes
|
|
|
|
* this construct and removes the whole bracket construction to get
|
2010-06-30 01:13:40 +08:00
|
|
|
* rid of the mnemonic (see bug 157561).
|
2004-11-13 20:32:01 +08:00
|
|
|
*
|
2003-08-12 01:14:32 +08:00
|
|
|
* Return value: A (possibly stripped) copy of @str which should be
|
2004-11-13 20:32:01 +08:00
|
|
|
* freed using g_free() when it is not needed any longer.
|
2003-08-12 01:14:32 +08:00
|
|
|
**/
|
|
|
|
gchar *
|
|
|
|
gimp_strip_uline (const gchar *str)
|
|
|
|
{
|
2004-11-13 20:32:01 +08:00
|
|
|
gchar *escaped;
|
|
|
|
gchar *p;
|
|
|
|
gboolean past_bracket = FALSE;
|
2003-08-12 01:14:32 +08:00
|
|
|
|
|
|
|
if (! str)
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
p = escaped = g_strdup (str);
|
|
|
|
|
|
|
|
while (*str)
|
|
|
|
{
|
|
|
|
if (*str == '_')
|
|
|
|
{
|
|
|
|
/* "__" means a literal "_" in the menu path */
|
|
|
|
if (str[1] == '_')
|
2004-11-13 20:32:01 +08:00
|
|
|
{
|
|
|
|
*p++ = *str++;
|
2006-08-06 21:12:43 +08:00
|
|
|
str++;
|
|
|
|
continue;
|
2004-11-13 20:32:01 +08:00
|
|
|
}
|
2003-08-12 01:14:32 +08:00
|
|
|
|
2004-11-13 20:32:01 +08:00
|
|
|
/* find the "(_X)" construct and remove it entirely */
|
|
|
|
if (past_bracket && str[1] && *(g_utf8_next_char (str + 1)) == ')')
|
|
|
|
{
|
|
|
|
str = g_utf8_next_char (str + 1) + 1;
|
|
|
|
p--;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
str++;
|
|
|
|
}
|
2003-08-12 01:14:32 +08:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2004-11-13 20:32:01 +08:00
|
|
|
past_bracket = (*str == '(');
|
|
|
|
|
2003-08-12 01:14:32 +08:00
|
|
|
*p++ = *str++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
*p = '\0';
|
|
|
|
|
|
|
|
return escaped;
|
|
|
|
}
|
2004-04-30 00:47:53 +08:00
|
|
|
|
|
|
|
/**
|
|
|
|
* gimp_escape_uline:
|
|
|
|
* @str: Underline infested string (or %NULL)
|
|
|
|
*
|
|
|
|
* This function returns a copy of @str with all underline converted
|
|
|
|
* to two adjacent underlines. This comes in handy when needing to display
|
|
|
|
* strings with underlines (like filenames) in a place that would convert
|
|
|
|
* them to mnemonics.
|
|
|
|
*
|
|
|
|
* Return value: A (possibly escaped) copy of @str which should be
|
|
|
|
* freed using g_free() when it is not needed any longer.
|
2004-11-10 21:55:12 +08:00
|
|
|
*
|
2015-06-01 03:18:09 +08:00
|
|
|
* Since: 2.2
|
2004-04-30 00:47:53 +08:00
|
|
|
**/
|
|
|
|
gchar *
|
|
|
|
gimp_escape_uline (const gchar *str)
|
|
|
|
{
|
|
|
|
gchar *escaped;
|
|
|
|
gchar *p;
|
|
|
|
gint n_ulines = 0;
|
|
|
|
|
|
|
|
if (! str)
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
for (p = (gchar *) str; *p; p++)
|
|
|
|
if (*p == '_')
|
|
|
|
n_ulines++;
|
|
|
|
|
|
|
|
p = escaped = g_malloc (strlen (str) + n_ulines + 1);
|
|
|
|
|
|
|
|
while (*str)
|
|
|
|
{
|
|
|
|
if (*str == '_')
|
|
|
|
*p++ = '_';
|
|
|
|
|
|
|
|
*p++ = *str++;
|
|
|
|
}
|
|
|
|
|
|
|
|
*p = '\0';
|
|
|
|
|
|
|
|
return escaped;
|
|
|
|
}
|
2004-07-29 20:33:15 +08:00
|
|
|
|
2005-08-03 06:52:23 +08:00
|
|
|
/**
|
|
|
|
* gimp_canonicalize_identifier:
|
|
|
|
* @identifier: The identifier string to canonicalize.
|
|
|
|
*
|
|
|
|
* Turns any input string into a canonicalized string.
|
|
|
|
*
|
|
|
|
* Canonical identifiers are e.g. expected by the PDB for procedure
|
2005-10-06 07:49:17 +08:00
|
|
|
* and parameter names. Every character of the input string that is
|
|
|
|
* not either '-', 'a-z', 'A-Z' or '0-9' will be replaced by a '-'.
|
2005-08-03 06:52:23 +08:00
|
|
|
*
|
|
|
|
* Return value: The canonicalized identifier. This is a newly
|
|
|
|
* allocated string that should be freed with g_free()
|
|
|
|
* when no longer needed.
|
2005-10-06 07:49:17 +08:00
|
|
|
*
|
2015-06-01 03:18:09 +08:00
|
|
|
* Since: 2.4
|
2005-08-03 06:52:23 +08:00
|
|
|
**/
|
|
|
|
gchar *
|
|
|
|
gimp_canonicalize_identifier (const gchar *identifier)
|
|
|
|
{
|
|
|
|
gchar *canonicalized = NULL;
|
|
|
|
|
|
|
|
if (identifier)
|
|
|
|
{
|
|
|
|
gchar *p;
|
|
|
|
|
|
|
|
canonicalized = g_strdup (identifier);
|
|
|
|
|
|
|
|
for (p = canonicalized; *p != 0; p++)
|
|
|
|
{
|
|
|
|
gchar c = *p;
|
|
|
|
|
|
|
|
if (c != '-' &&
|
|
|
|
(c < '0' || c > '9') &&
|
|
|
|
(c < 'A' || c > 'Z') &&
|
|
|
|
(c < 'a' || c > 'z'))
|
|
|
|
*p = '-';
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return canonicalized;
|
|
|
|
}
|
|
|
|
|
2004-11-10 20:44:13 +08:00
|
|
|
/**
|
|
|
|
* gimp_enum_get_desc:
|
|
|
|
* @enum_class: a #GEnumClass
|
|
|
|
* @value: a value from @enum_class
|
|
|
|
*
|
|
|
|
* Retrieves #GimpEnumDesc associated with the given value, or %NULL.
|
|
|
|
*
|
|
|
|
* Return value: the value's #GimpEnumDesc.
|
|
|
|
*
|
2015-06-01 03:18:09 +08:00
|
|
|
* Since: 2.2
|
2004-11-10 20:44:13 +08:00
|
|
|
**/
|
2004-10-26 01:55:25 +08:00
|
|
|
GimpEnumDesc *
|
|
|
|
gimp_enum_get_desc (GEnumClass *enum_class,
|
|
|
|
gint value)
|
|
|
|
{
|
|
|
|
const GimpEnumDesc *value_desc;
|
|
|
|
|
|
|
|
g_return_val_if_fail (G_IS_ENUM_CLASS (enum_class), NULL);
|
|
|
|
|
2007-07-06 18:02:31 +08:00
|
|
|
value_desc =
|
|
|
|
gimp_enum_get_value_descriptions (G_TYPE_FROM_CLASS (enum_class));
|
2004-10-26 01:55:25 +08:00
|
|
|
|
|
|
|
if (value_desc)
|
|
|
|
{
|
|
|
|
while (value_desc->value_desc)
|
|
|
|
{
|
|
|
|
if (value_desc->value == value)
|
|
|
|
return (GimpEnumDesc *) value_desc;
|
|
|
|
|
|
|
|
value_desc++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2004-07-29 20:33:15 +08:00
|
|
|
/**
|
|
|
|
* gimp_enum_get_value:
|
|
|
|
* @enum_type: the #GType of a registered enum
|
|
|
|
* @value: an integer value
|
2004-10-26 01:55:25 +08:00
|
|
|
* @value_name: return location for the value's name (or %NULL)
|
2004-07-29 20:33:15 +08:00
|
|
|
* @value_nick: return location for the value's nick (or %NULL)
|
2008-11-06 17:29:32 +08:00
|
|
|
* @value_desc: return location for the value's translated description (or %NULL)
|
2004-10-26 01:55:25 +08:00
|
|
|
* @value_help: return location for the value's translated help (or %NULL)
|
2004-07-29 20:33:15 +08:00
|
|
|
*
|
|
|
|
* Checks if @value is valid for the enum registered as @enum_type.
|
2004-10-26 01:55:25 +08:00
|
|
|
* If the value exists in that enum, its name, nick and its translated
|
2008-11-06 17:29:32 +08:00
|
|
|
* description and help are returned (if @value_name, @value_nick,
|
|
|
|
* @value_desc and @value_help are not %NULL).
|
2004-07-29 20:33:15 +08:00
|
|
|
*
|
|
|
|
* Return value: %TRUE if @value is valid for the @enum_type,
|
|
|
|
* %FALSE otherwise
|
|
|
|
*
|
2015-06-01 03:18:09 +08:00
|
|
|
* Since: 2.2
|
2004-07-29 20:33:15 +08:00
|
|
|
**/
|
|
|
|
gboolean
|
|
|
|
gimp_enum_get_value (GType enum_type,
|
|
|
|
gint value,
|
2004-10-26 01:55:25 +08:00
|
|
|
const gchar **value_name,
|
2004-07-29 20:33:15 +08:00
|
|
|
const gchar **value_nick,
|
2004-10-26 01:55:25 +08:00
|
|
|
const gchar **value_desc,
|
|
|
|
const gchar **value_help)
|
2004-07-29 20:33:15 +08:00
|
|
|
{
|
|
|
|
GEnumClass *enum_class;
|
|
|
|
GEnumValue *enum_value;
|
2005-09-28 19:02:02 +08:00
|
|
|
gboolean success = FALSE;
|
2004-07-29 20:33:15 +08:00
|
|
|
|
|
|
|
g_return_val_if_fail (G_TYPE_IS_ENUM (enum_type), FALSE);
|
|
|
|
|
2005-09-28 19:02:02 +08:00
|
|
|
enum_class = g_type_class_ref (enum_type);
|
2004-07-29 20:33:15 +08:00
|
|
|
enum_value = g_enum_get_value (enum_class, value);
|
|
|
|
|
|
|
|
if (enum_value)
|
|
|
|
{
|
2004-10-26 01:55:25 +08:00
|
|
|
if (value_name)
|
|
|
|
*value_name = enum_value->value_name;
|
|
|
|
|
2004-07-29 20:33:15 +08:00
|
|
|
if (value_nick)
|
|
|
|
*value_nick = enum_value->value_nick;
|
|
|
|
|
2004-10-26 01:55:25 +08:00
|
|
|
if (value_desc || value_help)
|
|
|
|
{
|
|
|
|
GimpEnumDesc *enum_desc;
|
|
|
|
|
|
|
|
enum_desc = gimp_enum_get_desc (enum_class, value);
|
|
|
|
|
2008-11-06 16:28:28 +08:00
|
|
|
if (value_desc)
|
|
|
|
{
|
|
|
|
if (enum_desc && enum_desc->value_desc)
|
|
|
|
{
|
|
|
|
const gchar *context;
|
|
|
|
|
|
|
|
context = gimp_type_get_translation_context (enum_type);
|
|
|
|
|
|
|
|
if (context) /* the new way, using NC_() */
|
|
|
|
*value_desc = g_dpgettext2 (gimp_type_get_translation_domain (enum_type),
|
|
|
|
context,
|
|
|
|
enum_desc->value_desc);
|
|
|
|
else /* for backward compatibility */
|
|
|
|
*value_desc = g_strip_context (enum_desc->value_desc,
|
|
|
|
dgettext (gimp_type_get_translation_domain (enum_type),
|
|
|
|
enum_desc->value_desc));
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
*value_desc = NULL;
|
|
|
|
}
|
|
|
|
}
|
2004-10-26 01:55:25 +08:00
|
|
|
|
|
|
|
if (value_help)
|
2008-11-06 16:28:28 +08:00
|
|
|
{
|
|
|
|
*value_help = ((enum_desc && enum_desc->value_help) ?
|
|
|
|
dgettext (gimp_type_get_translation_domain (enum_type),
|
|
|
|
enum_desc->value_help) :
|
|
|
|
NULL);
|
|
|
|
}
|
2004-10-26 01:55:25 +08:00
|
|
|
}
|
|
|
|
|
2005-09-28 19:02:02 +08:00
|
|
|
success = TRUE;
|
2004-10-26 01:55:25 +08:00
|
|
|
}
|
|
|
|
|
2005-09-28 19:02:02 +08:00
|
|
|
g_type_class_unref (enum_class);
|
|
|
|
|
|
|
|
return success;
|
2004-10-26 01:55:25 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
2004-11-10 20:44:13 +08:00
|
|
|
* gimp_enum_value_get_desc:
|
|
|
|
* @enum_class: a #GEnumClass
|
|
|
|
* @enum_value: a #GEnumValue from @enum_class
|
|
|
|
*
|
2008-11-06 16:28:28 +08:00
|
|
|
* Retrieves the translated description for a given @enum_value.
|
2004-11-10 20:44:13 +08:00
|
|
|
*
|
2008-11-06 16:28:28 +08:00
|
|
|
* Return value: the translated description of the enum value
|
2004-11-10 20:44:13 +08:00
|
|
|
*
|
2015-06-01 03:18:09 +08:00
|
|
|
* Since: 2.2
|
2004-11-10 20:44:13 +08:00
|
|
|
**/
|
|
|
|
const gchar *
|
|
|
|
gimp_enum_value_get_desc (GEnumClass *enum_class,
|
|
|
|
GEnumValue *enum_value)
|
|
|
|
{
|
|
|
|
GType type = G_TYPE_FROM_CLASS (enum_class);
|
|
|
|
GimpEnumDesc *enum_desc;
|
|
|
|
|
|
|
|
enum_desc = gimp_enum_get_desc (enum_class, enum_value->value);
|
|
|
|
|
2005-01-22 08:08:49 +08:00
|
|
|
if (enum_desc && enum_desc->value_desc)
|
2008-11-06 16:28:28 +08:00
|
|
|
{
|
|
|
|
const gchar *context;
|
|
|
|
|
|
|
|
context = gimp_type_get_translation_context (type);
|
|
|
|
|
|
|
|
if (context) /* the new way, using NC_() */
|
|
|
|
return g_dpgettext2 (gimp_type_get_translation_domain (type),
|
|
|
|
context,
|
|
|
|
enum_desc->value_desc);
|
|
|
|
else /* for backward compatibility */
|
|
|
|
return g_strip_context (enum_desc->value_desc,
|
|
|
|
dgettext (gimp_type_get_translation_domain (type),
|
|
|
|
enum_desc->value_desc));
|
|
|
|
}
|
2004-11-10 20:44:13 +08:00
|
|
|
|
|
|
|
return enum_value->value_name;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* gimp_enum_value_get_help:
|
|
|
|
* @enum_class: a #GEnumClass
|
|
|
|
* @enum_value: a #GEnumValue from @enum_class
|
|
|
|
*
|
|
|
|
* Retrieves the translated help for a given @enum_value.
|
|
|
|
*
|
|
|
|
* Return value: the translated help of the enum value
|
|
|
|
*
|
2015-06-01 03:18:09 +08:00
|
|
|
* Since: 2.2
|
2004-11-10 20:44:13 +08:00
|
|
|
**/
|
|
|
|
const gchar *
|
|
|
|
gimp_enum_value_get_help (GEnumClass *enum_class,
|
|
|
|
GEnumValue *enum_value)
|
|
|
|
{
|
|
|
|
GType type = G_TYPE_FROM_CLASS (enum_class);
|
|
|
|
GimpEnumDesc *enum_desc;
|
|
|
|
|
|
|
|
enum_desc = gimp_enum_get_desc (enum_class, enum_value->value);
|
|
|
|
|
2005-01-22 09:06:52 +08:00
|
|
|
if (enum_desc && enum_desc->value_help)
|
2004-11-10 20:44:13 +08:00
|
|
|
return dgettext (gimp_type_get_translation_domain (type),
|
|
|
|
enum_desc->value_help);
|
|
|
|
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
libgimpbase: add gimp_{enum,flags}_value_get_abbrev()
Add support for specifying an abbreviated description for enum/
flags values, which can be used in contexts where the full
description is too long.
Since the exact layout and size of Gimp{Enum,Flags}Desc is part of
the ABI, we can't simply add a field to these structs to hold the
abbreviated description. Instead, we use the fact that entries
with a repeated value in the value descriptions array are ignored,
and that the array is NULL terminated (in particular, that all non-
NULL entries are followed by at least one additional entry), and
specify the abbreviation in the "value_desc" field of the entry
that immediately follows the initial entry for a given value,
setting the "value" field of both entries to the same value.
Right now this behavior is undocumented, so there is no proper way
to specify abbreviated descriptions in the API, and is only meant
to be used in generated enum files.
2017-11-30 04:33:32 +08:00
|
|
|
/**
|
|
|
|
* gimp_enum_value_get_abbrev:
|
|
|
|
* @enum_class: a #GEnumClass
|
|
|
|
* @enum_value: a #GEnumValue from @enum_class
|
|
|
|
*
|
|
|
|
* Retrieves the translated abbreviation for a given @enum_value.
|
|
|
|
*
|
|
|
|
* Return value: the translated abbreviation of the enum value
|
|
|
|
*
|
|
|
|
* Since: 2.10
|
|
|
|
**/
|
|
|
|
const gchar *
|
|
|
|
gimp_enum_value_get_abbrev (GEnumClass *enum_class,
|
|
|
|
GEnumValue *enum_value)
|
|
|
|
{
|
|
|
|
GType type = G_TYPE_FROM_CLASS (enum_class);
|
|
|
|
GimpEnumDesc *enum_desc;
|
|
|
|
|
|
|
|
enum_desc = gimp_enum_get_desc (enum_class, enum_value->value);
|
|
|
|
|
|
|
|
if (enum_desc &&
|
|
|
|
enum_desc[1].value == enum_desc->value &&
|
|
|
|
enum_desc[1].value_desc)
|
|
|
|
{
|
2017-12-04 22:49:24 +08:00
|
|
|
return g_dpgettext2 (gimp_type_get_translation_domain (type),
|
|
|
|
gimp_type_get_translation_context (type),
|
|
|
|
enum_desc[1].value_desc);
|
libgimpbase: add gimp_{enum,flags}_value_get_abbrev()
Add support for specifying an abbreviated description for enum/
flags values, which can be used in contexts where the full
description is too long.
Since the exact layout and size of Gimp{Enum,Flags}Desc is part of
the ABI, we can't simply add a field to these structs to hold the
abbreviated description. Instead, we use the fact that entries
with a repeated value in the value descriptions array are ignored,
and that the array is NULL terminated (in particular, that all non-
NULL entries are followed by at least one additional entry), and
specify the abbreviation in the "value_desc" field of the entry
that immediately follows the initial entry for a given value,
setting the "value" field of both entries to the same value.
Right now this behavior is undocumented, so there is no proper way
to specify abbreviated descriptions in the API, and is only meant
to be used in generated enum files.
2017-11-30 04:33:32 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2004-11-10 20:44:13 +08:00
|
|
|
/**
|
|
|
|
* gimp_flags_get_first_desc:
|
|
|
|
* @flags_class: a #GFlagsClass
|
|
|
|
* @value: a value from @flags_class
|
|
|
|
*
|
|
|
|
* Retrieves the first #GimpFlagsDesc that matches the given value, or %NULL.
|
|
|
|
*
|
|
|
|
* Return value: the value's #GimpFlagsDesc.
|
|
|
|
*
|
2015-06-01 03:18:09 +08:00
|
|
|
* Since: 2.2
|
2004-11-10 20:44:13 +08:00
|
|
|
**/
|
|
|
|
GimpFlagsDesc *
|
|
|
|
gimp_flags_get_first_desc (GFlagsClass *flags_class,
|
|
|
|
guint value)
|
|
|
|
{
|
|
|
|
const GimpFlagsDesc *value_desc;
|
|
|
|
|
|
|
|
g_return_val_if_fail (G_IS_FLAGS_CLASS (flags_class), NULL);
|
|
|
|
|
2007-07-06 18:02:31 +08:00
|
|
|
value_desc =
|
|
|
|
gimp_flags_get_value_descriptions (G_TYPE_FROM_CLASS (flags_class));
|
2004-11-10 20:44:13 +08:00
|
|
|
|
|
|
|
if (value_desc)
|
|
|
|
{
|
|
|
|
while (value_desc->value_desc)
|
|
|
|
{
|
|
|
|
if ((value_desc->value & value) == value_desc->value)
|
|
|
|
return (GimpFlagsDesc *) value_desc;
|
|
|
|
|
|
|
|
value_desc++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* gimp_flags_get_first_value:
|
2004-10-26 01:55:25 +08:00
|
|
|
* @flags_type: the #GType of registered flags
|
|
|
|
* @value: an integer value
|
|
|
|
* @value_name: return location for the value's name (or %NULL)
|
|
|
|
* @value_nick: return location for the value's nick (or %NULL)
|
2008-11-06 17:29:32 +08:00
|
|
|
* @value_desc: return location for the value's translated description (or %NULL)
|
2004-10-26 01:55:25 +08:00
|
|
|
* @value_help: return location for the value's translated help (or %NULL)
|
|
|
|
*
|
|
|
|
* Checks if @value is valid for the flags registered as @flags_type.
|
2008-11-06 17:29:32 +08:00
|
|
|
* If the value exists in that flags, its name, nick and its
|
|
|
|
* translated description and help are returned (if @value_name,
|
|
|
|
* @value_nick, @value_desc and @value_help are not %NULL).
|
2004-10-26 01:55:25 +08:00
|
|
|
*
|
|
|
|
* Return value: %TRUE if @value is valid for the @flags_type,
|
|
|
|
* %FALSE otherwise
|
|
|
|
*
|
2015-06-01 03:18:09 +08:00
|
|
|
* Since: 2.2
|
2004-10-26 01:55:25 +08:00
|
|
|
**/
|
|
|
|
gboolean
|
2004-11-10 20:44:13 +08:00
|
|
|
gimp_flags_get_first_value (GType flags_type,
|
|
|
|
guint value,
|
|
|
|
const gchar **value_name,
|
|
|
|
const gchar **value_nick,
|
|
|
|
const gchar **value_desc,
|
|
|
|
const gchar **value_help)
|
2004-10-26 01:55:25 +08:00
|
|
|
{
|
|
|
|
GFlagsClass *flags_class;
|
|
|
|
GFlagsValue *flags_value;
|
|
|
|
|
|
|
|
g_return_val_if_fail (G_TYPE_IS_FLAGS (flags_type), FALSE);
|
|
|
|
|
|
|
|
flags_class = g_type_class_peek (flags_type);
|
|
|
|
flags_value = g_flags_get_first_value (flags_class, value);
|
|
|
|
|
|
|
|
if (flags_value)
|
|
|
|
{
|
2004-07-29 20:33:15 +08:00
|
|
|
if (value_name)
|
2004-10-26 01:55:25 +08:00
|
|
|
*value_name = flags_value->value_name;
|
|
|
|
|
|
|
|
if (value_nick)
|
|
|
|
*value_nick = flags_value->value_nick;
|
|
|
|
|
|
|
|
if (value_desc || value_help)
|
|
|
|
{
|
|
|
|
GimpFlagsDesc *flags_desc;
|
|
|
|
|
|
|
|
flags_desc = gimp_flags_get_first_desc (flags_class, value);
|
|
|
|
|
|
|
|
if (value_desc)
|
|
|
|
*value_desc = ((flags_desc && flags_desc->value_desc) ?
|
|
|
|
dgettext (gimp_type_get_translation_domain (flags_type),
|
|
|
|
flags_desc->value_desc) :
|
|
|
|
NULL);
|
|
|
|
|
|
|
|
if (value_help)
|
|
|
|
*value_help = ((flags_desc && flags_desc->value_desc) ?
|
|
|
|
dgettext (gimp_type_get_translation_domain (flags_type),
|
|
|
|
flags_desc->value_help) :
|
|
|
|
NULL);
|
|
|
|
}
|
2004-07-29 20:33:15 +08:00
|
|
|
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
2004-10-26 01:55:25 +08:00
|
|
|
/**
|
|
|
|
* gimp_flags_value_get_desc:
|
|
|
|
* @flags_class: a #GFlagsClass
|
|
|
|
* @flags_value: a #GFlagsValue from @flags_class
|
|
|
|
*
|
2008-11-06 16:28:28 +08:00
|
|
|
* Retrieves the translated description for a given @flags_value.
|
2004-10-26 01:55:25 +08:00
|
|
|
*
|
2008-11-06 16:28:28 +08:00
|
|
|
* Return value: the translated description of the flags value
|
2004-10-26 01:55:25 +08:00
|
|
|
*
|
2015-06-01 03:18:09 +08:00
|
|
|
* Since: 2.2
|
2004-10-26 01:55:25 +08:00
|
|
|
**/
|
|
|
|
const gchar *
|
|
|
|
gimp_flags_value_get_desc (GFlagsClass *flags_class,
|
|
|
|
GFlagsValue *flags_value)
|
|
|
|
{
|
|
|
|
GType type = G_TYPE_FROM_CLASS (flags_class);
|
|
|
|
GimpFlagsDesc *flags_desc;
|
|
|
|
|
|
|
|
flags_desc = gimp_flags_get_first_desc (flags_class, flags_value->value);
|
|
|
|
|
|
|
|
if (flags_desc->value_desc)
|
2017-12-04 22:49:24 +08:00
|
|
|
{
|
|
|
|
const gchar *context;
|
|
|
|
|
|
|
|
context = gimp_type_get_translation_context (type);
|
|
|
|
|
|
|
|
if (context) /* the new way, using NC_() */
|
|
|
|
return g_dpgettext2 (gimp_type_get_translation_domain (type),
|
|
|
|
context,
|
|
|
|
flags_desc->value_desc);
|
|
|
|
else /* for backward compatibility */
|
|
|
|
return g_strip_context (flags_desc->value_desc,
|
|
|
|
dgettext (gimp_type_get_translation_domain (type),
|
|
|
|
flags_desc->value_desc));
|
|
|
|
}
|
2004-10-26 01:55:25 +08:00
|
|
|
|
|
|
|
return flags_value->value_name;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* gimp_flags_value_get_help:
|
|
|
|
* @flags_class: a #GFlagsClass
|
|
|
|
* @flags_value: a #GFlagsValue from @flags_class
|
|
|
|
*
|
|
|
|
* Retrieves the translated help for a given @flags_value.
|
|
|
|
*
|
|
|
|
* Return value: the translated help of the flags value
|
|
|
|
*
|
2015-06-01 03:18:09 +08:00
|
|
|
* Since: 2.2
|
2004-10-26 01:55:25 +08:00
|
|
|
**/
|
|
|
|
const gchar *
|
|
|
|
gimp_flags_value_get_help (GFlagsClass *flags_class,
|
|
|
|
GFlagsValue *flags_value)
|
|
|
|
{
|
|
|
|
GType type = G_TYPE_FROM_CLASS (flags_class);
|
|
|
|
GimpFlagsDesc *flags_desc;
|
|
|
|
|
|
|
|
flags_desc = gimp_flags_get_first_desc (flags_class, flags_value->value);
|
2004-07-29 20:33:15 +08:00
|
|
|
|
2004-10-26 01:55:25 +08:00
|
|
|
if (flags_desc->value_help)
|
2004-07-29 20:33:15 +08:00
|
|
|
return dgettext (gimp_type_get_translation_domain (type),
|
2004-10-26 01:55:25 +08:00
|
|
|
flags_desc->value_help);
|
2004-07-29 20:33:15 +08:00
|
|
|
|
|
|
|
return NULL;
|
|
|
|
}
|
libgimpbase: add gimp_{enum,flags}_value_get_abbrev()
Add support for specifying an abbreviated description for enum/
flags values, which can be used in contexts where the full
description is too long.
Since the exact layout and size of Gimp{Enum,Flags}Desc is part of
the ABI, we can't simply add a field to these structs to hold the
abbreviated description. Instead, we use the fact that entries
with a repeated value in the value descriptions array are ignored,
and that the array is NULL terminated (in particular, that all non-
NULL entries are followed by at least one additional entry), and
specify the abbreviation in the "value_desc" field of the entry
that immediately follows the initial entry for a given value,
setting the "value" field of both entries to the same value.
Right now this behavior is undocumented, so there is no proper way
to specify abbreviated descriptions in the API, and is only meant
to be used in generated enum files.
2017-11-30 04:33:32 +08:00
|
|
|
|
|
|
|
/**
|
|
|
|
* gimp_flags_value_get_abbrev:
|
|
|
|
* @flags_class: a #GFlagsClass
|
|
|
|
* @flags_value: a #GFlagsValue from @flags_class
|
|
|
|
*
|
|
|
|
* Retrieves the translated abbreviation for a given @flags_value.
|
|
|
|
*
|
|
|
|
* Return value: the translated abbreviation of the flags value
|
|
|
|
*
|
|
|
|
* Since: 2.10
|
|
|
|
**/
|
|
|
|
const gchar *
|
|
|
|
gimp_flags_value_get_abbrev (GFlagsClass *flags_class,
|
|
|
|
GFlagsValue *flags_value)
|
|
|
|
{
|
|
|
|
GType type = G_TYPE_FROM_CLASS (flags_class);
|
|
|
|
GimpFlagsDesc *flags_desc;
|
|
|
|
|
|
|
|
flags_desc = gimp_flags_get_first_desc (flags_class, flags_value->value);
|
|
|
|
|
|
|
|
if (flags_desc &&
|
|
|
|
flags_desc[1].value == flags_desc->value &&
|
|
|
|
flags_desc[1].value_desc)
|
|
|
|
{
|
2017-12-04 22:49:24 +08:00
|
|
|
return g_dpgettext2 (gimp_type_get_translation_domain (type),
|
|
|
|
gimp_type_get_translation_context (type),
|
|
|
|
flags_desc[1].value_desc);
|
libgimpbase: add gimp_{enum,flags}_value_get_abbrev()
Add support for specifying an abbreviated description for enum/
flags values, which can be used in contexts where the full
description is too long.
Since the exact layout and size of Gimp{Enum,Flags}Desc is part of
the ABI, we can't simply add a field to these structs to hold the
abbreviated description. Instead, we use the fact that entries
with a repeated value in the value descriptions array are ignored,
and that the array is NULL terminated (in particular, that all non-
NULL entries are followed by at least one additional entry), and
specify the abbreviation in the "value_desc" field of the entry
that immediately follows the initial entry for a given value,
setting the "value" field of both entries to the same value.
Right now this behavior is undocumented, so there is no proper way
to specify abbreviated descriptions in the API, and is only meant
to be used in generated enum files.
2017-11-30 04:33:32 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
return NULL;
|
|
|
|
}
|