/****************************************************************************
- * Copyright (c) 1998-2008,2009 Free Software Foundation, Inc. *
+ * Copyright 2018-2020,2021 Thomas E. Dickey *
+ * Copyright 1998-2016,2017 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 *
#include "form.priv.h"
-MODULE_ID("$Id: frm_driver.c,v 1.93 2009/10/24 23:23:32 tom Exp $")
+MODULE_ID("$Id: frm_driver.c,v 1.135 2021/09/01 23:34:01 tom Exp $")
/*----------------------------------------------------------------------------
This is the core module of the form library. It contains the majority
#define GROW_IF_NAVIGATE (1)
#if USE_WIDEC_SUPPORT
-#define myADDNSTR(w, s, n) wadd_wchnstr(w, s, n)
-#define myINSNSTR(w, s, n) wins_wchnstr(w, s, n)
-#define myINNSTR(w, s, n) fix_wchnstr(w, s, n)
+#define myADDNSTR(w, s, n) wide_waddnstr(w, s, n)
+#define myINSNSTR(w, s, n) wide_winsnstr(w, s, n)
+#define myINNSTR(w, s, n) wide_winnstr(w, s, n)
#define myWCWIDTH(w, y, x) cell_width(w, y, x)
#else
#define myADDNSTR(w, s, n) waddnstr(w, s, n)
/* Calculate the position of a single row in a field buffer */
#define Position_Of_Row_In_Buffer(field,row) ((row)*(field)->dcols)
-/* Calculate start address for the fields buffer# N */
+/* Calculate start address for the field's buffer# N */
#define Address_Of_Nth_Buffer(field,N) \
((field)->buf + (N)*(1+Buffer_Length(field)))
-/* Calculate the start address of the row in the fields specified buffer# N */
+/* Calculate the start address of the row in the field's specified buffer# N */
#define Address_Of_Row_In_Nth_Buffer(field,N,row) \
(Address_Of_Nth_Buffer(field,N) + Position_Of_Row_In_Buffer(field,row))
-/* Calculate the start address of the row in the fields primary buffer */
+/* Calculate the start address of the row in the field's primary buffer */
#define Address_Of_Row_In_Buffer(field,row) \
Address_Of_Row_In_Nth_Buffer(field,0,row)
-/* Calculate the start address of the row in the forms current field
+/* Calculate the start address of the row in the form's current field
buffer# N */
#define Address_Of_Current_Row_In_Nth_Buffer(form,N) \
Address_Of_Row_In_Nth_Buffer((form)->current,N,(form)->currow)
-/* Calculate the start address of the row in the forms current field
+/* Calculate the start address of the row in the form's current field
primary buffer */
#define Address_Of_Current_Row_In_Buffer(form) \
Address_Of_Current_Row_In_Nth_Buffer(form,0)
-/* Calculate the address of the cursor in the forms current field
+/* Calculate the address of the cursor in the form's current field
primary buffer */
#define Address_Of_Current_Position_In_Nth_Buffer(form,N) \
(Address_Of_Current_Row_In_Nth_Buffer(form,N) + (form)->curcol)
-/* Calculate the address of the cursor in the forms current field
+/* Calculate the address of the cursor in the form's current field
buffer# N */
#define Address_Of_Current_Position_In_Buffer(form) \
Address_Of_Current_Position_In_Nth_Buffer(form,0)
instead of a derived window because it contains invisible parts.
This is true for non-public fields and for scrollable fields. */
#define Has_Invisible_Parts(field) \
- (!((field)->opts & O_PUBLIC) || \
+ (!(Field_Has_Option(field, O_PUBLIC)) || \
Is_Scroll_Field(field))
/* Logic to decide whether or not a field needs justification */
#define Justification_Allowed(field) \
(((field)->just != NO_JUSTIFICATION) && \
(Single_Line_Field(field)) && \
- (((field)->dcols == (field)->cols) && \
- ((field)->opts & O_STATIC)) )
+ ((Field_Has_Option(field, O_STATIC) && \
+ ((field)->dcols == (field)->cols)) || \
+ Field_Has_Option(field, O_DYNAMIC_JUSTIFY)))
/* Logic to determine whether or not a dynamic field may still grow */
#define Growable(field) ((field)->status & _MAY_GROW)
-/* Macro to set the attributes for a fields window */
+/* Macro to set the attributes for a field's window */
#define Set_Field_Window_Attributes(field,win) \
-( wbkgdset((win),(chtype)((field)->pad | (field)->back)), \
- (void) wattrset((win),(field)->fore) )
+( wbkgdset((win),(chtype)((chtype)((field)->pad) | (field)->back)), \
+ (void) wattrset((win), (int)(field)->fore) )
/* Logic to decide whether or not a field really appears on the form */
#define Field_Really_Appears(field) \
((field->form) &&\
(field->form->status & _POSTED) &&\
- (field->opts & O_VISIBLE) &&\
+ (Field_Has_Option(field, O_VISIBLE)) &&\
(field->page == field->form->curpage))
/* Logic to determine whether or not we are on the first position in the
static void
check_pos(FORM *form, int lineno)
{
- int y, x;
-
if (form && form->w)
{
+ int y, x;
+
getyx(form->w, y, x);
if (y != form->currow || x != form->curcol)
{
Wide-character special functions
--------------------------------------------------------------------------*/
#if USE_WIDEC_SUPPORT
-/* like winsnstr */
+/* add like waddnstr, but using cchar_t* rather than char*
+ */
+static int
+wide_waddnstr(WINDOW *w, const cchar_t *s, int n)
+{
+ int rc = OK;
+
+ while (n-- > 0)
+ {
+ if ((rc = wadd_wch(w, s)) != OK)
+ break;
+ ++s;
+ }
+ return rc;
+}
+
+/* insert like winsnstr, but using cchar_t* rather than char*
+ *
+ * X/Open Curses has no close equivalent; inserts are done only with wchar_t
+ * strings.
+ */
static int
-wins_wchnstr(WINDOW *w, cchar_t *s, int n)
+wide_winsnstr(WINDOW *w, const cchar_t *s, int n)
{
int code = ERR;
- int y, x;
while (n-- > 0)
{
+ int y, x;
+
getyx(w, y, x);
if ((code = wins_wch(w, s++)) != OK)
break;
return code;
}
-/* win_wchnstr is inconsistent with winnstr, since it returns OK rather than
- * the number of items transferred.
+/* retrieve like winnstr, but using cchar_t*, rather than char*.
+ *
+ * X/Open Curses' closest equivalent, win_wchnstr(), is inconsistent with
+ * winnstr(), since it returns OK rather than the number of items transferred.
*/
static int
-fix_wchnstr(WINDOW *w, cchar_t *s, int n)
+wide_winnstr(WINDOW *w, cchar_t *s, int n)
{
int x;
{
int width, height;
int y, x;
- int len;
int row;
FIELD_CELL *pBuffer;
row < height;
row++, pBuffer += width)
{
+ int len;
+
if ((len = (int)(After_End_Of_Data(pBuffer, width) - pBuffer)) > 0)
{
wmove(win, row, 0);
/*---------------------------------------------------------------------------
| 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
|
| Return Values : -
+--------------------------------------------------------------------------*/
-static void
-Window_To_Buffer(WINDOW *win, FIELD *field)
+FORM_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++)
}
}
+/*---------------------------------------------------------------------------
+| 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)
{
if (form->status & _WINDOW_MODIFIED)
{
- form->status &= ~_WINDOW_MODIFIED;
- form->status |= _FCHECK_REQUIRED;
- Window_To_Buffer(form->w, form->current);
+ ClrStatus(form, _WINDOW_MODIFIED);
+ SetStatus(form, _FCHECK_REQUIRED);
+ Window_To_Buffer(form, form->current);
wmove(form->w, form->currow, form->curcol);
}
}
growth = Minimum(field->maxgrow - field->dcols, growth);
field->dcols += growth;
if (field->dcols == field->maxgrow)
- field->status &= ~_MAY_GROW;
+ ClrStatus(field, _MAY_GROW);
}
else
{
growth = Minimum(field->maxgrow - field->drows, growth);
field->drows += growth;
if (field->drows == field->maxgrow)
- field->status &= ~_MAY_GROW;
+ ClrStatus(field, _MAY_GROW);
}
/* drows, dcols changed, so we get really the new buffer length */
new_buflen = Buffer_Length(field);
field->drows = old_drows;
if ((single_line_field && (field->dcols != field->maxgrow)) ||
(!single_line_field && (field->drows != field->maxgrow)))
- field->status |= _MAY_GROW;
+ SetStatus(field, _MAY_GROW);
}
else
{
* realloc().
*/
int i, j;
- FIELD_CELL *old_bp;
- FIELD_CELL *new_bp;
result = TRUE; /* allow sharing of recovery on failure */
field->buf = newbuf;
for (i = 0; i <= field->nbuf; i++)
{
- new_bp = Address_Of_Nth_Buffer(field, i);
- old_bp = oldbuf + i * (1 + old_buflen);
+ FIELD_CELL *new_bp = Address_Of_Nth_Buffer(field, i);
+ FIELD_CELL *old_bp = oldbuf + i * (1 + old_buflen);
+
for (j = 0; j < old_buflen; ++j)
new_bp[j] = old_bp[j];
while (j < new_buflen)
(field->dcols != field->maxgrow)) ||
(!single_line_field &&
(field->drows != field->maxgrow)))
- field->status |= _MAY_GROW;
+ SetStatus(field, _MAY_GROW);
free(newbuf);
}
}
| E_SYSTEM_ERROR - form has no current field or
| field-window
+--------------------------------------------------------------------------*/
-NCURSES_EXPORT(int)
+FORM_EXPORT(int)
_nc_Position_Form_Cursor(FORM *form)
{
FIELD *field;
| Facility : libnform
| Function : int _nc_Refresh_Current_Field(FORM * form)
|
-| Description : Propagate the changes in the fields window to the
+| Description : Propagate the changes in the field's window to the
| window of the form.
|
| Return Values : E_OK - on success
| E_BAD_ARGUMENT - invalid form pointer
| E_SYSTEM_ERROR - general error
+--------------------------------------------------------------------------*/
-NCURSES_EXPORT(int)
+static bool move_after_insert = TRUE;
+FORM_EXPORT(int)
_nc_Refresh_Current_Field(FORM *form)
{
WINDOW *formwin;
FIELD *field;
+ bool is_public;
T((T_CALLED("_nc_Refresh_Current_Field(%p)"), (void *)form));
field = form->current;
formwin = Get_Form_Window(form);
- if (field->opts & O_PUBLIC)
+ is_public = Field_Has_Option(field, O_PUBLIC);
+
+ if (Is_Scroll_Field(field))
{
- if (Is_Scroll_Field(field))
+ /* Again, in this case the fieldwin isn't derived from formwin,
+ so we have to perform a copy operation. */
+ if (Single_Line_Field(field))
{
- /* Again, in this case the fieldwin isn't derived from formwin,
- so we have to perform a copy operation. */
- if (Single_Line_Field(field))
+ /* horizontal scrolling */
+ if (form->curcol < form->begincol)
+ form->begincol = form->curcol;
+ else
{
- /* horizontal scrolling */
- if (form->curcol < form->begincol)
- form->begincol = form->curcol;
- else
- {
- if (form->curcol >= (form->begincol + field->cols))
- form->begincol = form->curcol - field->cols + 1;
- }
- copywin(form->w,
- formwin,
- 0,
- form->begincol,
- field->frow,
- field->fcol,
- field->frow,
- field->cols + field->fcol - 1,
- 0);
+ if (form->curcol >= (form->begincol + field->cols))
+ form->begincol = form->curcol - field->cols
+ + (move_after_insert ? 1 : 0);
}
- else
+ if (is_public)
+ copywin(form->w,
+ formwin,
+ 0,
+ form->begincol,
+ field->frow,
+ field->fcol,
+ field->frow,
+ field->cols + field->fcol - 1,
+ 0);
+ }
+ else
+ {
+ /* A multi-line, i.e. vertical scrolling field */
+ int first_modified_row, first_unmodified_row;
+
+ if (field->drows > field->rows)
{
- /* A multi-line, i.e. vertical scrolling field */
- int row_after_bottom, first_modified_row, first_unmodified_row;
+ int row_after_bottom = form->toprow + field->rows;
- if (field->drows > field->rows)
+ if (form->currow < form->toprow)
{
- row_after_bottom = form->toprow + field->rows;
- if (form->currow < form->toprow)
- {
- form->toprow = form->currow;
- field->status |= _NEWTOP;
- }
- if (form->currow >= row_after_bottom)
- {
- form->toprow = form->currow - field->rows + 1;
- field->status |= _NEWTOP;
- }
- if (field->status & _NEWTOP)
- {
- /* means we have to copy whole range */
- first_modified_row = form->toprow;
- first_unmodified_row = first_modified_row + field->rows;
- field->status &= ~_NEWTOP;
- }
- else
- {
- /* we try to optimize : finding the range of touched
- lines */
- first_modified_row = form->toprow;
- while (first_modified_row < row_after_bottom)
- {
- if (is_linetouched(form->w, first_modified_row))
- break;
- first_modified_row++;
- }
- first_unmodified_row = first_modified_row;
- while (first_unmodified_row < row_after_bottom)
- {
- if (!is_linetouched(form->w, first_unmodified_row))
- break;
- first_unmodified_row++;
- }
- }
+ form->toprow = form->currow;
+ SetStatus(field, _NEWTOP);
}
- else
+ if (form->currow >= row_after_bottom)
{
+ form->toprow = form->currow - field->rows + 1;
+ SetStatus(field, _NEWTOP);
+ }
+ if (field->status & _NEWTOP)
+ {
+ /* means we have to copy whole range */
first_modified_row = form->toprow;
first_unmodified_row = first_modified_row + field->rows;
+ ClrStatus(field, _NEWTOP);
+ }
+ else
+ {
+ /* we try to optimize : finding the range of touched
+ lines */
+ first_modified_row = form->toprow;
+ while (first_modified_row < row_after_bottom)
+ {
+ if (is_linetouched(form->w, first_modified_row))
+ break;
+ first_modified_row++;
+ }
+ first_unmodified_row = first_modified_row;
+ while (first_unmodified_row < row_after_bottom)
+ {
+ if (!is_linetouched(form->w, first_unmodified_row))
+ break;
+ first_unmodified_row++;
+ }
}
- if (first_unmodified_row != first_modified_row)
- copywin(form->w,
- formwin,
- first_modified_row,
- 0,
- field->frow + first_modified_row - form->toprow,
- field->fcol,
- field->frow + first_unmodified_row - form->toprow - 1,
- field->cols + field->fcol - 1,
- 0);
}
- wsyncup(formwin);
- }
- else
- {
- /* if the field-window is simply a derived window, i.e. contains no
- * invisible parts, the whole thing is trivial
- */
- wsyncup(form->w);
+ else
+ {
+ first_modified_row = form->toprow;
+ first_unmodified_row = first_modified_row + field->rows;
+ }
+ if (first_unmodified_row != first_modified_row && is_public)
+ copywin(form->w,
+ formwin,
+ first_modified_row,
+ 0,
+ field->frow + first_modified_row - form->toprow,
+ field->fcol,
+ field->frow + first_unmodified_row - form->toprow - 1,
+ field->cols + field->fcol - 1,
+ 0);
}
+ if (is_public)
+ wsyncup(formwin);
+ }
+ else
+ {
+ /* if the field-window is simply a derived window, i.e. contains no
+ * invisible parts, the whole thing is trivial
+ */
+ if (is_public)
+ wsyncup(form->w);
}
untouchwin(form->w);
returnCode(_nc_Position_Form_Cursor(form));
{
FIELD_CELL *bp;
int len;
- int col = 0;
- bp = Get_Start_Of_Data(field->buf, Buffer_Length(field));
+ bp = (Field_Has_Option(field, O_NO_LEFT_STRIP)
+ ? field->buf
+ : Get_Start_Of_Data(field->buf, Buffer_Length(field)));
len = (int)(After_End_Of_Data(field->buf, Buffer_Length(field)) - bp);
if (len > 0)
{
- assert(win && (field->drows == 1) && (field->dcols == field->cols));
+ int col = 0;
- switch (field->just)
- {
- case JUSTIFY_LEFT:
- break;
- case JUSTIFY_CENTER:
- col = (field->cols - len) / 2;
- break;
- case JUSTIFY_RIGHT:
- col = field->cols - len;
- break;
- default:
- break;
- }
+ assert(win && (field->drows == 1));
+
+ if (field->cols - len >= 0)
+ switch (field->just)
+ {
+ case JUSTIFY_LEFT:
+ break;
+ case JUSTIFY_CENTER:
+ col = (field->cols - len) / 2;
+ break;
+ case JUSTIFY_RIGHT:
+ col = field->cols - len;
+ break;
+ default:
+ break;
+ }
wmove(win, 0, col);
myADDNSTR(win, bp, len);
Undo_Justification(FIELD *field, WINDOW *win)
{
FIELD_CELL *bp;
+ int y, x;
int len;
- bp = Get_Start_Of_Data(field->buf, Buffer_Length(field));
+ getyx(win, y, x);
+
+ bp = (Field_Has_Option(field, O_NO_LEFT_STRIP)
+ ? field->buf
+ : Get_Start_Of_Data(field->buf, Buffer_Length(field)));
len = (int)(After_End_Of_Data(field->buf, Buffer_Length(field)) - bp);
if (len > 0)
wmove(win, 0, 0);
myADDNSTR(win, bp, len);
}
+ wmove(win, y, x);
}
/*---------------------------------------------------------------------------
| Facility : libnform
-| Function : static bool Check_Char(
+| Function : static bool Check_Char(FORM *form,
+| FIELD *field,
| FIELDTYPE * typ,
| int ch,
| TypeArgument *argp)
| 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)
{
{
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);
return E_SYSTEM_ERROR;
else
{
- if (field->opts & O_VISIBLE)
+ if (Field_Has_Option(field, O_VISIBLE))
{
Set_Field_Window_Attributes(field, win);
}
else
{
- (void)wattrset(win, WINDOW_ATTRS(fwin));
+ (void)wattrset(win, (int)WINDOW_ATTRS(fwin));
}
werase(win);
}
if (!bEraseFlag)
{
- if (field->opts & O_PUBLIC)
+ if (Field_Has_Option(field, O_PUBLIC))
{
if (Justification_Allowed(field))
Perform_Justification(field, win);
else
Buffer_To_Window(field, win);
}
- field->status &= ~_NEWTOP;
+ ClrStatus(field, _NEWTOP);
}
wsyncup(win);
delwin(win);
form->currow = form->curcol = form->toprow = form->begincol = 0;
werase(form->w);
- if ((field->opts & O_PUBLIC) && Justification_Allowed(field))
+ if ((Field_Has_Option(field, O_PUBLIC)) && Justification_Allowed(field))
Undo_Justification(field, form->w);
else
Buffer_To_Window(field, form->w);
- field->status |= _NEWTOP;
+ SetStatus(field, _NEWTOP);
res = _nc_Refresh_Current_Field(form);
}
else
res = Display_Field(field);
}
- field->status |= _CHANGED;
+ SetStatus(field, _CHANGED);
return (res);
}
{
FIELD *linked_field;
int res = E_OK;
- int syncres;
if (!field)
return (E_BAD_ARGUMENT);
return (E_SYSTEM_ERROR);
for (linked_field = field->link;
- linked_field != field;
+ (linked_field != field) && (linked_field != 0);
linked_field = linked_field->link)
{
+ int syncres;
+
if (((syncres = Synchronize_Field(linked_field)) != E_OK) &&
(res == E_OK))
res = syncres;
| Facility : libnform
| Function : int _nc_Synchronize_Attributes(FIELD * field)
|
-| Description : If a fields visual attributes have changed, this
+| Description : If a field's visual attributes have changed, this
| routine is called to propagate those changes to the
| screen.
|
| E_BAD_ARGUMENT - invalid field pointer
| E_SYSTEM_ERROR - some severe basic error
+--------------------------------------------------------------------------*/
-NCURSES_EXPORT(int)
+FORM_EXPORT(int)
_nc_Synchronize_Attributes(FIELD *field)
{
FORM *form;
int res = E_OK;
- WINDOW *formwin;
T((T_CALLED("_nc_Synchronize_Attributes(%p)"), (void *)field));
werase(form->w);
wmove(form->w, form->currow, form->curcol);
- if (field->opts & O_PUBLIC)
+ if (Field_Has_Option(field, O_PUBLIC))
{
if (Justification_Allowed(field))
Undo_Justification(field, form->w);
}
else
{
- formwin = Get_Form_Window(form);
+ WINDOW *formwin = Get_Form_Window(form);
+
copywin(form->w, formwin,
0, 0,
field->frow, field->fcol,
- field->rows - 1, field->cols - 1, 0);
+ field->frow + field->rows - 1,
+ field->fcol + field->cols - 1, 0);
wsyncup(formwin);
Buffer_To_Window(field, form->w);
- field->status |= _NEWTOP; /* fake refresh to paint all */
+ SetStatus(field, _NEWTOP); /* fake refresh to paint all */
_nc_Refresh_Current_Field(form);
}
}
| Function : int _nc_Synchronize_Options(FIELD * field,
| Field_Options newopts)
|
-| Description : If a fields options have changed, this routine is
+| Description : If a field's options have changed, this routine is
| called to propagate these changes to the screen and
| to really change the behavior of the field.
|
| E_CURRENT - field is the current one
| E_SYSTEM_ERROR - some severe basic error
+--------------------------------------------------------------------------*/
-NCURSES_EXPORT(int)
+FORM_EXPORT(int)
_nc_Synchronize_Options(FIELD *field, Field_Options newopts)
{
Field_Options oldopts;
if (form)
{
- if (form->current == field)
- {
- field->opts = oldopts;
- returnCode(E_CURRENT);
- }
-
if (form->status & _POSTED)
{
- if ((form->curpage == field->page))
+ if (form->current == field)
{
- if (changed_opts & O_VISIBLE)
+ field->opts = oldopts;
+ returnCode(E_CURRENT);
+ }
+ if (form->curpage == field->page)
+ {
+ if ((unsigned)changed_opts & O_VISIBLE)
{
- if (newopts & O_VISIBLE)
+ if ((unsigned)newopts & O_VISIBLE)
res = Display_Field(field);
else
res = Erase_Field(field);
}
else
{
- if ((changed_opts & O_PUBLIC) &&
- (newopts & O_VISIBLE))
+ if (((unsigned)changed_opts & O_PUBLIC) &&
+ ((unsigned)newopts & O_VISIBLE))
res = Display_Field(field);
}
}
}
}
- if (changed_opts & O_STATIC)
+ if ((unsigned)changed_opts & O_STATIC)
{
bool single_line_field = Single_Line_Field(field);
int res2 = E_OK;
- if (newopts & O_STATIC)
+ if ((unsigned)newopts & O_STATIC)
{
/* the field becomes now static */
- field->status &= ~_MAY_GROW;
+ ClrStatus(field, _MAY_GROW);
/* if actually we have no hidden columns, justification may
occur again */
if (single_line_field &&
(single_line_field && (field->dcols < field->maxgrow)) ||
(!single_line_field && (field->drows < field->maxgrow)))
{
- field->status |= _MAY_GROW;
+ SetStatus(field, _MAY_GROW);
/* a field with justification now changes its behavior,
so we must redisplay it */
if (single_line_field &&
returnCode(res);
}
+/*
+ * Removes the focus from the current field of the form.
+ */
+void
+_nc_Unset_Current_Field(FORM *form)
+{
+ FIELD *field = form->current;
+
+ _nc_Refresh_Current_Field(form);
+ if (Field_Has_Option(field, O_PUBLIC))
+ {
+ if (field->drows > field->rows)
+ {
+ if (form->toprow == 0)
+ ClrStatus(field, _NEWTOP);
+ else
+ SetStatus(field, _NEWTOP);
+ }
+ else
+ {
+ if (Justification_Allowed(field))
+ {
+ Window_To_Buffer(form, field);
+ werase(form->w);
+ Perform_Justification(field, form->w);
+ if (Field_Has_Option(field, O_DYNAMIC_JUSTIFY) &&
+ (form->w->_parent == 0))
+ {
+ copywin(form->w,
+ Get_Form_Window(form),
+ 0,
+ 0,
+ field->frow,
+ field->fcol,
+ field->frow,
+ field->cols + field->fcol - 1,
+ 0);
+ wsyncup(Get_Form_Window(form));
+ }
+ else
+ {
+ wsyncup(form->w);
+ }
+ }
+ }
+ }
+ delwin(form->w);
+ form->w = (WINDOW *)0;
+ form->current = 0;
+}
+
/*---------------------------------------------------------------------------
| Facility : libnform
| Function : int _nc_Set_Current_Field(FORM * form,
| E_SYSTEM_ERROR - some severe basic error
| E_NOT_CONNECTED - no fields are connected to the form
+--------------------------------------------------------------------------*/
-NCURSES_EXPORT(int)
+FORM_EXPORT(int)
_nc_Set_Current_Field(FORM *form, FIELD *newfield)
{
FIELD *field;
T((T_CALLED("_nc_Set_Current_Field(%p,%p)"), (void *)form, (void *)newfield));
- if (!form || !newfield || !form->current || (newfield->form != form))
+ if (!form || !newfield || (newfield->form != form))
returnCode(E_BAD_ARGUMENT);
if ((form->status & _IN_DRIVER))
if ((field != newfield) ||
!(form->status & _POSTED))
{
- if ((form->w) &&
- (field->opts & O_VISIBLE) &&
+ if (field && (form->w) &&
+ (Field_Has_Option(field, O_VISIBLE)) &&
(field->form->curpage == field->page))
- {
- _nc_Refresh_Current_Field(form);
- if (field->opts & O_PUBLIC)
- {
- if (field->drows > field->rows)
- {
- if (form->toprow == 0)
- field->status &= ~_NEWTOP;
- else
- field->status |= _NEWTOP;
- }
- else
- {
- if (Justification_Allowed(field))
- {
- Window_To_Buffer(form->w, field);
- werase(form->w);
- Perform_Justification(field, form->w);
- wsyncup(form->w);
- }
- }
- }
- delwin(form->w);
- form->w = (WINDOW *)0;
- }
+ _nc_Unset_Current_Field(form);
field = newfield;
delwin(form->w);
form->w = new_window;
- form->status &= ~_WINDOW_MODIFIED;
+ ClrStatus(form, _WINDOW_MODIFIED);
Set_Field_Window_Attributes(field, form->w);
if (Has_Invisible_Parts(field))
{
res = fct(form);
if (res == E_OK)
- form->current->status |= _NEWTOP;
+ SetStatus(form->current, _NEWTOP);
}
return (res);
}
int datalen = (int)(After_End_Of_Data(bp, field->dcols) - bp);
int freelen = field->dcols - datalen;
int requiredlen = len + 1;
- FIELD_CELL *split;
int result = E_REQUEST_DENIED;
if (freelen >= requiredlen)
myINSNSTR(form->w, txt, len);
wmove(form->w, row, len);
myINSNSTR(form->w, &myBLANK, 1);
- return E_OK;
+ result = E_OK;
}
else
{
if (row < (field->drows - 1))
{
+ FIELD_CELL *split;
+
split =
After_Last_Whitespace_Character(bp,
(int)(Get_Start_Of_Data(bp
return E_OK;
}
}
- return (result);
}
+ return (result);
}
/*---------------------------------------------------------------------------
int result = E_REQUEST_DENIED;
bool Last_Row = ((field->drows - 1) == form->currow);
- if ((field->opts & O_WRAP) && /* wrapping wanted */
+ if ((Field_Has_Option(field, O_WRAP)) && /* wrapping wanted */
(!Single_Line_Field(field)) && /* must be multi-line */
(There_Is_No_Room_For_A_Char_In_Line(form)) && /* line is full */
(!Last_Row || Growable(field))) /* there are more lines */
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 */
if (result != E_OK)
{
DeleteChar(form);
- Window_To_Buffer(form->w, field);
+ Window_To_Buffer(form, field);
result = E_REQUEST_DENIED;
}
}
editable fields.
*/
if ((fct == FE_Delete_Previous) &&
- (form->opts & O_BS_OVERLOAD) &&
+ ((unsigned)form->opts & O_BS_OVERLOAD) &&
First_Position_In_Current_Field(form))
{
res = Inter_Field_Navigation(FN_Previous_Field, form);
{
if (fct == FE_New_Line)
{
- if ((form->opts & O_NL_OVERLOAD) &&
+ if (((unsigned)form->opts & O_NL_OVERLOAD) &&
First_Position_In_Current_Field(form))
{
res = Inter_Field_Navigation(FN_Next_Field, form);
else
{
/* From now on, everything must be editable */
- if (form->current->opts & O_EDIT)
+ if ((unsigned)form->current->opts & O_EDIT)
{
res = fct(form);
if (res == E_OK)
- form->status |= _WINDOW_MODIFIED;
+ SetStatus(form, _WINDOW_MODIFIED);
}
}
}
if (Last_Row &&
(!(Growable(field) && !Single_Line_Field(field))))
{
- if (!(form->opts & O_NL_OVERLOAD))
+ if (!((unsigned)form->opts & O_NL_OVERLOAD))
returnCode(E_REQUEST_DENIED);
wmove(form->w, form->currow, form->curcol);
wclrtoeol(form->w);
handled in the generic routine. The reason is,
that FN_Next_Field may fail, but the form is
definitively changed */
- form->status |= _WINDOW_MODIFIED;
+ SetStatus(form, _WINDOW_MODIFIED);
returnCode(Inter_Field_Navigation(FN_Next_Field, form));
}
else
wclrtoeol(form->w);
form->currow++;
form->curcol = 0;
- form->status |= _WINDOW_MODIFIED;
+ SetStatus(form, _WINDOW_MODIFIED);
returnCode(E_OK);
}
}
if (Last_Row &&
!(Growable(field) && !Single_Line_Field(field)))
{
- if (!(form->opts & O_NL_OVERLOAD))
+ if (!((unsigned)form->opts & O_NL_OVERLOAD))
returnCode(E_REQUEST_DENIED);
returnCode(Inter_Field_Navigation(FN_Next_Field, form));
}
wmove(form->w, form->currow, form->curcol);
winsertln(form->w);
myADDNSTR(form->w, bp, (int)(t - bp));
- form->status |= _WINDOW_MODIFIED;
+ SetStatus(form, _WINDOW_MODIFIED);
returnCode(E_OK);
}
}
int result = E_REQUEST_DENIED;
T((T_CALLED("FE_Insert_Character(%p)"), (void *)form));
- if (Check_Char(field->type, (int)C_BLANK, (TypeArgument *)(field->arg)))
+ 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);
int result = E_REQUEST_DENIED;
T((T_CALLED("FE_Insert_Line(%p)"), (void *)form));
- if (Check_Char(field->type, (int)C_BLANK, (TypeArgument *)(field->arg)))
+ 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);
EM_Overlay_Mode(FORM *form)
{
T((T_CALLED("EM_Overlay_Mode(%p)"), (void *)form));
- form->status |= _OVLMODE;
+ SetStatus(form, _OVLMODE);
returnCode(E_OK);
}
EM_Insert_Mode(FORM *form)
{
T((T_CALLED("EM_Insert_Mode(%p)"), (void *)form));
- form->status &= ~_OVLMODE;
+ ClrStatus(form, _OVLMODE);
returnCode(E_OK);
}
/*---------------------------------------------------------------------------
| Facility : libnform
-| Function : static bool Next_Choice(
+| Function : static bool Next_Choice(FORM * form,
| FIELDTYPE * typ,
| FIELD * field,
| TypeArgument *argp)
| 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;
{
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)
| 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;
{
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
}
}
/*----------------------------------------------------------------------------
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);
}
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);
}
/*---------------------------------------------------------------------------
| Facility : libnform
-| Function : static bool Check_Field(
+| Function : static bool Check_Field(FORM* form,
| FIELDTYPE * typ,
| FIELD * field,
| TypeArgument * argp)
| 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)
{
- if (field->opts & O_NULLOK)
+ if (Field_Has_Option(field, O_NULLOK))
{
FIELD_CELL *bp = field->buf;
{
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;
| Return Values : TRUE - field is valid
| FALSE - field is invalid
+--------------------------------------------------------------------------*/
-NCURSES_EXPORT(bool)
+FORM_EXPORT(bool)
_nc_Internal_Validation(FORM *form)
{
FIELD *field;
Synchronize_Buffer(form);
if ((form->status & _FCHECK_REQUIRED) ||
- (!(field->opts & O_PASSOK)))
+ (!(Field_Has_Option(field, 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;
+ ClrStatus(form, _FCHECK_REQUIRED);
+ SetStatus(field, _CHANGED);
Synchronize_Linked_Fields(field);
}
return TRUE;
|
| Description : Get the next field after the given field on the current
| page. The order of fields is the one defined by the
-| fields array. Only visible and active fields are
+| field's array. Only visible and active fields are
| counted.
|
| Return Values : Pointer to the next field.
|
| Return Values : Pointer to calculated field.
+--------------------------------------------------------------------------*/
-NCURSES_EXPORT(FIELD *)
+FORM_EXPORT(FIELD *)
_nc_First_Active_Field(FORM *form)
{
FIELD **last_on_page = &form->field[form->page[form->curpage].pmax];
do
{
field = (field == last_on_page) ? first : field + 1;
- if (((*field)->opts & O_VISIBLE))
+ if (Field_Has_Option(*field, O_VISIBLE))
break;
}
while (proposed != (*field));
proposed = *field;
- if ((proposed == *last_on_page) && !(proposed->opts & O_VISIBLE))
+ if ((proposed == *last_on_page) &&
+ !((unsigned)proposed->opts & O_VISIBLE))
{
/* This means, there is also no visible field on the page.
So we propose the first one and hope the very best...
|
| Description : Get the previous field before the given field on the
| current page. The order of fields is the one defined by
-| the fields array. Only visible and active fields are
+| the field's array. Only visible and active fields are
| counted.
|
| Return Values : Pointer to the previous field.
| Function : static FIELD *Upper_Neighbor_Field(FIELD * field)
|
| Description : Because of the row-major nature of sorting the fields,
-| it is more difficult to define whats the upper neighbor
+| it is more difficult to define what the upper neighbor
| field really means. We define that it must be on a
| 'previous' line (cyclic order!) and is the rightmost
-| field laying on the left side of the given field. If
+| field lying on the left side of the given field. If
| this set is empty, we take the first field on the line.
|
| Return Values : Pointer to the upper neighbor field.
| Function : static FIELD *Down_Neighbor_Field(FIELD * field)
|
| Description : Because of the row-major nature of sorting the fields,
-| its more difficult to define whats the down neighbor
+| it is more difficult to define what the down neighbor
| field really means. We define that it must be on a
| 'next' line (cyclic order!) and is the leftmost
| field laying on the right side of the given field. If
| E_BAD_ARGUMENT - invalid field pointer
| E_SYSTEM_ERROR - some severe basic error
+--------------------------------------------------------------------------*/
-NCURSES_EXPORT(int)
+FORM_EXPORT(int)
_nc_Set_Form_Page(FORM *form, int page, FIELD *field)
{
int res = E_OK;
FIELD *last_field, *field_on_page;
werase(Get_Form_Window(form));
- form->curpage = page;
+ form->curpage = (short)page;
last_field = field_on_page = form->field[form->page[page].smin];
do
{
- if (field_on_page->opts & O_VISIBLE)
+ if ((unsigned)field_on_page->opts & O_VISIBLE)
if ((res = Display_Field(field_on_page)) != E_OK)
return (res);
field_on_page = field_on_page->snext;
| that the field is left and a new field is entered.
| So the field must be validated and the field init/term
| hooks must be called. Because also the page is changed,
-| the forms init/term hooks must be called also.
+| the form's init/term hooks must be called also.
|
| Return Values : E_OK - success
| E_INVALID_FIELD - field is invalid
Helper routines for the core form driver.
--------------------------------------------------------------------------*/
+# if USE_WIDEC_SUPPORT
+/*---------------------------------------------------------------------------
+| Facility : libnform
+| Function : static int Data_Entry_w(FORM * form, wchar_t c)
+|
+| Description : Enter the wide character c into at the current
+| position of the current field of the form.
+|
+| Return Values : E_OK - success
+| E_REQUEST_DENIED - driver could not process the request
+| E_SYSTEM_ERROR -
++--------------------------------------------------------------------------*/
+static int
+Data_Entry_w(FORM *form, wchar_t c)
+{
+ FIELD *field = form->current;
+ int result = E_REQUEST_DENIED;
+
+ T((T_CALLED("Data_Entry(%p,%s)"), (void *)form, _tracechtype((chtype)c)));
+ if ((Field_Has_Option(field, O_EDIT))
+#if FIX_FORM_INACTIVE_BUG
+ && (Field_Has_Option(field, O_ACTIVE))
+#endif
+ )
+ {
+ wchar_t given[2];
+ cchar_t temp_ch;
+
+ given[0] = c;
+ given[1] = 0;
+ setcchar(&temp_ch, given, 0, 0, (void *)0);
+ if ((Field_Has_Option(field, O_BLANK)) &&
+ First_Position_In_Current_Field(form) &&
+ !(form->status & _FCHECK_REQUIRED) &&
+ !(form->status & _WINDOW_MODIFIED))
+ werase(form->w);
+
+ if (form->status & _OVLMODE)
+ {
+ wadd_wch(form->w, &temp_ch);
+ }
+ else
+ /* no _OVLMODE */
+ {
+ bool There_Is_Room = Is_There_Room_For_A_Char_In_Line(form);
+
+ if (!(There_Is_Room ||
+ ((Single_Line_Field(field) && Growable(field)))))
+ RETURN(E_REQUEST_DENIED);
+
+ if (!There_Is_Room && !Field_Grown(field, 1))
+ RETURN(E_SYSTEM_ERROR);
+
+ wins_wch(form->w, &temp_ch);
+ }
+
+ if ((result = Wrapping_Not_Necessary_Or_Wrapping_Ok(form)) == E_OK)
+ {
+ bool End_Of_Field = (((field->drows - 1) == form->currow) &&
+ ((field->dcols - 1) == form->curcol));
+
+ form->status |= _WINDOW_MODIFIED;
+ if (End_Of_Field && !Growable(field) && (Field_Has_Option(field, O_AUTOSKIP)))
+ result = Inter_Field_Navigation(FN_Next_Field, form);
+ else
+ {
+ if (End_Of_Field && Growable(field) && !Field_Grown(field, 1))
+ result = E_SYSTEM_ERROR;
+ else
+ {
+ /*
+ * We have just added a byte to the form field. It may have
+ * been part of a multibyte character. If it was, the
+ * addch_used field is nonzero and we should not try to move
+ * to a new column.
+ */
+ if (WINDOW_EXT(form->w, addch_used) == 0)
+ IFN_Next_Character(form);
+
+ result = E_OK;
+ }
+ }
+ }
+ }
+ RETURN(result);
+}
+# endif
+
/*---------------------------------------------------------------------------
| Facility : libnform
| Function : static int Data_Entry(FORM * form,int c)
int result = E_REQUEST_DENIED;
T((T_CALLED("Data_Entry(%p,%s)"), (void *)form, _tracechtype((chtype)c)));
- if ((field->opts & O_EDIT)
+ if ((Field_Has_Option(field, O_EDIT))
#if FIX_FORM_INACTIVE_BUG
- && (field->opts & O_ACTIVE)
+ && (Field_Has_Option(field, O_ACTIVE))
#endif
)
{
- if ((field->opts & O_BLANK) &&
+ if ((Field_Has_Option(field, O_BLANK)) &&
First_Position_In_Current_Field(form) &&
!(form->status & _FCHECK_REQUIRED) &&
!(form->status & _WINDOW_MODIFIED))
bool End_Of_Field = (((field->drows - 1) == form->currow) &&
((field->dcols - 1) == form->curcol));
- form->status |= _WINDOW_MODIFIED;
- if (End_Of_Field && !Growable(field) && (field->opts & O_AUTOSKIP))
+ if (Field_Has_Option(field, O_EDGE_INSERT_STAY))
+ move_after_insert = !!(form->curcol
+ - form->begincol
+ - field->cols
+ + 1);
+
+ SetStatus(form, _WINDOW_MODIFIED);
+ if (End_Of_Field && !Growable(field) && (Field_Has_Option(field, O_AUTOSKIP)))
result = Inter_Field_Navigation(FN_Next_Field, form);
else
{
| E_NOT_CONNECTED - no fields are connected to the form
| E_UNKNOWN_COMMAND - command not known
+--------------------------------------------------------------------------*/
-NCURSES_EXPORT(int)
+FORM_EXPORT(int)
form_driver(FORM *form, int c)
{
- const Binding_Info *BI = (Binding_Info *) 0;
+ const Binding_Info *BI = (Binding_Info *)0;
int res = E_UNKNOWN_COMMAND;
+ move_after_insert = TRUE;
+
T((T_CALLED("form_driver(%p,%d)"), (void *)form, c));
if (!form)
RETURN(E_BAD_ARGUMENT);
- if (!(form->field))
+ if (!(form->field) || !(form->current))
RETURN(E_NOT_CONNECTED);
assert(form->page);
if ((c >= MIN_FORM_COMMAND && c <= MAX_FORM_COMMAND) &&
((bindings[c - MIN_FORM_COMMAND].keycode & Key_Mask) == c))
- BI = &(bindings[c - MIN_FORM_COMMAND]);
+ {
+ TR(TRACE_CALLS, ("form_request %s", form_request_name(c)));
+ BI = &(bindings[c - MIN_FORM_COMMAND]);
+ }
if (BI)
{
NULL /* Choice Request is generic */
};
size_t nMethods = (sizeof(Generic_Methods) / sizeof(Generic_Methods[0]));
- size_t method = (BI->keycode >> ID_Shft) & 0xffff; /* see ID_Mask */
+ size_t method = (size_t)((BI->keycode >> ID_Shft) & 0xffff); /* see ID_Mask */
if ((method >= nMethods) || !(BI->cmd))
res = E_SYSTEM_ERROR;
Generic_Method fct = Generic_Methods[method];
if (fct)
- res = fct(BI->cmd, form);
+ {
+ res = fct(BI->cmd, form);
+ }
else
- res = (BI->cmd) (form);
+ {
+ res = (BI->cmd) (form);
+ }
}
}
#ifdef NCURSES_MOUSE_VERSION
else if (KEY_MOUSE == c)
{
MEVENT event;
- WINDOW *win = form->win ? form->win : stdscr;
+ WINDOW *win = form->win ? form->win : StdScreen(Get_Form_Screen(form));
WINDOW *sub = form->sub ? form->sub : win;
getmouse(&event);
}
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;
+ int i;
for (i = min_field; i <= max_field; ++i)
{
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);
RETURN(res);
}
+# if USE_WIDEC_SUPPORT
+/*---------------------------------------------------------------------------
+| Facility : libnform
+| Function : int form_driver_w(FORM * form,int type,wchar_t c)
+|
+| Description : This is the workhorse of the forms system.
+|
+| Input is either a key code (request) or a wide char
+| returned by e.g. get_wch (). The type must be passed
+| as well,so that we are able to determine whether the char
+| is a multibyte char or a request.
+
+| If it is a request, the form driver executes
+| the request and returns the result. If it is data
+| (printable character), it enters the data into the
+| current position in the current field. If it is not
+| recognized, the form driver assumes it is an application
+| defined command and returns E_UNKNOWN_COMMAND.
+| Application defined command should be defined relative
+| to MAX_FORM_COMMAND, the maximum value of a request.
+|
+| Return Values : E_OK - success
+| E_SYSTEM_ERROR - system error
+| E_BAD_ARGUMENT - an argument is incorrect
+| E_NOT_POSTED - form is not posted
+| E_INVALID_FIELD - field contents are invalid
+| E_BAD_STATE - called from inside a hook routine
+| E_REQUEST_DENIED - request failed
+| E_NOT_CONNECTED - no fields are connected to the form
+| E_UNKNOWN_COMMAND - command not known
++--------------------------------------------------------------------------*/
+FORM_EXPORT(int)
+form_driver_w(FORM *form, int type, wchar_t c)
+{
+ const Binding_Info *BI = (Binding_Info *)0;
+ int res = E_UNKNOWN_COMMAND;
+
+ T((T_CALLED("form_driver(%p,%d)"), (void *)form, (int)c));
+
+ if (!form)
+ RETURN(E_BAD_ARGUMENT);
+
+ if (!(form->field))
+ RETURN(E_NOT_CONNECTED);
+
+ assert(form->page);
+
+ if (c == (wchar_t)FIRST_ACTIVE_MAGIC)
+ {
+ form->current = _nc_First_Active_Field(form);
+ RETURN(E_OK);
+ }
+
+ assert(form->current &&
+ form->current->buf &&
+ (form->current->form == form)
+ );
+
+ if (form->status & _IN_DRIVER)
+ RETURN(E_BAD_STATE);
+
+ if (!(form->status & _POSTED))
+ RETURN(E_NOT_POSTED);
+
+ /* check if this is a keycode or a (wide) char */
+ if (type == KEY_CODE_YES)
+ {
+ if ((c >= MIN_FORM_COMMAND && c <= MAX_FORM_COMMAND) &&
+ ((bindings[c - MIN_FORM_COMMAND].keycode & Key_Mask) == c))
+ BI = &(bindings[c - MIN_FORM_COMMAND]);
+ }
+
+ if (BI)
+ {
+ typedef int (*Generic_Method) (int (*const) (FORM *), FORM *);
+ static const Generic_Method Generic_Methods[] =
+ {
+ Page_Navigation, /* overloaded to call field&form hooks */
+ Inter_Field_Navigation, /* overloaded to call field hooks */
+ NULL, /* Intra-Field is generic */
+ Vertical_Scrolling, /* Overloaded to check multi-line */
+ Horizontal_Scrolling, /* Overloaded to check single-line */
+ Field_Editing, /* Overloaded to mark modification */
+ NULL, /* Edit Mode is generic */
+ NULL, /* Field Validation is generic */
+ NULL /* Choice Request is generic */
+ };
+ size_t nMethods = (sizeof(Generic_Methods) / sizeof(Generic_Methods[0]));
+ size_t method = (size_t)(BI->keycode >> ID_Shft) & 0xffff; /* see ID_Mask */
+
+ if ((method >= nMethods) || !(BI->cmd))
+ res = E_SYSTEM_ERROR;
+ else
+ {
+ Generic_Method fct = Generic_Methods[method];
+
+ if (fct)
+ res = fct(BI->cmd, form);
+ else
+ 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 */
+ 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;
+ int i;
+
+ 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 (type == OK)
+ {
+ res = Data_Entry_w(form, c);
+ }
+
+ _nc_Refresh_Current_Field(form);
+ RETURN(res);
+}
+# endif /* USE_WIDEC_SUPPORT */
+
/*----------------------------------------------------------------------------
Field-Buffer manipulation routines.
The effects of setting a buffer are tightly coupled to the core of the form
| For dynamic fields this may grow the fieldbuffers if
| the length of the value exceeds the current buffer
| length. For buffer 0 only printable values are allowed.
-| For static fields, the value needs not to be zero ter-
-| minated. It is copied up to the length of the buffer.
+| For static fields, the value must not be zero terminated.
+| It is copied up to the length of the buffer.
|
| Return Values : E_OK - success
| E_BAD_ARGUMENT - invalid argument
| E_SYSTEM_ERROR - system error
+--------------------------------------------------------------------------*/
-NCURSES_EXPORT(int)
+FORM_EXPORT(int)
set_field_buffer(FIELD *field, int buffer, const char *value)
{
FIELD_CELL *p;
int res = E_OK;
- unsigned int i;
- unsigned int len;
+ int i;
+ int len;
#if USE_WIDEC_SUPPORT
FIELD_CELL *widevalue = 0;
/* for a growable field we must assume zero terminated strings, because
somehow we have to detect the length of what should be copied.
*/
- unsigned int vlen = strlen(value);
+ int vlen = (int)strlen(value);
if (vlen > len)
{
* field->cols))))
RETURN(E_SYSTEM_ERROR);
+#if !USE_WIDEC_SUPPORT
len = vlen;
+#endif
}
}
* 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)
+ if (wresize(field->working, 1, Buffer_Length(field) + 1) == ERR)
#endif
{
delwin(field->working);
- field->working = newpad(field->drows, field->dcols);
+ field->working = newpad(1, Buffer_Length(field) + 1);
}
len = Buffer_Length(field);
wclear(field->working);
- mvwaddstr(field->working, 0, 0, value);
+ (void)mvwaddstr(field->working, 0, 0, value);
if ((widevalue = typeCalloc(FIELD_CELL, len + 1)) == 0)
{
}
else
{
- for (i = 0; i < (unsigned)field->drows; ++i)
+ for (i = 0; i < field->drows; ++i)
{
- mvwin_wchnstr(field->working, i, 0,
- widevalue + (i * field->dcols),
- field->dcols);
+ (void)mvwin_wchnstr(field->working, 0, (int)i * field->dcols,
+ widevalue + ((int)i * field->dcols),
+ field->dcols);
}
for (i = 0; i < len; ++i)
{
|
| Return Values : Pointer to buffer or NULL if arguments were invalid.
+--------------------------------------------------------------------------*/
-NCURSES_EXPORT(char *)
+FORM_EXPORT(char *)
field_buffer(const FIELD *field, int buffer)
{
char *result = 0;
{
#if USE_WIDEC_SUPPORT
FIELD_CELL *data = Address_Of_Nth_Buffer(field, buffer);
- unsigned need = 0;
+ size_t need = 0;
int size = Buffer_Length(field);
int n;
/* determine the number of bytes needed to store the expanded string */
for (n = 0; n < size; ++n)
{
- if (!isWidecExt(data[n]))
+ if (!isWidecExt(data[n]) && data[n].chars[0] != L'\0')
{
mbstate_t state;
size_t next;
init_mb(state);
next = _nc_wcrtomb(0, data[n].chars[0], &state);
- if (!isEILSEQ(next))
+ if (next > 0)
need += next;
}
}
free(field->expanded[buffer]);
field->expanded[buffer] = typeMalloc(char, need + 1);
- /* expand the multibyte data */
+ /*
+ * Expand the multibyte data.
+ *
+ * It may also be multi-column data. In that case, the data for a row
+ * may be null-padded to align to the dcols/drows layout (or it may
+ * contain embedded wide-character extensions). Change the null-padding
+ * to blanks as needed.
+ */
if ((result = field->expanded[buffer]) != 0)
{
wclear(field->working);
- mvwadd_wchnstr(field->working, 0, 0, data, size);
- mvwinnstr(field->working, 0, 0, result, (int)need);
+ wmove(field->working, 0, 0);
+ for (n = 0; n < size; ++n)
+ {
+ if (!isWidecExt(data[n]) && data[n].chars[0] != L'\0')
+ wadd_wch(field->working, &data[n]);
+ }
+ wmove(field->working, 0, 0);
+ winnstr(field->working, result, (int)need);
}
#else
result = Address_Of_Nth_Buffer(field, buffer);
| Convert a multibyte string to a wide-character string. The result must be
| freed by the caller.
+--------------------------------------------------------------------------*/
-NCURSES_EXPORT(wchar_t *)
+FORM_EXPORT(wchar_t *)
_nc_Widen_String(char *source, int *lengthp)
{
wchar_t *result = 0;
{
result[need] = wch;
}
- passed += status;
+ passed += (size_t)status;
++need;
}
else
{
if (pass)
{
- result[need] = source[passed];
+ result[need] = (wchar_t)source[passed];
}
++need;
++passed;
break;
result = typeCalloc(wchar_t, need);
- *lengthp = need;
+ *lengthp = (int)need;
if (result == 0)
break;
}