【问题标题】:Clearing a field buffer in ncurses在 ncurses 中清除字段缓冲区
【发布时间】:2015-10-24 19:47:52
【问题描述】:

我已经为 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, " ");
        }
    }

但是,它会在 second 调用 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 中的字段缓冲区,而不删除和重新添加它?

【问题讨论】:

    标签: c++ ncurses curses


    【解决方案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的帖子,我开始觉得我的生活是个谎言:-)。

    【讨论】:

    • 你能详细说明一下答案吗? :-)
    • 那些会清除关联的窗口,但不会清除字段缓冲区。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-01-26
    • 2012-10-12
    • 1970-01-01
    • 1970-01-01
    • 2013-01-23
    相关资源
    最近更新 更多