From 3ade071f273aaa973e44bf95d6b1d4913a18f03b Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Sun, 7 Apr 2024 19:39:48 +0200 Subject: Adding upstream version 43.2. Signed-off-by: Daniel Baumann --- eel/check-eel | 3 + eel/check-program.c | 58 +++++ eel/eel-art-extensions.c | 191 +++++++++++++++ eel/eel-art-extensions.h | 61 +++++ eel/eel-debug.c | 105 ++++++++ eel/eel-debug.h | 40 +++ eel/eel-glib-extensions.h | 30 +++ eel/eel-graphic-effects.c | 165 +++++++++++++ eel/eel-graphic-effects.h | 32 +++ eel/eel-lib-self-check-functions.c | 35 +++ eel/eel-lib-self-check-functions.h | 45 ++++ eel/eel-self-checks.c | 203 +++++++++++++++ eel/eel-self-checks.h | 78 ++++++ eel/eel-stock-dialogs.c | 292 ++++++++++++++++++++++ eel/eel-stock-dialogs.h | 40 +++ eel/eel-string.c | 488 +++++++++++++++++++++++++++++++++++++ eel/eel-string.h | 79 ++++++ eel/eel-vfs-extensions.c | 204 ++++++++++++++++ eel/eel-vfs-extensions.h | 50 ++++ eel/eel.h | 31 +++ eel/meson.build | 54 ++++ 21 files changed, 2284 insertions(+) create mode 100755 eel/check-eel create mode 100644 eel/check-program.c create mode 100644 eel/eel-art-extensions.c create mode 100644 eel/eel-art-extensions.h create mode 100644 eel/eel-debug.c create mode 100644 eel/eel-debug.h create mode 100644 eel/eel-glib-extensions.h create mode 100644 eel/eel-graphic-effects.c create mode 100644 eel/eel-graphic-effects.h create mode 100644 eel/eel-lib-self-check-functions.c create mode 100644 eel/eel-lib-self-check-functions.h create mode 100644 eel/eel-self-checks.c create mode 100644 eel/eel-self-checks.h create mode 100644 eel/eel-stock-dialogs.c create mode 100644 eel/eel-stock-dialogs.h create mode 100644 eel/eel-string.c create mode 100644 eel/eel-string.h create mode 100644 eel/eel-vfs-extensions.c create mode 100644 eel/eel-vfs-extensions.h create mode 100644 eel/eel.h create mode 100644 eel/meson.build (limited to 'eel') diff --git a/eel/check-eel b/eel/check-eel new file mode 100755 index 0000000..009e7dd --- /dev/null +++ b/eel/check-eel @@ -0,0 +1,3 @@ +#!/bin/sh +G_DEBUG=fatal-warnings ./check-program --sm-disable + diff --git a/eel/check-program.c b/eel/check-program.c new file mode 100644 index 0000000..04cbc7d --- /dev/null +++ b/eel/check-program.c @@ -0,0 +1,58 @@ +/* check-program.c: A simple driver for eel self checks. + * + * Copyright (C) 2000 Eazel, Inc. + * + * The Gnome Library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * The Gnome 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with the Gnome Library; see the file COPYING.LIB. If not, + * see . + * + * Authors: Ramiro Estrugo + */ + +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +int +main (int argc, + char *argv[]) +{ +#if !defined (EEL_OMIT_SELF_CHECK) + + eel_make_warnings_and_criticals_stop_in_debugger (); + + + LIBXML_TEST_VERSION + gtk_init (); + + /* Run the checks for eel twice. */ + + eel_run_lib_self_checks (); + eel_exit_if_self_checks_failed (); + + eel_run_lib_self_checks (); + eel_exit_if_self_checks_failed (); + + eel_debug_shut_down (); + +#endif /* !EEL_OMIT_SELF_CHECK */ + + return EXIT_SUCCESS; +} diff --git a/eel/eel-art-extensions.c b/eel/eel-art-extensions.c new file mode 100644 index 0000000..f9f4c9a --- /dev/null +++ b/eel/eel-art-extensions.c @@ -0,0 +1,191 @@ +/* eel-art-extensions.c - implementation of libart extension functions. + * + * Copyright (C) 2000 Eazel, Inc. + * + * The Gnome Library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * The Gnome 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with the Gnome Library; see the file COPYING.LIB. If not, + * see . + * + * Authors: Darin Adler + * Ramiro Estrugo + */ + +#include + +#include "eel-art-extensions.h" +#include "eel-lib-self-check-functions.h" +#include + +const EelDRect eel_drect_empty = { 0.0, 0.0, 0.0, 0.0 }; +const EelIRect eel_irect_empty = { 0, 0, 0, 0 }; + +static void +eel_irect_copy (EelIRect *dest, + const EelIRect *src) +{ + dest->x0 = src->x0; + dest->y0 = src->y0; + dest->x1 = src->x1; + dest->y1 = src->y1; +} + +static gboolean +eel_irect_is_empty (const EelIRect *src) +{ + return (src->x1 <= src->x0 || + src->y1 <= src->y0); +} + +void +eel_irect_union (EelIRect *dest, + const EelIRect *src1, + const EelIRect *src2) +{ + if (eel_irect_is_empty (src1)) + { + eel_irect_copy (dest, src2); + } + else if (eel_irect_is_empty (src2)) + { + eel_irect_copy (dest, src1); + } + else + { + dest->x0 = MIN (src1->x0, src2->x0); + dest->y0 = MIN (src1->y0, src2->y0); + dest->x1 = MAX (src1->x1, src2->x1); + dest->y1 = MAX (src1->y1, src2->y1); + } +} + +static void +eel_irect_intersect (EelIRect *dest, + const EelIRect *src1, + const EelIRect *src2) +{ + dest->x0 = MAX (src1->x0, src2->x0); + dest->y0 = MAX (src1->y0, src2->y0); + dest->x1 = MIN (src1->x1, src2->x1); + dest->y1 = MIN (src1->y1, src2->y1); +} + +/** + * eel_irect_get_width: + * + * @rectangle: An EelIRect. + * + * Returns: The width of the rectangle. + * + */ +int +eel_irect_get_width (EelIRect rectangle) +{ + return rectangle.x1 - rectangle.x0; +} + +/** + * eel_irect_get_height: + * + * @rectangle: An EelIRect. + * + * Returns: The height of the rectangle. + * + */ +int +eel_irect_get_height (EelIRect rectangle) +{ + return rectangle.y1 - rectangle.y0; +} + + +static void +eel_drect_copy (EelDRect *dest, + const EelDRect *src) +{ + dest->x0 = src->x0; + dest->y0 = src->y0; + dest->x1 = src->x1; + dest->y1 = src->y1; +} + +static gboolean +eel_drect_is_empty (const EelDRect *src) +{ + return (src->x1 <= src->x0 || src->y1 <= src->y0); +} + +void +eel_drect_union (EelDRect *dest, + const EelDRect *src1, + const EelDRect *src2) +{ + if (eel_drect_is_empty (src1)) + { + eel_drect_copy (dest, src2); + } + else if (eel_drect_is_empty (src2)) + { + eel_drect_copy (dest, src1); + } + else + { + dest->x0 = MIN (src1->x0, src2->x0); + dest->y0 = MIN (src1->y0, src2->y0); + dest->x1 = MAX (src1->x1, src2->x1); + dest->y1 = MAX (src1->y1, src2->y1); + } +} + +gboolean +eel_irect_hits_irect (EelIRect rectangle_a, + EelIRect rectangle_b) +{ + EelIRect intersection; + eel_irect_intersect (&intersection, &rectangle_a, &rectangle_b); + return !eel_irect_is_empty (&intersection); +} + +gboolean +eel_irect_equal (EelIRect rectangle_a, + EelIRect rectangle_b) +{ + return rectangle_a.x0 == rectangle_b.x0 + && rectangle_a.y0 == rectangle_b.y0 + && rectangle_a.x1 == rectangle_b.x1 + && rectangle_a.y1 == rectangle_b.y1; +} + +EelIRect +eel_irect_offset_by (EelIRect rectangle, + int x, + int y) +{ + rectangle.x0 += x; + rectangle.x1 += x; + rectangle.y0 += y; + rectangle.y1 += y; + + return rectangle; +} + +EelIRect +eel_irect_scale_by (EelIRect rectangle, + double scale) +{ + rectangle.x0 *= scale; + rectangle.x1 *= scale; + rectangle.y0 *= scale; + rectangle.y1 *= scale; + + return rectangle; +} diff --git a/eel/eel-art-extensions.h b/eel/eel-art-extensions.h new file mode 100644 index 0000000..b9dde53 --- /dev/null +++ b/eel/eel-art-extensions.h @@ -0,0 +1,61 @@ + +/* eel-art-extensions.h - interface of libart extension functions. + + Copyright (C) 2000 Eazel, Inc. + + The Gnome Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + The Gnome 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the Gnome Library; see the file COPYING.LIB. If not, + see . + + Authors: Darin Adler + Ramiro Estrugo +*/ + +#pragma once + +#include + +G_BEGIN_DECLS + +typedef struct { + double x0, y0, x1, y1; +} EelDRect; + +typedef struct { + /*< public >*/ + int x0, y0, x1, y1; +} EelIRect; + +extern const EelDRect eel_drect_empty; +extern const EelIRect eel_irect_empty; + +void eel_irect_union (EelIRect *dest, + const EelIRect *src1, + const EelIRect *src2); +gboolean eel_irect_equal (EelIRect rectangle_a, + EelIRect rectangle_b); +gboolean eel_irect_hits_irect (EelIRect rectangle_a, + EelIRect rectangle_b); +EelIRect eel_irect_offset_by (EelIRect rectangle, + int x, + int y); +EelIRect eel_irect_scale_by (EelIRect rectangle, + double scale); +int eel_irect_get_width (EelIRect rectangle); +int eel_irect_get_height (EelIRect rectangle); + +void eel_drect_union (EelDRect *dest, + const EelDRect *src1, + const EelDRect *src2); + +G_END_DECLS \ No newline at end of file diff --git a/eel/eel-debug.c b/eel/eel-debug.c new file mode 100644 index 0000000..f3d94ec --- /dev/null +++ b/eel/eel-debug.c @@ -0,0 +1,105 @@ +/* + * eel-debug.c: Eel debugging aids. + * + * Copyright (C) 2000, 2001 Eazel, Inc. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * This program 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this program; if not, see . + * + * Author: Darin Adler + */ + +#include +#include "eel-debug.h" + +#include +#include +#include + +typedef struct +{ + gpointer data; + GFreeFunc function; +} ShutdownFunction; + +static GList *shutdown_functions; + +/* Raise a SIGINT signal to get the attention of the debugger. + * When not running under the debugger, we don't want to stop, + * so we ignore the signal for just the moment that we raise it. + */ +static void +eel_stop_in_debugger (void) +{ + void (*saved_handler) (int); + + saved_handler = signal (SIGINT, SIG_IGN); + raise (SIGINT); + signal (SIGINT, saved_handler); +} + +/* Stop in the debugger after running the default log handler. + * This makes certain kinds of messages stop in the debugger + * without making them fatal (you can continue). + */ +static void +log_handler (const char *domain, + GLogLevelFlags level, + const char *message, + gpointer data) +{ + g_log_default_handler (domain, level, message, data); + if ((level & (G_LOG_LEVEL_CRITICAL | G_LOG_LEVEL_WARNING)) != 0) + { + eel_stop_in_debugger (); + } +} + +void +eel_make_warnings_and_criticals_stop_in_debugger (void) +{ + g_log_set_default_handler (log_handler, NULL); +} + +void +eel_debug_shut_down (void) +{ + ShutdownFunction *f; + + while (shutdown_functions != NULL) + { + f = shutdown_functions->data; + shutdown_functions = g_list_remove (shutdown_functions, f); + + f->function (f->data); + g_free (f); + } +} + +void +eel_debug_call_at_shutdown (EelFunction function) +{ + eel_debug_call_at_shutdown_with_data ((GFreeFunc) function, NULL); +} + +void +eel_debug_call_at_shutdown_with_data (GFreeFunc function, + gpointer data) +{ + ShutdownFunction *f; + + f = g_new (ShutdownFunction, 1); + f->data = data; + f->function = function; + shutdown_functions = g_list_prepend (shutdown_functions, f); +} diff --git a/eel/eel-debug.h b/eel/eel-debug.h new file mode 100644 index 0000000..5d65932 --- /dev/null +++ b/eel/eel-debug.h @@ -0,0 +1,40 @@ +/* + eel-debug.h: Eel debugging aids. + + Copyright (C) 2000, 2001 Eazel, Inc. + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + This program 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this program; if not, see . + + Author: Darin Adler +*/ + +#pragma once + +#include + +G_BEGIN_DECLS + +typedef void (* EelFunction) (void); + +void eel_make_warnings_and_criticals_stop_in_debugger (void); + +/* A way to do cleanup at exit for compatibility with shutdown tools + * like the ones in Bonobo. + */ +void eel_debug_shut_down (void); +void eel_debug_call_at_shutdown (EelFunction function); +void eel_debug_call_at_shutdown_with_data (GFreeFunc function, + gpointer data); + +G_END_DECLS \ No newline at end of file diff --git a/eel/eel-glib-extensions.h b/eel/eel-glib-extensions.h new file mode 100644 index 0000000..3b0ea0d --- /dev/null +++ b/eel/eel-glib-extensions.h @@ -0,0 +1,30 @@ + +/* eel-glib-extensions.h - interface for new functions that conceptually + belong in glib. Perhaps some of these will be + actually rolled into glib someday. + + Copyright (C) 2000 Eazel, Inc. + + The Gnome Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + The Gnome 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the Gnome Library; see the file COPYING.LIB. If not, + see . + + Authors: John Sullivan +*/ + +#pragma once + +#include + +/* A gboolean variant for bit fields. */ +typedef guint eel_boolean_bit; diff --git a/eel/eel-graphic-effects.c b/eel/eel-graphic-effects.c new file mode 100644 index 0000000..06af091 --- /dev/null +++ b/eel/eel-graphic-effects.c @@ -0,0 +1,165 @@ +/* Eel - pixbuf manipulation routines for graphical effects. + * + * Copyright (C) 2000 Eazel, Inc + * + * Author: Andy Hertzfeld + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, see . + */ + +/* This file contains pixbuf manipulation routines used for graphical effects like pre-lighting + * and selection hilighting */ + +#include + +#include "eel-graphic-effects.h" +#include "eel-glib-extensions.h" + +#include +#include + +/* shared utility to create a new pixbuf from the passed-in one */ + +static GdkPixbuf * +create_new_pixbuf (GdkPixbuf *src) +{ + g_assert (gdk_pixbuf_get_colorspace (src) == GDK_COLORSPACE_RGB); + g_assert ((!gdk_pixbuf_get_has_alpha (src) + && gdk_pixbuf_get_n_channels (src) == 3) + || (gdk_pixbuf_get_has_alpha (src) + && gdk_pixbuf_get_n_channels (src) == 4)); + + return gdk_pixbuf_new (gdk_pixbuf_get_colorspace (src), + gdk_pixbuf_get_has_alpha (src), + gdk_pixbuf_get_bits_per_sample (src), + gdk_pixbuf_get_width (src), + gdk_pixbuf_get_height (src)); +} + +/* utility routine to bump the level of a color component with pinning */ + +const int HOVER_COMPONENT_ADDITION = 15; + +static guchar +lighten_component (guchar cur_value) +{ + int new_value = cur_value; + new_value = cur_value + HOVER_COMPONENT_ADDITION; + if (new_value > 255) + { + new_value = 255; + } + return (guchar) new_value; +} + +GdkPixbuf * +eel_create_spotlight_pixbuf (GdkPixbuf *src) +{ + GdkPixbuf *dest; + int i, j; + int width, height, has_alpha, src_row_stride, dst_row_stride; + guchar *target_pixels, *original_pixels; + guchar *pixsrc, *pixdest; + + g_return_val_if_fail (gdk_pixbuf_get_colorspace (src) == GDK_COLORSPACE_RGB, NULL); + g_return_val_if_fail ((!gdk_pixbuf_get_has_alpha (src) + && gdk_pixbuf_get_n_channels (src) == 3) + || (gdk_pixbuf_get_has_alpha (src) + && gdk_pixbuf_get_n_channels (src) == 4), NULL); + g_return_val_if_fail (gdk_pixbuf_get_bits_per_sample (src) == 8, NULL); + + dest = create_new_pixbuf (src); + + has_alpha = gdk_pixbuf_get_has_alpha (src); + width = gdk_pixbuf_get_width (src); + height = gdk_pixbuf_get_height (src); + dst_row_stride = gdk_pixbuf_get_rowstride (dest); + src_row_stride = gdk_pixbuf_get_rowstride (src); + target_pixels = gdk_pixbuf_get_pixels (dest); + original_pixels = gdk_pixbuf_get_pixels (src); + + for (i = 0; i < height; i++) + { + pixdest = target_pixels + i * dst_row_stride; + pixsrc = original_pixels + i * src_row_stride; + for (j = 0; j < width; j++) + { + *pixdest++ = lighten_component (*pixsrc++); + *pixdest++ = lighten_component (*pixsrc++); + *pixdest++ = lighten_component (*pixsrc++); + if (has_alpha) + { + *pixdest++ = *pixsrc++; + } + } + } + return dest; +} + +/* This routine colorizes %src by multiplying each pixel with colors in %dest. */ + +GdkPixbuf * +eel_create_colorized_pixbuf (GdkPixbuf *src, + GdkPixbuf *dest) +{ + int i, j; + int width, height, has_alpha, src_row_stride, dst_row_stride; + guchar *target_pixels; + guchar *original_pixels; + guchar *pixsrc; + guchar *pixdest; + + g_return_val_if_fail (gdk_pixbuf_get_colorspace (src) == GDK_COLORSPACE_RGB, NULL); + g_return_val_if_fail (gdk_pixbuf_get_colorspace (dest) == GDK_COLORSPACE_RGB, NULL); + + g_return_val_if_fail ((!gdk_pixbuf_get_has_alpha (src) + && gdk_pixbuf_get_n_channels (src) == 3) + || (gdk_pixbuf_get_has_alpha (src) + && gdk_pixbuf_get_n_channels (src) == 4), NULL); + g_return_val_if_fail ((!gdk_pixbuf_get_has_alpha (dest) + && gdk_pixbuf_get_n_channels (dest) == 3) + || (gdk_pixbuf_get_has_alpha (dest) + && gdk_pixbuf_get_n_channels (dest) == 4), NULL); + + g_return_val_if_fail (gdk_pixbuf_get_bits_per_sample (src) == 8, NULL); + g_return_val_if_fail (gdk_pixbuf_get_bits_per_sample (dest) == 8, NULL); + + has_alpha = gdk_pixbuf_get_has_alpha (src); + width = gdk_pixbuf_get_width (src); + height = gdk_pixbuf_get_height (src); + src_row_stride = gdk_pixbuf_get_rowstride (src); + dst_row_stride = gdk_pixbuf_get_rowstride (dest); + target_pixels = gdk_pixbuf_get_pixels (dest); + original_pixels = gdk_pixbuf_get_pixels (src); + + for (i = 0; i < height; i++) + { + pixdest = target_pixels + i * dst_row_stride; + pixsrc = original_pixels + i * src_row_stride; + for (j = 0; j < width; j++) + { + *pixdest = ((*pixsrc++) * (*pixdest)) >> 8; + pixdest++; + *pixdest = ((*pixsrc++) * (*pixdest)) >> 8; + pixdest++; + *pixdest = ((*pixsrc++) * (*pixdest)) >> 8; + pixdest++; + if (has_alpha) + { + *pixdest++ = *pixsrc++; + } + } + } + return dest; +} diff --git a/eel/eel-graphic-effects.h b/eel/eel-graphic-effects.h new file mode 100644 index 0000000..67de5f7 --- /dev/null +++ b/eel/eel-graphic-effects.h @@ -0,0 +1,32 @@ +/* + eel-graphic-effects.h: Pixmap manipulation routines for graphical effects. + + Copyright (C) 2000 Eazel, Inc. + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + This program 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this program; if not, see . + + Authors: Andy Hertzfeld + */ + +#pragma once + +#include +#include + +/* return a lightened pixbuf for pre-lighting */ +GdkPixbuf *eel_create_spotlight_pixbuf (GdkPixbuf *source_pixbuf); + +/* return a pixbuf colorized with the color specified by the parameters */ +GdkPixbuf* eel_create_colorized_pixbuf (GdkPixbuf *source_pixbuf, + GdkPixbuf *dest); diff --git a/eel/eel-lib-self-check-functions.c b/eel/eel-lib-self-check-functions.c new file mode 100644 index 0000000..af1dddf --- /dev/null +++ b/eel/eel-lib-self-check-functions.c @@ -0,0 +1,35 @@ +/* + * eel-lib-self-check-functions.c: Wrapper for all self check functions + * in Eel proper. + * + * Copyright (C) 2000 Eazel, Inc. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * This program 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this program; if not, see . + * + * Author: Darin Adler + */ + +#include + +#if !defined (EEL_OMIT_SELF_CHECK) + +#include "eel-lib-self-check-functions.h" + +void +eel_run_lib_self_checks (void) +{ + EEL_LIB_FOR_EACH_SELF_CHECK_FUNCTION (EEL_CALL_SELF_CHECK_FUNCTION) +} + +#endif /* ! EEL_OMIT_SELF_CHECK */ diff --git a/eel/eel-lib-self-check-functions.h b/eel/eel-lib-self-check-functions.h new file mode 100644 index 0000000..3a21430 --- /dev/null +++ b/eel/eel-lib-self-check-functions.h @@ -0,0 +1,45 @@ +/* + eel-lib-self-check-functions.h: Wrapper and prototypes for all + self-check functions in libeel. + + Copyright (C) 2000 Eazel, Inc. + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + This program 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this program; if not, see . + + Author: Darin Adler +*/ + +#pragma once + +#include "eel-self-checks.h" + +void eel_run_lib_self_checks (void); + +/* Putting the prototypes for these self-check functions in each + header file for the files they are defined in would make compiling + the self-check framework take way too long (since one file would + have to include everything). + + So we put the list of functions here instead. + + Instead of just putting prototypes here, we put this macro that + can be used to do operations on the whole list of functions. +*/ + +#define EEL_LIB_FOR_EACH_SELF_CHECK_FUNCTION(macro) \ + macro (eel_self_check_string) \ +/* Add new self-check functions to the list above this line. */ + +/* Generate prototypes for all the functions. */ +EEL_LIB_FOR_EACH_SELF_CHECK_FUNCTION (EEL_SELF_CHECK_FUNCTION_PROTOTYPE) diff --git a/eel/eel-self-checks.c b/eel/eel-self-checks.c new file mode 100644 index 0000000..0ed94f2 --- /dev/null +++ b/eel/eel-self-checks.c @@ -0,0 +1,203 @@ +/* + * eel-self-checks.c: The self-check framework. + * + * Copyright (C) 1999 Eazel, Inc. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * This program 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this program; if not, see . + * + * Author: Darin Adler + */ + +#include + +#if !defined (EEL_OMIT_SELF_CHECK) + +#include "eel-self-checks.h" + +#include +#include +#include + +static gboolean failed; + +static const char *current_expression; +static const char *current_file_name; +static int current_line_number; + +void +eel_exit_if_self_checks_failed (void) +{ + if (!failed) + { + return; + } + + printf ("\n"); + + exit (EXIT_FAILURE); +} + +void +eel_report_check_failure (char *result, + char *expected) +{ + if (!failed) + { + fprintf (stderr, "\n"); + } + + fprintf (stderr, "FAIL: check failed in %s, line %d\n", current_file_name, current_line_number); + fprintf (stderr, " evaluated: %s\n", current_expression); + fprintf (stderr, " expected: %s\n", expected == NULL ? "NULL" : expected); + fprintf (stderr, " got: %s\n", result == NULL ? "NULL" : result); + + failed = TRUE; + + g_free (result); + g_free (expected); +} + +static char * +eel_strdup_boolean (gboolean boolean) +{ + if (boolean == FALSE) + { + return g_strdup ("FALSE"); + } + if (boolean == TRUE) + { + return g_strdup ("TRUE"); + } + return g_strdup_printf ("gboolean(%d)", boolean); +} + +void +eel_before_check (const char *expression, + const char *file_name, + int line_number) +{ + current_expression = expression; + current_file_name = file_name; + current_line_number = line_number; +} + +void +eel_after_check (void) +{ + /* It would be good to check here if there was a memory leak. */ +} + +void +eel_check_boolean_result (gboolean result, + gboolean expected) +{ + if (result != expected) + { + eel_report_check_failure (eel_strdup_boolean (result), + eel_strdup_boolean (expected)); + } + eel_after_check (); +} + +void +eel_check_rectangle_result (EelIRect result, + int expected_x0, + int expected_y0, + int expected_x1, + int expected_y1) +{ + if (result.x0 != expected_x0 + || result.y0 != expected_y0 + || result.x1 != expected_x1 + || result.y1 != expected_y1) + { + eel_report_check_failure (g_strdup_printf ("x0=%d, y0=%d, x1=%d, y1=%d", + result.x0, + result.y0, + result.x1, + result.y1), + g_strdup_printf ("x0=%d, y0=%d, x1=%d, y1=%d", + expected_x0, + expected_y0, + expected_x1, + expected_y1)); + } + eel_after_check (); +} + +void +eel_check_integer_result (long result, + long expected) +{ + if (result != expected) + { + eel_report_check_failure (g_strdup_printf ("%ld", result), + g_strdup_printf ("%ld", expected)); + } + eel_after_check (); +} + +void +eel_check_double_result (double result, + double expected) +{ + if (result != expected) + { + eel_report_check_failure (g_strdup_printf ("%f", result), + g_strdup_printf ("%f", expected)); + } + eel_after_check (); +} + +void +eel_check_string_result (char *result, + const char *expected) +{ + gboolean match; + + /* Stricter than eel_strcmp. + * NULL does not match "" in this test. + */ + if (expected == NULL) + { + match = result == NULL; + } + else + { + match = result != NULL && strcmp (result, expected) == 0; + } + + if (!match) + { + eel_report_check_failure (result, g_strdup (expected)); + } + else + { + g_free (result); + } + eel_after_check (); +} + +void +eel_before_check_function (const char *name) +{ + fprintf (stderr, "running %s\n", name); +} + +void +eel_after_check_function (void) +{ +} + +#endif /* ! EEL_OMIT_SELF_CHECK */ diff --git a/eel/eel-self-checks.h b/eel/eel-self-checks.h new file mode 100644 index 0000000..ac48e1f --- /dev/null +++ b/eel/eel-self-checks.h @@ -0,0 +1,78 @@ +/* + eel-self-checks.h: The self-check framework. + + Copyright (C) 1999 Eazel, Inc. + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + This program 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this program; if not, see . + + Author: Darin Adler +*/ + +#pragma once + +#include +#include + +#define EEL_CHECK_RESULT(type, expression, expected_value) \ +G_STMT_START { \ + eel_before_check (#expression, __FILE__, __LINE__); \ + eel_check_##type##_result (expression, expected_value); \ +} G_STMT_END + +#define EEL_CHECK_BOOLEAN_RESULT(expression, expected_value) \ + EEL_CHECK_RESULT(boolean, expression, expected_value) +#define EEL_CHECK_INTEGER_RESULT(expression, expected_value) \ + EEL_CHECK_RESULT(integer, expression, expected_value) +#define EEL_CHECK_DOUBLE_RESULT(expression, expected_value) \ + EEL_CHECK_RESULT(double, expression, expected_value) +#define EEL_CHECK_STRING_RESULT(expression, expected_value) \ + EEL_CHECK_RESULT(string, expression, expected_value) +#define EEL_CHECK_RECTANGLE_RESULT(expression, expected_x0, expected_y0, expected_x1, expected_y1) \ +G_STMT_START { \ + eel_before_check (#expression, __FILE__, __LINE__); \ + eel_check_rectangle_result (expression, expected_x0, expected_y0, expected_x1, expected_y1); \ +} G_STMT_END + +void eel_exit_if_self_checks_failed (void); +void eel_before_check_function (const char *name); +void eel_after_check_function (void); +void eel_before_check (const char *expression, + const char *file_name, + int line_number); +void eel_after_check (void); + +/* Both 'result' and 'expected' get freed with g_free */ +void eel_report_check_failure (char *result, + char *expected); +void eel_check_boolean_result (gboolean result, + gboolean expected_value); +void eel_check_integer_result (long result, + long expected_value); +void eel_check_double_result (double result, + double expected_value); +void eel_check_rectangle_result (EelIRect result, + int expected_x0, + int expected_y0, + int expected_x1, + int expected_y1); +void eel_check_string_result (char *result, + const char *expected_value); + +#define EEL_SELF_CHECK_FUNCTION_PROTOTYPE(function) \ + void function (void); + +#define EEL_CALL_SELF_CHECK_FUNCTION(function) \ + eel_before_check_function (#function); \ + function (); \ + eel_after_check_function (); diff --git a/eel/eel-stock-dialogs.c b/eel/eel-stock-dialogs.c new file mode 100644 index 0000000..d563fc2 --- /dev/null +++ b/eel/eel-stock-dialogs.c @@ -0,0 +1,292 @@ +/* eel-stock-dialogs.c: Various standard dialogs for Eel. + * + * Copyright (C) 2000 Eazel, Inc. + * + * The Gnome Library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * The Gnome 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with the Gnome Library; see the file COPYING.LIB. If not, + * see . + * + * Authors: Darin Adler + */ + +#include +#include "eel-stock-dialogs.h" + +#include "eel-glib-extensions.h" + +#include +#include +#include + +#define TIMED_WAIT_STANDARD_DURATION 2000 +#define TIMED_WAIT_MIN_TIME_UP 3000 + +#define TIMED_WAIT_MINIMUM_DIALOG_WIDTH 300 + +#define RESPONSE_DETAILS 1000 + +typedef struct +{ + EelCancelCallback cancel_callback; + gpointer callback_data; + + /* Parameters for creation of the window. */ + char *wait_message; + GtkWindow *parent_window; + + /* Timer to determine when we need to create the window. */ + guint timeout_handler_id; + + /* Window, once it's created. */ + GtkWidget *dialog; + + /* system time (microseconds) when dialog was created */ + gint64 dialog_creation_time; +} TimedWait; + +static GHashTable *timed_wait_hash_table; + +static void timed_wait_dialog_destroy_callback (GtkWidget *object, + gpointer callback_data); + +static guint +timed_wait_hash (gconstpointer value) +{ + const TimedWait *wait; + + wait = value; + + return GPOINTER_TO_UINT (wait->cancel_callback) + ^ GPOINTER_TO_UINT (wait->callback_data); +} + +static gboolean +timed_wait_hash_equal (gconstpointer value1, + gconstpointer value2) +{ + const TimedWait *wait1, *wait2; + + wait1 = value1; + wait2 = value2; + + return wait1->cancel_callback == wait2->cancel_callback + && wait1->callback_data == wait2->callback_data; +} + +static void +timed_wait_delayed_close_destroy_dialog_callback (GtkWidget *object, + gpointer callback_data) +{ + g_source_remove (GPOINTER_TO_UINT (callback_data)); +} + +static gboolean +timed_wait_delayed_close_timeout_callback (gpointer callback_data) +{ + guint handler_id; + + handler_id = GPOINTER_TO_UINT (g_object_get_data (G_OBJECT (callback_data), + "eel-stock-dialogs/delayed_close_handler_timeout_id")); + + g_signal_handlers_disconnect_by_func (G_OBJECT (callback_data), + G_CALLBACK (timed_wait_delayed_close_destroy_dialog_callback), + GUINT_TO_POINTER (handler_id)); + + gtk_window_destroy (GTK_WINDOW (callback_data)); + + return FALSE; +} + +static void +timed_wait_free (TimedWait *wait) +{ + guint delayed_close_handler_id; + guint64 time_up; + + g_assert (g_hash_table_lookup (timed_wait_hash_table, wait) != NULL); + + g_hash_table_remove (timed_wait_hash_table, wait); + + g_free (wait->wait_message); + if (wait->parent_window != NULL) + { + g_object_unref (wait->parent_window); + } + if (wait->timeout_handler_id != 0) + { + g_source_remove (wait->timeout_handler_id); + } + if (wait->dialog != NULL) + { + /* Make sure to detach from the "destroy" signal, or we'll + * double-free. + */ + g_signal_handlers_disconnect_by_func (G_OBJECT (wait->dialog), + G_CALLBACK (timed_wait_dialog_destroy_callback), + wait); + + /* compute time up in milliseconds */ + time_up = (g_get_monotonic_time () - wait->dialog_creation_time) / 1000; + + if (time_up < TIMED_WAIT_MIN_TIME_UP) + { + delayed_close_handler_id = g_timeout_add (TIMED_WAIT_MIN_TIME_UP - time_up, + timed_wait_delayed_close_timeout_callback, + wait->dialog); + g_object_set_data (G_OBJECT (wait->dialog), + "eel-stock-dialogs/delayed_close_handler_timeout_id", + GUINT_TO_POINTER (delayed_close_handler_id)); + g_signal_connect (wait->dialog, "destroy", + G_CALLBACK (timed_wait_delayed_close_destroy_dialog_callback), + GUINT_TO_POINTER (delayed_close_handler_id)); + } + else + { + gtk_window_destroy (GTK_WINDOW (wait->dialog)); + } + } + + /* And the wait object itself. */ + g_free (wait); +} + +static void +timed_wait_dialog_destroy_callback (GtkWidget *object, + gpointer callback_data) +{ + TimedWait *wait; + + wait = callback_data; + + g_assert (object == wait->dialog); + + wait->dialog = NULL; + + /* When there's no cancel_callback, the originator will/must + * call eel_timed_wait_stop which will call timed_wait_free. + */ + + if (wait->cancel_callback != NULL) + { + (*wait->cancel_callback)(wait->callback_data); + timed_wait_free (wait); + } +} + +static gboolean +timed_wait_callback (gpointer callback_data) +{ + TimedWait *wait; + GtkWidget *dialog; + + wait = callback_data; + + /* Put up the timed wait window. */ + dialog = adw_message_dialog_new (wait->parent_window, + wait->wait_message, + _("You can stop this operation by clicking cancel.")); + + adw_message_dialog_add_response (ADW_MESSAGE_DIALOG (dialog), "cancel", _("_Cancel")); + adw_message_dialog_set_default_response (ADW_MESSAGE_DIALOG (dialog), "cancel"); + + wait->dialog_creation_time = g_get_monotonic_time (); + gtk_window_present (GTK_WINDOW (dialog)); + + /* FIXME bugzilla.eazel.com 2441: + * Could parent here, but it's complicated because we + * don't want this window to go away just because the parent + * would go away first. + */ + + /* Make the dialog cancel the timed wait when it goes away. + * Connect to "destroy" instead of "response" since we want + * to be called no matter how the dialog goes away. + */ + g_signal_connect (dialog, "destroy", + G_CALLBACK (timed_wait_dialog_destroy_callback), + wait); + + wait->timeout_handler_id = 0; + wait->dialog = dialog; + + return FALSE; +} + +void +eel_timed_wait_start_with_duration (int duration, + EelCancelCallback cancel_callback, + gpointer callback_data, + const char *wait_message, + GtkWindow *parent_window) +{ + TimedWait *wait; + + g_return_if_fail (cancel_callback != NULL); + g_return_if_fail (callback_data != NULL); + g_return_if_fail (wait_message != NULL); + g_return_if_fail (parent_window == NULL || GTK_IS_WINDOW (parent_window)); + + /* Create the timed wait record. */ + wait = g_new0 (TimedWait, 1); + wait->wait_message = g_strdup (wait_message); + wait->cancel_callback = cancel_callback; + wait->callback_data = callback_data; + wait->parent_window = parent_window; + + if (parent_window != NULL) + { + g_object_ref (parent_window); + } + + /* Start the timer. */ + wait->timeout_handler_id = g_timeout_add (duration, timed_wait_callback, wait); + + /* Put in the hash table so we can find it later. */ + if (timed_wait_hash_table == NULL) + { + timed_wait_hash_table = g_hash_table_new (timed_wait_hash, timed_wait_hash_equal); + } + g_assert (g_hash_table_lookup (timed_wait_hash_table, wait) == NULL); + g_hash_table_insert (timed_wait_hash_table, wait, wait); + g_assert (g_hash_table_lookup (timed_wait_hash_table, wait) == wait); +} + +void +eel_timed_wait_start (EelCancelCallback cancel_callback, + gpointer callback_data, + const char *wait_message, + GtkWindow *parent_window) +{ + eel_timed_wait_start_with_duration + (TIMED_WAIT_STANDARD_DURATION, + cancel_callback, callback_data, + wait_message, parent_window); +} + +void +eel_timed_wait_stop (EelCancelCallback cancel_callback, + gpointer callback_data) +{ + TimedWait key; + TimedWait *wait; + + g_return_if_fail (callback_data != NULL); + + key.cancel_callback = cancel_callback; + key.callback_data = callback_data; + wait = g_hash_table_lookup (timed_wait_hash_table, &key); + + g_return_if_fail (wait != NULL); + + timed_wait_free (wait); +} diff --git a/eel/eel-stock-dialogs.h b/eel/eel-stock-dialogs.h new file mode 100644 index 0000000..8136735 --- /dev/null +++ b/eel/eel-stock-dialogs.h @@ -0,0 +1,40 @@ + +/* eel-stock-dialogs.h: Various standard dialogs for Eel. + + Copyright (C) 2000 Eazel, Inc. + + The Gnome Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + The Gnome 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the Gnome Library; see the file COPYING.LIB. If not, + see . + + Authors: Darin Adler +*/ + +#pragma once + +#include + +typedef void (* EelCancelCallback) (gpointer callback_data); + +/* Dialog for cancelling something that normally is fast enough not to need a dialog. */ +void eel_timed_wait_start (EelCancelCallback cancel_callback, + gpointer callback_data, + const char *wait_message, + GtkWindow *parent_window); +void eel_timed_wait_start_with_duration (int duration, + EelCancelCallback cancel_callback, + gpointer callback_data, + const char *wait_message, + GtkWindow *parent_window); +void eel_timed_wait_stop (EelCancelCallback cancel_callback, + gpointer callback_data); diff --git a/eel/eel-string.c b/eel/eel-string.c new file mode 100644 index 0000000..5cd705f --- /dev/null +++ b/eel/eel-string.c @@ -0,0 +1,488 @@ +/* + * eel-string.c: String routines to augment . + * + * Copyright (C) 2000 Eazel, Inc. + * + * The Gnome Library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * The Gnome 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with the Gnome Library; see the file COPYING.LIB. If not, + * see . + * + * Authors: Darin Adler + */ + +#include +#include "eel-string.h" + +#include +#include +#include +#include +#include + +#if !defined (EEL_OMIT_SELF_CHECK) +#include "eel-lib-self-check-functions.h" +#endif + +/** + * eel_str_double_underscores: + * @string: input string + * + * This is used if you want to preserve underscore characters + * when creating a label with gtk_label_new_with_mnemonic(). + * + * Returns: a newly allocated copy of @string, + * with a doubled number of underscores. + * If @string doesn't contain underscores, returns a copy of it. + * If @string is %NULL, returns %NULL. + */ +char * +eel_str_double_underscores (const char *string) +{ + int underscores; + const char *p; + char *q; + char *escaped; + + if (string == NULL) + { + return NULL; + } + + underscores = 0; + for (p = string; *p != '\0'; p++) + { + underscores += (*p == '_'); + } + + if (underscores == 0) + { + return g_strdup (string); + } + + escaped = g_new (char, strlen (string) + underscores + 1); + for (p = string, q = escaped; *p != '\0'; p++, q++) + { + /* Add an extra underscore. */ + if (*p == '_') + { + *q++ = '_'; + } + *q = *p; + } + *q = '\0'; + + return escaped; +} + +/** + * eel_str_capitalize: + * @string: input string + * + * Returns: a newly allocated copy of @string, + * with the first letter capitalized. + * If @string is %NULL, returns %NULL. + */ +char * +eel_str_capitalize (const char *string) +{ + char *capitalized = NULL; + + if (string == NULL) + { + return NULL; + } + + if (g_utf8_validate (string, -1, NULL)) + { + g_autofree gunichar *ucs4 = NULL; + ucs4 = g_utf8_to_ucs4 (string, -1, NULL, NULL, NULL); + if (ucs4 != NULL) + { + ucs4[0] = g_unichar_toupper (ucs4[0]); + capitalized = g_ucs4_to_utf8 (ucs4, -1, NULL, NULL, NULL); + } + } + + if (capitalized == NULL) + { + return g_strdup (string); + } + + return capitalized; +} + +/** + * eel_str_middle_truncate: + * @string: (not nullable): input string + * truncate_length: length of the truncated string + * + * Returns: (transfer full): a newly-allocated copy of @string with its middle + * truncated and replaced with ellipsis to fit into @truncate_length characters. + * If length of @string is already small enough, returns a copy of @string. + */ +gchar * +eel_str_middle_truncate (const gchar *string, + guint truncate_length) +{ + const gchar ellipsis[] = "…"; + glong ellipsis_length; + glong length; + glong num_left_chars; + glong num_right_chars; + g_autofree gchar *left_substring = NULL; + g_autofree gchar *right_substring = NULL; + + g_return_val_if_fail (string != NULL, NULL); + g_return_val_if_fail (truncate_length > 0, NULL); + + ellipsis_length = g_utf8_strlen (ellipsis, -1); + + /* Our ellipsis string + one character on each side. */ + if (truncate_length < ellipsis_length + 2) + { + return g_strdup (string); + } + + length = g_utf8_strlen (string, -1); + + if (length <= truncate_length) + { + return g_strdup (string); + } + + num_left_chars = (truncate_length - ellipsis_length) / 2; + num_right_chars = truncate_length - num_left_chars - ellipsis_length; + + g_assert (num_left_chars > 0); + g_assert (num_right_chars > 0); + + left_substring = g_utf8_substring (string, 0, num_left_chars); + right_substring = g_utf8_substring (string, length - num_right_chars, length); + + return g_strconcat (left_substring, ellipsis, right_substring, NULL); +} + +/** + * eel_str_strip_substring_and_after: + * @string: input string + * @substring: (not nullable): substring to use in search + * + * Returns: (transfer full): a copy of @string with the first occurence of + * @substring removed, along with any trailing characters. + * If @string is %NULL, returns %NULL. + */ +char * +eel_str_strip_substring_and_after (const char *string, + const char *substring) +{ + const char *substring_position; + + g_return_val_if_fail (substring != NULL, g_strdup (string)); + g_return_val_if_fail (substring[0] != '\0', g_strdup (string)); + + if (string == NULL) + { + return NULL; + } + + substring_position = strstr (string, substring); + if (substring_position == NULL) + { + return g_strdup (string); + } + + return g_strndup (string, + substring_position - string); +} + +/** + * eel_str_replace_substring: + * @string: input string + * @substring: (not nullable): string to be replaced + * @replacement: string used as replacement + * + * Returns: (transfer full): a copy of @string with all occurences of @substring + * replaced with @replacement. + */ +char * +eel_str_replace_substring (const char *string, + const char *substring, + const char *replacement) +{ + int substring_length, replacement_length, result_length, remaining_length; + const char *p, *substring_position; + char *result, *result_position; + + g_return_val_if_fail (substring != NULL, g_strdup (string)); + g_return_val_if_fail (substring[0] != '\0', g_strdup (string)); + + if (string == NULL) + { + return NULL; + } + + substring_length = substring ? strlen (substring) : 0; + replacement_length = replacement ? strlen (replacement) : 0; + + result_length = strlen (string); + for (p = string;; p = substring_position + substring_length) + { + substring_position = strstr (p, substring); + if (substring_position == NULL) + { + break; + } + result_length += replacement_length - substring_length; + } + + result = g_malloc (result_length + 1); + + result_position = result; + for (p = string;; p = substring_position + substring_length) + { + substring_position = strstr (p, substring); + if (substring_position == NULL) + { + remaining_length = strlen (p); + memcpy (result_position, p, remaining_length); + result_position += remaining_length; + break; + } + memcpy (result_position, p, substring_position - p); + result_position += substring_position - p; + memcpy (result_position, replacement, replacement_length); + result_position += replacement_length; + } + g_assert (result_position - result == result_length); + result_position[0] = '\0'; + + return result; +} + +/** + * get_common_prefix_length: + * @str_a: first string + * @str_b: second string + * @min_required_len: the minimum number of characters required in the prefix + * + * Returns: the size of the common prefix of two strings, in characters. + * If there's no common prefix, or the common prefix is smaller than + * min_required_len, this will return -1 + */ +static int +get_common_prefix_length (char *str_a, + char *str_b, + int min_required_len) +{ + int a_len; + int b_len; + int intersection_len; + int matching_chars; + char *a; + char *b; + + a_len = g_utf8_strlen (str_a, -1); + b_len = g_utf8_strlen (str_b, -1); + + intersection_len = MIN (a_len, b_len); + if (intersection_len < min_required_len) + { + return -1; + } + + matching_chars = 0; + a = str_a; + b = str_b; + while (matching_chars < intersection_len) + { + if (g_utf8_get_char (a) != g_utf8_get_char (b)) + { + break; + } + + ++matching_chars; + + a = g_utf8_next_char (a); + b = g_utf8_next_char (b); + } + + if (matching_chars < min_required_len) + { + return -1; + } + + return matching_chars; +} + +/** + * eel_str_get_common_prefix: + * @strs: a list of strings + * @min_required_len: the minimum number of characters required in prefix + * + * Returns: (transfer full): the common prefix for strings in @strs. + * If no such prefix exists or if the common prefix is smaller than + * @min_required_len, %NULL is returned. + */ +char * +eel_str_get_common_prefix (GList *strs, + int min_required_len) +{ + GList *l; + char *common_part; + char *name; + char *truncated; + int matching_chars; + + if (strs == NULL) + { + return NULL; + } + + common_part = NULL; + for (l = strs; l != NULL; l = l->next) + { + name = l->data; + if (name == NULL) + { + g_free (common_part); + return NULL; + } + + if (l->prev == NULL) + { + common_part = g_strdup (name); + continue; + } + + matching_chars = get_common_prefix_length (common_part, name, min_required_len); + + if (matching_chars == -1) + { + g_free (common_part); + return NULL; + } + + truncated = g_utf8_substring (common_part, 0, matching_chars); + g_free (common_part); + common_part = truncated; + } + + matching_chars = g_utf8_strlen (common_part, -1); + if (matching_chars < min_required_len) + { + g_free (common_part); + return NULL; + } + + return common_part; +} + +/**************** Custom printf ***********/ + +typedef struct +{ + const char *start; + const char *end; + GString *format; + int arg_pos; + int width_pos; + int width_format_index; + int precision_pos; + int precision_format_index; +} ConversionInfo; + +enum +{ + ARG_TYPE_INVALID, + ARG_TYPE_INT, + ARG_TYPE_LONG, + ARG_TYPE_LONG_LONG, + ARG_TYPE_SIZE, + ARG_TYPE_LONG_DOUBLE, + ARG_TYPE_DOUBLE, + ARG_TYPE_POINTER +}; + +#if !defined (EEL_OMIT_SELF_CHECK) + +void +eel_self_check_string (void) +{ + EEL_CHECK_STRING_RESULT (eel_str_double_underscores (NULL), NULL); + EEL_CHECK_STRING_RESULT (eel_str_double_underscores (""), ""); + EEL_CHECK_STRING_RESULT (eel_str_double_underscores ("_"), "__"); + EEL_CHECK_STRING_RESULT (eel_str_double_underscores ("foo"), "foo"); + EEL_CHECK_STRING_RESULT (eel_str_double_underscores ("foo_bar"), "foo__bar"); + EEL_CHECK_STRING_RESULT (eel_str_double_underscores ("foo_bar_2"), "foo__bar__2"); + EEL_CHECK_STRING_RESULT (eel_str_double_underscores ("_foo"), "__foo"); + EEL_CHECK_STRING_RESULT (eel_str_double_underscores ("foo_"), "foo__"); + + EEL_CHECK_STRING_RESULT (eel_str_capitalize (NULL), NULL); + EEL_CHECK_STRING_RESULT (eel_str_capitalize (""), ""); + EEL_CHECK_STRING_RESULT (eel_str_capitalize ("foo"), "Foo"); + EEL_CHECK_STRING_RESULT (eel_str_capitalize ("Foo"), "Foo"); + + EEL_CHECK_STRING_RESULT (eel_str_middle_truncate ("foo", 0), NULL); + EEL_CHECK_STRING_RESULT (eel_str_middle_truncate ("foo", 1), "foo"); + EEL_CHECK_STRING_RESULT (eel_str_middle_truncate ("foo", 3), "foo"); + EEL_CHECK_STRING_RESULT (eel_str_middle_truncate ("foo", 4), "foo"); + EEL_CHECK_STRING_RESULT (eel_str_middle_truncate ("foo", 5), "foo"); + EEL_CHECK_STRING_RESULT (eel_str_middle_truncate ("foo", 6), "foo"); + EEL_CHECK_STRING_RESULT (eel_str_middle_truncate ("foo", 7), "foo"); + EEL_CHECK_STRING_RESULT (eel_str_middle_truncate ("a_much_longer_foo", 0), NULL); + EEL_CHECK_STRING_RESULT (eel_str_middle_truncate ("a_much_longer_foo", 1), "a_much_longer_foo"); + EEL_CHECK_STRING_RESULT (eel_str_middle_truncate ("a_much_longer_foo", 2), "a_much_longer_foo"); + EEL_CHECK_STRING_RESULT (eel_str_middle_truncate ("a_much_longer_foo", 3), "a…o"); + EEL_CHECK_STRING_RESULT (eel_str_middle_truncate ("a_much_longer_foo", 4), "a…oo"); + EEL_CHECK_STRING_RESULT (eel_str_middle_truncate ("a_much_longer_foo", 5), "a_…oo"); + EEL_CHECK_STRING_RESULT (eel_str_middle_truncate ("a_much_longer_foo", 6), "a_…foo"); + EEL_CHECK_STRING_RESULT (eel_str_middle_truncate ("a_much_longer_foo", 7), "a_m…foo"); + EEL_CHECK_STRING_RESULT (eel_str_middle_truncate ("a_much_longer_foo", 8), "a_m…_foo"); + EEL_CHECK_STRING_RESULT (eel_str_middle_truncate ("a_much_longer_foo", 9), "a_mu…_foo"); + EEL_CHECK_STRING_RESULT (eel_str_middle_truncate ("something_even", 8), "som…even"); + EEL_CHECK_STRING_RESULT (eel_str_middle_truncate ("something_odd", 8), "som…_odd"); + EEL_CHECK_STRING_RESULT (eel_str_middle_truncate ("something_even", 9), "some…even"); + EEL_CHECK_STRING_RESULT (eel_str_middle_truncate ("something_odd", 9), "some…_odd"); + EEL_CHECK_STRING_RESULT (eel_str_middle_truncate ("something_even", 10), "some…_even"); + EEL_CHECK_STRING_RESULT (eel_str_middle_truncate ("something_odd", 10), "some…g_odd"); + EEL_CHECK_STRING_RESULT (eel_str_middle_truncate ("something_even", 11), "somet…_even"); + EEL_CHECK_STRING_RESULT (eel_str_middle_truncate ("something_odd", 11), "somet…g_odd"); + EEL_CHECK_STRING_RESULT (eel_str_middle_truncate ("something_even", 12), "somet…g_even"); + EEL_CHECK_STRING_RESULT (eel_str_middle_truncate ("something_odd", 12), "somet…ng_odd"); + EEL_CHECK_STRING_RESULT (eel_str_middle_truncate ("something_even", 13), "someth…g_even"); + EEL_CHECK_STRING_RESULT (eel_str_middle_truncate ("something_odd", 13), "something_odd"); + EEL_CHECK_STRING_RESULT (eel_str_middle_truncate ("something_even", 14), "something_even"); + EEL_CHECK_STRING_RESULT (eel_str_middle_truncate ("something_odd", 13), "something_odd"); + EEL_CHECK_STRING_RESULT (eel_str_middle_truncate ("ääääääääää", 5), "ää…ää"); + EEL_CHECK_STRING_RESULT (eel_str_middle_truncate ("あぃいぅうぇえぉ", 7), "あぃい…ぇえぉ"); + + EEL_CHECK_STRING_RESULT (eel_str_strip_substring_and_after (NULL, "bar"), NULL); + EEL_CHECK_STRING_RESULT (eel_str_strip_substring_and_after ("", "bar"), ""); + EEL_CHECK_STRING_RESULT (eel_str_strip_substring_and_after ("foo", "bar"), "foo"); + EEL_CHECK_STRING_RESULT (eel_str_strip_substring_and_after ("foo bar", "bar"), "foo "); + EEL_CHECK_STRING_RESULT (eel_str_strip_substring_and_after ("foo bar xxx", "bar"), "foo "); + EEL_CHECK_STRING_RESULT (eel_str_strip_substring_and_after ("bar", "bar"), ""); + + EEL_CHECK_STRING_RESULT (eel_str_replace_substring (NULL, "foo", NULL), NULL); + EEL_CHECK_STRING_RESULT (eel_str_replace_substring (NULL, "foo", "bar"), NULL); + EEL_CHECK_STRING_RESULT (eel_str_replace_substring ("bar", "foo", NULL), "bar"); + EEL_CHECK_STRING_RESULT (eel_str_replace_substring ("", "foo", ""), ""); + EEL_CHECK_STRING_RESULT (eel_str_replace_substring ("", "foo", "bar"), ""); + EEL_CHECK_STRING_RESULT (eel_str_replace_substring ("bar", "foo", ""), "bar"); + EEL_CHECK_STRING_RESULT (eel_str_replace_substring ("xxx", "x", "foo"), "foofoofoo"); + EEL_CHECK_STRING_RESULT (eel_str_replace_substring ("fff", "f", "foo"), "foofoofoo"); + EEL_CHECK_STRING_RESULT (eel_str_replace_substring ("foofoofoo", "foo", "f"), "fff"); + EEL_CHECK_STRING_RESULT (eel_str_replace_substring ("foofoofoo", "f", ""), "oooooo"); +} + +#endif /* !EEL_OMIT_SELF_CHECK */ diff --git a/eel/eel-string.h b/eel/eel-string.h new file mode 100644 index 0000000..a833750 --- /dev/null +++ b/eel/eel-string.h @@ -0,0 +1,79 @@ +/* + eel-string.h: String routines to augment . + + Copyright (C) 2000 Eazel, Inc. + + The Gnome Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + The Gnome 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the Gnome Library; see the file COPYING.LIB. If not, + see . + + Authors: Darin Adler +*/ + +#pragma once + +#include +#include +#include + +/* We use the "str" abbrevation to mean char * string, since + * "string" usually means g_string instead. We use the "istr" + * abbreviation to mean a case-insensitive char *. + */ + + +/* NULL is allowed for all the str parameters to these functions. */ + +/* Escape function for '_' character. */ +char * eel_str_double_underscores (const char *str); + +/* Capitalize a string */ +char * eel_str_capitalize (const char *str); + +/** + * eel_str_middle_truncate: + * @string: the string to truncate + * @truncate_length: the length limit at which to truncate + * + * If @string is longer than @truncate_length, replaces the middle with an + * ellipsis so the resulting string is exactly @truncate_length characters + * in length. Otherwise, returns a copy of @string. + * + * Do not use to ellipsize whole labels, only substrings that appear in them, + * e.g. file names. + * + * Returns: @string, truncated at the middle to @truncate_length or a copy + * if it was not longer than @truncate_length. + */ +gchar *eel_str_middle_truncate (const gchar *string, + guint truncate_length); + + +/* Remove all characters after the passed-in substring. */ +char * eel_str_strip_substring_and_after (const char *str, + const char *substring); + +/* Replace all occurrences of substring with replacement. */ +char * eel_str_replace_substring (const char *str, + const char *substring, + const char *replacement); + +/** + * eel_str_get_common_prefix: + * @str: set of strings + * @min_required_len: the minimum number of characters required in the prefix + * + * Returns: the common prefix for a set of strings, or NULL if there isn't a + * common prefix of length min_required_len + */ +char * eel_str_get_common_prefix (GList *strs, int min_required_len); diff --git a/eel/eel-vfs-extensions.c b/eel/eel-vfs-extensions.c new file mode 100644 index 0000000..ea9ef2b --- /dev/null +++ b/eel/eel-vfs-extensions.c @@ -0,0 +1,204 @@ +/* eel-vfs-extensions.c - gnome-vfs extensions. Its likely some of these will + * be part of gnome-vfs in the future. + * + * Copyright (C) 1999, 2000 Eazel, Inc. + * + * The Gnome Library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * The Gnome 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with the Gnome Library; see the file COPYING.LIB. If not, + * see . + * + * Authors: Darin Adler + * Pavel Cisler + * Mike Fleming + * John Sullivan + */ + +#include +#include "eel-vfs-extensions.h" +#include "eel-glib-extensions.h" +#include "eel-lib-self-check-functions.h" + +#include +#include +#include + +#include "eel-string.h" + +#include +#include + +gboolean +eel_uri_is_starred (const gchar *uri) +{ + return g_str_has_prefix (uri, "starred:"); +} + +/* It also matches trashed folders inside Trash, + * use `eel_uri_is_trash_root` if that's not desirable. */ +gboolean +eel_uri_is_trash (const char *uri) +{ + return g_str_has_prefix (uri, "trash:"); +} + +gboolean +eel_uri_is_trash_root (const char *uri) +{ + return g_strcmp0 (uri, "trash:///") == 0; +} + +gboolean +eel_uri_is_recent (const char *uri) +{ + return g_str_has_prefix (uri, "recent:"); +} + +gboolean +eel_uri_is_search (const char *uri) +{ + return g_str_has_prefix (uri, EEL_SEARCH_URI); +} + +gboolean +eel_uri_is_other_locations (const char *uri) +{ + return g_str_has_prefix (uri, "other-locations:"); +} + +gboolean +eel_uri_is_in_xdg_dirs (const gchar *uri) +{ + GUserDirectory dir; + g_autoptr (GFile) location = NULL; + gboolean has_prefix = FALSE; + + location = g_file_new_for_uri (uri); + for (dir = 0; dir < G_USER_N_DIRECTORIES; dir++) + { + g_autoptr (GFile) xdg_dir_location = NULL; + const gchar *path; + + path = g_get_user_special_dir (dir); + if (path == NULL) + { + continue; + } + + xdg_dir_location = g_file_new_for_path (path); + has_prefix = g_file_has_prefix (location, xdg_dir_location) || + g_file_equal (location, xdg_dir_location); + + if (has_prefix) + { + break; + } + } + + return has_prefix; +} + +/** + * eel_filename_get_extension_offset: + * @filename: a null-terminated string representing the basename of a file, with + * or without extension. + * + * Returns: (nullable) (transfer none): A pointer to the substring containing + * the dot and extension, or %NULL if there + * is no extension. + */ +char * +eel_filename_get_extension_offset (const char *filename) +{ + char *end, *end2; + const char *start; + + if (filename == NULL || filename[0] == '\0') + { + return NULL; + } + + /* basename must have at least one char */ + start = filename + 1; + + end = strrchr (start, '.'); + if (end == NULL || end[1] == '\0') + { + return NULL; + } + + if (end != start) + { + if (strcmp (end, ".gz") == 0 || + strcmp (end, ".bz2") == 0 || + strcmp (end, ".sit") == 0 || + strcmp (end, ".Z") == 0 || + strcmp (end, ".bz") == 0 || + strcmp (end, ".xz") == 0) + { + end2 = end - 1; + while (end2 > start && + *end2 != '.') + { + end2--; + } + if (end2 != start) + { + end = end2; + } + } + } + + return end; +} + +char * +eel_filename_strip_extension (const char *filename_with_extension) +{ + char *filename, *end; + + if (filename_with_extension == NULL) + { + return NULL; + } + + filename = g_strdup (filename_with_extension); + end = eel_filename_get_extension_offset (filename); + + if (end && end != filename) + { + *end = '\0'; + } + + return filename; +} + +void +eel_filename_get_rename_region (const char *filename, + int *start_offset, + int *end_offset) +{ + char *filename_without_extension; + + g_return_if_fail (start_offset != NULL); + g_return_if_fail (end_offset != NULL); + + *start_offset = 0; + *end_offset = 0; + + g_return_if_fail (filename != NULL); + + filename_without_extension = eel_filename_strip_extension (filename); + *end_offset = g_utf8_strlen (filename_without_extension, -1); + + g_free (filename_without_extension); +} diff --git a/eel/eel-vfs-extensions.h b/eel/eel-vfs-extensions.h new file mode 100644 index 0000000..b90fc69 --- /dev/null +++ b/eel/eel-vfs-extensions.h @@ -0,0 +1,50 @@ + +/* eel-vfs-extensions.h - gnome-vfs extensions. Its likely some of these will + be part of gnome-vfs in the future. + + Copyright (C) 1999, 2000 Eazel, Inc. + + The Gnome Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + The Gnome 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the Gnome Library; see the file COPYING.LIB. If not, + see . + + Authors: Darin Adler + Pavel Cisler + Mike Fleming + John Sullivan +*/ + +#pragma once + +#include + +G_BEGIN_DECLS + +#define EEL_TRASH_URI "trash:" +#define EEL_SEARCH_URI "x-nautilus-search:" + +gboolean eel_uri_is_starred (const char *uri); +gboolean eel_uri_is_trash (const char *uri); +gboolean eel_uri_is_trash_root (const char *uri); +gboolean eel_uri_is_search (const char *uri); +gboolean eel_uri_is_other_locations (const char *uri); +gboolean eel_uri_is_recent (const char *uri); +gboolean eel_uri_is_in_xdg_dirs (const char *uri); + +char * eel_filename_strip_extension (const char *filename); +void eel_filename_get_rename_region (const char *filename, + int *start_offset, + int *end_offset); +char * eel_filename_get_extension_offset (const char *filename); + +G_END_DECLS diff --git a/eel/eel.h b/eel/eel.h new file mode 100644 index 0000000..8553394 --- /dev/null +++ b/eel/eel.h @@ -0,0 +1,31 @@ + +/* eel.h + + Copyright (C) 2001 Eazel, Inc. + + The Gnome Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + The Gnome 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the Gnome Library; see the file COPYING.LIB. If not, + see . + + Authors: Maciej Stachowiak +*/ + +#pragma once + +#include +#include +#include +#include +#include +#include +#include diff --git a/eel/meson.build b/eel/meson.build new file mode 100644 index 0000000..650f77a --- /dev/null +++ b/eel/meson.build @@ -0,0 +1,54 @@ +libeel_2_sources = [ + 'eel-art-extensions.h', + 'eel-art-extensions.c', + 'eel-debug.h', + 'eel-debug.c', + 'eel-glib-extensions.h', + 'eel-graphic-effects.h', + 'eel-graphic-effects.c', + 'eel-self-checks.h', + 'eel-self-checks.c', + 'eel-stock-dialogs.h', + 'eel-stock-dialogs.c', + 'eel-string.h', + 'eel-string.c', + 'eel-vfs-extensions.h', + 'eel-vfs-extensions.c', + 'eel.h', + 'eel-lib-self-check-functions.h', + 'eel-lib-self-check-functions.c', +] + +libeel_2_deps = [ + config_h, + glib, + gtk, + libadwaita, + libm +] + +libeel_2 = static_library( + 'eel-2', + libeel_2_sources, + dependencies: libeel_2_deps, + include_directories: nautilus_include_dirs +) + +eel_2 = declare_dependency( + link_with: libeel_2, + include_directories: nautilus_include_dirs, + dependencies: libeel_2_deps +) + +check_eel = executable( + 'check-eel', + 'check-program.c', + dependencies: [ + eel_2, + xml + ] +) + +if get_option('tests') == 'all' + test('check-eel', check_eel) +endif -- cgit v1.2.3