#include <cdk_int.h>
 
/*
 * $Author: tom $
 * $Date: 2005/04/01 21:25:01 $
 * $Revision: 1.82 $
 */
 
/*
 * Declare file local prototypes.
 */
static BINDFN_PROTO(adjustAlphalistCB);
static BINDFN_PROTO(completeWordCB);
static int preProcessEntryField (EObjectType cdktype, void *object, void *clientData, chtype input);
static int createList (CDKALPHALIST *alphalist, char *list[], int listSize);

DeclareSetXXchar(static, _setMy);
DeclareCDKObjects(ALPHALIST, Alphalist, _setMy, String);

/*
 * This creates the alphalist widget.
 */
CDKALPHALIST *newCDKAlphalist (CDKSCREEN *cdkscreen, int xplace, int yplace, int height, int width, char *title, char *label, char *list[], int listSize, chtype fillerChar, chtype highlight, boolean Box, boolean shadow)
{
   CDKALPHALIST *alphalist	= 0;
   chtype *chtypeLabel		= 0;
   int parentWidth		= getmaxx(cdkscreen->window);
   int parentHeight		= getmaxy(cdkscreen->window);
   int boxWidth			= width;
   int boxHeight		= height;
   int xpos			= xplace;
   int ypos			= yplace;
   int tempWidth		= 0;
   int tempHeight		= 0;
   int labelLen			= 0;
   int x, junk2;

   static const struct { int from; int to; } bindings[] = {
		{ CDK_BACKCHAR,	KEY_PPAGE },
		{ CDK_FORCHAR,	KEY_NPAGE },
   };

   if ((alphalist = newCDKObject(CDKALPHALIST, &my_funcs)) == 0
    || !createList(alphalist, list, listSize))
   {
      destroyCDKObject(alphalist);
      return (0);
   }

   setCDKAlphalistBox (alphalist, Box);

  /*
   * If the height is a negative value, the height will
   * be ROWS-height, otherwise, the height will be the
   * given height.
   */
   boxHeight = setWidgetDimension (parentHeight, height, 0);

  /*
   * If the width is a negative value, the width will
   * be COLS-width, otherwise, the width will be the
   * given width.
   */
   boxWidth = setWidgetDimension (parentWidth, width, 0);

   /* Translate the label char *pointer to a chtype pointer. */
   if (label != 0)
   {
      chtypeLabel = char2Chtype (label, &labelLen, &junk2);
      freeChtype (chtypeLabel);
   }

   /* Rejustify the x and y positions if we need to. */
   alignxy (cdkscreen->window, &xpos, &ypos, boxWidth, boxHeight);

   /* Make the file selector window. */
   alphalist->win = newwin (boxHeight, boxWidth, ypos, xpos);

   if (alphalist->win == 0)
   {
      destroyCDKObject(alphalist);
      return (0);
   }
   keypad (alphalist->win, TRUE);

   /* Set some variables. */
   ScreenOf(alphalist)		= cdkscreen;
   alphalist->parent		= cdkscreen->window;
   alphalist->highlight		= highlight;
   alphalist->fillerChar	= fillerChar;
   alphalist->boxHeight		= boxHeight;
   alphalist->boxWidth		= boxWidth;
   initExitType(alphalist);
   alphalist->shadow		= shadow;
   alphalist->shadowWin		= 0;

   /* Do we want a shadow? */
   if (shadow)
   {
      alphalist->shadowWin = newwin (boxHeight, boxWidth, ypos + 1, xpos + 1);
   }

   /* We need to sort the list before we use it. */
   /* FIXME: sort after copying, so we don't break the caller */
   sortList (list, listSize);

   /* Copy the list information. */
   for (x=0; x < listSize; x++)
   {
      alphalist->list[x] = copyChar (list[x]);
   }
   alphalist->listSize = listSize;

   /* Create the entry field. */
   tempWidth = (isFullWidth(width)
   		 ? FULL
		 : boxWidth - 2 - labelLen);
   alphalist->entryField = newCDKEntry (cdkscreen,
					getbegx(alphalist->win),
					getbegy(alphalist->win),
					title, label,
					A_NORMAL, fillerChar, 
					vMIXED, tempWidth, 0, 512,
					Box, FALSE);
   setCDKEntryLLChar (alphalist->entryField, ACS_LTEE);
   setCDKEntryLRChar (alphalist->entryField, ACS_RTEE);

   /* Set the key bindings for the entry field. */
   bindCDKObject (vENTRY, alphalist->entryField, KEY_UP, adjustAlphalistCB, alphalist);
   bindCDKObject (vENTRY, alphalist->entryField, KEY_DOWN, adjustAlphalistCB, alphalist);
   bindCDKObject (vENTRY, alphalist->entryField, KEY_NPAGE, adjustAlphalistCB, alphalist);
   bindCDKObject (vENTRY, alphalist->entryField, KEY_PPAGE, adjustAlphalistCB, alphalist);
   bindCDKObject (vENTRY, alphalist->entryField, KEY_TAB, completeWordCB, alphalist);

   /* Set up the post-process function for the entry field. */
   setCDKEntryPreProcess (alphalist->entryField, preProcessEntryField, alphalist);

   /*
    * Create the scrolling list.  It overlaps the entry field by one line if
    * we are using box-borders.
    */
   tempHeight = getmaxy(alphalist->entryField->win) - BorderOf(alphalist);
   tempWidth = (isFullWidth(width)
   		? FULL
		: boxWidth - 1);
   alphalist->scrollField = newCDKScroll (cdkscreen, 
					  getbegx(alphalist->win),
					  getbegy(alphalist->entryField->win) + tempHeight,
					  RIGHT,
					  boxHeight - tempHeight,
					  tempWidth,
					  0, list, listSize,
					  NONUMBERS, A_REVERSE,
					  Box, FALSE);
   setCDKScrollULChar (alphalist->scrollField, ACS_LTEE);
   setCDKScrollURChar (alphalist->scrollField, ACS_RTEE);

   /* Setup the key bindings. */
   for (x = 0; x < (int) SIZEOF(bindings); ++x)
      bindCDKObject (vALPHALIST, alphalist, bindings[x].from, getcCDKBind, (void *)(long)bindings[x].to);

   /* Register this baby. */
   registerCDKObject (cdkscreen, vALPHALIST, alphalist);

   /* Return the file selector pointer. */
   return (alphalist);
}

/*
 * This erases the file selector from the screen.
 */
static void _eraseCDKAlphalist (CDKOBJS *object)
{
   if (validCDKObject (object))
   {
      CDKALPHALIST *alphalist = (CDKALPHALIST *)object;

      eraseCDKScroll (alphalist->scrollField);
      eraseCDKEntry (alphalist->entryField);

      eraseCursesWindow (alphalist->shadowWin);
      eraseCursesWindow (alphalist->win);
   }
}

/*
 * This moves the alphalist field to the given location.
 */
static void _moveCDKAlphalist (CDKOBJS *object, int xplace, int yplace, boolean relative, boolean refresh_flag)
{
   CDKALPHALIST *alphalist = (CDKALPHALIST *)object;

   /* Declare local variables. */
   int currentX = getbegx(alphalist->win);
   int currentY = getbegy(alphalist->win);
   int xpos	= xplace;
   int ypos	= yplace;
   int xdiff	= 0;
   int ydiff	= 0;

   /*
    * If this is a relative move, then we will adjust where we want
    * to move to.
    */
   if (relative)
   {
      xpos = getbegx(alphalist->win) + xplace;
      ypos = getbegy(alphalist->win) + yplace;
   }

   /* Adjust the window if we need to. */
   alignxy (WindowOf(alphalist), &xpos, &ypos, alphalist->boxWidth, alphalist->boxHeight);

   /* Get the difference. */
   xdiff = currentX - xpos;
   ydiff = currentY - ypos;

   /* Move the window to the new location. */
   moveCursesWindow(alphalist->win, -xdiff, -ydiff);
   moveCursesWindow(alphalist->shadowWin, -xdiff, -ydiff);

   /* Move the sub-widgets. */
   moveCDKEntry (alphalist->entryField, xplace, yplace, relative, FALSE);
   moveCDKScroll (alphalist->scrollField, xplace, yplace, relative, FALSE);

   /* Touch the windows so they 'move'. */
   refreshCDKWindow (WindowOf(alphalist));

   /* Redraw the window, if they asked for it. */
   if (refresh_flag)
   {
      drawCDKAlphalist (alphalist, ObjOf(alphalist)->box);
   }
}

/*
 * This draws the file selector widget.
 */
static void _drawCDKAlphalist (CDKOBJS *obj, boolean Box GCC_UNUSED)
{
    CDKALPHALIST * alphalist = (CDKALPHALIST *)obj;

   /* Does this widget have a shadow? */
   if (alphalist->shadowWin != 0)
   {
      drawShadow (alphalist->shadowWin);
   }

   /* Draw in the entry field. */
   drawCDKEntry (alphalist->entryField, ObjOf(alphalist->entryField)->box);

   /* Draw in the scroll field. */
   drawCDKScroll (alphalist->scrollField, ObjOf(alphalist->scrollField)->box);
}

/*
 * This activates the file selector.
 */
char *activateCDKAlphalist (CDKALPHALIST *alphalist, chtype *actions)
{
   char *ret = 0;

   /* Draw the widget. */
   drawCDKAlphalist (alphalist, ObjOf(alphalist)->box);

   /* Activate the widget. */
   ret = activateCDKEntry (alphalist->entryField, actions);

   /* Copy the exit type from the entry field. */
   copyExitType(alphalist, alphalist->entryField);

   /* Determine the exit status. */
   if (alphalist->exitType != vEARLY_EXIT)
   {
      return ret;
   }
   return 0;
}

/*
 * This injects a single character into the alphalist.
 */
static int _injectCDKAlphalist (CDKOBJS *object, chtype input)
{
   CDKALPHALIST *alphalist = (CDKALPHALIST *)object;
   char *ret = unknownString;

   /* Draw the widget. */
   drawCDKAlphalist (alphalist, ObjOf(alphalist)->box);

   /* Inject a character into the widget. */
   ret = injectCDKEntry (alphalist->entryField, input);

   /* Copy the exit type from the entry field. */
   copyExitType(alphalist, alphalist->entryField);

   /* Determine the exit status. */
   if (alphalist->exitType == vEARLY_EXIT)
      ret = unknownString;

   ResultOf(alphalist).valueString = ret;
   return (ret != unknownString);
}

dummyFocus(Alphalist)

dummyUnfocus(Alphalist)

dummyRefreshData(Alphalist)

dummySaveData(Alphalist)

/*
 * This sets multiple attributes of the widget.
 */
void setCDKAlphalist (CDKALPHALIST *alphalist, char *list[], int listSize, chtype fillerChar, chtype highlight, boolean Box)
{
   setCDKAlphalistContents (alphalist, list, listSize);
   setCDKAlphalistFillerChar (alphalist, fillerChar);
   setCDKAlphalistHighlight (alphalist, highlight);
   setCDKAlphalistBox (alphalist, Box);
}

/*
 * This function sets the information inside the file selector.
 */
void setCDKAlphalistContents (CDKALPHALIST *alphalist, char *list[], int listSize)
{
   /* Declare local variables. */
   CDKSCROLL *scrollp	= (CDKSCROLL *)alphalist->scrollField;
   CDKENTRY *entry	= (CDKENTRY *)alphalist->entryField;

   if (!createList(alphalist, list, listSize))
      return;

   /* Set the information in the scrolling list. */
   setCDKScroll (scrollp, list, listSize, NONUMBERS, scrollp->highlight, ObjOf(scrollp)->box);

   /* Clean out the entry field. */
   cleanCDKEntry (entry);

   /* Redraw the alphalist. */
   eraseCDKAlphalist (alphalist);
   drawCDKAlphalist (alphalist, ObjOf(alphalist)->box);
}

/*
 * This returns the contents of the alphalist.
 */
char **getCDKAlphalistContents (CDKALPHALIST *alphalist, int *size)
{
   (*size) = alphalist->listSize;
   return alphalist->list;
}

/*
 * This sets the filler character of the entry field of the alphalist.
 */
void setCDKAlphalistFillerChar (CDKALPHALIST *alphalist, chtype fillerCharacter)
{
   CDKENTRY *entry = (CDKENTRY *)alphalist->entryField;

   alphalist->fillerChar = fillerCharacter;

   setCDKEntryFillerChar (entry, fillerCharacter);
}
chtype getCDKAlphalistFillerChar (CDKALPHALIST *alphalist)
{
   return alphalist->fillerChar;
}

/*
 * This sets the highlight bar attributes.
 */
void setCDKAlphalistHighlight (CDKALPHALIST *alphalist, chtype highlight)
{
   alphalist->highlight = highlight;
}
chtype getCDKAlphalistHighlight (CDKALPHALIST *alphalist)
{
   return alphalist->highlight;
}

/*
 * This sets whether or not the widget will be drawn with a box.
 */
void setCDKAlphalistBox (CDKALPHALIST *alphalist, boolean Box)
{
   ObjOf(alphalist)->box = Box;
   ObjOf(alphalist)->borderSize = Box ? 1 : 0;
}

boolean getCDKAlphalistBox (CDKALPHALIST *alphalist)
{
   return ObjOf(alphalist)->box;
}

/*
 * These functions set the drawing characters of the widget.
 */
static void _setMyULchar (CDKOBJS *object, chtype character)
{
   CDKALPHALIST *alphalist = (CDKALPHALIST *)object;

   setCDKEntryULChar (alphalist->entryField, character);
}
static void _setMyURchar (CDKOBJS *object, chtype character)
{
   CDKALPHALIST *alphalist = (CDKALPHALIST *)object;

   setCDKEntryURChar (alphalist->entryField, character);
}
static void _setMyLLchar (CDKOBJS *object, chtype character)
{
   CDKALPHALIST *alphalist = (CDKALPHALIST *)object;

   setCDKScrollLLChar (alphalist->scrollField, character);
}
static void _setMyLRchar (CDKOBJS *object, chtype character)
{
   CDKALPHALIST *alphalist = (CDKALPHALIST *)object;

   setCDKScrollLRChar (alphalist->scrollField, character);
}
static void _setMyVTchar (CDKOBJS *object, chtype character)
{
   CDKALPHALIST *alphalist = (CDKALPHALIST *)object;

   setCDKEntryVerticalChar (alphalist->entryField, character);
   setCDKScrollVerticalChar (alphalist->scrollField, character);
}
static void _setMyHZchar (CDKOBJS *object, chtype character)
{
   CDKALPHALIST *alphalist = (CDKALPHALIST *)object;

   setCDKEntryHorizontalChar (alphalist->entryField, character);
   setCDKScrollHorizontalChar (alphalist->scrollField, character);
}
static void _setMyBXattr (CDKOBJS *object, chtype character)
{
   CDKALPHALIST *alphalist = (CDKALPHALIST *)object;

   setCDKEntryBoxAttribute (alphalist->entryField, character);
   setCDKScrollBoxAttribute (alphalist->scrollField, character);
}

/*
 * This sets the background attribute of the widget.
 */ 
static void _setBKattrAlphalist (CDKOBJS *obj, chtype attrib)
{
   CDKALPHALIST *alphalist = (CDKALPHALIST *) obj;

   setCDKEntryBackgroundAttrib (alphalist->entryField, attrib);
   setCDKScrollBackgroundAttrib (alphalist->scrollField, attrib);
}

/*
 * This destroys the file selector.	
 */
static void _destroyCDKAlphalist (CDKOBJS *object)
{
   if (object != 0)
   {
      CDKALPHALIST *alphalist = (CDKALPHALIST *)object;

      CDKfreeStrings(alphalist->list);

      destroyCDKEntry (alphalist->entryField);
      destroyCDKScroll (alphalist->scrollField);
    
      /* Free up the window pointers. */
      deleteCursesWindow (alphalist->shadowWin);
      deleteCursesWindow (alphalist->win);

      /* Unregister the object. */
      unregisterCDKObject (vALPHALIST, alphalist);
   }
}

/*
 * This function sets the pre-process function.
 */
void setCDKAlphalistPreProcess (CDKALPHALIST *alphalist, PROCESSFN callback, void *data)
{
   setCDKEntryPreProcess (alphalist->entryField, callback, data);
}
 
/*
 * This function sets the post-process function.
 */
void setCDKAlphalistPostProcess (CDKALPHALIST *alphalist, PROCESSFN callback, void *data)
{
   setCDKEntryPostProcess (alphalist->entryField, callback, data);
}

/*
 * Start of callback functions.
 */
static int adjustAlphalistCB (EObjectType objectType GCC_UNUSED, void *object GCC_UNUSED, void *clientData, chtype key)
{
   CDKALPHALIST *alphalist	= (CDKALPHALIST *)clientData;
   CDKSCROLL *scrollp		= (CDKSCROLL*)alphalist->scrollField;
   CDKENTRY *entry		= (CDKENTRY*)alphalist->entryField;
   char *current		= 0;

   /* Adjust the scrolling list. */
   injectCDKScroll (alphalist->scrollField, (chtype)key);

   /* Set the value in the entry field. */
   current = chtype2Char (scrollp->item[scrollp->currentItem]);
   setCDKEntryValue (entry, current);
   drawCDKEntry (entry, ObjOf(entry)->box);
   freeChar (current);
   return (TRUE);
}

/*
 * This is the heart-beat of the widget.
 */
static int preProcessEntryField (EObjectType cdktype GCC_UNUSED, void *object GCC_UNUSED, void *clientData, chtype input)
{
   CDKALPHALIST *alphalist	= (CDKALPHALIST *)clientData;
   CDKSCROLL *scrollp		= alphalist->scrollField;
   CDKENTRY *entry		= alphalist->entryField;
   int infoLen			= 0;
   int Index, difference, absoluteDifference, x;
   char pattern[5000];

   /* Make sure the entry field isn't empty. */
   if (entry->info != 0)
   {
      infoLen = (int)strlen (entry->info);
   }
   else
   {
      setCDKScrollPosition (scrollp, 0);
      drawCDKScroll (scrollp, ObjOf(scrollp)->box);
      return 1;
   }

   /* Check the input. */
   if ((isChar(input) && (isalnum (CharOf(input)) || ispunct (input)))
    || input == KEY_BACKSPACE
    || input == KEY_DC)
   {
      /* Copy the information from the entry field. */
      strcpy (pattern, entry->info);

      /* Truncate/Concatenate to the information in the entry field. */	 
      if (input == KEY_BACKSPACE || input == KEY_DC)
      {
	 pattern[infoLen] = '\0';
	 pattern[infoLen-1] = '\0';

	 /* If we had only 1 item in the list; jump back to the top. */
	 if (infoLen <= 1)
	 {
	    setCDKScrollPosition (scrollp, 0);
	    drawCDKScroll (scrollp, ObjOf(scrollp)->box);
	    return 1;
	 }
      }
      else
      {
	 pattern[infoLen] = (char)input;
	 pattern[infoLen + 1] = '\0';
      }

      /* Look for the pattern in the list. */
      Index = searchList (alphalist->list, alphalist->listSize, pattern);
      if (Index >= 0)
      {
	 difference		= Index - scrollp->currentItem;
	 absoluteDifference	= abs (difference);

	/*
	 * If the difference is less than zero, then move up.
	 * Otherwise move down.
	 */
	 if (difference <= 0)
	 {
	   /*
	    * If the difference is greater than 10 jump to the new
	    * index position. Otherwise provide the nice scroll.
	    */
	    if (absoluteDifference <= 10)
	    {
	       for (x=0; x < absoluteDifference; x++)
	       {
		  injectCDKScroll (scrollp, KEY_UP);
	       }
	    }
	    else
	    {
	       setCDKScrollPosition (scrollp, Index);
	    }
	    drawCDKScroll (scrollp, ObjOf(scrollp)->box);
	 }
	 else
	 {
	   /*
	    * If the difference is greater than 10 jump to the new
	    * index position. Otherwise provide the nice scroll.
	    */
	    if (absoluteDifference <= 10)
	    {
	       for (x=0; x < absoluteDifference; x++)
	       {
		  injectCDKScroll (scrollp, KEY_DOWN);
	       }
	    }
	    else
	    {
	       setCDKScrollPosition (scrollp, Index);
	    }
	    drawCDKScroll (scrollp, ObjOf(scrollp)->box);
	 }
      }
      else
      {
	 Beep();
	 return 0;
      }
   }
   return 1;
}

/*
 * This tries to complete the word in the entry field.
 */
static int completeWordCB (EObjectType objectType GCC_UNUSED, void *object GCC_UNUSED, void *clientData, chtype key GCC_UNUSED)
{
   CDKALPHALIST *alphalist	= (CDKALPHALIST *)clientData;
   CDKENTRY *entry		= (CDKENTRY*)alphalist->entryField;
   CDKSCROLL *scrollp		= 0;
   int currentIndex		= 0;
   int wordLength		= 0;
   int selected			= -1;
   int altCount			= 0;
   int height			= 0;
   int match			= 0;
   int Index			= 0;
   int ret			= 0;
   int x			= 0;
   char **altWords		= 0;
   unsigned used		= 0;

   if (entry->info == 0)
   {
      Beep();
      return (TRUE);
   }
   wordLength = (int)strlen (entry->info);

   /* If the word length is equal to zero, just leave. */
   if (wordLength == 0)
   {
      Beep();
      return (TRUE);
   }

   /* Look for a unique word match. */
   Index = searchList (alphalist->list, alphalist->listSize, entry->info);

   /* If the index is less than zero, return we didn't find a match. */
   if (Index < 0)
   {
      Beep();
      return (TRUE);
   }

   /* Did we find the last word in the list? */
   if (Index == alphalist->listSize-1)
   {
      setCDKEntryValue (entry, alphalist->list[Index]);
      drawCDKEntry (entry, ObjOf(entry)->box);
      return (TRUE);
   }

   /* Ok, we found a match, is the next item similar? */
   ret = strncmp (alphalist->list[Index + 1], entry->info, wordLength);
   if (ret == 0)
   {
      currentIndex	= Index;
      altCount		= 0;
      height		= 0;
      match		= 0;
      selected		= -1;

      /* Start looking for alternate words. */
      /* FIXME: bsearch would be more suitable */
      while ((currentIndex < alphalist->listSize)
	  && (strncmp (alphalist->list[currentIndex], entry->info, wordLength) == 0))
      {
	 used = CDKallocStrings(&altWords, alphalist->list[currentIndex++], altCount++, used);
      }
      
      /* Determine the height of the scrolling list. */
      height = (altCount < 8 ? altCount + 3 : 11);

      /* Create a scrolling list of close matches. */
      scrollp = newCDKScroll (entry->obj.screen, CENTER, CENTER, RIGHT, height, -30,
					"<C></B/5>Possible Matches.",
					altWords, altCount, NUMBERS,
					A_REVERSE, TRUE, FALSE);

      /* Allow them to select a close match. */
      match = activateCDKScroll (scrollp, 0);
      selected = scrollp->currentItem;
      
      /* Check how they exited the list. */
      if (scrollp->exitType == vESCAPE_HIT)
      {
	 /* Destroy the scrolling list. */
	 destroyCDKScroll (scrollp);

	 /* Clean up. */
	 CDKfreeStrings (altWords);

	 /* Beep at the user. */
	 Beep();

	 /* Redraw the alphalist and return. */
	 drawCDKAlphalist (alphalist, ObjOf(alphalist)->box);
	 return (TRUE);
      }

      /* Destroy the scrolling list. */
      destroyCDKScroll (scrollp);

      /* Set the entry field to the selected value. */
      setCDKEntry (entry, altWords[match], entry->min, entry->max, ObjOf(entry)->box);

      /* Move the highlight bar down to the selected value. */
      for (x=0; x < selected; x++)
      {
	 injectCDKScroll ((alphalist->scrollField), KEY_DOWN);
      }

      /* Clean up. */
      CDKfreeStrings (altWords);

      /* Redraw the alphalist. */
      drawCDKAlphalist (alphalist, ObjOf(alphalist)->box);
   }
   else
   {
      /* Set the entry field with the found item. */
      setCDKEntry (entry, alphalist->list[Index], entry->min, entry->max, ObjOf(entry)->box);
      drawCDKEntry (entry, ObjOf(entry)->box);
   }
   return (TRUE);
}

static int createList (CDKALPHALIST *alphalist, char *list[], int listSize)
{
   int status = 0;

   if (listSize > 0)
   {
      char **newlist = typeCallocN(char *, listSize + 1);

      if (newlist != 0)
      {
	 char **oldlist = alphalist->list;
	 int x;

	 /*
	  * We'll sort the list before we use it.  It would have been better to
	  * declare list[] const and only modify the copy, but there may be
	  * clients that rely on the old behavior.
	  */
	 sortList (list, listSize);

	 /* Copy in the new information. */
	 status = 1;
	 for (x=0; x < listSize; x++)
	 {
	    if ((newlist[x] = copyChar (list[x])) == 0)
	    {
	       status = 0;
	       break;
	    }
	 }
	 if (status)
	 {
	    CDKfreeStrings(oldlist);
	    alphalist->listSize = listSize;
	    alphalist->list = newlist;
	 }
	 else
	 {
	    CDKfreeStrings(newlist);
	 }
      }
   }
   return status;
}


syntax highlighted by Code2HTML, v. 0.9.1