rts-curses.c
1 //! @file rts-curses.c
2 //! @author J. Marcel van der Veer
3
4 //! @section Copyright
5 //!
6 //! This file is part of Algol68G - an Algol 68 compiler-interpreter.
7 //! Copyright 2001-2024 J. Marcel van der Veer [algol68g@xs4all.nl].
8
9 //! @section License
10 //!
11 //! This program is free software; you can redistribute it and/or modify it
12 //! under the terms of the GNU General Public License as published by the
13 //! Free Software Foundation; either version 3 of the License, or
14 //! (at your option) any later version.
15 //!
16 //! This program is distributed in the hope that it will be useful, but
17 //! WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
18 //! or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
19 //! more details. You should have received a copy of the GNU General Public
20 //! License along with this program. If not, see [http://www.gnu.org/licenses/].
21
22 //! @section Synopsis
23 //!
24 //! Curses interface.
25
26 #include "a68g.h"
27 #include "a68g-genie.h"
28 #include "a68g-prelude.h"
29
30 // Some routines that interface Algol68G and the curses library.
31
32 #if defined (HAVE_CURSES)
33
34 #define CHECK_CURSES_RETVAL(f) {\
35 if (!(f)) {\
36 diagnostic (A68_RUNTIME_ERROR, p, ERROR_CURSES);\
37 exit_genie (p, A68_RUNTIME_ERROR);\
38 }}
39
40 //! @brief Clean_curses.
41
42 void clean_curses (void)
43 {
44 if (A68 (curses_mode) == A68_TRUE) {
45 (void) wattrset (stdscr, A_NORMAL);
46 (void) endwin ();
47 A68 (curses_mode) = A68_FALSE;
48 }
49 }
50
51 //! @brief Init_curses.
52
53 void init_curses (void)
54 {
55 (void) initscr ();
56 (void) cbreak (); // raw () would cut off ctrl-c
57 (void) noecho ();
58 (void) nonl ();
59 (void) curs_set (0);
60 if (has_colors ()) {
61 (void) start_color ();
62 }
63 }
64
65 //! @brief Watch stdin for input, do not wait very long.
66
67 int rgetchar (void)
68 {
69 #if defined (BUILD_WIN32)
70 if (kbhit ()) {
71 return getch ();
72 } else {
73 return NULL_CHAR;
74 }
75 #else
76 struct timeval tv;
77 TV_SEC (&tv) = 0;
78 TV_USEC (&tv) = 100;
79 fd_set fd;
80 FD_ZERO (&fd);
81 FD_SET (0, &fd);
82 if (select (1, &fd, NULL, NULL, &tv)) {
83 // FD_ISSET(0, &fd) will be true.
84 return getch ();
85 } else {
86 return NULL_CHAR;
87 }
88 #endif
89 }
90
91 //! @brief PROC curses start = VOID
92
93 void genie_curses_start (NODE_T * p)
94 {
95 (void) p;
96 init_curses ();
97 A68 (curses_mode) = A68_TRUE;
98 }
99
100 //! @brief PROC curses end = VOID
101
102 void genie_curses_end (NODE_T * p)
103 {
104 (void) p;
105 clean_curses ();
106 }
107
108 //! @brief PROC curses clear = VOID
109
110 void genie_curses_clear (NODE_T * p)
111 {
112 if (A68 (curses_mode) == A68_FALSE) {
113 genie_curses_start (p);
114 }
115 CHECK_CURSES_RETVAL (clear () != ERR);
116 }
117
118 //! @brief PROC curses refresh = VOID
119
120 void genie_curses_refresh (NODE_T * p)
121 {
122 if (A68 (curses_mode) == A68_FALSE) {
123 genie_curses_start (p);
124 }
125 CHECK_CURSES_RETVAL (refresh () != ERR);
126 }
127
128 //! @brief PROC curses lines = INT
129
130 void genie_curses_lines (NODE_T * p)
131 {
132 if (A68 (curses_mode) == A68_FALSE) {
133 genie_curses_start (p);
134 }
135 PUSH_VALUE (p, LINES, A68_INT);
136 }
137
138 //! @brief PROC curses columns = INT
139
140 void genie_curses_columns (NODE_T * p)
141 {
142 if (A68 (curses_mode) == A68_FALSE) {
143 genie_curses_start (p);
144 }
145 PUSH_VALUE (p, COLS, A68_INT);
146 }
147
148 //! @brief PROC curses getchar = CHAR
149
150 void genie_curses_getchar (NODE_T * p)
151 {
152 if (A68 (curses_mode) == A68_FALSE) {
153 genie_curses_start (p);
154 }
155 PUSH_VALUE (p, (char) rgetchar (), A68_CHAR);
156 }
157
158 //! @brief PROC curses colour = VOID
159
160 #define GENIE_COLOUR(f, n, fg, bg)\
161 void f (NODE_T *p) {\
162 (void) p;\
163 if ((n) < COLOR_PAIRS) {\
164 (void) init_pair (n, (fg), (bg));\
165 wattrset (stdscr, COLOR_PAIR ((n)) | A_BOLD);\
166 }\
167 }\
168 void f##_inverse (NODE_T *p) {\
169 (void) p;\
170 if ((n + 8) < COLOR_PAIRS) {\
171 (void) init_pair ((n) + 8, (bg), (fg));\
172 wattrset (stdscr, COLOR_PAIR (((n) + 8)));\
173 }\
174 }
175
176 GENIE_COLOUR (genie_curses_blue, 1, COLOR_BLUE, COLOR_BLACK);
177 GENIE_COLOUR (genie_curses_cyan, 2, COLOR_CYAN, COLOR_BLACK);
178 GENIE_COLOUR (genie_curses_green, 3, COLOR_GREEN, COLOR_BLACK);
179 GENIE_COLOUR (genie_curses_magenta, 4, COLOR_MAGENTA, COLOR_BLACK);
180 GENIE_COLOUR (genie_curses_red, 5, COLOR_RED, COLOR_BLACK);
181 GENIE_COLOUR (genie_curses_white, 6, COLOR_WHITE, COLOR_BLACK);
182 GENIE_COLOUR (genie_curses_yellow, 7, COLOR_YELLOW, COLOR_BLACK);
183
184 //! @brief PROC curses delchar = (CHAR) BOOL
185
186 void genie_curses_del_char (NODE_T * p)
187 {
188 A68_CHAR ch;
189 POP_OBJECT (p, &ch, A68_CHAR);
190 int v = (int) VALUE (&ch);
191 PUSH_VALUE (p, (BOOL_T) (v == 8 || v == 127 || v == KEY_BACKSPACE), A68_BOOL);
192 }
193
194 //! @brief PROC curses putchar = (CHAR) VOID
195
196 void genie_curses_putchar (NODE_T * p)
197 {
198 if (A68 (curses_mode) == A68_FALSE) {
199 genie_curses_start (p);
200 }
201 A68_CHAR ch;
202 POP_OBJECT (p, &ch, A68_CHAR);
203 (void) (addch ((chtype) (VALUE (&ch))));
204 }
205
206 //! @brief PROC curses move = (INT, INT) VOID
207
208 void genie_curses_move (NODE_T * p)
209 {
210 if (A68 (curses_mode) == A68_FALSE) {
211 genie_curses_start (p);
212 }
213 A68_INT i, j;
214 POP_OBJECT (p, &j, A68_INT);
215 POP_OBJECT (p, &i, A68_INT);
216 if (VALUE (&i) < 0 || VALUE (&i) >= LINES) {
217 diagnostic (A68_RUNTIME_ERROR, p, ERROR_CURSES_OFF_SCREEN);
218 exit_genie (p, A68_RUNTIME_ERROR);
219 }
220 if (VALUE (&j) < 0 || VALUE (&j) >= COLS) {
221 diagnostic (A68_RUNTIME_ERROR, p, ERROR_CURSES_OFF_SCREEN);
222 exit_genie (p, A68_RUNTIME_ERROR);
223 }
224 CHECK_CURSES_RETVAL (move (VALUE (&i), VALUE (&j)) != ERR);
225 }
226
227 #endif
© 2002-2024 J.M. van der Veer (jmvdveer@xs4all.nl)
|