GUILE NCURSES 2.2: Let there be a window

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]

AltStyle によって変換されたページ (->オリジナル) /