0

I’m new to programming and I’d like to realise the following with ncurses in C: A form with fields to fill out and underneath this form, there is a continuously changing sensor value to be observed by the user during filling out the form, which results in the desired actions.

I’m glad I made it that far, that I can put the field buffer into my variables now, by pressing return, but now I’m facing a problem which seems to be not googleable.

My program started off from the example, which I posted underneath. In the original example I just added two lines and it already demonstrates my problem very well.

I set timeout(1); so the getch() function won’t wait for user input in the form before it prints the fresh sensor values. Into the while-loop I put in the sennsor value with mvprint.

Now the sensor values are always up-to-date and it is still possible to move from one field to the other with the arrow keys and type into the fields. But the visible Cursor always stays at the sensor value, which makes sense to me, because it is continuously moved there for printing. The forms driver seems to remember the position which was edited lastly, so that editing the fields will still function, but without any optical hint at which position the typing will be. The documentation refers to this position as the “editing-cursor” at one point.

Am I doing something completely wrong? Or is there a way to highlight the field, or even make the editing-cursor visible? Thank you!

    /* gcc -Wall -pthread -g -o formncurses formncurses.c -lform -lncurses */

    #include <form.h>

    int main()
    {   FIELD *field[3];
    FORM  *my_form;
    int ch;

    /* Initialize curses */
    initscr();
    cbreak();
    noecho();
    keypad(stdscr, TRUE);

    timeout(1);

    /* Initialize the fields */
    field[0] = new_field(1, 10, 4, 18, 0, 0);
    field[1] = new_field(1, 10, 6, 18, 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); 
    field_opts_off(field[1], O_AUTOSKIP);

    /* Create the form and post it */
    my_form = new_form(field);
    post_form(my_form);
    refresh();

    mvprintw(4, 10, "Value 1:");
    mvprintw(6, 10, "Value 2:");
    refresh();

    /* Loop through to get user requests */
    while((ch = getch()) != KEY_F(1))
    {   switch(ch)
        {   case KEY_DOWN:
                /* Go to next field */
                form_driver(my_form, REQ_NEXT_FIELD);
                /* Go to the end of the present buffer */
                /* Leaves nicely at the last character */
                form_driver(my_form, REQ_END_LINE);
                break;
            case KEY_UP:
                /* Go to previous field */
                form_driver(my_form, REQ_PREV_FIELD);
                form_driver(my_form, REQ_END_LINE);
                break;
            default:
                /* If this is a normal character, it gets */
                /* Printed                */    
                form_driver(my_form, ch);
                break;
        }

    mvprintw(12, 10, "Here stands the changing sensor value");

    }

    /* Un post form and free the memory */
    unpost_form(my_form);
    free_form(my_form);
    free_field(field[0]);
    free_field(field[1]); 

    endwin();
    return 0;
}
Wonnegrausen
  • 1
  • 1
  • 4

2 Answers2

1

The getch call essentially tells ncurses to leave the cursor where your mvprintw has left it — on the standard screen. To get it to move to your form, you would have to tell it to use wgetch, passing the WINDOW* pointer for the current form (which in turn holds a window's position for the field).

Further reading:

Thomas Dickey
  • 51,086
  • 7
  • 70
  • 105
  • Great! With an extra window for the form an wgetch its working now. Actually I have tried this out before and apparently made some mistake so that the value would not update unless I pressed a key. So I concluded (wrongly) that wgetch is not affected by timeout(1). Thanks a lot! – Wonnegrausen Apr 27 '17 at 16:02
0

One thing that @Thomas's answer does not provide is how to highlight the active field (as indicated by the title of the question). For completion's sake, I am going to add a function here that will allow you to do just that:

void highlight_current_field(FORM *form, FIELD *fields[])
{
    FIELD *cfield = current_field(form);
    FIELD *currfield;
    int i = 0;
    while ((currfield = fields[i]) != NULL)
    {
        if (currfield == cfield)
            set_field_back(currfield, A_STANDOUT);
        else if (i >= 4)
            set_field_back(currfield, A_UNDERLINE);

        ++i;
    }
}

I hope this helps fellow travelers. For more information on the attributes provide, check out this site.

cirrusio
  • 580
  • 5
  • 28