Moved string functions to gm-string, improved file reading

This commit is contained in:
Jesse van den Kieboom 2005-11-15 12:02:38 +00:00
parent 5f77eaba58
commit 56a85b6557
2 changed files with 268 additions and 301 deletions

View File

@ -8,6 +8,8 @@
#include <string.h> #include <string.h>
#include <stdio.h> #include <stdio.h>
#include <locale.h> #include <locale.h>
#include <sys/mman.h>
#include <fcntl.h>
#include <gtk/gtk.h> #include <gtk/gtk.h>
#include <regex.h> #include <regex.h>
@ -43,16 +45,16 @@ gm_fix_decimal_point(gchar *line, int len) {
gchar * gchar *
gm_fix_decimal_point_rev(gchar *line, int len) { gm_fix_decimal_point_rev(gchar *line, int len) {
int i; int i;
struct lconv *l = localeconv(); struct lconv *l = localeconv();
for (i = 0; i < len; i++) { for (i = 0; i < len; i++) {
if (line[i] == l->decimal_point[0]) { if (line[i] == l->decimal_point[0]) {
line[i] = '.'; line[i] = '.';
} }
} }
return line; return line;
} }
gchar * gchar *
@ -76,133 +78,104 @@ gm_ansi_strip(gchar * s) {
} }
int int
garray_length(gchar **s) { gm_garray_length(gchar **s) {
int i = 0; gchar **iter = s;
while (s[i] != NULL) { while (*iter++ != NULL)
i++; ;
}
return *iter - *s - 1;
return i;
} }
void g_list_free_simple(GList *s) { void gm_g_list_free_simple(GList *s) {
GList *tmp; GList *tmp;
for (tmp = s; tmp; tmp = tmp->next) { for (tmp = s; tmp; tmp = tmp->next) {
g_free(tmp->data); g_free(tmp->data);
} }
g_list_free(s); g_list_free(s);
} }
gchar * gchar *
g_list_find_simple(GList *s, gchar *f) { gm_g_list_find_simple(GList *s, gchar *f) {
GList *tmp; GList *tmp;
for (tmp = s; tmp; tmp = tmp->next) { for (tmp = s; tmp; tmp = tmp->next) {
if (strcmp(tmp->data, f) == 0) { if (strcmp(tmp->data, f) == 0) {
return tmp->data; return tmp->data;
} }
} }
return NULL; return NULL;
} }
void void
gm_dialog(gchar * message, GtkMessageType messagebox_type, gm_dialog(gchar * message, GtkMessageType messagebox_type,
GtkWindow * parent) { GtkWindow * parent) {
GtkWidget *dlg; GtkWidget *dlg;
if (parent == NULL) { if (parent == NULL) {
//parent = GTK_WINDOW(if_main_get_widget("wndMain")); //parent = GTK_WINDOW(if_main_get_widget("wndMain"));
} }
dlg = dlg = gtk_message_dialog_new(parent,
gtk_message_dialog_new(parent, GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT,
GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT, messagebox_type, GTK_BUTTONS_OK, message, NULL);
messagebox_type, GTK_BUTTONS_OK, message, NULL); gtk_dialog_run(GTK_DIALOG(dlg));
gtk_dialog_run(GTK_DIALOG(dlg)); gtk_widget_destroy(dlg);
gtk_widget_destroy(dlg);
} }
void void
gm_error_dialog(gchar * message, GtkWindow * parent) { gm_error_dialog(gchar * message, GtkWindow * parent) {
gm_dialog(message, GTK_MESSAGE_ERROR, parent); gm_dialog(message, GTK_MESSAGE_ERROR, parent);
} }
void void
gm_warning_dialog(gchar * message, GtkWindow * parent) { gm_warning_dialog(gchar * message, GtkWindow * parent) {
gm_dialog(message, GTK_MESSAGE_WARNING, parent); gm_dialog(message, GTK_MESSAGE_WARNING, parent);
} }
void void
gm_info_dialog(gchar * message, GtkWindow * parent) { gm_info_dialog(gchar * message, GtkWindow * parent) {
gm_dialog(message, GTK_MESSAGE_INFO, parent); gm_dialog(message, GTK_MESSAGE_INFO, parent);
} }
void void
gm_question_dialog(gchar * message, GtkWindow * parent) { gm_question_dialog(gchar * message, GtkWindow * parent) {
gm_dialog(message, GTK_MESSAGE_QUESTION, parent); gm_dialog(message, GTK_MESSAGE_QUESTION, parent);
} }
void void
gm_do_events() { gm_do_events() {
while (gtk_events_pending()) { while (gtk_events_pending()) {
gtk_main_iteration(); gtk_main_iteration();
} }
}
gchar *
gm_str_escape(gchar * line) {
gchar *newLine;
int i, j = 0;
if (strlen(line) == 0) {
return g_strdup("");
}
if (strstr(line, "\"") || strstr(line, "\\")) {
newLine = g_new(gchar, (strlen(line) * 2) + 1);
for (i = 0; i < (int)strlen(line); i++) {
if (line[i] == '"' || line[i] == '\\') {
newLine[j] = '\\';
j++;
}
newLine[j] = line[i];
j++;
}
newLine[j] = '\0';
return newLine;
} else {
return g_strdup(line);
}
} }
void void
gm_directory_remove_all(const gchar * path, gboolean remove_self) { gm_directory_remove_all(const gchar * path, gboolean remove_self) {
GDir *cDir; GDir *cDir;
gchar *name; gchar *name;
gchar *newPath; gchar *newPath;
if (g_file_test(path, G_FILE_TEST_IS_DIR)) { if (g_file_test(path, G_FILE_TEST_IS_DIR)) {
// Iterate through the files and do the right thingie // Iterate through the files and do the right thingie
if ((cDir = g_dir_open(path, 0, NULL))) { if ((cDir = g_dir_open(path, 0, NULL))) {
while ((name = (gchar *) (g_dir_read_name(cDir))) != NULL) { while ((name = (gchar *) (g_dir_read_name(cDir))) != NULL) {
newPath = g_strconcat(path, "/", name, NULL); newPath = g_strconcat(path, "/", name, NULL);
gm_directory_remove_all(newPath, TRUE); gm_directory_remove_all(newPath, TRUE);
g_free(newPath); g_free(newPath);
} }
g_dir_close(cDir);
} g_dir_close(cDir);
} }
}
if (remove_self) { if (remove_self) {
// Its a file, or just empty! MUST...BE...REMOVEEEED! // Its a file, or just empty! MUST...BE...REMOVEEEED!
remove(path); remove(path);
} }
} }
gint gint
@ -245,24 +218,24 @@ gm_url_regex_match(const gchar *msg, int len, GArray *start, GArray *end) {
} }
void void
gm_open_url (const gchar *url) { gm_open_url(const gchar *url) {
if (!url || strlen (url) == 0) { if (url == NULL || *url == '\0') {
return; return;
} }
/* gnome_url_show doesn't work when there's no protocol, so we might /* gnome_url_show doesn't work when there's no protocol, so we might
* need to add one. * need to add one.
*/ */
if (strstr (url, "://") == NULL) { if (strstr(url, "://") == NULL) {
gchar *tmp; gchar *tmp;
tmp = g_strconcat ("http://", url, NULL); tmp = g_strconcat("http://", url, NULL);
gnome_url_show(tmp, NULL); gnome_url_show(tmp, NULL);
g_free (tmp); g_free(tmp);
return; return;
} }
gnome_url_show (url, NULL); gnome_url_show(url, NULL);
} }
void void
@ -310,8 +283,8 @@ gint
gm_fetch_progress(GnomeVFSAsyncHandle *handle, gm_fetch_progress(GnomeVFSAsyncHandle *handle,
GnomeVFSXferProgressInfo *info, GnomeVFSXferProgressInfo *info,
GmFetchHandle *g) { GmFetchHandle *g) {
gchar *name; gchar *name;
const gchar *err; gchar const *err;
g->cur_phase = info->phase; g->cur_phase = info->phase;
g->cur_file = info->file_index; g->cur_file = info->file_index;
@ -320,190 +293,196 @@ gm_fetch_progress(GnomeVFSAsyncHandle *handle,
g->file_size = info->file_size; g->file_size = info->file_size;
g->bytes_copied = info->bytes_copied; g->bytes_copied = info->bytes_copied;
g->total_bytes_copied = info->total_bytes_copied; g->total_bytes_copied = info->total_bytes_copied;
g->status = info->status; g->status = info->status;
if (g->aborted) { if (g->aborted) {
g->cb(g, g->user_data); g->cb(g, g->user_data);
gm_fetch_handle_free(g); gm_fetch_handle_free(g);
return FALSE; return FALSE;
} }
if (info->target_name != NULL) { if (info->target_name != NULL) {
if (g->cur_file_name && strcmp(g->cur_file_name, info->target_name) != 0) { if (g->cur_file_name && strcmp(g->cur_file_name, info->target_name) != 0) {
g->cur_phase = GNOME_VFS_XFER_PHASE_FILECOMPLETED; g->cur_phase = GNOME_VFS_XFER_PHASE_FILECOMPLETED;
g->cb(g, g->user_data); g->cb(g, g->user_data);
g->cur_phase = info->phase; g->cur_phase = info->phase;
g_free(g->cur_file_name);
g->cur_file_name = NULL;
}
if (!g->cur_file_name) { g_free(g->cur_file_name);
g->cur_file_name = g_strdup(info->target_name); g->cur_file_name = NULL;
} }
}
if (!g->cur_file_name) {
g->cur_file_name = g_strdup(info->target_name);
}
}
if (info->status == GNOME_VFS_XFER_PROGRESS_STATUS_OVERWRITE) { if (info->status == GNOME_VFS_XFER_PROGRESS_STATUS_OVERWRITE) {
name = gnome_vfs_get_local_path_from_uri(info->target_name); name = gnome_vfs_get_local_path_from_uri(info->target_name);
gm_debug_msg(DEBUG_DEFAULT, "gnoemoe_fetch_progress: asking for overwriting %s: yes", name); gm_debug_msg(DEBUG_DEFAULT, "GmFetchProgress: asking for overwriting "
"%s: yes", name);
g->prev_status = GNOME_VFS_XFER_PROGRESS_STATUS_OVERWRITE; g->prev_status = GNOME_VFS_XFER_PROGRESS_STATUS_OVERWRITE;
return GNOME_VFS_XFER_OVERWRITE_ACTION_REPLACE; return GNOME_VFS_XFER_OVERWRITE_ACTION_REPLACE;
} else if (info->status == GNOME_VFS_XFER_PROGRESS_STATUS_VFSERROR) { } else if (info->status == GNOME_VFS_XFER_PROGRESS_STATUS_VFSERROR) {
name = gnome_vfs_get_local_path_from_uri(info->target_name); name = gnome_vfs_get_local_path_from_uri(info->target_name);
err = gnome_vfs_result_to_string(info->vfs_status); err = gnome_vfs_result_to_string(info->vfs_status);
gdk_threads_enter(); gdk_threads_enter();
gm_debug_msg(DEBUG_DEFAULT, "gnoemoe_fetch_progress: error for %s: %s", name, err); gm_debug_msg(DEBUG_DEFAULT, "GmFetchProgress: error for %s: %s", name,
g->cb(g, g->user_data); err);
gdk_threads_leave(); g->cb(g, g->user_data);
gdk_threads_leave();
g_free(g->cur_file_name); g_free(g->cur_file_name);
g->cur_file_name = NULL; g->cur_file_name = NULL;
g->prev_status = GNOME_VFS_XFER_PROGRESS_STATUS_VFSERROR; g->prev_status = GNOME_VFS_XFER_PROGRESS_STATUS_VFSERROR;
g_free(name); g_free(name);
return GNOME_VFS_XFER_ERROR_ACTION_SKIP; return GNOME_VFS_XFER_ERROR_ACTION_SKIP;
} }
if (info->phase == GNOME_VFS_XFER_PHASE_COMPLETED) { if (info->phase == GNOME_VFS_XFER_PHASE_COMPLETED) {
if (g->cur_file_name != NULL) { if (g->cur_file_name != NULL) {
g->cur_phase = GNOME_VFS_XFER_PHASE_FILECOMPLETED; g->cur_phase = GNOME_VFS_XFER_PHASE_FILECOMPLETED;
g->cb(g, g->user_data); g->cb(g, g->user_data);
g->cur_phase = info->phase; g->cur_phase = info->phase;
} }
g->done = TRUE; g->done = TRUE;
g->cb(g, g->user_data); g->cb(g, g->user_data);
gm_fetch_handle_free(g); gm_fetch_handle_free(g);
return TRUE;
} return TRUE;
}
g->prev_status = info->status; g->prev_status = info->status;
return TRUE; return TRUE;
} }
gint gint
gm_fetch_interact(GnomeVFSXferProgressInfo *info, gpointer user_data) { gm_fetch_interact(GnomeVFSXferProgressInfo *info, gpointer user_data) {
return 1; return 1;
} }
GmFetchHandle * GmFetchHandle *
gm_fetch(const GList *source, const GList *dest, gm_fetch(const GList *source, const GList *dest,
GFunc cb, gpointer user_data) { GFunc cb, gpointer user_data) {
GmFetchHandle *g = gm_fetch_handle_create(cb, user_data); GmFetchHandle *g = gm_fetch_handle_create(cb, user_data);
gchar *uri; gchar *uri;
GnomeVFSResult ret;
for (; source; source = source->next) {
uri = (gchar *)(source->data); for (; source; source = source->next) {
g->source_uri = g_list_append(g->source_uri, gnome_vfs_uri_new(uri)); uri = (gchar *)(source->data);
} g->source_uri = g_list_append(g->source_uri, gnome_vfs_uri_new(uri));
}
for (; dest; dest = dest->next) {
uri = (gchar *)(dest->data); for (; dest; dest = dest->next) {
g->dest_uri = g_list_append(g->dest_uri, gnome_vfs_uri_new(uri)); uri = (gchar *)(dest->data);
} g->dest_uri = g_list_append(g->dest_uri, gnome_vfs_uri_new(uri));
}
gnome_vfs_async_xfer(&(g->handle), g->source_uri, g->dest_uri,
GNOME_VFS_XFER_DEFAULT|GNOME_VFS_XFER_RECURSIVE, ret = gnome_vfs_async_xfer(&(g->handle), g->source_uri, g->dest_uri,
GNOME_VFS_XFER_ERROR_MODE_QUERY, GNOME_VFS_XFER_DEFAULT|GNOME_VFS_XFER_RECURSIVE,
GNOME_VFS_XFER_OVERWRITE_MODE_REPLACE, GNOME_VFS_XFER_ERROR_MODE_QUERY,
GNOME_VFS_PRIORITY_DEFAULT, GNOME_VFS_XFER_OVERWRITE_MODE_REPLACE,
(GnomeVFSAsyncXferProgressCallback)gm_fetch_progress, GNOME_VFS_PRIORITY_DEFAULT,
g, gm_fetch_interact, g); (GnomeVFSAsyncXferProgressCallback)gm_fetch_progress,
return g; g, gm_fetch_interact, g);
return g;
} }
gboolean gboolean
gm_is_end_scrolled(GtkScrolledWindow *wnd, guint charHeight) { gm_is_end_scrolled(GtkScrolledWindow *wnd, guint charHeight) {
GtkAdjustment *ad = gtk_scrolled_window_get_vadjustment(wnd); GtkAdjustment *ad = gtk_scrolled_window_get_vadjustment(wnd);
return ((ad->page_size + ad->value) >= ad->upper - (double)charHeight); return ((ad->page_size + ad->value) >= ad->upper - (double)charHeight);
} }
void void
gm_scroll_end(GtkTextView *view, gboolean needs) { gm_scroll_end(GtkTextView *view, gboolean needs) {
GtkTextBuffer *buf; GtkTextBuffer *buf;
GtkTextMark *mark; GtkTextMark *mark;
GtkTextIter iter; GtkTextIter iter;
if (!needs) { if (!needs) {
return; return;
} }
buf = gtk_text_view_get_buffer(view); buf = gtk_text_view_get_buffer(view);
mark = gtk_text_buffer_get_mark(buf, "end-of-buffer"); mark = gtk_text_buffer_get_mark(buf, "end-of-buffer");
if (mark == NULL) { if (mark == NULL) {
gtk_text_buffer_get_end_iter(buf, &iter); gtk_text_buffer_get_end_iter(buf, &iter);
mark = gtk_text_buffer_create_mark(buf, "end-of-buffer", &iter, FALSE); mark = gtk_text_buffer_create_mark(buf, "end-of-buffer", &iter, FALSE);
} }
gtk_text_view_scroll_to_mark(view, mark, 0.0, TRUE, 1.0, 1.0); gtk_text_view_scroll_to_mark(view, mark, 0.0, TRUE, 1.0, 1.0);
} }
#define MAX_BUF 1024 #define MAX_BUF 1024
GString * gchar *
gm_read_file(const gchar *fname, gboolean readall, OpenLogProgress func, gpointer user_data) { gm_read_file(const gchar *fname) {
FILE *f; int fd;
gchar line[MAX_BUF], *tmp; gchar *tmp, *mapped;
GString *str = NULL; long bytes_total = 0;
long bytes_read = 0, bytes_total = 0;
if (!fname) { if (!fname) {
return NULL; return NULL;
} }
f = fopen(fname, "r"); fd = open(fname, O_RDONLY);
if (f) { if (fd == -1) {
fseek(f, 0, SEEK_END); gm_debug_msg(DEBUG_DEFAULT, "GmReadFile: file (%s) could not be read: "
bytes_total = ftell(f); "%s", fname, strerror(errno));
rewind(f); return NULL;
}
str = g_string_new("");
bytes_total = lseek(fd, 0, SEEK_END);
lseek(fd, 0, SEEK_SET);
if (bytes_total == (off_t)-1) {
close(fd);
return NULL;
}
mapped = mmap(0, bytes_total, PROT_READ, MAP_PRIVATE, fd, 0);
if (mapped == MAP_FAILED) {
close(fd);
while (fgets((char *) &line, MAX_BUF, f) != NULL) { gm_debug_msg(DEBUG_DEFAULT, "GmReadFile: error while mapping file: %s",
bytes_read += strlen((char *)&line); strerror(errno));
tmp = NULL; return NULL;
if (g_utf8_validate(line, -1, NULL)) { }
if (readall) {
str = g_string_append(str, line); if (g_utf8_validate(mapped, bytes_total, NULL)) {
} // Easy, this is utf8!
tmp = g_strdup(line); tmp = g_strndup(mapped, bytes_total);
} else { } else {
tmp = g_locale_to_utf8(line, -1, NULL, NULL, NULL); // Try locale
tmp = g_locale_to_utf8(mapped, bytes_total, NULL, NULL, NULL);
if (!tmp) {
tmp = g_convert(line, -1, "UTF-8", "ISO-8859-15", NULL, NULL, NULL); if (!tmp) {
} // Now we're getting desperate... try ISO-8859-15
if (!tmp) { tmp = g_convert(mapped, bytes_total, "UTF-8", "ISO-8859-15", NULL,
tmp = g_convert(line, -1, "UTF-8", "ISO-8859-15", NULL, NULL, NULL); NULL, NULL);
} }
if (readall) { if (!tmp) {
str = g_string_append(str, tmp); // OMG try one last conversion to ISO-8859-1
} tmp = g_convert(mapped, bytes_total, "UTF-8", "ISO-8859-1", NULL,
} NULL, NULL);
}
if (func != NULL) { }
func(bytes_read, bytes_total, tmp, user_data);
} else { munmap(mapped, bytes_total);
g_free(tmp); close(fd);
} return tmp;
}
fclose(f);
return str;
} else {
gm_debug_msg(DEBUG_DEFAULT, "support_read_file: file (%s) could not be read: %s",
fname, strerror(errno));
return NULL;
}
} }
GtkWidget * GtkWidget *
@ -551,21 +530,24 @@ gm_create_tab_label(const gchar *icon, const gchar *caption, gboolean has_exit,
void void
gm_widget_destroy_data(GtkWidget *caller, GtkWidget *destroyer) { gm_widget_destroy_data(GtkWidget *caller, GtkWidget *destroyer) {
if (GTK_IS_WIDGET(destroyer)) { if (GTK_IS_WIDGET(destroyer)) {
gtk_widget_destroy(destroyer); gtk_widget_destroy(destroyer);
} }
} }
const gchar * const gchar *
gm_default_charset() { gm_default_charset() {
const gchar *loc = NULL; static const gchar *loc = NULL;
g_get_charset(&loc);
if (loc == NULL) {
if (loc == NULL || strlen(loc) == 0) { g_get_charset(&loc);
loc = "ISO-8859-15"; }
}
return loc; if (loc == NULL || *loc == 0) {
loc = "ISO-8859-15";
}
return loc;
} }
void void
@ -584,39 +566,6 @@ gm_notebook_focus_from_label(GtkNotebook *note, gchar *caption) {
} }
} }
void
gm_string_skip_space(gchar **ptr) {
while (**ptr != '\0' && g_unichar_isspace(g_utf8_get_char(*ptr))) {
*ptr = g_utf8_next_char(*ptr);
}
}
void
gm_string_skip_nonspace(gchar **ptr) {
while (**ptr != '\0' && !g_unichar_isspace(g_utf8_get_char(*ptr))) {
*ptr = g_utf8_next_char(*ptr);
}
}
void
gm_string_skip_till(gchar **ptr, gchar const *find) {
gchar const *fptr;
gunichar check;
while (**ptr != '\0') {
check = g_utf8_get_char(*ptr);
for (fptr = find; *fptr; ++fptr) {
// CHECK: find should also be treated as utf8!
if (check == (gunichar)(*fptr)) {
return;
}
}
*ptr = g_utf8_next_char(*ptr);
}
}
gchar * gchar *
gm_to_utf8_with_fallback(gchar const *text, gssize len, gchar const *from, gm_to_utf8_with_fallback(gchar const *text, gssize len, gchar const *from,
gchar const *fallback) { gchar const *fallback) {
@ -645,3 +594,25 @@ gm_to_utf8_with_fallback(gchar const *text, gssize len, gchar const *from,
g_string_free(str, FALSE); g_string_free(str, FALSE);
return res; return res;
} }
GtkWidget *
gm_container_item(GtkContainer *cnt, GType type) {
GList *child_first = gtk_container_get_children(cnt);
GList *child;
GtkWidget *result = NULL;
for (child = child_first; child; child = child->next) {
if (G_TYPE_CHECK_INSTANCE_TYPE(child->data, type)) {
result = GTK_WIDGET(child->data);
break;
} else if (GTK_IS_CONTAINER(child->data)) {
if ((result = gm_container_item(
GTK_CONTAINER(child->data), type))) {
break;
}
}
}
g_list_free(child_first);
return result;
}

View File

@ -114,8 +114,8 @@ gchar *gm_fix_decimal_point(gchar *line, int len);
gchar *gm_fix_decimal_point_rev(gchar *line, int len); gchar *gm_fix_decimal_point_rev(gchar *line, int len);
gchar *gm_ansi_strip(gchar * s); gchar *gm_ansi_strip(gchar * s);
int garray_length(gchar **s); int garray_length(gchar **s);
void g_list_free_simple(GList *s); void gm_g_list_free_simple(GList *s);
gchar *g_list_find_simple(GList *s, gchar *f); gchar *gm_g_list_find_simple(GList *s, gchar *f);
void gm_error_dialog(gchar * message, GtkWindow * parent); void gm_error_dialog(gchar * message, GtkWindow * parent);
void gm_warning_dialog(gchar * message, GtkWindow * parent); void gm_warning_dialog(gchar * message, GtkWindow * parent);
@ -124,11 +124,10 @@ void gm_question_dialog(gchar * message, GtkWindow * parent);
void gm_do_events(); void gm_do_events();
gchar *gm_str_escape(gchar * line);
void gm_directory_remove_all(const gchar * path, gboolean remove_self); void gm_directory_remove_all(const gchar * path, gboolean remove_self);
gint gm_url_regex_match(const gchar *msg, int len, GArray *start, GArray *end); gint gm_url_regex_match(const gchar *msg, int len, GArray *start, GArray *end);
void gm_open_url (const gchar *url); void gm_open_url(const gchar *url);
GmFetchHandle * gm_fetch(const GList *source, const GList *dest, GmFetchHandle * gm_fetch(const GList *source, const GList *dest,
GFunc cb, gpointer user_data); GFunc cb, gpointer user_data);
@ -137,20 +136,17 @@ void gm_fetch_handle_free(GmFetchHandle *g);
gboolean gm_is_end_scrolled(GtkScrolledWindow *wnd, guint charHeight); gboolean gm_is_end_scrolled(GtkScrolledWindow *wnd, guint charHeight);
void gm_scroll_end(GtkTextView *view, gboolean needs); void gm_scroll_end(GtkTextView *view, gboolean needs);
typedef void (*OpenLogProgress) (long, long, gchar *, gpointer); typedef gboolean (*ReadProgressFunc) (long, long, gchar *, gpointer);
GString *gm_read_file(const gchar *fname, gboolean readall,
OpenLogProgress func, gpointer user_data); gchar *gm_read_file(gchar const *fname);
GtkWidget *gm_create_tab_label(const gchar *icon, const gchar *caption, GtkWidget *gm_create_tab_label(const gchar *icon, const gchar *caption,
gboolean has_exit, GmLabelInfo *info); gboolean has_exit, GmLabelInfo *info);
void gm_widget_destroy_data(GtkWidget *caller, GtkWidget *destroyer); void gm_widget_destroy_data(GtkWidget *caller, GtkWidget *destroyer);
const gchar *gm_default_charset(); const gchar *gm_default_charset();
void gm_notebook_focus_from_label(GtkNotebook *note, gchar *caption); void gm_notebook_focus_from_label(GtkNotebook *note, gchar *caption);
void gm_string_skip_space(gchar **ptr);
void gm_string_skip_nonspace(gchar **ptr);
void gm_string_skip_till(gchar **ptr, gchar const *find);
gchar *gm_to_utf8_with_fallback(gchar const *text, gssize len, gchar const *from, gchar *gm_to_utf8_with_fallback(gchar const *text, gssize len, gchar const *from,
gchar const *fallback); gchar const *fallback);
GtkWidget *gm_container_item(GtkContainer *cnt, GType type);
#endif /* __GM_SUPPORT_H__ */ #endif /* __GM_SUPPORT_H__ */