2 //metadoc Curses copyright Steve Dekorte, 2004
3 //metadoc Curses license BSD revised
4 //metadoc Curses category Server
5 //metadoc Curses credits Original version by Edwin Zacharias. getCh method by Scott Dunlop.
6 /*metadoc Curses description
7 Curses allows writing and reading at arbitrary positions on the terminal. You have to call init to set the terminal to curses mode and end to end curses mode. The terminal is not updated until refresh is called. It is a bad idea to use the standard io's read and write methods when the terminal is in curses mode. The Curses primitive was written by Edwin Zacharias.
9 Here's an example that prints Hello at column 5 and row 7;
12 Curses move(5, 7) print(\"Hello\")
23 #if defined(__CYGWIN__) || defined(__MINGW32__)
29 #define IO_CURSES_INPUT_BUFFER_LENGTH 200
31 #define DATA(self) ((IoCursesData *)IoObject_dataPointer(self))
33 IoTag
*IoCurses_newTag(void *state
)
35 IoTag
*tag
= IoTag_newWithName_("Curses");
36 IoTag_state_(tag
, state
);
37 IoTag_freeFunc_(tag
, (IoTagFreeFunc
*)IoCurses_free
);
38 IoTag_cloneFunc_(tag
, (IoTagCloneFunc
*)IoCurses_rawClone
);
42 IoCurses
*IoCurses_proto(void *state
)
44 IoObject
*self
= IoObject_new(state
);
45 IoObject_tag_(self
, IoCurses_newTag(state
));
47 IoObject_setDataPointer_(self
, calloc(1, sizeof(IoCursesData
)));
48 IoState_registerProtoWithFunc_(state
, self
, IoCurses_proto
);
51 IoMethodTable methodTable
[] = {
52 {"begin", IoCurses_begin
},
53 {"end", IoCurses_end
},
55 //{"nodelay", IoCurses_nodelay},
56 //{"cBreak", IoCurses_cBreak},
57 //{"noCBreak", IoCurses_noCBreak},
58 //{"echo", IoCurses_echo},
59 //{"noEcho", IoCurses_noEcho},
60 {"move", IoCurses_move
},
61 {"write", IoCurses_print
},
62 {"writeCharacter", IoCurses_writeCharacter
},
63 //{"insert", IoCurses_insert},
64 //{"delete", IoCurses_delete},
65 //{"get", IoCurses_get},
66 {"asyncReadCharacter", IoCurses_getCh
},
67 //{"input", IoCurses_input},
68 //{"erase", IoCurses_erase},
69 {"clear", IoCurses_clear
},
70 //{"clearToEndOfLine", IoCurses_clearToEndOfLine},
71 {"refresh", IoCurses_refresh
},
76 {"width", IoCurses_width
},
77 {"height", IoCurses_height
},
79 {"hasColors", IoCurses_hasColors
},
81 {"setBackgroundBlack", IoCurses_setBackgroundBlack
},
82 {"setBackgroundBlue", IoCurses_setBackgroundBlue
},
83 {"setBackgroundGreen", IoCurses_setBackgroundGreen
},
84 {"setBackgroundCyan", IoCurses_setBackgroundCyan
},
85 {"setBackgroundRed", IoCurses_setBackgroundRed
},
86 {"setBackgroundMagenta", IoCurses_setBackgroundMagenta
},
87 {"setBackgroundYellow", IoCurses_setBackgroundYellow
},
88 {"setBackgroundWhite", IoCurses_setBackgroundWhite
},
90 {"setForegroundBlack", IoCurses_setForegroundBlack
},
91 {"setForegroundBlue", IoCurses_setForegroundBlue
},
92 {"setForegroundGreen", IoCurses_setForegroundGreen
},
93 {"setForegroundCyan", IoCurses_setForegroundCyan
},
94 {"setForegroundRed", IoCurses_setForegroundRed
},
95 {"setForegroundMagenta", IoCurses_setForegroundMagenta
},
96 {"setForegroundYellow", IoCurses_setForegroundYellow
},
97 {"setForegroundWhite", IoCurses_setForegroundWhite
},
101 IoObject_addMethodTable_(self
, methodTable
);
106 IoCurses
*IoCurses_rawClone(IoCurses
*proto
)
108 IoCurses
*self
= IoObject_rawClonePrimitive(proto
);
109 IoObject_setDataPointer_(self
, cpalloc(DATA(proto
), sizeof(IoCursesData
)));
113 /* ----------------------------------------------------------- */
115 IoCurses
*IoCurses_new(void *state
)
117 IoObject
*proto
= IoState_protoWithInitFunction_(state
, IoCurses_proto
);
118 return IOCLONE(proto
);
121 void IoCurses_free(IoCurses
*self
)
123 free(IoObject_dataPointer(self
));
126 /* ----------------------------------------------------------- */
128 void IoCurses_suspendCurses(IoCurses
*self
)
135 void IoCurses_resumeCurses(IoCurses
*self
)
140 IoObject
*IoCurses_showError(IoCurses
*self
, IoMessage
*m
, const char *name
, const char *description
)
142 IoCurses_suspendCurses(self
);
143 IoCurses_showError(self
, m
, name
, description
);
144 IoCurses_resumeCurses(self
);
148 /* in curses y (the column) is listed before x (the row) */
150 IoObject
*IoCurses_begin(IoCurses
*self
, IoObject
*locals
, IoMessage
*m
)
153 Sets the terminal to curses mode.
154 This should be called before any other curses methods.
160 //DATA(self)->colorOn = 1;
162 intrflush(stdscr
, FALSE
);
163 keypad(stdscr
, TRUE
);
164 nodelay(stdscr
, TRUE
);
173 IoObject
*IoCurses_end(IoCurses
*self
, IoObject
*locals
, IoMessage
*m
)
176 Ends curses mode. This should be called before standard io's read
177 and write methods are used. Returs self.
179 printf("IoCurses_end\n");
187 //reset_shell_mode();
189 //reset_shell_mode();
194 IoObject
*IoCurses_nodelay(IoCurses
*self
, IoObject
*locals
, IoMessage
*m
)
196 /*doc Curses nodelay(aBoolean)
197 Enables or disables block during read.
198 If aNumber is zero, nodelay is set to be false, otherwise it is set to be true.
201 int b
= IoNumber_asInt(IoMessage_locals_numberArgAt_(m
, locals
, 0));
207 IoObject
*IoCurses_cBreak(IoCurses
*self
, IoObject
*locals
, IoMessage
*m
)
209 /*doc Curses cBreak(aString)
210 Disables line buffering and erase/kill character-processing.
211 cBreak should be on for most purposes. Returns self.
216 IoCurses_showError(self
, m
, "Curses.cBreak", "Failed to enable cBreak.");
221 IoObject
*IoCurses_noCBreak(IoCurses
*self
, IoObject
*locals
, IoMessage
*m
)
223 /*doc Curses noCBreak
224 Allows line buffering and erase/kill character-processing.
225 cBreak should be on for most purposes. Returns self.
228 if (nocbreak() == ERR
)
230 IoCurses_showError(self
, m
, "Curses.noCBreak", "Failed to disable cBreak.");
235 IoObject
*IoCurses_echo(IoCurses
*self
, IoObject
*locals
, IoMessage
*m
)
238 Echoes user input to terminal. Returns self.
243 IoCurses_showError(self
, m
, "Curses.echo", "Failed to enable echo.");
248 IoObject
*IoCurses_noEcho(IoCurses
*self
, IoObject
*locals
, IoMessage
*m
)
251 Does not echo user input to terminal. Returns self.
256 IoCurses_showError(self
, m
, "Curses.noecho", "Failed to disable echo.");
261 IoObject
*IoCurses_move(IoCurses
*self
, IoObject
*locals
, IoMessage
*m
)
263 /*doc Curses move(x, y)
264 Moves the cursor to column y and row x on the terminal.
265 (0, 0) is at the top-left of the terminal. Returns self.
268 int x
= IoNumber_asInt(IoMessage_locals_numberArgAt_(m
, locals
, 0));
269 int y
= IoNumber_asInt(IoMessage_locals_numberArgAt_(m
, locals
, 1));
271 if (move(y
, x
) == ERR
)
273 IoCurses_showError(self
, m
, "Curses.move", "Failed to move curser.");
279 IoObject
*IoCurses_writeCharacter(IoCurses
*self
, IoObject
*locals
, IoMessage
*m
)
281 /*doc Curses writeCharacter(aCharacter)
282 Prints the aCharacter to the current position on the terminal,
283 overwriting existing text on the terminal. Returns self.
286 char c
= IoMessage_locals_intArgAt_(m
, locals
, 0);
290 /* IoCurses_showError(self, m, "Curses.print", "Failed to print string.");*/
295 IoObject
*IoCurses_print(IoCurses
*self
, IoObject
*locals
, IoMessage
*m
)
297 /*doc Curses print(aString)
298 Prints the string to the current position on the terminal,
299 overwriting existing text on the terminal. Returns self.
302 char *string
= IoSeq_asCString(IoMessage_locals_seqArgAt_(m
, locals
, 0));
304 if (addstr(string
) == ERR
)
306 /* IoCurses_showError(self, m, "Curses.print", "Failed to print string.");*/
311 IoObject
*IoCurses_insert(IoCurses
*self
, IoObject
*locals
, IoMessage
*m
)
313 /*doc Curses insert(aString)
314 Inserts the string at the current position on the terminal,
315 pushing existing text to the right. Returns self.
318 char *string
= IoSeq_asCString(IoMessage_locals_seqArgAt_(m
, locals
, 0));
320 if (insstr(string
) == ERR
)
322 IoCurses_showError(self
, m
, "Curses.insert", "Failed to insert string.");
327 IoObject
*IoCurses_delete(IoCurses
*self
, IoObject
*locals
, IoMessage
*m
)
329 /*doc Curses delete(n)
330 Deletes n characters at the current position. Text to the right is shifted left.
331 n is optional and defaults to 1. Returns self.
336 if (IoMessage_argCount(m
) > 0)
338 n
= IoNumber_asInt(IoMessage_locals_numberArgAt_(m
, locals
, 0));
341 for (n
= n
; n
> 0; n
--)
345 IoCurses_showError(self
, m
, "Curses.delete", "Failed to delete string.");
351 IoObject
*IoCurses_get(IoCurses
*self
, IoObject
*locals
, IoMessage
*m
)
354 Returns n characters from the terminal. n is optional and defaults to 1.
357 int inputCharacterLimit
= IO_CURSES_INPUT_BUFFER_LENGTH
;
358 char string
[inputCharacterLimit
];
360 if (IoMessage_argCount(m
) > 0)
362 IoNumber
*number
= IoMessage_locals_numberArgAt_(m
, locals
, 0);
363 inputCharacterLimit
= IoNumber_asInt(number
);
366 if (getnstr(string
, inputCharacterLimit
) == ERR
)
371 return IoState_symbolWithCString_(IOSTATE
, string
);
374 IoObject
*IoCurses_getCh(IoCurses
*self
, IoObject
*locals
, IoMessage
*m
)
377 Reads a single-byte character from the terminal associated with the
378 current or specified window. Returns a Number containing the byte.
388 return IONUMBER((double)key
);
391 IoObject
*IoCurses_input(IoCurses
*self
, IoObject
*locals
, IoMessage
*m
)
393 /*doc Curses input(n)
394 Returns user input up to a return, or a maximun of n characters.
398 char string
[length
+1];
400 if (IoMessage_argCount(m
) > 0)
402 length
= IoNumber_asInt(IoMessage_locals_numberArgAt_(m
, locals
, 0));
405 if (innstr(string
, length
) == ERR
)
410 return IoState_symbolWithCString_(IOSTATE
, string
);
413 IoObject
*IoCurses_clear(IoCurses
*self
, IoObject
*locals
, IoMessage
*m
)
416 Clears the terminal. Nicer than erase. Returns self.
423 IoObject
*IoCurses_clearToEndOfLine(IoCurses
*self
, IoObject
*locals
, IoMessage
*m
)
425 /*doc Curses clearToEndOfLine
426 Clears the text from the cursor to the end of the line. Returns self.
433 IoObject
*IoCurses_refresh(IoCurses
*self
, IoObject
*locals
, IoMessage
*m
)
436 Copies the current buffer to the screen. This must be called to make
437 changes to the screen. Returns self.
440 if (refresh() == ERR
)
442 IoCurses_showError(self
, m
, "Curses.refresh", "Failed to refresh screen.");
447 IoObject
*IoCurses_width(IoCurses
*self
, IoObject
*locals
, IoMessage
*m
)
450 Returns a Number containing the width of the current screen.
454 getmaxyx(stdscr
, h
, w
);
458 IoObject
*IoCurses_height(IoCurses
*self
, IoObject
*locals
, IoMessage
*m
)
461 Returns a Number containing the height of the current screen.
465 getmaxyx(stdscr
, h
, w
);
469 IoObject
*IoCurses_hasColors(IoCurses
*self
, IoObject
*locals
, IoMessage
*m
)
471 /*doc Curses hasColors
472 Returns true if the terminal supports color, false otherwise.
475 return IOBOOL(self
, has_colors());
478 void IoCurses_colorSet(IoCurses
*self
)
480 if (!DATA(self
)->colorOn
)
483 DATA(self
)->colorOn
= 1;
484 /*pair_content(0, &(DATA(self)->fgColor), &(DATA(self)->bgColor));*/
486 init_pair(0, DATA(self
)->fgColor
, DATA(self
)->bgColor
);
487 #if ! defined(__PDCURSES__)
490 attrset(COLOR_PAIR(0));
494 /* --- Background --- */
496 IoObject
*IoCurses_setBackgroundBlack(IoCurses
*self
, IoObject
*locals
, IoMessage
*m
)
498 /*doc Curses setBackgroundBlack
499 Sets the background color to black.
502 DATA(self
)->bgColor
= COLOR_BLACK
;
503 IoCurses_colorSet(self
);
507 IoObject
*IoCurses_setBackgroundBlue(IoCurses
*self
, IoObject
*locals
, IoMessage
*m
)
509 /*doc Curses setBackgroundBlue
510 Sets the background color to blue.
513 DATA(self
)->bgColor
= COLOR_BLUE
;
514 IoCurses_colorSet(self
);
518 IoObject
*IoCurses_setBackgroundGreen(IoCurses
*self
, IoObject
*locals
, IoMessage
*m
)
520 /*doc Curses setBackgroundGreen
521 Sets the background color to green.
524 DATA(self
)->bgColor
= COLOR_GREEN
;
525 IoCurses_colorSet(self
);
529 IoObject
*IoCurses_setBackgroundCyan(IoCurses
*self
, IoObject
*locals
, IoMessage
*m
)
531 /*doc Curses setBackgroundCyan
532 Sets the background color to cyan.
535 DATA(self
)->bgColor
= COLOR_CYAN
;
536 IoCurses_colorSet(self
);
540 IoObject
*IoCurses_setBackgroundRed(IoCurses
*self
, IoObject
*locals
, IoMessage
*m
)
542 /*doc Curses setBackgroundRed
543 Sets the background color to red.
546 DATA(self
)->bgColor
= COLOR_RED
;
547 IoCurses_colorSet(self
);
551 IoObject
*IoCurses_setBackgroundMagenta(IoCurses
*self
, IoObject
*locals
, IoMessage
*m
)
553 /*doc Curses setBackgroundMagenta
554 Sets the background color to magenta.
557 DATA(self
)->bgColor
= COLOR_MAGENTA
;
558 IoCurses_colorSet(self
);
562 IoObject
*IoCurses_setBackgroundYellow(IoCurses
*self
, IoObject
*locals
, IoMessage
*m
)
564 /*doc Curses setBackgroundYellow
565 Sets the background color to yellow.
568 DATA(self
)->bgColor
= COLOR_YELLOW
;
569 IoCurses_colorSet(self
);
573 IoObject
*IoCurses_setBackgroundWhite(IoCurses
*self
, IoObject
*locals
, IoMessage
*m
)
575 /*doc Curses setBackgroundWhite
576 Sets the background color to white.
579 DATA(self
)->bgColor
= COLOR_WHITE
;
580 IoCurses_colorSet(self
);
584 /* --- Foreground --- */
586 IoObject
*IoCurses_setForegroundBlack(IoCurses
*self
, IoObject
*locals
, IoMessage
*m
)
588 /*doc Curses setForegroundBlack
589 Sets the foreground color to black.
592 DATA(self
)->fgColor
= COLOR_BLACK
;
593 IoCurses_colorSet(self
);
597 IoObject
*IoCurses_setForegroundBlue(IoCurses
*self
, IoObject
*locals
, IoMessage
*m
)
599 /*doc Curses setForegroundBlue
600 Sets the foreground color to blue.
603 DATA(self
)->fgColor
= COLOR_BLUE
;
604 IoCurses_colorSet(self
);
608 IoObject
*IoCurses_setForegroundGreen(IoCurses
*self
, IoObject
*locals
, IoMessage
*m
)
610 /*doc Curses setForegroundGreen
611 Sets the foreground color to green.
614 DATA(self
)->fgColor
= COLOR_GREEN
;
615 IoCurses_colorSet(self
);
619 IoObject
*IoCurses_setForegroundCyan(IoCurses
*self
, IoObject
*locals
, IoMessage
*m
)
621 /*doc Curses setForegroundCyan
622 Sets the foreground color to cyan.
625 DATA(self
)->fgColor
= COLOR_CYAN
;
626 IoCurses_colorSet(self
);
630 IoObject
*IoCurses_setForegroundRed(IoCurses
*self
, IoObject
*locals
, IoMessage
*m
)
632 /*doc Curses setForegroundRed
633 Sets the foreground color to red.
636 DATA(self
)->fgColor
= COLOR_RED
;
637 IoCurses_colorSet(self
);
641 IoObject
*IoCurses_setForegroundMagenta(IoCurses
*self
, IoObject
*locals
, IoMessage
*m
)
643 /*doc Curses setForegroundMagenta
644 Sets the foreground color to magenta.
647 DATA(self
)->fgColor
= COLOR_MAGENTA
;
648 IoCurses_colorSet(self
);
652 IoObject
*IoCurses_setForegroundYellow(IoCurses
*self
, IoObject
*locals
, IoMessage
*m
)
654 /*doc Curses setForegroundYellow
655 Sets the foreground color to yellow.
658 DATA(self
)->fgColor
= COLOR_YELLOW
;
659 IoCurses_colorSet(self
);
663 IoObject
*IoCurses_setForegroundWhite(IoCurses
*self
, IoObject
*locals
, IoMessage
*m
)
665 /*doc Curses setForegroundWhite
666 Sets the foreground color to white.
669 DATA(self
)->fgColor
= COLOR_WHITE
;
670 IoCurses_colorSet(self
);
674 IoObject
*IoCurses_x(IoCurses
*self
, IoObject
*locals
, IoMessage
*m
)
677 Returns the cursor x position.
687 IoObject
*IoCurses_y(IoCurses
*self
, IoObject
*locals
, IoMessage
*m
)
690 Returns the cursor y position.