Main Page | Class List | Directories | File List | Class Members | File Members

gcompletion.c

Go to the documentation of this file.
00001 /* GLIB - Library of useful routines for C programming
00002  * Copyright (C) 1995-1997  Peter Mattis, Spencer Kimball and Josh MacDonald
00003  *
00004  * This library is free software; you can redistribute it and/or
00005  * modify it under the terms of the GNU Library General Public
00006  * License as published by the Free Software Foundation; either
00007  * version 2 of the License, or (at your option) any later version.
00008  *
00009  * This library is distributed in the hope that it will be useful,
00010  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00011  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00012  * Library General Public License for more details.
00013  *
00014  * You should have received a copy of the GNU Library General Public
00015  * License along with this library; if not, write to the
00016  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
00017  * Boston, MA 02111-1307, USA.
00018  */
00019 
00020 /*
00021  * Modified by the GLib Team and others 1997-1999.  See the AUTHORS
00022  * file for a list of people on the GLib Team.  See the ChangeLog
00023  * files for a list of changes.  These files are distributed with
00024  * GLib at ftp://ftp.gtk.org/pub/gtk/. 
00025  */
00026 
00027 /* 
00028  * MT safe
00029  */
00030 
00031 #include "glib.h"
00032 #include <string.h>
00033 
00034 static void completion_check_cache (GCompletion* cmp,
00035                                     gchar**      new_prefix);
00036 
00037 GCompletion* 
00038 g_completion_new (GCompletionFunc func)
00039 {
00040   GCompletion* gcomp;
00041   
00042   gcomp = g_new (GCompletion, 1);
00043   gcomp->items = NULL;
00044   gcomp->cache = NULL;
00045   gcomp->prefix = NULL;
00046   gcomp->func = func;
00047 
00048   return gcomp;
00049 }
00050 
00051 void 
00052 g_completion_add_items (GCompletion* cmp,
00053                         GList*       items)
00054 {
00055   GList* it;
00056   
00057   g_return_if_fail (cmp != NULL);
00058   g_return_if_fail (items != NULL);
00059   
00060   /* optimize adding to cache? */
00061   if (cmp->cache)
00062     {
00063       g_list_free (cmp->cache);
00064       cmp->cache = NULL;
00065     }
00066 
00067   if (cmp->prefix)
00068     {
00069       g_free (cmp->prefix);
00070       cmp->prefix = NULL;
00071     }
00072   
00073   it = items;
00074   while (it)
00075     {
00076       cmp->items = g_list_prepend (cmp->items, it->data);
00077       it = it->next;
00078     }
00079 }
00080 
00081 void 
00082 g_completion_remove_items (GCompletion* cmp,
00083                            GList*       items)
00084 {
00085   GList* it;
00086   
00087   g_return_if_fail (cmp != NULL);
00088   g_return_if_fail (items != NULL);
00089   
00090   it = items;
00091   while (cmp->items && it)
00092     {
00093       cmp->items = g_list_remove (cmp->items, it->data);
00094       it = it->next;
00095     }
00096 
00097   it = items;
00098   while (cmp->cache && it)
00099     {
00100       cmp->cache = g_list_remove(cmp->cache, it->data);
00101       it = it->next;
00102     }
00103 }
00104 
00105 void 
00106 g_completion_clear_items (GCompletion* cmp)
00107 {
00108   g_return_if_fail (cmp != NULL);
00109   
00110   g_list_free (cmp->items);
00111   cmp->items = NULL;
00112   g_list_free (cmp->cache);
00113   cmp->cache = NULL;
00114   g_free (cmp->prefix);
00115   cmp->prefix = NULL;
00116 }
00117 
00118 static void   
00119 completion_check_cache (GCompletion* cmp,
00120                         gchar**      new_prefix)
00121 {
00122   register GList* list;
00123   register gint len;
00124   register gint i;
00125   register gint plen;
00126   gchar* postfix;
00127   gchar* s;
00128   
00129   if (!new_prefix)
00130     return;
00131   if (!cmp->cache)
00132     {
00133       *new_prefix = NULL;
00134       return;
00135     }
00136   
00137   len = strlen(cmp->prefix);
00138   list = cmp->cache;
00139   s = cmp->func ? cmp->func (list->data) : (gchar*) list->data;
00140   postfix = s + len;
00141   plen = strlen (postfix);
00142   list = list->next;
00143   
00144   while (list && plen)
00145     {
00146       s = cmp->func ? cmp->func (list->data) : (gchar*) list->data;
00147       s += len;
00148       for (i = 0; i < plen; ++i)
00149         {
00150           if (postfix[i] != s[i])
00151             break;
00152         }
00153       plen = i;
00154       list = list->next;
00155     }
00156   
00157   *new_prefix = g_new0 (gchar, len + plen + 1);
00158   strncpy (*new_prefix, cmp->prefix, len);
00159   strncpy (*new_prefix + len, postfix, plen);
00160 }
00161 
00162 GList* 
00163 g_completion_complete (GCompletion* cmp,
00164                        gchar*       prefix,
00165                        gchar**      new_prefix)
00166 {
00167   gint plen, len;
00168   gint done = 0;
00169   GList* list;
00170   
00171   g_return_val_if_fail (cmp != NULL, NULL);
00172   g_return_val_if_fail (prefix != NULL, NULL);
00173   
00174   len = strlen (prefix);
00175   if (cmp->prefix && cmp->cache)
00176     {
00177       plen = strlen (cmp->prefix);
00178       if (plen <= len && !strncmp (prefix, cmp->prefix, plen))
00179         { 
00180           /* use the cache */
00181           list = cmp->cache;
00182           while (list)
00183             {
00184               if (strncmp (prefix,
00185                            cmp->func ? cmp->func (list->data) : (gchar*) list->data,
00186                            len))
00187                 {
00188                   list = g_list_remove_link (cmp->cache, list);
00189                   if (list != cmp->cache)
00190                     cmp->cache = list;
00191                 }
00192               else
00193                 list = list->next;
00194             }
00195           done = 1;
00196         }
00197     }
00198   
00199   if (!done)
00200     {
00201       /* normal code */
00202       g_list_free (cmp->cache);
00203       cmp->cache = NULL;
00204       list = cmp->items;
00205       while (*prefix && list)
00206         {
00207           if (!strncmp (prefix,
00208                         cmp->func ? cmp->func (list->data) : (gchar*) list->data,
00209                         len))
00210             cmp->cache = g_list_prepend (cmp->cache, list->data);
00211           list = list->next;
00212         }
00213     }
00214   if (cmp->prefix)
00215     {
00216       g_free (cmp->prefix);
00217       cmp->prefix = NULL;
00218     }
00219   if (cmp->cache)
00220     cmp->prefix = g_strdup (prefix);
00221   completion_check_cache (cmp, new_prefix);
00222   
00223   return *prefix ? cmp->cache : cmp->items;
00224 }
00225 
00226 void 
00227 g_completion_free (GCompletion* cmp)
00228 {
00229   g_return_if_fail (cmp != NULL);
00230   
00231   g_completion_clear_items (cmp);
00232   g_free (cmp);
00233 }
00234 
00235 #ifdef TEST_COMPLETION
00236 #include <stdio.h>
00237 int
00238 main (int   argc,
00239       char* argv[])
00240 {
00241   FILE *file;
00242   gchar buf[1024];
00243   GList *list;
00244   GList *result;
00245   GList *tmp;
00246   GCompletion *cmp;
00247   gint i;
00248   gchar *longp = NULL;
00249   
00250   if (argc < 3)
00251     {
00252       g_warning ("Usage: %s filename prefix1 [prefix2 ...]\n", argv[0]);
00253       return 1;
00254     }
00255   
00256   file = fopen (argv[1], "r");
00257   if (!file)
00258     {
00259       g_warning ("Cannot open %s\n", argv[1]);
00260       return 1;
00261     }
00262   
00263   cmp = g_completion_new (NULL);
00264   list = g_list_alloc ();
00265   while (fgets (buf, 1024, file))
00266     {
00267       list->data = g_strdup (buf);
00268       g_completion_add_items (cmp, list);
00269     }
00270   fclose (file);
00271   
00272   for (i = 2; i < argc; ++i)
00273     {
00274       printf ("COMPLETING: %s\n", argv[i]);
00275       result = g_completion_complete (cmp, argv[i], &longp);
00276       g_list_foreach (result, (GFunc) printf, NULL);
00277       printf ("LONG MATCH: %s\n", longp);
00278       g_free (longp);
00279       longp = NULL;
00280     }
00281   
00282   g_list_foreach (cmp->items, (GFunc) g_free, NULL);
00283   g_completion_free (cmp);
00284   g_list_free (list);
00285   
00286   return 0;
00287 }
00288 #endif

© sourcejam.com 2005-2008