4
* Copyright (c) 1999, 2002 Michael J. Roberts. All Rights Reserved.
6
* Please see the accompanying license file, LICENSE.TXT, for information
7
* on using and copying this software.
11
os_stdio.cpp - OS implementation for standard I/O
13
This is a simple stdio-based implementation of the OS display functions.
14
This is a portable implementation (at least, it's portable to any
15
platform where stdio can be used).
17
The main purpose of this implementation is to make it easy to build
18
command-line versions of tools that incorporate osifc-layer functions
19
without having to drag in the full-blown OS-specific implementation.
20
For example, test tools might find this useful.
24
09/04/99 MJRoberts - Creation
35
* status-line display mode
37
static int S_status_mode = 0;
42
void os_nonstop_mode(int flag)
56
void os_update_display()
61
* get highlighting character - indicate that highlighting is to be
64
/* set text attributes */
65
void os_set_text_attr(int /*attr*/)
67
/* not supported - ignore it */
71
void os_set_text_color(os_color_t /*fg*/, os_color_t /*bg*/)
73
/* not supported - ignore it */
76
/* set the screen color */
77
void os_set_screen_color(os_color_t /*color*/)
79
/* not supported - ignore it */
85
void os_printz(const char *str)
87
/* suppress output if we're not in plain text mode */
88
if (S_status_mode == 0)
95
int os_get_event(unsigned long timeout, int use_timeout,
96
os_event_info_t *info)
98
/* we can't handle timeouts */
100
return OS_EVT_NOTIMEOUT;
103
info->key[0] = os_getc_raw();
104
if (info->key[0] == 0)
105
info->key[1] = os_getc_raw();
107
/* return the keyboard event */
117
* print a ^L to clear the screen, if such sequences are interpreted
118
* by the display driver or terminal
124
* read from the keyboard
126
unsigned char *os_gets(unsigned char *buf, size_t buflen)
130
/* read from stdin; return failure if fgets does */
131
if (fgets((char *)buf, buflen, stdin) == 0)
134
/* remove the trailing newline in the result, if there is one */
135
if ((len = strlen((char *)buf)) != 0 && buf[len-1] == '\n')
138
/* return the buffer pointer */
143
* read from keyboard with timeout
145
int os_gets_timeout(unsigned char *buf, size_t bufl,
146
unsigned long timeout_in_milliseconds, int use_timeout)
149
* if we've been asked to read with a timeout, we can't comply, so
150
* just return the no-timeout-available error code; if we're reading
151
* without a timeout, just use the ordinary input reader
155
/* timeout requested, no can do - return the no-timeout error code */
156
return OS_EVT_NOTIMEOUT;
161
* no timeout requested, so use the ordinary reader, and translate
162
* its returns codes to the appropriate equivalents for this
163
* routine (null from os_gets -> error -> OS_EVT_EOF as our return
164
* code; non-null -> success -> OS_EVT_LINE)
166
return (os_gets(buf, bufl) == 0 ? OS_EVT_EOF : OS_EVT_LINE);
171
* Cancel interrupted input. We don't handle input with timeout in the
172
* first place, so interrupted input is impossible, so we need do nothing
175
void os_gets_cancel(int reset)
177
/* there's nothing for us to do */
181
* prompt for information through a dialog
183
int os_input_dialog(int /*icon_id*/,
184
const char *prompt, int standard_button_set,
185
const char **buttons, int button_count,
186
int /*default_index*/, int /*cancel_index*/)
188
/* keep going until we get a valid response */
200
const char *buttons[3];
205
{ { "&OK", "&Cancel" }, 2 },
206
{ { "&Yes", "&No" }, 2 },
207
{ { "&Yes", "&No", "&Cancel" }, 3 }
211
* if we have a standard button set selected, get our button
214
switch(standard_button_set)
217
/* use the explicit buttons provided */
224
/* use the selected standard button set */
225
buttons = (const char **)std_btns[i].buttons;
226
button_count = std_btns[i].button_count;
229
case OS_INDLG_OKCANCEL:
237
case OS_INDLG_YESNOCANCEL:
243
* we don't recognize other standard button sets - return an
250
* if there are no buttons defined, they'll never be able to
251
* respond, so we'd just loop forever - rather than let that
252
* happen, return failure
254
if (button_count == 0)
257
/* display a newline and the prompt string */
261
/* display the response */
262
for (i = 0 ; i < button_count ; ++i)
265
* display a slash to separate responses, if this isn't the
271
/* get the current button */
275
* Look for a "&" in the response string. If we find it,
276
* remove the "&" and enclose the shortcut key in parens.
278
for (p = cur ; *p != '&' && *p != '\0' ; ++p) ;
280
/* if we found the "&", put the next character in parens */
286
/* limit the prefix length to avoid overflowing the buffer */
288
if (pre_len > sizeof(buf) - 5)
289
pre_len = sizeof(buf) - 5;
291
/* limit the postfix length to avoid buffer overflow, too */
292
post_len = strlen(p + 2);
293
if (post_len > sizeof(buf) - 5 - pre_len)
294
post_len = sizeof(buf) - 5 - pre_len;
296
/* reformat the response string */
297
sprintf(buf, "%.*s(%c)%.*s",
298
(int)pre_len, cur, *(p + 1), (int)post_len, p + 2);
305
/* no '&' - just display the response string as-is */
310
/* read the response */
312
os_gets((unsigned char *)buf, sizeof(buf));
314
/* skip any leading spaces in the reply */
315
for (resp = buf ; isspace(*resp) ; ++resp) ;
317
/* if it's one character, check it against the shortcut keys */
318
if (strlen(resp) == 1)
320
/* scan the responses */
321
for (i = 0 ; i < button_count ; ++i)
323
/* look for a '&' in this button */
324
for (p = buttons[i] ; *p != '&' && *p != '\0' ; ++p) ;
326
/* if we found the '&', check the shortcut */
327
if (*p == '&' && toupper(*(p+1)) == toupper(*resp))
330
* this is the one - return the current index
331
* (bumping it by one to get a 1-based value)
339
* Either it's not a one-character reply, or it didn't match a
340
* short-cut - check it against the leading substrings of the
341
* responses. If it matches exactly one of the responses in its
342
* leading substring, use that response.
344
for (i = 0, match_cnt = 0 ; i < button_count ; ++i)
350
* compare this response to the user's response; skip any
351
* '&' in the button label
353
for (p1 = resp, p2 = buttons[i] ; *p1 != '\0' && *p2 != '\0' ;
356
/* if this is a '&' in the button label, skip it */
360
/* if these characters don't match, it's no match */
361
if (toupper(*p1) != toupper(*p2))
366
* if we reached the end of the user's response, we have a
367
* match in the leading substring - count it and remember
368
* this as the last one, but keep looking, since we need to
369
* make sure we don't have any other matches
379
* if we found exactly one match, return it (adjusting to a
380
* 1-based index); if we found more or less than one match, it's
381
* not a valid response, so start over with a new prompt
384
return last_found + 1;
391
int os_askfile(const char *prompt, char *reply, int replen,
392
int /*dialog_type*/, os_filetype_t /*file_type*/)
394
/* show the prompt */
398
/* ask for the filename */
399
os_gets((unsigned char *)reply, replen);
402
* if they entered an empty line, return "cancel"; otherwise, return
405
return (reply[0] == '\0' ? OS_AFE_CANCEL : OS_AFE_SUCCESS);
409
* get system information
411
int os_get_sysinfo(int code, void *param, long *result)
420
case SYSINFO_WAV_MIDI_OVL:
421
case SYSINFO_WAV_OVL:
422
case SYSINFO_PREF_IMAGES:
423
case SYSINFO_PREF_SOUNDS:
424
case SYSINFO_PREF_MUSIC:
425
case SYSINFO_PREF_LINKS:
430
case SYSINFO_LINKS_HTTP:
431
case SYSINFO_LINKS_FTP:
432
case SYSINFO_LINKS_NEWS:
433
case SYSINFO_LINKS_MAILTO:
434
case SYSINFO_LINKS_TELNET:
435
case SYSINFO_PNG_TRANS:
436
case SYSINFO_PNG_ALPHA:
438
case SYSINFO_TEXT_HILITE:
439
case SYSINFO_TEXT_COLORS:
440
case SYSINFO_BANNERS:
442
* we don't support any of these features - set the result to 0
447
/* return true to indicate that we recognized the code */
450
case SYSINFO_INTERP_CLASS:
451
/* indicate that we're a text-only interpreter */
452
*result = SYSINFO_ICLASS_TEXT;
456
/* we don't recognize other codes */
464
void os_status(int mode)
466
/* remember the new mode */
467
S_status_mode = mode;
471
* display a string in the right half of the status line
473
void os_strsc(const char *)
475
/* ignore it - we don't have a status line in this UI */
481
* this implementation is always in plain mode, so there's nothing
491
/* ------------------------------------------------------------------------ */
493
* none of the banner functions are useful in plain stdio mode
495
void *os_banner_create(void *parent, int where, void *other, int wintype,
496
int align, int siz, int siz_units, unsigned long style)
501
void os_banner_delete(void *banner_handle)
505
void os_banner_orphan(void *banner_handle)
509
void os_banner_disp(void *banner_handle, const char *txt, size_t len)
513
void os_banner_flush(void *banner_handle)
517
void os_banner_set_size(void *banner_handle, int siz, int siz_units,
522
void os_banner_size_to_contents(void *banner_handle)
526
void os_banner_start_html(void *banner_handle)
530
void os_banner_end_html(void *banner_handle)
534
void os_banner_set_attr(void *banner_handle, int attr)
538
void os_banner_set_color(void *banner_handle, os_color_t fg, os_color_t bg)
542
void os_banner_set_screen_color(void *banner_handle, os_color_t color)
546
void os_banner_clear(void *banner_handle)
550
int os_banner_get_charwidth(void *banner_handle)
555
int os_banner_get_charheight(void *banner_handle)
560
int os_banner_getinfo(void *banner_handle, os_banner_info_t *info)
565
void os_banner_goto(void *banner_handle, int row, int col)