X-Git-Url: https://ncurses.scripts.mit.edu/?p=ncurses.git;a=blobdiff_plain;f=form%2Ffrm_driver.c;h=123127b7db79fdfe36832c4ff29c4123210e0858;hp=f78a45e6b060853a0534684f8fce1a00c17ca9a6;hb=5ed80e8d7031c3fa12b4915d5e1f040257a24323;hpb=cfd9c6f8e5af24820fefbb789b7345d93b8ed837 diff --git a/form/frm_driver.c b/form/frm_driver.c index f78a45e6..123127b7 100644 --- a/form/frm_driver.c +++ b/form/frm_driver.c @@ -1,5 +1,5 @@ /**************************************************************************** - * Copyright (c) 1998-2014,2015 Free Software Foundation, Inc. * + * Copyright (c) 1998-2018,2019 Free Software Foundation, Inc. * * * * Permission is hereby granted, free of charge, to any person obtaining a * * copy of this software and associated documentation files (the * @@ -32,7 +32,7 @@ #include "form.priv.h" -MODULE_ID("$Id: frm_driver.c,v 1.117 2015/11/28 20:39:09 tom Exp $") +MODULE_ID("$Id: frm_driver.c,v 1.128 2019/01/20 01:25:02 tom Exp $") /*---------------------------------------------------------------------------- This is the core module of the form library. It contains the majority @@ -99,9 +99,9 @@ Perhaps at some time we will make this configurable at runtime. #define GROW_IF_NAVIGATE (1) #if USE_WIDEC_SUPPORT -#define myADDNSTR(w, s, n) wadd_wchnstr(w, s, n) -#define myINSNSTR(w, s, n) wins_wchnstr(w, s, n) -#define myINNSTR(w, s, n) fix_wchnstr(w, s, n) +#define myADDNSTR(w, s, n) wide_waddnstr(w, s, n) +#define myINSNSTR(w, s, n) wide_winsnstr(w, s, n) +#define myINNSTR(w, s, n) wide_winnstr(w, s, n) #define myWCWIDTH(w, y, x) cell_width(w, y, x) #else #define myADDNSTR(w, s, n) waddnstr(w, s, n) @@ -239,9 +239,29 @@ check_pos(FORM *form, int lineno) Wide-character special functions --------------------------------------------------------------------------*/ #if USE_WIDEC_SUPPORT -/* like winsnstr */ +/* add like waddnstr, but using cchar_t* rather than char* + */ +static int +wide_waddnstr(WINDOW *w, const cchar_t *s, int n) +{ + int rc = OK; + + while (n-- > 0) + { + if ((rc = wadd_wch(w, s)) != OK) + break; + ++s; + } + return rc; +} + +/* insert like winsnstr, but using cchar_t* rather than char* + * + * X/Open Curses has no close equivalent; inserts are done only with wchar_t + * strings. + */ static int -wins_wchnstr(WINDOW *w, cchar_t *s, int n) +wide_winsnstr(WINDOW *w, const cchar_t *s, int n) { int code = ERR; int y, x; @@ -257,11 +277,13 @@ wins_wchnstr(WINDOW *w, cchar_t *s, int n) return code; } -/* win_wchnstr is inconsistent with winnstr, since it returns OK rather than - * the number of items transferred. +/* retrieve like winnstr, but using cchar_t*, rather than char*. + * + * X/Open Curses' closest equivalent, win_wchnstr(), is inconsistent with + * winnstr(), since it returns OK rather than the number of items transferred. */ static int -fix_wchnstr(WINDOW *w, cchar_t *s, int n) +wide_winnstr(WINDOW *w, cchar_t *s, int n) { int x; @@ -844,11 +866,13 @@ _nc_Position_Form_Cursor(FORM *form) | E_BAD_ARGUMENT - invalid form pointer | E_SYSTEM_ERROR - general error +--------------------------------------------------------------------------*/ +static bool move_after_insert = TRUE; NCURSES_EXPORT(int) _nc_Refresh_Current_Field(FORM *form) { WINDOW *formwin; FIELD *field; + bool is_public; T((T_CALLED("_nc_Refresh_Current_Field(%p)"), (void *)form)); @@ -861,102 +885,105 @@ _nc_Refresh_Current_Field(FORM *form) field = form->current; formwin = Get_Form_Window(form); - if (Field_Has_Option(field, O_PUBLIC)) + is_public = Field_Has_Option(field, O_PUBLIC); + + if (Is_Scroll_Field(field)) { - if (Is_Scroll_Field(field)) + /* Again, in this case the fieldwin isn't derived from formwin, + so we have to perform a copy operation. */ + if (Single_Line_Field(field)) { - /* Again, in this case the fieldwin isn't derived from formwin, - so we have to perform a copy operation. */ - if (Single_Line_Field(field)) - { - /* horizontal scrolling */ - if (form->curcol < form->begincol) - form->begincol = form->curcol; - else - { - if (form->curcol >= (form->begincol + field->cols)) - form->begincol = form->curcol - field->cols + 1; - } - copywin(form->w, - formwin, - 0, - form->begincol, - field->frow, - field->fcol, - field->frow, - field->cols + field->fcol - 1, - 0); - } + /* horizontal scrolling */ + if (form->curcol < form->begincol) + form->begincol = form->curcol; else { - /* A multi-line, i.e. vertical scrolling field */ - int row_after_bottom, first_modified_row, first_unmodified_row; + if (form->curcol >= (form->begincol + field->cols)) + form->begincol = form->curcol - field->cols + + (move_after_insert ? 1 : 0); + } + if (is_public) + copywin(form->w, + formwin, + 0, + form->begincol, + field->frow, + field->fcol, + field->frow, + field->cols + field->fcol - 1, + 0); + } + else + { + /* A multi-line, i.e. vertical scrolling field */ + int row_after_bottom, first_modified_row, first_unmodified_row; - if (field->drows > field->rows) + if (field->drows > field->rows) + { + row_after_bottom = form->toprow + field->rows; + if (form->currow < form->toprow) { - row_after_bottom = form->toprow + field->rows; - if (form->currow < form->toprow) - { - form->toprow = form->currow; - SetStatus(field, _NEWTOP); - } - if (form->currow >= row_after_bottom) - { - form->toprow = form->currow - field->rows + 1; - SetStatus(field, _NEWTOP); - } - if (field->status & _NEWTOP) - { - /* means we have to copy whole range */ - first_modified_row = form->toprow; - first_unmodified_row = first_modified_row + field->rows; - ClrStatus(field, _NEWTOP); - } - else - { - /* we try to optimize : finding the range of touched - lines */ - first_modified_row = form->toprow; - while (first_modified_row < row_after_bottom) - { - if (is_linetouched(form->w, first_modified_row)) - break; - first_modified_row++; - } - first_unmodified_row = first_modified_row; - while (first_unmodified_row < row_after_bottom) - { - if (!is_linetouched(form->w, first_unmodified_row)) - break; - first_unmodified_row++; - } - } + form->toprow = form->currow; + SetStatus(field, _NEWTOP); } - else + if (form->currow >= row_after_bottom) { + form->toprow = form->currow - field->rows + 1; + SetStatus(field, _NEWTOP); + } + if (field->status & _NEWTOP) + { + /* means we have to copy whole range */ first_modified_row = form->toprow; first_unmodified_row = first_modified_row + field->rows; + ClrStatus(field, _NEWTOP); + } + else + { + /* we try to optimize : finding the range of touched + lines */ + first_modified_row = form->toprow; + while (first_modified_row < row_after_bottom) + { + if (is_linetouched(form->w, first_modified_row)) + break; + first_modified_row++; + } + first_unmodified_row = first_modified_row; + while (first_unmodified_row < row_after_bottom) + { + if (!is_linetouched(form->w, first_unmodified_row)) + break; + first_unmodified_row++; + } } - if (first_unmodified_row != first_modified_row) - copywin(form->w, - formwin, - first_modified_row, - 0, - field->frow + first_modified_row - form->toprow, - field->fcol, - field->frow + first_unmodified_row - form->toprow - 1, - field->cols + field->fcol - 1, - 0); } - wsyncup(formwin); - } - else - { - /* if the field-window is simply a derived window, i.e. contains no - * invisible parts, the whole thing is trivial - */ - wsyncup(form->w); + else + { + first_modified_row = form->toprow; + first_unmodified_row = first_modified_row + field->rows; + } + if (first_unmodified_row != first_modified_row && is_public) + copywin(form->w, + formwin, + first_modified_row, + 0, + field->frow + first_modified_row - form->toprow, + field->fcol, + field->frow + first_unmodified_row - form->toprow - 1, + field->cols + field->fcol - 1, + 0); } + if (is_public) + wsyncup(formwin); + } + else + { + /* if the field-window is simply a derived window, i.e. contains no + * invisible parts, the whole thing is trivial + */ + if (is_public) + wsyncup(form->w); } untouchwin(form->w); returnCode(_nc_Position_Form_Cursor(form)); @@ -1023,8 +1050,11 @@ static void Undo_Justification(FIELD *field, WINDOW *win) { FIELD_CELL *bp; + int y, x; int len; + getyx(win, y, x); + bp = (Field_Has_Option(field, O_NO_LEFT_STRIP) ? field->buf : Get_Start_Of_Data(field->buf, Buffer_Length(field))); @@ -1036,6 +1066,7 @@ Undo_Justification(FIELD *field, WINDOW *win) wmove(win, 0, 0); myADDNSTR(win, bp, len); } + wmove(win, y, x); } /*--------------------------------------------------------------------------- @@ -1275,7 +1306,8 @@ _nc_Synchronize_Attributes(FIELD *field) copywin(form->w, formwin, 0, 0, field->frow, field->fcol, - field->rows - 1, field->cols - 1, 0); + field->frow + field->rows - 1, + field->fcol + field->cols - 1, 0); wsyncup(formwin); Buffer_To_Window(field, form->w); SetStatus(field, _NEWTOP); /* fake refresh to paint all */ @@ -1395,6 +1427,57 @@ _nc_Synchronize_Options(FIELD *field, Field_Options newopts) returnCode(res); } +/* + * Removes the focus from the current field of the form. + */ +void +_nc_Unset_Current_Field(FORM *form) +{ + FIELD *field = form->current; + + _nc_Refresh_Current_Field(form); + if (Field_Has_Option(field, O_PUBLIC)) + { + if (field->drows > field->rows) + { + if (form->toprow == 0) + ClrStatus(field, _NEWTOP); + else + SetStatus(field, _NEWTOP); + } + else + { + if (Justification_Allowed(field)) + { + Window_To_Buffer(form, field); + werase(form->w); + Perform_Justification(field, form->w); + if (Field_Has_Option(field, O_DYNAMIC_JUSTIFY) && + (form->w->_parent == 0)) + { + copywin(form->w, + Get_Form_Window(form), + 0, + 0, + field->frow, + field->fcol, + field->frow, + field->cols + field->fcol - 1, + 0); + wsyncup(Get_Form_Window(form)); + } + else + { + wsyncup(form->w); + } + } + } + } + delwin(form->w); + form->w = (WINDOW *)0; + form->current = 0; +} + /*--------------------------------------------------------------------------- | Facility : libnform | Function : int _nc_Set_Current_Field(FORM * form, @@ -1415,7 +1498,7 @@ _nc_Set_Current_Field(FORM *form, FIELD *newfield) T((T_CALLED("_nc_Set_Current_Field(%p,%p)"), (void *)form, (void *)newfield)); - if (!form || !newfield || !form->current || (newfield->form != form)) + if (!form || !newfield || (newfield->form != form)) returnCode(E_BAD_ARGUMENT); if ((form->status & _IN_DRIVER)) @@ -1429,51 +1512,10 @@ _nc_Set_Current_Field(FORM *form, FIELD *newfield) if ((field != newfield) || !(form->status & _POSTED)) { - if ((form->w) && + if (field && (form->w) && (Field_Has_Option(field, O_VISIBLE)) && (field->form->curpage == field->page)) - { - _nc_Refresh_Current_Field(form); - if (Field_Has_Option(field, O_PUBLIC)) - { - if (field->drows > field->rows) - { - if (form->toprow == 0) - ClrStatus(field, _NEWTOP); - else - SetStatus(field, _NEWTOP); - } - else - { - if (Justification_Allowed(field)) - { - Window_To_Buffer(form, field); - werase(form->w); - Perform_Justification(field, form->w); - if (Field_Has_Option(field, O_DYNAMIC_JUSTIFY) && - (form->w->_parent == 0)) - { - copywin(form->w, - Get_Form_Window(form), - 0, - 0, - field->frow, - field->fcol, - field->frow, - field->cols + field->fcol - 1, - 0); - wsyncup(Get_Form_Window(form)); - } - else - { - wsyncup(form->w); - } - } - } - } - delwin(form->w); - form->w = (WINDOW *)0; - } + _nc_Unset_Current_Field(form); field = newfield; @@ -4034,7 +4076,7 @@ Data_Entry_w(FORM *form, wchar_t c) cchar_t temp_ch; given[0] = c; - given[1] = 1; + given[1] = 0; setcchar(&temp_ch, given, 0, 0, (void *)0); if ((Field_Has_Option(field, O_BLANK)) && First_Position_In_Current_Field(form) && @@ -4147,6 +4189,12 @@ Data_Entry(FORM *form, int c) bool End_Of_Field = (((field->drows - 1) == form->currow) && ((field->dcols - 1) == form->curcol)); + if (Field_Has_Option(field, O_EDGE_INSERT_STAY)) + move_after_insert = !!(form->curcol + - form->begincol + - field->cols + + 1); + SetStatus(form, _WINDOW_MODIFIED); if (End_Of_Field && !Growable(field) && (Field_Has_Option(field, O_AUTOSKIP))) result = Inter_Field_Navigation(FN_Next_Field, form); @@ -4311,12 +4359,14 @@ form_driver(FORM *form, int c) const Binding_Info *BI = (Binding_Info *) 0; int res = E_UNKNOWN_COMMAND; + move_after_insert = TRUE; + T((T_CALLED("form_driver(%p,%d)"), (void *)form, c)); if (!form) RETURN(E_BAD_ARGUMENT); - if (!(form->field)) + if (!(form->field) || !(form->current)) RETURN(E_NOT_CONNECTED); assert(form->page);