1 /** \file uimon-fallback.c
2 * \brief Fallback implementation for the ML-Monitor for when the VTE library
3 * is not available
4 *
5 * \author Fabrizio Gennari <fabrizio.ge@tiscali.it>
6 */
7
8 /*
9 * This file is part of VICE, the Versatile Commodore Emulator.
10 * See README for copyright notice.
11 *
12 * This program is free software; you can redistribute it and/or modify
13 * it under the terms of the GNU General Public License as published by
14 * the Free Software Foundation; either version 2 of the License, or
15 * (at your option) any later version.
16 *
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, write to the Free Software
24 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
25 * 02111-1307 USA.
26 *
27 */
28
29 /* FIXME: this code can probably be shared between GTK3/SDL */
30
31 #include "vice.h"
32
33 #include "debug_gtk3.h"
34 #include <stdlib.h>
35 #include <string.h>
36 #include <dirent.h>
37 #include <ctype.h>
38 #include <unistd.h>
39
40 #ifdef HAVE_SYS_IOCTL_H
41 #include <sys/ioctl.h>
42 #endif
43
44 #if (defined(sun) || defined(__sun)) && (defined(__SVR4) || defined(__svr4__))
45 #include <sys/stat.h>
46 #endif
47
48 #ifdef WIN32_COMPILE
49 #include <windows.h>
50 #include <winternl.h>
51 #endif
52
53 #include "console.h"
54 #include "lib.h"
55 #include "log.h"
56 #include "ui.h"
57 #include "uimon.h"
58 #include "uimon-fallback.h"
59
60
61 static console_t *console_log_local = NULL;
62
63 #if defined(HAVE_READLINE) && defined(HAVE_READLINE_READLINE_H)
64 #include <readline/readline.h>
65 #include <readline/history.h>
66 #else
67 static FILE *mon_input, *mon_output;
68 #endif
69
70 /** \brief NOP
71 *
72 * \return 0
73 */
consolefb_close_all(void)74 int consolefb_close_all(void)
75 {
76 /* This is a no-op on GNOME, should be fine here too */
77 return 0;
78 }
79
80
81 /** \brief NOP
82 *
83 * \return 0
84 */
consolefb_init(void)85 int consolefb_init(void)
86 {
87 NOT_IMPLEMENTED_WARN_ONLY();
88 return 0;
89 }
90
91 #if !defined(HAVE_READLINE) || !defined(HAVE_READLINE_READLINE_H)
consolefb_out(console_t * log,const char * format,...)92 int consolefb_out(console_t *log, const char *format, ...)
93 {
94 va_list ap;
95
96 va_start(ap, format);
97 vfprintf(mon_output, format, ap);
98 va_end(ap);
99
100 return 0;
101 }
102 #endif
103
104 #ifdef WIN32_COMPILE
vice_ismsystty(int fd)105 static int vice_ismsystty(int fd)
106 {
107 intptr_t h_stdin = _get_osfhandle(fd);
108 char ntfn_bytes[sizeof(OBJECT_NAME_INFORMATION) + 256 * sizeof(WCHAR)];
109 OBJECT_NAME_INFORMATION *ntfn = (OBJECT_NAME_INFORMATION*) ntfn_bytes;
110 NTSTATUS status;
111 ULONG ntfn_size = sizeof(ntfn_bytes);
112 USHORT i, l;
113 wchar_t c, *s0;
114
115 memset(ntfn, 0, ntfn_size);
116 status = NtQueryObject((HANDLE)h_stdin, ObjectNameInformation, ntfn, ntfn_size, &ntfn_size);
117
118 if (!NT_SUCCESS(status)) {
119 return 0;
120 }
121
122 l = ntfn->Name.Length;
123 s0 = ntfn->Name.Buffer;
124 /* Check for "\Device\NamedPipe" */
125 {
126 USHORT l1 = l;
127 wchar_t *s1 = s0;
128 wchar_t expect[] = L"\\Device\\NamedPipe\\";
129
130 if (s0[0] == '\\' && s0[1] == '\\' && s0[2] == '?' && s0[3] == '\\') {
131 l1 -= 4;
132 s1 += 4;
133 }
134 for (i = 0; i < l1; i++) {
135 wchar_t e = expect[i];
136 c = s1[i];
137 if (!e) {
138 break;
139 }
140 if (c != e) {
141 return 0;
142 }
143 }
144 }
145 /* Look for "-pty%d-" */
146 for (i = 0; i < l; i++) {
147 c = s0[i];
148 if (c == '-') {
149 wchar_t *s = s0 + i + 1;
150 if (s[0] == 'p' && s[1] == 't' && s[2] == 'y' && (c = s[3]) && (c >= '0') && (c <= '9'))
151 {
152 s += 4;
153 while ((c = *s) && (c >= '0') && (c <= '9')) {
154 s++;
155 }
156 if (c == '-' || c == 0) {
157 return 1;
158 }
159 }
160 }
161 }
162
163 return 0;
164 }
165
vice_isatty(int fd)166 static int vice_isatty(int fd)
167 {
168 if (!isatty(fileno(stdin))) {
169 return vice_ismsystty(fileno(stdin));
170 }
171 return 1;
172 }
173 #else
174 #define vice_isatty isatty
175 #endif
176
uimonfb_window_open(void)177 console_t *uimonfb_window_open(void)
178 {
179 #ifdef HAVE_SYS_IOCTL_H
180 struct winsize w;
181 #endif
182
183 if (!vice_isatty(fileno(stdin))) {
184 log_error(LOG_DEFAULT, "console_open: stdin is not a tty.");
185 console_log_local = NULL;
186 return NULL;
187 }
188 if (!vice_isatty(fileno(stdout))) {
189 log_error(LOG_DEFAULT, "console_open: stdout is not a tty.");
190 console_log_local = NULL;
191 return NULL;
192 }
193 console_log_local = lib_malloc(sizeof(console_t));
194 /* change window title for console identification purposes */
195 if (getenv("WINDOWID") == NULL) {
196 printf("\033]2;VICE monitor console (%d)\007", (int)getpid());
197 }
198
199 #if !defined(HAVE_READLINE) || !defined(HAVE_READLINE_READLINE_H)
200 mon_input = stdin;
201 mon_output = stdout;
202 #endif
203
204 #ifdef HAVE_SYS_IOCTL_H
205 if (ioctl(fileno(stdin), TIOCGWINSZ, &w)) {
206 console_log_local->console_xres = 80;
207 console_log_local->console_yres = 25;
208 } else {
209 console_log_local->console_xres = w.ws_col >= 40 ? w.ws_col : 40;
210 console_log_local->console_yres = w.ws_row >= 22 ? w.ws_row : 22;
211 }
212 #else
213 console_log_local->console_xres = 80;
214 console_log_local->console_yres = 25;
215 #endif
216 console_log_local->console_can_stay_open = 1;
217 console_log_local->console_cannot_output = 0;
218
219 /* partially implemented */
220 INCOMPLETE_IMPLEMENTATION();
221 #ifdef HAVE_MOUSE
222 /* ui_restore_mouse(); */
223 #endif
224 /* ui_focus_monitor(); */
225 return console_log_local;
226 }
227
uimonfb_window_close(void)228 void uimonfb_window_close(void)
229 {
230 lib_free(console_log_local);
231 console_log_local = NULL;
232
233 uimon_window_suspend();
234 }
235
uimonfb_window_suspend(void)236 void uimonfb_window_suspend( void )
237 {
238 /* ui_restore_focus(); */
239 #ifdef HAVE_MOUSE
240 /* ui_check_mouse_cursor(); */
241 #endif
242 NOT_IMPLEMENTED_WARN_ONLY();
243 }
244
uimonfb_window_resume(void)245 console_t *uimonfb_window_resume(void)
246 {
247 if (console_log_local) {
248 /* partially implemented */
249 INCOMPLETE_IMPLEMENTATION();
250 #ifdef HAVE_MOUSE
251 /* ui_restore_mouse(); */
252 #endif
253 /* ui_focus_monitor(); */
254 return console_log_local;
255 }
256 log_error(LOG_DEFAULT, "uimon_window_resume: log was not opened.");
257 return uimon_window_open();
258 }
259
uimonfb_out(const char * buffer)260 int uimonfb_out(const char *buffer)
261 {
262 fprintf(stdout, "%s", buffer);
263 return 0;
264 }
265
266 #if !defined(HAVE_READLINE) || !defined(HAVE_READLINE_READLINE_H)
readline(const char * prompt)267 char *readline(const char *prompt)
268 {
269 char *p = malloc(1024);
270
271 consolefb_out(NULL, "%s", prompt);
272
273 fflush(mon_output);
274 if (fgets(p, 1024, mon_input) == NULL) {
275 /* FIXME: handle error */
276 }
277
278 /* Remove trailing newlines. */
279 {
280 int len;
281
282 for (len = strlen(p); len > 0 && (p[len - 1] == '\r' || p[len - 1] == '\n'); len--) {
283 p[len - 1] = '\0';
284 }
285 }
286
287 return p;
288 }
289 #endif
290
uimonfb_get_in(char ** ppchCommandLine,const char * prompt)291 char *uimonfb_get_in(char **ppchCommandLine, const char *prompt)
292 {
293 char *p, *ret_sting;
294
295 p = readline(prompt);
296 #if defined(HAVE_READLINE) && defined(HAVE_READLINE_READLINE_H)
297 if (p && *p) {
298 add_history(p);
299 }
300 #endif
301 ret_sting = lib_stralloc(p);
302 free(p);
303
304 return ret_sting;
305 }
306
uimonfb_notify_change(void)307 void uimonfb_notify_change( void )
308 {
309 }
310
uimonfb_set_interface(struct monitor_interface_s ** monitor_interface_init,int count)311 void uimonfb_set_interface(struct monitor_interface_s **monitor_interface_init, int count)
312 {
313 }
314