As title suggests I need to leave a field in the form when a valid date is typed. I don't know if it is necessary to write from scratch a new validation type with:
typedef int (*HOOK)(); /* pointer to function returning int */
FIELDTYPE *new_fieldtype(HOOK f_validate, /* field validator */
HOOK c_validate) /* character validator */
or there is a simpler way to avoid the focus moving onto the next field if a function return false when an invalid date is typed.
I have the function isValidDate(…)
taken from here and I read the HowTo about to create a Custom Validation Type but it's still too complex for me.
I need an example about how to proceed:
Here the code I've written so far:
#include <stdio.h>
#include <stdbool.h>
#include <form.h>
// Macro to check if a given year is a leap year.
#define isLeapYear( year ) ( ( (year) % 4 == 0 && (year) % 100 != 0 ) || ( (year) % 400 == 0 ) )
// Define a structure to represent date
struct Date {
int day;
int month;
int year;
};
// Function to validate a date
bool isValidDate( struct Date date )
{
// the 1st element represents the number of days in January,
// second for Feb and so on, the last element represents days in Dec
int daysInMonth[] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
// Check if year is valid (greater than 0)
if (date.year <= 0)
return false;
// Check if month is between 1 and 12
if (date.month < 1 || date.month > 12)
return false;
// Check if day is within the range for the given month
if (date.day >= 1 && date.day <= daysInMonth[date.month - 1])
return true;
// Check for February in case of leap year
if (date.month == 2 && isLeapYear(date.year))
if (date.day < 1 || date.day > 29)
return false;
// If all conditions are met, the date is valid
return true;
}
int main()
{
FIELD *field[3];
FORM *input_form;
int ch, code = 0;
bool Ins = true;
// Initialize curses
initscr();
cbreak();
noecho();
keypad(stdscr, TRUE);
// Initialize the fields
field[0] = new_field(1, 16, 4, 19, 0, 0);
field[1] = new_field(1, 10, 6, 33, 0, 0);
field[2] = NULL;
// Set field options
set_field_back(field[0], A_UNDERLINE); // Print a line for the option
field_opts_off(field[0], O_AUTOSKIP); // Don't go to next field when this field is filled up
set_field_back(field[1], A_UNDERLINE);
// Create the form and post it
input_form = new_form(field);
post_form(input_form);
refresh();
mvprintw(6, 10, "Birth date DD/MM/YYYY:");
mvprintw(4, 10, "Name...: ");
refresh();
// Loop through to get user requests
while( (ch = getch()) != KEY_F(1) )
{
switch(ch)
{
case '\n':
case '\t':
case KEY_DOWN:
// Go to next field
form_driver(input_form, REQ_NEXT_FIELD);
// Go to the end of the present buffer, leaves nicely at the last character
form_driver(input_form, REQ_END_LINE);
break;
case KEY_BTAB:
case KEY_UP:
// Go to previous field
form_driver(input_form, REQ_PREV_FIELD);
form_driver(input_form, REQ_END_LINE);
break;
case KEY_BACKSPACE:
case 127:
form_driver(input_form, REQ_PREV_CHAR);
form_driver(input_form, REQ_DEL_CHAR);
break;
case KEY_HOME:
form_driver(input_form, REQ_BEG_LINE);
break;
case KEY_END:
form_driver(input_form, REQ_END_LINE);
break;
case KEY_LEFT:
form_driver(input_form, REQ_PREV_CHAR);
break;
case KEY_RIGHT:
form_driver(input_form, REQ_NEXT_CHAR);
break;
case KEY_IC: // Ins key: toggle between insertion/overwrite mode
form_driver(input_form, ( Ins = ! Ins ) ? REQ_INS_MODE : REQ_OVL_MODE );
break;
case KEY_DC: // Canc key
form_driver(input_form, REQ_DEL_CHAR);
form_driver(input_form, REQ_PREV_CHAR);
break;
default:
// If this is a normal character, it gets printed.
form_driver(input_form, ch);
form_driver(input_form, REQ_VALIDATION);
break;
}
}
// Un post form and free the memory
unpost_form(input_form);
free_form(input_form);
free_field(field[0]);
free_field(field[1]);
free_field(field[2]);
endwin();
exit_curses( code );
return 0;
}
To compile I use the following command:
gcc -Wall -pedantic -Wextra filename.c -lform -lncurses