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-2025 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 (A68G_RUNTIME_ERROR, p, ERROR_CURSES);\
37 exit_genie (p, A68G_RUNTIME_ERROR);\
38 }}
39
40 //! @brief Clean_curses.
41
42 void clean_curses (void)
43 {
44 if (A68G (curses_mode) == A68G_TRUE) {
45 (void) wattrset (stdscr, A_NORMAL);
46 (void) endwin ();
47 A68G (curses_mode) = A68G_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_WINDOWS)
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) = 1000;
79 fd_set fd;
80 FD_ZERO (&fd);
81 FD_SET (0, &fd);
82 int rc = select (1, &fd, NULL, NULL, &tv);
83 if (rc == -1 || rc == 0) {
84 return NULL_CHAR;
85 } else {
86 // FD_ISSET(0, &fd) will be true.
87 return getch ();
88 }
89 #endif
90 }
91
92 //! @brief PROC curses start = VOID
93
94 void genie_curses_start (NODE_T * p)
95 {
96 (void) p;
97 init_curses ();
98 A68G (curses_mode) = A68G_TRUE;
99 }
100
101 //! @brief PROC curses end = VOID
102
103 void genie_curses_end (NODE_T * p)
104 {
105 (void) p;
106 clean_curses ();
107 }
108
109 //! @brief PROC curses clear = VOID
110
111 void genie_curses_clear (NODE_T * p)
112 {
113 if (A68G (curses_mode) == A68G_FALSE) {
114 genie_curses_start (p);
115 }
116 CHECK_CURSES_RETVAL (clear () != ERR);
117 }
118
119 //! @brief PROC curses refresh = VOID
120
121 void genie_curses_refresh (NODE_T * p)
122 {
123 if (A68G (curses_mode) == A68G_FALSE) {
124 genie_curses_start (p);
125 }
126 CHECK_CURSES_RETVAL (refresh () != ERR);
127 }
128
129 //! @brief PROC curses lines = INT
130
131 void genie_curses_lines (NODE_T * p)
132 {
133 if (A68G (curses_mode) == A68G_FALSE) {
134 genie_curses_start (p);
135 }
136 PUSH_VALUE (p, LINES, A68G_INT);
137 }
138
139 //! @brief PROC curses columns = INT
140
141 void genie_curses_columns (NODE_T * p)
142 {
143 if (A68G (curses_mode) == A68G_FALSE) {
144 genie_curses_start (p);
145 }
146 PUSH_VALUE (p, COLS, A68G_INT);
147 }
148
149 //! @brief PROC curses getchar = CHAR
150
151 void genie_curses_getchar (NODE_T * p)
152 {
153 if (A68G (curses_mode) == A68G_FALSE) {
154 genie_curses_start (p);
155 }
156 PUSH_VALUE (p, (char) rgetchar (), A68G_CHAR);
157 }
158
159 //! @brief PROC curses colour = VOID
160
161 #define GENIE_COLOUR(f, n, fg, bg)\
162 void f (NODE_T *p) {\
163 (void) p;\
164 if ((n) < COLOR_PAIRS) {\
165 (void) init_pair (n, (fg), (bg));\
166 wattrset (stdscr, COLOR_PAIR ((n)) | A_BOLD);\
167 }\
168 }\
169 void f##_inverse (NODE_T *p) {\
170 (void) p;\
171 if ((n + 8) < COLOR_PAIRS) {\
172 (void) init_pair ((n) + 8, (bg), (fg));\
173 wattrset (stdscr, COLOR_PAIR (((n) + 8)));\
174 }\
175 }
176
177 GENIE_COLOUR (genie_curses_blue, 1, COLOR_BLUE, COLOR_BLACK);
178 GENIE_COLOUR (genie_curses_cyan, 2, COLOR_CYAN, COLOR_BLACK);
179 GENIE_COLOUR (genie_curses_green, 3, COLOR_GREEN, COLOR_BLACK);
180 GENIE_COLOUR (genie_curses_magenta, 4, COLOR_MAGENTA, COLOR_BLACK);
181 GENIE_COLOUR (genie_curses_red, 5, COLOR_RED, COLOR_BLACK);
182 GENIE_COLOUR (genie_curses_white, 6, COLOR_WHITE, COLOR_BLACK);
183 GENIE_COLOUR (genie_curses_yellow, 7, COLOR_YELLOW, COLOR_BLACK);
184
185 //! @brief PROC curses delchar = (CHAR) BOOL
186
187 void genie_curses_del_char (NODE_T * p)
188 {
189 A68G_CHAR ch;
190 POP_OBJECT (p, &ch, A68G_CHAR);
191 int v = (int) VALUE (&ch);
192 PUSH_VALUE (p, (BOOL_T) (v == 8 || v == 127 || v == KEY_BACKSPACE), A68G_BOOL);
193 }
194
195 //! @brief PROC curses putchar = (CHAR) VOID
196
197 void genie_curses_putchar (NODE_T * p)
198 {
199 if (A68G (curses_mode) == A68G_FALSE) {
200 genie_curses_start (p);
201 }
202 A68G_CHAR ch;
203 POP_OBJECT (p, &ch, A68G_CHAR);
204 (void) (addch ((chtype) (VALUE (&ch))));
205 }
206
207 //! @brief PROC curses move = (INT, INT) VOID
208
209 void genie_curses_move (NODE_T * p)
210 {
211 if (A68G (curses_mode) == A68G_FALSE) {
212 genie_curses_start (p);
213 }
214 A68G_INT i, j;
215 POP_OBJECT (p, &j, A68G_INT);
216 POP_OBJECT (p, &i, A68G_INT);
217 if (VALUE (&i) < 0 || VALUE (&i) >= LINES) {
218 diagnostic (A68G_RUNTIME_ERROR, p, ERROR_CURSES_OFF_SCREEN);
219 exit_genie (p, A68G_RUNTIME_ERROR);
220 }
221 if (VALUE (&j) < 0 || VALUE (&j) >= COLS) {
222 diagnostic (A68G_RUNTIME_ERROR, p, ERROR_CURSES_OFF_SCREEN);
223 exit_genie (p, A68G_RUNTIME_ERROR);
224 }
225 CHECK_CURSES_RETVAL (move (VALUE (&i), VALUE (&j)) != ERR);
226 }
227
228 #endif
© 2002-2025 J.M. van der Veer (jmvdveer@xs4all.nl)
|