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