|
|
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-2026 J. Marcel van der Veer [algol68g@algol68genie.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 curses_peek_char (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 (STDIN_FILENO, &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(STDIN_FILENO, &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) curses_peek_char (), 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
© 2001-2026 J.M. van der Veer
jmvdveer@algol68genie.nl