33#include <glib/gstdio.h>
42PLUGIN_SET_INFO(
_(
"Save Actions"),
_(
"This plugin provides different actions related to saving of files."),
43 VERSION,
_(
"The Geany developer team"))
101 if (G_UNLIKELY(
EMPTY(utf8_dir)) || target ==
NULL)
106 if (! g_path_is_absolute(tmp) ||
107 ! g_file_test(tmp, G_FILE_TEST_EXISTS) ||
108 ! g_file_test(tmp, G_FILE_TEST_IS_DIR))
124 const gchar *dir = g_path_skip_root(
filename);
130 while (*dir == G_DIR_SEPARATOR)
133 return (gchar *) dir;
139 gint cnt_dir_parts = 0;
150 dirname = g_path_get_dirname(
filename);
160 if (*cp == G_DIR_SEPARATOR && last_char != G_DIR_SEPARATOR)
179 result = g_strdup(
"");
182 result = g_strdup(result);
194 gchar *locale_filename_src;
195 gchar *locale_filename_dst;
197 gchar *dir_parts_src;
207 if ((src = g_fopen(locale_filename_src,
"r")) ==
NULL)
212 g_free(locale_filename_src);
217 basename_src = g_path_get_basename(locale_filename_src);
219 locale_filename_dst = g_strconcat(
221 dir_parts_src, G_DIR_SEPARATOR_S,
222 basename_src,
".", stamp,
NULL);
223 g_free(basename_src);
224 g_free(dir_parts_src);
227 if ((dst = g_fopen(locale_filename_dst,
"wb")) ==
NULL)
231 fd_dst = g_open(locale_filename_dst, O_CREAT | O_WRONLY,
S_IWUSR |
S_IRUSR);
232 if (fd_dst == -1 || (dst = fdopen(fd_dst,
"w")) ==
NULL)
237 g_free(locale_filename_src);
238 g_free(locale_filename_dst);
246 while (fgets(buf,
sizeof(buf), src) !=
NULL)
255 g_free(locale_filename_src);
256 g_free(locale_filename_dst);
265 const gchar *directory;
277 new_filename = g_build_filename(directory,
"gis_XXXXXX",
NULL);
282 fd = g_mkstemp(new_filename);
285 gchar *message = g_strdup_printf(
286 _(
"Instant Save filename could not be generated (%s)."), g_strerror(
errno));
288 g_warning(
"%s", message);
290 g_free(new_filename);
360 gint i,
max = gtk_notebook_get_n_pages(GTK_NOTEBOOK(
geany->main_widgets->notebook));
361 gint saved_files = 0;
368 for (i = 0; i <
max; i++)
386 "Autosave: Saved %d file automatically.",
387 "Autosave: Saved %d files automatically.", saved_files),
407 GKeyFile *config = g_key_file_new();
410 config_file = g_strconcat(
geany->app->configdir, G_DIR_SEPARATOR_S,
"plugins",
411 G_DIR_SEPARATOR_S,
"saveactions", G_DIR_SEPARATOR_S,
"saveactions.conf",
NULL);
416 config,
"saveactions",
"enable_autosave", FALSE);
418 config,
"saveactions",
"enable_autosave_losing_focus", FALSE);
420 config,
"saveactions",
"enable_instantsave", FALSE);
422 config,
"saveactions",
"enable_backupcopy", FALSE);
439 config,
"backupcopy",
"time_fmt",
"%Y-%m-%d-%H-%M-%S");
444 g_key_file_free(config);
454 dialog = gtk_file_chooser_dialog_new(
_(
"Select Directory"),
NULL,
455 GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER,
456 GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
457 GTK_STOCK_OPEN, GTK_RESPONSE_ACCEPT,
NULL);
461 gtk_file_chooser_set_current_folder(GTK_FILE_CHOOSER(
dialog),
text);
464 if (gtk_dialog_run(GTK_DIALOG(
dialog)) == GTK_RESPONSE_ACCEPT)
466 gchar *utf8_filename, *tmp;
468 tmp = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(
dialog));
471 gtk_entry_set_text(GTK_ENTRY(item), utf8_filename);
473 g_free(utf8_filename);
477 gtk_widget_destroy(
dialog);
483 if (response == GTK_RESPONSE_OK || response == GTK_RESPONSE_APPLY)
485 GKeyFile *config = g_key_file_new();
487 const gchar *backupcopy_text_dir, *instantsave_text_dir, *text_time;
488 gchar *config_dir = g_path_get_dirname(
config_file);
491 GTK_TOGGLE_BUTTON(
pref_widgets.checkbox_enable_autosave));
493 GTK_TOGGLE_BUTTON(
pref_widgets.checkbox_enable_autosave_losing_focus));
495 GTK_TOGGLE_BUTTON(
pref_widgets.checkbox_enable_instantsave));
497 GTK_TOGGLE_BUTTON(
pref_widgets.checkbox_enable_backupcopy));
502 GTK_TOGGLE_BUTTON(
pref_widgets.autosave_print_msg_checkbox));
504 GTK_TOGGLE_BUTTON(
pref_widgets.autosave_save_all_radio2));
509 instantsave_text_dir = gtk_entry_get_text(GTK_ENTRY(
pref_widgets.instantsave_entry_dir));
511 backupcopy_text_dir = gtk_entry_get_text(GTK_ENTRY(
pref_widgets.backupcopy_entry_dir));
512 text_time = gtk_entry_get_text(GTK_ENTRY(
pref_widgets.backupcopy_entry_time));
514 GTK_SPIN_BUTTON(
pref_widgets.backupcopy_spin_dir_levels));
519 g_key_file_set_boolean(config,
"saveactions",
"enable_autosave",
enable_autosave);
521 g_key_file_set_boolean(config,
"saveactions",
"enable_instantsave",
enable_instantsave);
522 g_key_file_set_boolean(config,
"saveactions",
"enable_backupcopy",
enable_backupcopy);
532 if (
EMPTY(instantsave_text_dir))
534 g_key_file_set_string(config,
"instantsave",
"target_dir",
"");
544 _(
"Instantsave directory does not exist or is not writable."));
549 g_key_file_set_string(config,
"backupcopy",
"time_fmt", text_time);
556 g_key_file_set_string(config,
"backupcopy",
"backup_dir", backupcopy_text_dir);
561 _(
"Backup directory does not exist or is not writable."));
566 if (! g_file_test(config_dir, G_FILE_TEST_IS_DIR) &&
utils_mkdir(config_dir, TRUE) != 0)
569 _(
"Plugin configuration directory could not be created."));
574 str = g_key_file_to_data(config,
NULL,
NULL);
583 g_key_file_free(config);
590 gboolean enable = gtk_toggle_button_get_active(tb);
592 switch (GPOINTER_TO_INT(data))
596 gtk_widget_set_sensitive(
pref_widgets.autosave_interval_spin, enable);
597 gtk_widget_set_sensitive(
pref_widgets.autosave_print_msg_checkbox, enable);
598 gtk_widget_set_sensitive(
pref_widgets.autosave_save_all_radio1, enable);
599 gtk_widget_set_sensitive(
pref_widgets.autosave_save_all_radio2, enable);
604 gtk_widget_set_sensitive(
pref_widgets.instantsave_ft_combo, enable);
609 gtk_widget_set_sensitive(
pref_widgets.backupcopy_entry_dir, enable);
610 gtk_widget_set_sensitive(
pref_widgets.backupcopy_entry_time, enable);
611 gtk_widget_set_sensitive(
pref_widgets.backupcopy_spin_dir_levels, enable);
621 GtkWidget *vbox, *
label, *notebook_vbox, *checkbox_enable;
622 GtkWidget *notebook, *inner_vbox;
624 vbox = gtk_box_new(GTK_ORIENTATION_VERTICAL, 6);
626 notebook = gtk_notebook_new();
627 gtk_widget_set_can_focus(notebook, FALSE);
628 gtk_container_set_border_width(GTK_CONTAINER(notebook), 5);
629 gtk_box_pack_start(GTK_BOX(vbox), notebook, FALSE, TRUE, 0);
635 GtkWidget *spin, *hbox, *checkbox, *checkbox_enable_as_lf, *radio1, *radio2;
637 notebook_vbox = gtk_box_new(GTK_ORIENTATION_VERTICAL, 2);
638 inner_vbox = gtk_box_new(GTK_ORIENTATION_VERTICAL, 5);
639 gtk_container_set_border_width(GTK_CONTAINER(inner_vbox), 5);
640 gtk_box_pack_start(GTK_BOX(notebook_vbox), inner_vbox, TRUE, TRUE, 5);
641 gtk_notebook_insert_page(GTK_NOTEBOOK(notebook),
644 checkbox_enable_as_lf = gtk_check_button_new_with_mnemonic(
_(
"Enable save when losing _focus"));
645 gtk_button_set_focus_on_click(GTK_BUTTON(checkbox_enable_as_lf), FALSE);
646 pref_widgets.checkbox_enable_autosave_losing_focus = checkbox_enable_as_lf;
647 gtk_box_pack_start(GTK_BOX(inner_vbox), checkbox_enable_as_lf, FALSE, FALSE, 6);
650 checkbox_enable = gtk_check_button_new_with_mnemonic(
_(
"_Enable"));
651 gtk_button_set_focus_on_click(GTK_BUTTON(checkbox_enable), FALSE);
652 pref_widgets.checkbox_enable_autosave = checkbox_enable;
653 gtk_box_pack_start(GTK_BOX(inner_vbox), checkbox_enable, FALSE, FALSE, 6);
654 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(checkbox_enable),
enable_autosave);
655 g_signal_connect(checkbox_enable,
"toggled",
658 label = gtk_label_new_with_mnemonic(
_(
"Auto save _interval:"));
659 gtk_misc_set_alignment(GTK_MISC(
label), 0, 0.5);
660 gtk_box_pack_start(GTK_BOX(inner_vbox),
label, TRUE, TRUE, 0);
662 pref_widgets.autosave_interval_spin = spin = gtk_spin_button_new_with_range(1, 1800, 1);
664 gtk_label_set_mnemonic_widget(GTK_LABEL(
label), spin);
666 label = gtk_label_new(
_(
"seconds"));
668 hbox = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 5);
669 gtk_box_pack_start(GTK_BOX(hbox), spin, TRUE, TRUE, 0);
670 gtk_box_pack_start(GTK_BOX(hbox),
label, FALSE, FALSE, 0);
672 gtk_box_pack_start(GTK_BOX(inner_vbox), hbox, FALSE, FALSE, 5);
674 checkbox = gtk_check_button_new_with_mnemonic(
675 _(
"_Print status message if files have been automatically saved"));
676 gtk_button_set_focus_on_click(GTK_BUTTON(checkbox), FALSE);
678 gtk_label_set_mnemonic_widget(GTK_LABEL(
label), checkbox);
679 gtk_box_pack_start(GTK_BOX(inner_vbox), checkbox, FALSE, FALSE, 5);
682 radio1 = gtk_radio_button_new_with_mnemonic(
NULL,
683 _(
"Save only current open _file"));
685 gtk_label_set_mnemonic_widget(GTK_LABEL(
label), radio1);
686 gtk_button_set_focus_on_click(GTK_BUTTON(radio1), FALSE);
689 radio2 = gtk_radio_button_new_with_mnemonic_from_widget(
690 GTK_RADIO_BUTTON(radio1),
_(
"Sa_ve all open files"));
692 gtk_label_set_mnemonic_widget(GTK_LABEL(
label), radio2);
693 gtk_button_set_focus_on_click(GTK_BUTTON(radio2), FALSE);
701 GtkWidget *combo, *hbox, *entry_dir, *button, *image, *help_label;
704 gchar *entry_dir_label_text;
706 notebook_vbox = gtk_box_new(GTK_ORIENTATION_VERTICAL, 2);
707 inner_vbox = gtk_box_new(GTK_ORIENTATION_VERTICAL, 5);
708 gtk_container_set_border_width(GTK_CONTAINER(inner_vbox), 5);
709 gtk_box_pack_start(GTK_BOX(notebook_vbox), inner_vbox, TRUE, TRUE, 5);
710 gtk_notebook_insert_page(GTK_NOTEBOOK(notebook),
713 checkbox_enable = gtk_check_button_new_with_mnemonic(
_(
"_Enable"));
714 pref_widgets.checkbox_enable_instantsave = checkbox_enable;
715 gtk_button_set_focus_on_click(GTK_BUTTON(checkbox_enable), FALSE);
717 gtk_box_pack_start(GTK_BOX(inner_vbox), checkbox_enable, FALSE, FALSE, 6);
718 g_signal_connect(checkbox_enable,
"toggled",
721 label = gtk_label_new_with_mnemonic(
_(
"Default _filetype to use for new files:"));
722 gtk_misc_set_alignment(GTK_MISC(
label), 0, 0.5);
723 gtk_box_pack_start(GTK_BOX(inner_vbox),
label, FALSE, FALSE, 0);
725 pref_widgets.instantsave_ft_combo = combo = gtk_combo_box_text_new();
731 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), ft->
name);
734 gtk_combo_box_set_active(GTK_COMBO_BOX(combo), i);
737 gtk_combo_box_set_wrap_width(GTK_COMBO_BOX(combo), 3);
738 gtk_label_set_mnemonic_widget(GTK_LABEL(
label), combo);
739 gtk_box_pack_start(GTK_BOX(inner_vbox), combo, FALSE, FALSE, 0);
741 entry_dir_label_text = g_strdup_printf(
742 _(
"_Directory to save files in (leave empty to use the default: %s):"), g_get_tmp_dir());
743 label = gtk_label_new_with_mnemonic(entry_dir_label_text);
744 gtk_misc_set_alignment(GTK_MISC(
label), 0, 0.5);
745 gtk_box_pack_start(GTK_BOX(inner_vbox),
label, FALSE, FALSE, 0);
746 g_free(entry_dir_label_text);
748 pref_widgets.instantsave_entry_dir = entry_dir = gtk_entry_new();
749 gtk_label_set_mnemonic_widget(GTK_LABEL(
label), entry_dir);
753 button = gtk_button_new();
754 g_signal_connect(button,
"clicked",
757 image = gtk_image_new_from_stock(GTK_STOCK_OPEN, GTK_ICON_SIZE_BUTTON);
760 hbox = gtk_hbox_new(FALSE, 6);
761 gtk_box_pack_start(GTK_BOX(hbox), entry_dir, TRUE, TRUE, 0);
762 gtk_box_pack_start(GTK_BOX(hbox), button, FALSE, FALSE, 0);
763 gtk_box_pack_start(GTK_BOX(inner_vbox), hbox, FALSE, FALSE, 0);
765 help_label = gtk_label_new(
766 _(
"<i>If you set the Instant Save directory to a directory "
767 "which is not automatically cleared,\nyou will need to cleanup instantly saved files "
768 "manually. The Instant Save plugin will not delete the created files.</i>"));
769 gtk_label_set_use_markup(GTK_LABEL(help_label), TRUE);
770 gtk_misc_set_alignment(GTK_MISC(help_label), 0, 0.5);
771 gtk_box_pack_start(GTK_BOX(inner_vbox), help_label, FALSE, FALSE, 0);
777 GtkWidget *hbox, *entry_dir, *entry_time, *button, *image, *spin_dir_levels;
779 notebook_vbox = gtk_box_new(GTK_ORIENTATION_VERTICAL, 2);
780 inner_vbox = gtk_box_new(GTK_ORIENTATION_VERTICAL, 5);
781 gtk_container_set_border_width(GTK_CONTAINER(inner_vbox), 5);
782 gtk_box_pack_start(GTK_BOX(notebook_vbox), inner_vbox, TRUE, TRUE, 5);
783 gtk_notebook_insert_page(GTK_NOTEBOOK(notebook),
786 checkbox_enable = gtk_check_button_new_with_mnemonic(
_(
"_Enable"));
787 pref_widgets.checkbox_enable_backupcopy = checkbox_enable;
788 gtk_button_set_focus_on_click(GTK_BUTTON(checkbox_enable), FALSE);
789 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(checkbox_enable),
enable_backupcopy);
790 gtk_box_pack_start(GTK_BOX(inner_vbox), checkbox_enable, FALSE, FALSE, 6);
791 g_signal_connect(checkbox_enable,
"toggled",
794 label = gtk_label_new_with_mnemonic(
_(
"_Directory to save backup files in:"));
795 gtk_misc_set_alignment(GTK_MISC(
label), 0, 0.5);
796 gtk_box_pack_start(GTK_BOX(inner_vbox),
label, FALSE, FALSE, 0);
798 pref_widgets.backupcopy_entry_dir = entry_dir = gtk_entry_new();
799 gtk_label_set_mnemonic_widget(GTK_LABEL(
label), entry_dir);
803 button = gtk_button_new();
804 g_signal_connect(button,
"clicked",
807 image = gtk_image_new_from_stock(GTK_STOCK_OPEN, GTK_ICON_SIZE_BUTTON);
810 hbox = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 6);
811 gtk_box_pack_start(GTK_BOX(hbox), entry_dir, TRUE, TRUE, 0);
812 gtk_box_pack_start(GTK_BOX(hbox), button, FALSE, FALSE, 0);
814 gtk_box_pack_start(GTK_BOX(inner_vbox), hbox, FALSE, FALSE, 0);
816 label = gtk_label_new_with_mnemonic(
817 _(
"Date/_Time format for backup files (\"man strftime\" for details):"));
818 gtk_misc_set_alignment(GTK_MISC(
label), 0, 0.5);
819 gtk_box_pack_start(GTK_BOX(inner_vbox),
label, FALSE, FALSE, 7);
821 pref_widgets.backupcopy_entry_time = entry_time = gtk_entry_new();
822 gtk_label_set_mnemonic_widget(GTK_LABEL(
label), entry_time);
825 gtk_box_pack_start(GTK_BOX(inner_vbox), entry_time, FALSE, FALSE, 0);
827 hbox = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 6);
829 label = gtk_label_new_with_mnemonic(
830 _(
"Directory _levels to include in the backup destination:"));
831 gtk_misc_set_alignment(GTK_MISC(
label), 0, 0.5);
832 gtk_box_pack_start(GTK_BOX(hbox),
label, FALSE, FALSE, 0);
834 spin_dir_levels = gtk_spin_button_new_with_range(0, 20, 1);
835 pref_widgets.backupcopy_spin_dir_levels = spin_dir_levels;
837 gtk_label_set_mnemonic_widget(GTK_LABEL(
label), spin_dir_levels);
838 gtk_box_pack_start(GTK_BOX(hbox), spin_dir_levels, FALSE, FALSE, 0);
840 gtk_box_pack_start(GTK_BOX(inner_vbox), hbox, FALSE, FALSE, 7);
844 g_signal_emit_by_name(
pref_widgets.checkbox_enable_autosave,
"toggled");
845 g_signal_emit_by_name(
pref_widgets.checkbox_enable_instantsave,
"toggled");
846 g_signal_emit_by_name(
pref_widgets.checkbox_enable_backupcopy,
"toggled");
void dialogs_show_msgbox(GtkMessageType type, const gchar *text,...)
Shows a message box of the type type with text.
GeanyDocument * document_get_current(void)
Finds the current document.
GeanyDocument * document_get_from_page(guint page_num)
Finds the document for the given notebook page page_num.
gboolean document_save_file(GeanyDocument *doc, gboolean force)
Saves the document.
void document_set_filetype(GeanyDocument *doc, GeanyFiletype *type)
Sets the filetype of the document (which controls syntax highlighting and tags)
#define DOC_VALID(doc_ptr)
Null-safe way to check GeanyDocument::is_valid.
void error(const errorSelection selection, const char *const format,...)
#define filetypes
Wraps GeanyData::filetypes_array so it can be used with C array syntax.
Single include for plugins.
#define GEANY_API_VERSION
The Application Programming Interface (API) version, incremented whenever any plugin data types are m...
#define PLUGIN_SET_INFO(p_name, p_description, p_version, p_author)
Sets the plugin name and some other basic information about a plugin.
#define PLUGIN_VERSION_CHECK(api_required)
Defines a function to check the plugin is safe to load.
#define geany
Simple macro for geany_data that reduces typing.
guint plugin_idle_add(GeanyPlugin *plugin, GSourceFunc function, gpointer data)
<simplesect kind="geany:skip"></simplesect> Adds a GLib main loop IDLE callback that will be removed ...
static gchar * instantsave_target_dir
GtkWidget * autosave_save_all_radio2
GtkWidget * autosave_print_msg_checkbox
static gchar * backupcopy_skip_root(gchar *filename)
GtkWidget * autosave_save_all_radio1
static gchar * backupcopy_time_fmt
GtkWidget * instantsave_ft_combo
static gint backupcopy_dir_levels
static struct @37 pref_widgets
@ NOTEBOOK_PAGE_INSTANTSAVE
@ NOTEBOOK_PAGE_BACKUPCOPY
GtkWidget * checkbox_enable_backupcopy
GtkWidget * checkbox_enable_instantsave
GtkWidget * backupcopy_spin_dir_levels
static gboolean enable_backupcopy
static gboolean save_on_focus_out_idle(gpointer p_cur_doc)
static gboolean auto_save(gpointer data)
GeanyPlugin * geany_plugin
static gint autosave_interval
static void instantsave_document_new_cb(GObject *obj, GeanyDocument *doc, gpointer user_data)
static gchar * config_file
void plugin_cleanup(void)
Called before unloading the plugin.
PluginCallback plugin_callbacks[]
static void backupcopy_document_save_cb(GObject *obj, GeanyDocument *doc, gpointer user_data)
static void target_directory_button_clicked_cb(GtkButton *button, gpointer item)
static gboolean autosave_print_msg
GtkWidget * backupcopy_entry_time
static gchar * backupcopy_backup_dir
GtkWidget * autosave_interval_spin
static gboolean enable_autosave
static gboolean autosave_save_all
static gchar * backupcopy_create_dir_parts(const gchar *filename)
GtkWidget * backupcopy_entry_dir
static guint autosave_src_id
void plugin_init(GeanyData *data)
Called after loading the plugin.
static void configure_response_cb(GtkDialog *dialog, gint response, G_GNUC_UNUSED gpointer data)
static gchar * instantsave_default_ft
static gboolean enable_autosave_losing_focus
GtkWidget * checkbox_enable_autosave_losing_focus
static void autosave_set_timeout(void)
GtkWidget * plugin_configure(GtkDialog *dialog)
Called before showing the plugin preferences dialog for multiple plugins.
static void checkbox_toggled_cb(GtkToggleButton *tb, gpointer data)
static gboolean store_target_directory(const gchar *utf8_dir, gchar **target)
static gboolean on_document_focus_out(GObject *object, GeanyEditor *editor, SCNotification *nt, gpointer data)
GtkWidget * checkbox_enable_autosave
GtkWidget * instantsave_entry_dir
static gboolean enable_instantsave
const GSList * filetypes_get_sorted_by_name(void)
Gets a list of filetype pointers sorted by name.
GeanyFiletype * filetypes_lookup_by_name(const gchar *name)
Finds a filetype pointer from its name field.
gtk_container_add(GTK_CONTAINER(dialog->vbox), check_button)
gtk_widget_show_all(dialog)
This contains pointers to global variables owned by Geany for plugins to use.
Structure for representing an open tab with all its properties.
gchar * file_name
The UTF-8 encoded file name.
GeanyFiletype * file_type
The filetype for this document, it's only a reference to one of the elements of the global filetypes ...
Editor-owned fields for each document.
struct GeanyDocument * document
The document associated with the editor.
gchar * name
Untranslated short name, such as "C", "None".
GeanyFiletypeID id
Index in filetypes.
gchar * extension
Default file extension for new files, or NULL.
Basic information for the plugin and identification.
Callback array entry type used with the plugin_callbacks symbol.
#define ngettext(String, PluralString, Number)
void ui_set_statusbar(gboolean log, const gchar *format,...)
Displays text on the statusbar.
gint utils_write_file(const gchar *filename, const gchar *text)
Writes text into a file named filename.
gint utils_get_setting_integer(GKeyFile *config, const gchar *section, const gchar *key, const gint default_value)
Wraps g_key_file_get_integer() to add a default value argument.
gboolean utils_get_setting_boolean(GKeyFile *config, const gchar *section, const gchar *key, const gboolean default_value)
Wraps g_key_file_get_boolean() to add a default value argument.
gchar * utils_get_utf8_from_locale(const gchar *locale_text)
Converts the given string (in locale encoding) into UTF-8 encoding.
gchar * utils_get_date_time(const gchar *format, time_t *time_to_use)
Retrieves a formatted date/time string from strftime().
gint utils_mkdir(const gchar *path, gboolean create_parent_dirs)
Creates a directory if it doesn't already exist.
gboolean utils_str_equal(const gchar *a, const gchar *b)
NULL-safe string comparison.
gchar * utils_get_setting_string(GKeyFile *config, const gchar *section, const gchar *key, const gchar *default_value)
Wraps g_key_file_get_string() to add a default value argument.
gchar * utils_get_locale_from_utf8(const gchar *utf8_text)
Converts the given UTF-8 encoded string into locale encoding.
#define foreach_slist(node, list)
Iterates all the nodes in list.
#define SETPTR(ptr, result)
Assigns result to ptr, then frees the old value.
#define EMPTY(ptr)
Returns TRUE if ptr is NULL or *ptr is FALSE.