Initial import
This commit is contained in:
parent
c4ff0f2521
commit
8b127400e8
|
@ -0,0 +1,207 @@
|
|||
#include <vte/vte.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <unistd.h>
|
||||
#include <libgnomevfs/gnome-vfs.h>
|
||||
#include <libgnome/libgnome.h>
|
||||
#include "gm-embedded-view.h"
|
||||
#include "../gm-app.h"
|
||||
#include "../gm-color-table.h"
|
||||
#include "../gm-options.h"
|
||||
#include "../gm-debug.h"
|
||||
|
||||
#define GM_EMBEDDED_VIEW_GET_PRIVATE(object)( \
|
||||
G_TYPE_INSTANCE_GET_PRIVATE((object), \
|
||||
GM_TYPE_EMBEDDED_VIEW, GmEmbeddedViewPrivate))
|
||||
|
||||
struct _GmEmbeddedViewPrivate {
|
||||
GmWorld *world;
|
||||
GmEditor *editor;
|
||||
|
||||
VteTerminal *vte;
|
||||
gchar *filename;
|
||||
GnomeVFSMonitorHandle *monitor;
|
||||
time_t last_modified;
|
||||
};
|
||||
|
||||
/* Signals
|
||||
|
||||
enum {
|
||||
PROTO
|
||||
NUM_SIGNALS
|
||||
};
|
||||
|
||||
static guint gm_embedded_view_signals[NUM_SIGNALS] = {0};*/
|
||||
|
||||
void on_gm_embedded_view_exited(VteTerminal *vte, GmEmbeddedView *embedded);
|
||||
void on_gm_embedded_view_file_changed(GnomeVFSMonitorHandle *handle,
|
||||
const gchar *monitor_uri, const gchar *info_uri,
|
||||
GnomeVFSMonitorEventType event_type, GmEmbeddedView *embedded);
|
||||
void on_gm_embedded_view_font_changed(GmColorTable *color_table,
|
||||
gchar const *desc, GmEmbeddedView *view);
|
||||
|
||||
G_DEFINE_TYPE(GmEmbeddedView, gm_embedded_view, GTK_TYPE_HBOX)
|
||||
|
||||
static void
|
||||
gm_embedded_view_finalize(GObject *object) {
|
||||
GmEmbeddedView *obj = GM_EMBEDDED_VIEW(object);
|
||||
struct stat buf;
|
||||
|
||||
if (obj->priv->monitor) {
|
||||
gnome_vfs_monitor_cancel(obj->priv->monitor);
|
||||
}
|
||||
|
||||
if (GM_IS_EDITOR(obj->priv->editor)) {
|
||||
if (stat(obj->priv->filename, &buf) != -1) {
|
||||
if (buf.st_mtime > obj->priv->last_modified) {
|
||||
gm_editor_save(obj->priv->editor);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (obj->priv->filename) {
|
||||
unlink(obj->priv->filename);
|
||||
g_free(obj->priv->filename);
|
||||
}
|
||||
|
||||
G_OBJECT_CLASS(gm_embedded_view_parent_class)->finalize(object);
|
||||
}
|
||||
|
||||
static void
|
||||
gm_embedded_view_class_init(GmEmbeddedViewClass *klass) {
|
||||
GObjectClass *object_class = G_OBJECT_CLASS(klass);
|
||||
|
||||
object_class->finalize = gm_embedded_view_finalize;
|
||||
|
||||
/*gm_embedded_view_signals[PROTO] =
|
||||
g_signal_new("proto",
|
||||
G_OBJECT_CLASS_TYPE(object_class),
|
||||
G_SIGNAL_RUN_LAST,
|
||||
G_STRUCT_OFFSET(GmEmbeddedViewClass, proto),
|
||||
NULL, NULL,
|
||||
g_cclosure_marshal_VOID__VOID,
|
||||
G_TYPE_NONE,
|
||||
0);*/
|
||||
|
||||
g_type_class_add_private(object_class, sizeof(GmEmbeddedViewPrivate));
|
||||
}
|
||||
|
||||
static void
|
||||
gm_embedded_view_init(GmEmbeddedView *obj) {
|
||||
GtkWidget *vte;
|
||||
GtkWidget *vscroll;
|
||||
|
||||
obj->priv = GM_EMBEDDED_VIEW_GET_PRIVATE(obj);
|
||||
|
||||
gtk_box_set_homogeneous(GTK_BOX(obj), FALSE);
|
||||
gtk_box_set_spacing(GTK_BOX(obj), 6);
|
||||
|
||||
vte = vte_terminal_new();
|
||||
vte_terminal_set_font_from_string(VTE_TERMINAL(vte),
|
||||
gm_color_table_font_description(gm_app_color_table(
|
||||
gm_app_instance())));
|
||||
vte_terminal_set_scroll_on_keystroke(VTE_TERMINAL(vte), TRUE);
|
||||
vte_terminal_set_scrollback_lines(VTE_TERMINAL(vte), 500);
|
||||
vte_terminal_set_scroll_on_output(VTE_TERMINAL(vte), FALSE);
|
||||
vte_terminal_set_word_chars(VTE_TERMINAL(vte), "-A-Za-z0-9,./?%&#:_");
|
||||
vte_terminal_set_allow_bold(VTE_TERMINAL(vte), TRUE);
|
||||
vte_terminal_set_audible_bell(VTE_TERMINAL(vte), TRUE);
|
||||
gtk_widget_show(vte);
|
||||
|
||||
vscroll = gtk_vscrollbar_new(VTE_TERMINAL(vte)->adjustment);
|
||||
gtk_widget_show(vscroll);
|
||||
gtk_box_pack_start(GTK_BOX(obj), vte, TRUE, TRUE, 0);
|
||||
gtk_box_pack_end(GTK_BOX(obj), vscroll, FALSE, FALSE, 0);
|
||||
|
||||
g_signal_connect(gm_app_color_table(gm_app_instance()), "font_changed",
|
||||
G_CALLBACK(on_gm_embedded_view_font_changed), obj);
|
||||
|
||||
obj->priv->vte = VTE_TERMINAL(vte);
|
||||
}
|
||||
|
||||
void
|
||||
gm_embedded_view_update_last_modified(GmEmbeddedView *embedded) {
|
||||
struct stat buf;
|
||||
|
||||
if (stat(embedded->priv->filename, &buf) != -1) {
|
||||
embedded->priv->last_modified = buf.st_mtime;
|
||||
}
|
||||
}
|
||||
|
||||
GmEmbeddedView *
|
||||
gm_embedded_view_new(GmWorld *world, GmEditor *editor) {
|
||||
GmEmbeddedView *obj = GM_EMBEDDED_VIEW(g_object_new(GM_TYPE_EMBEDDED_VIEW,
|
||||
NULL));
|
||||
gchar *cmd[4] = { NULL, NULL, NULL, NULL };
|
||||
GmOptions *options = gm_app_options(gm_app_instance());
|
||||
|
||||
obj->priv->world = world;
|
||||
obj->priv->editor = editor;
|
||||
obj->priv->filename = gm_editor_write_lines(editor);
|
||||
|
||||
gm_embedded_view_update_last_modified(obj);
|
||||
|
||||
cmd[0] = gnome_util_user_shell();
|
||||
|
||||
if (!cmd[0]) {
|
||||
cmd[0] = g_strdup("/bin/sh");
|
||||
}
|
||||
|
||||
cmd[1] = "-c";
|
||||
cmd[2] = g_strconcat(gm_options_get(options, "editor_alternative"), " ",
|
||||
obj->priv->filename, NULL);
|
||||
|
||||
vte_terminal_fork_command(obj->priv->vte, cmd[0], cmd, NULL,
|
||||
g_get_home_dir(), FALSE, TRUE, TRUE);
|
||||
|
||||
g_free(cmd[0]);
|
||||
g_free(cmd[2]);
|
||||
|
||||
gnome_vfs_monitor_add(&(obj->priv->monitor), obj->priv->filename,
|
||||
GNOME_VFS_MONITOR_FILE,
|
||||
(GnomeVFSMonitorCallback)on_gm_embedded_view_file_changed, obj);
|
||||
|
||||
g_signal_connect(obj->priv->vte, "child-exited",
|
||||
G_CALLBACK(on_gm_embedded_view_exited), obj);
|
||||
|
||||
return obj;
|
||||
}
|
||||
|
||||
GmEditor *
|
||||
gm_embedded_view_editor(GmEmbeddedView *view) {
|
||||
return view->priv->editor;
|
||||
}
|
||||
|
||||
/* Callbacks */
|
||||
void
|
||||
on_gm_embedded_view_file_changed(GnomeVFSMonitorHandle *handle,
|
||||
const gchar *monitor_uri, const gchar *info_uri,
|
||||
GnomeVFSMonitorEventType event_type, GmEmbeddedView *embedded) {
|
||||
switch (event_type) {
|
||||
case GNOME_VFS_MONITOR_EVENT_CHANGED:
|
||||
case GNOME_VFS_MONITOR_EVENT_CREATED:
|
||||
gm_debug_msg(DEBUG_DEFAULT, "GmEmbedded.OnFileChanged: "
|
||||
"change event detected!");
|
||||
|
||||
gm_editor_set_lines_from_file(embedded->priv->editor,
|
||||
embedded->priv->filename);
|
||||
gm_editor_save(embedded->priv->editor);
|
||||
gm_embedded_view_update_last_modified(embedded);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
on_gm_embedded_view_exited(VteTerminal *vte, GmEmbeddedView *embedded) {
|
||||
gm_editor_close(embedded->priv->editor);
|
||||
}
|
||||
|
||||
void
|
||||
on_gm_embedded_view_font_changed(GmColorTable *color_table, gchar const *desc,
|
||||
GmEmbeddedView *view) {
|
||||
vte_terminal_set_font_from_string(VTE_TERMINAL(view->priv->vte),
|
||||
gm_color_table_font_description(gm_app_color_table(
|
||||
gm_app_instance())));
|
||||
}
|
|
@ -0,0 +1,60 @@
|
|||
#ifndef __GM_EMBEDDED_VIEW_H__
|
||||
#define __GM_EMBEDDED_VIEW_H__
|
||||
|
||||
#include <glib-object.h>
|
||||
#include <gtk/gtk.h>
|
||||
#include "../gm-editor.h"
|
||||
#include "../gm-world.h"
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
/*
|
||||
* Type checking and casting macros
|
||||
*/
|
||||
#define GM_TYPE_EMBEDDED_VIEW (gm_embedded_view_get_type())
|
||||
#define GM_EMBEDDED_VIEW(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), \
|
||||
GM_TYPE_EMBEDDED_VIEW, GmEmbeddedView))
|
||||
#define GM_EMBEDDED_VIEW_CONST(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj),\
|
||||
GM_TYPE_EMBEDDED_VIEW, GmEmbeddedView const))
|
||||
#define GM_EMBEDDED_VIEW_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), \
|
||||
GM_TYPE_EMBEDDED_VIEW, GmEmbeddedViewClass))
|
||||
#define GM_IS_EMBEDDED_VIEW(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), \
|
||||
GM_TYPE_EMBEDDED_VIEW))
|
||||
#define GM_IS_EMBEDDED_VIEW_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), \
|
||||
GM_TYPE_EMBEDDED_VIEW))
|
||||
#define GM_EMBEDDED_VIEW_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), \
|
||||
GM_TYPE_EMBEDDED_VIEW, GmEmbeddedViewClass))
|
||||
|
||||
/* Private structure type */
|
||||
typedef struct _GmEmbeddedViewPrivate GmEmbeddedViewPrivate;
|
||||
|
||||
/*
|
||||
* Main object structure
|
||||
*/
|
||||
typedef struct _GmEmbeddedView GmEmbeddedView;
|
||||
|
||||
struct _GmEmbeddedView {
|
||||
GtkHBox parent;
|
||||
|
||||
/*< private > */
|
||||
GmEmbeddedViewPrivate *priv;
|
||||
};
|
||||
|
||||
/*
|
||||
* Class definition
|
||||
*/
|
||||
typedef struct _GmEmbeddedViewClass GmEmbeddedViewClass;
|
||||
|
||||
struct _GmEmbeddedViewClass {
|
||||
GtkHBoxClass parent_class;
|
||||
|
||||
/* Signals
|
||||
void (* proto) (GmEmbeddedView *obj); */
|
||||
};
|
||||
|
||||
GType gm_embedded_view_get_type(void) G_GNUC_CONST;
|
||||
GmEmbeddedView *gm_embedded_view_new(GmWorld *world, GmEditor *editor);
|
||||
GmEditor *gm_embedded_view_editor(GmEmbeddedView *view);
|
||||
|
||||
G_END_DECLS
|
||||
#endif /* __GM_EMBEDDED_VIEW_H__ */
|
|
@ -0,0 +1,141 @@
|
|||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <unistd.h>
|
||||
#include <libgnome/libgnome.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "gm-external-view.h"
|
||||
#include "../gm-debug.h"
|
||||
#include "../gm-app.h"
|
||||
#include "../gm-options.h"
|
||||
|
||||
void on_gm_external_view_exited(GPid pid, gint status, GmExternalView *view);
|
||||
void on_gm_external_view_file_changed(GnomeVFSMonitorHandle *handle,
|
||||
const gchar *monitor_uri, const gchar *info_uri,
|
||||
GnomeVFSMonitorEventType event_type, GmExternalView *view);
|
||||
|
||||
void
|
||||
gm_external_view_destroy(GmExternalView *view) {
|
||||
struct stat buf;
|
||||
|
||||
if (view->monitor) {
|
||||
gnome_vfs_monitor_cancel(view->monitor);
|
||||
}
|
||||
|
||||
g_source_remove(view->child_watch);
|
||||
g_spawn_close_pid(view->pid);
|
||||
|
||||
if (GM_IS_EDITOR(view->editor)) {
|
||||
if (stat(view->filename, &buf) != -1) {
|
||||
if (buf.st_mtime > view->last_modified) {
|
||||
gm_editor_save(view->editor);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (view->filename) {
|
||||
unlink(view->filename);
|
||||
g_free(view->filename);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
gm_external_view_update_last_modified(GmExternalView *view) {
|
||||
struct stat buf;
|
||||
|
||||
if (stat(view->filename, &buf) != -1) {
|
||||
view->last_modified = buf.st_mtime;
|
||||
}
|
||||
}
|
||||
|
||||
gboolean
|
||||
gm_external_view_spawn(GmExternalView *view, gchar **argv) {
|
||||
GError *err = NULL;
|
||||
|
||||
g_spawn_async(NULL, argv, NULL, G_SPAWN_SEARCH_PATH |
|
||||
G_SPAWN_DO_NOT_REAP_CHILD, NULL, NULL, &(view->pid), &err);
|
||||
|
||||
if (err) {
|
||||
gm_debug_msg(DEBUG_DEFAULT, "GmExternalView.Spawn: couldn't spawn "
|
||||
"editor: %s", err->message);
|
||||
g_error_free(err);
|
||||
return FALSE;
|
||||
} else {
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
GmExternalView *
|
||||
gm_external_view_new(GmWorld *world, GmEditor *editor) {
|
||||
GmExternalView *obj = g_new0(GmExternalView, 1);
|
||||
gchar *spawn_command[4] = {NULL, NULL, NULL, NULL};
|
||||
gchar **av, *command;
|
||||
gint an;
|
||||
GmOptions *options = gm_app_options(gm_app_instance());
|
||||
|
||||
obj->world = world;
|
||||
obj->editor = editor;
|
||||
obj->filename = gm_editor_write_lines(editor);
|
||||
|
||||
GM_DEBUG("Saved to: %s", obj->filename);
|
||||
|
||||
gm_external_view_update_last_modified(obj);
|
||||
|
||||
gnome_vfs_monitor_add(&(obj->monitor), obj->filename,
|
||||
GNOME_VFS_MONITOR_FILE,
|
||||
(GnomeVFSMonitorCallback)on_gm_external_view_file_changed, obj);
|
||||
|
||||
command = g_strconcat(gm_options_get(options, "editor_alternative"),
|
||||
" ", obj->filename, NULL);
|
||||
|
||||
if (gm_options_get_int(options, "editor_needs_terminal")) {
|
||||
spawn_command[0] = getenv("TERM");
|
||||
|
||||
if (spawn_command[0] == NULL) {
|
||||
spawn_command[0] = "xterm";
|
||||
}
|
||||
|
||||
spawn_command[1] = "-e";
|
||||
spawn_command[2] = command;
|
||||
|
||||
GM_DEBUG("Spawning: %s %s %s", spawn_command[0], spawn_command[1], spawn_command[2]);
|
||||
gm_external_view_spawn(obj, spawn_command);
|
||||
} else {
|
||||
g_shell_parse_argv(command, &an, &av, NULL);
|
||||
gm_external_view_spawn(obj, av);
|
||||
}
|
||||
|
||||
g_free(command);
|
||||
obj->child_watch = g_child_watch_add(obj->pid,
|
||||
(GChildWatchFunc)on_gm_external_view_exited, obj);
|
||||
|
||||
return obj;
|
||||
}
|
||||
|
||||
/* Callbacks */
|
||||
|
||||
void
|
||||
on_gm_external_view_exited(GPid pid, gint status, GmExternalView *view) {
|
||||
gm_editor_close(view->editor);
|
||||
}
|
||||
|
||||
void
|
||||
on_gm_external_view_file_changed(GnomeVFSMonitorHandle *handle,
|
||||
const gchar *monitor_uri, const gchar *info_uri,
|
||||
GnomeVFSMonitorEventType event_type, GmExternalView *view) {
|
||||
switch (event_type) {
|
||||
case GNOME_VFS_MONITOR_EVENT_CHANGED:
|
||||
case GNOME_VFS_MONITOR_EVENT_CREATED:
|
||||
gm_debug_msg(DEBUG_DEFAULT, "GmExternalView.OnFileChanged: "
|
||||
"change event detected!");
|
||||
|
||||
gm_editor_set_lines_from_file(view->editor,
|
||||
view->filename);
|
||||
gm_editor_save(view->editor);
|
||||
gm_external_view_update_last_modified(view);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,20 @@
|
|||
#include <glib.h>
|
||||
#include <libgnomevfs/gnome-vfs.h>
|
||||
#include "../gm-editor.h"
|
||||
#include "../gm-world.h"
|
||||
|
||||
#define GM_EXTERNAL_VIEW(obj) (GmExternalView *)(obj)
|
||||
|
||||
typedef struct _GmExternalView {
|
||||
GmWorld *world;
|
||||
GmEditor *editor;
|
||||
|
||||
gchar *filename;
|
||||
GnomeVFSMonitorHandle *monitor;
|
||||
time_t last_modified;
|
||||
GPid pid;
|
||||
guint child_watch;
|
||||
} GmExternalView;
|
||||
|
||||
GmExternalView *gm_external_view_new(GmWorld *world, GmEditor *editor);
|
||||
void gm_external_view_destroy(GmExternalView *view);
|
|
@ -0,0 +1,193 @@
|
|||
#include "gm-searchable.h"
|
||||
|
||||
GType
|
||||
gm_searchable_get_type() {
|
||||
static GType searchable_type = 0;
|
||||
|
||||
if (searchable_type == 0) {
|
||||
static const GTypeInfo searchable_info = {
|
||||
sizeof (GmSearchableInterface),
|
||||
NULL, /* base_init */
|
||||
NULL, /* base_finalize */
|
||||
NULL, /* class_init */
|
||||
NULL, /* class_finalize */
|
||||
NULL, /* class_data */
|
||||
0,
|
||||
0, /* n_preallocs */
|
||||
NULL /* instance_init */
|
||||
};
|
||||
|
||||
searchable_type = g_type_register_static(G_TYPE_INTERFACE,
|
||||
"GmSearchable", &searchable_info, 0);
|
||||
}
|
||||
|
||||
return searchable_type;
|
||||
}
|
||||
|
||||
/* Searching implementations */
|
||||
gboolean
|
||||
gm_searchable_text_view_find_next(GtkTextView *text_view, const gchar *str,
|
||||
GmSearchableSearchFlags flags) {
|
||||
GtkTextBuffer *buffer = NULL;
|
||||
GtkTextIter end, start, match_start, match_end;
|
||||
gboolean found = FALSE;
|
||||
|
||||
g_return_val_if_fail(text_view != NULL, FALSE);
|
||||
|
||||
if (str == NULL || *str == '\0') {
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
buffer = gtk_text_view_get_buffer(text_view);
|
||||
|
||||
if (buffer) {
|
||||
if (!gtk_text_buffer_get_selection_bounds(buffer, &start, &end)) {
|
||||
if (flags & GM_SEARCHABLE_SEARCH_BACKWARDS) {
|
||||
gtk_text_buffer_get_end_iter(buffer, &end);
|
||||
} else {
|
||||
gtk_text_buffer_get_start_iter(buffer, &end);
|
||||
}
|
||||
|
||||
start = end;
|
||||
}
|
||||
|
||||
if (flags & GM_SEARCHABLE_SEARCH_FORWARDS) {
|
||||
found = gtk_text_iter_forward_search(&end, str,
|
||||
GTK_TEXT_SEARCH_VISIBLE_ONLY | GTK_TEXT_SEARCH_TEXT_ONLY,
|
||||
&match_start, &match_end, NULL);
|
||||
} else {
|
||||
found = gtk_text_iter_backward_search(&start, str,
|
||||
GTK_TEXT_SEARCH_VISIBLE_ONLY | GTK_TEXT_SEARCH_TEXT_ONLY,
|
||||
&match_start, &match_end, NULL);
|
||||
}
|
||||
|
||||
if (found) {
|
||||
gtk_text_buffer_place_cursor(buffer, &match_start);
|
||||
gtk_text_buffer_move_mark_by_name(buffer, "selection_bound",
|
||||
&match_end);
|
||||
gtk_text_view_scroll_to_iter(text_view, &match_start,
|
||||
0.0, FALSE, 0.0, 0.0);
|
||||
}
|
||||
}
|
||||
|
||||
return found;
|
||||
}
|
||||
|
||||
gboolean
|
||||
gm_searchable_text_view_find_first(GtkTextView *text_view,
|
||||
const gchar *str, GmSearchableSearchFlags flags) {
|
||||
GtkTextIter iter;
|
||||
GtkTextBuffer *buffer;
|
||||
|
||||
g_return_val_if_fail(text_view != NULL, FALSE);
|
||||
|
||||
buffer = gtk_text_view_get_buffer(text_view);
|
||||
|
||||
if (buffer) {
|
||||
if (flags & GM_SEARCHABLE_SEARCH_BACKWARDS) {
|
||||
gtk_text_buffer_get_end_iter(buffer, &iter);
|
||||
} else {
|
||||
gtk_text_buffer_get_start_iter(buffer, &iter);
|
||||
}
|
||||
|
||||
gtk_text_buffer_place_cursor(buffer, &iter);
|
||||
|
||||
return gm_searchable_text_view_find_next(text_view, str, flags);
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
GtkTextView *
|
||||
gm_searchable_interface_get_text_view(GmSearchable *self,
|
||||
GmSearchableInterface *iface) {
|
||||
g_return_val_if_fail(iface != NULL, FALSE);
|
||||
|
||||
if (iface->get_text_view == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return (* iface->get_text_view) (self);
|
||||
}
|
||||
|
||||
GtkTextView *
|
||||
gm_searchable_get_text_view(GmSearchable *self) {
|
||||
GmSearchableInterface *iface;
|
||||
|
||||
g_return_val_if_fail(GM_IS_SEARCHABLE(self), FALSE);
|
||||
|
||||
iface = GM_SEARCHABLE_GET_INTERFACE(self);
|
||||
|
||||
return gm_searchable_interface_get_text_view(self, iface);
|
||||
}
|
||||
|
||||
gboolean
|
||||
gm_searchable_can_find(GmSearchable *self) {
|
||||
GmSearchableInterface *iface;
|
||||
|
||||
g_return_val_if_fail(GM_IS_SEARCHABLE(self), FALSE);
|
||||
|
||||
iface = GM_SEARCHABLE_GET_INTERFACE(self);
|
||||
|
||||
g_return_val_if_fail(iface != NULL, FALSE);
|
||||
|
||||
if (iface->find_first == NULL || iface->find_next == NULL) {
|
||||
if (gm_searchable_interface_get_text_view(self, iface) != NULL) {
|
||||
return TRUE;
|
||||
} else {
|
||||
return FALSE;
|
||||
}
|
||||
} else {
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
gboolean
|
||||
gm_searchable_find_first(GmSearchable *self, const gchar *str,
|
||||
GmSearchableSearchFlags flags) {
|
||||
GmSearchableInterface *iface;
|
||||
GtkTextView *text_view;
|
||||
|
||||
g_return_val_if_fail(GM_IS_SEARCHABLE(self), FALSE);
|
||||
|
||||
iface = GM_SEARCHABLE_GET_INTERFACE(self);
|
||||
|
||||
g_return_val_if_fail(iface != NULL, FALSE);
|
||||
|
||||
if (iface->find_first == NULL) {
|
||||
text_view = gm_searchable_interface_get_text_view(self, iface);
|
||||
|
||||
if (text_view) {
|
||||
return gm_searchable_text_view_find_first(text_view, str, flags);
|
||||
} else {
|
||||
g_return_val_if_reached(FALSE);
|
||||
}
|
||||
}
|
||||
|
||||
return (* iface->find_first) (self, str, flags);
|
||||
}
|
||||
|
||||
gboolean
|
||||
gm_searchable_find_next(GmSearchable *self, const gchar *str,
|
||||
GmSearchableSearchFlags flags) {
|
||||
GmSearchableInterface *iface;
|
||||
GtkTextView *text_view;
|
||||
|
||||
g_return_val_if_fail(GM_IS_SEARCHABLE(self), FALSE);
|
||||
|
||||
iface = GM_SEARCHABLE_GET_INTERFACE(self);
|
||||
|
||||
g_return_val_if_fail(iface != NULL, FALSE);
|
||||
|
||||
if (iface->find_next == NULL) {
|
||||
text_view = gm_searchable_interface_get_text_view(self, iface);
|
||||
|
||||
if (text_view) {
|
||||
return gm_searchable_text_view_find_next(text_view, str, flags);
|
||||
} else {
|
||||
g_return_val_if_reached(FALSE);
|
||||
}
|
||||
}
|
||||
|
||||
return (* iface->find_next) (self, str, flags);
|
||||
}
|
|
@ -0,0 +1,45 @@
|
|||
#ifndef __GM_SEARCHABLE_H__
|
||||
#define __GM_SEARCHABLE_H__
|
||||
|
||||
#include <gtk/gtk.h>
|
||||
#include <glib.h>
|
||||
|
||||
#define GM_TYPE_SEARCHABLE (gm_searchable_get_type())
|
||||
#define GM_SEARCHABLE(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), \
|
||||
GM_TYPE_SEARCHABLE, GmSearchable))
|
||||
#define GM_SEARCHABLE_CLASS(obj) (G_TYPE_CHECK_CLASS_CAST((obj), \
|
||||
GM_TYPE_SEARCHABLE, GmSearchableInterface))
|
||||
#define GM_IS_SEARCHABLE(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), \
|
||||
GM_TYPE_SEARCHABLE))
|
||||
#define GM_SEARCHABLE_GET_INTERFACE(inst) (G_TYPE_INSTANCE_GET_INTERFACE( \
|
||||
(inst), GM_TYPE_SEARCHABLE, GmSearchableInterface))
|
||||
|
||||
typedef struct _GmSearchable GmSearchable; /* dummy object */
|
||||
typedef struct _GmSearchableInterface GmSearchableInterface;
|
||||
|
||||
typedef enum _GmSearchableSearchFlags {
|
||||
GM_SEARCHABLE_SEARCH_NONE = 0,
|
||||
GM_SEARCHABLE_SEARCH_FORWARDS = 1 << 0,
|
||||
GM_SEARCHABLE_SEARCH_BACKWARDS = 1 << 1
|
||||
} GmSearchableSearchFlags;
|
||||
|
||||
struct _GmSearchableInterface {
|
||||
GTypeInterface parent;
|
||||
|
||||
GtkTextView *(* get_text_view) (GmSearchable *self);
|
||||
gboolean (* find_first) (GmSearchable *self, gchar const *str,
|
||||
GmSearchableSearchFlags flags);
|
||||
gboolean (* find_next) (GmSearchable *self, gchar const *str,
|
||||
GmSearchableSearchFlags flags);
|
||||
};
|
||||
|
||||
GType gm_searchable_get_type();
|
||||
|
||||
GtkTextView *gm_searchable_get_text_view(GmSearchable *self);
|
||||
gboolean gm_searchable_can_find(GmSearchable *self);
|
||||
gboolean gm_searchable_find_first(GmSearchable *self, const gchar *str,
|
||||
GmSearchableSearchFlags flags);
|
||||
gboolean gm_searchable_find_next(GmSearchable *self, const gchar *str,
|
||||
GmSearchableSearchFlags flags);
|
||||
|
||||
#endif /* __GM_SEARCHABLE_H__ */
|
Reference in New Issue