Next: , Previous: , Up: Menu Library   [Contents][Index]


4.14.1 Menu basics

To create menus, you first create items, and then post the menu to the display. After that, all the processing of user responses is done in an elegant function menu-driver which is the work horse of any menu program.

The general flow of control of a menu program looks like this.

  1. Initialize curses
  2. Create items using new-item. You can specify a name and description for the items.
  3. Create the menu with new-menu by specifying the items with which it is to be attached.
  4. Post the menu with menu-post and refresh the screen.
  5. Process the user requests with a loop and do necessary updates to menu with menu-driver.
  6. Unpost the menu with menu-unpost.
  7. End curses.

Let’s see a program which prints a simple menu and updates the current selection with up, down arrows.

To use menu library functions, you have to use the module (ncurses menu).

#!/usr/local/bin/guile
-s
!#

(use-modules (srfi srfi-1)
             (ncurses curses)
             (ncurses menu))

(define stdscr (initscr))
(cbreak!)
(noecho!)
(keypad! stdscr #t)

(let* (;; Labels for the menu items
       (names '("Choice 1" "Choice 2" "Choice 3" "Choice 4" "Exit"))
       (descriptions '("Description 1" "Description 2" "Description 3"
                       "Description 4" ""))

       ;; Create menu items for each label
       (my-items (map (lambda (name desc) (new-item name desc))
                      names
                      descriptions))
       ;; Create the menu
       (my-menu (new-menu my-items)))

  ;; Draw the menu
  (move stdscr (- (lines) 2) 0)
  (addstr stdscr "Press 'q' to Quit")
  (post-menu my-menu)
  (refresh stdscr)

  ;; Process the up and down arrow keys.  Break the loop if F1 is
  ;; pressed.  Ignore other keys.
  (let loop ((c (getch stdscr)))
    (cond

     ;; Move down the menu when down arrow is pressed and then loop.
     ((eqv? c KEY_DOWN)
      (begin
        (menu-driver my-menu REQ_DOWN_ITEM)
        (loop (getch stdscr))))

     ;; Move up the menu when the up arrow is pressed and then loop.
     ((eqv? c KEY_UP)
      (begin
        (menu-driver my-menu REQ_UP_ITEM)
        (loop (getch stdscr))))

     ;; When enter is pressed, return the selection and quit.
     ((or (eqv? c KEY_ENTER)
          (eqv? c #\cr)
          (eqv? c #\nl))
      (begin
        (unpost-menu my-menu)
        (move stdscr (- (lines) 4) 0)
        (addstr stdscr
                (format #f "You selected item #~a: ~a"
                        (item-index (current-item my-menu))
                        (item-name (current-item my-menu))))
        (refresh stdscr)
        (sleep 2)))

     ;; If 'Q' or 'q'  is pressed, quit.  Otherwise, loop.
     ((not (or (eqv? c #\Q) (eqv? c #\q)))
      (loop (getch stdscr)))))

  (endwin))

This program demonstrates the basic concepts involved in creating a menu using menus library. First we create the items using new-item and then attach them to the menu with new-menu function. After posting the menu and refreshing the screen, the main processing loop starts. It reads user input and takes corresponding action. The function menu-driver is the main work horse of the menu system. The second parameter to this function tells what’s to be done with the menu. According to the parameter, menu-driver does the corresponding task. The value can be either a menu navigational request, an ASCII character, or a KEY_MOUSE special key associated with a mouse event.

The menu_driver accepts following navigational requests.

REQ_LEFT_ITEM

Move left to an item.

REQ_RIGHT_ITEM

Move right to an item.

REQ_UP_ITEM

Move up to an item.

REQ_DOWN_ITEM

Move down to an item.

REQ_SCR_ULINE

Scroll up a line.

REQ_SCR_DLINE

Scroll down a line.

REQ_SCR_DPAGE

Scroll down a page.

REQ_SCR_UPAGE

Scroll up a page.

REQ_FIRST_ITEM

Move to the first item.

REQ_LAST_ITEM

Move to the last item.

REQ_NEXT_ITEM

Move to the next item.

REQ_PREV_ITEM

Move to the previous item.

REQ_TOGGLE_ITEM

Select/deselect an item.

REQ_CLEAR_PATTERN

Clear the menu pattern buffer.

REQ_BACK_PATTERN

Delete the previous character from the pattern buffer.

REQ_NEXT_MATCH

Move to the next item matching the pattern match.

REQ_PREV_MATCH

Move to the previous item matching the pattern match.

Don’t get overwhelmed by the number of options. We will see them slowly one after another. The options of interest in this example are REQ_UP_ITEM and REQ_DOWN_ITEM. These two options when passed to menu_driver, menu driver updates the current item to one item up or down respectively.


Next: , Previous: , Up: Menu Library   [Contents][Index]