/* -*-C-*-
-$Id: os2conio.c,v 1.2 1994/11/28 08:11:48 cph Exp $
+$Id: os2conio.c,v 1.3 1994/12/02 20:42:55 cph Exp $
Copyright (c) 1994 Massachusetts Institute of Technology
promotional, or sales literature without prior written consent from
MIT in each case. */
+#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
\f
-typedef struct line_buffer_s
-{
- msg_t * message;
- struct line_buffer_s * next;
-} line_buffer_t;
-
-static void console_thread (void *);
+#ifdef USE_PMCON
+#define getch OS2_pm_console_getch
+#else
#ifndef USE_PMIO
-static int getch (void);
+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 init_line_buffer (void);
-static line_buffer_t * make_line_buffer (line_buffer_t *);
-static void push_line_buffer (void);
-static void pop_line_buffer (void);
-static line_buffer_t * reverse_line_buffer (void);
-
static void process_input_char (char);
static void do_rubout (void);
static void add_to_line (char);
static void write_output_1 (const char *, const char *);
static unsigned int char_output_length (char);
-#define LINEFEED '\012'
-
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 line_buffer_t * line_buffer;
+static readahead_buffer_t * line_buffer;
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 ());
input_buffered_p = 1;
console_thread (void * arg)
{
grab_console_lock ();
- init_line_buffer ();
+ line_buffer = (OS2_make_readahead_buffer ());
release_console_lock ();
(void) OS2_thread_initialize (console_writer_qid);
while (1)
OS2_send_message (OS2_interrupt_qid, message);
/* Flush buffers only for certain chars? */
flush_input ();
+ if (c == '\a')
+ write_char ('\a', 0);
}
}
}
OS2_endthread ();
}
-#ifndef USE_PMIO
+#if ((!defined(USE_PMCON)) && (!defined(USE_PMIO)))
static int
getch (void)
{
while (1)
{
-#if 1
+#ifdef USE_VIO
KBDKEYINFO info;
XTD_API_CALL
(kbd_char_in, ((&info), IO_WAIT, 0),
}
\f
static void
-init_line_buffer (void)
-{
- line_buffer = 0;
- push_line_buffer ();
-}
-
-static line_buffer_t *
-make_line_buffer (line_buffer_t * next)
-{
- line_buffer_t * buffer = (OS_malloc (sizeof (line_buffer_t)));
- msg_t * message = (OS2_make_readahead ());
- (SM_READAHEAD_SIZE (message)) = 0;
- (buffer -> message) = message;
- (buffer -> next) = next;
- return (buffer);
-}
-
-static void
-push_line_buffer (void)
-{
- line_buffer = (make_line_buffer (line_buffer));
-}
-
-static void
-pop_line_buffer (void)
-{
- line_buffer_t * buffer = line_buffer;
- OS2_destroy_message (buffer -> message);
- line_buffer = (buffer -> next);
- OS_free (buffer);
-}
-
-static line_buffer_t *
-reverse_line_buffer (void)
-{
- line_buffer_t * this = line_buffer;
- line_buffer_t * prev = 0;
- line_buffer_t * next;
- line_buffer = 0;
- while (1)
- {
- next = (this -> next);
- (this -> next) = prev;
- if (next == 0)
- break;
- prev = this;
- this = next;
- }
- push_line_buffer ();
- return (this);
-}
-
-#define LINE_BUFFER_SIZE (SM_READAHEAD_SIZE (line_buffer -> message))
-#define LINE_BUFFER_DATA (SM_READAHEAD_DATA (line_buffer -> message))
-\f
-static void
process_input_char (char c)
{
if (!input_buffered_p)
do_rubout ();
break;
case '\r':
- do_self_insert (LINEFEED);
+ do_self_insert ('\n');
finish_line ();
break;
default:
add_char_to_line_buffer (char c)
{
grab_console_lock ();
- if (LINE_BUFFER_SIZE == SM_READAHEAD_MAX)
- push_line_buffer ();
- (LINE_BUFFER_DATA [LINE_BUFFER_SIZE ++]) = c;
+ OS2_readahead_buffer_insert (line_buffer, c);
release_console_lock ();
}
do_rubout (void)
{
grab_console_lock ();
- if (LINE_BUFFER_SIZE == 0)
+ if (OS2_readahead_buffer_emptyp (line_buffer))
{
- if ((line_buffer -> next) == 0)
- {
- release_console_lock ();
- write_char ('\a', 0);
- return;
- }
- pop_line_buffer ();
+ release_console_lock ();
+ write_char ('\a', 0);
+ return;
}
{
unsigned int n
- = (char_output_length (LINE_BUFFER_DATA [-- LINE_BUFFER_SIZE]));
+ = (char_output_length (OS2_readahead_buffer_rubout (line_buffer)));
unsigned int i;
release_console_lock ();
for (i = 0; (i < n); i += 1)
static void
finish_line (void)
{
- line_buffer_t * buffer;
+ msg_list_t * messages;
grab_console_lock ();
- buffer = (reverse_line_buffer ());
+ messages = (OS2_readahead_buffer_read_all (line_buffer));
release_console_lock ();
- while (buffer != 0)
+ while (messages != 0)
{
- send_readahead (buffer -> message);
- buffer = (buffer -> next);
- OS_free (buffer);
+ msg_list_t * element = messages;
+ messages = (messages -> next);
+ send_readahead (element -> message);
+ OS_free (element);
}
}
{
case chop_read:
(* ((long *) arg3))
- = (channel_thread_read (channel, ((char *) arg1), ((size_t) arg2)));
+ = (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);
static void
flush_input (void)
{
+ msg_list_t * messages;
grab_console_lock ();
- while ((line_buffer -> next) != 0)
- pop_line_buffer ();
- LINE_BUFFER_SIZE = 0;
+ messages = (OS2_readahead_buffer_read_all (line_buffer));
release_console_lock ();
+ while (messages != 0)
+ {
+ msg_list_t * element = messages;
+ messages = (messages -> next);
+ OS2_destroy_message (element -> message);
+ OS_free (element);
+ }
}
static void
write_output ((&c), 1, cooked_p);
}
+void
+OS2_console_write (const char * data, size_t size)
+{
+ write_output (data, size, 1);
+}
+
static void
write_output (const char * data, size_t size, int cooked_p)
{
out = output_translation;
}
c = (*scan++);
- if (isprint (c))
+ if ((isprint (c)) || (c == '\f') || (c == '\a'))
(*out++) = c;
- else if (c == LINEFEED)
+ else if (c == '\n')
{
(*out++) = '\r';
- (*out++) = c;
+ (*out++) = '\012';
}
else if (c < 0x20)
{
}
}
}
-
+\f
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 */
-#if 1
+#ifdef USE_VIO
+
STD_API_CALL (vio_wrt_tty, (((PCH) scan), (end - scan), 0));
-#else
+
+#else /* not USE_VIO */
+
while (1)
{
ULONG n;
if (scan == end)
break;
}
-#endif
+
+#endif /* not USE_VIO */
#endif /* not USE_PMIO */
+#endif /* not USE_PMCON */
}
static unsigned int
/* -*-C-*-
-$Id: os2msg.c,v 1.1 1994/11/28 03:42:58 cph Exp $
+$Id: os2msg.c,v 1.2 1994/12/02 20:42:46 cph Exp $
Copyright (c) 1994 Massachusetts Institute of Technology
static qid_t allocate_qid (void);
static void OS2_initialize_message_lengths (void);
-static void read_and_dispatch_nonblocking (tqueue_t *);
-static void read_and_dispatch_one_blocking (tqueue_t *);
static void write_subqueue (msg_t *);
static msg_t * read_subqueue (qid_t);
static int subqueue_emptyp (qid_t);
static int read_scm_tqueue (tqueue_t *, int);
static void write_scm_tqueue (tqueue_t *, msg_t *);
static void process_interrupt_messages (void);
-static int read_pm_tqueue (tqueue_t *, int);
-static void write_pm_tqueue (tqueue_t *, msg_t *);
\f
-typedef struct msg_list_s
-{
- msg_t * message;
- struct msg_list_s * next;
-} msg_list_t;
-
typedef struct
{
unsigned int allocatedp : 1; /* queue allocated? */
unsigned int openp : 1; /* queue open? */
qid_t twin; /* other end of connection */
+ qid_receive_filter_t filter; /* filter for received messages */
tqueue_t * tqueue; /* thread queue for reception */
msg_list_t * subqueue_head; /* head of receiving subqueue */
msg_list_t * subqueue_tail; /* tail of receiving subqueue */
#define QID_TQUEUE(q) ((_QID (q)) . tqueue)
#define QID_SUBQUEUE_HEAD(q) ((_QID (q)) . subqueue_head)
#define QID_SUBQUEUE_TAIL(q) ((_QID (q)) . subqueue_tail)
+#define QID_FILTER(q) ((_QID (q)) . filter)
#define MSG_QUEUE_TYPE(m) 0
#define MSG_QUEUE_PRIORITY(m) 0
}
}
OS2_initialize_message_lengths ();
+ SET_MSG_TYPE_LENGTH (mt_init, sm_init_t);
SET_MSG_TYPE_LENGTH (mt_console_interrupt, sm_console_interrupt_t);
SET_MSG_TYPE_LENGTH (mt_timer_event, sm_timer_event_t);
+ SET_MSG_TYPE_LENGTH (mt_generic_reply, sm_generic_reply_t);
qid_lock = (OS2_create_mutex_semaphore ());
OS2_scheme_tqueue = (make_scm_tqueue ());
OS2_make_qid_pair ((&OS2_interrupt_qid_local), (&OS2_interrupt_qid));
(QID_ALLOCATEDP (qid)) = 0;
OS2_release_mutex_semaphore (qid_lock);
}
+
+void
+OS2_set_qid_receive_filter (qid_t qid, qid_receive_filter_t filter)
+{
+ (QID_FILTER (qid)) = filter;
+}
\f
/* Message Lengths */
msg_t * message;
while (1)
{
- read_and_dispatch_nonblocking (tqueue);
+ while (read_tqueue (tqueue, 0))
+ ;
if ((TQUEUE_TYPE (tqueue)) == tqt_scm)
{
process_interrupt_messages ();
message = (read_subqueue (qid));
if ((!blockp) || (message != 0))
break;
- read_and_dispatch_one_blocking (tqueue);
+ (void) read_tqueue (tqueue, 1);
}
return (message);
}
-static void
-read_and_dispatch_nonblocking (tqueue_t * tqueue)
-{
- while (read_tqueue (tqueue, 0))
- ;
+msg_t *
+OS2_wait_for_message (qid_t qid, msg_type_t reply_type)
+{
+ msg_t * reply = (OS2_receive_message (qid, 1));
+ if (OS2_error_message_p (reply))
+ OS2_handle_error_message (reply);
+ if ((MSG_TYPE (reply)) != reply_type)
+ OS2_logic_error ("Incorrect reply message type.");
+ return (reply);
}
-static void
-read_and_dispatch_one_blocking (tqueue_t * tqueue)
+msg_t *
+OS2_message_transaction (qid_t qid, msg_t * request, msg_type_t reply_type)
{
- (void) read_tqueue (tqueue, 1);
+ OS2_send_message (qid, request);
+ OS2_wait_for_message (qid, reply_type);
}
\f
static void
write_subqueue (msg_t * message)
{
qid_t qid = (MSG_SENDER (message));
- msg_list_t * tail = (QID_SUBQUEUE_TAIL (qid));
- msg_list_t * elt = (OS_malloc (sizeof (struct msg_list_s)));
- (elt -> message) = message;
- (elt -> next) = 0;
- if (tail == 0)
- (QID_SUBQUEUE_HEAD (qid)) = elt;
- else
- (tail -> next) = elt;
- (QID_SUBQUEUE_TAIL (qid)) = elt;
+ qid_receive_filter_t filter = (QID_FILTER (qid));
+ if (filter != 0)
+ {
+ message = ((* filter) (message));
+ if (message == 0)
+ return;
+ }
+ {
+ msg_list_t * tail = (QID_SUBQUEUE_TAIL (qid));
+ msg_list_t * elt = (OS_malloc (sizeof (struct msg_list_s)));
+ (elt -> message) = message;
+ (elt -> next) = 0;
+ if (tail == 0)
+ (QID_SUBQUEUE_HEAD (qid)) = elt;
+ else
+ (tail -> next) = elt;
+ (QID_SUBQUEUE_TAIL (qid)) = elt;
+ }
}
static msg_t *
case tqt_scm:
return (read_scm_tqueue (tqueue, blockp));
case tqt_pm:
- return (read_pm_tqueue (tqueue, blockp));
+ return (OS2_read_pm_tqueue (tqueue, blockp));
}
}
write_scm_tqueue (tqueue, message);
break;
case tqt_pm:
- write_pm_tqueue (tqueue, message);
+ OS2_write_pm_tqueue (tqueue, message);
break;
}
}
return (tqueue);
}
+void
+OS2_close_std_tqueue (tqueue_t * tqueue)
+{
+ OS2_close_queue (STD_TQUEUE_QUEUE (tqueue));
+ OS2_close_event_semaphore (STD_TQUEUE_EVENT (tqueue));
+ OS_free (tqueue);
+}
+
static int
read_std_tqueue (tqueue_t * tqueue, int blockp)
{
if (read_std_tqueue (tqueue, blockp))
{
result = 1;
- /* If blockp was set, after we have read one message we read
- any remaining messages in non-blocking mode. */
+ /* At most one message needs to be read in blocking mode. */
blockp = 0;
}
while (test_and_clear_attention_interrupt ());
void
OS2_handle_attention_interrupt (void)
{
- read_and_dispatch_nonblocking (QID_TQUEUE (OS2_interrupt_qid_local));
+ tqueue_t * tqueue = (QID_TQUEUE (OS2_interrupt_qid_local));
+ while (read_tqueue (tqueue, 0))
+ ;
process_interrupt_messages ();
}
OS2_destroy_message (message);
}
}
-\f
-static int
-read_pm_tqueue (tqueue_t * tqueue, int blockp)
-{
- return (0);
-}
-
-static void
-write_pm_tqueue (tqueue_t * tqueue, msg_t * message)
-{
-}
/* -*-C-*-
-$Id: os2msg.h,v 1.1 1994/11/28 03:42:59 cph Exp $
+$Id: os2msg.h,v 1.2 1994/12/02 20:42:38 cph Exp $
Copyright (c) 1994 Massachusetts Institute of Technology
\f
typedef enum
{
+ /* This is sent to acknowledge that the other end of a qid pair has
+ been opened. Sometimes it is necessary to wait until the
+ connection is established before proceeding. */
+ mt_init,
+
+ /* This is sent by a "readahead" thread whenever it has some data to
+ give to the other end of the connection. These messages are
+ generated asynchronously whenever the readahead is available. */
mt_readahead,
+
+ /* This is sent by the receiver or a readahead message. It is used
+ to regulate the amount of readahead in the connection.
+ Typically, the readahead thread won't generate any more readahead
+ messages until the readahead_ack is received. */
mt_readahead_ack,
+
+ /* This is a console interrupt event. It is generated automatically
+ by the console readahead thread (or the PM thread if the console
+ is implemented as a PM window), and causes a Scheme character
+ interrupt to be signalled in the interrupt-code register. */
mt_console_interrupt,
+
+ /* This is a timer interrupt event. It is generated automatically
+ by the timer thread when the timer is active. */
+ mt_timer_event,
+
+ /* These are error messages. They are sent as a reply to a request
+ when an error is generated during the processing of the request. */
mt_error,
- mt_kill_request,
mt_syscall_error,
- mt_timer_event,
+
+ /* This is a generic reply that is used to acknowledge requests that
+ return no meaningful data other than that they have completed. */
+ mt_generic_reply,
+
+ /* This is a request/reply pair that asks the PM thread to create a
+ terminal window. */
+ mt_twindow_open_request,
+ mt_twindow_open_reply,
+
+ /* This requests the PM thread to close an existing terminal window. */
+ mt_twindow_close_request,
+
+ /* This requests the PM thread to write some characters on a
+ terminal window. */
+ mt_twindow_write_request,
+
+ /* This requests the PM thread to move the cursor of a terminal
+ window. */
+ mt_twindow_move_cursor_request,
+
+ /* This requests the PM thread to clear a terminal window. */
+ mt_twindow_clear_request,
+
+ /* This requests the PM thread to clear to the end of a line in a
+ terminal window. */
+ mt_twindow_clear_eol_request,
+
+ /* This requests the PM thread to scroll a rectangular region in a
+ terminal window. */
+ mt_twindow_scroll_request,
+
+ /* These are messages that are automatically generated by the PM
+ thread when the corresponding events occur. */
+ mt_key_event, /* key press */
+ mt_button_event, /* mouse button press */
+ mt_close_event, /* window close */
+ mt_visibility_event, /* window visibility change */
+ mt_resize_event, /* window resized */
+
+ /* This requests the thread on the other end of the connection to
+ kill itself. At present this request is not used. */
+ mt_kill_request,
mt_supremum
} msg_type_t;
#define MSG_TYPE_SUP ((unsigned int) mt_supremum)
#define MSG_TYPE_MAX (MSG_TYPE_SUP - 1)
-
+\f
typedef unsigned char qid_t;
#define QID_MAX (UCHAR_MAX - 1)
#define QID_NONE UCHAR_MAX
} tqueue_t;
#define TQUEUE_TYPE(q) (((tqueue_t *) (q)) -> type)
+typedef msg_t * (* qid_receive_filter_t) (msg_t *);
+
extern tqueue_t * OS2_scheme_tqueue;
extern qid_t OS2_interrupt_qid;
extern void OS2_open_qid (qid_t, tqueue_t *);
extern int OS2_qid_openp (qid_t);
extern void OS2_close_qid (qid_t);
+extern void OS2_set_qid_receive_filter (qid_t, qid_receive_filter_t);
extern msg_length_t OS2_message_type_length (msg_type_t);
extern void OS2_set_message_type_length (msg_type_t, msg_length_t);
extern msg_t * OS2_create_message (msg_type_t);
extern void OS2_destroy_message (msg_t *);
extern void OS2_send_message (qid_t, msg_t *);
extern msg_t * OS2_receive_message (qid_t, int);
+extern msg_t * OS2_wait_for_message (qid_t, msg_type_t);
+extern msg_t * OS2_message_transaction (qid_t, msg_t *, msg_type_t);
extern tqueue_t * OS2_make_std_tqueue (void);
-
+extern void OS2_close_std_tqueue (tqueue_t *);
+\f
#define MSG_LENGTH(m) (OS2_message_type_length (MSG_TYPE (m)))
#define SET_MSG_TYPE_LENGTH(t, s) \
OS2_set_message_type_length ((t), (sizeof (s)))
+typedef struct msg_list_s
+{
+ msg_t * message;
+ struct msg_list_s * next;
+} msg_list_t;
+
typedef struct
{
DECLARE_MSG_HEADER_FIELDS;
#define SM_CONSOLE_INTERRUPT_CODE(m) (((sm_console_interrupt_t *) (m)) -> code)
typedef msg_t sm_timer_event_t;
+typedef msg_t sm_init_t;
+typedef msg_t sm_generic_reply_t;
#endif /* SCM_OS2MSG_H */