150276Speter/**************************************************************************** 2176187Srafan * Copyright (c) 1998-2007,2008 Free Software Foundation, Inc. * 350276Speter * * 450276Speter * Permission is hereby granted, free of charge, to any person obtaining a * 550276Speter * copy of this software and associated documentation files (the * 650276Speter * "Software"), to deal in the Software without restriction, including * 750276Speter * without limitation the rights to use, copy, modify, merge, publish, * 850276Speter * distribute, distribute with modifications, sublicense, and/or sell * 950276Speter * copies of the Software, and to permit persons to whom the Software is * 1050276Speter * furnished to do so, subject to the following conditions: * 1150276Speter * * 1250276Speter * The above copyright notice and this permission notice shall be included * 1350276Speter * in all copies or substantial portions of the Software. * 1450276Speter * * 1550276Speter * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS * 1650276Speter * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * 1750276Speter * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. * 1850276Speter * IN NO EVENT SHALL THE ABOVE COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, * 1950276Speter * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR * 2050276Speter * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR * 2150276Speter * THE USE OR OTHER DEALINGS IN THE SOFTWARE. * 2250276Speter * * 2350276Speter * Except as contained in this notice, the name(s) of the above copyright * 2450276Speter * holders shall not be used in advertising or otherwise to promote the * 2550276Speter * sale, use or other dealings in this Software without prior written * 2650276Speter * authorization. * 2750276Speter ****************************************************************************/ 2850276Speter 2950276Speter/**************************************************************************** 30166124Srafan * Author: Juergen Pfeifer, 1995,1997 * 3150276Speter ****************************************************************************/ 32166124Srafan 3350276Speter#include "form.priv.h" 3450276Speter 35184989SrafanMODULE_ID("$Id: frm_driver.c,v 1.88 2008/10/18 16:25:00 tom Exp $") 3650276Speter 3750276Speter/*---------------------------------------------------------------------------- 3850276Speter This is the core module of the form library. It contains the majority 39166124Srafan of the driver routines as well as the form_driver function. 4050276Speter 4150276Speter Essentially this module is nearly the whole library. This is because 4250276Speter all the functions in this module depends on some others in the module, 4350276Speter so it makes no sense to split them into separate files because they 4450276Speter will always be linked together. The only acceptable concern is turnaround 45166124Srafan time for this module, but now we have all Pentiums or RISCs, so what! 4650276Speter 4750276Speter The driver routines are grouped into nine generic categories: 4850276Speter 4950276Speter a) Page Navigation ( all functions prefixed by PN_ ) 5050276Speter The current page of the form is left and some new page is 5150276Speter entered. 5250276Speter b) Inter-Field Navigation ( all functions prefixed by FN_ ) 5350276Speter The current field of the form is left and some new field is 5450276Speter entered. 5550276Speter c) Intra-Field Navigation ( all functions prefixed by IFN_ ) 56166124Srafan The current position in the current field is changed. 5750276Speter d) Vertical Scrolling ( all functions prefixed by VSC_ ) 58166124Srafan Essentially this is a specialization of Intra-Field navigation. 5950276Speter It has to check for a multi-line field. 6050276Speter e) Horizontal Scrolling ( all functions prefixed by HSC_ ) 61166124Srafan Essentially this is a specialization of Intra-Field navigation. 6250276Speter It has to check for a single-line field. 6350276Speter f) Field Editing ( all functions prefixed by FE_ ) 6450276Speter The content of the current field is changed 6550276Speter g) Edit Mode requests ( all functions prefixed by EM_ ) 6650276Speter Switching between insert and overlay mode 6750276Speter h) Field-Validation requests ( all functions prefixed by FV_ ) 6850276Speter Perform verifications of the field. 6950276Speter i) Choice requests ( all functions prefixed by CR_ ) 7050276Speter Requests to enumerate possible field values 7150276Speter --------------------------------------------------------------------------*/ 7250276Speter 7350276Speter/*---------------------------------------------------------------------------- 7450276Speter Some remarks on the placements of assert() macros : 7550276Speter I use them only on "strategic" places, i.e. top level entries where 7650276Speter I want to make sure that things are set correctly. Throughout subordinate 7750276Speter routines I omit them mostly. 7850276Speter --------------------------------------------------------------------------*/ 7950276Speter 8050276Speter/* 8150276SpeterSome options that may effect compatibility in behavior to SVr4 forms, 82166124Srafanbut they are here to allow a more intuitive and user friendly behavior of 8350276Speterour form implementation. This doesn't affect the API, so we feel it is 8450276Speteruncritical. 8550276Speter 86166124SrafanThe initial implementation tries to stay very close with the behavior 8750276Speterof the original SVr4 implementation, although in some areas it is quite 8850276Speterclear that this isn't the most appropriate way. As far as possible this 8950276Spetersources will allow you to build a forms lib that behaves quite similar 90166124Srafanto SVr4, but now and in the future we will give you better options. 9150276SpeterPerhaps at some time we will make this configurable at runtime. 9250276Speter*/ 9350276Speter 94166124Srafan/* Implement a more user-friendly previous/next word behavior */ 9550276Speter#define FRIENDLY_PREV_NEXT_WORD (1) 96166124Srafan/* Fix the wrong behavior for forms with all fields inactive */ 9750276Speter#define FIX_FORM_INACTIVE_BUG (1) 9850276Speter/* Allow dynamic field growth also when navigating past the end */ 9950276Speter#define GROW_IF_NAVIGATE (1) 10050276Speter 101166124Srafan#if USE_WIDEC_SUPPORT 102166124Srafan#define myADDNSTR(w, s, n) wadd_wchnstr(w, s, n) 103166124Srafan#define myINSNSTR(w, s, n) wins_wchnstr(w, s, n) 104166124Srafan#define myINNSTR(w, s, n) fix_wchnstr(w, s, n) 105166124Srafan#define myWCWIDTH(w, y, x) cell_width(w, y, x) 106166124Srafan#else 107166124Srafan#define myADDNSTR(w, s, n) waddnstr(w, s, n) 108166124Srafan#define myINSNSTR(w, s, n) winsnstr(w, s, n) 109166124Srafan#define myINNSTR(w, s, n) winnstr(w, s, n) 110166124Srafan#define myWCWIDTH(w, y, x) 1 111166124Srafan#endif 112166124Srafan 11350276Speter/*---------------------------------------------------------------------------- 11450276Speter Forward references to some internally used static functions 11550276Speter --------------------------------------------------------------------------*/ 116166124Srafanstatic int Inter_Field_Navigation(int (*const fct) (FORM *), FORM *form); 117166124Srafanstatic int FN_Next_Field(FORM *form); 118166124Srafanstatic int FN_Previous_Field(FORM *form); 11950276Speterstatic int FE_New_Line(FORM *); 12050276Speterstatic int FE_Delete_Previous(FORM *); 121166124Srafan 12250276Speter/*---------------------------------------------------------------------------- 12350276Speter Macro Definitions. 12450276Speter 12550276Speter Some Remarks on that: I use the convention to use UPPERCASE for constants 12650276Speter defined by Macros. If I provide a macro as a kind of inline routine to 12750276Speter provide some logic, I use my Upper_Lower case style. 12850276Speter --------------------------------------------------------------------------*/ 12950276Speter 13050276Speter/* Calculate the position of a single row in a field buffer */ 13150276Speter#define Position_Of_Row_In_Buffer(field,row) ((row)*(field)->dcols) 13250276Speter 13350276Speter/* Calculate start address for the fields buffer# N */ 13450276Speter#define Address_Of_Nth_Buffer(field,N) \ 13550276Speter ((field)->buf + (N)*(1+Buffer_Length(field))) 13650276Speter 13750276Speter/* Calculate the start address of the row in the fields specified buffer# N */ 13850276Speter#define Address_Of_Row_In_Nth_Buffer(field,N,row) \ 13950276Speter (Address_Of_Nth_Buffer(field,N) + Position_Of_Row_In_Buffer(field,row)) 14050276Speter 14150276Speter/* Calculate the start address of the row in the fields primary buffer */ 14250276Speter#define Address_Of_Row_In_Buffer(field,row) \ 14350276Speter Address_Of_Row_In_Nth_Buffer(field,0,row) 14450276Speter 14550276Speter/* Calculate the start address of the row in the forms current field 14650276Speter buffer# N */ 14750276Speter#define Address_Of_Current_Row_In_Nth_Buffer(form,N) \ 14850276Speter Address_Of_Row_In_Nth_Buffer((form)->current,N,(form)->currow) 14950276Speter 15050276Speter/* Calculate the start address of the row in the forms current field 15150276Speter primary buffer */ 15250276Speter#define Address_Of_Current_Row_In_Buffer(form) \ 15350276Speter Address_Of_Current_Row_In_Nth_Buffer(form,0) 15450276Speter 15550276Speter/* Calculate the address of the cursor in the forms current field 15650276Speter primary buffer */ 15750276Speter#define Address_Of_Current_Position_In_Nth_Buffer(form,N) \ 15850276Speter (Address_Of_Current_Row_In_Nth_Buffer(form,N) + (form)->curcol) 15950276Speter 16050276Speter/* Calculate the address of the cursor in the forms current field 16150276Speter buffer# N */ 16250276Speter#define Address_Of_Current_Position_In_Buffer(form) \ 16350276Speter Address_Of_Current_Position_In_Nth_Buffer(form,0) 16450276Speter 165166124Srafan/* Logic to decide whether or not a field is actually a field with 16650276Speter vertical or horizontal scrolling */ 16750276Speter#define Is_Scroll_Field(field) \ 16850276Speter (((field)->drows > (field)->rows) || \ 16950276Speter ((field)->dcols > (field)->cols)) 17050276Speter 17150276Speter/* Logic to decide whether or not a field needs to have an individual window 17250276Speter instead of a derived window because it contains invisible parts. 17350276Speter This is true for non-public fields and for scrollable fields. */ 17450276Speter#define Has_Invisible_Parts(field) \ 17550276Speter (!((field)->opts & O_PUBLIC) || \ 17650276Speter Is_Scroll_Field(field)) 17750276Speter 17850276Speter/* Logic to decide whether or not a field needs justification */ 17950276Speter#define Justification_Allowed(field) \ 18050276Speter (((field)->just != NO_JUSTIFICATION) && \ 18150276Speter (Single_Line_Field(field)) && \ 18250276Speter (((field)->dcols == (field)->cols) && \ 18350276Speter ((field)->opts & O_STATIC)) ) 18450276Speter 18550276Speter/* Logic to determine whether or not a dynamic field may still grow */ 18650276Speter#define Growable(field) ((field)->status & _MAY_GROW) 18750276Speter 18850276Speter/* Macro to set the attributes for a fields window */ 18950276Speter#define Set_Field_Window_Attributes(field,win) \ 19050276Speter( wbkgdset((win),(chtype)((field)->pad | (field)->back)), \ 19150276Speter wattrset((win),(field)->fore) ) 19250276Speter 19350276Speter/* Logic to decide whether or not a field really appears on the form */ 19450276Speter#define Field_Really_Appears(field) \ 19550276Speter ((field->form) &&\ 19650276Speter (field->form->status & _POSTED) &&\ 19750276Speter (field->opts & O_VISIBLE) &&\ 19850276Speter (field->page == field->form->curpage)) 19950276Speter 20050276Speter/* Logic to determine whether or not we are on the first position in the 20150276Speter current field */ 20250276Speter#define First_Position_In_Current_Field(form) \ 20350276Speter (((form)->currow==0) && ((form)->curcol==0)) 20450276Speter 20550276Speter#define Minimum(a,b) (((a)<=(b)) ? (a) : (b)) 20650276Speter#define Maximum(a,b) (((a)>=(b)) ? (a) : (b)) 207166124Srafan 208166124Srafan/*---------------------------------------------------------------------------- 209166124Srafan Useful constants 210166124Srafan --------------------------------------------------------------------------*/ 211166124Srafanstatic FIELD_CELL myBLANK = BLANK; 212166124Srafanstatic FIELD_CELL myZEROS; 213166124Srafan 214166124Srafan#ifdef TRACE 215166124Srafanstatic void 216166124Srafancheck_pos(FORM *form, int lineno) 217166124Srafan{ 218166124Srafan int y, x; 219166124Srafan 220166124Srafan if (form && form->w) 221166124Srafan { 222166124Srafan getyx(form->w, y, x); 223166124Srafan if (y != form->currow || x != form->curcol) 224166124Srafan { 225166124Srafan T(("CHECKPOS %s@%d have position %d,%d vs want %d,%d", 226166124Srafan __FILE__, lineno, 227166124Srafan y, x, 228166124Srafan form->currow, form->curcol)); 229166124Srafan } 230166124Srafan } 231166124Srafan} 232166124Srafan#define CHECKPOS(form) check_pos(form, __LINE__) 233166124Srafan#else 234166124Srafan#define CHECKPOS(form) /* nothing */ 235166124Srafan#endif 236166124Srafan 237166124Srafan/*---------------------------------------------------------------------------- 238166124Srafan Wide-character special functions 239166124Srafan --------------------------------------------------------------------------*/ 240166124Srafan#if USE_WIDEC_SUPPORT 241166124Srafan/* like winsnstr */ 242166124Srafanstatic int 243166124Srafanwins_wchnstr(WINDOW *w, cchar_t *s, int n) 244166124Srafan{ 245166124Srafan int code = ERR; 246166124Srafan int y, x; 247166124Srafan 248166124Srafan while (n-- > 0) 249166124Srafan { 250166124Srafan getyx(w, y, x); 251166124Srafan if ((code = wins_wch(w, s++)) != OK) 252166124Srafan break; 253166124Srafan if ((code = wmove(w, y, x + 1)) != OK) 254166124Srafan break; 255166124Srafan } 256166124Srafan return code; 257166124Srafan} 258166124Srafan 259166124Srafan/* win_wchnstr is inconsistent with winnstr, since it returns OK rather than 260166124Srafan * the number of items transferred. 261166124Srafan */ 262166124Srafanstatic int 263166124Srafanfix_wchnstr(WINDOW *w, cchar_t *s, int n) 264166124Srafan{ 265174993Srafan int x; 266174993Srafan 267166124Srafan win_wchnstr(w, s, n); 268174993Srafan /* 269174993Srafan * This function is used to extract the text only from the window. 270174993Srafan * Strip attributes and color from the string so they will not be added 271174993Srafan * back when copying the string to the window. 272174993Srafan */ 273174993Srafan for (x = 0; x < n; ++x) 274174993Srafan { 275174993Srafan RemAttr(s[x], A_ATTRIBUTES); 276174993Srafan SetPair(s[x], 0); 277174993Srafan } 278166124Srafan return n; 279166124Srafan} 280166124Srafan 281166124Srafan/* 282166124Srafan * Returns the column of the base of the given cell. 283166124Srafan */ 284166124Srafanstatic int 285166124Srafancell_base(WINDOW *win, int y, int x) 286166124Srafan{ 287166124Srafan int result = x; 288166124Srafan 289166124Srafan while (LEGALYX(win, y, x)) 290166124Srafan { 291166124Srafan cchar_t *data = &(win->_line[y].text[x]); 292166124Srafan 293166124Srafan if (isWidecBase(CHDEREF(data)) || !isWidecExt(CHDEREF(data))) 294166124Srafan { 295166124Srafan result = x; 296166124Srafan break; 297166124Srafan } 298166124Srafan --x; 299166124Srafan } 300166124Srafan return result; 301166124Srafan} 302166124Srafan 303166124Srafan/* 304166124Srafan * Returns the number of columns needed for the given cell in a window. 305166124Srafan */ 306166124Srafanstatic int 307166124Srafancell_width(WINDOW *win, int y, int x) 308166124Srafan{ 309166124Srafan int result = 1; 310166124Srafan 311166124Srafan if (LEGALYX(win, y, x)) 312166124Srafan { 313166124Srafan cchar_t *data = &(win->_line[y].text[x]); 314166124Srafan 315166124Srafan if (isWidecExt(CHDEREF(data))) 316166124Srafan { 317166124Srafan /* recur, providing the number of columns to the next character */ 318166124Srafan result = cell_width(win, y, x - 1); 319166124Srafan } 320166124Srafan else 321166124Srafan { 322166124Srafan result = wcwidth(CharOf(CHDEREF(data))); 323166124Srafan } 324166124Srafan } 325166124Srafan return result; 326166124Srafan} 327166124Srafan 328166124Srafan/* 329166124Srafan * There is no wide-character function such as wdel_wch(), so we must find 330166124Srafan * all of the cells that comprise a multi-column character and delete them 331166124Srafan * one-by-one. 332166124Srafan */ 333166124Srafanstatic void 334166124Srafandelete_char(FORM *form) 335166124Srafan{ 336166124Srafan int cells = cell_width(form->w, form->currow, form->curcol); 337166124Srafan 338166124Srafan form->curcol = cell_base(form->w, form->currow, form->curcol); 339166124Srafan wmove(form->w, form->currow, form->curcol); 340166124Srafan while (cells-- > 0) 341166124Srafan { 342166124Srafan wdelch(form->w); 343166124Srafan } 344166124Srafan} 345166124Srafan#define DeleteChar(form) delete_char(form) 346166124Srafan#else 347166124Srafan#define DeleteChar(form) \ 348166124Srafan wmove((form)->w, (form)->currow, (form)->curcol), \ 349166124Srafan wdelch((form)->w) 350166124Srafan#endif 351166124Srafan 35250276Speter/*--------------------------------------------------------------------------- 353166124Srafan| Facility : libnform 35450276Speter| Function : static char *Get_Start_Of_Data(char * buf, int blen) 355166124Srafan| 35650276Speter| Description : Return pointer to first non-blank position in buffer. 35750276Speter| If buffer is empty return pointer to buffer itself. 35850276Speter| 35950276Speter| Return Values : Pointer to first non-blank position in buffer 36050276Speter+--------------------------------------------------------------------------*/ 361166124SrafanNCURSES_INLINE static FIELD_CELL * 362166124SrafanGet_Start_Of_Data(FIELD_CELL *buf, int blen) 36350276Speter{ 364166124Srafan FIELD_CELL *p = buf; 365166124Srafan FIELD_CELL *end = &buf[blen]; 36650276Speter 367166124Srafan assert(buf && blen >= 0); 368166124Srafan while ((p < end) && ISBLANK(*p)) 36950276Speter p++; 370166124Srafan return ((p == end) ? buf : p); 37150276Speter} 37250276Speter 37350276Speter/*--------------------------------------------------------------------------- 374166124Srafan| Facility : libnform 37550276Speter| Function : static char *After_End_Of_Data(char * buf, int blen) 376166124Srafan| 37750276Speter| Description : Return pointer after last non-blank position in buffer. 37850276Speter| If buffer is empty, return pointer to buffer itself. 37950276Speter| 380166124Srafan| Return Values : Pointer to position after last non-blank position in 38150276Speter| buffer. 38250276Speter+--------------------------------------------------------------------------*/ 383166124SrafanNCURSES_INLINE static FIELD_CELL * 384166124SrafanAfter_End_Of_Data(FIELD_CELL *buf, int blen) 38550276Speter{ 386166124Srafan FIELD_CELL *p = &buf[blen]; 387166124Srafan 388166124Srafan assert(buf && blen >= 0); 389166124Srafan while ((p > buf) && ISBLANK(p[-1])) 39050276Speter p--; 391166124Srafan return (p); 39250276Speter} 39350276Speter 39450276Speter/*--------------------------------------------------------------------------- 395166124Srafan| Facility : libnform 39650276Speter| Function : static char *Get_First_Whitespace_Character( 39750276Speter| char * buf, int blen) 398166124Srafan| 39950276Speter| Description : Position to the first whitespace character. 40050276Speter| 40150276Speter| Return Values : Pointer to first whitespace character in buffer. 40250276Speter+--------------------------------------------------------------------------*/ 403166124SrafanNCURSES_INLINE static FIELD_CELL * 404166124SrafanGet_First_Whitespace_Character(FIELD_CELL *buf, int blen) 40550276Speter{ 406166124Srafan FIELD_CELL *p = buf; 407166124Srafan FIELD_CELL *end = &p[blen]; 408166124Srafan 409166124Srafan assert(buf && blen >= 0); 410166124Srafan while ((p < end) && !ISBLANK(*p)) 41150276Speter p++; 412166124Srafan return ((p == end) ? buf : p); 41350276Speter} 41450276Speter 41550276Speter/*--------------------------------------------------------------------------- 416166124Srafan| Facility : libnform 41750276Speter| Function : static char *After_Last_Whitespace_Character( 41850276Speter| char * buf, int blen) 419166124Srafan| 42050276Speter| Description : Get the position after the last whitespace character. 42150276Speter| 422166124Srafan| Return Values : Pointer to position after last whitespace character in 42350276Speter| buffer. 42450276Speter+--------------------------------------------------------------------------*/ 425166124SrafanNCURSES_INLINE static FIELD_CELL * 426166124SrafanAfter_Last_Whitespace_Character(FIELD_CELL *buf, int blen) 42750276Speter{ 428166124Srafan FIELD_CELL *p = &buf[blen]; 429166124Srafan 430166124Srafan assert(buf && blen >= 0); 431166124Srafan while ((p > buf) && !ISBLANK(p[-1])) 43250276Speter p--; 433166124Srafan return (p); 43450276Speter} 43550276Speter 43650276Speter/* Set this to 1 to use the div_t version. This is a good idea if your 43750276Speter compiler has an intrinsic div() support. Unfortunately GNU-C has it 438166124Srafan not yet. 43950276Speter N.B.: This only works if form->curcol follows immediately form->currow 440166124Srafan and both are of type int. 44150276Speter*/ 44250276Speter#define USE_DIV_T (0) 44350276Speter 44450276Speter/*--------------------------------------------------------------------------- 445166124Srafan| Facility : libnform 44650276Speter| Function : static void Adjust_Cursor_Position( 44750276Speter| FORM * form, const char * pos) 448166124Srafan| 449166124Srafan| Description : Set current row and column of the form to values 45050276Speter| corresponding to the buffer position. 45150276Speter| 45250276Speter| Return Values : - 45350276Speter+--------------------------------------------------------------------------*/ 454166124SrafanNCURSES_INLINE static void 455166124SrafanAdjust_Cursor_Position(FORM *form, const FIELD_CELL *pos) 45650276Speter{ 45750276Speter FIELD *field; 45850276Speter int idx; 45950276Speter 46050276Speter field = form->current; 461166124Srafan assert(pos >= field->buf && field->dcols > 0); 462166124Srafan idx = (int)(pos - field->buf); 46350276Speter#if USE_DIV_T 464166124Srafan *((div_t *) & (form->currow)) = div(idx, field->dcols); 46550276Speter#else 46650276Speter form->currow = idx / field->dcols; 46750276Speter form->curcol = idx - field->cols * form->currow; 468166124Srafan#endif 469166124Srafan if (field->drows < form->currow) 47050276Speter form->currow = 0; 47150276Speter} 47250276Speter 47350276Speter/*--------------------------------------------------------------------------- 474166124Srafan| Facility : libnform 47550276Speter| Function : static void Buffer_To_Window( 47650276Speter| const FIELD * field, 47750276Speter| WINDOW * win) 478166124Srafan| 479166124Srafan| Description : Copy the buffer to the window. If it is a multi-line 48050276Speter| field, the buffer is split to the lines of the 48150276Speter| window without any editing. 48250276Speter| 48350276Speter| Return Values : - 48450276Speter+--------------------------------------------------------------------------*/ 485166124Srafanstatic void 486166124SrafanBuffer_To_Window(const FIELD *field, WINDOW *win) 48750276Speter{ 48850276Speter int width, height; 489166124Srafan int y, x; 49050276Speter int len; 49150276Speter int row; 492166124Srafan FIELD_CELL *pBuffer; 49350276Speter 49450276Speter assert(win && field); 49550276Speter 496166124Srafan getyx(win, y, x); 497166124Srafan width = getmaxx(win); 49850276Speter height = getmaxy(win); 49950276Speter 500166124Srafan for (row = 0, pBuffer = field->buf; 501166124Srafan row < height; 502166124Srafan row++, pBuffer += width) 50350276Speter { 504166124Srafan if ((len = (int)(After_End_Of_Data(pBuffer, width) - pBuffer)) > 0) 50550276Speter { 506166124Srafan wmove(win, row, 0); 507166124Srafan myADDNSTR(win, pBuffer, len); 50850276Speter } 509166124Srafan } 510166124Srafan wmove(win, y, x); 51150276Speter} 51250276Speter 51350276Speter/*--------------------------------------------------------------------------- 514166124Srafan| Facility : libnform 51550276Speter| Function : static void Window_To_Buffer( 51650276Speter| WINDOW * win, 51750276Speter| FIELD * field) 518166124Srafan| 51950276Speter| Description : Copy the content of the window into the buffer. 52050276Speter| The multiple lines of a window are simply 52150276Speter| concatenated into the buffer. Pad characters in 52250276Speter| the window will be replaced by blanks in the buffer. 52350276Speter| 52450276Speter| Return Values : - 52550276Speter+--------------------------------------------------------------------------*/ 526166124Srafanstatic void 527166124SrafanWindow_To_Buffer(WINDOW *win, FIELD *field) 52850276Speter{ 52950276Speter int pad; 53050276Speter int len = 0; 531166124Srafan FIELD_CELL *p; 53250276Speter int row, height; 53350276Speter 534166124Srafan assert(win && field && field->buf); 535166124Srafan 53650276Speter pad = field->pad; 53750276Speter p = field->buf; 53850276Speter height = getmaxy(win); 53950276Speter 540166124Srafan for (row = 0; (row < height) && (row < field->drows); row++) 54150276Speter { 542166124Srafan wmove(win, row, 0); 543166124Srafan len += myINNSTR(win, p + len, field->dcols); 54450276Speter } 545166124Srafan p[len] = myZEROS; 54650276Speter 54750276Speter /* replace visual padding character by blanks in buffer */ 54850276Speter if (pad != C_BLANK) 54950276Speter { 55050276Speter int i; 551166124Srafan 552166124Srafan for (i = 0; i < len; i++, p++) 55350276Speter { 554166124Srafan if ((unsigned long)CharOf(*p) == ChCharOf(pad) 555166124Srafan#if USE_WIDEC_SUPPORT 556166124Srafan && p->chars[1] == 0 557166124Srafan#endif 558166124Srafan ) 559166124Srafan *p = myBLANK; 56050276Speter } 56150276Speter } 56250276Speter} 56350276Speter 56450276Speter/*--------------------------------------------------------------------------- 565166124Srafan| Facility : libnform 56650276Speter| Function : static void Synchronize_Buffer(FORM * form) 567166124Srafan| 56850276Speter| Description : If there was a change, copy the content of the 56950276Speter| window into the buffer, so the buffer is synchronized 57050276Speter| with the windows content. We have to indicate that the 57150276Speter| buffer needs validation due to the change. 57250276Speter| 57350276Speter| Return Values : - 57450276Speter+--------------------------------------------------------------------------*/ 575166124SrafanNCURSES_INLINE static void 576166124SrafanSynchronize_Buffer(FORM *form) 57750276Speter{ 57850276Speter if (form->status & _WINDOW_MODIFIED) 57950276Speter { 58050276Speter form->status &= ~_WINDOW_MODIFIED; 581166124Srafan form->status |= _FCHECK_REQUIRED; 582166124Srafan Window_To_Buffer(form->w, form->current); 583166124Srafan wmove(form->w, form->currow, form->curcol); 58450276Speter } 58550276Speter} 58650276Speter 58750276Speter/*--------------------------------------------------------------------------- 588166124Srafan| Facility : libnform 58950276Speter| Function : static bool Field_Grown( FIELD *field, int amount) 590166124Srafan| 59150276Speter| Description : This function is called for growable dynamic fields 59250276Speter| only. It has to increase the buffers and to allocate 59350276Speter| a new window for this field. 59450276Speter| This function has the side effect to set a new 59550276Speter| field-buffer pointer, the dcols and drows values 59650276Speter| as well as a new current Window for the field. 59750276Speter| 59850276Speter| Return Values : TRUE - field successfully increased 59950276Speter| FALSE - there was some error 60050276Speter+--------------------------------------------------------------------------*/ 601166124Srafanstatic bool 602166124SrafanField_Grown(FIELD *field, int amount) 60350276Speter{ 60450276Speter bool result = FALSE; 60550276Speter 60650276Speter if (field && Growable(field)) 60750276Speter { 60850276Speter bool single_line_field = Single_Line_Field(field); 60950276Speter int old_buflen = Buffer_Length(field); 61050276Speter int new_buflen; 61150276Speter int old_dcols = field->dcols; 61250276Speter int old_drows = field->drows; 613166124Srafan FIELD_CELL *oldbuf = field->buf; 614166124Srafan FIELD_CELL *newbuf; 61550276Speter 61650276Speter int growth; 61750276Speter FORM *form = field->form; 618166124Srafan bool need_visual_update = ((form != (FORM *)0) && 61950276Speter (form->status & _POSTED) && 620166124Srafan (form->current == field)); 621166124Srafan 62250276Speter if (need_visual_update) 62350276Speter Synchronize_Buffer(form); 624166124Srafan 62550276Speter if (single_line_field) 62650276Speter { 62750276Speter growth = field->cols * amount; 62850276Speter if (field->maxgrow) 629166124Srafan growth = Minimum(field->maxgrow - field->dcols, growth); 63050276Speter field->dcols += growth; 63150276Speter if (field->dcols == field->maxgrow) 63250276Speter field->status &= ~_MAY_GROW; 63350276Speter } 63450276Speter else 63550276Speter { 63650276Speter growth = (field->rows + field->nrow) * amount; 63750276Speter if (field->maxgrow) 638166124Srafan growth = Minimum(field->maxgrow - field->drows, growth); 63950276Speter field->drows += growth; 64050276Speter if (field->drows == field->maxgrow) 64150276Speter field->status &= ~_MAY_GROW; 64250276Speter } 64350276Speter /* drows, dcols changed, so we get really the new buffer length */ 64450276Speter new_buflen = Buffer_Length(field); 645166124Srafan newbuf = (FIELD_CELL *)malloc(Total_Buffer_Size(field)); 64650276Speter if (!newbuf) 647166124Srafan { 648166124Srafan /* restore to previous state */ 64950276Speter field->dcols = old_dcols; 65050276Speter field->drows = old_drows; 651166124Srafan if ((single_line_field && (field->dcols != field->maxgrow)) || 652166124Srafan (!single_line_field && (field->drows != field->maxgrow))) 65350276Speter field->status |= _MAY_GROW; 65450276Speter } 65550276Speter else 656166124Srafan { 657166124Srafan /* Copy all the buffers. This is the reason why we can't just use 658166124Srafan * realloc(). 659166124Srafan */ 660166124Srafan int i, j; 661166124Srafan FIELD_CELL *old_bp; 662166124Srafan FIELD_CELL *new_bp; 663166124Srafan 664166124Srafan result = TRUE; /* allow sharing of recovery on failure */ 665166124Srafan 666174993Srafan T((T_CREATE("fieldcell %p"), newbuf)); 66750276Speter field->buf = newbuf; 668166124Srafan for (i = 0; i <= field->nbuf; i++) 66950276Speter { 670166124Srafan new_bp = Address_Of_Nth_Buffer(field, i); 671166124Srafan old_bp = oldbuf + i * (1 + old_buflen); 672166124Srafan for (j = 0; j < old_buflen; ++j) 673166124Srafan new_bp[j] = old_bp[j]; 674166124Srafan while (j < new_buflen) 675166124Srafan new_bp[j++] = myBLANK; 676166124Srafan new_bp[new_buflen] = myZEROS; 67750276Speter } 67850276Speter 679176187Srafan#if USE_WIDEC_SUPPORT && NCURSES_EXT_FUNCS 680166124Srafan if (wresize(field->working, 1, Buffer_Length(field) + 1) == ERR) 681166124Srafan result = FALSE; 682166124Srafan#endif 683166124Srafan 684166124Srafan if (need_visual_update && result) 685166124Srafan { 686166124Srafan WINDOW *new_window = newpad(field->drows, field->dcols); 687166124Srafan 688166124Srafan if (new_window != 0) 689166124Srafan { 690166124Srafan assert(form != (FORM *)0); 691166124Srafan if (form->w) 692166124Srafan delwin(form->w); 693166124Srafan form->w = new_window; 694166124Srafan Set_Field_Window_Attributes(field, form->w); 695166124Srafan werase(form->w); 696166124Srafan Buffer_To_Window(field, form->w); 697166124Srafan untouchwin(form->w); 698166124Srafan wmove(form->w, form->currow, form->curcol); 69950276Speter } 700166124Srafan else 701166124Srafan result = FALSE; 70250276Speter } 70350276Speter 704166124Srafan if (result) 70550276Speter { 706166124Srafan free(oldbuf); 707166124Srafan /* reflect changes in linked fields */ 708166124Srafan if (field != field->link) 70950276Speter { 710166124Srafan FIELD *linked_field; 711166124Srafan 712166124Srafan for (linked_field = field->link; 713166124Srafan linked_field != field; 714166124Srafan linked_field = linked_field->link) 715166124Srafan { 716166124Srafan linked_field->buf = field->buf; 717166124Srafan linked_field->drows = field->drows; 718166124Srafan linked_field->dcols = field->dcols; 719166124Srafan } 72050276Speter } 72150276Speter } 722166124Srafan else 723166124Srafan { 724166124Srafan /* restore old state */ 725166124Srafan field->dcols = old_dcols; 726166124Srafan field->drows = old_drows; 727166124Srafan field->buf = oldbuf; 728166124Srafan if ((single_line_field && 729166124Srafan (field->dcols != field->maxgrow)) || 730166124Srafan (!single_line_field && 731166124Srafan (field->drows != field->maxgrow))) 732166124Srafan field->status |= _MAY_GROW; 733166124Srafan free(newbuf); 734166124Srafan } 735166124Srafan } 73650276Speter } 737166124Srafan return (result); 73850276Speter} 73950276Speter 740174993Srafan#ifdef NCURSES_MOUSE_VERSION 74150276Speter/*--------------------------------------------------------------------------- 742166124Srafan| Facility : libnform 743174993Srafan| Function : int Field_encloses(FIELD *field, int ry, int rx) 744174993Srafan| 745174993Srafan| Description : Check if the given coordinates lie within the given field. 746174993Srafan| 747174993Srafan| Return Values : E_OK - success 748174993Srafan| E_BAD_ARGUMENT - invalid form pointer 749174993Srafan| E_SYSTEM_ERROR - form has no current field or 750174993Srafan| field-window 751174993Srafan+--------------------------------------------------------------------------*/ 752174993Srafanstatic int 753174993SrafanField_encloses(FIELD *field, int ry, int rx) 754174993Srafan{ 755174993Srafan T((T_CALLED("Field_encloses(%p)"), field)); 756174993Srafan if (field != 0 757174993Srafan && field->frow <= ry 758174993Srafan && (field->frow + field->rows) > ry 759174993Srafan && field->fcol <= rx 760174993Srafan && (field->fcol + field->cols) > rx) 761174993Srafan { 762174993Srafan RETURN(E_OK); 763174993Srafan } 764174993Srafan RETURN(E_INVALID_FIELD); 765174993Srafan} 766174993Srafan#endif 767174993Srafan 768174993Srafan/*--------------------------------------------------------------------------- 769174993Srafan| Facility : libnform 77050276Speter| Function : int _nc_Position_Form_Cursor(FORM * form) 771166124Srafan| 77250276Speter| Description : Position the cursor in the window for the current 773166124Srafan| field to be in sync. with the currow and curcol 77450276Speter| values. 77550276Speter| 77650276Speter| Return Values : E_OK - success 77750276Speter| E_BAD_ARGUMENT - invalid form pointer 77850276Speter| E_SYSTEM_ERROR - form has no current field or 77950276Speter| field-window 78050276Speter+--------------------------------------------------------------------------*/ 78176726SpeterNCURSES_EXPORT(int) 782166124Srafan_nc_Position_Form_Cursor(FORM *form) 78350276Speter{ 784166124Srafan FIELD *field; 78550276Speter WINDOW *formwin; 786166124Srafan 78750276Speter if (!form) 788166124Srafan return (E_BAD_ARGUMENT); 78950276Speter 790166124Srafan if (!form->w || !form->current) 791166124Srafan return (E_SYSTEM_ERROR); 79250276Speter 793166124Srafan field = form->current; 794166124Srafan formwin = Get_Form_Window(form); 79550276Speter 796166124Srafan wmove(form->w, form->currow, form->curcol); 797166124Srafan if (Has_Invisible_Parts(field)) 79850276Speter { 79950276Speter /* in this case fieldwin isn't derived from formwin, so we have 800166124Srafan to move the cursor in formwin by hand... */ 80150276Speter wmove(formwin, 80250276Speter field->frow + form->currow - form->toprow, 80350276Speter field->fcol + form->curcol - form->begincol); 80450276Speter wcursyncup(formwin); 80550276Speter } 806166124Srafan else 80750276Speter wcursyncup(form->w); 808166124Srafan return (E_OK); 80950276Speter} 81050276Speter 81150276Speter/*--------------------------------------------------------------------------- 812166124Srafan| Facility : libnform 81350276Speter| Function : int _nc_Refresh_Current_Field(FORM * form) 814166124Srafan| 81550276Speter| Description : Propagate the changes in the fields window to the 81650276Speter| window of the form. 81750276Speter| 81850276Speter| Return Values : E_OK - on success 81950276Speter| E_BAD_ARGUMENT - invalid form pointer 82050276Speter| E_SYSTEM_ERROR - general error 82150276Speter+--------------------------------------------------------------------------*/ 82276726SpeterNCURSES_EXPORT(int) 823166124Srafan_nc_Refresh_Current_Field(FORM *form) 82450276Speter{ 82550276Speter WINDOW *formwin; 826166124Srafan FIELD *field; 82750276Speter 828166124Srafan T((T_CALLED("_nc_Refresh_Current_Field(%p)"), form)); 829166124Srafan 83050276Speter if (!form) 83150276Speter RETURN(E_BAD_ARGUMENT); 83250276Speter 833166124Srafan if (!form->w || !form->current) 83450276Speter RETURN(E_SYSTEM_ERROR); 83550276Speter 836166124Srafan field = form->current; 837166124Srafan formwin = Get_Form_Window(form); 83850276Speter 83950276Speter if (field->opts & O_PUBLIC) 84050276Speter { 84150276Speter if (Is_Scroll_Field(field)) 84250276Speter { 84350276Speter /* Again, in this case the fieldwin isn't derived from formwin, 84450276Speter so we have to perform a copy operation. */ 84550276Speter if (Single_Line_Field(field)) 846166124Srafan { 847166124Srafan /* horizontal scrolling */ 84850276Speter if (form->curcol < form->begincol) 849166124Srafan form->begincol = form->curcol; 85050276Speter else 85150276Speter { 85250276Speter if (form->curcol >= (form->begincol + field->cols)) 853166124Srafan form->begincol = form->curcol - field->cols + 1; 85450276Speter } 85550276Speter copywin(form->w, 85650276Speter formwin, 85750276Speter 0, 85850276Speter form->begincol, 85950276Speter field->frow, 86050276Speter field->fcol, 86150276Speter field->frow, 86250276Speter field->cols + field->fcol - 1, 86350276Speter 0); 86450276Speter } 86550276Speter else 866166124Srafan { 867166124Srafan /* A multi-line, i.e. vertical scrolling field */ 868166124Srafan int row_after_bottom, first_modified_row, first_unmodified_row; 86950276Speter 87050276Speter if (field->drows > field->rows) 87150276Speter { 87250276Speter row_after_bottom = form->toprow + field->rows; 87350276Speter if (form->currow < form->toprow) 87450276Speter { 87550276Speter form->toprow = form->currow; 87650276Speter field->status |= _NEWTOP; 87750276Speter } 87850276Speter if (form->currow >= row_after_bottom) 87950276Speter { 88050276Speter form->toprow = form->currow - field->rows + 1; 88150276Speter field->status |= _NEWTOP; 88250276Speter } 88350276Speter if (field->status & _NEWTOP) 884166124Srafan { 885166124Srafan /* means we have to copy whole range */ 88650276Speter first_modified_row = form->toprow; 88750276Speter first_unmodified_row = first_modified_row + field->rows; 88850276Speter field->status &= ~_NEWTOP; 88950276Speter } 890166124Srafan else 891166124Srafan { 892166124Srafan /* we try to optimize : finding the range of touched 893166124Srafan lines */ 89450276Speter first_modified_row = form->toprow; 895166124Srafan while (first_modified_row < row_after_bottom) 89650276Speter { 897166124Srafan if (is_linetouched(form->w, first_modified_row)) 89850276Speter break; 89950276Speter first_modified_row++; 90050276Speter } 90150276Speter first_unmodified_row = first_modified_row; 902166124Srafan while (first_unmodified_row < row_after_bottom) 90350276Speter { 904166124Srafan if (!is_linetouched(form->w, first_unmodified_row)) 90550276Speter break; 90650276Speter first_unmodified_row++; 90750276Speter } 90850276Speter } 90950276Speter } 91050276Speter else 91150276Speter { 912166124Srafan first_modified_row = form->toprow; 91350276Speter first_unmodified_row = first_modified_row + field->rows; 91450276Speter } 91550276Speter if (first_unmodified_row != first_modified_row) 91650276Speter copywin(form->w, 91750276Speter formwin, 91850276Speter first_modified_row, 91950276Speter 0, 92050276Speter field->frow + first_modified_row - form->toprow, 92150276Speter field->fcol, 92250276Speter field->frow + first_unmodified_row - form->toprow - 1, 92350276Speter field->cols + field->fcol - 1, 92450276Speter 0); 92550276Speter } 92650276Speter wsyncup(formwin); 92750276Speter } 92850276Speter else 929166124Srafan { 930166124Srafan /* if the field-window is simply a derived window, i.e. contains no 931166124Srafan * invisible parts, the whole thing is trivial 932166124Srafan */ 93350276Speter wsyncup(form->w); 93450276Speter } 93550276Speter } 93650276Speter untouchwin(form->w); 937166124Srafan returnCode(_nc_Position_Form_Cursor(form)); 93850276Speter} 939166124Srafan 94050276Speter/*--------------------------------------------------------------------------- 941166124Srafan| Facility : libnform 94250276Speter| Function : static void Perform_Justification( 94350276Speter| FIELD * field, 94450276Speter| WINDOW * win) 94550276Speter| 946166124Srafan| Description : Output field with requested justification 947166124Srafan| 94850276Speter| Return Values : - 94950276Speter+--------------------------------------------------------------------------*/ 950166124Srafanstatic void 951166124SrafanPerform_Justification(FIELD *field, WINDOW *win) 95250276Speter{ 953166124Srafan FIELD_CELL *bp; 95450276Speter int len; 955166124Srafan int col = 0; 95650276Speter 957166124Srafan bp = Get_Start_Of_Data(field->buf, Buffer_Length(field)); 958166124Srafan len = (int)(After_End_Of_Data(field->buf, Buffer_Length(field)) - bp); 95950276Speter 960166124Srafan if (len > 0) 96150276Speter { 96250276Speter assert(win && (field->drows == 1) && (field->dcols == field->cols)); 96350276Speter 964166124Srafan switch (field->just) 96550276Speter { 96650276Speter case JUSTIFY_LEFT: 96750276Speter break; 96850276Speter case JUSTIFY_CENTER: 969166124Srafan col = (field->cols - len) / 2; 97050276Speter break; 97150276Speter case JUSTIFY_RIGHT: 97250276Speter col = field->cols - len; 97350276Speter break; 97450276Speter default: 97550276Speter break; 97650276Speter } 97750276Speter 978166124Srafan wmove(win, 0, col); 979166124Srafan myADDNSTR(win, bp, len); 98050276Speter } 98150276Speter} 98250276Speter 98350276Speter/*--------------------------------------------------------------------------- 984166124Srafan| Facility : libnform 98550276Speter| Function : static void Undo_Justification( 98650276Speter| FIELD * field, 98750276Speter| WINDOW * win) 988166124Srafan| 98950276Speter| Description : Display field without any justification, i.e. 99050276Speter| left justified 99150276Speter| 99250276Speter| Return Values : - 99350276Speter+--------------------------------------------------------------------------*/ 994166124Srafanstatic void 995166124SrafanUndo_Justification(FIELD *field, WINDOW *win) 99650276Speter{ 997166124Srafan FIELD_CELL *bp; 99850276Speter int len; 99950276Speter 1000166124Srafan bp = Get_Start_Of_Data(field->buf, Buffer_Length(field)); 1001166124Srafan len = (int)(After_End_Of_Data(field->buf, Buffer_Length(field)) - bp); 100250276Speter 1003166124Srafan if (len > 0) 100450276Speter { 100550276Speter assert(win); 1006166124Srafan wmove(win, 0, 0); 1007166124Srafan myADDNSTR(win, bp, len); 100850276Speter } 100950276Speter} 101050276Speter 101150276Speter/*--------------------------------------------------------------------------- 1012166124Srafan| Facility : libnform 101350276Speter| Function : static bool Check_Char( 101450276Speter| FIELDTYPE * typ, 101550276Speter| int ch, 101650276Speter| TypeArgument *argp) 1017166124Srafan| 101850276Speter| Description : Perform a single character check for character ch 1019166124Srafan| according to the fieldtype instance. 102050276Speter| 102150276Speter| Return Values : TRUE - Character is valid 102250276Speter| FALSE - Character is invalid 102350276Speter+--------------------------------------------------------------------------*/ 1024166124Srafanstatic bool 1025166124SrafanCheck_Char(FIELDTYPE *typ, int ch, TypeArgument *argp) 102650276Speter{ 1027166124Srafan if (typ) 102850276Speter { 102950276Speter if (typ->status & _LINKED_TYPE) 103050276Speter { 103150276Speter assert(argp); 1032166124Srafan return ( 1033166124Srafan Check_Char(typ->left, ch, argp->left) || 1034166124Srafan Check_Char(typ->right, ch, argp->right)); 1035166124Srafan } 1036166124Srafan else 103750276Speter { 103850276Speter if (typ->ccheck) 1039166124Srafan return typ->ccheck(ch, (void *)argp); 104050276Speter } 104150276Speter } 1042166124Srafan return (!iscntrl(UChar(ch)) ? TRUE : FALSE); 104350276Speter} 104450276Speter 104550276Speter/*--------------------------------------------------------------------------- 1046166124Srafan| Facility : libnform 104750276Speter| Function : static int Display_Or_Erase_Field( 104850276Speter| FIELD * field, 104950276Speter| bool bEraseFlag) 1050166124Srafan| 105150276Speter| Description : Create a subwindow for the field and display the 105250276Speter| buffer contents (apply justification if required) 105350276Speter| or simply erase the field. 105450276Speter| 105550276Speter| Return Values : E_OK - on success 105650276Speter| E_SYSTEM_ERROR - some error (typical no memory) 105750276Speter+--------------------------------------------------------------------------*/ 1058166124Srafanstatic int 1059166124SrafanDisplay_Or_Erase_Field(FIELD *field, bool bEraseFlag) 106050276Speter{ 106150276Speter WINDOW *win; 106250276Speter WINDOW *fwin; 106350276Speter 106450276Speter if (!field) 106550276Speter return E_SYSTEM_ERROR; 106650276Speter 106750276Speter fwin = Get_Form_Window(field->form); 1068166124Srafan win = derwin(fwin, 1069166124Srafan field->rows, field->cols, field->frow, field->fcol); 107050276Speter 1071166124Srafan if (!win) 107250276Speter return E_SYSTEM_ERROR; 107350276Speter else 107450276Speter { 107550276Speter if (field->opts & O_VISIBLE) 1076166124Srafan Set_Field_Window_Attributes(field, win); 107750276Speter else 1078166124Srafan wattrset(win, WINDOW_ATTRS(fwin)); 107950276Speter werase(win); 108050276Speter } 108150276Speter 108250276Speter if (!bEraseFlag) 108350276Speter { 108450276Speter if (field->opts & O_PUBLIC) 108550276Speter { 108650276Speter if (Justification_Allowed(field)) 1087166124Srafan Perform_Justification(field, win); 108850276Speter else 1089166124Srafan Buffer_To_Window(field, win); 109050276Speter } 109150276Speter field->status &= ~_NEWTOP; 109250276Speter } 109350276Speter wsyncup(win); 109450276Speter delwin(win); 109550276Speter return E_OK; 109650276Speter} 109750276Speter 109850276Speter/* Macros to preset the bEraseFlag */ 109950276Speter#define Display_Field(field) Display_Or_Erase_Field(field,FALSE) 110050276Speter#define Erase_Field(field) Display_Or_Erase_Field(field,TRUE) 110150276Speter 110250276Speter/*--------------------------------------------------------------------------- 1103166124Srafan| Facility : libnform 110450276Speter| Function : static int Synchronize_Field(FIELD * field) 1105166124Srafan| 110650276Speter| Description : Synchronize the windows content with the value in 110750276Speter| the buffer. 110850276Speter| 110950276Speter| Return Values : E_OK - success 1110166124Srafan| E_BAD_ARGUMENT - invalid field pointer 111150276Speter| E_SYSTEM_ERROR - some severe basic error 111250276Speter+--------------------------------------------------------------------------*/ 1113166124Srafanstatic int 1114166124SrafanSynchronize_Field(FIELD *field) 111550276Speter{ 111650276Speter FORM *form; 111750276Speter int res = E_OK; 111850276Speter 111950276Speter if (!field) 1120166124Srafan return (E_BAD_ARGUMENT); 112150276Speter 1122166124Srafan if (((form = field->form) != (FORM *)0) 112350276Speter && Field_Really_Appears(field)) 112450276Speter { 112550276Speter if (field == form->current) 1126166124Srafan { 1127166124Srafan form->currow = form->curcol = form->toprow = form->begincol = 0; 112850276Speter werase(form->w); 1129166124Srafan 1130166124Srafan if ((field->opts & O_PUBLIC) && Justification_Allowed(field)) 1131166124Srafan Undo_Justification(field, form->w); 113250276Speter else 1133166124Srafan Buffer_To_Window(field, form->w); 1134166124Srafan 113550276Speter field->status |= _NEWTOP; 1136166124Srafan res = _nc_Refresh_Current_Field(form); 113750276Speter } 113850276Speter else 1139166124Srafan res = Display_Field(field); 114050276Speter } 114150276Speter field->status |= _CHANGED; 1142166124Srafan return (res); 114350276Speter} 114450276Speter 114550276Speter/*--------------------------------------------------------------------------- 1146166124Srafan| Facility : libnform 114750276Speter| Function : static int Synchronize_Linked_Fields(FIELD * field) 1148166124Srafan| 114950276Speter| Description : Propagate the Synchronize_Field function to all linked 115050276Speter| fields. The first error that occurs in the sequence 1151166124Srafan| of updates is the return value. 115250276Speter| 115350276Speter| Return Values : E_OK - success 1154166124Srafan| E_BAD_ARGUMENT - invalid field pointer 115550276Speter| E_SYSTEM_ERROR - some severe basic error 115650276Speter+--------------------------------------------------------------------------*/ 1157166124Srafanstatic int 1158166124SrafanSynchronize_Linked_Fields(FIELD *field) 115950276Speter{ 116050276Speter FIELD *linked_field; 116150276Speter int res = E_OK; 116250276Speter int syncres; 116350276Speter 116450276Speter if (!field) 1165166124Srafan return (E_BAD_ARGUMENT); 116650276Speter 116750276Speter if (!field->link) 1168166124Srafan return (E_SYSTEM_ERROR); 116950276Speter 1170166124Srafan for (linked_field = field->link; 1171166124Srafan linked_field != field; 1172166124Srafan linked_field = linked_field->link) 117350276Speter { 1174166124Srafan if (((syncres = Synchronize_Field(linked_field)) != E_OK) && 1175166124Srafan (res == E_OK)) 117650276Speter res = syncres; 117750276Speter } 1178166124Srafan return (res); 117950276Speter} 118050276Speter 118150276Speter/*--------------------------------------------------------------------------- 1182166124Srafan| Facility : libnform 118350276Speter| Function : int _nc_Synchronize_Attributes(FIELD * field) 1184166124Srafan| 118550276Speter| Description : If a fields visual attributes have changed, this 118650276Speter| routine is called to propagate those changes to the 1187166124Srafan| screen. 118850276Speter| 118950276Speter| Return Values : E_OK - success 119050276Speter| E_BAD_ARGUMENT - invalid field pointer 119150276Speter| E_SYSTEM_ERROR - some severe basic error 119250276Speter+--------------------------------------------------------------------------*/ 119376726SpeterNCURSES_EXPORT(int) 1194166124Srafan_nc_Synchronize_Attributes(FIELD *field) 119550276Speter{ 119650276Speter FORM *form; 119750276Speter int res = E_OK; 119850276Speter WINDOW *formwin; 119950276Speter 1200166124Srafan T((T_CALLED("_nc_Synchronize_Attributes(%p)"), field)); 1201166124Srafan 120250276Speter if (!field) 1203166124Srafan returnCode(E_BAD_ARGUMENT); 120450276Speter 1205166124Srafan CHECKPOS(field->form); 1206166124Srafan if (((form = field->form) != (FORM *)0) 120750276Speter && Field_Really_Appears(field)) 1208166124Srafan { 1209166124Srafan if (form->current == field) 121050276Speter { 121150276Speter Synchronize_Buffer(form); 1212166124Srafan Set_Field_Window_Attributes(field, form->w); 121350276Speter werase(form->w); 1214166124Srafan wmove(form->w, form->currow, form->curcol); 1215166124Srafan 121650276Speter if (field->opts & O_PUBLIC) 121750276Speter { 121850276Speter if (Justification_Allowed(field)) 1219166124Srafan Undo_Justification(field, form->w); 1220166124Srafan else 1221166124Srafan Buffer_To_Window(field, form->w); 122250276Speter } 1223166124Srafan else 122450276Speter { 1225166124Srafan formwin = Get_Form_Window(form); 1226166124Srafan copywin(form->w, formwin, 1227166124Srafan 0, 0, 1228166124Srafan field->frow, field->fcol, 1229166124Srafan field->rows - 1, field->cols - 1, 0); 123050276Speter wsyncup(formwin); 1231166124Srafan Buffer_To_Window(field, form->w); 1232166124Srafan field->status |= _NEWTOP; /* fake refresh to paint all */ 123350276Speter _nc_Refresh_Current_Field(form); 123450276Speter } 123550276Speter } 1236166124Srafan else 123750276Speter { 123850276Speter res = Display_Field(field); 123950276Speter } 124050276Speter } 1241166124Srafan CHECKPOS(form); 1242166124Srafan returnCode(res); 124350276Speter} 124450276Speter 124550276Speter/*--------------------------------------------------------------------------- 1246166124Srafan| Facility : libnform 124750276Speter| Function : int _nc_Synchronize_Options(FIELD * field, 124850276Speter| Field_Options newopts) 1249166124Srafan| 125050276Speter| Description : If a fields options have changed, this routine is 125150276Speter| called to propagate these changes to the screen and 1252166124Srafan| to really change the behavior of the field. 125350276Speter| 125450276Speter| Return Values : E_OK - success 1255166124Srafan| E_BAD_ARGUMENT - invalid field pointer 1256166124Srafan| E_CURRENT - field is the current one 125750276Speter| E_SYSTEM_ERROR - some severe basic error 125850276Speter+--------------------------------------------------------------------------*/ 125976726SpeterNCURSES_EXPORT(int) 1260166124Srafan_nc_Synchronize_Options(FIELD *field, Field_Options newopts) 126150276Speter{ 126250276Speter Field_Options oldopts; 126350276Speter Field_Options changed_opts; 126450276Speter FORM *form; 126550276Speter int res = E_OK; 126650276Speter 1267166124Srafan T((T_CALLED("_nc_Synchronize_Options(%p,%#x)"), field, newopts)); 1268166124Srafan 126950276Speter if (!field) 1270166124Srafan returnCode(E_BAD_ARGUMENT); 127150276Speter 1272166124Srafan oldopts = field->opts; 127350276Speter changed_opts = oldopts ^ newopts; 1274166124Srafan field->opts = newopts; 1275166124Srafan form = field->form; 127650276Speter 127750276Speter if (form) 127850276Speter { 127950276Speter if (form->current == field) 128050276Speter { 128150276Speter field->opts = oldopts; 1282166124Srafan returnCode(E_CURRENT); 128350276Speter } 128450276Speter 128550276Speter if (form->status & _POSTED) 128650276Speter { 128750276Speter if ((form->curpage == field->page)) 128850276Speter { 128950276Speter if (changed_opts & O_VISIBLE) 129050276Speter { 129150276Speter if (newopts & O_VISIBLE) 129250276Speter res = Display_Field(field); 129350276Speter else 129450276Speter res = Erase_Field(field); 129550276Speter } 129650276Speter else 129750276Speter { 129850276Speter if ((changed_opts & O_PUBLIC) && 129950276Speter (newopts & O_VISIBLE)) 130050276Speter res = Display_Field(field); 130150276Speter } 130250276Speter } 130350276Speter } 130450276Speter } 130550276Speter 130650276Speter if (changed_opts & O_STATIC) 130750276Speter { 130850276Speter bool single_line_field = Single_Line_Field(field); 130950276Speter int res2 = E_OK; 131050276Speter 131150276Speter if (newopts & O_STATIC) 1312166124Srafan { 1313166124Srafan /* the field becomes now static */ 131450276Speter field->status &= ~_MAY_GROW; 131550276Speter /* if actually we have no hidden columns, justification may 131650276Speter occur again */ 1317166124Srafan if (single_line_field && 1318166124Srafan (field->cols == field->dcols) && 131950276Speter (field->just != NO_JUSTIFICATION) && 132050276Speter Field_Really_Appears(field)) 132150276Speter { 132250276Speter res2 = Display_Field(field); 132350276Speter } 132450276Speter } 132550276Speter else 1326166124Srafan { 1327166124Srafan /* field is no longer static */ 1328166124Srafan if ((field->maxgrow == 0) || 1329166124Srafan (single_line_field && (field->dcols < field->maxgrow)) || 133050276Speter (!single_line_field && (field->drows < field->maxgrow))) 133150276Speter { 133250276Speter field->status |= _MAY_GROW; 1333166124Srafan /* a field with justification now changes its behavior, 1334166124Srafan so we must redisplay it */ 1335166124Srafan if (single_line_field && 133650276Speter (field->just != NO_JUSTIFICATION) && 133750276Speter Field_Really_Appears(field)) 133850276Speter { 133950276Speter res2 = Display_Field(field); 1340166124Srafan } 1341166124Srafan } 134250276Speter } 134350276Speter if (res2 != E_OK) 134450276Speter res = res2; 134550276Speter } 134650276Speter 1347166124Srafan returnCode(res); 134850276Speter} 134950276Speter 135050276Speter/*--------------------------------------------------------------------------- 1351166124Srafan| Facility : libnform 135250276Speter| Function : int _nc_Set_Current_Field(FORM * form, 135350276Speter| FIELD * newfield) 1354166124Srafan| 135550276Speter| Description : Make the newfield the new current field. 135650276Speter| 1357166124Srafan| Return Values : E_OK - success 1358166124Srafan| E_BAD_ARGUMENT - invalid form or field pointer 1359166124Srafan| E_SYSTEM_ERROR - some severe basic error 1360166124Srafan| E_NOT_CONNECTED - no fields are connected to the form 136150276Speter+--------------------------------------------------------------------------*/ 136276726SpeterNCURSES_EXPORT(int) 1363166124Srafan_nc_Set_Current_Field(FORM *form, FIELD *newfield) 136450276Speter{ 1365166124Srafan FIELD *field; 136650276Speter WINDOW *new_window; 136750276Speter 1368166124Srafan T((T_CALLED("_nc_Set_Current_Field(%p,%p)"), form, newfield)); 136950276Speter 1370166124Srafan if (!form || !newfield || !form->current || (newfield->form != form)) 1371166124Srafan returnCode(E_BAD_ARGUMENT); 137250276Speter 1373166124Srafan if ((form->status & _IN_DRIVER)) 1374166124Srafan returnCode(E_BAD_STATE); 1375166124Srafan 137650276Speter if (!(form->field)) 1377166124Srafan returnCode(E_NOT_CONNECTED); 137850276Speter 137950276Speter field = form->current; 1380166124Srafan 1381166124Srafan if ((field != newfield) || 138250276Speter !(form->status & _POSTED)) 138350276Speter { 1384166124Srafan if ((form->w) && 138550276Speter (field->opts & O_VISIBLE) && 138650276Speter (field->form->curpage == field->page)) 138750276Speter { 138850276Speter _nc_Refresh_Current_Field(form); 138950276Speter if (field->opts & O_PUBLIC) 139050276Speter { 139150276Speter if (field->drows > field->rows) 139250276Speter { 1393166124Srafan if (form->toprow == 0) 139450276Speter field->status &= ~_NEWTOP; 1395166124Srafan else 139650276Speter field->status |= _NEWTOP; 1397166124Srafan } 1398166124Srafan else 139950276Speter { 140050276Speter if (Justification_Allowed(field)) 140150276Speter { 1402166124Srafan Window_To_Buffer(form->w, field); 140350276Speter werase(form->w); 1404166124Srafan Perform_Justification(field, form->w); 140550276Speter wsyncup(form->w); 140650276Speter } 140750276Speter } 140850276Speter } 140950276Speter delwin(form->w); 141076726Speter form->w = (WINDOW *)0; 141150276Speter } 1412166124Srafan 141350276Speter field = newfield; 141450276Speter 141550276Speter if (Has_Invisible_Parts(field)) 1416166124Srafan new_window = newpad(field->drows, field->dcols); 1417166124Srafan else 141850276Speter new_window = derwin(Get_Form_Window(form), 1419166124Srafan field->rows, field->cols, field->frow, field->fcol); 142050276Speter 1421166124Srafan if (!new_window) 1422166124Srafan returnCode(E_SYSTEM_ERROR); 142350276Speter 142450276Speter form->current = field; 142576726Speter 142676726Speter if (form->w) 142776726Speter delwin(form->w); 1428166124Srafan form->w = new_window; 142976726Speter 143050276Speter form->status &= ~_WINDOW_MODIFIED; 1431166124Srafan Set_Field_Window_Attributes(field, form->w); 143250276Speter 143350276Speter if (Has_Invisible_Parts(field)) 143450276Speter { 143550276Speter werase(form->w); 1436166124Srafan Buffer_To_Window(field, form->w); 1437166124Srafan } 1438166124Srafan else 143950276Speter { 144050276Speter if (Justification_Allowed(field)) 144150276Speter { 144250276Speter werase(form->w); 1443166124Srafan Undo_Justification(field, form->w); 144450276Speter wsyncup(form->w); 144550276Speter } 144650276Speter } 144750276Speter 144850276Speter untouchwin(form->w); 144950276Speter } 145050276Speter 145150276Speter form->currow = form->curcol = form->toprow = form->begincol = 0; 1452166124Srafan returnCode(E_OK); 145350276Speter} 1454166124Srafan 145550276Speter/*---------------------------------------------------------------------------- 145650276Speter Intra-Field Navigation routines 145750276Speter --------------------------------------------------------------------------*/ 145850276Speter 145950276Speter/*--------------------------------------------------------------------------- 1460166124Srafan| Facility : libnform 146150276Speter| Function : static int IFN_Next_Character(FORM * form) 1462166124Srafan| 1463166124Srafan| Description : Move to the next character in the field. In a multi-line 146450276Speter| field this wraps at the end of the line. 146550276Speter| 146650276Speter| Return Values : E_OK - success 146750276Speter| E_REQUEST_DENIED - at the rightmost position 146850276Speter+--------------------------------------------------------------------------*/ 1469166124Srafanstatic int 1470166124SrafanIFN_Next_Character(FORM *form) 147150276Speter{ 147250276Speter FIELD *field = form->current; 1473166124Srafan int step = myWCWIDTH(form->w, form->currow, form->curcol); 1474166124Srafan 1475166124Srafan T((T_CALLED("IFN_Next_Character(%p)"), form)); 1476166124Srafan if ((form->curcol += step) == field->dcols) 147750276Speter { 1478166124Srafan if ((++(form->currow)) == field->drows) 147950276Speter { 148050276Speter#if GROW_IF_NAVIGATE 1481166124Srafan if (!Single_Line_Field(field) && Field_Grown(field, 1)) 1482166124Srafan { 1483166124Srafan form->curcol = 0; 1484166124Srafan returnCode(E_OK); 1485166124Srafan } 148650276Speter#endif 148750276Speter form->currow--; 148850276Speter#if GROW_IF_NAVIGATE 1489166124Srafan if (Single_Line_Field(field) && Field_Grown(field, 1)) 1490166124Srafan returnCode(E_OK); 149150276Speter#endif 1492166124Srafan form->curcol -= step; 1493166124Srafan returnCode(E_REQUEST_DENIED); 149450276Speter } 149550276Speter form->curcol = 0; 149650276Speter } 1497166124Srafan returnCode(E_OK); 149850276Speter} 149950276Speter 150050276Speter/*--------------------------------------------------------------------------- 1501166124Srafan| Facility : libnform 150250276Speter| Function : static int IFN_Previous_Character(FORM * form) 1503166124Srafan| 1504166124Srafan| Description : Move to the previous character in the field. In a 1505166124Srafan| multi-line field this wraps and the beginning of the 150650276Speter| line. 150750276Speter| 150850276Speter| Return Values : E_OK - success 150950276Speter| E_REQUEST_DENIED - at the leftmost position 151050276Speter+--------------------------------------------------------------------------*/ 1511166124Srafanstatic int 1512166124SrafanIFN_Previous_Character(FORM *form) 151350276Speter{ 1514166124Srafan int amount = myWCWIDTH(form->w, form->currow, form->curcol - 1); 1515166124Srafan int oldcol = form->curcol; 1516166124Srafan 1517166124Srafan T((T_CALLED("IFN_Previous_Character(%p)"), form)); 1518166124Srafan if ((form->curcol -= amount) < 0) 151950276Speter { 1520166124Srafan if ((--(form->currow)) < 0) 152150276Speter { 152250276Speter form->currow++; 1523166124Srafan form->curcol = oldcol; 1524166124Srafan returnCode(E_REQUEST_DENIED); 152550276Speter } 152650276Speter form->curcol = form->current->dcols - 1; 152750276Speter } 1528166124Srafan returnCode(E_OK); 152950276Speter} 153050276Speter 153150276Speter/*--------------------------------------------------------------------------- 1532166124Srafan| Facility : libnform 153350276Speter| Function : static int IFN_Next_Line(FORM * form) 1534166124Srafan| 153550276Speter| Description : Move to the beginning of the next line in the field 153650276Speter| 153750276Speter| Return Values : E_OK - success 153850276Speter| E_REQUEST_DENIED - at the last line 153950276Speter+--------------------------------------------------------------------------*/ 1540166124Srafanstatic int 1541166124SrafanIFN_Next_Line(FORM *form) 154250276Speter{ 154350276Speter FIELD *field = form->current; 154450276Speter 1545166124Srafan T((T_CALLED("IFN_Next_Line(%p)"), form)); 1546166124Srafan if ((++(form->currow)) == field->drows) 154750276Speter { 154850276Speter#if GROW_IF_NAVIGATE 1549166124Srafan if (!Single_Line_Field(field) && Field_Grown(field, 1)) 1550166124Srafan returnCode(E_OK); 155150276Speter#endif 155250276Speter form->currow--; 1553166124Srafan returnCode(E_REQUEST_DENIED); 155450276Speter } 155550276Speter form->curcol = 0; 1556166124Srafan returnCode(E_OK); 155750276Speter} 155850276Speter 155950276Speter/*--------------------------------------------------------------------------- 1560166124Srafan| Facility : libnform 156150276Speter| Function : static int IFN_Previous_Line(FORM * form) 1562166124Srafan| 156350276Speter| Description : Move to the beginning of the previous line in the field 156450276Speter| 156550276Speter| Return Values : E_OK - success 156650276Speter| E_REQUEST_DENIED - at the first line 156750276Speter+--------------------------------------------------------------------------*/ 1568166124Srafanstatic int 1569166124SrafanIFN_Previous_Line(FORM *form) 157050276Speter{ 1571166124Srafan T((T_CALLED("IFN_Previous_Line(%p)"), form)); 1572166124Srafan if ((--(form->currow)) < 0) 157350276Speter { 157450276Speter form->currow++; 1575166124Srafan returnCode(E_REQUEST_DENIED); 157650276Speter } 157750276Speter form->curcol = 0; 1578166124Srafan returnCode(E_OK); 157950276Speter} 158050276Speter 158150276Speter/*--------------------------------------------------------------------------- 1582166124Srafan| Facility : libnform 158350276Speter| Function : static int IFN_Next_Word(FORM * form) 1584166124Srafan| 158550276Speter| Description : Move to the beginning of the next word in the field. 158650276Speter| 158750276Speter| Return Values : E_OK - success 158850276Speter| E_REQUEST_DENIED - there is no next word 158950276Speter+--------------------------------------------------------------------------*/ 1590166124Srafanstatic int 1591166124SrafanIFN_Next_Word(FORM *form) 159250276Speter{ 159350276Speter FIELD *field = form->current; 1594166124Srafan FIELD_CELL *bp = Address_Of_Current_Position_In_Buffer(form); 1595166124Srafan FIELD_CELL *s; 1596166124Srafan FIELD_CELL *t; 159750276Speter 1598166124Srafan T((T_CALLED("IFN_Next_Word(%p)"), form)); 1599166124Srafan 160050276Speter /* We really need access to the data, so we have to synchronize */ 160150276Speter Synchronize_Buffer(form); 160250276Speter 160350276Speter /* Go to the first whitespace after the current position (including 1604166124Srafan current position). This is then the starting point to look for the 1605166124Srafan next non-blank data */ 1606166124Srafan s = Get_First_Whitespace_Character(bp, Buffer_Length(field) - 160750276Speter (int)(bp - field->buf)); 160850276Speter 160950276Speter /* Find the start of the next word */ 1610166124Srafan t = Get_Start_Of_Data(s, Buffer_Length(field) - 161150276Speter (int)(s - field->buf)); 161250276Speter#if !FRIENDLY_PREV_NEXT_WORD 1613166124Srafan if (s == t) 1614166124Srafan returnCode(E_REQUEST_DENIED); 161550276Speter else 161650276Speter#endif 161750276Speter { 1618166124Srafan Adjust_Cursor_Position(form, t); 1619166124Srafan returnCode(E_OK); 162050276Speter } 162150276Speter} 162250276Speter 162350276Speter/*--------------------------------------------------------------------------- 1624166124Srafan| Facility : libnform 162550276Speter| Function : static int IFN_Previous_Word(FORM * form) 1626166124Srafan| 162750276Speter| Description : Move to the beginning of the previous word in the field. 162850276Speter| 162950276Speter| Return Values : E_OK - success 163050276Speter| E_REQUEST_DENIED - there is no previous word 163150276Speter+--------------------------------------------------------------------------*/ 1632166124Srafanstatic int 1633166124SrafanIFN_Previous_Word(FORM *form) 163450276Speter{ 163550276Speter FIELD *field = form->current; 1636166124Srafan FIELD_CELL *bp = Address_Of_Current_Position_In_Buffer(form); 1637166124Srafan FIELD_CELL *s; 1638166124Srafan FIELD_CELL *t; 1639166124Srafan bool again = FALSE; 164050276Speter 1641166124Srafan T((T_CALLED("IFN_Previous_Word(%p)"), form)); 1642166124Srafan 164350276Speter /* We really need access to the data, so we have to synchronize */ 164450276Speter Synchronize_Buffer(form); 164550276Speter 1646166124Srafan s = After_End_Of_Data(field->buf, (int)(bp - field->buf)); 164750276Speter /* s points now right after the last non-blank in the buffer before bp. 164850276Speter If bp was in a word, s equals bp. In this case we must find the last 164950276Speter whitespace in the buffer before bp and repeat the game to really find 165050276Speter the previous word! */ 1651166124Srafan if (s == bp) 165250276Speter again = TRUE; 1653166124Srafan 165450276Speter /* And next call now goes backward to look for the last whitespace 165550276Speter before that, pointing right after this, so it points to the begin 1656166124Srafan of the previous word. 1657166124Srafan */ 1658166124Srafan t = After_Last_Whitespace_Character(field->buf, (int)(s - field->buf)); 165950276Speter#if !FRIENDLY_PREV_NEXT_WORD 1660166124Srafan if (s == t) 1661166124Srafan returnCode(E_REQUEST_DENIED); 166250276Speter#endif 166350276Speter if (again) 1664166124Srafan { 1665166124Srafan /* and do it again, replacing bp by t */ 1666166124Srafan s = After_End_Of_Data(field->buf, (int)(t - field->buf)); 1667166124Srafan t = After_Last_Whitespace_Character(field->buf, (int)(s - field->buf)); 166850276Speter#if !FRIENDLY_PREV_NEXT_WORD 1669166124Srafan if (s == t) 1670166124Srafan returnCode(E_REQUEST_DENIED); 167150276Speter#endif 167250276Speter } 1673166124Srafan Adjust_Cursor_Position(form, t); 1674166124Srafan returnCode(E_OK); 167550276Speter} 167650276Speter 167750276Speter/*--------------------------------------------------------------------------- 1678166124Srafan| Facility : libnform 167950276Speter| Function : static int IFN_Beginning_Of_Field(FORM * form) 1680166124Srafan| 168150276Speter| Description : Place the cursor at the first non-pad character in 1682166124Srafan| the field. 168350276Speter| 1684166124Srafan| Return Values : E_OK - success 168550276Speter+--------------------------------------------------------------------------*/ 1686166124Srafanstatic int 1687166124SrafanIFN_Beginning_Of_Field(FORM *form) 168850276Speter{ 168950276Speter FIELD *field = form->current; 169050276Speter 1691166124Srafan T((T_CALLED("IFN_Beginning_Of_Field(%p)"), form)); 169250276Speter Synchronize_Buffer(form); 169350276Speter Adjust_Cursor_Position(form, 1694166124Srafan Get_Start_Of_Data(field->buf, Buffer_Length(field))); 1695166124Srafan returnCode(E_OK); 169650276Speter} 169750276Speter 169850276Speter/*--------------------------------------------------------------------------- 1699166124Srafan| Facility : libnform 170050276Speter| Function : static int IFN_End_Of_Field(FORM * form) 1701166124Srafan| 170250276Speter| Description : Place the cursor after the last non-pad character in 170350276Speter| the field. If the field occupies the last position in 1704166124Srafan| the buffer, the cursor is positioned on the last 170550276Speter| character. 170650276Speter| 170750276Speter| Return Values : E_OK - success 170850276Speter+--------------------------------------------------------------------------*/ 1709166124Srafanstatic int 1710166124SrafanIFN_End_Of_Field(FORM *form) 171150276Speter{ 171250276Speter FIELD *field = form->current; 1713166124Srafan FIELD_CELL *pos; 171450276Speter 1715166124Srafan T((T_CALLED("IFN_End_Of_Field(%p)"), form)); 171650276Speter Synchronize_Buffer(form); 1717166124Srafan pos = After_End_Of_Data(field->buf, Buffer_Length(field)); 1718166124Srafan if (pos == (field->buf + Buffer_Length(field))) 171950276Speter pos--; 1720166124Srafan Adjust_Cursor_Position(form, pos); 1721166124Srafan returnCode(E_OK); 172250276Speter} 172350276Speter 172450276Speter/*--------------------------------------------------------------------------- 1725166124Srafan| Facility : libnform 172650276Speter| Function : static int IFN_Beginning_Of_Line(FORM * form) 1727166124Srafan| 172850276Speter| Description : Place the cursor on the first non-pad character in 172950276Speter| the current line of the field. 173050276Speter| 173150276Speter| Return Values : E_OK - success 173250276Speter+--------------------------------------------------------------------------*/ 1733166124Srafanstatic int 1734166124SrafanIFN_Beginning_Of_Line(FORM *form) 173550276Speter{ 173650276Speter FIELD *field = form->current; 173750276Speter 1738166124Srafan T((T_CALLED("IFN_Beginning_Of_Line(%p)"), form)); 173950276Speter Synchronize_Buffer(form); 174050276Speter Adjust_Cursor_Position(form, 1741166124Srafan Get_Start_Of_Data(Address_Of_Current_Row_In_Buffer(form), 1742166124Srafan field->dcols)); 1743166124Srafan returnCode(E_OK); 174450276Speter} 174550276Speter 174650276Speter/*--------------------------------------------------------------------------- 1747166124Srafan| Facility : libnform 174850276Speter| Function : static int IFN_End_Of_Line(FORM * form) 1749166124Srafan| 175050276Speter| Description : Place the cursor after the last non-pad character in the 1751166124Srafan| current line of the field. If the field occupies the 175250276Speter| last column in the line, the cursor is positioned on the 175350276Speter| last character of the line. 175450276Speter| 175550276Speter| Return Values : E_OK - success 175650276Speter+--------------------------------------------------------------------------*/ 1757166124Srafanstatic int 1758166124SrafanIFN_End_Of_Line(FORM *form) 175950276Speter{ 176050276Speter FIELD *field = form->current; 1761166124Srafan FIELD_CELL *pos; 1762166124Srafan FIELD_CELL *bp; 176350276Speter 1764166124Srafan T((T_CALLED("IFN_End_Of_Line(%p)"), form)); 176550276Speter Synchronize_Buffer(form); 1766166124Srafan bp = Address_Of_Current_Row_In_Buffer(form); 1767166124Srafan pos = After_End_Of_Data(bp, field->dcols); 176850276Speter if (pos == (bp + field->dcols)) 176950276Speter pos--; 1770166124Srafan Adjust_Cursor_Position(form, pos); 1771166124Srafan returnCode(E_OK); 177250276Speter} 177350276Speter 177450276Speter/*--------------------------------------------------------------------------- 1775166124Srafan| Facility : libnform 177650276Speter| Function : static int IFN_Left_Character(FORM * form) 1777166124Srafan| 177850276Speter| Description : Move one character to the left in the current line. 1779166124Srafan| This doesn't cycle. 178050276Speter| 178150276Speter| Return Values : E_OK - success 178250276Speter| E_REQUEST_DENIED - already in first column 178350276Speter+--------------------------------------------------------------------------*/ 1784166124Srafanstatic int 1785166124SrafanIFN_Left_Character(FORM *form) 178650276Speter{ 1787166124Srafan int amount = myWCWIDTH(form->w, form->currow, form->curcol - 1); 1788166124Srafan int oldcol = form->curcol; 1789166124Srafan 1790166124Srafan T((T_CALLED("IFN_Left_Character(%p)"), form)); 1791166124Srafan if ((form->curcol -= amount) < 0) 179250276Speter { 1793166124Srafan form->curcol = oldcol; 1794166124Srafan returnCode(E_REQUEST_DENIED); 179550276Speter } 1796166124Srafan returnCode(E_OK); 179750276Speter} 179850276Speter 179950276Speter/*--------------------------------------------------------------------------- 1800166124Srafan| Facility : libnform 180150276Speter| Function : static int IFN_Right_Character(FORM * form) 1802166124Srafan| 180350276Speter| Description : Move one character to the right in the current line. 180450276Speter| This doesn't cycle. 180550276Speter| 180650276Speter| Return Values : E_OK - success 180750276Speter| E_REQUEST_DENIED - already in last column 180850276Speter+--------------------------------------------------------------------------*/ 1809166124Srafanstatic int 1810166124SrafanIFN_Right_Character(FORM *form) 181150276Speter{ 1812166124Srafan int amount = myWCWIDTH(form->w, form->currow, form->curcol); 1813166124Srafan int oldcol = form->curcol; 1814166124Srafan 1815166124Srafan T((T_CALLED("IFN_Right_Character(%p)"), form)); 1816166124Srafan if ((form->curcol += amount) >= form->current->dcols) 181750276Speter { 181850276Speter#if GROW_IF_NAVIGATE 181950276Speter FIELD *field = form->current; 1820166124Srafan 1821166124Srafan if (Single_Line_Field(field) && Field_Grown(field, 1)) 1822166124Srafan returnCode(E_OK); 182350276Speter#endif 1824166124Srafan form->curcol = oldcol; 1825166124Srafan returnCode(E_REQUEST_DENIED); 182650276Speter } 1827166124Srafan returnCode(E_OK); 182850276Speter} 182950276Speter 183050276Speter/*--------------------------------------------------------------------------- 1831166124Srafan| Facility : libnform 183250276Speter| Function : static int IFN_Up_Character(FORM * form) 1833166124Srafan| 183450276Speter| Description : Move one line up. This doesn't cycle through the lines 183550276Speter| of the field. 183650276Speter| 183750276Speter| Return Values : E_OK - success 183850276Speter| E_REQUEST_DENIED - already in last column 183950276Speter+--------------------------------------------------------------------------*/ 1840166124Srafanstatic int 1841166124SrafanIFN_Up_Character(FORM *form) 184250276Speter{ 1843166124Srafan T((T_CALLED("IFN_Up_Character(%p)"), form)); 1844166124Srafan if ((--(form->currow)) < 0) 184550276Speter { 184650276Speter form->currow++; 1847166124Srafan returnCode(E_REQUEST_DENIED); 184850276Speter } 1849166124Srafan returnCode(E_OK); 185050276Speter} 185150276Speter 185250276Speter/*--------------------------------------------------------------------------- 1853166124Srafan| Facility : libnform 185450276Speter| Function : static int IFN_Down_Character(FORM * form) 1855166124Srafan| 185650276Speter| Description : Move one line down. This doesn't cycle through the 185750276Speter| lines of the field. 185850276Speter| 185950276Speter| Return Values : E_OK - success 186050276Speter| E_REQUEST_DENIED - already in last column 186150276Speter+--------------------------------------------------------------------------*/ 1862166124Srafanstatic int 1863166124SrafanIFN_Down_Character(FORM *form) 186450276Speter{ 186550276Speter FIELD *field = form->current; 186650276Speter 1867166124Srafan T((T_CALLED("IFN_Down_Character(%p)"), form)); 1868166124Srafan if ((++(form->currow)) == field->drows) 186950276Speter { 187050276Speter#if GROW_IF_NAVIGATE 1871166124Srafan if (!Single_Line_Field(field) && Field_Grown(field, 1)) 1872166124Srafan returnCode(E_OK); 187350276Speter#endif 187450276Speter --(form->currow); 1875166124Srafan returnCode(E_REQUEST_DENIED); 187650276Speter } 1877166124Srafan returnCode(E_OK); 187850276Speter} 187950276Speter/*---------------------------------------------------------------------------- 1880166124Srafan END of Intra-Field Navigation routines 188150276Speter --------------------------------------------------------------------------*/ 1882166124Srafan 188350276Speter/*---------------------------------------------------------------------------- 188450276Speter Vertical scrolling helper routines 188550276Speter --------------------------------------------------------------------------*/ 188650276Speter 188750276Speter/*--------------------------------------------------------------------------- 1888166124Srafan| Facility : libnform 1889166124Srafan| Function : static int VSC_Generic(FORM *form, int nlines) 189050276Speter| 1891166124Srafan| Description : Scroll multi-line field forward (nlines>0) or 1892166124Srafan| backward (nlines<0) this many lines. 189350276Speter| 1894166124Srafan| Return Values : E_OK - success 189550276Speter| E_REQUEST_DENIED - can't scroll 189650276Speter+--------------------------------------------------------------------------*/ 1897166124Srafanstatic int 1898166124SrafanVSC_Generic(FORM *form, int nlines) 189950276Speter{ 190050276Speter FIELD *field = form->current; 190150276Speter int res = E_REQUEST_DENIED; 1902166124Srafan int rows_to_go = (nlines > 0 ? nlines : -nlines); 190350276Speter 1904166124Srafan if (nlines > 0) 190550276Speter { 1906166124Srafan if ((rows_to_go + form->toprow) > (field->drows - field->rows)) 190750276Speter rows_to_go = (field->drows - field->rows - form->toprow); 190850276Speter 190950276Speter if (rows_to_go > 0) 191050276Speter { 191150276Speter form->currow += rows_to_go; 191250276Speter form->toprow += rows_to_go; 191350276Speter res = E_OK; 191450276Speter } 191550276Speter } 191650276Speter else 191750276Speter { 191850276Speter if (rows_to_go > form->toprow) 191950276Speter rows_to_go = form->toprow; 1920166124Srafan 192150276Speter if (rows_to_go > 0) 192250276Speter { 192350276Speter form->currow -= rows_to_go; 192450276Speter form->toprow -= rows_to_go; 192550276Speter res = E_OK; 192650276Speter } 192750276Speter } 1928166124Srafan return (res); 192950276Speter} 193050276Speter/*---------------------------------------------------------------------------- 193150276Speter End of Vertical scrolling helper routines 193250276Speter --------------------------------------------------------------------------*/ 1933166124Srafan 193450276Speter/*---------------------------------------------------------------------------- 193550276Speter Vertical scrolling routines 193650276Speter --------------------------------------------------------------------------*/ 193750276Speter 193850276Speter/*--------------------------------------------------------------------------- 1939166124Srafan| Facility : libnform 194050276Speter| Function : static int Vertical_Scrolling( 194150276Speter| int (* const fct) (FORM *), 194250276Speter| FORM * form) 1943166124Srafan| 1944166124Srafan| Description : Performs the generic vertical scrolling routines. 194550276Speter| This has to check for a multi-line field and to set 1946166124Srafan| the _NEWTOP flag if scrolling really occurred. 194750276Speter| 194850276Speter| Return Values : Propagated error code from low-level driver calls 194950276Speter+--------------------------------------------------------------------------*/ 1950166124Srafanstatic int 1951166124SrafanVertical_Scrolling(int (*const fct) (FORM *), FORM *form) 195250276Speter{ 195350276Speter int res = E_REQUEST_DENIED; 195450276Speter 195550276Speter if (!Single_Line_Field(form->current)) 195650276Speter { 195750276Speter res = fct(form); 195850276Speter if (res == E_OK) 195950276Speter form->current->status |= _NEWTOP; 196050276Speter } 1961166124Srafan return (res); 196250276Speter} 196350276Speter 196450276Speter/*--------------------------------------------------------------------------- 1965166124Srafan| Facility : libnform 196650276Speter| Function : static int VSC_Scroll_Line_Forward(FORM * form) 1967166124Srafan| 196850276Speter| Description : Scroll multi-line field forward a line 196950276Speter| 197050276Speter| Return Values : E_OK - success 197150276Speter| E_REQUEST_DENIED - no data ahead 197250276Speter+--------------------------------------------------------------------------*/ 1973166124Srafanstatic int 1974166124SrafanVSC_Scroll_Line_Forward(FORM *form) 197550276Speter{ 1976166124Srafan T((T_CALLED("VSC_Scroll_Line_Forward(%p)"), form)); 1977166124Srafan returnCode(VSC_Generic(form, 1)); 197850276Speter} 197950276Speter 198050276Speter/*--------------------------------------------------------------------------- 1981166124Srafan| Facility : libnform 198250276Speter| Function : static int VSC_Scroll_Line_Backward(FORM * form) 1983166124Srafan| 198450276Speter| Description : Scroll multi-line field backward a line 198550276Speter| 198650276Speter| Return Values : E_OK - success 198750276Speter| E_REQUEST_DENIED - no data behind 198850276Speter+--------------------------------------------------------------------------*/ 1989166124Srafanstatic int 1990166124SrafanVSC_Scroll_Line_Backward(FORM *form) 199150276Speter{ 1992166124Srafan T((T_CALLED("VSC_Scroll_Line_Backward(%p)"), form)); 1993166124Srafan returnCode(VSC_Generic(form, -1)); 199450276Speter} 199550276Speter 199650276Speter/*--------------------------------------------------------------------------- 1997166124Srafan| Facility : libnform 199850276Speter| Function : static int VSC_Scroll_Page_Forward(FORM * form) 1999166124Srafan| 200050276Speter| Description : Scroll a multi-line field forward a page 200150276Speter| 200250276Speter| Return Values : E_OK - success 200350276Speter| E_REQUEST_DENIED - no data ahead 200450276Speter+--------------------------------------------------------------------------*/ 2005166124Srafanstatic int 2006166124SrafanVSC_Scroll_Page_Forward(FORM *form) 200750276Speter{ 2008166124Srafan T((T_CALLED("VSC_Scroll_Page_Forward(%p)"), form)); 2009166124Srafan returnCode(VSC_Generic(form, form->current->rows)); 201050276Speter} 201150276Speter 201250276Speter/*--------------------------------------------------------------------------- 2013166124Srafan| Facility : libnform 201450276Speter| Function : static int VSC_Scroll_Half_Page_Forward(FORM * form) 2015166124Srafan| 201650276Speter| Description : Scroll a multi-line field forward half a page 201750276Speter| 201850276Speter| Return Values : E_OK - success 201950276Speter| E_REQUEST_DENIED - no data ahead 202050276Speter+--------------------------------------------------------------------------*/ 2021166124Srafanstatic int 2022166124SrafanVSC_Scroll_Half_Page_Forward(FORM *form) 202350276Speter{ 2024166124Srafan T((T_CALLED("VSC_Scroll_Half_Page_Forward(%p)"), form)); 2025166124Srafan returnCode(VSC_Generic(form, (form->current->rows + 1) / 2)); 202650276Speter} 202750276Speter 202850276Speter/*--------------------------------------------------------------------------- 2029166124Srafan| Facility : libnform 203050276Speter| Function : static int VSC_Scroll_Page_Backward(FORM * form) 2031166124Srafan| 203250276Speter| Description : Scroll a multi-line field backward a page 203350276Speter| 203450276Speter| Return Values : E_OK - success 203550276Speter| E_REQUEST_DENIED - no data behind 203650276Speter+--------------------------------------------------------------------------*/ 2037166124Srafanstatic int 2038166124SrafanVSC_Scroll_Page_Backward(FORM *form) 203950276Speter{ 2040166124Srafan T((T_CALLED("VSC_Scroll_Page_Backward(%p)"), form)); 2041166124Srafan returnCode(VSC_Generic(form, -(form->current->rows))); 204250276Speter} 204350276Speter 204450276Speter/*--------------------------------------------------------------------------- 2045166124Srafan| Facility : libnform 204650276Speter| Function : static int VSC_Scroll_Half_Page_Backward(FORM * form) 2047166124Srafan| 204850276Speter| Description : Scroll a multi-line field backward half a page 204950276Speter| 205050276Speter| Return Values : E_OK - success 205150276Speter| E_REQUEST_DENIED - no data behind 205250276Speter+--------------------------------------------------------------------------*/ 2053166124Srafanstatic int 2054166124SrafanVSC_Scroll_Half_Page_Backward(FORM *form) 205550276Speter{ 2056166124Srafan T((T_CALLED("VSC_Scroll_Half_Page_Backward(%p)"), form)); 2057166124Srafan returnCode(VSC_Generic(form, -((form->current->rows + 1) / 2))); 205850276Speter} 205950276Speter/*---------------------------------------------------------------------------- 206050276Speter End of Vertical scrolling routines 206150276Speter --------------------------------------------------------------------------*/ 2062166124Srafan 206350276Speter/*---------------------------------------------------------------------------- 206450276Speter Horizontal scrolling helper routines 206550276Speter --------------------------------------------------------------------------*/ 206650276Speter 206750276Speter/*--------------------------------------------------------------------------- 2068166124Srafan| Facility : libnform 2069166124Srafan| Function : static int HSC_Generic(FORM *form, int ncolumns) 207050276Speter| 2071166124Srafan| Description : Scroll single-line field forward (ncolumns>0) or 2072166124Srafan| backward (ncolumns<0) this many columns. 207350276Speter| 2074166124Srafan| Return Values : E_OK - success 207550276Speter| E_REQUEST_DENIED - can't scroll 207650276Speter+--------------------------------------------------------------------------*/ 2077166124Srafanstatic int 2078166124SrafanHSC_Generic(FORM *form, int ncolumns) 207950276Speter{ 208050276Speter FIELD *field = form->current; 208150276Speter int res = E_REQUEST_DENIED; 2082166124Srafan int cols_to_go = (ncolumns > 0 ? ncolumns : -ncolumns); 208350276Speter 2084166124Srafan if (ncolumns > 0) 208550276Speter { 208650276Speter if ((cols_to_go + form->begincol) > (field->dcols - field->cols)) 208750276Speter cols_to_go = field->dcols - field->cols - form->begincol; 2088166124Srafan 208950276Speter if (cols_to_go > 0) 209050276Speter { 2091166124Srafan form->curcol += cols_to_go; 209250276Speter form->begincol += cols_to_go; 209350276Speter res = E_OK; 209450276Speter } 209550276Speter } 209650276Speter else 209750276Speter { 2098166124Srafan if (cols_to_go > form->begincol) 209950276Speter cols_to_go = form->begincol; 210050276Speter 210150276Speter if (cols_to_go > 0) 210250276Speter { 2103166124Srafan form->curcol -= cols_to_go; 210450276Speter form->begincol -= cols_to_go; 210550276Speter res = E_OK; 210650276Speter } 210750276Speter } 2108166124Srafan return (res); 210950276Speter} 211050276Speter/*---------------------------------------------------------------------------- 211150276Speter End of Horizontal scrolling helper routines 211250276Speter --------------------------------------------------------------------------*/ 2113166124Srafan 211450276Speter/*---------------------------------------------------------------------------- 211550276Speter Horizontal scrolling routines 211650276Speter --------------------------------------------------------------------------*/ 211750276Speter 211850276Speter/*--------------------------------------------------------------------------- 2119166124Srafan| Facility : libnform 212050276Speter| Function : static int Horizontal_Scrolling( 212150276Speter| int (* const fct) (FORM *), 212250276Speter| FORM * form) 2123166124Srafan| 2124166124Srafan| Description : Performs the generic horizontal scrolling routines. 212550276Speter| This has to check for a single-line field. 212650276Speter| 212750276Speter| Return Values : Propagated error code from low-level driver calls 212850276Speter+--------------------------------------------------------------------------*/ 2129166124Srafanstatic int 2130166124SrafanHorizontal_Scrolling(int (*const fct) (FORM *), FORM *form) 213150276Speter{ 213250276Speter if (Single_Line_Field(form->current)) 213350276Speter return fct(form); 213450276Speter else 2135166124Srafan return (E_REQUEST_DENIED); 213650276Speter} 213750276Speter 213850276Speter/*--------------------------------------------------------------------------- 2139166124Srafan| Facility : libnform 214050276Speter| Function : static int HSC_Scroll_Char_Forward(FORM * form) 2141166124Srafan| 214250276Speter| Description : Scroll single-line field forward a character 214350276Speter| 214450276Speter| Return Values : E_OK - success 214550276Speter| E_REQUEST_DENIED - no data ahead 214650276Speter+--------------------------------------------------------------------------*/ 2147166124Srafanstatic int 2148166124SrafanHSC_Scroll_Char_Forward(FORM *form) 214950276Speter{ 2150166124Srafan T((T_CALLED("HSC_Scroll_Char_Forward(%p)"), form)); 2151166124Srafan returnCode(HSC_Generic(form, 1)); 215250276Speter} 215350276Speter 215450276Speter/*--------------------------------------------------------------------------- 2155166124Srafan| Facility : libnform 215650276Speter| Function : static int HSC_Scroll_Char_Backward(FORM * form) 2157166124Srafan| 215850276Speter| Description : Scroll single-line field backward a character 215950276Speter| 216050276Speter| Return Values : E_OK - success 216150276Speter| E_REQUEST_DENIED - no data behind 216250276Speter+--------------------------------------------------------------------------*/ 2163166124Srafanstatic int 2164166124SrafanHSC_Scroll_Char_Backward(FORM *form) 216550276Speter{ 2166166124Srafan T((T_CALLED("HSC_Scroll_Char_Backward(%p)"), form)); 2167166124Srafan returnCode(HSC_Generic(form, -1)); 216850276Speter} 216950276Speter 217050276Speter/*--------------------------------------------------------------------------- 2171166124Srafan| Facility : libnform 217250276Speter| Function : static int HSC_Horizontal_Line_Forward(FORM* form) 2173166124Srafan| 217450276Speter| Description : Scroll single-line field forward a line 217550276Speter| 217650276Speter| Return Values : E_OK - success 217750276Speter| E_REQUEST_DENIED - no data ahead 217850276Speter+--------------------------------------------------------------------------*/ 2179166124Srafanstatic int 2180166124SrafanHSC_Horizontal_Line_Forward(FORM *form) 218150276Speter{ 2182166124Srafan T((T_CALLED("HSC_Horizontal_Line_Forward(%p)"), form)); 2183166124Srafan returnCode(HSC_Generic(form, form->current->cols)); 218450276Speter} 218550276Speter 218650276Speter/*--------------------------------------------------------------------------- 2187166124Srafan| Facility : libnform 218850276Speter| Function : static int HSC_Horizontal_Half_Line_Forward(FORM* form) 2189166124Srafan| 219050276Speter| Description : Scroll single-line field forward half a line 219150276Speter| 219250276Speter| Return Values : E_OK - success 219350276Speter| E_REQUEST_DENIED - no data ahead 219450276Speter+--------------------------------------------------------------------------*/ 2195166124Srafanstatic int 2196166124SrafanHSC_Horizontal_Half_Line_Forward(FORM *form) 219750276Speter{ 2198166124Srafan T((T_CALLED("HSC_Horizontal_Half_Line_Forward(%p)"), form)); 2199166124Srafan returnCode(HSC_Generic(form, (form->current->cols + 1) / 2)); 220050276Speter} 220150276Speter 220250276Speter/*--------------------------------------------------------------------------- 2203166124Srafan| Facility : libnform 220450276Speter| Function : static int HSC_Horizontal_Line_Backward(FORM* form) 2205166124Srafan| 220650276Speter| Description : Scroll single-line field backward a line 220750276Speter| 220850276Speter| Return Values : E_OK - success 220950276Speter| E_REQUEST_DENIED - no data behind 221050276Speter+--------------------------------------------------------------------------*/ 2211166124Srafanstatic int 2212166124SrafanHSC_Horizontal_Line_Backward(FORM *form) 221350276Speter{ 2214166124Srafan T((T_CALLED("HSC_Horizontal_Line_Backward(%p)"), form)); 2215166124Srafan returnCode(HSC_Generic(form, -(form->current->cols))); 221650276Speter} 221750276Speter 221850276Speter/*--------------------------------------------------------------------------- 2219166124Srafan| Facility : libnform 222050276Speter| Function : static int HSC_Horizontal_Half_Line_Backward(FORM* form) 2221166124Srafan| 222250276Speter| Description : Scroll single-line field backward half a line 222350276Speter| 222450276Speter| Return Values : E_OK - success 222550276Speter| E_REQUEST_DENIED - no data behind 222650276Speter+--------------------------------------------------------------------------*/ 2227166124Srafanstatic int 2228166124SrafanHSC_Horizontal_Half_Line_Backward(FORM *form) 222950276Speter{ 2230166124Srafan T((T_CALLED("HSC_Horizontal_Half_Line_Backward(%p)"), form)); 2231166124Srafan returnCode(HSC_Generic(form, -((form->current->cols + 1) / 2))); 223250276Speter} 223350276Speter 223450276Speter/*---------------------------------------------------------------------------- 223550276Speter End of Horizontal scrolling routines 223650276Speter --------------------------------------------------------------------------*/ 2237166124Srafan 223850276Speter/*---------------------------------------------------------------------------- 223950276Speter Helper routines for Field Editing 224050276Speter --------------------------------------------------------------------------*/ 224150276Speter 224250276Speter/*--------------------------------------------------------------------------- 2243166124Srafan| Facility : libnform 224450276Speter| Function : static bool Is_There_Room_For_A_Line(FORM * form) 2245166124Srafan| 224650276Speter| Description : Check whether or not there is enough room in the 224750276Speter| buffer to enter a whole line. 224850276Speter| 224950276Speter| Return Values : TRUE - there is enough space 225050276Speter| FALSE - there is not enough space 225150276Speter+--------------------------------------------------------------------------*/ 2252166124SrafanNCURSES_INLINE static bool 2253166124SrafanIs_There_Room_For_A_Line(FORM *form) 225450276Speter{ 225550276Speter FIELD *field = form->current; 2256166124Srafan FIELD_CELL *begin_of_last_line, *s; 2257166124Srafan 225850276Speter Synchronize_Buffer(form); 2259166124Srafan begin_of_last_line = Address_Of_Row_In_Buffer(field, (field->drows - 1)); 2260166124Srafan s = After_End_Of_Data(begin_of_last_line, field->dcols); 2261166124Srafan return ((s == begin_of_last_line) ? TRUE : FALSE); 226250276Speter} 226350276Speter 226450276Speter/*--------------------------------------------------------------------------- 2265166124Srafan| Facility : libnform 226650276Speter| Function : static bool Is_There_Room_For_A_Char_In_Line(FORM * form) 2267166124Srafan| 226850276Speter| Description : Checks whether or not there is room for a new character 226950276Speter| in the current line. 227050276Speter| 227150276Speter| Return Values : TRUE - there is room 227250276Speter| FALSE - there is not enough room (line full) 227350276Speter+--------------------------------------------------------------------------*/ 2274166124SrafanNCURSES_INLINE static bool 2275166124SrafanIs_There_Room_For_A_Char_In_Line(FORM *form) 227650276Speter{ 227750276Speter int last_char_in_line; 227850276Speter 2279166124Srafan wmove(form->w, form->currow, form->current->dcols - 1); 2280166124Srafan last_char_in_line = (int)(winch(form->w) & A_CHARTEXT); 2281166124Srafan wmove(form->w, form->currow, form->curcol); 228250276Speter return (((last_char_in_line == form->current->pad) || 228350276Speter is_blank(last_char_in_line)) ? TRUE : FALSE); 228450276Speter} 228550276Speter 228650276Speter#define There_Is_No_Room_For_A_Char_In_Line(f) \ 228750276Speter !Is_There_Room_For_A_Char_In_Line(f) 228850276Speter 228950276Speter/*--------------------------------------------------------------------------- 2290166124Srafan| Facility : libnform 229150276Speter| Function : static int Insert_String( 229250276Speter| FORM * form, 229350276Speter| int row, 229450276Speter| char *txt, 229550276Speter| int len ) 2296166124Srafan| 229750276Speter| Description : Insert the 'len' characters beginning at pointer 'txt' 229850276Speter| into the 'row' of the 'form'. The insertion occurs 229950276Speter| on the beginning of the row, all other characters are 2300166124Srafan| moved to the right. After the text a pad character will 230150276Speter| be inserted to separate the text from the rest. If 230250276Speter| necessary the insertion moves characters on the next 230350276Speter| line to make place for the requested insertion string. 230450276Speter| 2305166124Srafan| Return Values : E_OK - success 230650276Speter| E_REQUEST_DENIED - 230750276Speter| E_SYSTEM_ERROR - system error 230850276Speter+--------------------------------------------------------------------------*/ 2309166124Srafanstatic int 2310166124SrafanInsert_String(FORM *form, int row, FIELD_CELL *txt, int len) 2311166124Srafan{ 2312166124Srafan FIELD *field = form->current; 2313166124Srafan FIELD_CELL *bp = Address_Of_Row_In_Buffer(field, row); 2314166124Srafan int datalen = (int)(After_End_Of_Data(bp, field->dcols) - bp); 2315166124Srafan int freelen = field->dcols - datalen; 2316166124Srafan int requiredlen = len + 1; 2317166124Srafan FIELD_CELL *split; 231850276Speter int result = E_REQUEST_DENIED; 231950276Speter 232050276Speter if (freelen >= requiredlen) 232150276Speter { 2322166124Srafan wmove(form->w, row, 0); 2323166124Srafan myINSNSTR(form->w, txt, len); 2324166124Srafan wmove(form->w, row, len); 2325166124Srafan myINSNSTR(form->w, &myBLANK, 1); 232650276Speter return E_OK; 232750276Speter } 232850276Speter else 2329166124Srafan { 2330166124Srafan /* we have to move characters on the next line. If we are on the 2331166124Srafan last line this may work, if the field is growable */ 233250276Speter if ((row == (field->drows - 1)) && Growable(field)) 233350276Speter { 2334166124Srafan if (!Field_Grown(field, 1)) 2335166124Srafan return (E_SYSTEM_ERROR); 233650276Speter /* !!!Side-Effect : might be changed due to growth!!! */ 2337166124Srafan bp = Address_Of_Row_In_Buffer(field, row); 233850276Speter } 233950276Speter 2340166124Srafan if (row < (field->drows - 1)) 2341166124Srafan { 2342166124Srafan split = 2343166124Srafan After_Last_Whitespace_Character(bp, 2344166124Srafan (int)(Get_Start_Of_Data(bp 2345166124Srafan + field->dcols 2346166124Srafan - requiredlen, 2347166124Srafan requiredlen) 2348166124Srafan - bp)); 234950276Speter /* split points now to the first character of the portion of the 235050276Speter line that must be moved to the next line */ 2351166124Srafan datalen = (int)(split - bp); /* + freelen has to stay on this line */ 2352166124Srafan freelen = field->dcols - (datalen + freelen); /* for the next line */ 235350276Speter 2354166124Srafan if ((result = Insert_String(form, row + 1, split, freelen)) == E_OK) 235550276Speter { 2356166124Srafan wmove(form->w, row, datalen); 235750276Speter wclrtoeol(form->w); 2358166124Srafan wmove(form->w, row, 0); 2359166124Srafan myINSNSTR(form->w, txt, len); 2360166124Srafan wmove(form->w, row, len); 2361166124Srafan myINSNSTR(form->w, &myBLANK, 1); 236250276Speter return E_OK; 236350276Speter } 236450276Speter } 2365166124Srafan return (result); 236650276Speter } 236750276Speter} 236850276Speter 236950276Speter/*--------------------------------------------------------------------------- 2370166124Srafan| Facility : libnform 237150276Speter| Function : static int Wrapping_Not_Necessary_Or_Wrapping_Ok( 237250276Speter| FORM * form) 2373166124Srafan| 237450276Speter| Description : If a character has been entered into a field, it may 237550276Speter| be that wrapping has to occur. This routine checks 237650276Speter| whether or not wrapping is required and if so, performs 237750276Speter| the wrapping. 237850276Speter| 237950276Speter| Return Values : E_OK - no wrapping required or wrapping 2380166124Srafan| was successful 238150276Speter| E_REQUEST_DENIED - 238250276Speter| E_SYSTEM_ERROR - some system error 238350276Speter+--------------------------------------------------------------------------*/ 2384166124Srafanstatic int 2385166124SrafanWrapping_Not_Necessary_Or_Wrapping_Ok(FORM *form) 238650276Speter{ 2387166124Srafan FIELD *field = form->current; 238850276Speter int result = E_REQUEST_DENIED; 238950276Speter bool Last_Row = ((field->drows - 1) == form->currow); 239050276Speter 2391166124Srafan if ((field->opts & O_WRAP) && /* wrapping wanted */ 2392166124Srafan (!Single_Line_Field(field)) && /* must be multi-line */ 2393166124Srafan (There_Is_No_Room_For_A_Char_In_Line(form)) && /* line is full */ 2394166124Srafan (!Last_Row || Growable(field))) /* there are more lines */ 239550276Speter { 2396166124Srafan FIELD_CELL *bp; 2397166124Srafan FIELD_CELL *split; 239850276Speter int chars_to_be_wrapped; 239950276Speter int chars_to_remain_on_line; 2400166124Srafan 240150276Speter if (Last_Row) 2402166124Srafan { 2403166124Srafan /* the above logic already ensures, that in this case the field 240450276Speter is growable */ 2405166124Srafan if (!Field_Grown(field, 1)) 240650276Speter return E_SYSTEM_ERROR; 240750276Speter } 240850276Speter bp = Address_Of_Current_Row_In_Buffer(form); 2409166124Srafan Window_To_Buffer(form->w, field); 2410166124Srafan split = After_Last_Whitespace_Character(bp, field->dcols); 241150276Speter /* split points to the first character of the sequence to be brought 241250276Speter on the next line */ 241350276Speter chars_to_remain_on_line = (int)(split - bp); 2414166124Srafan chars_to_be_wrapped = field->dcols - chars_to_remain_on_line; 241550276Speter if (chars_to_remain_on_line > 0) 241650276Speter { 2417166124Srafan if ((result = Insert_String(form, form->currow + 1, split, 2418166124Srafan chars_to_be_wrapped)) == E_OK) 241950276Speter { 2420166124Srafan wmove(form->w, form->currow, chars_to_remain_on_line); 242150276Speter wclrtoeol(form->w); 242250276Speter if (form->curcol >= chars_to_remain_on_line) 242350276Speter { 242450276Speter form->currow++; 242550276Speter form->curcol -= chars_to_remain_on_line; 242650276Speter } 242750276Speter return E_OK; 242850276Speter } 242950276Speter } 243050276Speter else 243150276Speter return E_OK; 2432166124Srafan if (result != E_OK) 243350276Speter { 2434166124Srafan DeleteChar(form); 2435166124Srafan Window_To_Buffer(form->w, field); 243650276Speter result = E_REQUEST_DENIED; 243750276Speter } 243850276Speter } 243950276Speter else 2440166124Srafan result = E_OK; /* wrapping was not necessary */ 2441166124Srafan return (result); 244250276Speter} 2443166124Srafan 244450276Speter/*---------------------------------------------------------------------------- 244550276Speter Field Editing routines 244650276Speter --------------------------------------------------------------------------*/ 244750276Speter 244850276Speter/*--------------------------------------------------------------------------- 2449166124Srafan| Facility : libnform 245050276Speter| Function : static int Field_Editing( 245150276Speter| int (* const fct) (FORM *), 245250276Speter| FORM * form) 2453166124Srafan| 245450276Speter| Description : Generic routine for field editing requests. The driver 245550276Speter| routines are only called for editable fields, the 2456166124Srafan| _WINDOW_MODIFIED flag is set if editing occurred. 245750276Speter| This is somewhat special due to the overload semantics 245850276Speter| of the NEW_LINE and DEL_PREV requests. 245950276Speter| 246050276Speter| Return Values : Error code from low level drivers. 246150276Speter+--------------------------------------------------------------------------*/ 2462166124Srafanstatic int 2463166124SrafanField_Editing(int (*const fct) (FORM *), FORM *form) 246450276Speter{ 246550276Speter int res = E_REQUEST_DENIED; 246650276Speter 2467166124Srafan /* We have to deal here with the specific case of the overloaded 2468166124Srafan behavior of New_Line and Delete_Previous requests. 246950276Speter They may end up in navigational requests if we are on the first 247050276Speter character in a field. But navigation is also allowed on non- 247150276Speter editable fields. 2472166124Srafan */ 2473166124Srafan if ((fct == FE_Delete_Previous) && 2474166124Srafan (form->opts & O_BS_OVERLOAD) && 2475166124Srafan First_Position_In_Current_Field(form)) 247650276Speter { 2477166124Srafan res = Inter_Field_Navigation(FN_Previous_Field, form); 247850276Speter } 247950276Speter else 248050276Speter { 2481166124Srafan if (fct == FE_New_Line) 248250276Speter { 2483166124Srafan if ((form->opts & O_NL_OVERLOAD) && 248450276Speter First_Position_In_Current_Field(form)) 248550276Speter { 2486166124Srafan res = Inter_Field_Navigation(FN_Next_Field, form); 248750276Speter } 248850276Speter else 248950276Speter /* FE_New_Line deals itself with the _WINDOW_MODIFIED flag */ 249050276Speter res = fct(form); 249150276Speter } 249250276Speter else 249350276Speter { 249450276Speter /* From now on, everything must be editable */ 249550276Speter if (form->current->opts & O_EDIT) 249650276Speter { 249750276Speter res = fct(form); 2498166124Srafan if (res == E_OK) 249950276Speter form->status |= _WINDOW_MODIFIED; 250050276Speter } 250150276Speter } 250250276Speter } 250350276Speter return res; 250450276Speter} 250550276Speter 250650276Speter/*--------------------------------------------------------------------------- 2507166124Srafan| Facility : libnform 250850276Speter| Function : static int FE_New_Line(FORM * form) 2509166124Srafan| 251050276Speter| Description : Perform a new line request. This is rather complex 2511166124Srafan| compared to other routines in this code due to the 251250276Speter| rather difficult to understand description in the 251350276Speter| manuals. 251450276Speter| 251550276Speter| Return Values : E_OK - success 251650276Speter| E_REQUEST_DENIED - new line not allowed 251750276Speter| E_SYSTEM_ERROR - system error 251850276Speter+--------------------------------------------------------------------------*/ 2519166124Srafanstatic int 2520166124SrafanFE_New_Line(FORM *form) 252150276Speter{ 2522166124Srafan FIELD *field = form->current; 2523166124Srafan FIELD_CELL *bp, *t; 2524166124Srafan bool Last_Row = ((field->drows - 1) == form->currow); 2525166124Srafan 2526166124Srafan T((T_CALLED("FE_New_Line(%p)"), form)); 2527166124Srafan if (form->status & _OVLMODE) 252850276Speter { 2529166124Srafan if (Last_Row && 253050276Speter (!(Growable(field) && !Single_Line_Field(field)))) 253150276Speter { 253250276Speter if (!(form->opts & O_NL_OVERLOAD)) 2533166124Srafan returnCode(E_REQUEST_DENIED); 2534166124Srafan wmove(form->w, form->currow, form->curcol); 253550276Speter wclrtoeol(form->w); 253650276Speter /* we have to set this here, although it is also 253750276Speter handled in the generic routine. The reason is, 253850276Speter that FN_Next_Field may fail, but the form is 253950276Speter definitively changed */ 254050276Speter form->status |= _WINDOW_MODIFIED; 2541166124Srafan returnCode(Inter_Field_Navigation(FN_Next_Field, form)); 254250276Speter } 2543166124Srafan else 254450276Speter { 2545166124Srafan if (Last_Row && !Field_Grown(field, 1)) 2546166124Srafan { 2547166124Srafan /* N.B.: due to the logic in the 'if', LastRow==TRUE 2548166124Srafan means here that the field is growable and not 2549166124Srafan a single-line field */ 2550166124Srafan returnCode(E_SYSTEM_ERROR); 255150276Speter } 2552166124Srafan wmove(form->w, form->currow, form->curcol); 255350276Speter wclrtoeol(form->w); 255450276Speter form->currow++; 255550276Speter form->curcol = 0; 255650276Speter form->status |= _WINDOW_MODIFIED; 2557166124Srafan returnCode(E_OK); 255850276Speter } 255950276Speter } 2560166124Srafan else 2561166124Srafan { 2562166124Srafan /* Insert Mode */ 256350276Speter if (Last_Row && 256450276Speter !(Growable(field) && !Single_Line_Field(field))) 256550276Speter { 256650276Speter if (!(form->opts & O_NL_OVERLOAD)) 2567166124Srafan returnCode(E_REQUEST_DENIED); 2568166124Srafan returnCode(Inter_Field_Navigation(FN_Next_Field, form)); 256950276Speter } 2570166124Srafan else 257150276Speter { 257250276Speter bool May_Do_It = !Last_Row && Is_There_Room_For_A_Line(form); 2573166124Srafan 257450276Speter if (!(May_Do_It || Growable(field))) 2575166124Srafan returnCode(E_REQUEST_DENIED); 2576166124Srafan if (!May_Do_It && !Field_Grown(field, 1)) 2577166124Srafan returnCode(E_SYSTEM_ERROR); 2578166124Srafan 2579166124Srafan bp = Address_Of_Current_Position_In_Buffer(form); 2580166124Srafan t = After_End_Of_Data(bp, field->dcols - form->curcol); 2581166124Srafan wmove(form->w, form->currow, form->curcol); 258250276Speter wclrtoeol(form->w); 258350276Speter form->currow++; 2584166124Srafan form->curcol = 0; 2585166124Srafan wmove(form->w, form->currow, form->curcol); 258650276Speter winsertln(form->w); 2587166124Srafan myADDNSTR(form->w, bp, (int)(t - bp)); 258850276Speter form->status |= _WINDOW_MODIFIED; 2589166124Srafan returnCode(E_OK); 259050276Speter } 259150276Speter } 259250276Speter} 259350276Speter 259450276Speter/*--------------------------------------------------------------------------- 2595166124Srafan| Facility : libnform 259650276Speter| Function : static int FE_Insert_Character(FORM * form) 2597166124Srafan| 259850276Speter| Description : Insert blank character at the cursor position 259950276Speter| 260050276Speter| Return Values : E_OK 260150276Speter| E_REQUEST_DENIED 260250276Speter+--------------------------------------------------------------------------*/ 2603166124Srafanstatic int 2604166124SrafanFE_Insert_Character(FORM *form) 260550276Speter{ 260650276Speter FIELD *field = form->current; 260750276Speter int result = E_REQUEST_DENIED; 260850276Speter 2609166124Srafan T((T_CALLED("FE_Insert_Character(%p)"), form)); 2610166124Srafan if (Check_Char(field->type, (int)C_BLANK, (TypeArgument *)(field->arg))) 261150276Speter { 261250276Speter bool There_Is_Room = Is_There_Room_For_A_Char_In_Line(form); 261350276Speter 261450276Speter if (There_Is_Room || 261550276Speter ((Single_Line_Field(field) && Growable(field)))) 261650276Speter { 2617166124Srafan if (!There_Is_Room && !Field_Grown(field, 1)) 2618166124Srafan result = E_SYSTEM_ERROR; 261950276Speter else 262050276Speter { 2621166124Srafan winsch(form->w, (chtype)C_BLANK); 262250276Speter result = Wrapping_Not_Necessary_Or_Wrapping_Ok(form); 262350276Speter } 262450276Speter } 262550276Speter } 2626166124Srafan returnCode(result); 262750276Speter} 262850276Speter 262950276Speter/*--------------------------------------------------------------------------- 2630166124Srafan| Facility : libnform 263150276Speter| Function : static int FE_Insert_Line(FORM * form) 2632166124Srafan| 263350276Speter| Description : Insert a blank line at the cursor position 263450276Speter| 263550276Speter| Return Values : E_OK - success 263650276Speter| E_REQUEST_DENIED - line can not be inserted 263750276Speter+--------------------------------------------------------------------------*/ 2638166124Srafanstatic int 2639166124SrafanFE_Insert_Line(FORM *form) 264050276Speter{ 264150276Speter FIELD *field = form->current; 264250276Speter int result = E_REQUEST_DENIED; 264350276Speter 2644166124Srafan T((T_CALLED("FE_Insert_Line(%p)"), form)); 2645166124Srafan if (Check_Char(field->type, (int)C_BLANK, (TypeArgument *)(field->arg))) 264650276Speter { 2647166124Srafan bool Maybe_Done = (form->currow != (field->drows - 1)) && 2648166124Srafan Is_There_Room_For_A_Line(form); 264950276Speter 265050276Speter if (!Single_Line_Field(field) && 265150276Speter (Maybe_Done || Growable(field))) 265250276Speter { 2653166124Srafan if (!Maybe_Done && !Field_Grown(field, 1)) 265450276Speter result = E_SYSTEM_ERROR; 265550276Speter else 265650276Speter { 265750276Speter form->curcol = 0; 265850276Speter winsertln(form->w); 265950276Speter result = E_OK; 266050276Speter } 266150276Speter } 266250276Speter } 2663166124Srafan returnCode(result); 266450276Speter} 266550276Speter 266650276Speter/*--------------------------------------------------------------------------- 2667166124Srafan| Facility : libnform 266850276Speter| Function : static int FE_Delete_Character(FORM * form) 2669166124Srafan| 267050276Speter| Description : Delete character at the cursor position 267150276Speter| 267250276Speter| Return Values : E_OK - success 267350276Speter+--------------------------------------------------------------------------*/ 2674166124Srafanstatic int 2675166124SrafanFE_Delete_Character(FORM *form) 267650276Speter{ 2677166124Srafan T((T_CALLED("FE_Delete_Character(%p)"), form)); 2678166124Srafan DeleteChar(form); 2679166124Srafan returnCode(E_OK); 268050276Speter} 268150276Speter 268250276Speter/*--------------------------------------------------------------------------- 2683166124Srafan| Facility : libnform 268450276Speter| Function : static int FE_Delete_Previous(FORM * form) 2685166124Srafan| 268650276Speter| Description : Delete character before cursor. Again this is a rather 268750276Speter| difficult piece compared to others due to the overloading 268850276Speter| semantics of backspace. 268950276Speter| N.B.: The case of overloaded BS on first field position 269050276Speter| is already handled in the generic routine. 269150276Speter| 269250276Speter| Return Values : E_OK - success 269350276Speter| E_REQUEST_DENIED - Character can't be deleted 269450276Speter+--------------------------------------------------------------------------*/ 2695166124Srafanstatic int 2696166124SrafanFE_Delete_Previous(FORM *form) 269750276Speter{ 2698166124Srafan FIELD *field = form->current; 2699166124Srafan 2700166124Srafan T((T_CALLED("FE_Delete_Previous(%p)"), form)); 270150276Speter if (First_Position_In_Current_Field(form)) 2702166124Srafan returnCode(E_REQUEST_DENIED); 270350276Speter 2704166124Srafan if ((--(form->curcol)) < 0) 270550276Speter { 2706166124Srafan FIELD_CELL *this_line, *prev_line, *prev_end, *this_end; 2707166124Srafan int this_row = form->currow; 2708166124Srafan 270950276Speter form->curcol++; 2710166124Srafan if (form->status & _OVLMODE) 2711166124Srafan returnCode(E_REQUEST_DENIED); 2712166124Srafan 2713166124Srafan prev_line = Address_Of_Row_In_Buffer(field, (form->currow - 1)); 2714166124Srafan this_line = Address_Of_Row_In_Buffer(field, (form->currow)); 271550276Speter Synchronize_Buffer(form); 2716166124Srafan prev_end = After_End_Of_Data(prev_line, field->dcols); 2717166124Srafan this_end = After_End_Of_Data(this_line, field->dcols); 2718166124Srafan if ((int)(this_end - this_line) > 2719166124Srafan (field->cols - (int)(prev_end - prev_line))) 2720166124Srafan returnCode(E_REQUEST_DENIED); 2721166124Srafan wmove(form->w, form->currow, form->curcol); 272250276Speter wdeleteln(form->w); 2723166124Srafan Adjust_Cursor_Position(form, prev_end); 2724166124Srafan /* 2725166124Srafan * If we did not really move to the previous line, help the user a 2726166124Srafan * little. It is however a little inconsistent. Normally, when 2727166124Srafan * backspacing around the point where text wraps to a new line in a 2728166124Srafan * multi-line form, we absorb one keystroke for the wrapping point. That 2729166124Srafan * is consistent with SVr4 forms. However, SVr4 does not allow typing 2730166124Srafan * into the last column of the field, and requires the user to enter a 2731166124Srafan * newline to move to the next line. Therefore it can consistently eat 2732166124Srafan * that keystroke. Since ncurses allows the last column, it wraps 2733166124Srafan * automatically (given the proper options). But we cannot eat the 2734166124Srafan * keystroke to back over the wrapping point, since that would put the 2735166124Srafan * cursor past the end of the form field. In this case, just delete the 2736166124Srafan * character at the end of the field. 2737166124Srafan */ 2738166124Srafan if (form->currow == this_row && this_row > 0) 2739166124Srafan { 2740166124Srafan form->currow -= 1; 2741166124Srafan form->curcol = field->dcols - 1; 2742166124Srafan DeleteChar(form); 2743166124Srafan } 2744166124Srafan else 2745166124Srafan { 2746166124Srafan wmove(form->w, form->currow, form->curcol); 2747166124Srafan myADDNSTR(form->w, this_line, (int)(this_end - this_line)); 2748166124Srafan } 2749166124Srafan } 2750166124Srafan else 275150276Speter { 2752166124Srafan DeleteChar(form); 275350276Speter } 2754166124Srafan returnCode(E_OK); 275550276Speter} 275650276Speter 275750276Speter/*--------------------------------------------------------------------------- 2758166124Srafan| Facility : libnform 275950276Speter| Function : static int FE_Delete_Line(FORM * form) 2760166124Srafan| 276150276Speter| Description : Delete line at cursor position. 276250276Speter| 276350276Speter| Return Values : E_OK - success 276450276Speter+--------------------------------------------------------------------------*/ 2765166124Srafanstatic int 2766166124SrafanFE_Delete_Line(FORM *form) 276750276Speter{ 2768166124Srafan T((T_CALLED("FE_Delete_Line(%p)"), form)); 276950276Speter form->curcol = 0; 277050276Speter wdeleteln(form->w); 2771166124Srafan returnCode(E_OK); 277250276Speter} 277350276Speter 277450276Speter/*--------------------------------------------------------------------------- 2775166124Srafan| Facility : libnform 277650276Speter| Function : static int FE_Delete_Word(FORM * form) 2777166124Srafan| 277850276Speter| Description : Delete word at cursor position 277950276Speter| 278050276Speter| Return Values : E_OK - success 278150276Speter| E_REQUEST_DENIED - failure 278250276Speter+--------------------------------------------------------------------------*/ 2783166124Srafanstatic int 2784166124SrafanFE_Delete_Word(FORM *form) 278550276Speter{ 2786166124Srafan FIELD *field = form->current; 2787166124Srafan FIELD_CELL *bp = Address_Of_Current_Row_In_Buffer(form); 2788166124Srafan FIELD_CELL *ep = bp + field->dcols; 2789166124Srafan FIELD_CELL *cp = bp + form->curcol; 2790166124Srafan FIELD_CELL *s; 2791166124Srafan 2792166124Srafan T((T_CALLED("FE_Delete_Word(%p)"), form)); 279350276Speter Synchronize_Buffer(form); 2794166124Srafan if (ISBLANK(*cp)) 2795166124Srafan returnCode(E_REQUEST_DENIED); /* not in word */ 279650276Speter 279750276Speter /* move cursor to begin of word and erase to end of screen-line */ 279850276Speter Adjust_Cursor_Position(form, 2799166124Srafan After_Last_Whitespace_Character(bp, form->curcol)); 2800166124Srafan wmove(form->w, form->currow, form->curcol); 280150276Speter wclrtoeol(form->w); 280250276Speter 280350276Speter /* skip over word in buffer */ 2804166124Srafan s = Get_First_Whitespace_Character(cp, (int)(ep - cp)); 280550276Speter /* to begin of next word */ 2806166124Srafan s = Get_Start_Of_Data(s, (int)(ep - s)); 2807166124Srafan if ((s != cp) && !ISBLANK(*s)) 280850276Speter { 280950276Speter /* copy remaining line to window */ 2810166124Srafan myADDNSTR(form->w, s, (int)(s - After_End_Of_Data(s, (int)(ep - s)))); 281150276Speter } 2812166124Srafan returnCode(E_OK); 281350276Speter} 281450276Speter 281550276Speter/*--------------------------------------------------------------------------- 2816166124Srafan| Facility : libnform 281750276Speter| Function : static int FE_Clear_To_End_Of_Line(FORM * form) 2818166124Srafan| 281950276Speter| Description : Clear to end of current line. 282050276Speter| 282150276Speter| Return Values : E_OK - success 282250276Speter+--------------------------------------------------------------------------*/ 2823166124Srafanstatic int 2824166124SrafanFE_Clear_To_End_Of_Line(FORM *form) 282550276Speter{ 2826166124Srafan T((T_CALLED("FE_Clear_To_End_Of_Line(%p)"), form)); 2827166124Srafan wmove(form->w, form->currow, form->curcol); 282850276Speter wclrtoeol(form->w); 2829166124Srafan returnCode(E_OK); 283050276Speter} 283150276Speter 283250276Speter/*--------------------------------------------------------------------------- 2833166124Srafan| Facility : libnform 2834166124Srafan| Function : static int FE_Clear_To_End_Of_Field(FORM * form) 283550276Speter| 2836166124Srafan| Description : Clear to end of field. 2837166124Srafan| 283850276Speter| Return Values : E_OK - success 283950276Speter+--------------------------------------------------------------------------*/ 2840166124Srafanstatic int 2841166124SrafanFE_Clear_To_End_Of_Field(FORM *form) 284250276Speter{ 2843166124Srafan T((T_CALLED("FE_Clear_To_End_Of_Field(%p)"), form)); 2844166124Srafan wmove(form->w, form->currow, form->curcol); 284550276Speter wclrtobot(form->w); 2846166124Srafan returnCode(E_OK); 284750276Speter} 284850276Speter 284950276Speter/*--------------------------------------------------------------------------- 2850166124Srafan| Facility : libnform 285150276Speter| Function : static int FE_Clear_Field(FORM * form) 2852166124Srafan| 285350276Speter| Description : Clear entire field. 285450276Speter| 285550276Speter| Return Values : E_OK - success 285650276Speter+--------------------------------------------------------------------------*/ 2857166124Srafanstatic int 2858166124SrafanFE_Clear_Field(FORM *form) 285950276Speter{ 2860166124Srafan T((T_CALLED("FE_Clear_Field(%p)"), form)); 286150276Speter form->currow = form->curcol = 0; 286250276Speter werase(form->w); 2863166124Srafan returnCode(E_OK); 286450276Speter} 286550276Speter/*---------------------------------------------------------------------------- 2866166124Srafan END of Field Editing routines 286750276Speter --------------------------------------------------------------------------*/ 2868166124Srafan 286950276Speter/*---------------------------------------------------------------------------- 287050276Speter Edit Mode routines 287150276Speter --------------------------------------------------------------------------*/ 287250276Speter 287350276Speter/*--------------------------------------------------------------------------- 2874166124Srafan| Facility : libnform 287550276Speter| Function : static int EM_Overlay_Mode(FORM * form) 2876166124Srafan| 287750276Speter| Description : Switch to overlay mode. 287850276Speter| 287950276Speter| Return Values : E_OK - success 288050276Speter+--------------------------------------------------------------------------*/ 2881166124Srafanstatic int 2882166124SrafanEM_Overlay_Mode(FORM *form) 288350276Speter{ 2884166124Srafan T((T_CALLED("EM_Overlay_Mode(%p)"), form)); 288550276Speter form->status |= _OVLMODE; 2886166124Srafan returnCode(E_OK); 288750276Speter} 288850276Speter 288950276Speter/*--------------------------------------------------------------------------- 2890166124Srafan| Facility : libnform 289150276Speter| Function : static int EM_Insert_Mode(FORM * form) 2892166124Srafan| 289350276Speter| Description : Switch to insert mode 289450276Speter| 289550276Speter| Return Values : E_OK - success 289650276Speter+--------------------------------------------------------------------------*/ 2897166124Srafanstatic int 2898166124SrafanEM_Insert_Mode(FORM *form) 289950276Speter{ 2900166124Srafan T((T_CALLED("EM_Insert_Mode(%p)"), form)); 290150276Speter form->status &= ~_OVLMODE; 2902166124Srafan returnCode(E_OK); 290350276Speter} 290450276Speter 290550276Speter/*---------------------------------------------------------------------------- 2906166124Srafan END of Edit Mode routines 290750276Speter --------------------------------------------------------------------------*/ 2908166124Srafan 290950276Speter/*---------------------------------------------------------------------------- 291050276Speter Helper routines for Choice Requests 291150276Speter --------------------------------------------------------------------------*/ 291250276Speter 291350276Speter/*--------------------------------------------------------------------------- 2914166124Srafan| Facility : libnform 291550276Speter| Function : static bool Next_Choice( 291650276Speter| FIELDTYPE * typ, 291750276Speter| FIELD * field, 291850276Speter| TypeArgument *argp) 2919166124Srafan| 292050276Speter| Description : Get the next field choice. For linked types this is 292150276Speter| done recursively. 292250276Speter| 292350276Speter| Return Values : TRUE - next choice successfully retrieved 292450276Speter| FALSE - couldn't retrieve next choice 292550276Speter+--------------------------------------------------------------------------*/ 2926166124Srafanstatic bool 2927166124SrafanNext_Choice(FIELDTYPE *typ, FIELD *field, TypeArgument *argp) 292850276Speter{ 2929166124Srafan if (!typ || !(typ->status & _HAS_CHOICE)) 293050276Speter return FALSE; 293150276Speter 293250276Speter if (typ->status & _LINKED_TYPE) 293350276Speter { 293450276Speter assert(argp); 2935166124Srafan return ( 2936166124Srafan Next_Choice(typ->left, field, argp->left) || 2937166124Srafan Next_Choice(typ->right, field, argp->right)); 2938166124Srafan } 293950276Speter else 294050276Speter { 294150276Speter assert(typ->next); 2942166124Srafan return typ->next(field, (void *)argp); 294350276Speter } 294450276Speter} 294550276Speter 294650276Speter/*--------------------------------------------------------------------------- 2947166124Srafan| Facility : libnform 294850276Speter| Function : static bool Previous_Choice( 294950276Speter| FIELDTYPE * typ, 295050276Speter| FIELD * field, 295150276Speter| TypeArgument *argp) 2952166124Srafan| 295350276Speter| Description : Get the previous field choice. For linked types this 295450276Speter| is done recursively. 295550276Speter| 295650276Speter| Return Values : TRUE - previous choice successfully retrieved 295750276Speter| FALSE - couldn't retrieve previous choice 295850276Speter+--------------------------------------------------------------------------*/ 2959166124Srafanstatic bool 2960166124SrafanPrevious_Choice(FIELDTYPE *typ, FIELD *field, TypeArgument *argp) 296150276Speter{ 2962166124Srafan if (!typ || !(typ->status & _HAS_CHOICE)) 296350276Speter return FALSE; 296450276Speter 296550276Speter if (typ->status & _LINKED_TYPE) 296650276Speter { 296750276Speter assert(argp); 2968166124Srafan return ( 2969166124Srafan Previous_Choice(typ->left, field, argp->left) || 2970166124Srafan Previous_Choice(typ->right, field, argp->right)); 2971166124Srafan } 2972166124Srafan else 297350276Speter { 297450276Speter assert(typ->prev); 2975166124Srafan return typ->prev(field, (void *)argp); 297650276Speter } 297750276Speter} 297850276Speter/*---------------------------------------------------------------------------- 297950276Speter End of Helper routines for Choice Requests 298050276Speter --------------------------------------------------------------------------*/ 2981166124Srafan 298250276Speter/*---------------------------------------------------------------------------- 298350276Speter Routines for Choice Requests 298450276Speter --------------------------------------------------------------------------*/ 298550276Speter 298650276Speter/*--------------------------------------------------------------------------- 2987166124Srafan| Facility : libnform 298850276Speter| Function : static int CR_Next_Choice(FORM * form) 2989166124Srafan| 299050276Speter| Description : Get the next field choice. 299150276Speter| 299250276Speter| Return Values : E_OK - success 299350276Speter| E_REQUEST_DENIED - next choice couldn't be retrieved 299450276Speter+--------------------------------------------------------------------------*/ 2995166124Srafanstatic int 2996166124SrafanCR_Next_Choice(FORM *form) 299750276Speter{ 299850276Speter FIELD *field = form->current; 2999166124Srafan 3000166124Srafan T((T_CALLED("CR_Next_Choice(%p)"), form)); 300150276Speter Synchronize_Buffer(form); 3002166124Srafan returnCode((Next_Choice(field->type, field, (TypeArgument *)(field->arg))) 3003166124Srafan ? E_OK 3004166124Srafan : E_REQUEST_DENIED); 300550276Speter} 300650276Speter 300750276Speter/*--------------------------------------------------------------------------- 3008166124Srafan| Facility : libnform 300950276Speter| Function : static int CR_Previous_Choice(FORM * form) 3010166124Srafan| 301150276Speter| Description : Get the previous field choice. 301250276Speter| 301350276Speter| Return Values : E_OK - success 301450276Speter| E_REQUEST_DENIED - prev. choice couldn't be retrieved 301550276Speter+--------------------------------------------------------------------------*/ 3016166124Srafanstatic int 3017166124SrafanCR_Previous_Choice(FORM *form) 301850276Speter{ 301950276Speter FIELD *field = form->current; 3020166124Srafan 3021166124Srafan T((T_CALLED("CR_Previous_Choice(%p)"), form)); 302250276Speter Synchronize_Buffer(form); 3023166124Srafan returnCode((Previous_Choice(field->type, field, (TypeArgument *)(field->arg))) 3024166124Srafan ? E_OK 3025166124Srafan : E_REQUEST_DENIED); 302650276Speter} 302750276Speter/*---------------------------------------------------------------------------- 302850276Speter End of Routines for Choice Requests 302950276Speter --------------------------------------------------------------------------*/ 3030166124Srafan 303150276Speter/*---------------------------------------------------------------------------- 303250276Speter Helper routines for Field Validations. 303350276Speter --------------------------------------------------------------------------*/ 303450276Speter 303550276Speter/*--------------------------------------------------------------------------- 3036166124Srafan| Facility : libnform 303750276Speter| Function : static bool Check_Field( 303850276Speter| FIELDTYPE * typ, 303950276Speter| FIELD * field, 304050276Speter| TypeArgument * argp) 3041166124Srafan| 304250276Speter| Description : Check the field according to its fieldtype and its 304350276Speter| actual arguments. For linked fieldtypes this is done 304450276Speter| recursively. 304550276Speter| 304650276Speter| Return Values : TRUE - field is valid 304750276Speter| FALSE - field is invalid. 304850276Speter+--------------------------------------------------------------------------*/ 3049166124Srafanstatic bool 3050166124SrafanCheck_Field(FIELDTYPE *typ, FIELD *field, TypeArgument *argp) 305150276Speter{ 305250276Speter if (typ) 305350276Speter { 305450276Speter if (field->opts & O_NULLOK) 305550276Speter { 3056166124Srafan FIELD_CELL *bp = field->buf; 3057166124Srafan 305850276Speter assert(bp); 3059166124Srafan while (ISBLANK(*bp)) 3060166124Srafan { 3061166124Srafan bp++; 3062166124Srafan } 3063166124Srafan if (CharOf(*bp) == 0) 306450276Speter return TRUE; 306550276Speter } 306650276Speter 306750276Speter if (typ->status & _LINKED_TYPE) 306850276Speter { 306950276Speter assert(argp); 3070166124Srafan return ( 3071166124Srafan Check_Field(typ->left, field, argp->left) || 3072166124Srafan Check_Field(typ->right, field, argp->right)); 307350276Speter } 3074166124Srafan else 307550276Speter { 307650276Speter if (typ->fcheck) 3077166124Srafan return typ->fcheck(field, (void *)argp); 307850276Speter } 307950276Speter } 308050276Speter return TRUE; 308150276Speter} 308250276Speter 308350276Speter/*--------------------------------------------------------------------------- 3084166124Srafan| Facility : libnform 308550276Speter| Function : bool _nc_Internal_Validation(FORM * form ) 308650276Speter| 3087166124Srafan| Description : Validate the current field of the form. 3088166124Srafan| 308950276Speter| Return Values : TRUE - field is valid 309050276Speter| FALSE - field is invalid 309150276Speter+--------------------------------------------------------------------------*/ 309276726SpeterNCURSES_EXPORT(bool) 3093166124Srafan_nc_Internal_Validation(FORM *form) 309450276Speter{ 309550276Speter FIELD *field; 309650276Speter 3097166124Srafan field = form->current; 3098166124Srafan 309950276Speter Synchronize_Buffer(form); 310050276Speter if ((form->status & _FCHECK_REQUIRED) || 310150276Speter (!(field->opts & O_PASSOK))) 310250276Speter { 3103166124Srafan if (!Check_Field(field->type, field, (TypeArgument *)(field->arg))) 310450276Speter return FALSE; 3105166124Srafan form->status &= ~_FCHECK_REQUIRED; 310650276Speter field->status |= _CHANGED; 310750276Speter Synchronize_Linked_Fields(field); 310850276Speter } 310950276Speter return TRUE; 311050276Speter} 311150276Speter/*---------------------------------------------------------------------------- 311250276Speter End of Helper routines for Field Validations. 311350276Speter --------------------------------------------------------------------------*/ 3114166124Srafan 311550276Speter/*---------------------------------------------------------------------------- 311650276Speter Routines for Field Validation. 311750276Speter --------------------------------------------------------------------------*/ 311850276Speter 311950276Speter/*--------------------------------------------------------------------------- 3120166124Srafan| Facility : libnform 312150276Speter| Function : static int FV_Validation(FORM * form) 3122166124Srafan| 312350276Speter| Description : Validate the current field of the form. 312450276Speter| 312550276Speter| Return Values : E_OK - field valid 312650276Speter| E_INVALID_FIELD - field not valid 312750276Speter+--------------------------------------------------------------------------*/ 3128166124Srafanstatic int 3129166124SrafanFV_Validation(FORM *form) 313050276Speter{ 3131166124Srafan T((T_CALLED("FV_Validation(%p)"), form)); 313250276Speter if (_nc_Internal_Validation(form)) 3133166124Srafan returnCode(E_OK); 313450276Speter else 3135166124Srafan returnCode(E_INVALID_FIELD); 313650276Speter} 313750276Speter/*---------------------------------------------------------------------------- 313850276Speter End of routines for Field Validation. 313950276Speter --------------------------------------------------------------------------*/ 3140166124Srafan 314150276Speter/*---------------------------------------------------------------------------- 314250276Speter Helper routines for Inter-Field Navigation 314350276Speter --------------------------------------------------------------------------*/ 314450276Speter 314550276Speter/*--------------------------------------------------------------------------- 3146166124Srafan| Facility : libnform 314750276Speter| Function : static FIELD *Next_Field_On_Page(FIELD * field) 3148166124Srafan| 3149166124Srafan| Description : Get the next field after the given field on the current 315050276Speter| page. The order of fields is the one defined by the 315150276Speter| fields array. Only visible and active fields are 315250276Speter| counted. 315350276Speter| 315450276Speter| Return Values : Pointer to the next field. 315550276Speter+--------------------------------------------------------------------------*/ 3156166124SrafanNCURSES_INLINE static FIELD * 3157166124SrafanNext_Field_On_Page(FIELD *field) 315850276Speter{ 3159166124Srafan FORM *form = field->form; 316050276Speter FIELD **field_on_page = &form->field[field->index]; 316150276Speter FIELD **first_on_page = &form->field[form->page[form->curpage].pmin]; 3162166124Srafan FIELD **last_on_page = &form->field[form->page[form->curpage].pmax]; 316350276Speter 316450276Speter do 316550276Speter { 3166166124Srafan field_on_page = 3167166124Srafan (field_on_page == last_on_page) ? first_on_page : field_on_page + 1; 316850276Speter if (Field_Is_Selectable(*field_on_page)) 316950276Speter break; 3170166124Srafan } 3171166124Srafan while (field != (*field_on_page)); 3172166124Srafan return (*field_on_page); 317350276Speter} 317450276Speter 317550276Speter/*--------------------------------------------------------------------------- 3176166124Srafan| Facility : libnform 317750276Speter| Function : FIELD* _nc_First_Active_Field(FORM * form) 3178166124Srafan| 317950276Speter| Description : Get the first active field on the current page, 318050276Speter| if there are such. If there are none, get the first 318150276Speter| visible field on the page. If there are also none, 318250276Speter| we return the first field on page and hope the best. 318350276Speter| 318450276Speter| Return Values : Pointer to calculated field. 318550276Speter+--------------------------------------------------------------------------*/ 3186166124SrafanNCURSES_EXPORT(FIELD *) 3187166124Srafan_nc_First_Active_Field(FORM *form) 318850276Speter{ 318950276Speter FIELD **last_on_page = &form->field[form->page[form->curpage].pmax]; 319050276Speter FIELD *proposed = Next_Field_On_Page(*last_on_page); 319150276Speter 319250276Speter if (proposed == *last_on_page) 3193166124Srafan { 3194166124Srafan /* there might be the special situation, where there is no 3195166124Srafan active and visible field on the current page. We then select 3196166124Srafan the first visible field on this readonly page 3197166124Srafan */ 319850276Speter if (Field_Is_Not_Selectable(proposed)) 319950276Speter { 320050276Speter FIELD **field = &form->field[proposed->index]; 320150276Speter FIELD **first = &form->field[form->page[form->curpage].pmin]; 320250276Speter 320350276Speter do 320450276Speter { 3205166124Srafan field = (field == last_on_page) ? first : field + 1; 320650276Speter if (((*field)->opts & O_VISIBLE)) 320750276Speter break; 3208166124Srafan } 3209166124Srafan while (proposed != (*field)); 3210166124Srafan 321150276Speter proposed = *field; 321250276Speter 3213166124Srafan if ((proposed == *last_on_page) && !(proposed->opts & O_VISIBLE)) 3214166124Srafan { 3215166124Srafan /* This means, there is also no visible field on the page. 3216166124Srafan So we propose the first one and hope the very best... 3217166124Srafan Some very clever user has designed a readonly and invisible 3218166124Srafan page on this form. 321950276Speter */ 322050276Speter proposed = *first; 322150276Speter } 322250276Speter } 322350276Speter } 3224166124Srafan return (proposed); 322550276Speter} 322650276Speter 322750276Speter/*--------------------------------------------------------------------------- 3228166124Srafan| Facility : libnform 322950276Speter| Function : static FIELD *Previous_Field_On_Page(FIELD * field) 3230166124Srafan| 3231166124Srafan| Description : Get the previous field before the given field on the 3232166124Srafan| current page. The order of fields is the one defined by 323350276Speter| the fields array. Only visible and active fields are 323450276Speter| counted. 323550276Speter| 323650276Speter| Return Values : Pointer to the previous field. 323750276Speter+--------------------------------------------------------------------------*/ 3238166124SrafanNCURSES_INLINE static FIELD * 3239166124SrafanPrevious_Field_On_Page(FIELD *field) 324050276Speter{ 3241166124Srafan FORM *form = field->form; 324250276Speter FIELD **field_on_page = &form->field[field->index]; 324350276Speter FIELD **first_on_page = &form->field[form->page[form->curpage].pmin]; 3244166124Srafan FIELD **last_on_page = &form->field[form->page[form->curpage].pmax]; 3245166124Srafan 324650276Speter do 324750276Speter { 3248166124Srafan field_on_page = 3249166124Srafan (field_on_page == first_on_page) ? last_on_page : field_on_page - 1; 325050276Speter if (Field_Is_Selectable(*field_on_page)) 325150276Speter break; 3252166124Srafan } 3253166124Srafan while (field != (*field_on_page)); 3254166124Srafan 325550276Speter return (*field_on_page); 325650276Speter} 325750276Speter 325850276Speter/*--------------------------------------------------------------------------- 3259166124Srafan| Facility : libnform 326050276Speter| Function : static FIELD *Sorted_Next_Field(FIELD * field) 3261166124Srafan| 3262166124Srafan| Description : Get the next field after the given field on the current 326350276Speter| page. The order of fields is the one defined by the 326450276Speter| (row,column) geometry, rows are major. 326550276Speter| 326650276Speter| Return Values : Pointer to the next field. 326750276Speter+--------------------------------------------------------------------------*/ 3268166124SrafanNCURSES_INLINE static FIELD * 3269166124SrafanSorted_Next_Field(FIELD *field) 327050276Speter{ 327150276Speter FIELD *field_on_page = field; 327250276Speter 327350276Speter do 327450276Speter { 327550276Speter field_on_page = field_on_page->snext; 327650276Speter if (Field_Is_Selectable(field_on_page)) 327750276Speter break; 3278166124Srafan } 3279166124Srafan while (field_on_page != field); 3280166124Srafan 328150276Speter return (field_on_page); 328250276Speter} 328350276Speter 328450276Speter/*--------------------------------------------------------------------------- 3285166124Srafan| Facility : libnform 328650276Speter| Function : static FIELD *Sorted_Previous_Field(FIELD * field) 3287166124Srafan| 3288166124Srafan| Description : Get the previous field before the given field on the 3289166124Srafan| current page. The order of fields is the one defined 329050276Speter| by the (row,column) geometry, rows are major. 329150276Speter| 329250276Speter| Return Values : Pointer to the previous field. 329350276Speter+--------------------------------------------------------------------------*/ 3294166124SrafanNCURSES_INLINE static FIELD * 3295166124SrafanSorted_Previous_Field(FIELD *field) 329650276Speter{ 329750276Speter FIELD *field_on_page = field; 329850276Speter 329950276Speter do 330050276Speter { 330150276Speter field_on_page = field_on_page->sprev; 330250276Speter if (Field_Is_Selectable(field_on_page)) 330350276Speter break; 3304166124Srafan } 3305166124Srafan while (field_on_page != field); 3306166124Srafan 330750276Speter return (field_on_page); 330850276Speter} 330950276Speter 331050276Speter/*--------------------------------------------------------------------------- 3311166124Srafan| Facility : libnform 3312166124Srafan| Function : static FIELD *Left_Neighbor_Field(FIELD * field) 3313166124Srafan| 3314166124Srafan| Description : Get the left neighbor of the field on the same line 331550276Speter| and the same page. Cycles through the line. 331650276Speter| 3317166124Srafan| Return Values : Pointer to left neighbor field. 331850276Speter+--------------------------------------------------------------------------*/ 3319166124SrafanNCURSES_INLINE static FIELD * 3320166124SrafanLeft_Neighbor_Field(FIELD *field) 332150276Speter{ 332250276Speter FIELD *field_on_page = field; 332350276Speter 3324166124Srafan /* For a field that has really a left neighbor, the while clause 332550276Speter immediately fails and the loop is left, positioned at the right 3326166124Srafan neighbor. Otherwise we cycle backwards through the sorted field list 332750276Speter until we enter the same line (from the right end). 3328166124Srafan */ 332950276Speter do 333050276Speter { 333150276Speter field_on_page = Sorted_Previous_Field(field_on_page); 3332166124Srafan } 3333166124Srafan while (field_on_page->frow != field->frow); 3334166124Srafan 333550276Speter return (field_on_page); 333650276Speter} 333750276Speter 333850276Speter/*--------------------------------------------------------------------------- 3339166124Srafan| Facility : libnform 3340166124Srafan| Function : static FIELD *Right_Neighbor_Field(FIELD * field) 3341166124Srafan| 3342166124Srafan| Description : Get the right neighbor of the field on the same line 334350276Speter| and the same page. 334450276Speter| 3345166124Srafan| Return Values : Pointer to right neighbor field. 334650276Speter+--------------------------------------------------------------------------*/ 3347166124SrafanNCURSES_INLINE static FIELD * 3348166124SrafanRight_Neighbor_Field(FIELD *field) 334950276Speter{ 335050276Speter FIELD *field_on_page = field; 335150276Speter 3352166124Srafan /* See the comments on Left_Neighbor_Field to understand how it works */ 335350276Speter do 335450276Speter { 335550276Speter field_on_page = Sorted_Next_Field(field_on_page); 3356166124Srafan } 3357166124Srafan while (field_on_page->frow != field->frow); 3358166124Srafan 335950276Speter return (field_on_page); 336050276Speter} 336150276Speter 336250276Speter/*--------------------------------------------------------------------------- 3363166124Srafan| Facility : libnform 3364166124Srafan| Function : static FIELD *Upper_Neighbor_Field(FIELD * field) 3365166124Srafan| 336650276Speter| Description : Because of the row-major nature of sorting the fields, 3367166124Srafan| it is more difficult to define whats the upper neighbor 336850276Speter| field really means. We define that it must be on a 336950276Speter| 'previous' line (cyclic order!) and is the rightmost 337050276Speter| field laying on the left side of the given field. If 337150276Speter| this set is empty, we take the first field on the line. 337250276Speter| 3373166124Srafan| Return Values : Pointer to the upper neighbor field. 337450276Speter+--------------------------------------------------------------------------*/ 3375166124Srafanstatic FIELD * 3376166124SrafanUpper_Neighbor_Field(FIELD *field) 337750276Speter{ 337850276Speter FIELD *field_on_page = field; 337950276Speter int frow = field->frow; 338050276Speter int fcol = field->fcol; 338150276Speter 338250276Speter /* Walk back to the 'previous' line. The second term in the while clause 338350276Speter just guarantees that we stop if we cycled through the line because 338450276Speter there might be no 'previous' line if the page has just one line. 3385166124Srafan */ 338650276Speter do 338750276Speter { 338850276Speter field_on_page = Sorted_Previous_Field(field_on_page); 3389166124Srafan } 3390166124Srafan while (field_on_page->frow == frow && field_on_page->fcol != fcol); 3391166124Srafan 3392166124Srafan if (field_on_page->frow != frow) 3393166124Srafan { 3394166124Srafan /* We really found a 'previous' line. We are positioned at the 339550276Speter rightmost field on this line */ 3396166124Srafan frow = field_on_page->frow; 339750276Speter 3398166124Srafan /* We walk to the left as long as we are really right of the 3399166124Srafan field. */ 3400166124Srafan while (field_on_page->frow == frow && field_on_page->fcol > fcol) 340150276Speter field_on_page = Sorted_Previous_Field(field_on_page); 340250276Speter 3403166124Srafan /* If we wrapped, just go to the right which is the first field on 3404166124Srafan the row */ 3405166124Srafan if (field_on_page->frow != frow) 340650276Speter field_on_page = Sorted_Next_Field(field_on_page); 340750276Speter } 3408166124Srafan 340950276Speter return (field_on_page); 341050276Speter} 341150276Speter 341250276Speter/*--------------------------------------------------------------------------- 3413166124Srafan| Facility : libnform 3414166124Srafan| Function : static FIELD *Down_Neighbor_Field(FIELD * field) 3415166124Srafan| 341650276Speter| Description : Because of the row-major nature of sorting the fields, 3417166124Srafan| its more difficult to define whats the down neighbor 341850276Speter| field really means. We define that it must be on a 341950276Speter| 'next' line (cyclic order!) and is the leftmost 342050276Speter| field laying on the right side of the given field. If 342150276Speter| this set is empty, we take the last field on the line. 342250276Speter| 3423166124Srafan| Return Values : Pointer to the upper neighbor field. 342450276Speter+--------------------------------------------------------------------------*/ 3425166124Srafanstatic FIELD * 3426166124SrafanDown_Neighbor_Field(FIELD *field) 342750276Speter{ 342850276Speter FIELD *field_on_page = field; 342950276Speter int frow = field->frow; 343050276Speter int fcol = field->fcol; 343150276Speter 343250276Speter /* Walk forward to the 'next' line. The second term in the while clause 343350276Speter just guarantees that we stop if we cycled through the line because 343450276Speter there might be no 'next' line if the page has just one line. 3435166124Srafan */ 343650276Speter do 343750276Speter { 343850276Speter field_on_page = Sorted_Next_Field(field_on_page); 3439166124Srafan } 3440166124Srafan while (field_on_page->frow == frow && field_on_page->fcol != fcol); 344150276Speter 3442166124Srafan if (field_on_page->frow != frow) 3443166124Srafan { 3444166124Srafan /* We really found a 'next' line. We are positioned at the rightmost 344550276Speter field on this line */ 344650276Speter frow = field_on_page->frow; 344750276Speter 3448166124Srafan /* We walk to the right as long as we are really left of the 3449166124Srafan field. */ 3450166124Srafan while (field_on_page->frow == frow && field_on_page->fcol < fcol) 345150276Speter field_on_page = Sorted_Next_Field(field_on_page); 345250276Speter 3453166124Srafan /* If we wrapped, just go to the left which is the last field on 3454166124Srafan the row */ 3455166124Srafan if (field_on_page->frow != frow) 345650276Speter field_on_page = Sorted_Previous_Field(field_on_page); 345750276Speter } 3458166124Srafan 3459166124Srafan return (field_on_page); 346050276Speter} 3461166124Srafan 346250276Speter/*---------------------------------------------------------------------------- 346350276Speter Inter-Field Navigation routines 346450276Speter --------------------------------------------------------------------------*/ 346550276Speter 346650276Speter/*--------------------------------------------------------------------------- 3467166124Srafan| Facility : libnform 346850276Speter| Function : static int Inter_Field_Navigation( 346950276Speter| int (* const fct) (FORM *), 347050276Speter| FORM * form) 3471166124Srafan| 3472166124Srafan| Description : Generic behavior for changing the current field, the 347350276Speter| field is left and a new field is entered. So the field 347450276Speter| must be validated and the field init/term hooks must 347550276Speter| be called. 347650276Speter| 347750276Speter| Return Values : E_OK - success 347850276Speter| E_INVALID_FIELD - field is invalid 347950276Speter| some other - error from subordinate call 348050276Speter+--------------------------------------------------------------------------*/ 3481166124Srafanstatic int 3482166124SrafanInter_Field_Navigation(int (*const fct) (FORM *), FORM *form) 348350276Speter{ 348450276Speter int res; 348550276Speter 3486166124Srafan if (!_nc_Internal_Validation(form)) 348750276Speter res = E_INVALID_FIELD; 348850276Speter else 348950276Speter { 3490166124Srafan Call_Hook(form, fieldterm); 349150276Speter res = fct(form); 3492166124Srafan Call_Hook(form, fieldinit); 349350276Speter } 349450276Speter return res; 349550276Speter} 349650276Speter 349750276Speter/*--------------------------------------------------------------------------- 3498166124Srafan| Facility : libnform 349950276Speter| Function : static int FN_Next_Field(FORM * form) 3500166124Srafan| 350150276Speter| Description : Move to the next field on the current page of the form 350250276Speter| 350350276Speter| Return Values : E_OK - success 350450276Speter| != E_OK - error from subordinate call 350550276Speter+--------------------------------------------------------------------------*/ 3506166124Srafanstatic int 3507166124SrafanFN_Next_Field(FORM *form) 350850276Speter{ 3509166124Srafan T((T_CALLED("FN_Next_Field(%p)"), form)); 3510166124Srafan returnCode(_nc_Set_Current_Field(form, 3511166124Srafan Next_Field_On_Page(form->current))); 351250276Speter} 351350276Speter 351450276Speter/*--------------------------------------------------------------------------- 3515166124Srafan| Facility : libnform 351650276Speter| Function : static int FN_Previous_Field(FORM * form) 3517166124Srafan| 3518166124Srafan| Description : Move to the previous field on the current page of the 351950276Speter| form 352050276Speter| 352150276Speter| Return Values : E_OK - success 352250276Speter| != E_OK - error from subordinate call 352350276Speter+--------------------------------------------------------------------------*/ 3524166124Srafanstatic int 3525166124SrafanFN_Previous_Field(FORM *form) 352650276Speter{ 3527166124Srafan T((T_CALLED("FN_Previous_Field(%p)"), form)); 3528166124Srafan returnCode(_nc_Set_Current_Field(form, 3529166124Srafan Previous_Field_On_Page(form->current))); 353050276Speter} 353150276Speter 353250276Speter/*--------------------------------------------------------------------------- 3533166124Srafan| Facility : libnform 353450276Speter| Function : static int FN_First_Field(FORM * form) 3535166124Srafan| 353650276Speter| Description : Move to the first field on the current page of the form 353750276Speter| 353850276Speter| Return Values : E_OK - success 353950276Speter| != E_OK - error from subordinate call 354050276Speter+--------------------------------------------------------------------------*/ 3541166124Srafanstatic int 3542166124SrafanFN_First_Field(FORM *form) 354350276Speter{ 3544166124Srafan T((T_CALLED("FN_First_Field(%p)"), form)); 3545166124Srafan returnCode(_nc_Set_Current_Field(form, 3546166124Srafan Next_Field_On_Page(form->field[form->page[form->curpage].pmax]))); 354750276Speter} 354850276Speter 354950276Speter/*--------------------------------------------------------------------------- 3550166124Srafan| Facility : libnform 355150276Speter| Function : static int FN_Last_Field(FORM * form) 3552166124Srafan| 355350276Speter| Description : Move to the last field on the current page of the form 355450276Speter| 355550276Speter| Return Values : E_OK - success 355650276Speter| != E_OK - error from subordinate call 355750276Speter+--------------------------------------------------------------------------*/ 3558166124Srafanstatic int 3559166124SrafanFN_Last_Field(FORM *form) 356050276Speter{ 3561166124Srafan T((T_CALLED("FN_Last_Field(%p)"), form)); 3562166124Srafan returnCode( 3563166124Srafan _nc_Set_Current_Field(form, 3564166124Srafan Previous_Field_On_Page(form->field[form->page[form->curpage].pmin]))); 356550276Speter} 356650276Speter 356750276Speter/*--------------------------------------------------------------------------- 3568166124Srafan| Facility : libnform 356950276Speter| Function : static int FN_Sorted_Next_Field(FORM * form) 3570166124Srafan| 357150276Speter| Description : Move to the sorted next field on the current page 357250276Speter| of the form. 357350276Speter| 357450276Speter| Return Values : E_OK - success 357550276Speter| != E_OK - error from subordinate call 357650276Speter+--------------------------------------------------------------------------*/ 3577166124Srafanstatic int 3578166124SrafanFN_Sorted_Next_Field(FORM *form) 357950276Speter{ 3580166124Srafan T((T_CALLED("FN_Sorted_Next_Field(%p)"), form)); 3581166124Srafan returnCode(_nc_Set_Current_Field(form, 3582166124Srafan Sorted_Next_Field(form->current))); 358350276Speter} 358450276Speter 358550276Speter/*--------------------------------------------------------------------------- 3586166124Srafan| Facility : libnform 358750276Speter| Function : static int FN_Sorted_Previous_Field(FORM * form) 3588166124Srafan| 358950276Speter| Description : Move to the sorted previous field on the current page 359050276Speter| of the form. 359150276Speter| 359250276Speter| Return Values : E_OK - success 359350276Speter| != E_OK - error from subordinate call 359450276Speter+--------------------------------------------------------------------------*/ 3595166124Srafanstatic int 3596166124SrafanFN_Sorted_Previous_Field(FORM *form) 359750276Speter{ 3598166124Srafan T((T_CALLED("FN_Sorted_Previous_Field(%p)"), form)); 3599166124Srafan returnCode(_nc_Set_Current_Field(form, 3600166124Srafan Sorted_Previous_Field(form->current))); 360150276Speter} 360250276Speter 360350276Speter/*--------------------------------------------------------------------------- 3604166124Srafan| Facility : libnform 360550276Speter| Function : static int FN_Sorted_First_Field(FORM * form) 3606166124Srafan| 360750276Speter| Description : Move to the sorted first field on the current page 360850276Speter| of the form. 360950276Speter| 361050276Speter| Return Values : E_OK - success 361150276Speter| != E_OK - error from subordinate call 361250276Speter+--------------------------------------------------------------------------*/ 3613166124Srafanstatic int 3614166124SrafanFN_Sorted_First_Field(FORM *form) 361550276Speter{ 3616166124Srafan T((T_CALLED("FN_Sorted_First_Field(%p)"), form)); 3617166124Srafan returnCode(_nc_Set_Current_Field(form, 3618166124Srafan Sorted_Next_Field(form->field[form->page[form->curpage].smax]))); 361950276Speter} 362050276Speter 362150276Speter/*--------------------------------------------------------------------------- 3622166124Srafan| Facility : libnform 362350276Speter| Function : static int FN_Sorted_Last_Field(FORM * form) 3624166124Srafan| 362550276Speter| Description : Move to the sorted last field on the current page 362650276Speter| of the form. 362750276Speter| 362850276Speter| Return Values : E_OK - success 362950276Speter| != E_OK - error from subordinate call 363050276Speter+--------------------------------------------------------------------------*/ 3631166124Srafanstatic int 3632166124SrafanFN_Sorted_Last_Field(FORM *form) 363350276Speter{ 3634166124Srafan T((T_CALLED("FN_Sorted_Last_Field(%p)"), form)); 3635166124Srafan returnCode(_nc_Set_Current_Field(form, 3636166124Srafan Sorted_Previous_Field(form->field[form->page[form->curpage].smin]))); 363750276Speter} 363850276Speter 363950276Speter/*--------------------------------------------------------------------------- 3640166124Srafan| Facility : libnform 364150276Speter| Function : static int FN_Left_Field(FORM * form) 3642166124Srafan| 364350276Speter| Description : Get the field on the left of the current field on the 364450276Speter| same line and the same page. Cycles through the line. 364550276Speter| 364650276Speter| Return Values : E_OK - success 364750276Speter| != E_OK - error from subordinate call 364850276Speter+--------------------------------------------------------------------------*/ 3649166124Srafanstatic int 3650166124SrafanFN_Left_Field(FORM *form) 365150276Speter{ 3652166124Srafan T((T_CALLED("FN_Left_Field(%p)"), form)); 3653166124Srafan returnCode(_nc_Set_Current_Field(form, 3654166124Srafan Left_Neighbor_Field(form->current))); 365550276Speter} 365650276Speter 365750276Speter/*--------------------------------------------------------------------------- 3658166124Srafan| Facility : libnform 365950276Speter| Function : static int FN_Right_Field(FORM * form) 3660166124Srafan| 366150276Speter| Description : Get the field on the right of the current field on the 366250276Speter| same line and the same page. Cycles through the line. 366350276Speter| 366450276Speter| Return Values : E_OK - success 366550276Speter| != E_OK - error from subordinate call 366650276Speter+--------------------------------------------------------------------------*/ 3667166124Srafanstatic int 3668166124SrafanFN_Right_Field(FORM *form) 366950276Speter{ 3670166124Srafan T((T_CALLED("FN_Right_Field(%p)"), form)); 3671166124Srafan returnCode(_nc_Set_Current_Field(form, 3672166124Srafan Right_Neighbor_Field(form->current))); 367350276Speter} 367450276Speter 367550276Speter/*--------------------------------------------------------------------------- 3676166124Srafan| Facility : libnform 367750276Speter| Function : static int FN_Up_Field(FORM * form) 3678166124Srafan| 3679166124Srafan| Description : Get the upper neighbor of the current field. This 368050276Speter| cycles through the page. See the comments of the 3681166124Srafan| Upper_Neighbor_Field function to understand how 3682166124Srafan| 'upper' is defined. 368350276Speter| 368450276Speter| Return Values : E_OK - success 368550276Speter| != E_OK - error from subordinate call 368650276Speter+--------------------------------------------------------------------------*/ 3687166124Srafanstatic int 3688166124SrafanFN_Up_Field(FORM *form) 368950276Speter{ 3690166124Srafan T((T_CALLED("FN_Up_Field(%p)"), form)); 3691166124Srafan returnCode(_nc_Set_Current_Field(form, 3692166124Srafan Upper_Neighbor_Field(form->current))); 369350276Speter} 369450276Speter 369550276Speter/*--------------------------------------------------------------------------- 3696166124Srafan| Facility : libnform 369750276Speter| Function : static int FN_Down_Field(FORM * form) 3698166124Srafan| 3699166124Srafan| Description : Get the down neighbor of the current field. This 370050276Speter| cycles through the page. See the comments of the 3701166124Srafan| Down_Neighbor_Field function to understand how 3702166124Srafan| 'down' is defined. 370350276Speter| 370450276Speter| Return Values : E_OK - success 370550276Speter| != E_OK - error from subordinate call 370650276Speter+--------------------------------------------------------------------------*/ 3707166124Srafanstatic int 3708166124SrafanFN_Down_Field(FORM *form) 370950276Speter{ 3710166124Srafan T((T_CALLED("FN_Down_Field(%p)"), form)); 3711166124Srafan returnCode(_nc_Set_Current_Field(form, 3712166124Srafan Down_Neighbor_Field(form->current))); 371350276Speter} 371450276Speter/*---------------------------------------------------------------------------- 3715166124Srafan END of Field Navigation routines 371650276Speter --------------------------------------------------------------------------*/ 3717166124Srafan 371850276Speter/*---------------------------------------------------------------------------- 371950276Speter Helper routines for Page Navigation 372050276Speter --------------------------------------------------------------------------*/ 372150276Speter 372250276Speter/*--------------------------------------------------------------------------- 3723166124Srafan| Facility : libnform 372450276Speter| Function : int _nc_Set_Form_Page(FORM * form, 372550276Speter| int page, 372650276Speter| FIELD * field) 3727166124Srafan| 3728166124Srafan| Description : Make the given page number the current page and make 372950276Speter| the given field the current field on the page. If 373050276Speter| for the field NULL is given, make the first field on 373150276Speter| the page the current field. The routine acts only 373250276Speter| if the requested page is not the current page. 373350276Speter| 373450276Speter| Return Values : E_OK - success 373550276Speter| != E_OK - error from subordinate call 3736166124Srafan| E_BAD_ARGUMENT - invalid field pointer 3737166124Srafan| E_SYSTEM_ERROR - some severe basic error 373850276Speter+--------------------------------------------------------------------------*/ 373976726SpeterNCURSES_EXPORT(int) 3740166124Srafan_nc_Set_Form_Page(FORM *form, int page, FIELD *field) 374150276Speter{ 374250276Speter int res = E_OK; 374350276Speter 3744166124Srafan if ((form->curpage != page)) 374550276Speter { 374650276Speter FIELD *last_field, *field_on_page; 374750276Speter 374850276Speter werase(Get_Form_Window(form)); 374950276Speter form->curpage = page; 375050276Speter last_field = field_on_page = form->field[form->page[page].smin]; 375150276Speter do 375250276Speter { 375350276Speter if (field_on_page->opts & O_VISIBLE) 3754166124Srafan if ((res = Display_Field(field_on_page)) != E_OK) 3755166124Srafan return (res); 375650276Speter field_on_page = field_on_page->snext; 3757166124Srafan } 3758166124Srafan while (field_on_page != last_field); 375950276Speter 376050276Speter if (field) 3761166124Srafan res = _nc_Set_Current_Field(form, field); 376250276Speter else 376350276Speter /* N.B.: we don't encapsulate this by Inter_Field_Navigation(), 376450276Speter because this is already executed in a page navigation 3765166124Srafan context that contains field navigation 376650276Speter */ 376750276Speter res = FN_First_Field(form); 376850276Speter } 3769166124Srafan return (res); 377050276Speter} 377150276Speter 377250276Speter/*--------------------------------------------------------------------------- 3773166124Srafan| Facility : libnform 377450276Speter| Function : static int Next_Page_Number(const FORM * form) 3775166124Srafan| 377650276Speter| Description : Calculate the page number following the current page 377750276Speter| number. This cycles if the highest page number is 3778166124Srafan| reached. 377950276Speter| 378050276Speter| Return Values : The next page number 378150276Speter+--------------------------------------------------------------------------*/ 3782166124SrafanNCURSES_INLINE static int 3783166124SrafanNext_Page_Number(const FORM *form) 378450276Speter{ 378550276Speter return (form->curpage + 1) % form->maxpage; 378650276Speter} 378750276Speter 378850276Speter/*--------------------------------------------------------------------------- 3789166124Srafan| Facility : libnform 379050276Speter| Function : static int Previous_Page_Number(const FORM * form) 3791166124Srafan| 379250276Speter| Description : Calculate the page number before the current page 379350276Speter| number. This cycles if the first page number is 3794166124Srafan| reached. 379550276Speter| 379650276Speter| Return Values : The previous page number 379750276Speter+--------------------------------------------------------------------------*/ 3798166124SrafanNCURSES_INLINE static int 3799166124SrafanPrevious_Page_Number(const FORM *form) 380050276Speter{ 3801166124Srafan return (form->curpage != 0 ? form->curpage - 1 : form->maxpage - 1); 380250276Speter} 3803166124Srafan 380450276Speter/*---------------------------------------------------------------------------- 3805166124Srafan Page Navigation routines 380650276Speter --------------------------------------------------------------------------*/ 380750276Speter 380850276Speter/*--------------------------------------------------------------------------- 3809166124Srafan| Facility : libnform 381050276Speter| Function : static int Page_Navigation( 381150276Speter| int (* const fct) (FORM *), 381250276Speter| FORM * form) 3813166124Srafan| 3814166124Srafan| Description : Generic behavior for changing a page. This means 381550276Speter| that the field is left and a new field is entered. 381650276Speter| So the field must be validated and the field init/term 381750276Speter| hooks must be called. Because also the page is changed, 381850276Speter| the forms init/term hooks must be called also. 381950276Speter| 382050276Speter| Return Values : E_OK - success 382150276Speter| E_INVALID_FIELD - field is invalid 382250276Speter| some other - error from subordinate call 382350276Speter+--------------------------------------------------------------------------*/ 3824166124Srafanstatic int 3825166124SrafanPage_Navigation(int (*const fct) (FORM *), FORM *form) 382650276Speter{ 382750276Speter int res; 382850276Speter 3829166124Srafan if (!_nc_Internal_Validation(form)) 383050276Speter res = E_INVALID_FIELD; 383150276Speter else 383250276Speter { 3833166124Srafan Call_Hook(form, fieldterm); 3834166124Srafan Call_Hook(form, formterm); 383550276Speter res = fct(form); 3836166124Srafan Call_Hook(form, forminit); 3837166124Srafan Call_Hook(form, fieldinit); 383850276Speter } 383950276Speter return res; 384050276Speter} 384150276Speter 384250276Speter/*--------------------------------------------------------------------------- 3843166124Srafan| Facility : libnform 384450276Speter| Function : static int PN_Next_Page(FORM * form) 3845166124Srafan| 384650276Speter| Description : Move to the next page of the form 384750276Speter| 384850276Speter| Return Values : E_OK - success 384950276Speter| != E_OK - error from subordinate call 385050276Speter+--------------------------------------------------------------------------*/ 3851166124Srafanstatic int 3852166124SrafanPN_Next_Page(FORM *form) 3853166124Srafan{ 3854166124Srafan T((T_CALLED("PN_Next_Page(%p)"), form)); 3855166124Srafan returnCode(_nc_Set_Form_Page(form, Next_Page_Number(form), (FIELD *)0)); 385650276Speter} 385750276Speter 385850276Speter/*--------------------------------------------------------------------------- 3859166124Srafan| Facility : libnform 386050276Speter| Function : static int PN_Previous_Page(FORM * form) 3861166124Srafan| 386250276Speter| Description : Move to the previous page of the form 386350276Speter| 386450276Speter| Return Values : E_OK - success 386550276Speter| != E_OK - error from subordinate call 386650276Speter+--------------------------------------------------------------------------*/ 3867166124Srafanstatic int 3868166124SrafanPN_Previous_Page(FORM *form) 386950276Speter{ 3870166124Srafan T((T_CALLED("PN_Previous_Page(%p)"), form)); 3871166124Srafan returnCode(_nc_Set_Form_Page(form, Previous_Page_Number(form), (FIELD *)0)); 387250276Speter} 387350276Speter 387450276Speter/*--------------------------------------------------------------------------- 3875166124Srafan| Facility : libnform 387650276Speter| Function : static int PN_First_Page(FORM * form) 3877166124Srafan| 387850276Speter| Description : Move to the first page of the form 387950276Speter| 388050276Speter| Return Values : E_OK - success 388150276Speter| != E_OK - error from subordinate call 388250276Speter+--------------------------------------------------------------------------*/ 3883166124Srafanstatic int 3884166124SrafanPN_First_Page(FORM *form) 388550276Speter{ 3886166124Srafan T((T_CALLED("PN_First_Page(%p)"), form)); 3887166124Srafan returnCode(_nc_Set_Form_Page(form, 0, (FIELD *)0)); 388850276Speter} 388950276Speter 389050276Speter/*--------------------------------------------------------------------------- 3891166124Srafan| Facility : libnform 389250276Speter| Function : static int PN_Last_Page(FORM * form) 3893166124Srafan| 389450276Speter| Description : Move to the last page of the form 389550276Speter| 389650276Speter| Return Values : E_OK - success 389750276Speter| != E_OK - error from subordinate call 389850276Speter+--------------------------------------------------------------------------*/ 3899166124Srafanstatic int 3900166124SrafanPN_Last_Page(FORM *form) 390150276Speter{ 3902166124Srafan T((T_CALLED("PN_Last_Page(%p)"), form)); 3903166124Srafan returnCode(_nc_Set_Form_Page(form, form->maxpage - 1, (FIELD *)0)); 390450276Speter} 3905166124Srafan 390650276Speter/*---------------------------------------------------------------------------- 3907166124Srafan END of Field Navigation routines 390850276Speter --------------------------------------------------------------------------*/ 3909166124Srafan 391050276Speter/*---------------------------------------------------------------------------- 391150276Speter Helper routines for the core form driver. 391250276Speter --------------------------------------------------------------------------*/ 391350276Speter 391450276Speter/*--------------------------------------------------------------------------- 3915166124Srafan| Facility : libnform 391650276Speter| Function : static int Data_Entry(FORM * form,int c) 3917166124Srafan| 391850276Speter| Description : Enter character c into at the current position of the 391950276Speter| current field of the form. 392050276Speter| 3921166124Srafan| Return Values : E_OK - success 3922166124Srafan| E_REQUEST_DENIED - driver could not process the request 392350276Speter| E_SYSTEM_ERROR - 392450276Speter+--------------------------------------------------------------------------*/ 3925166124Srafanstatic int 3926166124SrafanData_Entry(FORM *form, int c) 392750276Speter{ 3928166124Srafan FIELD *field = form->current; 392950276Speter int result = E_REQUEST_DENIED; 393050276Speter 3931166124Srafan T((T_CALLED("Data_Entry(%p,%s)"), form, _tracechtype((chtype)c))); 3932166124Srafan if ((field->opts & O_EDIT) 393350276Speter#if FIX_FORM_INACTIVE_BUG 3934166124Srafan && (field->opts & O_ACTIVE) 393550276Speter#endif 3936166124Srafan ) 393750276Speter { 3938166124Srafan if ((field->opts & O_BLANK) && 3939166124Srafan First_Position_In_Current_Field(form) && 3940166124Srafan !(form->status & _FCHECK_REQUIRED) && 3941166124Srafan !(form->status & _WINDOW_MODIFIED)) 394250276Speter werase(form->w); 394350276Speter 394450276Speter if (form->status & _OVLMODE) 394550276Speter { 3946166124Srafan waddch(form->w, (chtype)c); 3947166124Srafan } 3948166124Srafan else 3949166124Srafan /* no _OVLMODE */ 395050276Speter { 395150276Speter bool There_Is_Room = Is_There_Room_For_A_Char_In_Line(form); 395250276Speter 395350276Speter if (!(There_Is_Room || 395450276Speter ((Single_Line_Field(field) && Growable(field))))) 3955166124Srafan RETURN(E_REQUEST_DENIED); 395650276Speter 3957166124Srafan if (!There_Is_Room && !Field_Grown(field, 1)) 3958166124Srafan RETURN(E_SYSTEM_ERROR); 395950276Speter 3960166124Srafan winsch(form->w, (chtype)c); 396150276Speter } 396250276Speter 3963166124Srafan if ((result = Wrapping_Not_Necessary_Or_Wrapping_Ok(form)) == E_OK) 396450276Speter { 3965166124Srafan bool End_Of_Field = (((field->drows - 1) == form->currow) && 3966166124Srafan ((field->dcols - 1) == form->curcol)); 3967166124Srafan 396850276Speter form->status |= _WINDOW_MODIFIED; 396950276Speter if (End_Of_Field && !Growable(field) && (field->opts & O_AUTOSKIP)) 3970166124Srafan result = Inter_Field_Navigation(FN_Next_Field, form); 397150276Speter else 397250276Speter { 3973166124Srafan if (End_Of_Field && Growable(field) && !Field_Grown(field, 1)) 397450276Speter result = E_SYSTEM_ERROR; 397550276Speter else 397650276Speter { 3977166124Srafan#if USE_WIDEC_SUPPORT 3978166124Srafan /* 3979166124Srafan * We have just added a byte to the form field. It may have 3980166124Srafan * been part of a multibyte character. If it was, the 3981166124Srafan * addch_used field is nonzero and we should not try to move 3982166124Srafan * to a new column. 3983166124Srafan */ 3984166124Srafan if (WINDOW_EXT(form->w, addch_used) == 0) 3985166124Srafan IFN_Next_Character(form); 3986166124Srafan#else 398750276Speter IFN_Next_Character(form); 3988166124Srafan#endif 398950276Speter result = E_OK; 399050276Speter } 399150276Speter } 399250276Speter } 399350276Speter } 3994166124Srafan RETURN(result); 399550276Speter} 3996166124Srafan 399750276Speter/* Structure to describe the binding of a request code to a function. 399850276Speter The member keycode codes the request value as well as the generic 399950276Speter routine to use for the request. The code for the generic routine 400050276Speter is coded in the upper 16 Bits while the request code is coded in 4001166124Srafan the lower 16 bits. 400250276Speter 400350276Speter In terms of C++ you might think of a request as a class with a 400450276Speter virtual method "perform". The different types of request are 400550276Speter derived from this base class and overload (or not) the base class 400650276Speter implementation of perform. 400750276Speter*/ 4008166124Srafantypedef struct 4009166124Srafan{ 4010166124Srafan int keycode; /* must be at least 32 bit: hi:mode, lo: key */ 4011166124Srafan int (*cmd) (FORM *); /* low level driver routine for this key */ 4012166124Srafan} 4013166124SrafanBinding_Info; 401450276Speter 401550276Speter/* You may see this is the class-id of the request type class */ 4016166124Srafan#define ID_PN (0x00000000) /* Page navigation */ 4017166124Srafan#define ID_FN (0x00010000) /* Inter-Field navigation */ 4018166124Srafan#define ID_IFN (0x00020000) /* Intra-Field navigation */ 4019166124Srafan#define ID_VSC (0x00030000) /* Vertical Scrolling */ 4020166124Srafan#define ID_HSC (0x00040000) /* Horizontal Scrolling */ 4021166124Srafan#define ID_FE (0x00050000) /* Field Editing */ 4022166124Srafan#define ID_EM (0x00060000) /* Edit Mode */ 4023166124Srafan#define ID_FV (0x00070000) /* Field Validation */ 4024166124Srafan#define ID_CH (0x00080000) /* Choice */ 402550276Speter#define ID_Mask (0xffff0000) 402650276Speter#define Key_Mask (0x0000ffff) 402750276Speter#define ID_Shft (16) 402850276Speter 402950276Speter/* This array holds all the Binding Infos */ 4030166124Srafan/* *INDENT-OFF* */ 4031166124Srafanstatic const Binding_Info bindings[MAX_FORM_COMMAND - MIN_FORM_COMMAND + 1] = 403250276Speter{ 403350276Speter { REQ_NEXT_PAGE |ID_PN ,PN_Next_Page}, 403450276Speter { REQ_PREV_PAGE |ID_PN ,PN_Previous_Page}, 403550276Speter { REQ_FIRST_PAGE |ID_PN ,PN_First_Page}, 403650276Speter { REQ_LAST_PAGE |ID_PN ,PN_Last_Page}, 4037166124Srafan 403850276Speter { REQ_NEXT_FIELD |ID_FN ,FN_Next_Field}, 403950276Speter { REQ_PREV_FIELD |ID_FN ,FN_Previous_Field}, 404050276Speter { REQ_FIRST_FIELD |ID_FN ,FN_First_Field}, 404150276Speter { REQ_LAST_FIELD |ID_FN ,FN_Last_Field}, 404250276Speter { REQ_SNEXT_FIELD |ID_FN ,FN_Sorted_Next_Field}, 404350276Speter { REQ_SPREV_FIELD |ID_FN ,FN_Sorted_Previous_Field}, 404450276Speter { REQ_SFIRST_FIELD |ID_FN ,FN_Sorted_First_Field}, 404550276Speter { REQ_SLAST_FIELD |ID_FN ,FN_Sorted_Last_Field}, 404650276Speter { REQ_LEFT_FIELD |ID_FN ,FN_Left_Field}, 404750276Speter { REQ_RIGHT_FIELD |ID_FN ,FN_Right_Field}, 404850276Speter { REQ_UP_FIELD |ID_FN ,FN_Up_Field}, 404950276Speter { REQ_DOWN_FIELD |ID_FN ,FN_Down_Field}, 4050166124Srafan 405150276Speter { REQ_NEXT_CHAR |ID_IFN ,IFN_Next_Character}, 405250276Speter { REQ_PREV_CHAR |ID_IFN ,IFN_Previous_Character}, 405350276Speter { REQ_NEXT_LINE |ID_IFN ,IFN_Next_Line}, 405450276Speter { REQ_PREV_LINE |ID_IFN ,IFN_Previous_Line}, 405550276Speter { REQ_NEXT_WORD |ID_IFN ,IFN_Next_Word}, 405650276Speter { REQ_PREV_WORD |ID_IFN ,IFN_Previous_Word}, 405750276Speter { REQ_BEG_FIELD |ID_IFN ,IFN_Beginning_Of_Field}, 405850276Speter { REQ_END_FIELD |ID_IFN ,IFN_End_Of_Field}, 405950276Speter { REQ_BEG_LINE |ID_IFN ,IFN_Beginning_Of_Line}, 406050276Speter { REQ_END_LINE |ID_IFN ,IFN_End_Of_Line}, 406150276Speter { REQ_LEFT_CHAR |ID_IFN ,IFN_Left_Character}, 406250276Speter { REQ_RIGHT_CHAR |ID_IFN ,IFN_Right_Character}, 406350276Speter { REQ_UP_CHAR |ID_IFN ,IFN_Up_Character}, 406450276Speter { REQ_DOWN_CHAR |ID_IFN ,IFN_Down_Character}, 4065166124Srafan 406650276Speter { REQ_NEW_LINE |ID_FE ,FE_New_Line}, 406750276Speter { REQ_INS_CHAR |ID_FE ,FE_Insert_Character}, 406850276Speter { REQ_INS_LINE |ID_FE ,FE_Insert_Line}, 406950276Speter { REQ_DEL_CHAR |ID_FE ,FE_Delete_Character}, 407050276Speter { REQ_DEL_PREV |ID_FE ,FE_Delete_Previous}, 407150276Speter { REQ_DEL_LINE |ID_FE ,FE_Delete_Line}, 407250276Speter { REQ_DEL_WORD |ID_FE ,FE_Delete_Word}, 407350276Speter { REQ_CLR_EOL |ID_FE ,FE_Clear_To_End_Of_Line}, 4074166124Srafan { REQ_CLR_EOF |ID_FE ,FE_Clear_To_End_Of_Field}, 407550276Speter { REQ_CLR_FIELD |ID_FE ,FE_Clear_Field}, 4076166124Srafan 407750276Speter { REQ_OVL_MODE |ID_EM ,EM_Overlay_Mode}, 407850276Speter { REQ_INS_MODE |ID_EM ,EM_Insert_Mode}, 4079166124Srafan 408050276Speter { REQ_SCR_FLINE |ID_VSC ,VSC_Scroll_Line_Forward}, 408150276Speter { REQ_SCR_BLINE |ID_VSC ,VSC_Scroll_Line_Backward}, 408250276Speter { REQ_SCR_FPAGE |ID_VSC ,VSC_Scroll_Page_Forward}, 408350276Speter { REQ_SCR_BPAGE |ID_VSC ,VSC_Scroll_Page_Backward}, 408450276Speter { REQ_SCR_FHPAGE |ID_VSC ,VSC_Scroll_Half_Page_Forward}, 408550276Speter { REQ_SCR_BHPAGE |ID_VSC ,VSC_Scroll_Half_Page_Backward}, 4086166124Srafan 408750276Speter { REQ_SCR_FCHAR |ID_HSC ,HSC_Scroll_Char_Forward}, 408850276Speter { REQ_SCR_BCHAR |ID_HSC ,HSC_Scroll_Char_Backward}, 408950276Speter { REQ_SCR_HFLINE |ID_HSC ,HSC_Horizontal_Line_Forward}, 409050276Speter { REQ_SCR_HBLINE |ID_HSC ,HSC_Horizontal_Line_Backward}, 409150276Speter { REQ_SCR_HFHALF |ID_HSC ,HSC_Horizontal_Half_Line_Forward}, 409250276Speter { REQ_SCR_HBHALF |ID_HSC ,HSC_Horizontal_Half_Line_Backward}, 4093166124Srafan 409450276Speter { REQ_VALIDATION |ID_FV ,FV_Validation}, 409550276Speter 409650276Speter { REQ_NEXT_CHOICE |ID_CH ,CR_Next_Choice}, 409750276Speter { REQ_PREV_CHOICE |ID_CH ,CR_Previous_Choice} 409850276Speter}; 4099166124Srafan/* *INDENT-ON* */ 410050276Speter 410150276Speter/*--------------------------------------------------------------------------- 4102166124Srafan| Facility : libnform 410350276Speter| Function : int form_driver(FORM * form,int c) 4104166124Srafan| 410550276Speter| Description : This is the workhorse of the forms system. It checks 410650276Speter| to determine whether the character c is a request or 410750276Speter| data. If it is a request, the form driver executes 410850276Speter| the request and returns the result. If it is data 410950276Speter| (printable character), it enters the data into the 411050276Speter| current position in the current field. If it is not 411150276Speter| recognized, the form driver assumes it is an application 411250276Speter| defined command and returns E_UNKNOWN_COMMAND. 411350276Speter| Application defined command should be defined relative 411450276Speter| to MAX_FORM_COMMAND, the maximum value of a request. 411550276Speter| 411650276Speter| Return Values : E_OK - success 411750276Speter| E_SYSTEM_ERROR - system error 411850276Speter| E_BAD_ARGUMENT - an argument is incorrect 411950276Speter| E_NOT_POSTED - form is not posted 412050276Speter| E_INVALID_FIELD - field contents are invalid 412150276Speter| E_BAD_STATE - called from inside a hook routine 412250276Speter| E_REQUEST_DENIED - request failed 4123166124Srafan| E_NOT_CONNECTED - no fields are connected to the form 412450276Speter| E_UNKNOWN_COMMAND - command not known 412550276Speter+--------------------------------------------------------------------------*/ 412676726SpeterNCURSES_EXPORT(int) 4127166124Srafanform_driver(FORM *form, int c) 412850276Speter{ 4129166124Srafan const Binding_Info *BI = (Binding_Info *) 0; 413050276Speter int res = E_UNKNOWN_COMMAND; 413150276Speter 4132166124Srafan T((T_CALLED("form_driver(%p,%d)"), form, c)); 4133166124Srafan 413450276Speter if (!form) 413550276Speter RETURN(E_BAD_ARGUMENT); 413650276Speter 413750276Speter if (!(form->field)) 413850276Speter RETURN(E_NOT_CONNECTED); 4139166124Srafan 414050276Speter assert(form->page); 4141166124Srafan 4142166124Srafan if (c == FIRST_ACTIVE_MAGIC) 414350276Speter { 414450276Speter form->current = _nc_First_Active_Field(form); 4145166124Srafan RETURN(E_OK); 414650276Speter } 4147166124Srafan 4148166124Srafan assert(form->current && 4149166124Srafan form->current->buf && 415050276Speter (form->current->form == form) 4151166124Srafan ); 4152166124Srafan 4153166124Srafan if (form->status & _IN_DRIVER) 415450276Speter RETURN(E_BAD_STATE); 415550276Speter 4156166124Srafan if (!(form->status & _POSTED)) 415750276Speter RETURN(E_NOT_POSTED); 4158166124Srafan 4159166124Srafan if ((c >= MIN_FORM_COMMAND && c <= MAX_FORM_COMMAND) && 4160166124Srafan ((bindings[c - MIN_FORM_COMMAND].keycode & Key_Mask) == c)) 4161166124Srafan BI = &(bindings[c - MIN_FORM_COMMAND]); 4162166124Srafan 416350276Speter if (BI) 416450276Speter { 4165166124Srafan typedef int (*Generic_Method) (int (*const) (FORM *), FORM *); 4166166124Srafan static const Generic_Method Generic_Methods[] = 4167166124Srafan { 4168166124Srafan Page_Navigation, /* overloaded to call field&form hooks */ 4169166124Srafan Inter_Field_Navigation, /* overloaded to call field hooks */ 4170166124Srafan NULL, /* Intra-Field is generic */ 4171166124Srafan Vertical_Scrolling, /* Overloaded to check multi-line */ 4172166124Srafan Horizontal_Scrolling, /* Overloaded to check single-line */ 4173166124Srafan Field_Editing, /* Overloaded to mark modification */ 4174166124Srafan NULL, /* Edit Mode is generic */ 4175166124Srafan NULL, /* Field Validation is generic */ 4176166124Srafan NULL /* Choice Request is generic */ 4177166124Srafan }; 4178166124Srafan size_t nMethods = (sizeof(Generic_Methods) / sizeof(Generic_Methods[0])); 4179184989Srafan size_t method = (BI->keycode >> ID_Shft) & 0xffff; /* see ID_Mask */ 4180166124Srafan 4181166124Srafan if ((method >= nMethods) || !(BI->cmd)) 418250276Speter res = E_SYSTEM_ERROR; 418350276Speter else 418450276Speter { 418550276Speter Generic_Method fct = Generic_Methods[method]; 4186166124Srafan 418750276Speter if (fct) 4188166124Srafan res = fct(BI->cmd, form); 418950276Speter else 4190166124Srafan res = (BI->cmd) (form); 419150276Speter } 4192166124Srafan } 4193174993Srafan#ifdef NCURSES_MOUSE_VERSION 4194174993Srafan else if (KEY_MOUSE == c) 4195174993Srafan { 4196174993Srafan MEVENT event; 4197174993Srafan WINDOW *win = form->win ? form->win : stdscr; 4198174993Srafan WINDOW *sub = form->sub ? form->sub : win; 4199174993Srafan 4200174993Srafan getmouse(&event); 4201174993Srafan if ((event.bstate & (BUTTON1_CLICKED | 4202174993Srafan BUTTON1_DOUBLE_CLICKED | 4203174993Srafan BUTTON1_TRIPLE_CLICKED)) 4204174993Srafan && wenclose(win, event.y, event.x)) 4205174993Srafan { /* we react only if the click was in the userwin, that means 4206174993Srafan * inside the form display area or at the decoration window. 4207174993Srafan */ 4208174993Srafan int ry = event.y, rx = event.x; /* screen coordinates */ 4209174993Srafan 4210174993Srafan res = E_REQUEST_DENIED; 4211174993Srafan if (mouse_trafo(&ry, &rx, FALSE)) 4212174993Srafan { /* rx, ry are now "curses" coordinates */ 4213174993Srafan if (ry < sub->_begy) 4214174993Srafan { /* we clicked above the display region; this is 4215174993Srafan * interpreted as "scroll up" request 4216174993Srafan */ 4217174993Srafan if (event.bstate & BUTTON1_CLICKED) 4218174993Srafan res = form_driver(form, REQ_PREV_FIELD); 4219174993Srafan else if (event.bstate & BUTTON1_DOUBLE_CLICKED) 4220174993Srafan res = form_driver(form, REQ_PREV_PAGE); 4221174993Srafan else if (event.bstate & BUTTON1_TRIPLE_CLICKED) 4222174993Srafan res = form_driver(form, REQ_FIRST_FIELD); 4223174993Srafan } 4224174993Srafan else if (ry > sub->_begy + sub->_maxy) 4225174993Srafan { /* we clicked below the display region; this is 4226174993Srafan * interpreted as "scroll down" request 4227174993Srafan */ 4228174993Srafan if (event.bstate & BUTTON1_CLICKED) 4229174993Srafan res = form_driver(form, REQ_NEXT_FIELD); 4230174993Srafan else if (event.bstate & BUTTON1_DOUBLE_CLICKED) 4231174993Srafan res = form_driver(form, REQ_NEXT_PAGE); 4232174993Srafan else if (event.bstate & BUTTON1_TRIPLE_CLICKED) 4233174993Srafan res = form_driver(form, REQ_LAST_FIELD); 4234174993Srafan } 4235174993Srafan else if (wenclose(sub, event.y, event.x)) 4236174993Srafan { /* Inside the area we try to find the hit item */ 4237174993Srafan int i; 4238174993Srafan 4239174993Srafan ry = event.y; 4240174993Srafan rx = event.x; 4241174993Srafan if (wmouse_trafo(sub, &ry, &rx, FALSE)) 4242174993Srafan { 4243174993Srafan int min_field = form->page[form->curpage].pmin; 4244174993Srafan int max_field = form->page[form->curpage].pmax; 4245174993Srafan 4246174993Srafan for (i = min_field; i <= max_field; ++i) 4247174993Srafan { 4248174993Srafan FIELD *field = form->field[i]; 4249174993Srafan 4250174993Srafan if (Field_Is_Selectable(field) 4251174993Srafan && Field_encloses(field, ry, rx) == E_OK) 4252174993Srafan { 4253174993Srafan res = _nc_Set_Current_Field(form, field); 4254174993Srafan if (res == E_OK) 4255174993Srafan res = _nc_Position_Form_Cursor(form); 4256174993Srafan if (res == E_OK 4257174993Srafan && (event.bstate & BUTTON1_DOUBLE_CLICKED)) 4258174993Srafan res = E_UNKNOWN_COMMAND; 4259174993Srafan break; 4260174993Srafan } 4261174993Srafan } 4262174993Srafan } 4263174993Srafan } 4264174993Srafan } 4265174993Srafan } 4266174993Srafan else 4267174993Srafan res = E_REQUEST_DENIED; 4268174993Srafan } 4269174993Srafan#endif /* NCURSES_MOUSE_VERSION */ 4270166124Srafan else if (!(c & (~(int)MAX_REGULAR_CHARACTER))) 427150276Speter { 4272166124Srafan /* 4273166124Srafan * If we're using 8-bit characters, iscntrl+isprint cover the whole set. 4274166124Srafan * But with multibyte characters, there is a third possibility, i.e., 4275166124Srafan * parts of characters that build up into printable characters which are 4276166124Srafan * not considered printable. 4277166124Srafan * 4278166124Srafan * FIXME: the wide-character branch should also use Check_Char(). 4279166124Srafan */ 4280166124Srafan#if USE_WIDEC_SUPPORT 4281166124Srafan if (!iscntrl(UChar(c))) 4282166124Srafan#else 4283166124Srafan if (isprint(UChar(c)) && 4284166124Srafan Check_Char(form->current->type, c, 428550276Speter (TypeArgument *)(form->current->arg))) 4286166124Srafan#endif 4287166124Srafan res = Data_Entry(form, c); 428850276Speter } 428950276Speter _nc_Refresh_Current_Field(form); 429050276Speter RETURN(res); 429150276Speter} 4292166124Srafan 429350276Speter/*---------------------------------------------------------------------------- 429450276Speter Field-Buffer manipulation routines. 4295166124Srafan The effects of setting a buffer are tightly coupled to the core of the form 429650276Speter driver logic. This is especially true in the case of growable fields. 4297166124Srafan So I don't separate this into a separate module. 429850276Speter --------------------------------------------------------------------------*/ 429950276Speter 430050276Speter/*--------------------------------------------------------------------------- 4301166124Srafan| Facility : libnform 430250276Speter| Function : int set_field_buffer(FIELD *field, 430350276Speter| int buffer, char *value) 4304166124Srafan| 430550276Speter| Description : Set the given buffer of the field to the given value. 430650276Speter| Buffer 0 stores the displayed content of the field. 430750276Speter| For dynamic fields this may grow the fieldbuffers if 430850276Speter| the length of the value exceeds the current buffer 430950276Speter| length. For buffer 0 only printable values are allowed. 431050276Speter| For static fields, the value needs not to be zero ter- 4311166124Srafan| minated. It is copied up to the length of the buffer. 431250276Speter| 431350276Speter| Return Values : E_OK - success 431450276Speter| E_BAD_ARGUMENT - invalid argument 431550276Speter| E_SYSTEM_ERROR - system error 431650276Speter+--------------------------------------------------------------------------*/ 431776726SpeterNCURSES_EXPORT(int) 4318166124Srafanset_field_buffer(FIELD *field, int buffer, const char *value) 431950276Speter{ 4320166124Srafan FIELD_CELL *p; 432150276Speter int res = E_OK; 4322166124Srafan unsigned int i; 432350276Speter unsigned int len; 432450276Speter 4325166124Srafan#if USE_WIDEC_SUPPORT 4326166124Srafan FIELD_CELL *widevalue = 0; 4327166124Srafan#endif 4328166124Srafan 4329166124Srafan T((T_CALLED("set_field_buffer(%p,%d,%s)"), field, buffer, _nc_visbuf(value))); 4330166124Srafan 4331166124Srafan if (!field || !value || ((buffer < 0) || (buffer > field->nbuf))) 433250276Speter RETURN(E_BAD_ARGUMENT); 433350276Speter 4334166124Srafan len = Buffer_Length(field); 433550276Speter 433650276Speter if (Growable(field)) 433750276Speter { 433850276Speter /* for a growable field we must assume zero terminated strings, because 4339166124Srafan somehow we have to detect the length of what should be copied. 4340166124Srafan */ 434150276Speter unsigned int vlen = strlen(value); 4342166124Srafan 434350276Speter if (vlen > len) 434450276Speter { 434550276Speter if (!Field_Grown(field, 4346166124Srafan (int)(1 + (vlen - len) / ((field->rows + field->nrow) 4347166124Srafan * field->cols)))) 434850276Speter RETURN(E_SYSTEM_ERROR); 434950276Speter 435050276Speter len = vlen; 435150276Speter } 435250276Speter } 435350276Speter 4354166124Srafan p = Address_Of_Nth_Buffer(field, buffer); 4355166124Srafan 4356166124Srafan#if USE_WIDEC_SUPPORT 4357166124Srafan /* 4358166124Srafan * Use addstr's logic for converting a string to an array of cchar_t's. 4359166124Srafan * There should be a better way, but this handles nonspacing characters 4360166124Srafan * and other special cases that we really do not want to handle here. 4361166124Srafan */ 4362184989Srafan#if NCURSES_EXT_FUNCS 4363184989Srafan if (wresize(field->working, field->drows, field->dcols) == ERR) 4364184989Srafan#endif 4365184989Srafan { 4366184989Srafan delwin(field->working); 4367184989Srafan field->working = newpad(field->drows, field->dcols); 4368184989Srafan } 4369166124Srafan wclear(field->working); 4370166124Srafan mvwaddstr(field->working, 0, 0, value); 4371166124Srafan 4372174993Srafan if ((widevalue = typeCalloc(FIELD_CELL, len + 1)) == 0) 4373166124Srafan { 4374166124Srafan RETURN(E_SYSTEM_ERROR); 4375166124Srafan } 4376166124Srafan else 4377166124Srafan { 4378184989Srafan for (i = 0; i < (unsigned)field->drows; ++i) 4379184989Srafan { 4380184989Srafan mvwin_wchnstr(field->working, i, 0, 4381184989Srafan widevalue + (i * field->dcols), 4382184989Srafan field->dcols); 4383184989Srafan } 4384166124Srafan for (i = 0; i < len; ++i) 4385166124Srafan { 4386166124Srafan if (CharEq(myZEROS, widevalue[i])) 4387166124Srafan { 4388166124Srafan while (i < len) 4389166124Srafan p[i++] = myBLANK; 4390166124Srafan break; 4391166124Srafan } 4392166124Srafan p[i] = widevalue[i]; 4393166124Srafan } 4394166124Srafan free(widevalue); 4395166124Srafan } 439650276Speter#else 4397166124Srafan for (i = 0; i < len; ++i) 439850276Speter { 4399166124Srafan if (value[i] == '\0') 4400166124Srafan { 4401166124Srafan while (i < len) 4402166124Srafan p[i++] = myBLANK; 4403166124Srafan break; 4404166124Srafan } 4405166124Srafan p[i] = value[i]; 440650276Speter } 440750276Speter#endif 440850276Speter 4409166124Srafan if (buffer == 0) 441050276Speter { 441150276Speter int syncres; 4412166124Srafan 4413166124Srafan if (((syncres = Synchronize_Field(field)) != E_OK) && 4414166124Srafan (res == E_OK)) 441550276Speter res = syncres; 4416166124Srafan if (((syncres = Synchronize_Linked_Fields(field)) != E_OK) && 4417166124Srafan (res == E_OK)) 441850276Speter res = syncres; 441950276Speter } 442050276Speter RETURN(res); 4421166124Srafan} 442250276Speter 442350276Speter/*--------------------------------------------------------------------------- 4424166124Srafan| Facility : libnform 442550276Speter| Function : char *field_buffer(const FIELD *field,int buffer) 4426166124Srafan| 442750276Speter| Description : Return the address of the buffer for the field. 442850276Speter| 442950276Speter| Return Values : Pointer to buffer or NULL if arguments were invalid. 443050276Speter+--------------------------------------------------------------------------*/ 443176726SpeterNCURSES_EXPORT(char *) 4432166124Srafanfield_buffer(const FIELD *field, int buffer) 443350276Speter{ 4434166124Srafan char *result = 0; 4435166124Srafan 4436166124Srafan T((T_CALLED("field_buffer(%p,%d)"), field, buffer)); 4437166124Srafan 443850276Speter if (field && (buffer >= 0) && (buffer <= field->nbuf)) 4439166124Srafan { 4440166124Srafan#if USE_WIDEC_SUPPORT 4441166124Srafan FIELD_CELL *data = Address_Of_Nth_Buffer(field, buffer); 4442166124Srafan unsigned need = 0; 4443166124Srafan int size = Buffer_Length(field); 4444166124Srafan int n; 4445166124Srafan 4446166124Srafan /* determine the number of bytes needed to store the expanded string */ 4447166124Srafan for (n = 0; n < size; ++n) 4448166124Srafan { 4449166124Srafan if (!isWidecExt(data[n])) 4450166124Srafan { 4451166124Srafan mbstate_t state; 4452166124Srafan size_t next; 4453166124Srafan 4454166124Srafan init_mb(state); 4455166124Srafan next = _nc_wcrtomb(0, data[n].chars[0], &state); 4456166124Srafan if (!isEILSEQ(next)) 4457174993Srafan need += next; 4458166124Srafan } 4459166124Srafan } 4460166124Srafan 4461166124Srafan /* allocate a place to store the expanded string */ 4462166124Srafan if (field->expanded[buffer] != 0) 4463166124Srafan free(field->expanded[buffer]); 4464166124Srafan field->expanded[buffer] = typeMalloc(char, need + 1); 4465166124Srafan 4466166124Srafan /* expand the multibyte data */ 4467166124Srafan if ((result = field->expanded[buffer]) != 0) 4468166124Srafan { 4469166124Srafan wclear(field->working); 4470166124Srafan mvwadd_wchnstr(field->working, 0, 0, data, size); 4471174993Srafan mvwinnstr(field->working, 0, 0, result, (int)need); 4472166124Srafan } 4473166124Srafan#else 4474166124Srafan result = Address_Of_Nth_Buffer(field, buffer); 4475166124Srafan#endif 4476166124Srafan } 4477166124Srafan returnPtr(result); 447850276Speter} 447950276Speter 4480166124Srafan#if USE_WIDEC_SUPPORT 4481166124Srafan 4482166124Srafan/* FIXME: see lib_get_wch.c */ 4483166124Srafan#if HAVE_MBTOWC && HAVE_MBLEN 4484166124Srafan#define reset_mbytes(state) mblen(NULL, 0), mbtowc(NULL, NULL, 0) 4485166124Srafan#define count_mbytes(buffer,length,state) mblen(buffer,length) 4486166124Srafan#define trans_mbytes(wch,buffer,length,state) \ 4487166124Srafan (int) mbtowc(&wch, buffer, length) 4488166124Srafan#elif HAVE_MBRTOWC && HAVE_MBRLEN 4489166124Srafan#define NEED_STATE 4490166124Srafan#define reset_mbytes(state) init_mb(state) 4491166124Srafan#define count_mbytes(buffer,length,state) mbrlen(buffer,length,&state) 4492166124Srafan#define trans_mbytes(wch,buffer,length,state) \ 4493166124Srafan (int) mbrtowc(&wch, buffer, length, &state) 4494166124Srafan#else 4495166124Srafanmake an error 4496166124Srafan#endif 4497166124Srafan 4498166124Srafan/*--------------------------------------------------------------------------- 4499166124Srafan| Convert a multibyte string to a wide-character string. The result must be 4500166124Srafan| freed by the caller. 4501166124Srafan+--------------------------------------------------------------------------*/ 4502166124SrafanNCURSES_EXPORT(wchar_t *) 4503166124Srafan_nc_Widen_String(char *source, int *lengthp) 4504166124Srafan{ 4505166124Srafan wchar_t *result = 0; 4506166124Srafan wchar_t wch; 4507166124Srafan size_t given = strlen(source); 4508166124Srafan size_t tries; 4509166124Srafan int pass; 4510166124Srafan int status; 4511166124Srafan 4512166124Srafan#ifdef NEED_STATE 4513166124Srafan mbstate_t state; 4514166124Srafan#endif 4515166124Srafan 4516166124Srafan for (pass = 0; pass < 2; ++pass) 4517166124Srafan { 4518166124Srafan unsigned need = 0; 4519166124Srafan size_t passed = 0; 4520166124Srafan 4521166124Srafan while (passed < given) 4522166124Srafan { 4523166124Srafan bool found = FALSE; 4524166124Srafan 4525166124Srafan for (tries = 1, status = 0; tries <= (given - passed); ++tries) 4526166124Srafan { 4527166124Srafan int save = source[passed + tries]; 4528166124Srafan 4529166124Srafan source[passed + tries] = 0; 4530166124Srafan reset_mbytes(state); 4531166124Srafan status = trans_mbytes(wch, source + passed, tries, state); 4532166124Srafan source[passed + tries] = save; 4533166124Srafan 4534166124Srafan if (status > 0) 4535166124Srafan { 4536166124Srafan found = TRUE; 4537166124Srafan break; 4538166124Srafan } 4539166124Srafan } 4540166124Srafan if (found) 4541166124Srafan { 4542166124Srafan if (pass) 4543166124Srafan { 4544166124Srafan result[need] = wch; 4545166124Srafan } 4546166124Srafan passed += status; 4547166124Srafan ++need; 4548166124Srafan } 4549166124Srafan else 4550166124Srafan { 4551166124Srafan if (pass) 4552166124Srafan { 4553166124Srafan result[need] = source[passed]; 4554166124Srafan } 4555166124Srafan ++need; 4556166124Srafan ++passed; 4557166124Srafan } 4558166124Srafan } 4559166124Srafan 4560166124Srafan if (!pass) 4561166124Srafan { 4562166124Srafan if (!need) 4563166124Srafan break; 4564166124Srafan result = typeCalloc(wchar_t, need); 4565166124Srafan 4566166124Srafan *lengthp = need; 4567166124Srafan if (result == 0) 4568166124Srafan break; 4569166124Srafan } 4570166124Srafan } 4571166124Srafan 4572166124Srafan return result; 4573166124Srafan} 4574166124Srafan#endif 4575166124Srafan 457650276Speter/* frm_driver.c ends here */ 4577