]> git.deb.at Git - pkg/abook.git/blobdiff - misc.c
Upload 0.6.1-2 to unstable
[pkg/abook.git] / misc.c
diff --git a/misc.c b/misc.c
index 24123a63fa0e7a4ab54bbf00350a8ed92b538a47..0f96b7a878316948c11d98a70259865d5e70ac55 100644 (file)
--- a/misc.c
+++ b/misc.c
@@ -1,15 +1,14 @@
 
 /*
- * $Id: misc.c,v 1.14 2004/02/18 19:40:57 jheinonen Exp $
+ * $Id$
  *
  * by JH <jheinonen@users.sourceforge.net>
  *
  * Copyright (C) Jaakko Heinonen
+ * getaline() Copyright (C) Lars Wirzenius
+ * sprintf and snprintf copyright is owned by various people
  */
 
-#define ABOOK_SRC      1
-/*#undef ABOOK_SRC*/
-
 #include <stdio.h>
 #include <string.h>
 #include <stdlib.h>
 #ifdef HAVE_CONFIG_H
 #      include "config.h"
 #endif
-#ifdef HANDLE_MULTIBYTE
-#      include <mbswidth.h>
-#endif
+#include <mbswidth.h>
+#include "abook.h"
 #include "misc.h"
-#ifdef ABOOK_SRC
-#      include "abook.h"
-#endif
+#include "xmalloc.h"
 
 #ifndef DEBUG
 #      define NDEBUG   1
@@ -55,12 +51,12 @@ strtrim(char *s)
 
        assert(s != NULL);
 
-       for(t = s; ISSPACE(*t); t++);
+       for(t = s; isspace(*t); t++);
 
        memmove(s, t, strlen(t)+1);
 
        for (tt = t = s; *t != '\0'; t++)
-               if(!ISSPACE(*t))
+               if(!isspace(*t))
                        tt = t+1;
 
        *tt = '\0';
@@ -68,6 +64,41 @@ strtrim(char *s)
        return s;
 }
 
+int
+is_number(char *p)
+{
+       if(!p || !*p || (*p == '-' && !*++p))
+               return 0;
+
+       for(; *p; p++)
+               if(!isdigit(*p))
+                       return 0;
+
+       return 1;
+}
+
+#ifndef HAVE_STRCASESTR
+char *
+strcasestr(const char *haystack, const char *needle)
+{
+       int i;
+       int k;
+
+       assert(haystack != NULL);
+       assert(needle != NULL);
+
+       for(i=0; i<strlen(haystack)-strlen(needle)+1; i++) {
+               for(k=0; k<strlen(needle); k++, i++) {
+                       if (tolower(haystack[i]) != tolower(needle[k]))
+                               break;
+                       else if ((k+1) == strlen(needle))
+                               return &haystack[i];
+               }
+       }
+
+       return NULL;
+}
+#endif
 
 #ifdef HAVE_CONFIG_H
 #      include "config.h"
@@ -85,17 +116,12 @@ strtrim(char *s)
 #endif
 
 char *
-mkstr (const char *format, ... )
+strdup_printf (const char *format, ... )
 {
        MY_VA_LOCAL_DECL;
        size_t size = 100;
-       char *buffer =
-#ifdef ABOOK_SRC
-               (char *) abook_malloc (size);
-#else
-               (char *) xmalloc (size);
-#endif
-       
+       char *buffer = xmalloc (size);
+
        assert(format != NULL);
 
        for(;;) {
@@ -112,13 +138,8 @@ mkstr (const char *format, ... )
                        size = n + 1;
                else
                        size *= 2;
-               
-               buffer =
-#ifdef ABOOK_SRC
-                       (char *) abook_realloc (buffer, size);
-#else
-                       (char *) xrealloc (buffer, size);
-#endif
+
+               buffer = xrealloc(buffer, size);
        }
 }
 
@@ -140,15 +161,8 @@ strconcat (const char *str, ...)
                MY_VA_SHIFT(s, char*);
        }
        MY_VA_END;
-       
-       concat = (char *)
-#ifdef ABOOK_SRC
-       abook_malloc(l);
-#else
-       xmalloc(l);
-#endif
-       if(concat == NULL)
-               return NULL;
+
+       concat =  xmalloc(l);
 
        strcpy (concat, str);
        MY_VA_START(str);
@@ -193,23 +207,45 @@ my_getcwd()
        char *dir = NULL;
        size_t size = 100;
 
-       if( (dir = (char *)malloc(size)) == NULL)
+       if( (dir = xmalloc(size)) == NULL)
                return NULL;
 
        *dir = 0;
-       
+
        while( getcwd(dir, size) == NULL && errno == ERANGE )
-               if( (dir = (char *)realloc(dir, size *=2)) == NULL)
+               if( (dir = xrealloc(dir, size *=2)) == NULL)
                        return NULL;
 
        return dir;
 }
 
-#define INITIAL_SIZE   128
-#ifndef ABOOK_SRC
-#      define abook_malloc(X) xmalloc(X)
-#      define abook_realloc(X, XX) xrealloc(X, XX)
-#endif
+/*
+ * getaline()
+ *
+ * Copyright (c) 1994 Lars Wirzenius
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer
+ *    in this position and unchanged.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
 
 char *
 getaline(FILE *f)
@@ -233,7 +269,7 @@ getaline(FILE *f)
 
        len = 0;
        size = thres;
-       buf = (char *)abook_malloc(size);
+       buf = xmalloc(size);
 
        while (fgets(buf+len, size-len, f) != NULL) {
                len += strlen(buf+len);
@@ -241,7 +277,7 @@ getaline(FILE *f)
                        break;          /* the whole line has been read */
 
                for (inc = size, p = NULL; inc > mininc; inc /= 2)
-                       if ((p = (char *)abook_realloc(buf, size + inc)) !=
+                       if ((p = xrealloc_inc(buf, size, inc)) !=
                                        NULL)
                                break;
 
@@ -250,7 +286,7 @@ getaline(FILE *f)
        }
 
        if (len == 0) {
-               free(buf);
+               xfree(buf);
                return NULL;    /* nothing read (eof or error) */
        }
 
@@ -258,7 +294,7 @@ getaline(FILE *f)
                buf[--len] = '\0';
 
        if (size - len > mucho) { /* a plenitude of unused memory? */
-               p = (char *)abook_realloc(buf, len+1);
+               p = xrealloc_inc(buf, len, 1);
                if (p != NULL) {
                        buf = p;
                        size = len+1;
@@ -272,11 +308,7 @@ int
 strwidth(const char *s)
 {
        assert(s);
-#ifdef HANDLE_MULTIBYTE
-       return (int)mbswidth(s, 0);
-#else
-       return strlen(s);
-#endif
+       return mbswidth(s, 0);
 }
 
 int
@@ -320,9 +352,9 @@ bytes2width(const char *s, int width)
  *    original.  Also, there is now a builtin-test, just compile with:
  *           gcc -DTEST_SNPRINTF -o snprintf snprintf.c -lm
  *    and run snprintf for results.
- * 
+ *
  *  Thomas Roessler <roessler@guug.de> 01/27/98 for mutt 0.89i
- *    The PGP code was using unsigned hexadecimal formats. 
+ *    The PGP code was using unsigned hexadecimal formats.
  *    Unfortunately, unsigned formats simply didn't work.
  *
  *  Michael Elkins <me@cs.hmc.edu> 03/05/98 for mutt 0.90.8
@@ -371,7 +403,7 @@ bytes2width(const char *s, int width)
 /*int snprintf (char *str, size_t count, const char *fmt, ...);*/
 /*int vsnprintf (char *str, size_t count, const char *fmt, va_list arg);*/
 
-static void dopr (char *buffer, size_t maxlen, const char *format, 
+static void dopr (char *buffer, size_t maxlen, const char *format,
                   va_list args);
 static void fmtstr (char *buffer, size_t *currlen, size_t maxlen,
                    char *value, int flags, int min, int max);
@@ -424,7 +456,7 @@ static void dopr (char *buffer, size_t maxlen, const char *format, va_list args)
   int flags;
   int cflags;
   size_t currlen;
-  
+
   state = DP_S_DEFAULT;
   currlen = flags = cflags = min = 0;
   max = -1;
@@ -432,20 +464,20 @@ static void dopr (char *buffer, size_t maxlen, const char *format, va_list args)
 
   while (state != DP_S_DONE)
   {
-    if ((ch == '\0') || (currlen >= maxlen)) 
+    if ((ch == '\0') || (currlen >= maxlen))
       state = DP_S_DONE;
 
-    switch(state) 
+    switch(state)
     {
     case DP_S_DEFAULT:
-      if (ch == '%') 
+      if (ch == '%')
        state = DP_S_FLAGS;
-      else 
+      else
        dopr_outch (buffer, &currlen, maxlen, ch);
       ch = *format++;
       break;
     case DP_S_FLAGS:
-      switch (ch) 
+      switch (ch)
       {
       case '-':
        flags |= DP_F_MINUS;
@@ -473,49 +505,49 @@ static void dopr (char *buffer, size_t maxlen, const char *format, va_list args)
       }
       break;
     case DP_S_MIN:
-      if (isdigit((unsigned char)ch)) 
+      if (isdigit((unsigned char)ch))
       {
        min = 10*min + char_to_int (ch);
        ch = *format++;
-      } 
-      else if (ch == '*') 
+      }
+      else if (ch == '*')
       {
        min = va_arg (args, int);
        ch = *format++;
        state = DP_S_DOT;
-      } 
-      else 
+      }
+      else
        state = DP_S_DOT;
       break;
     case DP_S_DOT:
-      if (ch == '.') 
+      if (ch == '.')
       {
        state = DP_S_MAX;
        ch = *format++;
-      } 
-      else 
+      }
+      else
        state = DP_S_MOD;
       break;
     case DP_S_MAX:
-      if (isdigit((unsigned char)ch)) 
+      if (isdigit((unsigned char)ch))
       {
        if (max < 0)
          max = 0;
        max = 10*max + char_to_int (ch);
        ch = *format++;
-      } 
-      else if (ch == '*') 
+      }
+      else if (ch == '*')
       {
        max = va_arg (args, int);
        ch = *format++;
        state = DP_S_MOD;
-      } 
-      else 
+      }
+      else
        state = DP_S_MOD;
       break;
     case DP_S_MOD:
       /* Currently, we don't support Long Long, bummer */
-      switch (ch) 
+      switch (ch)
       {
       case 'h':
        cflags = DP_C_SHORT;
@@ -535,11 +567,11 @@ static void dopr (char *buffer, size_t maxlen, const char *format, va_list args)
       state = DP_S_CONV;
       break;
     case DP_S_CONV:
-      switch (ch) 
+      switch (ch)
       {
       case 'd':
       case 'i':
-       if (cflags == DP_C_SHORT) 
+       if (cflags == DP_C_SHORT)
          value = va_arg (args, short int);
        else if (cflags == DP_C_LONG)
          value = va_arg (args, long int);
@@ -608,7 +640,7 @@ static void dopr (char *buffer, size_t maxlen, const char *format, va_list args)
        break;
       case 's':
        strvalue = va_arg (args, char *);
-       if (max < 0) 
+       if (max < 0)
          max = maxlen; /* ie, no max */
        fmtstr (buffer, &currlen, maxlen, strvalue, flags, min, max);
        break;
@@ -617,19 +649,19 @@ static void dopr (char *buffer, size_t maxlen, const char *format, va_list args)
        fmtint (buffer, &currlen, maxlen, (long) strvalue, 16, min, max, flags);
        break;
       case 'n':
-       if (cflags == DP_C_SHORT) 
+       if (cflags == DP_C_SHORT)
        {
          short int *num;
          num = va_arg (args, short int *);
          *num = currlen;
-        } 
-       else if (cflags == DP_C_LONG) 
+        }
+       else if (cflags == DP_C_LONG)
        {
          long int *num;
          num = va_arg (args, long int *);
          *num = currlen;
-        } 
-       else 
+        }
+       else
        {
          int *num;
          num = va_arg (args, int *);
@@ -659,9 +691,9 @@ static void dopr (char *buffer, size_t maxlen, const char *format, va_list args)
       break; /* some picky compilers need this */
     }
   }
-  if (currlen < maxlen - 1) 
+  if (currlen < maxlen - 1)
     buffer[currlen] = '\0';
-  else 
+  else
     buffer[maxlen - 1] = '\0';
 }
 
@@ -670,7 +702,7 @@ static void fmtstr (char *buffer, size_t *currlen, size_t maxlen,
 {
   int padlen, strln;     /* amount to pad */
   int cnt = 0;
-  
+
   if (value == 0)
   {
     value = "<NULL>";
@@ -678,23 +710,23 @@ static void fmtstr (char *buffer, size_t *currlen, size_t maxlen,
 
   for (strln = 0; value[strln]; ++strln); /* strlen */
   padlen = min - strln;
-  if (padlen < 0) 
+  if (padlen < 0)
     padlen = 0;
-  if (flags & DP_F_MINUS) 
+  if (flags & DP_F_MINUS)
     padlen = -padlen; /* Left Justify */
 
-  while ((padlen > 0) && (cnt < max)) 
+  while ((padlen > 0) && (cnt < max))
   {
     dopr_outch (buffer, currlen, maxlen, ' ');
     --padlen;
     ++cnt;
   }
-  while (*value && (cnt < max)) 
+  while (*value && (cnt < max))
   {
     dopr_outch (buffer, currlen, maxlen, *value++);
     ++cnt;
   }
-  while ((padlen < 0) && (cnt < max)) 
+  while ((padlen < 0) && (cnt < max))
   {
     dopr_outch (buffer, currlen, maxlen, ' ');
     ++padlen;
@@ -714,7 +746,7 @@ static void fmtint (char *buffer, size_t *currlen, size_t maxlen,
   int spadlen = 0; /* amount to space pad */
   int zpadlen = 0; /* amount to zero pad */
   int caps = 0;
-  
+
   if (max < 0)
     max = 0;
 
@@ -733,7 +765,7 @@ static void fmtint (char *buffer, size_t *currlen, size_t maxlen,
       if (flags & DP_F_SPACE)
        signvalue = ' ';
   }
-  
+
   if (flags & DP_F_UP) caps = 1; /* Should characters be upper case? */
 
   do {
@@ -754,7 +786,7 @@ static void fmtint (char *buffer, size_t *currlen, size_t maxlen,
     zpadlen = MAX(zpadlen, spadlen);
     spadlen = 0;
   }
-  if (flags & DP_F_MINUS) 
+  if (flags & DP_F_MINUS)
     spadlen = -spadlen; /* Left Justifty */
 
 #ifdef DEBUG_SNPRINTF
@@ -763,18 +795,18 @@ static void fmtint (char *buffer, size_t *currlen, size_t maxlen,
 #endif
 
   /* Spaces */
-  while (spadlen > 0) 
+  while (spadlen > 0)
   {
     dopr_outch (buffer, currlen, maxlen, ' ');
     --spadlen;
   }
 
   /* Sign */
-  if (signvalue) 
+  if (signvalue)
     dopr_outch (buffer, currlen, maxlen, signvalue);
 
   /* Zeros */
-  if (zpadlen > 0) 
+  if (zpadlen > 0)
   {
     while (zpadlen > 0)
     {
@@ -784,9 +816,9 @@ static void fmtint (char *buffer, size_t *currlen, size_t maxlen,
   }
 
   /* Digits */
-  while (place > 0) 
+  while (place > 0)
     dopr_outch (buffer, currlen, maxlen, convert[--place]);
-  
+
   /* Left Justified spaces */
   while (spadlen < 0) {
     dopr_outch (buffer, currlen, maxlen, ' ');
@@ -813,7 +845,7 @@ static long double pow10 (int exp)
     result *= 10;
     exp--;
   }
-  
+
   return result;
 }
 
@@ -839,12 +871,12 @@ static void fmtfp (char *buffer, size_t *currlen, size_t maxlen,
   int iplace = 0;
   int fplace = 0;
   int padlen = 0; /* amount to pad */
-  int zpadlen = 0; 
+  int zpadlen = 0;
   int caps = 0;
   long intpart;
   long fracpart;
-  
-  /* 
+
+  /*
    * AIX manpage says the default is 0, but Solaris says the default
    * is 6, and sprintf on AIX defaults to 6
    */
@@ -868,8 +900,8 @@ static void fmtfp (char *buffer, size_t *currlen, size_t maxlen,
 
   intpart = ufvalue;
 
-  /* 
-   * Sorry, we only support 9 digits past the decimal because of our 
+  /*
+   * Sorry, we only support 9 digits past the decimal because of our
    * conversion method
    */
   if (max > 9)
@@ -909,18 +941,18 @@ static void fmtfp (char *buffer, size_t *currlen, size_t maxlen,
   fconvert[fplace] = 0;
 
   /* -1 for decimal point, another -1 if we are printing a sign */
-  padlen = min - iplace - max - 1 - ((signvalue) ? 1 : 0); 
+  padlen = min - iplace - max - 1 - ((signvalue) ? 1 : 0);
   zpadlen = max - fplace;
   if (zpadlen < 0)
     zpadlen = 0;
-  if (padlen < 0) 
+  if (padlen < 0)
     padlen = 0;
-  if (flags & DP_F_MINUS) 
+  if (flags & DP_F_MINUS)
     padlen = -padlen; /* Left Justifty */
 
-  if ((flags & DP_F_ZERO) && (padlen > 0)) 
+  if ((flags & DP_F_ZERO) && (padlen > 0))
   {
-    if (signvalue) 
+    if (signvalue)
     {
       dopr_outch (buffer, currlen, maxlen, signvalue);
       --padlen;
@@ -937,10 +969,10 @@ static void fmtfp (char *buffer, size_t *currlen, size_t maxlen,
     dopr_outch (buffer, currlen, maxlen, ' ');
     --padlen;
   }
-  if (signvalue) 
+  if (signvalue)
     dopr_outch (buffer, currlen, maxlen, signvalue);
 
-  while (iplace > 0) 
+  while (iplace > 0)
     dopr_outch (buffer, currlen, maxlen, iconvert[--iplace]);
 
   /*
@@ -949,7 +981,7 @@ static void fmtfp (char *buffer, size_t *currlen, size_t maxlen,
    */
   dopr_outch (buffer, currlen, maxlen, '.');
 
-  while (fplace > 0) 
+  while (fplace > 0)
     dopr_outch (buffer, currlen, maxlen, fconvert[--fplace]);
 
   while (zpadlen > 0)
@@ -958,7 +990,7 @@ static void fmtfp (char *buffer, size_t *currlen, size_t maxlen,
     --zpadlen;
   }
 
-  while (padlen < 0) 
+  while (padlen < 0)
   {
     dopr_outch (buffer, currlen, maxlen, ' ');
     ++padlen;
@@ -995,7 +1027,7 @@ int snprintf (va_alist) va_dcl
   char *fmt;
 #endif
   VA_LOCAL_DECL;
-    
+
   VA_START (fmt);
   VA_SHIFT (str, char *);
   VA_SHIFT (count, size_t );
@@ -1027,7 +1059,7 @@ int main (void)
     "%3.2f",
     NULL
   };
-  double fp_nums[] = { -1.5, 134.21, 91340.2, 341.1234, 0203.9, 0.96, 0.996, 
+  double fp_nums[] = { -1.5, 134.21, 91340.2, 341.1234, 0203.9, 0.96, 0.996,
     0.9996, 1.996, 4.136, 0};
   char *int_fmt[] = {
     "%-1.5d",
@@ -1055,7 +1087,7 @@ int main (void)
       sprintf (buf2, fp_fmt[x], fp_nums[y]);
       if (strcmp (buf1, buf2))
       {
-       printf("snprintf doesn't match Format: %s\n\tsnprintf = %s\n\tsprintf  = %s\n", 
+       printf("snprintf doesn't match Format: %s\n\tsnprintf = %s\n\tsprintf  = %s\n",
            fp_fmt[x], buf1, buf2);
        fail++;
       }
@@ -1069,7 +1101,7 @@ int main (void)
       sprintf (buf2, int_fmt[x], int_nums[y]);
       if (strcmp (buf1, buf2))
       {
-       printf("snprintf doesn't match Format: %s\n\tsnprintf = %s\n\tsprintf  = %s\n", 
+       printf("snprintf doesn't match Format: %s\n\tsnprintf = %s\n\tsprintf  = %s\n",
            int_fmt[x], buf1, buf2);
        fail++;
       }
@@ -1080,3 +1112,189 @@ int main (void)
 #endif /* SNPRINTF_TEST */
 
 #endif /* !HAVE_SNPRINTF */
+
+
+
+
+/*
+ * List handling functions
+ */
+
+void
+abook_list_append(abook_list **list, char *str)
+{
+       abook_list *tmp;
+
+       if(!str)
+               return;
+
+       for(tmp = *list; tmp && tmp->next; tmp = tmp->next)
+               ;
+
+       if(tmp) {
+               tmp->next = xmalloc(sizeof(abook_list));
+               tmp = tmp->next;
+       } else
+               tmp = *list = xmalloc(sizeof(abook_list));
+
+       tmp->data = xstrdup(str);
+       tmp->next = NULL;
+}
+
+void
+abook_list_free(abook_list **list)
+{
+       abook_list *prev = NULL, *tmp = *list;
+
+       if(!list)
+               return;
+
+       while(tmp) {
+               xfree(tmp->data);
+               prev = tmp;
+               tmp = tmp->next;
+               xfree(prev);
+       }
+
+       *list = NULL;
+}
+
+abook_list *
+csv_to_abook_list(char *str)
+{
+       char *start, *p = str, *end;
+       abook_list *list = NULL;
+
+       if(!str)
+               return NULL;
+
+       SKIPWS(p);
+       start = end = p;
+
+       while(*p) {
+               if(!strchr(", ", *p)) {
+                       end = ++p;
+                       continue;
+               }
+
+               if((*p == ',') && (end - start)) {
+                       abook_list_append(&list, xstrndup(start, end - start));
+                       p++;
+                       SKIPWS(p);
+                       start = end = p;
+                       continue;
+               }
+
+               p++;
+       }
+       if(end - start)
+               abook_list_append(&list, xstrndup(start, end - start));
+
+       return list;
+}
+
+char *
+abook_list_to_csv(abook_list *list)
+{
+       abook_list *tmp;
+       char *res = NULL;
+
+       for(tmp = list; tmp; tmp = tmp->next) {
+               if(tmp == list)
+                       res = xstrdup(tmp->data);
+               else {
+                       res = xrealloc(res, strlen(res)+strlen(tmp->data)+2);
+                       strcat(res, ",");
+                       strcat(res, tmp->data);
+               }
+       }
+
+       return res;
+}
+
+void
+abook_list_rotate(abook_list **list, enum rotate_dir dir)
+{
+       abook_list *tmp = *list;
+
+       if(!tmp || !tmp->next)
+               return;
+
+       switch(dir) {
+               case ROTATE_LEFT:
+                       for(; tmp && tmp->next; tmp = tmp->next)
+                               ;
+
+                       tmp->next = *list;
+                       tmp = *list;
+                       *list = (*list)->next;
+                       tmp->next = NULL;
+                       break;
+               case ROTATE_RIGHT:
+                       for(; tmp && tmp->next && tmp->next->next;
+                                       tmp = tmp->next)
+                               ;
+
+                       tmp->next->next = *list;
+                       *list = tmp->next;
+                       tmp->next = NULL;
+                       break;
+               default:
+                       assert(0);
+       }
+}
+
+/* if str == NULL, deleting the list element */
+void
+abook_list_replace(abook_list **list, int index, char *str)
+{
+       abook_list *cur, *prev;
+       int i = 0;
+
+       cur = prev = *list;
+
+       if((index == 0) && !str) {
+               *list = cur->next;
+               free(cur->data);
+               free(cur);
+               return;
+       }
+       
+       while(1) {
+               if(!cur)
+                       return;
+
+               if(i == index)
+                       break;
+
+               prev = cur;
+               cur = cur->next;
+               i++;
+       }
+
+       if(str) {
+               free(cur->data);
+               cur->data = xstrdup(str);
+       } else {
+               prev->next = cur->next;
+               free(cur->data);
+               free(cur);
+       }
+}
+
+abook_list *
+abook_list_get(abook_list *list, int index)
+{
+       int i = 0;
+
+       while(1) {
+               if(!list)
+                       return NULL;
+
+               if(i == index)
+                       return list;
+
+               i++;
+               list = list->next;
+       }
+}