Next: , Previous: , Up: Windows Tutorial   [Contents][Index]


4.9.2 Let there be a window

What fun is it if a window is created and we can’t see it? So the fun part begins by displaying the window. The functions box and border can be used to draw a border around the window. Let’s explore these functions in more detail in this example.

This example isn’t meant as a practical example of what windows are good for. It just shows how to make, draw, erase, and destroy them.

#!/usr/bin/guile
!#

(use-modules (ncurses curses))

;; This procedure makes a new window and draws a box
;; around it
(define (create-newwin height width starty startx)
  ((lambda (win)			; Make a lambda proc that
     (box win (acs-vline) (acs-hline))	; Makes a box,
     (refresh win)			; Draws the window
     win)				; Returns the window to the caller

   (newwin height width starty startx))) ; Create a window and apply it
                                        ; to the lambda function

;; This procedure erases the box around a window and then deletes it
(define (destroy-win win)
  (let ((s (normal #\sp)))
    (border win s s s s s s s s)	; Draw a box of spaces
    (refresh win)
    (delwin win)))

;; This prodecure deletes a window than then draw a new one someplace
;; else
(define (move-win win height width starty startx)
  (destroy-win win)
  (create-newwin height width starty startx))


;; Program Begins
(define stdscr (initscr))		; Start curses
(cbreak!)				; Line buffering disabled
(keypad! stdscr #t)			; Check for function keys


(let* ((height 3)
       (width 10)
       (starty (round (/ (- (lines) height) 2)))
       (startx (round (/ (- (cols) width) 2))))

  (addstr stdscr "Press F1 to exit")
  (refresh stdscr)
  (let loop ((starty starty)
             (startx startx)
             (my-win (create-newwin height width starty startx))
             (ch (getch stdscr)))
    (cond
     ((eqv? ch KEY_LEFT)
      (loop starty
            (- startx 1)
            (move-win my-win height width starty (- startx 1))
            (getch stdscr)))

     ((eqv? ch KEY_RIGHT)
      (loop starty
            (+ startx 1)
            (move-win my-win height width starty (+ startx 1))
            (getch stdscr)))

     ((eqv? ch KEY_UP)
      (loop (- starty 1)
            startx
            (move-win my-win height width (- starty 1) startx)
            (getch stdscr)))

     ((eqv? ch KEY_DOWN)
      (loop (+ starty 1)
            startx
            (move-win my-win height width (+ starty 1) startx)
            (getch stdscr)))

     ((eqv? ch (key-f 1))
      #f)

     (else
      (loop starty startx my-win (getch stdscr)))))

  (endwin))

Don’t scream. I know it is a big example. But there are some important things to explain here. This program creates a rectangular window that can be moved with left, right, up, and down arrow keys. It repeatedly creates and destroys windows as a user presses a key. Don’t go beyond the screen limits. Checking for limits is left as an exercise for the reader. Let’s dissect it line by line.

The create-newwin function creates a window with newwin and draws a box around it with box. For the horizontal lines in the box, I chose the special drawing character acs-hline. The vertical lines are the special drawing character acs-vline. For the corners of the box, the box procedure will use a guess of the best available corners for the terminal.

Most terminals will have special box drawing characters available. The procedure acs-hline and acs-vline will return these special drawing characters. If the terminal you are using does not have box drawing characters available, acs-hline and acs-vline will return the hyphen “-” and the vertical bar “|”.

The procedure destroy-win first erases the window from the screen by painting a border of blanks and then calling delwin to deallocate memory related to it. Depending on the key the user presses, startx and starty are changed, and a new window is created.

In the destroy-win, as you can see, I used border instead of box. The reason is this: border draws a border around the window and the characters given to it as the four corners and the four lines. To put it clearly, if you called border as below:

(border win
        (normal #\|)
        (normal #\|)
        (normal #\-)
        (normal #\-)
        (normal #\+)
        (normal #\+)
        (normal #\+)
        (normal #\+))

it produces something like this

   +-----+
   |     |
   |     |
   |     |
   +-----+

It wouldn’t have been sufficient to use (box win (normal #\sp) (normal #\sp)) to erase the box, because the box procedure still would have drawn the four corners of the box.


Next: , Previous: , Up: Windows Tutorial   [Contents][Index]