4

I spent the last year learning C++ (using C++ Primer as the recommended material from https://stackoverflow.com/a/388282/1440199). I wanted to learn to use ncurses to make my first flying-solo program. Even though NCurses is C-based, it is more or less not well known that native ncurses C++ wrappers exist. However, the documentation for them are almost nonexistent; there's a demo.cc file Ive been using as a basis, and a few places around the web. Anyways, Ive made it my final exam, so to speak, to understand and use these wrappers.

The problem I am encountering is of the "best programming practices" type: Because of the lack of documented examples, I'm unsure of the best way to create a submenu from the demo's initial menu system.

The best idea I can come up with is to use the example way to attach ncurses++'s NCursesUserItem to a menu item. Would the User Pointer be a pointer to the previous menu class? In NCurses, you can post and unpost menus, so I am also assuming I want to 'unpost' the previous menu when the new one 'posts', thats why I wanted a pointer to the previous menu upon showing the new one.

The typesafe example way to attach userdata(for set_item_userptr) to a menu item:

template<class T> class SubMenu : public NCursesUserItem<T>
{
  public:
    SubMenu (const char* p_name,
             const T* p_UserData)
            : NCursesUserItem<T>(p_name, static_cast<const char*>(0), p_UserData){}

    virtual ~SubMenu() {}

    bool action() {
        // I believe I want to unpost the previous menu here
        //  before posting the new submenu?
        NCursesUserItem<T>::UserData()->prev_menu()->unpost();
        //This doesn't work, but its kind of what I want to do.
        NCursesUserItem<T>::UserData()->post();
        return FALSE;
    }
};

The Main menu object. I created the Submenu object here and passed 'this' (the main menu pointer) as an argument to it.

class MainMenu : public NCursesMenu
{
  private:
    NCursesMenuItem** I;
    Choice0Menu* u;
#define n_items 3
  public:
    MainMenu ()
    : NCursesMenu (n_items+2, 25, (lines()-5)/2, (cols()-23)/2), I(0), u(0)
    {
        u = new Choice0Menu(this);
        I = new NCursesMenuItem*[1+n_items];
        I[0] = new SubMenu<Choice0Menu> ("Choice 0", u);
        I[1] = new PadAction("Choice 1");
        I[2] = new QuitItem();
        I[3] = new NCursesMenuItem();

        InitMenu(I, TRUE, TRUE);
    }
};

Choice0Menu class, which should contain a back button for returning to the Main Menu (I[2])

class Choice0Menu : public NCursesMenu
{
  private:
    NCursesMenuItem** I;
    MainMenu* w;
#define n_items 3

  public:
    Choice0Menu (MainMenu* prev)
    : NCursesMenu (n_items+2, 25, (lines()-5)/2, (cols()-23)/2), I(0), w(prev)
{
    I = new NCursesMenuItem*[1+n_items];
    I[0] = new ScanAction("Submenu Choice 0");
    I[1] = new PadAction("Submenu Choice 1");
    I[2] = new MainMenuAction("Go Back");
    I[3] = new NCursesMenuItem();

    InitMenu(I, TRUE, TRUE);

    // returns the pointer to the prev object
    MainMenu* prev_menu() const{
        return w;
    }
};

I just have a lot of doubts about this way of doing it, for example, maybe I dont have to pass the entire 'this' pointer to the main menu when creating the submenu, just the post and unpost members. And MainMenu and Choice0Menu classes are very similar in function, so maybe even make it into one template class? As Choice0Menu takes a MainMenu as an argument, maybe it should be T* to take any menu type..

My method doesn't seem the 'clean' way to program the problem.

Thanks for the help. I have been studying this problem for almost 2 weeks now...

mrflash818
  • 930
  • 13
  • 24
tgunnoe
  • 443
  • 1
  • 3
  • 10

1 Answers1

0

To be honest I wouldn't use the native C++ interface. I too got into ncurses and saw the native C++ interface but its just a dumb wrapper. No type checking, all using raw pointers (no std::shared_ptr system), its worst than ATL in windows.

Honestly I just went ahead and rebuilt some of these classes as the classes themselves are very loose wrapers. I do like how they try to get rid of all the macros and change them to inline functions, but without some kind of pointer management or even just using string_view, there really isn't a point.

Paul Bruner
  • 435
  • 4
  • 8