A Curses Gotcha

10 PM December 11, 2003

For the last month or so, I’ve been ‘doing’ C++. The project is based on NCurses, an open source implementation of the curses character terminal library.

After working with Java and Python for so long, NCurses seems, well… horrible. If you make a programming mistake, the typical NCurses reaction is to print either “form library error”, or maybe even “menu library error”, crash your application, and leave the terminal in a strange mode, requiring you to type in a secret (by dint of character echo being turned off) incantation and press CTRL-J before proceeding.

Anyway, just before lunch yesterday, my application stopped updating the position of the terminal’s blinking cursor. You would think that a product named Curses could keep track of a cursor wouldn’t you?

Closer inspection revealed that all the keys worked properly, TAB cycled through fields as expected, and the Curses getyx() call reported that the cursor was in the correct place. Only the cursor wasn’t in the correct place at all; it was stuck half way down the screen, and it was blinking at me.

I spent the next 14 working hours debugging.

It came down to a function named getch(), which gets characters. I thought I was calling the standard ‘C’ library getch(), but it turns out I was calling a C++ member function named getch(). During a refactoring, I moved the getch() call from one class to another, and all of a sudden it was now referring to a global function named getch(). This global function worked fine, except for entirely screwing up cursor positioning.

In fact, the NCurses header files declare fifteen different getch()s. Some are global functions, some are member functions, and some are macros. I still can’t pin down exactly which one I was calling, but it was a one line fix.

And the moral is, “When you need to get a char, use the Curses getch(), without the cursed gotcha.”

By alang | # | Comments (1)
(Posted to Software Development)

Comments

At 11:18, 15 Dec 2003 Andrew Reid wrote:

Whoah - flashback to my final year uni project where I learnt the pain of curses while writing a text editor and had the dubious pleasure of confirming that the VT100 support worked by running the program on a real VT100!

The moral of the story is not to hide names in an outer namespace by reusing them in an inner one (incidentally the compiler I've been using lately (Sun C++) has a warning for this) - another flashback, this time to my first job out of uni where I encountered the following evilness:

#define fopen() _myfopen()

(#)

Add Comment




(Not displayed)






(Leave blank line between paragraphs. URLs converted to links. HTML stripped. Indented source code will be formatted with <pre> tags.)




© 2003-2006 Alan Green