about summary refs log tree commit diff stats
path: root/src/tools
diff options
context:
space:
mode:
authorJames Booth <boothj5@gmail.com>2013-02-02 21:43:59 +0000
committerJames Booth <boothj5@gmail.com>2013-02-02 21:43:59 +0000
commit740e5b422832f8d043d96f33a0d33bf1725dbbc0 (patch)
treee28525525de760b696bfd4f7dbb326334db8ee29 /src/tools
parentfc5bfb7d33dc6e1a6a53c46d414df4f9324f6ad5 (diff)
downloadprofani-tty-740e5b422832f8d043d96f33a0d33bf1725dbbc0.tar.gz
Added command and tools subdirs to source
Diffstat (limited to 'src/tools')
-rw-r--r--src/tools/autocomplete.c224
-rw-r--r--src/tools/autocomplete.h45
-rw-r--r--src/tools/history.c267
-rw-r--r--src/tools/history.h33
-rw-r--r--src/tools/tinyurl.c88
-rw-r--r--src/tools/tinyurl.h31
6 files changed, 688 insertions, 0 deletions
diff --git a/src/tools/autocomplete.c b/src/tools/autocomplete.c
new file mode 100644
index 00000000..baeeecb2
--- /dev/null
+++ b/src/tools/autocomplete.c
@@ -0,0 +1,224 @@
+/*
+ * autocomplete.c
+ *
+ * Copyright (C) 2012, 2013 James Booth <boothj5@gmail.com>
+ *
+ * This file is part of Profanity.
+ *
+ * Profanity is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Profanity 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Profanity.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include <stdlib.h>
+#include <string.h>
+
+#include "autocomplete.h"
+
+struct autocomplete_t {
+    GSList *items;
+    GSList *last_found;
+    gchar *search_str;
+};
+
+static gchar * _search_from(Autocomplete ac, GSList *curr);
+
+Autocomplete
+autocomplete_new(void)
+{
+    Autocomplete new = malloc(sizeof(struct autocomplete_t));
+    new->items = NULL;
+    new->last_found = NULL;
+    new->search_str = NULL;
+
+    return new;
+}
+
+void
+autocomplete_clear(Autocomplete ac)
+{
+    g_slist_free_full(ac->items, free);
+    ac->items = NULL;
+
+    autocomplete_reset(ac);
+}
+
+void
+autocomplete_reset(Autocomplete ac)
+{
+    ac->last_found = NULL;
+    if (ac->search_str != NULL) {
+        free(ac->search_str);
+        ac->search_str = NULL;
+    }
+}
+
+void
+autocomplete_free(Autocomplete ac)
+{
+    autocomplete_clear(ac);
+    g_free(ac);
+    ac = NULL;
+}
+
+gboolean
+autocomplete_add(Autocomplete ac, void *item)
+{
+    if (ac->items == NULL) {
+        ac->items = g_slist_append(ac->items, item);
+        return TRUE;
+    } else {
+        GSList *curr = ac->items;
+
+        while(curr) {
+
+            // insert
+            if (g_strcmp0(curr->data, item) > 0) {
+                ac->items = g_slist_insert_before(ac->items,
+                    curr, item);
+                return TRUE;
+
+            // update
+            } else if (g_strcmp0(curr->data, item) == 0) {
+                // only update if data different
+                if (strcmp(curr->data, item) != 0) {
+                    free(curr->data);
+                    curr->data = item;
+                    return TRUE;
+                } else {
+                    return FALSE;
+                }
+            }
+
+            curr = g_slist_next(curr);
+        }
+
+        // hit end, append
+        ac->items = g_slist_append(ac->items, item);
+
+        return TRUE;
+    }
+}
+
+gboolean
+autocomplete_remove(Autocomplete ac, const char * const item)
+{
+    // reset last found if it points to the item to be removed
+    if (ac->last_found != NULL)
+        if (g_strcmp0(ac->last_found->data, item) == 0)
+            ac->last_found = NULL;
+
+    if (!ac->items) {
+        return FALSE;
+    } else {
+        GSList *curr = ac->items;
+
+        while(curr) {
+            if (g_strcmp0(curr->data, item) == 0) {
+                void *current_item = curr->data;
+                ac->items = g_slist_remove(ac->items, curr->data);
+                free(current_item);
+
+                return TRUE;
+            }
+
+            curr = g_slist_next(curr);
+        }
+
+        return FALSE;
+    }
+}
+
+GSList *
+autocomplete_get_list(Autocomplete ac)
+{
+    GSList *copy = NULL;
+    GSList *curr = ac->items;
+
+    while(curr) {
+        copy = g_slist_append(copy, strdup(curr->data));
+        curr = g_slist_next(curr);
+    }
+
+    return copy;
+}
+
+gchar *
+autocomplete_complete(Autocomplete ac, gchar *search_str)
+{
+    gchar *found = NULL;
+
+    // no items to search
+    if (!ac->items)
+        return NULL;
+
+    // first search attempt
+    if (ac->last_found == NULL) {
+        ac->search_str =
+            (gchar *) malloc((strlen(search_str) + 1) * sizeof(gchar));
+        strcpy(ac->search_str, search_str);
+
+        found = _search_from(ac, ac->items);
+        return found;
+
+    // subsequent search attempt
+    } else {
+        // search from here+1 tp end
+        found = _search_from(ac, g_slist_next(ac->last_found));
+        if (found != NULL)
+            return found;
+
+        // search from beginning
+        found = _search_from(ac, ac->items);
+        if (found != NULL)
+            return found;
+
+        // we found nothing, reset search
+        autocomplete_reset(ac);
+        return NULL;
+    }
+}
+
+static gchar *
+_search_from(Autocomplete ac, GSList *curr)
+{
+    while(curr) {
+
+        // match found
+        if (strncmp(curr->data, ac->search_str, strlen(ac->search_str)) == 0) {
+
+            // set pointer to last found
+            ac->last_found = curr;
+
+            // if contains space, quote before returning
+            if (g_strrstr(curr->data, " ")) {
+                GString *quoted = g_string_new("\"");
+                g_string_append(quoted, curr->data);
+                g_string_append(quoted, "\"");
+
+                gchar *result = quoted->str;
+                g_string_free(quoted, FALSE);
+
+                return result;
+
+            // otherwise just return the string
+            } else {
+                return strdup(curr->data);
+            }
+        }
+
+        curr = g_slist_next(curr);
+    }
+
+    return NULL;
+}
diff --git a/src/tools/autocomplete.h b/src/tools/autocomplete.h
new file mode 100644
index 00000000..03f4a013
--- /dev/null
+++ b/src/tools/autocomplete.h
@@ -0,0 +1,45 @@
+/*
+ * autocomplete.h
+ *
+ * Copyright (C) 2012, 2013 James Booth <boothj5@gmail.com>
+ *
+ * This file is part of Profanity.
+ *
+ * Profanity is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Profanity 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Profanity.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef AUTOCOMPLETE_H
+#define AUTOCOMPLETE_H
+
+#include <glib.h>
+
+typedef struct autocomplete_t *Autocomplete;
+typedef const char * (*PStrFunc)(const void *obj);
+typedef void * (*PCopyFunc)(const void *obj);
+typedef int (*PEqualFunc)(const void *o1, const void *o2);
+typedef int (*PEqualDeepFunc)(const void *o1, const void *o2);
+
+Autocomplete autocomplete_new(void);
+Autocomplete obj_autocomplete_new(PStrFunc str_func, PCopyFunc copy_func,
+    PEqualDeepFunc equal_deep_func, GDestroyNotify free_func);
+void autocomplete_clear(Autocomplete ac);
+void autocomplete_reset(Autocomplete ac);
+void autocomplete_free(Autocomplete ac);
+gboolean autocomplete_add(Autocomplete ac, void *item);
+gboolean autocomplete_remove(Autocomplete ac, const char * const item);
+GSList * autocomplete_get_list(Autocomplete ac);
+gchar * autocomplete_complete(Autocomplete ac, gchar *search_str);
+
+#endif
diff --git a/src/tools/history.c b/src/tools/history.c
new file mode 100644
index 00000000..5ac41969
--- /dev/null
+++ b/src/tools/history.c
@@ -0,0 +1,267 @@
+/*
+ * history.c
+ *
+ * Copyright (C) 2012, 2013 James Booth <boothj5@gmail.com>
+ *
+ * This file is part of Profanity.
+ *
+ * Profanity is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Profanity 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Profanity.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include <stdlib.h>
+#include <string.h>
+
+#include <glib.h>
+
+#include "history.h"
+
+struct history_session_t {
+    GList *items;
+    GList *sess_curr;
+    GList *sess_new;
+    GList *orig_curr;
+};
+
+struct history_t {
+    GList *items;
+    guint max_size;
+    struct history_session_t session;
+};
+
+static void _replace_history_with_session(History history);
+static gboolean _adding_new(History history);
+static void _reset_session(History history);
+static gboolean _has_session(History history);
+static void _remove_first(History history);
+static void _update_current_session_item(History history, char *item);
+static void _add_to_history(History history, char *item);
+static void _remove_last_session_item(History history);
+static void _replace_current_with_original(History history);
+static void _create_session(History history);
+static void _session_previous(History history);
+static void _session_next(History history);
+
+History
+history_new(unsigned int size)
+{
+    History new_history = malloc(sizeof(struct history_t));
+    new_history->items = NULL;
+    new_history->max_size = size;
+
+    _reset_session(new_history);
+
+    return new_history;
+}
+
+void
+history_append(History history, char *item)
+{
+    char *copied = "";
+    if (item != NULL) {
+        copied = strdup(item);
+    }
+
+    if (history->items == NULL) {
+        _add_to_history(history, copied);
+        return;
+    }
+
+    if (!_has_session(history)) {
+        if (g_list_length(history->items) == history->max_size) {
+            _remove_first(history);
+        }
+
+        _add_to_history(history, copied);
+
+    } else {
+        _update_current_session_item(history, copied);
+
+        if (_adding_new(history)) {
+            if (strcmp(history->session.sess_curr->data, "") == 0) {
+                _remove_last_session_item(history);
+            }
+
+            _replace_history_with_session(history);
+
+        } else {
+            _remove_last_session_item(history);
+
+            char *new = strdup(history->session.sess_curr->data);
+            history->session.items = g_list_append(history->session.items, new);
+
+            _replace_current_with_original(history);
+            _replace_history_with_session(history);
+        }
+    }
+}
+
+char *
+history_previous(History history, char *item)
+{
+    // no history
+    if (history->items == NULL) {
+        return NULL;
+    }
+
+    char *copied = "";
+    if (item != NULL) {
+        copied = strdup(item);
+    }
+
+    if (!_has_session(history)) {
+        _create_session(history);
+
+        // add the new item
+        history->session.items = g_list_append(history->session.items, copied);
+        history->session.sess_new = g_list_last(history->session.items);
+
+        char *result = strdup(history->session.sess_curr->data);
+        return result;
+    } else {
+        _update_current_session_item(history, copied);
+        _session_previous(history);
+    }
+
+    char *result = strdup(history->session.sess_curr->data);
+    return result;
+}
+
+char *
+history_next(History history, char *item)
+{
+    // no history, or no session, return NULL
+    if ((history->items == NULL) || (history->session.items == NULL)) {
+        return NULL;
+    }
+
+    char *copied = "";
+    if (item != NULL) {
+        copied = strdup(item);
+    }
+
+    _update_current_session_item(history, copied);
+    _session_next(history);
+
+    char *result = strdup(history->session.sess_curr->data);
+    return result;
+}
+
+static void
+_replace_history_with_session(History history)
+{
+    g_list_free(history->items);
+    history->items = g_list_copy(history->session.items);
+
+    if (g_list_length(history->items) > history->max_size) {
+        _remove_first(history);
+    }
+
+    _reset_session(history);
+}
+
+static gboolean
+_adding_new(History history)
+{
+    return (history->session.sess_curr ==
+        g_list_last(history->session.items));
+}
+
+static void
+_reset_session(History history)
+{
+    history->session.items = NULL;
+    history->session.sess_curr = NULL;
+    history->session.sess_new = NULL;
+    history->session.orig_curr = NULL;
+}
+
+static gboolean
+_has_session(History history)
+{
+    return (history->session.items != NULL);
+}
+
+static void
+_remove_first(History history)
+{
+    GList *first = g_list_first(history->items);
+    char *first_item = first->data;
+    history->items = g_list_remove(history->items, first_item);
+}
+
+static void
+_update_current_session_item(History history, char *item)
+{
+    history->session.sess_curr->data = item;
+}
+
+static void
+_add_to_history(History history, char *item)
+{
+    history->items = g_list_append(history->items, item);
+}
+
+static void
+_remove_last_session_item(History history)
+{
+    history->session.items = g_list_reverse(history->session.items);
+    GList *first = g_list_first(history->session.items);
+    history->session.items =
+        g_list_remove(history->session.items, first->data);
+    history->session.items = g_list_reverse(history->session.items);
+}
+
+static void
+_replace_current_with_original(History history)
+{
+    history->session.sess_curr->data = strdup(history->session.orig_curr->data);
+}
+
+static void
+_create_session(History history)
+{
+    history->session.items = g_list_copy(history->items);
+    history->session.sess_curr = g_list_last(history->session.items);
+    history->session.orig_curr = g_list_last(history->items);
+}
+
+static void
+_session_previous(History history)
+{
+    history->session.sess_curr =
+        g_list_previous(history->session.sess_curr);
+    if (history->session.orig_curr == NULL)
+        history->session.orig_curr = g_list_last(history->items);
+    else
+        history->session.orig_curr =
+            g_list_previous(history->session.orig_curr);
+
+    if (history->session.sess_curr == NULL) {
+        history->session.sess_curr = g_list_first(history->session.items);
+        history->session.orig_curr = g_list_first(history->items);
+    }
+}
+
+static void
+_session_next(History history)
+{
+    history->session.sess_curr = g_list_next(history->session.sess_curr);
+    history->session.orig_curr = g_list_next(history->session.orig_curr);
+
+    if (history->session.sess_curr == NULL) {
+        history->session.sess_curr = g_list_last(history->session.items);
+        history->session.orig_curr = NULL;
+    }
+}
diff --git a/src/tools/history.h b/src/tools/history.h
new file mode 100644
index 00000000..4258f7a7
--- /dev/null
+++ b/src/tools/history.h
@@ -0,0 +1,33 @@
+/*
+ * history.h
+ *
+ * Copyright (C) 2012, 2013 James Booth <boothj5@gmail.com>
+ *
+ * This file is part of Profanity.
+ *
+ * Profanity is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Profanity 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Profanity.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef HISTORY_H
+#define HISTORY_H
+
+typedef struct history_t  *History;
+
+History history_new(unsigned int size);
+char * history_previous(History history, char *item);
+char * history_next(History history, char *item);
+void history_append(History history, char *item);
+
+#endif
diff --git a/src/tools/tinyurl.c b/src/tools/tinyurl.c
new file mode 100644
index 00000000..87fafc47
--- /dev/null
+++ b/src/tools/tinyurl.c
@@ -0,0 +1,88 @@
+/*
+ * tinyurl.c
+ *
+ * Copyright (C) 2012, 2013 James Booth <boothj5@gmail.com>
+ *
+ * This file is part of Profanity.
+ *
+ * Profanity is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Profanity 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Profanity.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include <stdlib.h>
+#include <string.h>
+
+#include <curl/curl.h>
+#include <curl/easy.h>
+#include <glib.h>
+
+struct curl_data_t
+{
+    char *buffer;
+    size_t size;
+};
+
+static size_t _data_callback(void *ptr, size_t size, size_t nmemb, void *data);
+
+gboolean
+tinyurl_valid(char *url)
+{
+    return (g_str_has_prefix(url, "http://") ||
+        g_str_has_prefix(url, "https://"));
+}
+
+char *
+tinyurl_get(char *url)
+{
+    GString *full_url = g_string_new("http://tinyurl.com/api-create.php?url=");
+    g_string_append(full_url, url);
+
+    CURL *handle = curl_easy_init();
+    struct curl_data_t output;
+    output.buffer = NULL;
+    output.size = 0;
+
+    curl_easy_setopt(handle, CURLOPT_URL, full_url->str);
+    curl_easy_setopt(handle, CURLOPT_WRITEFUNCTION, _data_callback);
+    curl_easy_setopt(handle, CURLOPT_WRITEDATA, (void *)&output);
+
+    curl_easy_perform(handle);
+    curl_easy_cleanup(handle);
+
+    g_string_free(full_url, TRUE);
+
+    if (output.buffer != NULL) {
+        output.buffer[output.size++] = '\0';
+        return output.buffer;
+    } else {
+        return NULL;
+    }
+}
+
+static size_t
+_data_callback(void *ptr, size_t size, size_t nmemb, void *data)
+{
+    size_t realsize = size * nmemb;
+    struct curl_data_t *mem = (struct curl_data_t *) data;
+    mem->buffer = realloc(mem->buffer, mem->size + realsize + 1);
+
+    if ( mem->buffer )
+    {
+        memcpy( &( mem->buffer[ mem->size ] ), ptr, realsize );
+        mem->size += realsize;
+        mem->buffer[ mem->size ] = 0;
+    }
+
+    return realsize;
+}
diff --git a/src/tools/tinyurl.h b/src/tools/tinyurl.h
new file mode 100644
index 00000000..58070839
--- /dev/null
+++ b/src/tools/tinyurl.h
@@ -0,0 +1,31 @@
+/*
+ * tinyurl.h
+ *
+ * Copyright (C) 2012, 2013 James Booth <boothj5@gmail.com>
+ *
+ * This file is part of Profanity.
+ *
+ * Profanity is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Profanity 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Profanity.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef TINYURL_H
+#define TINYURL_H
+
+#include <glib.h>
+
+gboolean tinyurl_valid(char *url);
+char * tinyurl_get(char *url);
+
+#endif