home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
OS/2 Shareware BBS: 10 Tools
/
10-Tools.zip
/
mitsch75.zip
/
scheme-7_5_17-src.zip
/
scheme-7.5.17
/
src
/
microcode
/
os2conio.c
< prev
next >
Wrap
C/C++ Source or Header
|
1999-01-02
|
11KB
|
477 lines
/* -*-C-*-
$Id: os2conio.c,v 1.10 1999/01/02 06:11:34 cph Exp $
Copyright (c) 1994-1999 Massachusetts Institute of Technology
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or (at
your option) any later version.
This program is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#define USE_PMCON
/* #define USE_VIO */
/* #define USE_PMIO */
#include "os2.h"
#ifdef USE_PMCON
extern void OS2_initialize_pm_console (void);
extern int OS2_pm_console_getch (void);
extern void OS2_pm_console_write (const char *, size_t);
#else
#ifdef USE_PMIO
#include <pmio.h>
#endif
#endif
#ifdef USE_PMCON
#define getch OS2_pm_console_getch
#else
#ifndef USE_PMIO
static int getch (void);
#endif
#endif
static void console_thread (void *);
static void grab_console_lock (void);
static void release_console_lock (void);
static void process_input_char (char);
static void do_rubout (void);
static void add_to_line (char);
static void do_newline (void);
static void do_self_insert (char);
static void add_char_to_line_buffer (char);
static void finish_line (void);
static void send_char (char);
static void send_readahead (msg_t *);
static void handle_console_interrupt (msg_t *);
static void console_operator
(Tchannel, chop_t, choparg_t, choparg_t, choparg_t);;
static void flush_input (void);
static void console_input_buffered (Tchannel, int, int *);
static void console_output_cooked (Tchannel, int, int *);
static void write_char (char, int);
static void write_output (const char *, size_t, int);
static void write_output_1 (const char *, const char *);
static unsigned int char_output_length (char);
static HMTX console_lock;
static int input_buffered_p;
static int output_cooked_p;
static qid_t console_writer_qid;
static channel_context_t * console_context;
static void * line_buffer;
TID OS2_console_tid;
void
OS2_initialize_console (void)
{
#ifdef USE_PMCON
OS2_initialize_pm_console ();
#else
#ifdef USE_PMIO
pmio_fontspec = "6.System VIO";
set_width (80);
set_height (40);
start_pmio ();
#endif
#endif
console_lock = (OS2_create_mutex_semaphore (0, 0));
input_buffered_p = 1;
output_cooked_p = 1;
console_context = (OS2_make_channel_context ());
OS2_open_qid ((CHANNEL_CONTEXT_READER_QID (console_context)),
OS2_scheme_tqueue);
console_writer_qid = (CHANNEL_CONTEXT_WRITER_QID (console_context));
OS2_open_qid (console_writer_qid, (OS2_make_std_tqueue ()));
(CHANNEL_CONTEXT_FIRST_READ_P (console_context)) = 0;
OS2_console_tid = (OS2_beginthread (console_thread, 0, 0x4000));
(CHANNEL_CONTEXT_TID (console_context)) = OS2_console_tid;
}
static void
console_thread (void * arg)
{
EXCEPTIONREGISTRATIONRECORD registration;
grab_console_lock ();
line_buffer = (OS2_make_readahead_buffer ());
release_console_lock ();
(void) OS2_thread_initialize ((®istration), console_writer_qid);
while (1)
{
int c = (getch ());
if (c == EOF)
{
msg_t * message = (OS2_make_readahead ());
(SM_READAHEAD_SIZE (message)) = 0;
send_readahead (message);
break;
}
{
int code = (OS2_keyboard_interrupt_handler (c));
if (code == '\0')
process_input_char (c);
else
{
msg_t * message = (OS2_create_message (mt_console_interrupt));
(SM_CONSOLE_INTERRUPT_CODE (message)) = code;
OS2_send_message (OS2_interrupt_qid, message);
/* Flush buffers only for certain chars? */
flush_input ();
if (c == '\a')
write_char ('\a', 0);
}
}
}
{
tqueue_t * tqueue = (OS2_qid_tqueue (console_writer_qid));
OS2_close_qid (console_writer_qid);
OS2_close_std_tqueue (tqueue);
}
OS2_endthread ();
}
#if ((!defined(USE_PMCON)) && (!defined(USE_PMIO)))
static int
getch (void)
{
while (1)
{
#ifdef USE_VIO
KBDKEYINFO info;
XTD_API_CALL
(kbd_char_in, ((&info), IO_WAIT, 0),
{
if (rc == ERROR_KBD_INVALID_HANDLE)
return (EOF);
});
if ((info . fbStatus) == 0x40)
return (info . chChar);
#else
int c = (_getch ());
if (c == EOF)
return (EOF);
else if ((c == 0) || (c == 0xe0))
{
/* Discard extended keycodes. */
if ((_getch ()) == EOF)
return (EOF);
}
else
return (c);
#endif
}
}
#endif /* not USE_PMIO */
static void
grab_console_lock (void)
{
OS2_request_mutex_semaphore (console_lock);
}
static void
release_console_lock (void)
{
OS2_release_mutex_semaphore (console_lock);
}
static void
process_input_char (char c)
{
if (!input_buffered_p)
send_char (c);
else switch (c)
{
case '\b':
case '\177':
do_rubout ();
break;
case '\r':
do_self_insert ('\r');
do_self_insert ('\n');
finish_line ();
break;
default:
do_self_insert (c);
break;
}
}
static void
do_self_insert (char c)
{
add_char_to_line_buffer (c);
write_char (c, 1);
}
static void
add_char_to_line_buffer (char c)
{
grab_console_lock ();
OS2_readahead_buffer_insert (line_buffer, c);
release_console_lock ();
}
static void
do_rubout (void)
{
grab_console_lock ();
if (OS2_readahead_buffer_emptyp (line_buffer))
{
release_console_lock ();
write_char ('\a', 0);
return;
}
{
unsigned int n
= (char_output_length (OS2_readahead_buffer_rubout (line_buffer)));
unsigned int i;
release_console_lock ();
for (i = 0; (i < n); i += 1)
write_char ('\b', 0);
for (i = 0; (i < n); i += 1)
write_char (' ', 0);
for (i = 0; (i < n); i += 1)
write_char ('\b', 0);
}
}
static void
finish_line (void)
{
msg_t ** messages;
msg_t ** scan;
grab_console_lock ();
messages = (OS2_readahead_buffer_read_all (line_buffer));
release_console_lock ();
scan = messages;
while (1)
{
msg_t * msg = (*scan++);
if (msg == 0)
break;
send_readahead (msg);
}
OS_free (messages);
}
static void
send_char (char c)
{
msg_t * message = (OS2_make_readahead ());
(SM_READAHEAD_SIZE (message)) = 1;
((SM_READAHEAD_DATA (message)) [0]) = c;
send_readahead (message);
}
static void
send_readahead (msg_t * message)
{
OS2_send_message (console_writer_qid, message);
(void) OS2_wait_for_readahead_ack (console_writer_qid);
}
void
OS2_initialize_console_channel (Tchannel channel)
{
(CHANNEL_OPERATOR_CONTEXT (channel)) = console_context;
(CHANNEL_OPERATOR (channel)) = console_operator;
}
static void
console_operator (Tchannel channel, chop_t operation,
choparg_t arg1, choparg_t arg2, choparg_t arg3)
{
switch (operation)
{
case chop_read:
(* ((long *) arg3))
= (OS2_channel_thread_read
(channel, ((char *) arg1), ((size_t) arg2)));
break;
case chop_write:
write_output (((const char *) arg1), ((size_t) arg2), output_cooked_p);
(* ((long *) arg3)) = ((size_t) arg2);
break;
case chop_close:
case chop_output_flush:
case chop_output_drain:
break;
case chop_input_flush:
flush_input ();
break;
case chop_input_buffered:
console_input_buffered (channel, ((int) arg1), ((int *) arg2));
break;
case chop_output_cooked:
console_output_cooked (channel, ((int) arg1), ((int *) arg2));
break;
default:
OS2_logic_error ("Unknown operation for console.");
break;
}
}
static void
flush_input (void)
{
msg_t ** messages;
msg_t ** scan;
grab_console_lock ();
messages = (OS2_readahead_buffer_read_all (line_buffer));
release_console_lock ();
scan = messages;
while (1)
{
msg_t * msg = (*scan++);
if (msg == 0)
break;
OS2_destroy_message (msg);
}
OS_free (messages);
}
static void
console_input_buffered (Tchannel channel, int new, int * pold)
{
if (new < 0)
(* pold) = input_buffered_p;
else
{
int old = input_buffered_p;
input_buffered_p = new;
if (old && (!new))
flush_input ();
}
}
static void
console_output_cooked (Tchannel channel, int new, int * pold)
{
if (new < 0)
(* pold) = output_cooked_p;
else
output_cooked_p = (new ? 1 : 0);
}
static void
write_char (char c, int cooked_p)
{
write_output ((&c), 1, cooked_p);
}
void
OS2_console_write (const char * data, size_t size)
{
write_output (data, size, 2);
}
static void
write_output (const char * data, size_t size, int cooked_p)
{
const char * scan = data;
const char * end = (scan + size);
char output_translation [256];
char * out = output_translation;
char * out_limit = (out + ((sizeof (output_translation)) - 4));
char c;
if (cooked_p == 0)
write_output_1 (scan, end);
else
while (1)
{
if ((scan == end) || (out >= out_limit))
{
write_output_1 (output_translation, out);
if (scan == end)
break;
out = output_translation;
}
c = (*scan++);
if ((cooked_p == 2) && (c == '\n'))
{
(*out++) = '\r';
(*out++) = '\n';
}
else if ((isprint (c))
|| (c == '\f')
|| (c == '\a')
|| (c == '\r')
|| (c == '\n'))
(*out++) = c;
else if (c < 0x20)
{
(*out++) = '^';
(*out++) = ('@' + c);
}
else
{
(*out++) = '\\';
(*out++) = ('0' + ((c >> 6) & 3));
(*out++) = ('0' + ((c >> 3) & 7));
(*out++) = ('0' + (c & 7));
}
}
}
static void
write_output_1 (const char * scan, const char * end)
{
#ifdef USE_PMCON
OS2_pm_console_write (scan, (end - scan));
#else /* not USE_PMCON */
#ifdef USE_PMIO
put_raw ((end - scan), scan);
#else /* not USE_PMIO */
#ifdef USE_VIO
STD_API_CALL (vio_wrt_tty, (((PCH) scan), (end - scan), 0));
#else /* not USE_VIO */
while (1)
{
ULONG n;
APIRET rc = (dos_write (1, ((void *) scan), (end - scan), (& n)));
if (rc != NO_ERROR)
break;
scan += n;
if (scan == end)
break;
}
#endif /* not USE_VIO */
#endif /* not USE_PMIO */
#endif /* not USE_PMCON */
}
static unsigned int
char_output_length (char c)
{
return ((isprint (c)) ? 1 : (c < 0x20) ? 2 : 4);
}