[BACK]Return to template.c CVS log [TXT][DIR] Up to [cvs.NetBSD.org] / othersrc / dist / cdk

File: [cvs.NetBSD.org] / othersrc / dist / cdk / template.c (download)

Revision 1.3, Tue Jan 9 18:41:54 2001 UTC (13 years, 6 months ago) by garbled
Branch: MAIN
CVS Tags: HEAD
Changes since 1.2: +2 -3 lines

Fix a problem in these widgets where they uncondititonally set the
exitType to either vEARLY_EXIT, or vESCAPE_HIT when returning from a bound
function.  This had the unfortunate effect that when you hit F2 to refresh
the screen in sushi, it would exit out immediately after refreshing the
screen.

This modification allows the programmer to still create an exit-causing
bound function, by simply setting the exitType in the function, as was likely
intended by the author.  Many thanks to Charles Hannum for helping me figure
this out.

This should fix problems noted by itojun on tech-userlevel with the function
keys.

#include <cdk.h>

/*
 * $Author: garbled $
 * $Date: 2001/01/09 18:41:54 $
 * $Revision: 1.3 $
 */

/*
 * Declare file local prototypes.
 */
static void CDKTemplateCallBack (CDKTEMPLATE *cdktemplate, chtype input);
static void drawCDKTemplateField (CDKTEMPLATE *cdktemplate);
static void adjustCDKTemplateCursor (CDKTEMPLATE *cdktemplate, int direction);

#define isPlateChar(c) ((c) != 0 && strchr("#ACcMXxz", c) != 0)

/*
 * Declare file local variables.
 */
extern char *GPasteBuffer;

DeclareCDKObjects(my_funcs,Template);

/*
 * This creates a cdktemplate widget.
 */
CDKTEMPLATE *newCDKTemplate (CDKSCREEN *cdkscreen, int xplace, int yplace, char *title, char *label, char *plate, char *Overlay, boolean Box, boolean shadow)
{
   /* Set up some variables */
   CDKTEMPLATE *cdktemplate	= newCDKObject(CDKTEMPLATE, &my_funcs);
   chtype *holder		= 0;
   int parentWidth		= getmaxx(cdkscreen->window);
   int parentHeight		= getmaxy(cdkscreen->window);
   int boxWidth			= 0;
   int boxHeight		= 3;
   int maxWidth			= INT_MIN;
   int xpos			= xplace;
   int ypos			= yplace;
   int horizontalAdjust		= 0;
   int fieldWidth		= 0;
   int plateLen			= 0;
   int junk			= 0;
   char **temp			= 0;
   int x, len, junk2;

   /* Make sure the plate is not null. */
   if (plate == 0)
   {
      free (cdktemplate);
      return 0;
   }
   fieldWidth = (int)strlen (plate);

   /* Set some basic values of the cdktemplate field. */
   cdktemplate->label		= 0;
   cdktemplate->labelLen	= 0;
   cdktemplate->labelWin	= 0;
   cdktemplate->titleLines	= 0;

   /* Translate the char * label to a chtype * */
   if (label != 0)
   {
      cdktemplate->label	= char2Chtype (label, &cdktemplate->labelLen, &junk);
   }

   /* Translate the char * Overlay to a chtype * */
   if (Overlay != 0)
   {
      cdktemplate->overlay = char2Chtype (Overlay, &cdktemplate->overlayLen, &junk);
      cdktemplate->fieldAttr = cdktemplate->overlay[0] & A_ATTRIBUTES;
   }
   else
   {
      cdktemplate->overlay	= 0;
      cdktemplate->overlayLen	= 0;
      cdktemplate->fieldAttr	= A_NORMAL;
   }

   /* Set the box width. */
   boxWidth = fieldWidth+ cdktemplate->labelLen + 2;

   /* Translate the char * items to chtype * */
   if (title != 0)
   {
      temp = CDKsplitString (title, '\n');
      cdktemplate->titleLines = CDKcountStrings (temp);

      /* We need to determine the widest title line. */
      for (x=0; x < cdktemplate->titleLines; x++)
      {
	 holder = char2Chtype (temp[x], &len, &junk2);
	 maxWidth = MAXIMUM (maxWidth, len);
	 freeChtype (holder);
      }

      /*
       * If one of the title lines is wider than the field and the label,
       * the box width will expand to accomodate.
       */
       if (maxWidth > boxWidth)
       {
	  horizontalAdjust = (int)((maxWidth - boxWidth) / 2) + 1;
	  boxWidth = maxWidth + 2;
       }

      /* For each line in the title, convert from char * to chtype * */
      for (x=0; x < cdktemplate->titleLines; x++)
      {
	 cdktemplate->title[x]	  = char2Chtype (temp[x], &cdktemplate->titleLen[x], &cdktemplate->titlePos[x]);
	 cdktemplate->titlePos[x] = justifyString (boxWidth - 2, cdktemplate->titleLen[x], cdktemplate->titlePos[x]);
      }

      CDKfreeStrings(temp);
   }
   else
   {
      /* No title? Set the required variables. */
      cdktemplate->titleLines = 0;
   }
   boxHeight += cdktemplate->titleLines;

  /*
   * Make sure we didn't extend beyond the dimensions of the window.
   */
   boxWidth = MINIMUM (boxWidth, parentWidth);
   boxHeight = MINIMUM (boxHeight, parentHeight);
   fieldWidth = MINIMUM (boxWidth - 2 - cdktemplate->labelLen, fieldWidth);

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

   /* Make the cdktemplate window */
   cdktemplate->win = newwin (boxHeight + !!shadow, boxWidth + !!shadow, ypos, xpos);

   /* Is the cdktemplate window null?? */
   if (cdktemplate->win == 0)
   {
      /* Clean up any used memory. */
      freeChtype (cdktemplate->label);
      freeChtype (cdktemplate->overlay);
      free (cdktemplate);

      /* Return a null pointer. */
      return (0);
   }
   keypad (cdktemplate->win, TRUE);

   if (cdktemplate->titleLines > 0)
   {
      /* Make the title window. */
      cdktemplate->titleWin = subwin (cdktemplate->win,
				cdktemplate->titleLines, boxWidth - 2,
				ypos + 1, xpos + 1);
   }

   /* Make the label window. */
   if (cdktemplate->label != 0)
   {
      cdktemplate->labelWin = subwin (cdktemplate->win,
				1, cdktemplate->labelLen + 2,
				ypos + cdktemplate->titleLines + 1,
				xpos + horizontalAdjust + 1);
   }

   /* Make the field window. */
   cdktemplate->fieldWin = subwin (cdktemplate->win,
				1, fieldWidth,
				ypos + cdktemplate->titleLines + 1,
				xpos + cdktemplate->labelLen + horizontalAdjust + 1);
   keypad (cdktemplate->fieldWin, TRUE);

   /* Set up the info field. */
   cdktemplate->plateLen = (int)strlen(plate);
   cdktemplate->info = (char *)malloc (sizeof(char) * (cdktemplate->plateLen + 2));
   memset (cdktemplate->info, '\0', cdktemplate->plateLen + 1);

   /* Copy the plate to the cdktemplate. */
   plateLen		= strlen (plate);
   cdktemplate->plate	= (char *)malloc (sizeof (char) * plateLen + 3);
   strncpy (cdktemplate->plate, plate, plateLen + 3);

   /* Set up the rest of the structure	*/
   ScreenOf(cdktemplate)		= cdkscreen;
   cdktemplate->parent			= cdkscreen->window;
   cdktemplate->fieldWidth		= fieldWidth;
   cdktemplate->boxHeight		= boxHeight;
   cdktemplate->boxWidth		= boxWidth;
   cdktemplate->platePos		= 0;
   cdktemplate->screenPos		= 0;
   cdktemplate->infoPos			= 0;
   cdktemplate->exitType		= vNEVER_ACTIVATED;
   cdktemplate->min			= 0;
   ObjOf(cdktemplate)->box		= Box;
   cdktemplate->shadow			= shadow;
   cdktemplate->callbackfn		= (void *)&CDKTemplateCallBack;
   cdktemplate->preProcessFunction	= 0;
   cdktemplate->preProcessData		= 0;
   cdktemplate->postProcessFunction	= 0;
   cdktemplate->postProcessData		= 0;
   cdktemplate->ULChar			= ACS_ULCORNER;
   cdktemplate->URChar			= ACS_URCORNER;
   cdktemplate->LLChar			= ACS_LLCORNER;
   cdktemplate->LRChar			= ACS_LRCORNER;
   cdktemplate->HChar			= ACS_HLINE;
   cdktemplate->VChar			= ACS_VLINE;
   cdktemplate->BoxAttrib		= A_NORMAL;

   /* Clean the key bindings. */
   cleanCDKObjectBindings (vTEMPLATE, cdktemplate);

   /* Register this baby.		 */
   registerCDKObject (cdkscreen, vTEMPLATE, cdktemplate);

   /* Return the pointer to the structure */
   return cdktemplate;
}

/*
 * This actually manages the cdktemplate widget...
 */
char *activateCDKTemplate (CDKTEMPLATE *cdktemplate, chtype *actions)
{
   /* Declare local variables. */
   chtype input = 0;
   char *ret	= 0;

   /* Draw the object. */
   drawCDKTemplate (cdktemplate, ObjOf(cdktemplate)->box);

   /* Check if actions is null. */
   if (actions == 0)
   {
      for (;;)
      {
	 /* Get the input. */
	 wrefresh (cdktemplate->fieldWin);
	 input = wgetch (cdktemplate->fieldWin);

	 /* Inject the character into the widget. */
	 ret = injectCDKTemplate (cdktemplate, input);
	 if (cdktemplate->exitType != vEARLY_EXIT)
	 {
	    return ret;
	 }
      }
   }
   else
   {
      int length = chlen (actions);
      int x = 0;

      /* Inject each character one at a time. */
      for (x=0; x < length; x++)
      {
	 ret = injectCDKTemplate (cdktemplate, actions[x]);
	 if (cdktemplate->exitType != vEARLY_EXIT)
	 {
	    return ret;
	 }
      }
   }

   /* Set the exit type and return. */
   cdktemplate->exitType = vEARLY_EXIT;
   return ret;
}

/*
 * This injects a character into the widget.
 */
char *injectCDKTemplate (CDKTEMPLATE *cdktemplate, chtype input)
{
   /* Declare some local variables. */
   int ppReturn = 1;
   int length, x;

   /* Set the exit type and return. */
   cdktemplate->exitType = vEARLY_EXIT;

   /* Move the cursor. */
   drawCDKTemplateField (cdktemplate);

   /* Check if there is a pre-process function to be called. */
   if (cdktemplate->preProcessFunction != 0)
   {
      ppReturn = ((PROCESSFN)(cdktemplate->preProcessFunction)) (vTEMPLATE, cdktemplate, cdktemplate->preProcessData, input);
   }

   /* Should we continue? */
   if (ppReturn != 0)
   {
      /* Check a predefined binding...		 */
      if (checkCDKObjectBind (vTEMPLATE, cdktemplate, input) != 0)
      {
	 return 0;
      }
      else
      {
	 switch (input)
	 {
	    case KEY_LEFT : case KEY_RIGHT : case KEY_UP : case KEY_DOWN :
		 Beep();
		 break;

	    case CDK_ERASE :
		 if (strlen(cdktemplate->info) != 0)
		 {
		    cleanChar (cdktemplate->info, cdktemplate->plateLen + 1, '\0');
		    cdktemplate->screenPos = 0;
		    cdktemplate->infoPos = 0;
		    cdktemplate->platePos = 0;
		    drawCDKTemplateField (cdktemplate);
		 }
		 break;

	    case CDK_CUT:
		 if ((int)strlen(cdktemplate->info) != 0)
		 {
		    freeChar (GPasteBuffer);
		    GPasteBuffer = copyChar (cdktemplate->info);
		    cleanChar (cdktemplate->info, cdktemplate->plateLen + 1, '\0');
		    cdktemplate->screenPos = 0;
		    cdktemplate->infoPos = 0;
		    cdktemplate->platePos = 0;
		    drawCDKTemplateField (cdktemplate);
		 }
		 else
		 {
		    Beep();
		 }
		 break;

	    case CDK_COPY:
		 if ((int)strlen(cdktemplate->info) != 0)
		 {
		    freeChar (GPasteBuffer);
		    GPasteBuffer = copyChar (cdktemplate->info);
		 }
		 else
		 {
		    Beep();
		 }
		 break;

	    case CDK_PASTE:
		 if (GPasteBuffer != 0)
		 {
		    /* Clean the informatiob from the field. */
		    cleanChar (cdktemplate->info, cdktemplate->plateLen + 1, '\0');
		    cdktemplate->screenPos = 0;
		    cdktemplate->infoPos = 0;
		    cdktemplate->platePos = 0;

		    /* Start inserting each character one at a time. */
		    length = (int)strlen (GPasteBuffer);
		    for (x=0; x < length; x++)
		    {
		       ((TEMPLATECB)cdktemplate->callbackfn)(cdktemplate, GPasteBuffer[x]);
		    }
		    drawCDKTemplateField (cdktemplate);
		 }
		 else
		 {
		    Beep();
		 }
		 break;

	    case KEY_RETURN : case KEY_TAB : case KEY_ENTER : case KEY_CR :
		 if ((int)strlen(cdktemplate->info) < (int)cdktemplate->min)
		 {
		    Beep();
		 }
		 else
		 {
		    cdktemplate->exitType = vNORMAL;
		    return cdktemplate->info;
		 }
		 break;

	    case KEY_ESC :
		 cdktemplate->exitType = vESCAPE_HIT;
		 return 0;

	    case CDK_REFRESH :
		 eraseCDKScreen (ScreenOf(cdktemplate));
		 refreshCDKScreen (ScreenOf(cdktemplate));
		 break;

	    default :
		 ((TEMPLATECB)cdktemplate->callbackfn)(cdktemplate, input);
		 break;
	 }
      }

      /* Should we call a post-process? */
      if (cdktemplate->postProcessFunction != 0)
      {
	 ((PROCESSFN)(cdktemplate->postProcessFunction)) (vTEMPLATE, cdktemplate, cdktemplate->postProcessData, input);
      }
   }

   /* Set the exit type and return. */
   cdktemplate->exitType = vEARLY_EXIT;
   return 0;
}

/*
 * This is the standard callback proc for the cdktemplate.
 */
static void CDKTemplateCallBack (CDKTEMPLATE *cdktemplate, chtype input)
{
   chtype fieldColor;

   /* Check the character input. */
   if (input == DELETE || input == KEY_BACKSPACE ||
	input == CONTROL('H') || input == KEY_DC)
   {
      /* Make sure we don't go out of bounds. */
      if (cdktemplate->platePos == 0 || cdktemplate->info[0] == '\0')
      {
	 Beep();
	 return;
      }

      /* Remove it and redisplay.... */
      cdktemplate->info[--cdktemplate->infoPos] = '\0';
      cdktemplate->platePos--;
      cdktemplate->screenPos--;

      /* Move the cursor */
      fieldColor = cdktemplate->overlay[cdktemplate->screenPos] & A_ATTRIBUTES;
      adjustCDKTemplateCursor (cdktemplate, -1);
      mvwaddch (cdktemplate->fieldWin, 0, cdktemplate->screenPos,
		cdktemplate->overlay[cdktemplate->platePos] | fieldColor);
      adjustCDKTemplateCursor (cdktemplate, -1);
   }
   else
   {
      /* To be safe, we should cast the chtype to a char */
      char newchar = (char)input;

      /* Make sure we don't go out of bounds. */
      if (cdktemplate->platePos >= cdktemplate->fieldWidth)
      {
	 Beep();
	 return;
      }

      /* We should check to see if what they typed in matches */
      /* what the plate states. */
      if (isdigit((int)newchar) && (
		cdktemplate->plate[cdktemplate->platePos] == 'A' ||
		cdktemplate->plate[cdktemplate->platePos] == 'C' ||
		cdktemplate->plate[cdktemplate->platePos] == 'c'))
      {
	 Beep();
	 return;
      }
      if (!isdigit ((int)newchar) &&
		cdktemplate->plate[cdktemplate->platePos] == '#')
      {
	 Beep();
	 return;
      }

      /* Do we need to convert the case??? */
      if (cdktemplate->plate[cdktemplate->platePos] == 'C' ||
		cdktemplate->plate[cdktemplate->platePos] == 'X')
      {
	 if (isascii ((int)newchar) && islower ((int)newchar))
	 {
	    newchar = toupper ((int)newchar);
	 }
      }
      else if (cdktemplate->plate[cdktemplate->platePos] == 'c' ||
		cdktemplate->plate[cdktemplate->platePos] == 'x')
      {
	 if (isascii ((int)newchar) && isupper ((int)newchar))
	 {
	    newchar = tolower ((int)newchar);
	 }
      }

      /* Add it and redisplay.... */
      fieldColor = cdktemplate->overlay[cdktemplate->screenPos] & A_ATTRIBUTES;
      cdktemplate->info[cdktemplate->infoPos++] = newchar;
      cdktemplate->info[cdktemplate->infoPos] = '\0';
      mvwaddch (cdktemplate->fieldWin, 0, cdktemplate->screenPos,
			newchar | fieldColor);
      cdktemplate->platePos++;
      cdktemplate->screenPos++;

      /* Move the cursor */
      adjustCDKTemplateCursor (cdktemplate, +1);
   }
   wnoutrefresh (cdktemplate->fieldWin);
   wnoutrefresh (cdktemplate->win); 
}

/*
 * This takes the overlay and the info, and mixes the two, for a
 * 'mixed' character string...
 */
char *mixCDKTemplate (CDKTEMPLATE *cdktemplate)
{
   /* Reconstruct the info. */
   char *mixedString	= 0;
   int platePos		= 0;
   int infoPos		= 0;

   /* Make some room for the mixed string. */
   mixedString = (char *) malloc ((sizeof (char) * cdktemplate->plateLen) + 3);
   cleanChar (mixedString, cdktemplate->plateLen + 3, '\0');

   /* Start copying from the plate to the destination string. */
   while (platePos < cdktemplate->plateLen)
   {
      if (isPlateChar(cdktemplate->plate[platePos]))
      {
	 mixedString[platePos]	= cdktemplate->info[infoPos++];
      }
      else
      {
	 mixedString[platePos]	= cdktemplate->plate[platePos];
      }
      platePos++;
   }

   /* Return the new string. */
   return mixedString;
}

/*
 * This takes a mixed string and returns a non-mixed string.
 */
char *unmixCDKTemplate (CDKTEMPLATE *cdktemplate, char *info)
{
   /* Reconstruct the info. */
   char *unmixedString	= 0;
   int infolen		= (int)strlen (info);
   int x		= 0;
   int pos		= 0;

   /* Create a char * pointer. */
   unmixedString	= (char *)malloc (sizeof(char) * (infolen + 2));
   cleanChar (unmixedString, infolen + 2, '\0');

   /* Start copying. */
   while (pos < infolen)
   {
      if (isPlateChar(cdktemplate->plate[pos]))
      {
	 unmixedString[x++] = info[pos++];
      }
      else
      {
	 pos++;
      }
   }

   /* Return the new string. */
   return unmixedString;
}

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

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

   /* Adjust the window if we need to. */
   alignxy (WindowOf(cdktemplate), &xplace, &yplace, cdktemplate->boxWidth, cdktemplate->boxHeight);

   /* Move the window to the new location. */
   moveCursesWindow(cdktemplate->win, xplace, yplace);

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

/*
 * This function draws the tmeplate widget.
 */
static void _drawCDKTemplate (CDKOBJS *object, boolean Box)
{
   CDKTEMPLATE *cdktemplate = (CDKTEMPLATE *)object;
   int x;

   /* Box it if needed */
   if (Box)
   {
      attrbox (cdktemplate->win,
		cdktemplate->ULChar, cdktemplate->URChar,
		cdktemplate->LLChar, cdktemplate->LRChar,
		cdktemplate->HChar,  cdktemplate->VChar,
		cdktemplate->BoxAttrib,
		cdktemplate->shadow);
   }

   if (cdktemplate->titleLines > 0)
   {
      /* Draw in the title if there is one. */
      for (x=0; x < cdktemplate->titleLines; x++)
      {
	 writeChtype (cdktemplate->titleWin,
			cdktemplate->titlePos[x], x,
			cdktemplate->title[x],
			HORIZONTAL, 0,
			cdktemplate->titleLen[x]);
      }
      wnoutrefresh (cdktemplate->titleWin);
   }

   /* Draw the cdktemplate field. */
   drawCDKTemplateField (cdktemplate);
}

/*
 * This draws the cdktemplate field.
 */
static void drawCDKTemplateField (CDKTEMPLATE *cdktemplate)
{
   /* Declare local variables. */
   chtype fieldColor	= 0;
   int infolen		= (int)strlen (cdktemplate->info);
   int x		= 0;

   /* Draw in the label and the cdktemplate object. */
   if (cdktemplate->label != 0)
   {
      writeChtype (cdktemplate->labelWin,
			0, 0,
			cdktemplate->label,
			HORIZONTAL, 0,
			cdktemplate->labelLen);
      wnoutrefresh (cdktemplate->labelWin);
   }

   /* Draw in the cdktemplate... */
   if (cdktemplate->overlay != 0)
   {
      writeChtype (cdktemplate->fieldWin,
			0, 0,
			cdktemplate->overlay,
			HORIZONTAL, 0,
			cdktemplate->overlayLen);
   }

   /* Adjust the cursor. */
   if (infolen != 0)
   {
      int pos	= 0;
      for (x=0; x < cdktemplate->fieldWidth; x++)
      {
	 if (isPlateChar(cdktemplate->plate[x]) && pos < infolen)
	 {
	    fieldColor = cdktemplate->overlay[x] & A_ATTRIBUTES;
	    mvwaddch (cdktemplate->fieldWin,
			0, x,
			cdktemplate->info[pos++]|fieldColor);
	 }
      }
      wmove (cdktemplate->fieldWin, 0, cdktemplate->screenPos);
   }
   else
   {
      adjustCDKTemplateCursor (cdktemplate, +1);
   }
   wnoutrefresh (cdktemplate->fieldWin);
   wnoutrefresh (cdktemplate->win);
}

/*
 * This function adjusts the cursor for the cdktemplate.
 */
static void adjustCDKTemplateCursor (CDKTEMPLATE *cdktemplate, int direction)
{
   while (!isPlateChar(cdktemplate->plate[cdktemplate->platePos])
      &&  cdktemplate->platePos < cdktemplate->fieldWidth)
   {
      cdktemplate->platePos += direction;
      cdktemplate->screenPos += direction;
   }
   wmove (cdktemplate->fieldWin, 0, cdktemplate->screenPos);
}

/*
 * These functions set the drawing characters of the widget.
 */
void setCDKTemplateULChar (CDKTEMPLATE *cdktemplate, chtype character)
{
   cdktemplate->ULChar = character;
}
void setCDKTemplateURChar (CDKTEMPLATE *cdktemplate, chtype character)
{
   cdktemplate->URChar = character;
}
void setCDKTemplateLLChar (CDKTEMPLATE *cdktemplate, chtype character)
{
   cdktemplate->LLChar = character;
}
void setCDKTemplateLRChar (CDKTEMPLATE *cdktemplate, chtype character)
{
   cdktemplate->LRChar = character;
}
void setCDKTemplateVerticalChar (CDKTEMPLATE *cdktemplate, chtype character)
{
   cdktemplate->VChar = character;
}
void setCDKTemplateHorizontalChar (CDKTEMPLATE *cdktemplate, chtype character)
{
   cdktemplate->HChar = character;
}
void setCDKTemplateBoxAttribute (CDKTEMPLATE *cdktemplate, chtype character)
{
   cdktemplate->BoxAttrib = character;
}

/*
 * This sets the background color of the widget.
 */
void setCDKTemplateBackgroundColor (CDKTEMPLATE *cdktemplate, char *color)
{
   chtype *holder = 0;
   int junk1, junk2;

   /* Make sure the color isn't null. */
   if (color == 0)
   {
      return;
   }

   /* Convert the value of the environment variable to a chtype. */
   holder = char2Chtype (color, &junk1, &junk2);

   /* Set the widgets background color. */
   wbkgd (cdktemplate->win, holder[0]);
   wbkgd (cdktemplate->fieldWin, holder[0]);
   if (cdktemplate->labelWin != 0)
   {
      wbkgd (cdktemplate->labelWin, holder[0]);
   }

   /* Clean up. */
   freeChtype (holder);
}

/*
 * This function destroys this widget.
 */
void destroyCDKTemplate (CDKTEMPLATE *cdktemplate)
{
   int x;

   /* Erase the object. */
   eraseCDKTemplate (cdktemplate);

   /* Clear out the character pointers. */
   freeChtype (cdktemplate->label);
   freeChtype (cdktemplate->overlay);
   freeChar (cdktemplate->plate);
   freeChar (cdktemplate->info);
   for (x=0; x < cdktemplate->titleLines; x++)
   {
      freeChtype (cdktemplate->title[x]);
   }

   /* Delete the windows. */
   deleteCursesWindow (cdktemplate->win);

   /* Unregister this object. */
   unregisterCDKObject (vTEMPLATE, cdktemplate);

   /* Finish cleaning up. */
   free (cdktemplate);
}

/*
 * This function erases the widget.
 */
static void _eraseCDKTemplate (CDKOBJS *object)
{
   CDKTEMPLATE *cdktemplate = (CDKTEMPLATE *)object;

   eraseCursesWindow (cdktemplate->win);
}

/*
 * This function sets the value given to the cdktemplate.
 */
void setCDKTemplate (CDKTEMPLATE *cdktemplate, char *newValue, boolean Box)
{
   setCDKTemplateValue (cdktemplate, newValue);
   setCDKTemplateBox (cdktemplate, Box);
}

/*
 * This function sets the value given to the cdktemplate.
 */
void setCDKTemplateValue (CDKTEMPLATE *cdktemplate, char *newValue)
{
   /* Declare local variables. */
   int len		= 0;
   int copychars	= 0;
   int x;

   /* Just to be sure, if let's make sure the new value isn't null. */
   if (newValue == 0)
   {
      /* Then we want to just erase the old value. */
      cleanChar (cdktemplate->info, cdktemplate->fieldWidth, '\0');

      /* Set the cursor place values. */
      cdktemplate->screenPos = 0;
      cdktemplate->platePos = 0;
      cdktemplate->infoPos = 0;
      return;
   }

   /* Determine how many characters we need to copy. */
   len		= (int)strlen (newValue);
   copychars	= MINIMUM (len, cdktemplate->fieldWidth);

   /* OK, erase the old value, and copy in the new value. */
   cleanChar (cdktemplate->info, cdktemplate->fieldWidth, '\0');
   strncpy (cdktemplate->info, newValue, copychars);

   /* Use the function which handles the input of the characters. */
   for (x=0; x < len; x++)
   {
      ((TEMPLATECB)cdktemplate->callbackfn)(cdktemplate, (chtype)newValue[x]);
   }
}
char *getCDKTemplateValue (CDKTEMPLATE *cdktemplate)
{
   return cdktemplate->info;
}

/*
 * This sets the minimum number of characters to enter into the widget.
 */
void setCDKTemplateMin (CDKTEMPLATE *cdktemplate, int min)
{
   if (min >= 0)
   {
      cdktemplate->min = min;
   }
}
int getCDKTemplateMin (CDKTEMPLATE *cdktemplate)
{
   return cdktemplate->min;
}

/*
 * This sets the box attribute of the cdktemplate widget.
 */
void setCDKTemplateBox (CDKTEMPLATE *cdktemplate, boolean Box)
{
   ObjOf(cdktemplate)->box = Box;
}
boolean getCDKTemplateBox (CDKTEMPLATE *cdktemplate)
{
   return ObjOf(cdktemplate)->box;
}

/*
 * This erases the information in the cdktemplate widget.
 */
void cleanCDKTemplate (CDKTEMPLATE *cdktemplate)
{
   cleanChar (cdktemplate->info, cdktemplate->fieldWidth, '\0');
}

/*
 * This function sets the callback function for the widget.
 */
void setCDKTemplateCB (CDKTEMPLATE *cdktemplate, TEMPLATECB callback)
{
   cdktemplate->callbackfn = (void *)callback;
}

/*
 * This function sets the pre-process function.
 */
void setCDKTemplatePreProcess (CDKTEMPLATE *cdktemplate, PROCESSFN callback, void *data)
{
   cdktemplate->preProcessFunction = callback;
   cdktemplate->preProcessData = data;
}

/*
 * This function sets the post-process function.
 */
void setCDKTemplatePostProcess (CDKTEMPLATE *cdktemplate, PROCESSFN callback, void *data)
{
   cdktemplate->postProcessFunction = callback;
   cdktemplate->postProcessData = data;
}