ncurses 5.7 - patch 20091107
[ncurses.git] / form / frm_driver.c
index 354bace8b4f38896cc400c134cb9e1088971586d..e919163edecb9a04e127893d77be961d6abeb467 100644 (file)
@@ -1,5 +1,5 @@
 /****************************************************************************
- * Copyright (c) 1998-2005,2006 Free Software Foundation, Inc.              *
+ * Copyright (c) 1998-2008,2009 Free Software Foundation, Inc.              *
  *                                                                          *
  * Permission is hereby granted, free of charge, to any person obtaining a  *
  * copy of this software and associated documentation files (the            *
@@ -32,7 +32,7 @@
 
 #include "form.priv.h"
 
-MODULE_ID("$Id: frm_driver.c,v 1.76 2006/11/04 18:45:35 tom Exp $")
+MODULE_ID("$Id: frm_driver.c,v 1.94 2009/11/07 19:54:03 tom Exp $")
 
 /*----------------------------------------------------------------------------
   This is the core module of the form library. It contains the majority
@@ -188,7 +188,7 @@ static int FE_Delete_Previous(FORM *);
 /* Macro to set the attributes for a fields window */
 #define Set_Field_Window_Attributes(field,win) \
 (  wbkgdset((win),(chtype)((field)->pad | (field)->back)), \
-   wattrset((win),(field)->fore) )
+   (void) wattrset((win),(field)->fore) )
 
 /* Logic to decide whether or not a field really appears on the form */
 #define Field_Really_Appears(field)         \
@@ -262,7 +262,19 @@ wins_wchnstr(WINDOW *w, cchar_t *s, int n)
 static int
 fix_wchnstr(WINDOW *w, cchar_t *s, int n)
 {
+  int x;
+
   win_wchnstr(w, s, n);
+  /*
+   * This function is used to extract the text only from the window.
+   * Strip attributes and color from the string so they will not be added
+   * back when copying the string to the window.
+   */
+  for (x = 0; x < n; ++x)
+    {
+      RemAttr(s[x], A_ATTRIBUTES);
+      SetPair(s[x], 0);
+    }
   return n;
 }
 
@@ -500,9 +512,10 @@ Buffer_To_Window(const FIELD *field, WINDOW *win)
 
 /*---------------------------------------------------------------------------
 |   Facility      :  libnform
-|   Function      :  static void Window_To_Buffer(
+|   Function      :  void _nc_get_fieldbuffer(
 |                                          WINDOW * win,
-|                                          FIELD  * field)
+|                                          FIELD  * field,
+|                                          FIELD_CELL * buf)
 |
 |   Description   :  Copy the content of the window into the buffer.
 |                    The multiple lines of a window are simply
@@ -511,18 +524,22 @@ Buffer_To_Window(const FIELD *field, WINDOW *win)
 |
 |   Return Values :  -
 +--------------------------------------------------------------------------*/
-static void
-Window_To_Buffer(WINDOW *win, FIELD *field)
+NCURSES_EXPORT(void)
+_nc_get_fieldbuffer(FORM *form, FIELD *field, FIELD_CELL *buf)
 {
   int pad;
   int len = 0;
   FIELD_CELL *p;
   int row, height;
+  WINDOW *win;
+
+  assert(form && field && buf);
 
-  assert(win && field && field->buf);
+  win = form->w;
+  assert(win);
 
   pad = field->pad;
-  p = field->buf;
+  p = buf;
   height = getmaxy(win);
 
   for (row = 0; (row < height) && (row < field->drows); row++)
@@ -549,6 +566,25 @@ Window_To_Buffer(WINDOW *win, FIELD *field)
     }
 }
 
+/*---------------------------------------------------------------------------
+|   Facility      :  libnform
+|   Function      :  static void Window_To_Buffer(
+|                                          FORM   * form,
+|                                          FIELD  * field)
+|
+|   Description   :  Copy the content of the window into the buffer.
+|                    The multiple lines of a window are simply
+|                    concatenated into the buffer. Pad characters in
+|                    the window will be replaced by blanks in the buffer.
+|
+|   Return Values :  -
++--------------------------------------------------------------------------*/
+static void
+Window_To_Buffer(FORM *form, FIELD *field)
+{
+  _nc_get_fieldbuffer(form, field, field->buf);
+}
+
 /*---------------------------------------------------------------------------
 |   Facility      :  libnform
 |   Function      :  static void Synchronize_Buffer(FORM * form)
@@ -567,7 +603,7 @@ Synchronize_Buffer(FORM *form)
     {
       form->status &= ~_WINDOW_MODIFIED;
       form->status |= _FCHECK_REQUIRED;
-      Window_To_Buffer(form->w, form->current);
+      Window_To_Buffer(form, form->current);
       wmove(form->w, form->currow, form->curcol);
     }
 }
@@ -651,6 +687,7 @@ Field_Grown(FIELD *field, int amount)
 
          result = TRUE;        /* allow sharing of recovery on failure */
 
+         T((T_CREATE("fieldcell %p"), (void *)newbuf));
          field->buf = newbuf;
          for (i = 0; i <= field->nbuf; i++)
            {
@@ -663,7 +700,7 @@ Field_Grown(FIELD *field, int amount)
              new_bp[new_buflen] = myZEROS;
            }
 
-#if USE_WIDEC_SUPPORT
+#if USE_WIDEC_SUPPORT && NCURSES_EXT_FUNCS
          if (wresize(field->working, 1, Buffer_Length(field) + 1) == ERR)
            result = FALSE;
 #endif
@@ -724,6 +761,34 @@ Field_Grown(FIELD *field, int amount)
   return (result);
 }
 
+#ifdef NCURSES_MOUSE_VERSION
+/*---------------------------------------------------------------------------
+|   Facility      :  libnform
+|   Function      :  int Field_encloses(FIELD *field, int ry, int rx)
+|
+|   Description   :  Check if the given coordinates lie within the given field.
+|
+|   Return Values :  E_OK              - success
+|                    E_BAD_ARGUMENT    - invalid form pointer
+|                    E_SYSTEM_ERROR    - form has no current field or
+|                                        field-window
++--------------------------------------------------------------------------*/
+static int
+Field_encloses(FIELD *field, int ry, int rx)
+{
+  T((T_CALLED("Field_encloses(%p)"), (void *)field));
+  if (field != 0
+      && field->frow <= ry
+      && (field->frow + field->rows) > ry
+      && field->fcol <= rx
+      && (field->fcol + field->cols) > rx)
+    {
+      RETURN(E_OK);
+    }
+  RETURN(E_INVALID_FIELD);
+}
+#endif
+
 /*---------------------------------------------------------------------------
 |   Facility      :  libnform
 |   Function      :  int _nc_Position_Form_Cursor(FORM * form)
@@ -784,7 +849,7 @@ _nc_Refresh_Current_Field(FORM *form)
   WINDOW *formwin;
   FIELD *field;
 
-  T((T_CALLED("_nc_Refresh_Current_Field(%p)"), form));
+  T((T_CALLED("_nc_Refresh_Current_Field(%p)"), (void *)form));
 
   if (!form)
     RETURN(E_BAD_ARGUMENT);
@@ -969,7 +1034,8 @@ Undo_Justification(FIELD *field, WINDOW *win)
 
 /*---------------------------------------------------------------------------
 |   Facility      :  libnform
-|   Function      :  static bool Check_Char(
+|   Function      :  static bool Check_Char(FORM  *form,
+|                                           FIELD *field,
 |                                           FIELDTYPE * typ,
 |                                           int ch,
 |                                           TypeArgument *argp)
@@ -981,7 +1047,11 @@ Undo_Justification(FIELD *field, WINDOW *win)
 |                    FALSE            - Character is invalid
 +--------------------------------------------------------------------------*/
 static bool
-Check_Char(FIELDTYPE *typ, int ch, TypeArgument *argp)
+Check_Char(FORM *form,
+          FIELD *field,
+          FIELDTYPE *typ,
+          int ch,
+          TypeArgument *argp)
 {
   if (typ)
     {
@@ -989,13 +1059,23 @@ Check_Char(FIELDTYPE *typ, int ch, TypeArgument *argp)
        {
          assert(argp);
          return (
-                  Check_Char(typ->left, ch, argp->left) ||
-                  Check_Char(typ->right, ch, argp->right));
+                  Check_Char(form, field, typ->left, ch, argp->left) ||
+                  Check_Char(form, field, typ->right, ch, argp->right));
        }
       else
        {
+#if NCURSES_INTEROP_FUNCS
+         if (typ->charcheck.occheck)
+           {
+             if (typ->status & _GENERIC)
+               return typ->charcheck.gccheck(ch, form, field, (void *)argp);
+             else
+               return typ->charcheck.occheck(ch, (void *)argp);
+           }
+#else
          if (typ->ccheck)
            return typ->ccheck(ch, (void *)argp);
+#endif
        }
     }
   return (!iscntrl(UChar(ch)) ? TRUE : FALSE);
@@ -1032,9 +1112,13 @@ Display_Or_Erase_Field(FIELD *field, bool bEraseFlag)
   else
     {
       if (field->opts & O_VISIBLE)
-       Set_Field_Window_Attributes(field, win);
+       {
+         Set_Field_Window_Attributes(field, win);
+       }
       else
-       wattrset(win, WINDOW_ATTRS(fwin));
+       {
+         (void)wattrset(win, WINDOW_ATTRS(fwin));
+       }
       werase(win);
     }
 
@@ -1156,7 +1240,7 @@ _nc_Synchronize_Attributes(FIELD *field)
   int res = E_OK;
   WINDOW *formwin;
 
-  T((T_CALLED("_nc_Synchronize_Attributes(%p)"), field));
+  T((T_CALLED("_nc_Synchronize_Attributes(%p)"), (void *)field));
 
   if (!field)
     returnCode(E_BAD_ARGUMENT);
@@ -1223,7 +1307,7 @@ _nc_Synchronize_Options(FIELD *field, Field_Options newopts)
   FORM *form;
   int res = E_OK;
 
-  T((T_CALLED("_nc_Synchronize_Options(%p,%#x)"), field, newopts));
+  T((T_CALLED("_nc_Synchronize_Options(%p,%#x)"), (void *)field, newopts));
 
   if (!field)
     returnCode(E_BAD_ARGUMENT);
@@ -1235,14 +1319,13 @@ _nc_Synchronize_Options(FIELD *field, Field_Options newopts)
 
   if (form)
     {
-      if (form->current == field)
-       {
-         field->opts = oldopts;
-         returnCode(E_CURRENT);
-       }
-
       if (form->status & _POSTED)
        {
+         if (form->current == field)
+           {
+             field->opts = oldopts;
+             returnCode(E_CURRENT);
+           }
          if ((form->curpage == field->page))
            {
              if (changed_opts & O_VISIBLE)
@@ -1324,7 +1407,7 @@ _nc_Set_Current_Field(FORM *form, FIELD *newfield)
   FIELD *field;
   WINDOW *new_window;
 
-  T((T_CALLED("_nc_Set_Current_Field(%p,%p)"), form, newfield));
+  T((T_CALLED("_nc_Set_Current_Field(%p,%p)"), (void *)form, (void *)newfield));
 
   if (!form || !newfield || !form->current || (newfield->form != form))
     returnCode(E_BAD_ARGUMENT);
@@ -1358,7 +1441,7 @@ _nc_Set_Current_Field(FORM *form, FIELD *newfield)
                {
                  if (Justification_Allowed(field))
                    {
-                     Window_To_Buffer(form->w, field);
+                     Window_To_Buffer(form, field);
                      werase(form->w);
                      Perform_Justification(field, form->w);
                      wsyncup(form->w);
@@ -1431,7 +1514,7 @@ IFN_Next_Character(FORM *form)
   FIELD *field = form->current;
   int step = myWCWIDTH(form->w, form->currow, form->curcol);
 
-  T((T_CALLED("IFN_Next_Character(%p)"), form));
+  T((T_CALLED("IFN_Next_Character(%p)"), (void *)form));
   if ((form->curcol += step) == field->dcols)
     {
       if ((++(form->currow)) == field->drows)
@@ -1473,7 +1556,7 @@ IFN_Previous_Character(FORM *form)
   int amount = myWCWIDTH(form->w, form->currow, form->curcol - 1);
   int oldcol = form->curcol;
 
-  T((T_CALLED("IFN_Previous_Character(%p)"), form));
+  T((T_CALLED("IFN_Previous_Character(%p)"), (void *)form));
   if ((form->curcol -= amount) < 0)
     {
       if ((--(form->currow)) < 0)
@@ -1501,7 +1584,7 @@ IFN_Next_Line(FORM *form)
 {
   FIELD *field = form->current;
 
-  T((T_CALLED("IFN_Next_Line(%p)"), form));
+  T((T_CALLED("IFN_Next_Line(%p)"), (void *)form));
   if ((++(form->currow)) == field->drows)
     {
 #if GROW_IF_NAVIGATE
@@ -1527,7 +1610,7 @@ IFN_Next_Line(FORM *form)
 static int
 IFN_Previous_Line(FORM *form)
 {
-  T((T_CALLED("IFN_Previous_Line(%p)"), form));
+  T((T_CALLED("IFN_Previous_Line(%p)"), (void *)form));
   if ((--(form->currow)) < 0)
     {
       form->currow++;
@@ -1554,7 +1637,7 @@ IFN_Next_Word(FORM *form)
   FIELD_CELL *s;
   FIELD_CELL *t;
 
-  T((T_CALLED("IFN_Next_Word(%p)"), form));
+  T((T_CALLED("IFN_Next_Word(%p)"), (void *)form));
 
   /* We really need access to the data, so we have to synchronize */
   Synchronize_Buffer(form);
@@ -1597,7 +1680,7 @@ IFN_Previous_Word(FORM *form)
   FIELD_CELL *t;
   bool again = FALSE;
 
-  T((T_CALLED("IFN_Previous_Word(%p)"), form));
+  T((T_CALLED("IFN_Previous_Word(%p)"), (void *)form));
 
   /* We really need access to the data, so we have to synchronize */
   Synchronize_Buffer(form);
@@ -1647,7 +1730,7 @@ IFN_Beginning_Of_Field(FORM *form)
 {
   FIELD *field = form->current;
 
-  T((T_CALLED("IFN_Beginning_Of_Field(%p)"), form));
+  T((T_CALLED("IFN_Beginning_Of_Field(%p)"), (void *)form));
   Synchronize_Buffer(form);
   Adjust_Cursor_Position(form,
                         Get_Start_Of_Data(field->buf, Buffer_Length(field)));
@@ -1671,7 +1754,7 @@ IFN_End_Of_Field(FORM *form)
   FIELD *field = form->current;
   FIELD_CELL *pos;
 
-  T((T_CALLED("IFN_End_Of_Field(%p)"), form));
+  T((T_CALLED("IFN_End_Of_Field(%p)"), (void *)form));
   Synchronize_Buffer(form);
   pos = After_End_Of_Data(field->buf, Buffer_Length(field));
   if (pos == (field->buf + Buffer_Length(field)))
@@ -1694,7 +1777,7 @@ IFN_Beginning_Of_Line(FORM *form)
 {
   FIELD *field = form->current;
 
-  T((T_CALLED("IFN_Beginning_Of_Line(%p)"), form));
+  T((T_CALLED("IFN_Beginning_Of_Line(%p)"), (void *)form));
   Synchronize_Buffer(form);
   Adjust_Cursor_Position(form,
                         Get_Start_Of_Data(Address_Of_Current_Row_In_Buffer(form),
@@ -1720,7 +1803,7 @@ IFN_End_Of_Line(FORM *form)
   FIELD_CELL *pos;
   FIELD_CELL *bp;
 
-  T((T_CALLED("IFN_End_Of_Line(%p)"), form));
+  T((T_CALLED("IFN_End_Of_Line(%p)"), (void *)form));
   Synchronize_Buffer(form);
   bp = Address_Of_Current_Row_In_Buffer(form);
   pos = After_End_Of_Data(bp, field->dcols);
@@ -1746,7 +1829,7 @@ IFN_Left_Character(FORM *form)
   int amount = myWCWIDTH(form->w, form->currow, form->curcol - 1);
   int oldcol = form->curcol;
 
-  T((T_CALLED("IFN_Left_Character(%p)"), form));
+  T((T_CALLED("IFN_Left_Character(%p)"), (void *)form));
   if ((form->curcol -= amount) < 0)
     {
       form->curcol = oldcol;
@@ -1771,7 +1854,7 @@ IFN_Right_Character(FORM *form)
   int amount = myWCWIDTH(form->w, form->currow, form->curcol);
   int oldcol = form->curcol;
 
-  T((T_CALLED("IFN_Right_Character(%p)"), form));
+  T((T_CALLED("IFN_Right_Character(%p)"), (void *)form));
   if ((form->curcol += amount) >= form->current->dcols)
     {
 #if GROW_IF_NAVIGATE
@@ -1799,7 +1882,7 @@ IFN_Right_Character(FORM *form)
 static int
 IFN_Up_Character(FORM *form)
 {
-  T((T_CALLED("IFN_Up_Character(%p)"), form));
+  T((T_CALLED("IFN_Up_Character(%p)"), (void *)form));
   if ((--(form->currow)) < 0)
     {
       form->currow++;
@@ -1823,7 +1906,7 @@ IFN_Down_Character(FORM *form)
 {
   FIELD *field = form->current;
 
-  T((T_CALLED("IFN_Down_Character(%p)"), form));
+  T((T_CALLED("IFN_Down_Character(%p)"), (void *)form));
   if ((++(form->currow)) == field->drows)
     {
 #if GROW_IF_NAVIGATE
@@ -1932,7 +2015,7 @@ Vertical_Scrolling(int (*const fct) (FORM *), FORM *form)
 static int
 VSC_Scroll_Line_Forward(FORM *form)
 {
-  T((T_CALLED("VSC_Scroll_Line_Forward(%p)"), form));
+  T((T_CALLED("VSC_Scroll_Line_Forward(%p)"), (void *)form));
   returnCode(VSC_Generic(form, 1));
 }
 
@@ -1948,7 +2031,7 @@ VSC_Scroll_Line_Forward(FORM *form)
 static int
 VSC_Scroll_Line_Backward(FORM *form)
 {
-  T((T_CALLED("VSC_Scroll_Line_Backward(%p)"), form));
+  T((T_CALLED("VSC_Scroll_Line_Backward(%p)"), (void *)form));
   returnCode(VSC_Generic(form, -1));
 }
 
@@ -1964,7 +2047,7 @@ VSC_Scroll_Line_Backward(FORM *form)
 static int
 VSC_Scroll_Page_Forward(FORM *form)
 {
-  T((T_CALLED("VSC_Scroll_Page_Forward(%p)"), form));
+  T((T_CALLED("VSC_Scroll_Page_Forward(%p)"), (void *)form));
   returnCode(VSC_Generic(form, form->current->rows));
 }
 
@@ -1980,7 +2063,7 @@ VSC_Scroll_Page_Forward(FORM *form)
 static int
 VSC_Scroll_Half_Page_Forward(FORM *form)
 {
-  T((T_CALLED("VSC_Scroll_Half_Page_Forward(%p)"), form));
+  T((T_CALLED("VSC_Scroll_Half_Page_Forward(%p)"), (void *)form));
   returnCode(VSC_Generic(form, (form->current->rows + 1) / 2));
 }
 
@@ -1996,7 +2079,7 @@ VSC_Scroll_Half_Page_Forward(FORM *form)
 static int
 VSC_Scroll_Page_Backward(FORM *form)
 {
-  T((T_CALLED("VSC_Scroll_Page_Backward(%p)"), form));
+  T((T_CALLED("VSC_Scroll_Page_Backward(%p)"), (void *)form));
   returnCode(VSC_Generic(form, -(form->current->rows)));
 }
 
@@ -2012,7 +2095,7 @@ VSC_Scroll_Page_Backward(FORM *form)
 static int
 VSC_Scroll_Half_Page_Backward(FORM *form)
 {
-  T((T_CALLED("VSC_Scroll_Half_Page_Backward(%p)"), form));
+  T((T_CALLED("VSC_Scroll_Half_Page_Backward(%p)"), (void *)form));
   returnCode(VSC_Generic(form, -((form->current->rows + 1) / 2)));
 }
 /*----------------------------------------------------------------------------
@@ -2106,7 +2189,7 @@ Horizontal_Scrolling(int (*const fct) (FORM *), FORM *form)
 static int
 HSC_Scroll_Char_Forward(FORM *form)
 {
-  T((T_CALLED("HSC_Scroll_Char_Forward(%p)"), form));
+  T((T_CALLED("HSC_Scroll_Char_Forward(%p)"), (void *)form));
   returnCode(HSC_Generic(form, 1));
 }
 
@@ -2122,7 +2205,7 @@ HSC_Scroll_Char_Forward(FORM *form)
 static int
 HSC_Scroll_Char_Backward(FORM *form)
 {
-  T((T_CALLED("HSC_Scroll_Char_Backward(%p)"), form));
+  T((T_CALLED("HSC_Scroll_Char_Backward(%p)"), (void *)form));
   returnCode(HSC_Generic(form, -1));
 }
 
@@ -2138,7 +2221,7 @@ HSC_Scroll_Char_Backward(FORM *form)
 static int
 HSC_Horizontal_Line_Forward(FORM *form)
 {
-  T((T_CALLED("HSC_Horizontal_Line_Forward(%p)"), form));
+  T((T_CALLED("HSC_Horizontal_Line_Forward(%p)"), (void *)form));
   returnCode(HSC_Generic(form, form->current->cols));
 }
 
@@ -2154,7 +2237,7 @@ HSC_Horizontal_Line_Forward(FORM *form)
 static int
 HSC_Horizontal_Half_Line_Forward(FORM *form)
 {
-  T((T_CALLED("HSC_Horizontal_Half_Line_Forward(%p)"), form));
+  T((T_CALLED("HSC_Horizontal_Half_Line_Forward(%p)"), (void *)form));
   returnCode(HSC_Generic(form, (form->current->cols + 1) / 2));
 }
 
@@ -2170,7 +2253,7 @@ HSC_Horizontal_Half_Line_Forward(FORM *form)
 static int
 HSC_Horizontal_Line_Backward(FORM *form)
 {
-  T((T_CALLED("HSC_Horizontal_Line_Backward(%p)"), form));
+  T((T_CALLED("HSC_Horizontal_Line_Backward(%p)"), (void *)form));
   returnCode(HSC_Generic(form, -(form->current->cols)));
 }
 
@@ -2186,7 +2269,7 @@ HSC_Horizontal_Line_Backward(FORM *form)
 static int
 HSC_Horizontal_Half_Line_Backward(FORM *form)
 {
-  T((T_CALLED("HSC_Horizontal_Half_Line_Backward(%p)"), form));
+  T((T_CALLED("HSC_Horizontal_Half_Line_Backward(%p)"), (void *)form));
   returnCode(HSC_Generic(form, -((form->current->cols + 1) / 2)));
 }
 
@@ -2365,7 +2448,7 @@ Wrapping_Not_Necessary_Or_Wrapping_Ok(FORM *form)
            return E_SYSTEM_ERROR;
        }
       bp = Address_Of_Current_Row_In_Buffer(form);
-      Window_To_Buffer(form->w, field);
+      Window_To_Buffer(form, field);
       split = After_Last_Whitespace_Character(bp, field->dcols);
       /* split points to the first character of the sequence to be brought
          on the next line */
@@ -2391,7 +2474,7 @@ Wrapping_Not_Necessary_Or_Wrapping_Ok(FORM *form)
       if (result != E_OK)
        {
          DeleteChar(form);
-         Window_To_Buffer(form->w, field);
+         Window_To_Buffer(form, field);
          result = E_REQUEST_DENIED;
        }
     }
@@ -2482,7 +2565,7 @@ FE_New_Line(FORM *form)
   FIELD_CELL *bp, *t;
   bool Last_Row = ((field->drows - 1) == form->currow);
 
-  T((T_CALLED("FE_New_Line(%p)"), form));
+  T((T_CALLED("FE_New_Line(%p)"), (void *)form));
   if (form->status & _OVLMODE)
     {
       if (Last_Row &&
@@ -2565,8 +2648,9 @@ FE_Insert_Character(FORM *form)
   FIELD *field = form->current;
   int result = E_REQUEST_DENIED;
 
-  T((T_CALLED("FE_Insert_Character(%p)"), form));
-  if (Check_Char(field->type, (int)C_BLANK, (TypeArgument *)(field->arg)))
+  T((T_CALLED("FE_Insert_Character(%p)"), (void *)form));
+  if (Check_Char(form, field, field->type, (int)C_BLANK,
+                (TypeArgument *)(field->arg)))
     {
       bool There_Is_Room = Is_There_Room_For_A_Char_In_Line(form);
 
@@ -2600,8 +2684,9 @@ FE_Insert_Line(FORM *form)
   FIELD *field = form->current;
   int result = E_REQUEST_DENIED;
 
-  T((T_CALLED("FE_Insert_Line(%p)"), form));
-  if (Check_Char(field->type, (int)C_BLANK, (TypeArgument *)(field->arg)))
+  T((T_CALLED("FE_Insert_Line(%p)"), (void *)form));
+  if (Check_Char(form, field,
+                field->type, (int)C_BLANK, (TypeArgument *)(field->arg)))
     {
       bool Maybe_Done = (form->currow != (field->drows - 1)) &&
       Is_There_Room_For_A_Line(form);
@@ -2633,7 +2718,7 @@ FE_Insert_Line(FORM *form)
 static int
 FE_Delete_Character(FORM *form)
 {
-  T((T_CALLED("FE_Delete_Character(%p)"), form));
+  T((T_CALLED("FE_Delete_Character(%p)"), (void *)form));
   DeleteChar(form);
   returnCode(E_OK);
 }
@@ -2656,7 +2741,7 @@ FE_Delete_Previous(FORM *form)
 {
   FIELD *field = form->current;
 
-  T((T_CALLED("FE_Delete_Previous(%p)"), form));
+  T((T_CALLED("FE_Delete_Previous(%p)"), (void *)form));
   if (First_Position_In_Current_Field(form))
     returnCode(E_REQUEST_DENIED);
 
@@ -2724,7 +2809,7 @@ FE_Delete_Previous(FORM *form)
 static int
 FE_Delete_Line(FORM *form)
 {
-  T((T_CALLED("FE_Delete_Line(%p)"), form));
+  T((T_CALLED("FE_Delete_Line(%p)"), (void *)form));
   form->curcol = 0;
   wdeleteln(form->w);
   returnCode(E_OK);
@@ -2748,7 +2833,7 @@ FE_Delete_Word(FORM *form)
   FIELD_CELL *cp = bp + form->curcol;
   FIELD_CELL *s;
 
-  T((T_CALLED("FE_Delete_Word(%p)"), form));
+  T((T_CALLED("FE_Delete_Word(%p)"), (void *)form));
   Synchronize_Buffer(form);
   if (ISBLANK(*cp))
     returnCode(E_REQUEST_DENIED);      /* not in word */
@@ -2782,7 +2867,7 @@ FE_Delete_Word(FORM *form)
 static int
 FE_Clear_To_End_Of_Line(FORM *form)
 {
-  T((T_CALLED("FE_Clear_To_End_Of_Line(%p)"), form));
+  T((T_CALLED("FE_Clear_To_End_Of_Line(%p)"), (void *)form));
   wmove(form->w, form->currow, form->curcol);
   wclrtoeol(form->w);
   returnCode(E_OK);
@@ -2799,7 +2884,7 @@ FE_Clear_To_End_Of_Line(FORM *form)
 static int
 FE_Clear_To_End_Of_Field(FORM *form)
 {
-  T((T_CALLED("FE_Clear_To_End_Of_Field(%p)"), form));
+  T((T_CALLED("FE_Clear_To_End_Of_Field(%p)"), (void *)form));
   wmove(form->w, form->currow, form->curcol);
   wclrtobot(form->w);
   returnCode(E_OK);
@@ -2816,7 +2901,7 @@ FE_Clear_To_End_Of_Field(FORM *form)
 static int
 FE_Clear_Field(FORM *form)
 {
-  T((T_CALLED("FE_Clear_Field(%p)"), form));
+  T((T_CALLED("FE_Clear_Field(%p)"), (void *)form));
   form->currow = form->curcol = 0;
   werase(form->w);
   returnCode(E_OK);
@@ -2840,7 +2925,7 @@ FE_Clear_Field(FORM *form)
 static int
 EM_Overlay_Mode(FORM *form)
 {
-  T((T_CALLED("EM_Overlay_Mode(%p)"), form));
+  T((T_CALLED("EM_Overlay_Mode(%p)"), (void *)form));
   form->status |= _OVLMODE;
   returnCode(E_OK);
 }
@@ -2856,7 +2941,7 @@ EM_Overlay_Mode(FORM *form)
 static int
 EM_Insert_Mode(FORM *form)
 {
-  T((T_CALLED("EM_Insert_Mode(%p)"), form));
+  T((T_CALLED("EM_Insert_Mode(%p)"), (void *)form));
   form->status &= ~_OVLMODE;
   returnCode(E_OK);
 }
@@ -2871,7 +2956,7 @@ EM_Insert_Mode(FORM *form)
 
 /*---------------------------------------------------------------------------
 |   Facility      :  libnform
-|   Function      :  static bool Next_Choice(
+|   Function      :  static bool Next_Choice(FORM * form,
 |                                            FIELDTYPE * typ,
 |                                            FIELD * field,
 |                                            TypeArgument *argp)
@@ -2883,7 +2968,7 @@ EM_Insert_Mode(FORM *form)
 |                    FALSE   - couldn't retrieve next choice
 +--------------------------------------------------------------------------*/
 static bool
-Next_Choice(FIELDTYPE *typ, FIELD *field, TypeArgument *argp)
+Next_Choice(FORM *form, FIELDTYPE *typ, FIELD *field, TypeArgument *argp)
 {
   if (!typ || !(typ->status & _HAS_CHOICE))
     return FALSE;
@@ -2892,19 +2977,27 @@ Next_Choice(FIELDTYPE *typ, FIELD *field, TypeArgument *argp)
     {
       assert(argp);
       return (
-              Next_Choice(typ->left, field, argp->left) ||
-              Next_Choice(typ->right, field, argp->right));
+              Next_Choice(form, typ->left, field, argp->left) ||
+              Next_Choice(form, typ->right, field, argp->right));
     }
   else
     {
+#if NCURSES_INTEROP_FUNCS
+      assert(typ->enum_next.onext);
+      if (typ->status & _GENERIC)
+       return typ->enum_next.gnext(form, field, (void *)argp);
+      else
+       return typ->enum_next.onext(field, (void *)argp);
+#else
       assert(typ->next);
       return typ->next(field, (void *)argp);
+#endif
     }
 }
 
 /*---------------------------------------------------------------------------
 |   Facility      :  libnform
-|   Function      :  static bool Previous_Choice(
+|   Function      :  static bool Previous_Choice(FORM * form,
 |                                                FIELDTYPE * typ,
 |                                                FIELD * field,
 |                                                TypeArgument *argp)
@@ -2916,7 +3009,7 @@ Next_Choice(FIELDTYPE *typ, FIELD *field, TypeArgument *argp)
 |                    FALSE   - couldn't retrieve previous choice
 +--------------------------------------------------------------------------*/
 static bool
-Previous_Choice(FIELDTYPE *typ, FIELD *field, TypeArgument *argp)
+Previous_Choice(FORM *form, FIELDTYPE *typ, FIELD *field, TypeArgument *argp)
 {
   if (!typ || !(typ->status & _HAS_CHOICE))
     return FALSE;
@@ -2925,13 +3018,21 @@ Previous_Choice(FIELDTYPE *typ, FIELD *field, TypeArgument *argp)
     {
       assert(argp);
       return (
-              Previous_Choice(typ->left, field, argp->left) ||
-              Previous_Choice(typ->right, field, argp->right));
+              Previous_Choice(form, typ->left, field, argp->left) ||
+              Previous_Choice(form, typ->right, field, argp->right));
     }
   else
     {
+#if NCURSES_INTEROP_FUNCS
+      assert(typ->enum_prev.oprev);
+      if (typ->status & _GENERIC)
+       return typ->enum_prev.gprev(form, field, (void *)argp);
+      else
+       return typ->enum_prev.oprev(field, (void *)argp);
+#else
       assert(typ->prev);
       return typ->prev(field, (void *)argp);
+#endif
     }
 }
 /*----------------------------------------------------------------------------
@@ -2956,9 +3057,9 @@ CR_Next_Choice(FORM *form)
 {
   FIELD *field = form->current;
 
-  T((T_CALLED("CR_Next_Choice(%p)"), form));
+  T((T_CALLED("CR_Next_Choice(%p)"), (void *)form));
   Synchronize_Buffer(form);
-  returnCode((Next_Choice(field->type, field, (TypeArgument *)(field->arg)))
+  returnCode((Next_Choice(form, field->type, field, (TypeArgument *)(field->arg)))
             ? E_OK
             : E_REQUEST_DENIED);
 }
@@ -2977,9 +3078,9 @@ CR_Previous_Choice(FORM *form)
 {
   FIELD *field = form->current;
 
-  T((T_CALLED("CR_Previous_Choice(%p)"), form));
+  T((T_CALLED("CR_Previous_Choice(%p)"), (void *)form));
   Synchronize_Buffer(form);
-  returnCode((Previous_Choice(field->type, field, (TypeArgument *)(field->arg)))
+  returnCode((Previous_Choice(form, field->type, field, (TypeArgument *)(field->arg)))
             ? E_OK
             : E_REQUEST_DENIED);
 }
@@ -2993,7 +3094,7 @@ CR_Previous_Choice(FORM *form)
 
 /*---------------------------------------------------------------------------
 |   Facility      :  libnform
-|   Function      :  static bool Check_Field(
+|   Function      :  static bool Check_Field(FORM* form,
 |                                            FIELDTYPE * typ,
 |                                            FIELD * field,
 |                                            TypeArgument * argp)
@@ -3006,7 +3107,7 @@ CR_Previous_Choice(FORM *form)
 |                    FALSE      - field is invalid.
 +--------------------------------------------------------------------------*/
 static bool
-Check_Field(FIELDTYPE *typ, FIELD *field, TypeArgument *argp)
+Check_Field(FORM *form, FIELDTYPE *typ, FIELD *field, TypeArgument *argp)
 {
   if (typ)
     {
@@ -3027,13 +3128,23 @@ Check_Field(FIELDTYPE *typ, FIELD *field, TypeArgument *argp)
        {
          assert(argp);
          return (
-                  Check_Field(typ->left, field, argp->left) ||
-                  Check_Field(typ->right, field, argp->right));
+                  Check_Field(form, typ->left, field, argp->left) ||
+                  Check_Field(form, typ->right, field, argp->right));
        }
       else
        {
+#if NCURSES_INTEROP_FUNCS
+         if (typ->fieldcheck.ofcheck)
+           {
+             if (typ->status & _GENERIC)
+               return typ->fieldcheck.gfcheck(form, field, (void *)argp);
+             else
+               return typ->fieldcheck.ofcheck(field, (void *)argp);
+           }
+#else
          if (typ->fcheck)
            return typ->fcheck(field, (void *)argp);
+#endif
        }
     }
   return TRUE;
@@ -3059,7 +3170,7 @@ _nc_Internal_Validation(FORM *form)
   if ((form->status & _FCHECK_REQUIRED) ||
       (!(field->opts & O_PASSOK)))
     {
-      if (!Check_Field(field->type, field, (TypeArgument *)(field->arg)))
+      if (!Check_Field(form, field->type, field, (TypeArgument *)(field->arg)))
        return FALSE;
       form->status &= ~_FCHECK_REQUIRED;
       field->status |= _CHANGED;
@@ -3087,7 +3198,7 @@ _nc_Internal_Validation(FORM *form)
 static int
 FV_Validation(FORM *form)
 {
-  T((T_CALLED("FV_Validation(%p)"), form));
+  T((T_CALLED("FV_Validation(%p)"), (void *)form));
   if (_nc_Internal_Validation(form))
     returnCode(E_OK);
   else
@@ -3465,7 +3576,7 @@ Inter_Field_Navigation(int (*const fct) (FORM *), FORM *form)
 static int
 FN_Next_Field(FORM *form)
 {
-  T((T_CALLED("FN_Next_Field(%p)"), form));
+  T((T_CALLED("FN_Next_Field(%p)"), (void *)form));
   returnCode(_nc_Set_Current_Field(form,
                                   Next_Field_On_Page(form->current)));
 }
@@ -3483,7 +3594,7 @@ FN_Next_Field(FORM *form)
 static int
 FN_Previous_Field(FORM *form)
 {
-  T((T_CALLED("FN_Previous_Field(%p)"), form));
+  T((T_CALLED("FN_Previous_Field(%p)"), (void *)form));
   returnCode(_nc_Set_Current_Field(form,
                                   Previous_Field_On_Page(form->current)));
 }
@@ -3500,7 +3611,7 @@ FN_Previous_Field(FORM *form)
 static int
 FN_First_Field(FORM *form)
 {
-  T((T_CALLED("FN_First_Field(%p)"), form));
+  T((T_CALLED("FN_First_Field(%p)"), (void *)form));
   returnCode(_nc_Set_Current_Field(form,
                                   Next_Field_On_Page(form->field[form->page[form->curpage].pmax])));
 }
@@ -3517,7 +3628,7 @@ FN_First_Field(FORM *form)
 static int
 FN_Last_Field(FORM *form)
 {
-  T((T_CALLED("FN_Last_Field(%p)"), form));
+  T((T_CALLED("FN_Last_Field(%p)"), (void *)form));
   returnCode(
              _nc_Set_Current_Field(form,
                                    Previous_Field_On_Page(form->field[form->page[form->curpage].pmin])));
@@ -3536,7 +3647,7 @@ FN_Last_Field(FORM *form)
 static int
 FN_Sorted_Next_Field(FORM *form)
 {
-  T((T_CALLED("FN_Sorted_Next_Field(%p)"), form));
+  T((T_CALLED("FN_Sorted_Next_Field(%p)"), (void *)form));
   returnCode(_nc_Set_Current_Field(form,
                                   Sorted_Next_Field(form->current)));
 }
@@ -3554,7 +3665,7 @@ FN_Sorted_Next_Field(FORM *form)
 static int
 FN_Sorted_Previous_Field(FORM *form)
 {
-  T((T_CALLED("FN_Sorted_Previous_Field(%p)"), form));
+  T((T_CALLED("FN_Sorted_Previous_Field(%p)"), (void *)form));
   returnCode(_nc_Set_Current_Field(form,
                                   Sorted_Previous_Field(form->current)));
 }
@@ -3572,7 +3683,7 @@ FN_Sorted_Previous_Field(FORM *form)
 static int
 FN_Sorted_First_Field(FORM *form)
 {
-  T((T_CALLED("FN_Sorted_First_Field(%p)"), form));
+  T((T_CALLED("FN_Sorted_First_Field(%p)"), (void *)form));
   returnCode(_nc_Set_Current_Field(form,
                                   Sorted_Next_Field(form->field[form->page[form->curpage].smax])));
 }
@@ -3590,7 +3701,7 @@ FN_Sorted_First_Field(FORM *form)
 static int
 FN_Sorted_Last_Field(FORM *form)
 {
-  T((T_CALLED("FN_Sorted_Last_Field(%p)"), form));
+  T((T_CALLED("FN_Sorted_Last_Field(%p)"), (void *)form));
   returnCode(_nc_Set_Current_Field(form,
                                   Sorted_Previous_Field(form->field[form->page[form->curpage].smin])));
 }
@@ -3608,7 +3719,7 @@ FN_Sorted_Last_Field(FORM *form)
 static int
 FN_Left_Field(FORM *form)
 {
-  T((T_CALLED("FN_Left_Field(%p)"), form));
+  T((T_CALLED("FN_Left_Field(%p)"), (void *)form));
   returnCode(_nc_Set_Current_Field(form,
                                   Left_Neighbor_Field(form->current)));
 }
@@ -3626,7 +3737,7 @@ FN_Left_Field(FORM *form)
 static int
 FN_Right_Field(FORM *form)
 {
-  T((T_CALLED("FN_Right_Field(%p)"), form));
+  T((T_CALLED("FN_Right_Field(%p)"), (void *)form));
   returnCode(_nc_Set_Current_Field(form,
                                   Right_Neighbor_Field(form->current)));
 }
@@ -3646,7 +3757,7 @@ FN_Right_Field(FORM *form)
 static int
 FN_Up_Field(FORM *form)
 {
-  T((T_CALLED("FN_Up_Field(%p)"), form));
+  T((T_CALLED("FN_Up_Field(%p)"), (void *)form));
   returnCode(_nc_Set_Current_Field(form,
                                   Upper_Neighbor_Field(form->current)));
 }
@@ -3666,7 +3777,7 @@ FN_Up_Field(FORM *form)
 static int
 FN_Down_Field(FORM *form)
 {
-  T((T_CALLED("FN_Down_Field(%p)"), form));
+  T((T_CALLED("FN_Down_Field(%p)"), (void *)form));
   returnCode(_nc_Set_Current_Field(form,
                                   Down_Neighbor_Field(form->current)));
 }
@@ -3810,7 +3921,7 @@ Page_Navigation(int (*const fct) (FORM *), FORM *form)
 static int
 PN_Next_Page(FORM *form)
 {
-  T((T_CALLED("PN_Next_Page(%p)"), form));
+  T((T_CALLED("PN_Next_Page(%p)"), (void *)form));
   returnCode(_nc_Set_Form_Page(form, Next_Page_Number(form), (FIELD *)0));
 }
 
@@ -3826,7 +3937,7 @@ PN_Next_Page(FORM *form)
 static int
 PN_Previous_Page(FORM *form)
 {
-  T((T_CALLED("PN_Previous_Page(%p)"), form));
+  T((T_CALLED("PN_Previous_Page(%p)"), (void *)form));
   returnCode(_nc_Set_Form_Page(form, Previous_Page_Number(form), (FIELD *)0));
 }
 
@@ -3842,7 +3953,7 @@ PN_Previous_Page(FORM *form)
 static int
 PN_First_Page(FORM *form)
 {
-  T((T_CALLED("PN_First_Page(%p)"), form));
+  T((T_CALLED("PN_First_Page(%p)"), (void *)form));
   returnCode(_nc_Set_Form_Page(form, 0, (FIELD *)0));
 }
 
@@ -3858,7 +3969,7 @@ PN_First_Page(FORM *form)
 static int
 PN_Last_Page(FORM *form)
 {
-  T((T_CALLED("PN_Last_Page(%p)"), form));
+  T((T_CALLED("PN_Last_Page(%p)"), (void *)form));
   returnCode(_nc_Set_Form_Page(form, form->maxpage - 1, (FIELD *)0));
 }
 
@@ -3887,7 +3998,7 @@ Data_Entry(FORM *form, int c)
   FIELD *field = form->current;
   int result = E_REQUEST_DENIED;
 
-  T((T_CALLED("Data_Entry(%p,%s)"), form, _tracechtype((chtype)c)));
+  T((T_CALLED("Data_Entry(%p,%s)"), (void *)form, _tracechtype((chtype)c)));
   if ((field->opts & O_EDIT)
 #if FIX_FORM_INACTIVE_BUG
       && (field->opts & O_ACTIVE)
@@ -4088,7 +4199,7 @@ form_driver(FORM *form, int c)
   const Binding_Info *BI = (Binding_Info *) 0;
   int res = E_UNKNOWN_COMMAND;
 
-  T((T_CALLED("form_driver(%p,%d)"), form, c));
+  T((T_CALLED("form_driver(%p,%d)"), (void *)form, c));
 
   if (!form)
     RETURN(E_BAD_ARGUMENT);
@@ -4135,7 +4246,7 @@ form_driver(FORM *form, int c)
        NULL                    /* Choice Request is generic           */
       };
       size_t nMethods = (sizeof(Generic_Methods) / sizeof(Generic_Methods[0]));
-      size_t method = ((BI->keycode & ID_Mask) >> ID_Shft) & 0xffff;
+      size_t method = (BI->keycode >> ID_Shft) & 0xffff;       /* see ID_Mask */
 
       if ((method >= nMethods) || !(BI->cmd))
        res = E_SYSTEM_ERROR;
@@ -4149,6 +4260,83 @@ form_driver(FORM *form, int c)
            res = (BI->cmd) (form);
        }
     }
+#ifdef NCURSES_MOUSE_VERSION
+  else if (KEY_MOUSE == c)
+    {
+      MEVENT event;
+      WINDOW *win = form->win ? form->win : StdScreen(Get_Form_Screen(form));
+      WINDOW *sub = form->sub ? form->sub : win;
+
+      getmouse(&event);
+      if ((event.bstate & (BUTTON1_CLICKED |
+                          BUTTON1_DOUBLE_CLICKED |
+                          BUTTON1_TRIPLE_CLICKED))
+         && wenclose(win, event.y, event.x))
+       {                       /* we react only if the click was in the userwin, that means
+                                * inside the form display area or at the decoration window.
+                                */
+         int ry = event.y, rx = event.x;       /* screen coordinates */
+
+         res = E_REQUEST_DENIED;
+         if (mouse_trafo(&ry, &rx, FALSE))
+           {                   /* rx, ry are now "curses" coordinates */
+             if (ry < sub->_begy)
+               {               /* we clicked above the display region; this is
+                                * interpreted as "scroll up" request
+                                */
+                 if (event.bstate & BUTTON1_CLICKED)
+                   res = form_driver(form, REQ_PREV_FIELD);
+                 else if (event.bstate & BUTTON1_DOUBLE_CLICKED)
+                   res = form_driver(form, REQ_PREV_PAGE);
+                 else if (event.bstate & BUTTON1_TRIPLE_CLICKED)
+                   res = form_driver(form, REQ_FIRST_FIELD);
+               }
+             else if (ry > sub->_begy + sub->_maxy)
+               {               /* we clicked below the display region; this is
+                                * interpreted as "scroll down" request
+                                */
+                 if (event.bstate & BUTTON1_CLICKED)
+                   res = form_driver(form, REQ_NEXT_FIELD);
+                 else if (event.bstate & BUTTON1_DOUBLE_CLICKED)
+                   res = form_driver(form, REQ_NEXT_PAGE);
+                 else if (event.bstate & BUTTON1_TRIPLE_CLICKED)
+                   res = form_driver(form, REQ_LAST_FIELD);
+               }
+             else if (wenclose(sub, event.y, event.x))
+               {               /* Inside the area we try to find the hit item */
+                 int i;
+
+                 ry = event.y;
+                 rx = event.x;
+                 if (wmouse_trafo(sub, &ry, &rx, FALSE))
+                   {
+                     int min_field = form->page[form->curpage].pmin;
+                     int max_field = form->page[form->curpage].pmax;
+
+                     for (i = min_field; i <= max_field; ++i)
+                       {
+                         FIELD *field = form->field[i];
+
+                         if (Field_Is_Selectable(field)
+                             && Field_encloses(field, ry, rx) == E_OK)
+                           {
+                             res = _nc_Set_Current_Field(form, field);
+                             if (res == E_OK)
+                               res = _nc_Position_Form_Cursor(form);
+                             if (res == E_OK
+                                 && (event.bstate & BUTTON1_DOUBLE_CLICKED))
+                               res = E_UNKNOWN_COMMAND;
+                             break;
+                           }
+                       }
+                   }
+               }
+           }
+       }
+      else
+       res = E_REQUEST_DENIED;
+    }
+#endif /* NCURSES_MOUSE_VERSION */
   else if (!(c & (~(int)MAX_REGULAR_CHARACTER)))
     {
       /*
@@ -4163,7 +4351,7 @@ form_driver(FORM *form, int c)
       if (!iscntrl(UChar(c)))
 #else
       if (isprint(UChar(c)) &&
-         Check_Char(form->current->type, c,
+         Check_Char(form, form->current, form->current->type, c,
                     (TypeArgument *)(form->current->arg)))
 #endif
        res = Data_Entry(form, c);
@@ -4208,22 +4396,13 @@ set_field_buffer(FIELD *field, int buffer, const char *value)
   FIELD_CELL *widevalue = 0;
 #endif
 
-  T((T_CALLED("set_field_buffer(%p,%d,%s)"), field, buffer, _nc_visbuf(value)));
+  T((T_CALLED("set_field_buffer(%p,%d,%s)"), (void *)field, buffer, _nc_visbuf(value)));
 
   if (!field || !value || ((buffer < 0) || (buffer > field->nbuf)))
     RETURN(E_BAD_ARGUMENT);
 
   len = Buffer_Length(field);
 
-  if (buffer == 0)
-    {
-      for (i = 0; (value[i] != '\0') && (i < len); ++i)
-       {
-         if (iscntrl(UChar(value[i])))
-           RETURN(E_BAD_ARGUMENT);
-       }
-    }
-
   if (Growable(field))
     {
       /* for a growable field we must assume zero terminated strings, because
@@ -4238,14 +4417,6 @@ set_field_buffer(FIELD *field, int buffer, const char *value)
                                                     * field->cols))))
            RETURN(E_SYSTEM_ERROR);
 
-         /* in this case we also have to check, whether or not the remaining
-            characters in value are also printable for buffer 0. */
-         if (buffer == 0)
-           {
-             for (i = len; i < vlen; i++)
-               if (iscntrl(UChar(value[i])))
-                 RETURN(E_BAD_ARGUMENT);
-           }
          len = vlen;
        }
     }
@@ -4258,16 +4429,29 @@ set_field_buffer(FIELD *field, int buffer, const char *value)
    * There should be a better way, but this handles nonspacing characters
    * and other special cases that we really do not want to handle here.
    */
+#if NCURSES_EXT_FUNCS
+  if (wresize(field->working, field->drows, field->dcols) == ERR)
+#endif
+    {
+      delwin(field->working);
+      field->working = newpad(field->drows, field->dcols);
+    }
+  len = Buffer_Length(field);
   wclear(field->working);
   mvwaddstr(field->working, 0, 0, value);
 
-  if ((widevalue = (FIELD_CELL *)calloc(len, sizeof(FIELD_CELL))) == 0)
+  if ((widevalue = typeCalloc(FIELD_CELL, len + 1)) == 0)
     {
       RETURN(E_SYSTEM_ERROR);
     }
   else
     {
-      mvwin_wchnstr(field->working, 0, 0, widevalue, (int)len);
+      for (i = 0; i < (unsigned)field->drows; ++i)
+       {
+         mvwin_wchnstr(field->working, i, 0,
+                       widevalue + (i * field->dcols),
+                       field->dcols);
+       }
       for (i = 0; i < len; ++i)
        {
          if (CharEq(myZEROS, widevalue[i]))
@@ -4320,7 +4504,7 @@ field_buffer(const FIELD *field, int buffer)
 {
   char *result = 0;
 
-  T((T_CALLED("field_buffer(%p,%d)"), field, buffer));
+  T((T_CALLED("field_buffer(%p,%d)"), (const void *)field, buffer));
 
   if (field && (buffer >= 0) && (buffer <= field->nbuf))
     {
@@ -4341,10 +4525,7 @@ field_buffer(const FIELD *field, int buffer)
              init_mb(state);
              next = _nc_wcrtomb(0, data[n].chars[0], &state);
              if (!isEILSEQ(next))
-               {
-                 if (next != 0)
-                   need += next;
-               }
+               need += next;
            }
        }
 
@@ -4358,7 +4539,7 @@ field_buffer(const FIELD *field, int buffer)
        {
          wclear(field->working);
          mvwadd_wchnstr(field->working, 0, 0, data, size);
-         mvwinnstr(field->working, 0, 0, result, (int)need + 1);
+         mvwinnstr(field->working, 0, 0, result, (int)need);
        }
 #else
       result = Address_Of_Nth_Buffer(field, buffer);
@@ -4369,22 +4550,6 @@ field_buffer(const FIELD *field, int buffer)
 
 #if USE_WIDEC_SUPPORT
 
-/* FIXME: see lib_get_wch.c */
-#if HAVE_MBTOWC && HAVE_MBLEN
-#define reset_mbytes(state) mblen(NULL, 0), mbtowc(NULL, NULL, 0)
-#define count_mbytes(buffer,length,state) mblen(buffer,length)
-#define trans_mbytes(wch,buffer,length,state) \
-       (int) mbtowc(&wch, buffer, length)
-#elif HAVE_MBRTOWC && HAVE_MBRLEN
-#define NEED_STATE
-#define reset_mbytes(state) init_mb(state)
-#define count_mbytes(buffer,length,state) mbrlen(buffer,length,&state)
-#define trans_mbytes(wch,buffer,length,state) \
-       (int) mbrtowc(&wch, buffer, length, &state)
-#else
-make an error
-#endif
-
 /*---------------------------------------------------------------------------
 | Convert a multibyte string to a wide-character string.  The result must be
 | freed by the caller.
@@ -4399,7 +4564,7 @@ _nc_Widen_String(char *source, int *lengthp)
   int pass;
   int status;
 
-#ifdef NEED_STATE
+#ifndef state_unused
   mbstate_t state;
 #endif
 
@@ -4418,8 +4583,8 @@ _nc_Widen_String(char *source, int *lengthp)
 
              source[passed + tries] = 0;
              reset_mbytes(state);
-             status = trans_mbytes(wch, source + passed, tries, state);
-             source[passed + tries] = save;
+             status = check_mbytes(wch, source + passed, tries, state);
+             source[passed + tries] = (char)save;
 
              if (status > 0)
                {