~ubuntu-branches/ubuntu/maverick/gimp/maverick-updates

« back to all changes in this revision

Viewing changes to libgimpbase/gimputils.c

  • Committer: Bazaar Package Importer
  • Author(s): Daniel Holbach
  • Date: 2005-12-09 19:44:52 UTC
  • Revision ID: james.westby@ubuntu.com-20051209194452-yggpemjlofpjqyf4
Tags: upstream-2.2.9
ImportĀ upstreamĀ versionĀ 2.2.9

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* LIBGIMP - The GIMP Library
 
2
 * Copyright (C) 1995-1997 Spencer Kimball and Peter Mattis
 
3
 *
 
4
 * gimputils.c
 
5
 * Copyright (C) 2003  Sven Neumann <sven@gimp.org>
 
6
 *
 
7
 * This library is free software; you can redistribute it and/or
 
8
 * modify it under the terms of the GNU Lesser General Public
 
9
 * License as published by the Free Software Foundation; either
 
10
 * version 2 of the License, or (at your option) any later version.
 
11
 *
 
12
 * This library is distributed in the hope that it will be useful,
 
13
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 
14
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 
15
 * Lesser General Public License for more details.
 
16
 *
 
17
 * You should have received a copy of the GNU Lesser General Public
 
18
 * License along with this library; if not, write to the
 
19
 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
 
20
 * Boston, MA 02111-1307, USA.
 
21
 */
 
22
 
 
23
#include "config.h"
 
24
 
 
25
#include <string.h>
 
26
 
 
27
#include <glib-object.h>
 
28
 
 
29
#include "gimpbasetypes.h"
 
30
#include "gimputils.h"
 
31
 
 
32
#include "libgimp/libgimp-intl.h"
 
33
 
 
34
 
 
35
/**
 
36
 * gimp_utf8_strtrim:
 
37
 * @str: an UTF-8 encoded string (or %NULL)
 
38
 * @max_chars: the maximum number of characters before the string get
 
39
 * trimmed
 
40
 *
 
41
 * Creates a (possibly trimmed) copy of @str. The string is cut if it
 
42
 * exceeds @max_chars characters or on the first newline. The fact
 
43
 * that the string was trimmed is indicated by appending an ellipsis.
 
44
 *
 
45
 * Returns: A (possibly trimmed) copy of @str which should be freed
 
46
 * using g_free() when it is not needed any longer.
 
47
 **/
 
48
gchar *
 
49
gimp_utf8_strtrim (const gchar *str,
 
50
                   gint         max_chars)
 
51
{
 
52
  /* FIXME: should we make this translatable? */
 
53
  static const gchar *ellipsis = "...";
 
54
  static const gint   e_len    = 3;
 
55
 
 
56
  if (str)
 
57
    {
 
58
      const gchar *p;
 
59
      const gchar *newline = NULL;
 
60
      gint         chars   = 0;
 
61
      gunichar     unichar;
 
62
 
 
63
      for (p = str; *p; p = g_utf8_next_char (p))
 
64
        {
 
65
          if (++chars > max_chars)
 
66
            break;
 
67
 
 
68
          unichar = g_utf8_get_char (p);
 
69
 
 
70
          switch (g_unichar_break_type (unichar))
 
71
            {
 
72
            case G_UNICODE_BREAK_MANDATORY:
 
73
            case G_UNICODE_BREAK_LINE_FEED:
 
74
              newline = p;
 
75
              break;
 
76
            default:
 
77
              continue;
 
78
            }
 
79
 
 
80
          break;
 
81
        }
 
82
 
 
83
      if (*p)
 
84
        {
 
85
          gsize  len     = p - str;
 
86
          gchar *trimmed = g_new (gchar, len + e_len + 2);
 
87
 
 
88
          memcpy (trimmed, str, len);
 
89
          if (newline)
 
90
            trimmed[len++] = ' ';
 
91
 
 
92
          g_strlcpy (trimmed + len, ellipsis, e_len + 1);
 
93
 
 
94
          return trimmed;
 
95
        }
 
96
 
 
97
      return g_strdup (str);
 
98
    }
 
99
 
 
100
  return NULL;
 
101
}
 
102
 
 
103
/**
 
104
 * gimp_any_to_utf8:
 
105
 * @str:            The string to be converted to UTF-8.
 
106
 * @len:            The length of the string, or -1 if the string
 
107
 *                  is nul-terminated.
 
108
 * @warning_format: The message format for the warning message if conversion
 
109
 *                  to UTF-8 fails. See the <function>printf()</function>
 
110
 *                  documentation.
 
111
 * @Varargs:        The parameters to insert into the format string.
 
112
 *
 
113
 * This function takes any string (UTF-8 or not) and always returns a valid
 
114
 * UTF-8 string.
 
115
 *
 
116
 * If @str is valid UTF-8, a copy of the string is returned.
 
117
 *
 
118
 * If UTF-8 validation fails, g_locale_to_utf8() is tried and if it
 
119
 * succeeds the resulting string is returned.
 
120
 *
 
121
 * Otherwise, the portion of @str that is UTF-8, concatenated
 
122
 * with "(invalid UTF-8 string)" is returned. If not even the start
 
123
 * of @str is valid UTF-8, only "(invalid UTF-8 string)" is returned.
 
124
 *
 
125
 * Return value: The UTF-8 string as described above.
 
126
 **/
 
127
gchar *
 
128
gimp_any_to_utf8 (const gchar  *str,
 
129
                  gssize        len,
 
130
                  const gchar  *warning_format,
 
131
                  ...)
 
132
{
 
133
  const gchar *start_invalid;
 
134
  gchar       *utf8;
 
135
 
 
136
  g_return_val_if_fail (str != NULL, NULL);
 
137
 
 
138
  if (g_utf8_validate (str, len, &start_invalid))
 
139
    {
 
140
      if (len < 0)
 
141
        utf8 = g_strdup (str);
 
142
      else
 
143
        utf8 = g_strndup (str, len);
 
144
    }
 
145
  else
 
146
    {
 
147
      utf8 = g_locale_to_utf8 (str, len, NULL, NULL, NULL);
 
148
    }
 
149
 
 
150
  if (! utf8)
 
151
    {
 
152
      if (warning_format)
 
153
        {
 
154
          va_list warning_args;
 
155
 
 
156
          va_start (warning_args, warning_format);
 
157
 
 
158
          g_logv (G_LOG_DOMAIN, G_LOG_LEVEL_MESSAGE,
 
159
                  warning_format, warning_args);
 
160
 
 
161
          va_end (warning_args);
 
162
        }
 
163
 
 
164
      if (start_invalid > str)
 
165
        {
 
166
          gchar *tmp;
 
167
 
 
168
          tmp = g_strndup (str, start_invalid - str);
 
169
          utf8 = g_strconcat (tmp, _("(invalid UTF-8 string)"), NULL);
 
170
          g_free (tmp);
 
171
        }
 
172
      else
 
173
        {
 
174
          utf8 = g_strdup (_("(invalid UTF-8 string)"));
 
175
        }
 
176
    }
 
177
 
 
178
  return utf8;
 
179
}
 
180
 
 
181
/**
 
182
 * gimp_filename_to_utf8:
 
183
 * @filename: The filename to be converted to UTF-8.
 
184
 *
 
185
 * Convert a filename in the filesystem's encoding to UTF-8
 
186
 * temporarily.  The return value is a pointer to a string that is
 
187
 * guaranteed to be valid only during the current iteration of the
 
188
 * main loop or until the next call to gimp_filename_to_utf8().
 
189
 *
 
190
 * The only purpose of this function is to provide an easy way to pass
 
191
 * a filename in the filesystem encoding to a function that expects an
 
192
 * UTF-8 encoded filename.
 
193
 *
 
194
 * Return value: A temporarily valid UTF-8 representation of @filename.
 
195
 *               This string must not be changed or freed.
 
196
 **/
 
197
const gchar *
 
198
gimp_filename_to_utf8 (const gchar *filename)
 
199
{
 
200
  /* Simpleminded implementation, but at least allocates just one copy
 
201
   * of each translation. Could check if already UTF-8, and if so
 
202
   * return filename as is. Could perhaps (re)use a suitably large
 
203
   * cyclic buffer, but then would have to verify that all calls
 
204
   * really need the return value just for a "short" time.
 
205
   */
 
206
 
 
207
  static GHashTable *ht = NULL;
 
208
  gchar             *filename_utf8;
 
209
 
 
210
  if (! filename)
 
211
    return NULL;
 
212
 
 
213
  if (! ht)
 
214
    ht = g_hash_table_new (g_str_hash, g_str_equal);
 
215
 
 
216
  filename_utf8 = g_hash_table_lookup (ht, filename);
 
217
 
 
218
  if (! filename_utf8)
 
219
    {
 
220
      filename_utf8 = g_filename_to_utf8 (filename, -1, NULL, NULL, NULL);
 
221
      g_hash_table_insert (ht, g_strdup (filename), filename_utf8);
 
222
    }
 
223
 
 
224
  return filename_utf8;
 
225
}
 
226
 
 
227
 
 
228
/**
 
229
 * gimp_strip_uline:
 
230
 * @str: underline infested string (or %NULL)
 
231
 *
 
232
 * This function returns a copy of @str stripped of underline
 
233
 * characters. This comes in handy when needing to strip mnemonics
 
234
 * from menu paths etc.
 
235
 *
 
236
 * In some languages, mnemonics are handled by adding the mnemonic
 
237
 * character in brackets (like "File (_F)"). This function recognizes
 
238
 * this construct and removes the whole bracket construction to get
 
239
 * rid of the mnemonic (see bug #157561).
 
240
 *
 
241
 * Return value: A (possibly stripped) copy of @str which should be
 
242
 *               freed using g_free() when it is not needed any longer.
 
243
 **/
 
244
gchar *
 
245
gimp_strip_uline (const gchar *str)
 
246
{
 
247
  gchar    *escaped;
 
248
  gchar    *p;
 
249
  gboolean  past_bracket = FALSE;
 
250
 
 
251
  if (! str)
 
252
    return NULL;
 
253
 
 
254
  p = escaped = g_strdup (str);
 
255
 
 
256
  while (*str)
 
257
    {
 
258
      if (*str == '_')
 
259
        {
 
260
          /*  "__" means a literal "_" in the menu path  */
 
261
          if (str[1] == '_')
 
262
            {
 
263
             *p++ = *str++;
 
264
             *p++ = *str++;
 
265
            }
 
266
 
 
267
          /*  find the "(_X)" construct and remove it entirely  */
 
268
          if (past_bracket && str[1] && *(g_utf8_next_char (str + 1)) == ')')
 
269
            {
 
270
              str = g_utf8_next_char (str + 1) + 1;
 
271
              p--;
 
272
            }
 
273
          else
 
274
            {
 
275
              str++;
 
276
            }
 
277
        }
 
278
      else
 
279
        {
 
280
          past_bracket = (*str == '(');
 
281
 
 
282
          *p++ = *str++;
 
283
        }
 
284
    }
 
285
 
 
286
  *p = '\0';
 
287
 
 
288
  return escaped;
 
289
}
 
290
 
 
291
/**
 
292
 * gimp_escape_uline:
 
293
 * @str: Underline infested string (or %NULL)
 
294
 *
 
295
 * This function returns a copy of @str with all underline converted
 
296
 * to two adjacent underlines. This comes in handy when needing to display
 
297
 * strings with underlines (like filenames) in a place that would convert
 
298
 * them to mnemonics.
 
299
 *
 
300
 * Return value: A (possibly escaped) copy of @str which should be
 
301
 * freed using g_free() when it is not needed any longer.
 
302
 *
 
303
 * Since: GIMP 2.2
 
304
 **/
 
305
gchar *
 
306
gimp_escape_uline (const gchar *str)
 
307
{
 
308
  gchar *escaped;
 
309
  gchar *p;
 
310
  gint   n_ulines = 0;
 
311
 
 
312
  if (! str)
 
313
    return NULL;
 
314
 
 
315
  for (p = (gchar *) str; *p; p++)
 
316
    if (*p == '_')
 
317
      n_ulines++;
 
318
 
 
319
  p = escaped = g_malloc (strlen (str) + n_ulines + 1);
 
320
 
 
321
  while (*str)
 
322
    {
 
323
      if (*str == '_')
 
324
        *p++ = '_';
 
325
 
 
326
      *p++ = *str++;
 
327
    }
 
328
 
 
329
  *p = '\0';
 
330
 
 
331
  return escaped;
 
332
}
 
333
 
 
334
/**
 
335
 * gimp_enum_get_desc:
 
336
 * @enum_class: a #GEnumClass
 
337
 * @value:      a value from @enum_class
 
338
 *
 
339
 * Retrieves #GimpEnumDesc associated with the given value, or %NULL.
 
340
 *
 
341
 * Return value: the value's #GimpEnumDesc.
 
342
 *
 
343
 * Since: GIMP 2.2
 
344
 **/
 
345
GimpEnumDesc *
 
346
gimp_enum_get_desc (GEnumClass *enum_class,
 
347
                    gint        value)
 
348
{
 
349
  const GimpEnumDesc *value_desc;
 
350
 
 
351
  g_return_val_if_fail (G_IS_ENUM_CLASS (enum_class), NULL);
 
352
 
 
353
  value_desc = gimp_enum_get_value_descriptions (G_TYPE_FROM_CLASS (enum_class));
 
354
 
 
355
  if (value_desc)
 
356
    {
 
357
      while (value_desc->value_desc)
 
358
        {
 
359
          if (value_desc->value == value)
 
360
            return (GimpEnumDesc *) value_desc;
 
361
 
 
362
          value_desc++;
 
363
        }
 
364
    }
 
365
 
 
366
  return NULL;
 
367
}
 
368
 
 
369
/**
 
370
 * gimp_enum_get_value:
 
371
 * @enum_type:  the #GType of a registered enum
 
372
 * @value:      an integer value
 
373
 * @value_name: return location for the value's name (or %NULL)
 
374
 * @value_nick: return location for the value's nick (or %NULL)
 
375
 * @value_desc: return location for the value's translated desc (or %NULL)
 
376
 * @value_help: return location for the value's translated help (or %NULL)
 
377
 *
 
378
 * Checks if @value is valid for the enum registered as @enum_type.
 
379
 * If the value exists in that enum, its name, nick and its translated
 
380
 * desc and help are returned (if @value_name, @value_nick, @value_desc
 
381
 * and @value_help are not %NULL).
 
382
 *
 
383
 * Return value: %TRUE if @value is valid for the @enum_type,
 
384
 *               %FALSE otherwise
 
385
 *
 
386
 * Since: GIMP 2.2
 
387
 **/
 
388
gboolean
 
389
gimp_enum_get_value (GType         enum_type,
 
390
                     gint          value,
 
391
                     const gchar **value_name,
 
392
                     const gchar **value_nick,
 
393
                     const gchar **value_desc,
 
394
                     const gchar **value_help)
 
395
{
 
396
  GEnumClass *enum_class;
 
397
  GEnumValue *enum_value;
 
398
  gboolean    success = FALSE;
 
399
 
 
400
  g_return_val_if_fail (G_TYPE_IS_ENUM (enum_type), FALSE);
 
401
 
 
402
  enum_class = g_type_class_ref (enum_type);
 
403
  enum_value = g_enum_get_value (enum_class, value);
 
404
 
 
405
  if (enum_value)
 
406
    {
 
407
      if (value_name)
 
408
        *value_name = enum_value->value_name;
 
409
 
 
410
      if (value_nick)
 
411
        *value_nick = enum_value->value_nick;
 
412
 
 
413
      if (value_desc || value_help)
 
414
        {
 
415
          GimpEnumDesc *enum_desc;
 
416
 
 
417
          enum_desc = gimp_enum_get_desc (enum_class, value);
 
418
 
 
419
          if (value_desc)
 
420
            *value_desc = ((enum_desc && enum_desc->value_desc) ?
 
421
                           dgettext (gimp_type_get_translation_domain (enum_type),
 
422
                                     enum_desc->value_desc) :
 
423
                           NULL);
 
424
 
 
425
          if (value_help)
 
426
            *value_help = ((enum_desc && enum_desc->value_desc) ?
 
427
                           dgettext (gimp_type_get_translation_domain (enum_type),
 
428
                                     enum_desc->value_help) :
 
429
                           NULL);
 
430
        }
 
431
 
 
432
      success = TRUE;
 
433
    }
 
434
 
 
435
  g_type_class_unref (enum_class);
 
436
 
 
437
  return success;
 
438
}
 
439
 
 
440
/**
 
441
 * gimp_enum_value_get_desc:
 
442
 * @enum_class: a #GEnumClass
 
443
 * @enum_value: a #GEnumValue from @enum_class
 
444
 *
 
445
 * Retrieves the translated desc for a given @enum_value.
 
446
 *
 
447
 * Return value: the translated desc of the enum value
 
448
 *
 
449
 * Since: GIMP 2.2
 
450
 **/
 
451
const gchar *
 
452
gimp_enum_value_get_desc (GEnumClass *enum_class,
 
453
                          GEnumValue *enum_value)
 
454
{
 
455
  GType         type = G_TYPE_FROM_CLASS (enum_class);
 
456
  GimpEnumDesc *enum_desc;
 
457
 
 
458
  enum_desc = gimp_enum_get_desc (enum_class, enum_value->value);
 
459
 
 
460
  if (enum_desc && enum_desc->value_desc)
 
461
    return dgettext (gimp_type_get_translation_domain (type),
 
462
                     enum_desc->value_desc);
 
463
 
 
464
  return enum_value->value_name;
 
465
}
 
466
 
 
467
/**
 
468
 * gimp_enum_value_get_help:
 
469
 * @enum_class: a #GEnumClass
 
470
 * @enum_value: a #GEnumValue from @enum_class
 
471
 *
 
472
 * Retrieves the translated help for a given @enum_value.
 
473
 *
 
474
 * Return value: the translated help of the enum value
 
475
 *
 
476
 * Since: GIMP 2.2
 
477
 **/
 
478
const gchar *
 
479
gimp_enum_value_get_help (GEnumClass *enum_class,
 
480
                          GEnumValue *enum_value)
 
481
{
 
482
  GType         type = G_TYPE_FROM_CLASS (enum_class);
 
483
  GimpEnumDesc *enum_desc;
 
484
 
 
485
  enum_desc = gimp_enum_get_desc (enum_class, enum_value->value);
 
486
 
 
487
  if (enum_desc && enum_desc->value_help)
 
488
    return dgettext (gimp_type_get_translation_domain (type),
 
489
                     enum_desc->value_help);
 
490
 
 
491
  return NULL;
 
492
}
 
493
 
 
494
/**
 
495
 * gimp_flags_get_first_desc:
 
496
 * @flags_class: a #GFlagsClass
 
497
 * @value:       a value from @flags_class
 
498
 *
 
499
 * Retrieves the first #GimpFlagsDesc that matches the given value, or %NULL.
 
500
 *
 
501
 * Return value: the value's #GimpFlagsDesc.
 
502
 *
 
503
 * Since: GIMP 2.2
 
504
 **/
 
505
GimpFlagsDesc *
 
506
gimp_flags_get_first_desc (GFlagsClass *flags_class,
 
507
                           guint        value)
 
508
{
 
509
  const GimpFlagsDesc *value_desc;
 
510
 
 
511
  g_return_val_if_fail (G_IS_FLAGS_CLASS (flags_class), NULL);
 
512
 
 
513
  value_desc = gimp_flags_get_value_descriptions (G_TYPE_FROM_CLASS (flags_class));
 
514
 
 
515
  if (value_desc)
 
516
    {
 
517
      while (value_desc->value_desc)
 
518
        {
 
519
          if ((value_desc->value & value) == value_desc->value)
 
520
            return (GimpFlagsDesc *) value_desc;
 
521
 
 
522
          value_desc++;
 
523
        }
 
524
    }
 
525
 
 
526
  return NULL;
 
527
}
 
528
 
 
529
/**
 
530
 * gimp_flags_get_first_value:
 
531
 * @flags_type: the #GType of registered flags
 
532
 * @value:      an integer value
 
533
 * @value_name: return location for the value's name (or %NULL)
 
534
 * @value_nick: return location for the value's nick (or %NULL)
 
535
 * @value_desc: return location for the value's translated desc (or %NULL)
 
536
 * @value_help: return location for the value's translated help (or %NULL)
 
537
 *
 
538
 * Checks if @value is valid for the flags registered as @flags_type.
 
539
 * If the value exists in that flags, its name, nick and its translated
 
540
 * desc and help are returned (if @value_name, @value_nick, @value_desc
 
541
 * and @value_help are not %NULL).
 
542
 *
 
543
 * Return value: %TRUE if @value is valid for the @flags_type,
 
544
 *               %FALSE otherwise
 
545
 *
 
546
 * Since: GIMP 2.2
 
547
 **/
 
548
gboolean
 
549
gimp_flags_get_first_value (GType         flags_type,
 
550
                            guint         value,
 
551
                            const gchar **value_name,
 
552
                            const gchar **value_nick,
 
553
                            const gchar **value_desc,
 
554
                            const gchar **value_help)
 
555
{
 
556
  GFlagsClass *flags_class;
 
557
  GFlagsValue *flags_value;
 
558
 
 
559
  g_return_val_if_fail (G_TYPE_IS_FLAGS (flags_type), FALSE);
 
560
 
 
561
  flags_class = g_type_class_peek (flags_type);
 
562
  flags_value = g_flags_get_first_value (flags_class, value);
 
563
 
 
564
  if (flags_value)
 
565
    {
 
566
      if (value_name)
 
567
        *value_name = flags_value->value_name;
 
568
 
 
569
      if (value_nick)
 
570
        *value_nick = flags_value->value_nick;
 
571
 
 
572
      if (value_desc || value_help)
 
573
        {
 
574
          GimpFlagsDesc *flags_desc;
 
575
 
 
576
          flags_desc = gimp_flags_get_first_desc (flags_class, value);
 
577
 
 
578
          if (value_desc)
 
579
            *value_desc = ((flags_desc && flags_desc->value_desc) ?
 
580
                           dgettext (gimp_type_get_translation_domain (flags_type),
 
581
                                     flags_desc->value_desc) :
 
582
                           NULL);
 
583
 
 
584
          if (value_help)
 
585
            *value_help = ((flags_desc && flags_desc->value_desc) ?
 
586
                           dgettext (gimp_type_get_translation_domain (flags_type),
 
587
                                     flags_desc->value_help) :
 
588
                           NULL);
 
589
        }
 
590
 
 
591
      return TRUE;
 
592
    }
 
593
 
 
594
  return FALSE;
 
595
}
 
596
 
 
597
/**
 
598
 * gimp_flags_value_get_desc:
 
599
 * @flags_class: a #GFlagsClass
 
600
 * @flags_value: a #GFlagsValue from @flags_class
 
601
 *
 
602
 * Retrieves the translated desc for a given @flags_value.
 
603
 *
 
604
 * Return value: the translated desc of the flags value
 
605
 *
 
606
 * Since: GIMP 2.2
 
607
 **/
 
608
const gchar *
 
609
gimp_flags_value_get_desc (GFlagsClass *flags_class,
 
610
                           GFlagsValue *flags_value)
 
611
{
 
612
  GType         type = G_TYPE_FROM_CLASS (flags_class);
 
613
  GimpFlagsDesc *flags_desc;
 
614
 
 
615
  flags_desc = gimp_flags_get_first_desc (flags_class, flags_value->value);
 
616
 
 
617
  if (flags_desc->value_desc)
 
618
    return dgettext (gimp_type_get_translation_domain (type),
 
619
                     flags_desc->value_desc);
 
620
 
 
621
  return flags_value->value_name;
 
622
}
 
623
 
 
624
/**
 
625
 * gimp_flags_value_get_help:
 
626
 * @flags_class: a #GFlagsClass
 
627
 * @flags_value: a #GFlagsValue from @flags_class
 
628
 *
 
629
 * Retrieves the translated help for a given @flags_value.
 
630
 *
 
631
 * Return value: the translated help of the flags value
 
632
 *
 
633
 * Since: GIMP 2.2
 
634
 **/
 
635
const gchar *
 
636
gimp_flags_value_get_help (GFlagsClass *flags_class,
 
637
                           GFlagsValue *flags_value)
 
638
{
 
639
  GType         type = G_TYPE_FROM_CLASS (flags_class);
 
640
  GimpFlagsDesc *flags_desc;
 
641
 
 
642
  flags_desc = gimp_flags_get_first_desc (flags_class, flags_value->value);
 
643
 
 
644
  if (flags_desc->value_help)
 
645
    return dgettext (gimp_type_get_translation_domain (type),
 
646
                     flags_desc->value_help);
 
647
 
 
648
  return NULL;
 
649
}