在ncurses中清除字段缓冲区

时间:2015-10-24 19:47:53

标签: c++ ncurses curses

我为curses表单对象构建了一个通用包装器,用于大型 我正在研究的模拟项目。

基本上,我实例化一个generic_form对象,添加一些字段和它们 对它的描述,然后通过fill_form()例程给它焦点并获得用户输入。

因为每个generic_form对象可以多次使用,也就是说,每次实例化时可能会多次调用fill_form(),我需要在fill_form()例程的开头清除字段缓冲区。目前,我在例程的开头使用它:

//clear the field buffers in case there's junk in them
    for (std::vector<FIELD*>::iterator clear_iter = fields.begin();
            clear_iter != fields.end(); clear_iter++)
    {
        if (*clear_iter != nullptr)
        {
            set_field_buffer(*clear_iter, 0, " ");
        }
    }

但是,它会在第二次调用fill_form()例程的set_field_buffer行引发浮点异常。此外,set_field_buffer行似乎实际上没有做任何事情,至少没有清除缓冲区,因为在例程结束时没有调用free_field,而是在对象析构函数中,字段缓冲区保持不变在每次后续通话中。

为简洁起见,这是(丑陋的,正在开发的)fill_form()例程的全部内容:

void generic_form::fill_form()
{
    //fields.push_back(NULL);
    if (fields.size() == 1)
    {
        fields.push_back(NULL);
        form = new_form(static_cast<FIELD**>(fields.data()));
        fields.erase((fields.end() - 1));
        assert(fields.size() == 1);
    }
    else
    {
        form = new_form(static_cast<FIELD**>(fields.data()));
    }
    WINDOW* form_win = derwin(screen, fields.size() + 1, largest_desc + 6, ypos, 
            xpos);
    set_form_win(form, form_win);
    set_form_sub(form, form_win);
    //clear the field buffers in case there's junk in them
    for (std::vector<FIELD*>::iterator clear_iter = fields.begin();
            clear_iter != fields.end(); clear_iter++)
    {
        if (*clear_iter != nullptr)
        {
            set_field_buffer(*clear_iter, 0, " ");
        }
    }
    post_form(form);
    for (int x = 0; x < descriptions.size(); x++)
    {
        mvwprintw(form_win, x, 0, descriptions.at(x).c_str());
    }
    wmove(form_win, 0, largest_desc + 1);
    touchwin(screen);
    wrefresh(form_win);
    /* Loop through to get user requests */
    int ch;
    while((ch = getch()) != '\n')//KEY_F(1))
    {   switch(ch)
            {       
            case KEY_DOWN:
                    /* Go to next field */
                    form_driver(form, REQ_NEXT_FIELD);
                    /* Go to the end of the present buffer */
                    /* Leaves nicely at the last character */
                    form_driver(form, REQ_END_LINE);
                    break;
            case KEY_UP:
                    /* Go to previous field */
                    form_driver(form, REQ_PREV_FIELD);
                    form_driver(form, REQ_END_LINE);
                    break;
            case KEY_LEFT:
                    form_driver(form, REQ_PREV_CHAR);
                    break;
            case KEY_RIGHT:
                    form_driver(form, REQ_NEXT_CHAR);
                    break;

            // Delete the char before cursor
            case KEY_BACKSPACE:
            case 127:
                    form_driver(form, REQ_DEL_PREV);
                                break;

            // Delete the char under the cursor
            case KEY_DC:
                    form_driver(form, REQ_DEL_CHAR);
                    break;
            default:
                    /* If this is a normal character, it gets */
                    /* Printed                */    
                    form_driver(form, ch);
                    break;
            }
    }
    form_driver(form, REQ_VALIDATION);
    for (int x = 0; x < fields.size() && first_run; x++)
    {
        //store the int_inputs from the forms
        if ((fields.at(x) != nullptr) && (field_type(fields.at(x)) ==
                TYPE_INTEGER))
        {
            int_inputs.push_back(std::atoi(field_buffer((fields.at(x)), 0)));
        }
        if ((fields.at(x) != nullptr) && (field_type(fields.at(x)) ==
                TYPE_ALPHA))
        {
            str_inputs.push_back(field_buffer((fields.at(x)), 0));
        }
    }
    first_run = false;
    /* Un post form and free the memory */
    unpost_form(form);
    free_form(form);
    for (int x = 0; x < fields.size(); x++)
    {
        free_field(fields.at(x));
    }
    delwin(form_win);
}

长话短说/ TLDR: 如何清除或重置ncurses中的字段缓冲区,而不删除并重新添加它?

1 个答案:

答案 0 :(得分:1)

您可以使用form_driver()

清理字段缓冲区

摘录man form_driver

REQ_CLR_EOL
   Clear to end of line from cursor.

REQ_CLR_EOF
   Clear to end of field from cursor.

REQ_CLR_FIELD
   Clear the entire field.

详细说明一下:-),我使用类似以下的代码清除字段:

#include <stdio.h>
#include <stdlib.h>
#include <form.h>

enum f_name_l
{
  f_name, f_surname, f_last
};

int main (void)
{
  int ch = 0, i = 0;
  FIELD *field[3], *save_field;
  FORM *my_form;

  initscr ();
  start_color ();
  noecho ();
  raw ();
  keypad (stdscr, TRUE);
  refresh ();

  field[f_name] = new_field (1, 10, 0, 25, 0, 0);
  field[f_surname] = new_field (1, 10, 2, 25, 0, 0);
  field[f_last] = NULL;

  set_field_back (field[f_name], A_UNDERLINE);
  set_field_back (field[f_surname], A_UNDERLINE);

  my_form = new_form (field);
  post_form (my_form);

  // Form labels
  mvprintw (0, 1, "Name: ");
  mvprintw (2, 1, "Surname: ");
  mvprintw (4, 1, "F5 to clear active field. F6 to clear form.");

  pos_form_cursor (my_form);

  refresh ();

  // ^q to exit
  while ((ch = getch ()) != 17)
  {
    switch (ch)
    {
      case KEY_UP:
        form_driver (my_form, REQ_PREV_FIELD);
      break;
      case KEY_DOWN:
        form_driver (my_form, REQ_NEXT_FIELD);
      break;
      case KEY_F(5):
        form_driver (my_form, REQ_CLR_FIELD);
      break;
      case KEY_F(6):
        save_field = current_field (my_form);

        for (i = 0; i < f_last; i++)
        {
          set_current_field (my_form, field[i]);
          form_driver (my_form, REQ_CLR_FIELD);
        }

        set_current_field (my_form, save_field);
      break;
      default:
        form_driver (my_form, ch);
      break;
    }

    form_driver (my_form, REQ_VALIDATION);
  }

  endwin ();

  return EXIT_SUCCESS;
}

但是看到Thomas Dickey的帖子,我开始觉得我的生活是谎言: - )。