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
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.
create-newwin function creates a window with
and draws a box around it with
box. For the horizontal lines in
the box, I chose the special drawing character
vertical lines are the special drawing character
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.
acs-vline will return these
special drawing characters. If the terminal you are using does not
have box drawing characters available,
acs-vline will return the hyphen “-” and the vertical bar
destroy-win first erases the window from the
screen by painting a border of blanks and then calling
to deallocate memory related to it. Depending on the key the user
starty are changed, and a new window
destroy-win, as you can see, I used
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
(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
still would have drawn the four corners of the box.