summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/query-tool.c176
1 files changed, 176 insertions, 0 deletions
diff --git a/src/query-tool.c b/src/query-tool.c
new file mode 100644
index 0000000..55fd823
--- /dev/null
+++ b/src/query-tool.c
@@ -0,0 +1,176 @@
+/*
+ * A tool to query multiple dictionaries for the specified word
+ *
+ * Intended for use in IRC bots and similar silly things---words go in, one
+ * on a line, and entries come out, one dictionary at a time, finalised with
+ * an empty line. Newlines are escaped with `\n', backslashes with `\\'.
+ *
+ * So far only the `m' field is supported. Feel free to extend the program
+ * according to your needs, it's not very complicated.
+ *
+ * Copyright (c) 2013, Přemysl Janouch <p.janouch@gmail.com>
+ * All rights reserved.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+
+#include <glib.h>
+#include <gio/gio.h>
+
+#include "stardict.h"
+#include "stardict-private.h"
+#include "generator.h"
+
+static guint
+count_equal_chars (const gchar *a, const gchar *b)
+{
+ guint count = 0;
+ while (*a && *b)
+ if (*a++ == *b++)
+ count++;
+ return count;
+}
+
+static void
+do_dictionary (StardictDict *dict, const gchar *word)
+{
+ gboolean found;
+ StardictIterator *iter = stardict_dict_search (dict, word, &found);
+ if (!found)
+ goto out;
+
+ // Default Stardict ordering is ASCII case-insensitive.
+ // Try to find a better matching entry based on letter case:
+
+ gint64 best_offset = stardict_iterator_get_offset (iter);
+ guint best_score = count_equal_chars
+ (stardict_iterator_get_word (iter), word);
+
+ while (TRUE)
+ {
+ stardict_iterator_next (iter);
+ if (!stardict_iterator_is_valid (iter))
+ break;
+
+ const gchar *iter_word = stardict_iterator_get_word (iter);
+ if (g_ascii_strcasecmp (iter_word, word))
+ break;
+
+ guint score = count_equal_chars (iter_word, word);
+ if (score > best_score)
+ {
+ best_offset = stardict_iterator_get_offset (iter);
+ best_score = score;
+ }
+ }
+
+ stardict_iterator_set_offset (iter, best_offset, FALSE);
+
+ StardictEntry *entry = stardict_iterator_get_entry (iter);
+ StardictInfo *info = stardict_dict_get_info (dict);
+ const GList *list = stardict_entry_get_fields (entry);
+ for (; list; list = list->next)
+ {
+ StardictEntryField *field = list->data;
+ if (field->type == STARDICT_FIELD_MEANING)
+ {
+ const gchar *desc = field->data;
+ printf ("%s:", info->book_name);
+ for (; *desc; desc++)
+ {
+ if (*desc == '\\')
+ printf ("\\\\");
+ else if (*desc == '\n')
+ printf ("\\n");
+ else
+ putchar (*desc);
+ }
+ putchar ('\n');
+ }
+ }
+ g_object_unref (entry);
+out:
+ g_object_unref (iter);
+}
+
+int
+main (int argc, char *argv[])
+{
+G_GNUC_BEGIN_IGNORE_DEPRECATIONS
+ if (glib_check_version (2, 36, 0))
+ g_type_init ();
+G_GNUC_END_IGNORE_DEPRECATIONS
+
+ GError *error = NULL;
+ GOptionContext *ctx = g_option_context_new
+ ("DICTIONARY.ifo... - query multiple dictionaries");
+ if (!g_option_context_parse (ctx, &argc, &argv, &error))
+ {
+ g_printerr ("Error: option parsing failed: %s\n", error->message);
+ exit (EXIT_FAILURE);
+ }
+ g_option_context_free (ctx);
+
+ if (argc < 2)
+ {
+ g_printerr ("Error: no dictionaries given\n");
+ exit (EXIT_FAILURE);
+ }
+
+ guint n_dicts = argc - 1;
+ StardictDict **dicts = g_alloca (sizeof *dicts * n_dicts);
+
+ guint i;
+ for (i = 1; i <= n_dicts; i++)
+ {
+ dicts[i - 1] = stardict_dict_new (argv[i], &error);
+ if (error)
+ {
+ g_printerr ("Error: opening dictionary `%s' failed: %s\n",
+ argv[i], error->message);
+ exit (EXIT_FAILURE);
+ }
+ }
+
+ while (TRUE)
+ {
+ GString *s = g_string_new (NULL);
+
+ gint c;
+ while ((c = getchar ()) != EOF && c != '\n')
+ if (c != '\r')
+ g_string_append_c (s, c);
+
+ if (s->len)
+ for (i = 0; i < n_dicts; i++)
+ do_dictionary (dicts[i], s->str);
+
+ printf ("\n");
+ fflush (NULL);
+ g_string_free (s, TRUE);
+
+ if (c == EOF)
+ break;
+ }
+
+ for (i = 0; i < n_dicts; i++)
+ g_object_unref (dicts[i]);
+
+ return 0;
+}