find.c
changeset 21 01fe372188ac
parent 17 d95d9e7a2b81
child 22 0b923f95df16
--- a/find.c	Sat Sep 01 13:04:10 2007 +0200
+++ b/find.c	Sat Sep 01 21:49:41 2007 +0200
@@ -55,6 +55,9 @@
         exit(-1);
     }
 
+    d->trim_first_line = 0;
+    d->trim_last_newlines = 0;
+
     free(filename);
 }
 
@@ -65,20 +68,62 @@
     fclose(d->defs);
 }
 
+static int trim_first_line(char *def, int len)
+{
+    int new_line_pos;
+    int i,j;
+    for(i=0; i < len; ++i)
+    {
+        if (def[i] == '\n')
+        {
+            /* Break */
+            memmove(def, def + i + 1 /* \n */,
+                    len - i - 1);
+            def[len-i-1] = 0;
+            return len-i-1/*\n*/+1/*\0*/;
+        }
+    }
+    return len;
+}
+
+static int trim_last_newlines(char *def, int len)
+{
+    int new_line_pos;
+    int i,j;
+    for(i=len-1; i >= 0; --i)
+    {
+        if (def[i] != '\n' && def[i] != '\r')
+        {
+            def[i+1] = '\0';
+            return i + 1;
+        }
+    }
+    return len;
+}
+
 static void fill_def(struct Dict *d, int offset, int length, char * def)
 {
     fseek(d->defs, offset, SEEK_SET);
     fread(def, 1, length, d->defs);
+    def[length] = 0;
+    if (d->trim_first_line)
+    {
+        length = trim_first_line(def, length + 1/*\0*/) - 1 /*\0*/;
+    }
+    if (d->trim_last_newlines)
+    {
+        length = trim_last_newlines(def, length+1) - 1; /* math as above*/
+    }
 }
 
-static int pointer_at_end(struct Dict *d, unsigned char *ptr)
+static int pointer_at_end(struct Dict *d, const unsigned char *ptr)
 {
     if (ptr >= (d->index + d->indexsize))
         return 1;
     return 0;
 }
 
-static char * skip_until_newline(struct Dict *d, char *from)
+static const char * skip_until_newline(struct Dict *d, const char *from)
 {
     if (pointer_at_end(d, from))
         return 0;
@@ -118,17 +163,28 @@
     return -1;
 }
 
-static char * bin_search(struct Dict *d, const char *word)
+static const char * search_next(struct Dict *d, const char *word, const char *from)
+{
+    const char *ret;
+    ret = skip_until_newline(d, from);
+    if (compare(from, word) == 0)
+        return ret;
+    return 0;
+}
+
+static const char * bin_search(struct Dict *d, const char *word)
 {
     int step, pivot;
+    const char *ret;
+    const char *test;
+    int comparision;
+    int found_once = 0;
 
     pivot = d->indexsize / 2;
     step = d->indexsize / 2;
 
     do
     {
-        char *test;
-        int comparision;
         test = d->index + pivot;
         test = skip_until_newline(d, test);
         if (test == 0)
@@ -136,11 +192,13 @@
         test += 1; /* skip exactly the new line */
 
         comparision = compare(word, test);
-        if (comparision == 0)
+        if (comparision <= 0)
         {
-            return test + strlen(word) + 1; /* skip word and \n */
-        } else if (comparision < 0)
-        {
+            if (comparision == 0)
+                found_once = 1;
+            /* If == 0, we don't know that it's the FIRST
+             * match possible in the dictionary.
+             * We want all possible matches. */
             step = step / 2;
             pivot = pivot - step;
         } else if (comparision > 0)
@@ -149,13 +207,24 @@
             pivot = pivot + step;
         }
     } while(step > 0);
-    return 0;
+
+    if (!found_once)
+        return 0;
+
+    if (comparision == 0) /* last comparision */
+    {
+        ret = skip_until_newline(d, d->index + pivot) + 1;
+    } else
+    {
+        ret = skip_until_newline(d, test) + 1;
+    }
+    return ret;
 }
 
-static int my_get_int(char **pos)
+static int my_get_int(const char **pos)
 {
     int i;
-    char *start;
+    const char *start;
     int val;
 
     start = *pos;
@@ -169,16 +238,26 @@
 void find_def(struct Dict *d, const char *word, char * def)
 {
     int offset, len;
-    char *pos;
+    const char *found, *pos;
+    int wordlen;
 
-    pos = bin_search(d, word); /* pos points to the offset already. */
-    if (pos == 0)
+    def[0] = 0;
+    /* we will get a pointer to the offset for the ints*/
+    found = bin_search(d, word);
+    if (found == 0)
+        return;
+    wordlen = strlen(word);
+    do
     {
-        def[0] = 0;
-        /*fprintf(stderr, "Cannot find %s\n", word);*/
-        return;
-    }
-    offset = my_get_int(&pos); /* increments pos */
-    len = my_get_int(&pos); /* increments pos */
-    fill_def(d, offset, len, def);
+        found += wordlen+1;
+        pos = found;
+        offset = my_get_int(&pos); /* increments pos */
+        len = my_get_int(&pos); /* increments pos */
+        fill_def(d, offset, len, def);
+        found = search_next(d, word, found);
+        if (!found)
+            break;
+        strcat(def, ", ");
+        def += strlen(def);
+    } while(1);
 }