diff --git a/gtk/Makefile.am b/gtk/Makefile.am index d2b91d696d..25729d04dc 100644 --- a/gtk/Makefile.am +++ b/gtk/Makefile.am @@ -568,6 +568,7 @@ gtk_private_h_sources = \ gtktooltipwindowprivate.h \ gtktreedatalist.h \ gtktreeprivate.h \ + gtkutilsprivate.h \ gtkwidgetprivate.h \ gtkwidgetpathprivate.h \ gtkwin32drawprivate.h \ @@ -928,6 +929,7 @@ gtk_base_c_sources = \ gtktreeview.c \ gtktreeviewcolumn.c \ gtktypebuiltins.c \ + gtkutils.c \ gtkvolumebutton.c \ gtkviewport.c \ gtkwidget.c \ diff --git a/gtk/gtkimmodule.c b/gtk/gtkimmodule.c index 065d5ba3e8..24a5f62302 100644 --- a/gtk/gtkimmodule.c +++ b/gtk/gtkimmodule.c @@ -35,6 +35,7 @@ #include "gtkimcontextsimple.h" #include "gtksettings.h" #include "gtkprivate.h" +#include "gtkutilsprivate.h" #include "gtkintl.h" #ifdef GDK_WINDOWING_X11 @@ -331,147 +332,6 @@ add_builtin_module (const gchar *module_name, return module; } -static gboolean -scan_string (const char **pos, GString *out) -{ - const char *p = *pos, *q = *pos; - char *tmp, *tmp2; - gboolean quoted; - - while (g_ascii_isspace (*p)) - p++; - - if (!*p) - return FALSE; - else if (*p == '"') - { - p++; - quoted = FALSE; - for (q = p; (*q != '"') || quoted; q++) - { - if (!*q) - return FALSE; - quoted = (*q == '\\') && !quoted; - } - - tmp = g_strndup (p, q - p); - tmp2 = g_strcompress (tmp); - g_string_truncate (out, 0); - g_string_append (out, tmp2); - g_free (tmp); - g_free (tmp2); - } - - q++; - *pos = q; - - return TRUE; -} - -static gboolean -skip_space (const char **pos) -{ - const char *p = *pos; - - while (g_ascii_isspace (*p)) - p++; - - *pos = p; - - return !(*p == '\0'); -} - -static gint -read_line (FILE *stream, GString *str) -{ - gboolean quoted = FALSE; - gboolean comment = FALSE; - int n_read = 0; - int lines = 1; - - flockfile (stream); - - g_string_truncate (str, 0); - - while (1) - { - int c; - - c = getc_unlocked (stream); - - if (c == EOF) - { - if (quoted) - g_string_append_c (str, '\\'); - - goto done; - } - else - n_read++; - - if (quoted) - { - quoted = FALSE; - - switch (c) - { - case '#': - g_string_append_c (str, '#'); - break; - case '\r': - case '\n': - { - int next_c = getc_unlocked (stream); - - if (!(next_c == EOF || - (c == '\r' && next_c == '\n') || - (c == '\n' && next_c == '\r'))) - ungetc (next_c, stream); - - lines++; - - break; - } - default: - g_string_append_c (str, '\\'); - g_string_append_c (str, c); - } - } - else - { - switch (c) - { - case '#': - comment = TRUE; - break; - case '\\': - if (!comment) - quoted = TRUE; - break; - case '\n': - { - int next_c = getc_unlocked (stream); - - if (!(c == EOF || - (c == '\r' && next_c == '\n') || - (c == '\n' && next_c == '\r'))) - ungetc (next_c, stream); - - goto done; - } - default: - if (!comment) - g_string_append_c (str, c); - } - } - } - - done: - funlockfile (stream); - - return (n_read > 0) ? lines : 0; -} - static void gtk_im_module_initialize (void) { @@ -558,13 +418,13 @@ gtk_im_module_initialize (void) return; } - while (!have_error && read_line (file, line_buf)) + while (!have_error && gtk_read_line (file, line_buf)) { const char *p; p = line_buf->str; - if (!skip_space (&p)) + if (!gtk_skip_space (&p)) { /* Blank line marking the end of a module */ @@ -584,7 +444,7 @@ gtk_im_module_initialize (void) */ module = g_object_new (GTK_TYPE_IM_MODULE, NULL); - if (!scan_string (&p, tmp_buf) || skip_space (&p)) + if (!gtk_scan_string (&p, tmp_buf) || gtk_skip_space (&p)) { g_warning ("Error parsing context info in '%s'\n %s", filename, line_buf->str); have_error = TRUE; @@ -602,19 +462,19 @@ gtk_im_module_initialize (void) /* Read information about a context type */ - if (!scan_string (&p, tmp_buf)) + if (!gtk_scan_string (&p, tmp_buf)) goto context_error; info->context_id = g_strdup (tmp_buf->str); - if (!scan_string (&p, tmp_buf)) + if (!gtk_scan_string (&p, tmp_buf)) goto context_error; info->context_name = g_strdup (tmp_buf->str); - if (!scan_string (&p, tmp_buf)) + if (!gtk_scan_string (&p, tmp_buf)) goto context_error; info->domain = g_strdup (tmp_buf->str); - if (!scan_string (&p, tmp_buf)) + if (!gtk_scan_string (&p, tmp_buf)) goto context_error; info->domain_dirname = g_strdup (tmp_buf->str); @@ -622,11 +482,11 @@ gtk_im_module_initialize (void) correct_localedir_prefix ((char **) &info->domain_dirname); #endif - if (!scan_string (&p, tmp_buf)) + if (!gtk_scan_string (&p, tmp_buf)) goto context_error; info->default_locales = g_strdup (tmp_buf->str); - if (skip_space (&p)) + if (gtk_skip_space (&p)) goto context_error; infos = g_slist_prepend (infos, info); diff --git a/gtk/gtkutils.c b/gtk/gtkutils.c new file mode 100644 index 0000000000..a6818b2bca --- /dev/null +++ b/gtk/gtkutils.c @@ -0,0 +1,193 @@ +/* GTK - The GIMP Toolkit + * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see .Free + */ + +/* + * Modified by the GTK+ Team and others 1997-2000. See the AUTHORS + * file for a list of people on the GTK+ Team. See the ChangeLog + * files for a list of changes. These files are distributed with + * GTK+ at ftp://ftp.gtk.org/pub/gtk/. + */ + +#include "config.h" + +#include +#include +#include +#include + +#include +#include + +/* Copied from pango-utils.c */ + +/* We need to call getc() a lot in a loop. This is suboptimal, + * as getc() does thread locking on the FILE it is given. + * To optimize that, lock the file first, then call getc(), + * then unlock. + * If locking functions are not present in libc, fall back + * to the suboptimal getc(). + */ +#if !defined(HAVE_FLOCKFILE) && !defined(HAVE__LOCK_FILE) +# define flockfile(f) (void)1 +# define funlockfile(f) (void)1 +# define getc_unlocked(f) getc(f) +#elif !defined(HAVE_FLOCKFILE) && defined(HAVE__LOCK_FILE) +# define flockfile(f) _lock_file(f) +# define funlockfile(f) _unlock_file(f) +# define getc_unlocked(f) _getc_nolock(f) +#endif + +gboolean +gtk_scan_string (const char **pos, GString *out) +{ + const char *p = *pos, *q = *pos; + char *tmp, *tmp2; + gboolean quoted; + + while (g_ascii_isspace (*p)) + p++; + + if (!*p) + return FALSE; + else if (*p == '"') + { + p++; + quoted = FALSE; + for (q = p; (*q != '"') || quoted; q++) + { + if (!*q) + return FALSE; + quoted = (*q == '\\') && !quoted; + } + + tmp = g_strndup (p, q - p); + tmp2 = g_strcompress (tmp); + g_string_truncate (out, 0); + g_string_append (out, tmp2); + g_free (tmp); + g_free (tmp2); + } + + q++; + *pos = q; + + return TRUE; +} + +gboolean +gtk_skip_space (const char **pos) +{ + const char *p = *pos; + + while (g_ascii_isspace (*p)) + p++; + + *pos = p; + + return !(*p == '\0'); +} + +gint +gtk_read_line (FILE *stream, GString *str) +{ + gboolean quoted = FALSE; + gboolean comment = FALSE; + int n_read = 0; + int lines = 1; + + flockfile (stream); + + g_string_truncate (str, 0); + + while (1) + { + int c; + + c = getc_unlocked (stream); + + if (c == EOF) + { + if (quoted) + g_string_append_c (str, '\\'); + + goto done; + } + else + n_read++; + + if (quoted) + { + quoted = FALSE; + + switch (c) + { + case '#': + g_string_append_c (str, '#'); + break; + case '\r': + case '\n': + { + int next_c = getc_unlocked (stream); + + if (!(next_c == EOF || + (c == '\r' && next_c == '\n') || + (c == '\n' && next_c == '\r'))) + ungetc (next_c, stream); + + lines++; + + break; + } + default: + g_string_append_c (str, '\\'); + g_string_append_c (str, c); + } + } + else + { + switch (c) + { + case '#': + comment = TRUE; + break; + case '\\': + if (!comment) + quoted = TRUE; + break; + case '\n': + { + int next_c = getc_unlocked (stream); + + if (!(c == EOF || + (c == '\r' && next_c == '\n') || + (c == '\n' && next_c == '\r'))) + ungetc (next_c, stream); + + goto done; + } + default: + if (!comment) + g_string_append_c (str, c); + } + } + } + + done: + funlockfile (stream); + + return (n_read > 0) ? lines : 0; +} diff --git a/gtk/gtkutilsprivate.h b/gtk/gtkutilsprivate.h new file mode 100644 index 0000000000..e5d34bbce0 --- /dev/null +++ b/gtk/gtkutilsprivate.h @@ -0,0 +1,16 @@ +#ifndef __GTKUTILS_H__ +#define __GTKUTILS_H__ + +#include + +G_BEGIN_DECLS + +gboolean gtk_scan_string (const char **pos, + GString *out); +gboolean gtk_skip_space (const char **pos); +gint gtk_read_line (FILE *stream, + GString *str); + +G_END_DECLS + +#endif