Initial revision
authorGuillermo J. Rozas <edu/mit/csail/zurich/gjr>
Thu, 24 Jun 1993 01:52:12 +0000 (01:52 +0000)
committerGuillermo J. Rozas <edu/mit/csail/zurich/gjr>
Thu, 24 Jun 1993 01:52:12 +0000 (01:52 +0000)
v7/src/microcode/ntgui.c [new file with mode: 0644]
v7/src/microcode/ntgui.h [new file with mode: 0644]
v7/src/microcode/ntscreen.c [new file with mode: 0644]
v7/src/microcode/ntscreen.h [new file with mode: 0644]
v7/src/microcode/ntutl/ntgui.rc [new file with mode: 0644]

diff --git a/v7/src/microcode/ntgui.c b/v7/src/microcode/ntgui.c
new file mode 100644 (file)
index 0000000..448069b
--- /dev/null
@@ -0,0 +1,686 @@
+#include "scheme.h"
+#include "prims.h"
+#include "nt.h"
+#include "os.h"
+#include "ntgui.h"
+#include "ntscreen.h"
+#include <string.h>
+
+
+extern /*static*/ HANDLE  ghInstance = 0;
+
+
+BOOL InitApplication(HANDLE);
+BOOL InitInstance(HANDLE, int);
+
+void *xmalloc(int);
+void xfree(void*);
+
+#ifdef GUI
+int PASCAL
+WinMain (HANDLE hInst, HANDLE hPrevInst, LPSTR lpCmdLine, int nCmdShow)
+{
+    int argc;
+    char **argv;
+    
+    ghInstance = hInst;
+    
+    {
+      int cmdlen = strlen(lpCmdLine);
+      int maxargs = cmdlen/2+2;
+      char *cmdline = malloc(cmdlen+1);
+      char *s;
+
+      argv = malloc(sizeof(char*) * maxargs);
+      
+      if (cmdline==0 || argv==0) {
+       outf_fatal ("WinMain cant malloc");
+       outf_flush_fatal ();
+       return  FALSE;
+      }        
+
+      argc = 1;
+      argv[0] = "scheme";
+      
+      s = strcpy (cmdline, lpCmdLine);
+      
+      while (*s) {
+       if (*s==' ')
+         *s++ = 0;
+       else {
+         argv[argc++] = s;
+         while (*s != 0 && *s != ' ') s++;
+       }
+      }
+      argv[argc] = 0;
+    }
+    
+    if (!hPrevInst)
+      if (!InitApplication(ghInstance))
+       return  FALSE;
+    
+    if (!InitInstance(ghInstance, nCmdShow))
+      return  FALSE;
+      
+    
+    main(argc, argv);
+}
+#endif
+
+
+BOOL
+DEFUN (InitApplication, (hInstance), HANDLE hInstance)
+{
+    WNDCLASS wc;
+    static BOOL done = FALSE;
+    
+    if (done) return  TRUE;
+    done = TRUE;
+    
+    //wc.style         = CS_HREDRAW | CS_VREDRAW;
+    //wc.lpfnWndProc   = TranscriptWndProc;
+    //wc.cbClsExtra    = 0;
+    //wc.cbWndExtra    = sizeof (Transcript*);
+    //wc.hInstance     = hInstance;
+    //wc.hIcon         = NULL;
+    //wc.hCursor       = LoadCursor (NULL, IDC_ARROW);
+    //wc.hbrBackground = GetStockObject (WHITE_BRUSH);
+    //wc.lpszMenuName  = transcript_class_name;
+    //wc.lpszClassName = transcript_class_name;
+
+    //if (!RegisterClass(&wc))
+    //  return  FALSE;
+  
+    return  Screen_InitApplication (hInstance);
+    //return  TRUE;
+}
+
+static BOOL instance_initialized = FALSE;
+
+BOOL
+DEFUN (InitInstance, (hInstance, nCmdShow), HANDLE hInstance AND int nCmdShow)
+{
+    instance_initialized = TRUE;
+
+    return  Screen_InitInstance (hInstance, nCmdShow);
+    //return  TRUE;
+}
+
+
+
+//void
+//DEFUN_VOID (nt_gui_default_poll)
+//{
+//   static int n = 0;
+//#ifdef GUI
+//   DWORD pending_types;
+//   int events_processed = 0;
+//
+//   outf_console("\001");  outf_flush_console();
+//   while (events_processed < 5 &&
+//          (pending_types = GetQueueStatus(QS_INPUT)) >> 16) {
+//     MSG msg;
+//     //outf_console("GetQueueStatus() = 0x%08x\n", pending_types);
+//     //outf_console("GetMessage()\n");
+//   outf_console("\360");  outf_flush_console();
+//     GetMessage (&msg, 0, 0, 0);
+//     TranslateMessage(&msg);
+//     DispatchMessage(&msg);
+//   outf_console("\361");  outf_flush_console();
+//     events_processed ++;
+//   }
+//   //outf_console("events_processed = %d\n", events_processed);
+//   outf_console("\002");  outf_flush_console();
+//#endif
+//}
+
+
+void
+DEFUN_VOID (nt_gui_default_poll)
+{
+#ifdef GUI
+   MSG  msg;
+   int events_processed = 0;
+
+   while (//events_processed < 5 &&
+          PeekMessage (&msg, 0, 0, 0, PM_REMOVE)) {
+     TranslateMessage(&msg);
+     DispatchMessage(&msg);
+     events_processed ++;
+   }
+#endif
+}
+
+
+DEFINE_PRIMITIVE ("NT-DEFAULT-POLL-GUI-INTERRUPT",
+                  Prim_nt_default_poll_gui_interrupt, 2, 2,
+                 "NT High-priority timer interrupt handler for Windows I/O.")
+{
+  PRIMITIVE_HEADER (2);
+  nt_gui_default_poll ();
+//  CLEAR_INTERRUPT (INT_Global_GC);
+  CLEAR_INTERRUPT (INT_Global_1);
+  PRIMITIVE_RETURN (UNSPECIFIC);
+}
+
+DEFINE_PRIMITIVE ("NT-DEFAULT-POLL-GUI", Prim_nt_default_poll_gui, 2, 2,
+"")
+{
+  PRIMITIVE_HEADER(2)
+  {
+    nt_gui_default_poll ();
+    PRIMITIVE_RETURN  (UNSPECIFIC);
+  }
+}
+
+void
+DEFUN_VOID (NT_gui_init)
+{
+   if (!instance_initialized) {
+     if (!InitApplication (ghInstance))
+       outf_console ("InitApplication failed\n");
+     if (!InitInstance (ghInstance, SW_SHOWNORMAL))
+       outf_console ("InitInstance failed\n");
+   }
+}
+
+
+\f
+static long  
+scheme_object_to_windows_object (SCHEME_OBJECT thing)
+{
+    if (INTEGER_P (thing))
+      return  integer_to_long (thing);
+
+    if (STRING_P (thing))
+      return  (long) STRING_LOC (thing, 0);
+
+    if (thing==SHARP_F)
+      return  0;
+    if (thing==SHARP_T)
+      return  1;
+
+    if (OBJECT_TYPE (thing) == TC_VECTOR_1B ||
+        OBJECT_TYPE (thing) == TC_VECTOR_16B)
+      return  (long) VECTOR_LOC (thing, 0);
+
+    return  (long)thing;
+}
+
+\f
+/****************************************************************************/
+/* first scheme window procedure requires every procedure to be purified    */
+/****************************************************************************/
+
+static SCHEME_OBJECT
+apply4 (SCHEME_OBJECT procedure, SCHEME_OBJECT arg1, SCHEME_OBJECT arg2,
+                                 SCHEME_OBJECT arg3, SCHEME_OBJECT arg4)
+{
+    return  C_call_scheme (procedure, 4, &arg1);
+}
+
+LRESULT CALLBACK
+C_to_Scheme_WndProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
+{
+    SCHEME_OBJECT  thunk;
+    SCHEME_OBJECT  result;
+    
+    if (message==WM_CREATE || message==WM_NCCREATE) {
+      /*install thunk*/
+      LPCREATESTRUCT lpcs = (LPCREATESTRUCT) lParam;
+      SetWindowLong(hwnd, 0, (LONG)lpcs->lpCreateParams);
+    }
+    
+    thunk = GetWindowLong (hwnd, 0);
+    
+    if (thunk==0)
+      return  DefWindowProc (hwnd, message, wParam, lParam);
+    
+    result = apply4(thunk,
+                ulong_to_integer(hwnd), ulong_to_integer(message),
+               ulong_to_integer(wParam), ulong_to_integer(lParam));
+
+    return  scheme_object_to_windows_object (result);
+}
+
+
+DEFINE_PRIMITIVE ("GET-SCHEME-WINDOW-PROCEDURE", Prim_get_scheme_window_procedure, 1, 1,
+"")
+{
+  PRIMITIVE_HEADER(1);
+  {
+    HWND hWnd = (HWND)arg_integer (1);
+    SCHEME_OBJECT  result;
+    
+    if (GetWindowLong(hWnd, GWL_WNDPROC) != (LONG) C_to_Scheme_WndProc)
+      result = SHARP_F;
+    else
+      result = (SCHEME_OBJECT) GetWindowLong(hWnd, 0);
+
+    PRIMITIVE_RETURN (result);
+  }
+}
+
+/****************************************************************************/
+/*
+    Second version:  There is only one scheme wndproc, which is called
+    to re-dispatch to the correct wndproc, indexing of the hwnd argument.
+    The one scheme procedure is set with SET-GENERAL-SCHEME-WNDPROC.
+    The procedure must be a purified first.
+*/
+
+
+static SCHEME_OBJECT general_scheme_wndproc = SHARP_F;
+
+DEFINE_PRIMITIVE ("GET-GENERAL-SCHEME-WNDPROC",
+Prim_get_general_scheme_wndproc, 0, 0, "")
+{
+  PRIMITIVE_HEADER(0);
+  {
+    PRIMITIVE_RETURN (general_scheme_wndproc);
+  }
+}
+
+DEFINE_PRIMITIVE ("SET-GENERAL-SCHEME-WNDPROC",
+Prim_set_general_scheme_wndproc, 1, 1, "")
+{
+  PRIMITIVE_HEADER(1);
+  {
+    SCHEME_OBJECT  wndproc = ARG_REF(1);
+    if (! ADDRESS_PURE_P (OBJECT_ADDRESS (wndproc)))
+      signal_error_from_primitive (ERR_ARG_1_WRONG_TYPE);
+    general_scheme_wndproc = wndproc;
+    PRIMITIVE_RETURN (UNSPECIFIC);
+  }
+}
+
+
+LRESULT CALLBACK
+C_to_Scheme_WndProc_2 (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
+{
+    SCHEME_OBJECT  result;
+    
+    if (general_scheme_wndproc == SHARP_F)
+      return  DefWindowProc (hwnd, message, wParam, lParam);
+    
+    result = apply4(general_scheme_wndproc,
+                    ulong_to_integer(hwnd), ulong_to_integer(message),
+                   ulong_to_integer(wParam), ulong_to_integer(lParam));
+
+    return  scheme_object_to_windows_object (result);
+}
+
+
+/***************************************************************************/
+
+DEFINE_PRIMITIVE ("GET-HANDLE", Prim_get_handle, 1, 1,
+"(GET-HANDLE id)\n"
+"Returns an otherwise hard to get global C variable\n"
+"id    entity\n"
+"0     instance handle\n"
+"1     master tty handle\n"
+"2     C to Scheme windows procedure address\n"
+"3     C to Scheme windows procedure address (eta version)\n"
+)
+{
+  extern  HANDLE  master_tty_window;
+  PRIMITIVE_HEADER(1);
+  {
+    long  arg = arg_integer (1);
+    long  result = 0;
+    switch (arg) {
+      case 0:  result = (long) ghInstance;             break;
+      case 1:   result = (long) master_tty_window;     break;
+      case 2:  result = (long) C_to_Scheme_WndProc;    break;
+      case 3:  result = (long) C_to_Scheme_WndProc_2;  break;
+      default:  error_bad_range_arg (1);
+      }
+    PRIMITIVE_RETURN (long_to_integer (result));
+  }
+}
+
+
+
+static unsigned long
+DEFUN (arg_ulong_default, (arg_number, def),
+       int arg_number AND unsigned long def)
+{
+  fast SCHEME_OBJECT object = (ARG_REF (arg_number));
+  if (object == SHARP_F)
+    return  def;
+  if (! (INTEGER_P (object)))
+    error_wrong_type_arg (arg_number);
+  return  integer_to_ulong (object);
+}
+
+
+DEFINE_PRIMITIVE ("WIN:CREATE-WINDOW", Prim_create_window, 10, 10,
+"class-name\n"
+"window-name\n"
+"style\n"
+"X\n"
+"Y\n"
+"width\n"
+"height\n"
+"parent\n"
+"menu\n"
+"(instance omitted)\n"
+"lpParam: (lambda (hwnd message wparam lparam)). [think about MDI later]\n")
+{
+    LPSTR  class_name;
+    LPSTR  window_name;
+    DWORD  style;
+    int    x, y, w, h;
+    HWND   hWndParent;
+    HMENU  hMenu;
+    //HANDLE hInst;
+    LPVOID lpvParam;
+    HWND   result;
+    
+    CHECK_ARG (1, STRING_P);
+    CHECK_ARG (2, STRING_P);
+    class_name = STRING_LOC (ARG_REF (1), 0);
+    window_name = STRING_LOC (ARG_REF (2), 0);
+    style = integer_to_ulong (ARG_REF (3));
+    x = arg_ulong_default (4, CW_USEDEFAULT);
+    y = arg_ulong_default (5, CW_USEDEFAULT);
+    w = arg_ulong_default (6, CW_USEDEFAULT);
+    h = arg_ulong_default (7, CW_USEDEFAULT);
+    hWndParent = (HWND) arg_ulong_default (8, 0);
+    hMenu      =  (HMENU) arg_ulong_default (9, 0);
+    lpvParam   = (LPVOID)  ARG_REF (10);
+    
+    result = CreateWindowEx (0, class_name, window_name, style, x, y, w, h,
+                   hWndParent, hMenu, ghInstance, lpvParam);
+                
+    return  ulong_to_integer (result);
+}
+
+
+DEFINE_PRIMITIVE ("WIN:DEF-WINDOW-PROC", Prim_def_window_proc, 4, 4, "")
+{
+    //outf_console ("\001");
+    return
+      long_to_integer (
+       DefWindowProc (
+         scheme_object_to_windows_object (ARG_REF (1)),
+         scheme_object_to_windows_object (ARG_REF (2)),
+         scheme_object_to_windows_object (ARG_REF (3)),
+         scheme_object_to_windows_object (ARG_REF (4))));
+}
+
+
+DEFINE_PRIMITIVE ("REGISTER-CLASS",
+                  Prim__register_class, 10, 10,
+"(REGISTER-CLASS style wndproc clsExtra wndExtra hInstance hIcon hCursor\n"
+"                hBackground menu-name class-name)\n\n"
+
+"cursor     = 32512(arrow), 32513(ibeam), 32514(hourglass) 32515(cross), 32516(uparrow)\n"
+"background = 0 (white_brush)\n"
+)
+{
+    // should lift background and cursor
+    WNDCLASS wc;
+    BOOL  rc;
+    PRIMITIVE_HEADER (10);
+    CHECK_ARG (10, STRING_P);
+
+    wc.style         = arg_integer (1);
+    wc.lpfnWndProc   = arg_integer (2);
+    wc.cbClsExtra    = scheme_object_to_windows_object (ARG_REF(3));
+    wc.cbWndExtra    = scheme_object_to_windows_object (ARG_REF(4));
+    wc.hInstance     = scheme_object_to_windows_object (ARG_REF(5));
+    wc.hIcon         = scheme_object_to_windows_object (ARG_REF(6));
+    wc.hCursor       = LoadCursor (NULL, MAKEINTRESOURCE(arg_integer(7)));
+    wc.hbrBackground = GetStockObject (arg_integer(8));
+    wc.lpszMenuName  = scheme_object_to_windows_object (ARG_REF(9));
+    wc.lpszClassName = scheme_object_to_windows_object (ARG_REF(10));
+
+    rc = RegisterClass (&wc);
+    PRIMITIVE_RETURN (BOOLEAN_TO_OBJECT(rc));
+}
+\f
+DEFINE_PRIMITIVE ("APPLY_1", Prim_apply_1_xyz, 2, 2, "")
+{
+    SCHEME_OBJECT  proc, arg, result;
+    PRIMITIVE_HEADER (2);
+    
+    proc = ARG_REF (1);
+    arg  = ARG_REF (2);
+    
+    result = C_call_scheme (proc, 1, &arg);
+    
+    PRIMITIVE_RETURN (result);
+}
+
+
+\f
+/************************************************************************/
+/* Primitive versions of library stuff                                 */
+/************************************************************************/
+
+
+DEFINE_PRIMITIVE ("NT:GET-MODULE-HANDLE", Prim_get_module_handle, 1, 1,
+"(GET-MODULE-HANDLE string) -> handle")
+{
+    HANDLE it;
+
+    PRIMITIVE_HEADER (1);
+    
+    CHECK_ARG (1, STRING_P);
+    it = GetModuleHandle (STRING_LOC (ARG_REF (1), 0));
+    PRIMITIVE_RETURN (long_to_integer (it));
+}
+
+DEFINE_PRIMITIVE ("NT:LOAD-LIBRARY", Prim_nt_load_library, 1, 1,
+"(LOAD-LIBRARY string) -> handle")
+{
+    HANDLE it;
+
+    PRIMITIVE_HEADER (1);
+    
+    CHECK_ARG (1, STRING_P);
+    it = LoadLibrary ((LPSTR)STRING_LOC (ARG_REF (1), 0));
+    PRIMITIVE_RETURN (long_to_integer (it));
+}
+
+DEFINE_PRIMITIVE ("NT:GET-PROC-ADDRESS", Prim_nt_get_proc_address, 2, 2,
+"(GET-PROC-ADDRESS handle string/integer) -> address")
+{
+    HMODULE  module;
+    LPSTR    function_name;
+    FARPROC  it;
+    SCHEME_OBJECT  function;
+    
+    PRIMITIVE_HEADER (2);
+    
+    module   = arg_integer (1);
+    function = ARG_REF (2);
+    if (STRING_P (function))
+      function_name = STRING_LOC (function, 0);
+    else
+      function_name = (LPSTR) arg_integer (2);
+
+    it = GetProcAddress (module, function_name);
+
+    PRIMITIVE_RETURN (it==NULL ? SHARP_F : long_to_integer (it));
+}
+
+
+
+\f
+DEFINE_PRIMITIVE ("NT:SEND-MESSAGE", Prim_send_message, 4, 4,
+"(SEND-MESSAGE  handle  message  wparam  lparam)")
+{
+    HWND    hwnd;
+    UINT    message;
+    WPARAM  wParam;
+    LPARAM  lParam;
+    SCHEME_OBJECT  thing;
+    PRIMITIVE_HEADER (4);
+    
+    hwnd    = arg_integer (1);
+    message = arg_integer (2);
+    wParam  = arg_integer (3);
+    thing = ARG_REF (4);
+    if (STRING_P (thing))
+      lParam = (LPARAM) STRING_LOC (thing, 0);
+    else
+      lParam = arg_integer (4);
+    
+    PRIMITIVE_RETURN (
+      long_to_integer (SendMessage (hwnd, message, wParam, lParam)));
+}
+
+\f
+
+
+// Indirect calls to a __stdcall procedure are compiled as if to a _cdecl
+// procedure.  The result is disaster.  The fudge_calls give us some
+// protection because the procedure entry code pushes registers.  These
+// get trampled, but with luck the values saved were not live.
+//
+//static long fudge_call_1 (long (* WINAPI f)(long), long a)
+//{
+//   return  f(a);
+//}
+//
+//DEFINE_PRIMITIVE ("CALL-FF-1", Prim_call_ff_1, 2, 2,
+//"")
+//{
+//    long  result;
+//    long (* WINAPI f)(long);
+//    PRIMITIVE_HEADER (2);
+//    
+//    f =  arg_integer (1);
+//    result = fudge_call_1 (f, call_ff_arg (ARG_REF (2)));
+//    
+//    PRIMITIVE_RETURN (long_to_integer (result));
+//}
+//
+//static long fudge_call_2 (long (* WINAPI f)(long,long), long a1, long a2)
+//{
+//    return  f(a1,a2);
+//}
+//
+//DEFINE_PRIMITIVE ("CALL-FF-2", Prim_call_ff_2, 3, 3,
+//"")
+//{
+//    long (* WINAPI f)(long,long);
+//    
+//    PRIMITIVE_HEADER (3);
+//    
+//    f =  arg_integer (1);
+//    PRIMITIVE_RETURN (long_to_integer (fudge_call_2 (f, call_ff_arg (ARG_REF(2)), call_ff_arg (ARG_REF(3)))));
+//}
+//
+//static long fudge_call_3 (long (* WINAPI f)(long,long,long),
+//                          long a1, long a2, long a3)
+//{
+//    return  f(a1,a2,a3);
+//}
+//
+//DEFINE_PRIMITIVE ("CALL-FF-3", Prim_call_ff_3, 4, 4,
+//"")
+//{
+//    long (*f)(long,long,long);
+//    long result;
+//    
+//    PRIMITIVE_HEADER (4);
+//    
+//    f =  arg_integer (1);
+//    result = fudge_call_3 (f, call_ff_arg(ARG_REF(2)), call_ff_arg(ARG_REF(3)), call_ff_arg(ARG_REF(4)));
+//    PRIMITIVE_RETURN (long_to_integer (result));
+//}
+
+static  SCHEME_OBJECT call_ff_really()
+{
+
+  {
+    /*  use a struct for locals that live across the foreign function call
+        so that their position in the stack is the right end of the stack
+       frame with respect to the stacked C arguments */
+    struct {
+      long c_args[50];
+      long old_esp;
+    } local;
+    
+    long result;
+
+    /*  We save the stack pointer and restore it because the called function
+        may pop the arguments (pascal/__stdcall) or expect us to (__cdecl). */
+
+    /*  The stack pointer is saved in a static variable so that we can find
+        it if the compiler does SP-relative addressing with a broken SP */
+    
+    /*  The implication is that things will break if this gets overwritten.
+        This will happen if the foreign function directly or indirectly 
+       allows a Scheme interrupt to be processed (eg by calling as scheme
+       function with interrupts enabled and that function gets rescheduled
+       in the threads package. */
+    
+    static long saved_esp;
+    
+    long nargs = (LEXPR_N_ARGUMENTS ());
+    if (nargs < 1)
+      signal_error_from_primitive (ERR_WRONG_NUMBER_OF_ARGUMENTS);
+    if (nargs > 30)
+      signal_error_from_primitive (ERR_WRONG_NUMBER_OF_ARGUMENTS);
+    {
+      long *arg_sp = &local.c_args[10];
+      SCHEME_OBJECT *argument_scan = ARG_LOC (2);
+      SCHEME_OBJECT *argument_limit = ARG_LOC (nargs+1);
+
+      long  function_address = arg_integer(1);
+
+      while (argument_scan != argument_limit)
+       *arg_sp++ = 
+         scheme_object_to_windows_object (STACK_LOCATIVE_POP(argument_scan));
+      
+      arg_sp = &local.c_args[10];
+      local.old_esp = saved_esp;
+      __asm
+      {
+       // Important: The order of these instructions guards against
+       // stack pointer relative addressing.
+       mov     eax, dword ptr [function_address]
+       mov     dword ptr [saved_esp], esp
+       mov     esp, dword ptr [arg_sp]
+       call    eax
+       mov     esp, dword ptr [saved_esp]
+       mov     dword ptr [result], eax
+      }
+      saved_esp = local.old_esp;
+      return  long_to_integer (result);
+    }
+  }
+}
+
+DEFINE_PRIMITIVE ("CALL-FF", Prim_call_ff, 0, LEXPR, 0)
+{
+    /* this indirection saves registers correctly in this stack frame
+       rather than in a bad position in relation to the bogus C argument
+       stack */
+    PRIMITIVE_HEADER (LEXPR);
+    PRIMITIVE_RETURN (call_ff_really());
+}
+
+
+\f
+static void *
+xmalloc (int size)
+{
+    void *result = malloc(size);
+    if (!result) {
+      outf_fatal ("ntgui: xmalloc failed");
+      outf_flush_fatal ();
+      abort ();
+    }
+    return  result;
+}
+
+static void
+xfree (void *p)
+{
+    free (p);
+}
diff --git a/v7/src/microcode/ntgui.h b/v7/src/microcode/ntgui.h
new file mode 100644 (file)
index 0000000..5db06d9
--- /dev/null
@@ -0,0 +1,21 @@
+
+void EXFUN (NT_gui_init, (void));
+
+#define IDM_NEW            100
+#define IDM_OPEN           101
+#define IDM_SAVE           102
+#define IDM_SAVEAS         103
+#define IDM_PRINT          104
+#define IDM_PRINTSETUP     105
+#define IDM_EXIT           106
+#define IDM_UNDO           200
+#define IDM_CUT            201
+#define IDM_COPY           202
+#define IDM_PASTE          203
+#define IDM_LINK           204
+#define IDM_LINKS          205
+#define IDM_HELPCONTENTS   300
+#define IDM_HELPSEARCH     301
+#define IDM_HELPHELP       302
+#define IDM_ABOUT          303
+#define IDM_EMERGENCYKILL  400
diff --git a/v7/src/microcode/ntscreen.c b/v7/src/microcode/ntscreen.c
new file mode 100644 (file)
index 0000000..3c42db6
--- /dev/null
@@ -0,0 +1,2082 @@
+#include <stdlib.h>
+#include "ntscreen.h"
+//#include "screen.rh"
+
+// constant definitions
+
+#define GWL_SCREEN        0
+#define SCREENEXTRABYTES        sizeof( LONG )
+
+#define ATOM_TTYINFO       0x100
+
+//#define MAXCOLS 132
+//#define MAXROWS  66
+#define MAXCOLS 80
+#define MAXROWS 40
+
+// cursor states
+
+#define CS_HIDE         0x00
+#define CS_SHOW         0x01
+
+// Flow control flags
+
+// ascii definitions
+
+#define ASCII_BEL       0x07
+#define ASCII_BS        0x08
+#define ASCII_LF        0x0A
+#define ASCII_FF       0x0C
+#define ASCII_CR        0x0D
+
+// data structures
+
+#define MAX_EVENTS 1000
+
+typedef struct tagSCREEN_EVENT_LINK {
+  SCREEN_EVENT event;
+  struct tagSCREEN_EVENT_LINK *next;
+} SCREEN_EVENT_LINK;
+
+#define MAX_COMMANDS 30
+
+#define MAX_BINDINGS 10 
+
+#define MAX_LINEINPUT 1024
+
+typedef struct tagSCREENINFO
+{
+   SCREEN  registry_link;
+   
+   HWND           hWnd;
+   
+   char              *chars;
+   SCREEN_ATTRIBUTE  *attrs;
+   WORD              mode_flags;       //events & modes
+   SCREEN_ATTRIBUTE  write_attribute;
+   
+   WORD    CursorState ;
+
+   HFONT   hFont ;
+   LOGFONT lfFont ;
+   DWORD   rgbFGColour ;
+   int     xSize, ySize, xScroll, yScroll, xOffset, yOffset;
+   int     column, row, xChar, yChar ;
+   int     width, height;  //size in characters
+
+   int n_events;
+   SCREEN_EVENT_LINK  *events;
+   SCREEN_EVENT_LINK  *free_events;
+   SCREEN_EVENT_LINK  *queue_head,  *queue_tail;
+
+   int n_commands;
+   struct {
+     WORD wID;
+     COMMAND_HANDLER  thunk;
+   } commands[MAX_COMMANDS];
+   
+   int n_bindings;
+   struct {
+     char   key;
+     WORD   command;
+   } bindings[MAX_BINDINGS];
+
+   
+   // for line input
+   int n_chars;
+   char  *line_buffer;
+} SCREEN_STRUCT;
+
+//#define WIDTH(screen) (screen->width)
+#define WIDTH(screen) MAXCOLS
+#define HEIGHT(screen) MAXROWS
+// macros ( for easier readability )
+
+#define GETHINST( x )  ((HINSTANCE) GetWindowLong( x, GWL_HINSTANCE ))
+#define GETSCREEN( x ) ((SCREEN) GetWindowLong( x, GWL_SCREEN ))
+#define SETSCREEN( x, y ) SetWindowLong( x, GWL_SCREEN, (LONG) y )
+
+
+#define SET_PROP( x, y, z )  SetProp( x, MAKEINTATOM( y ), z )
+#define GET_PROP( x, y )     GetProp( x, MAKEINTATOM( y ) )
+#define REMOVE_PROP( x, y )  RemoveProp( x, MAKEINTATOM( y ) )
+
+// CRT mappings to NT API
+
+#define _fmemset   memset
+#define _fmemmove  memmove
+
+// function prototypes (private)
+
+LRESULT CreateScreenInfo (HWND);
+BOOL DestroyScreenInfo (HWND);
+BOOL ResetScreen (SCREEN);
+BOOL KillScreenFocus (HWND);
+BOOL PaintScreen (HWND);
+BOOL SetScreenFocus (HWND);
+BOOL ScrollScreenHorz (HWND, WORD, WORD);
+BOOL ScrollScreenVert (HWND, WORD, WORD);
+BOOL SizeScreen (HWND, WORD, WORD);
+BOOL ProcessScreenCharacter (HWND, int, int, DWORD);
+BOOL WriteScreenBlock (HWND, LPSTR, int);
+int  ReadScreen (SCREEN, char*, int);
+BOOL MoveScreenCursor (SCREEN);
+BOOL Screen_SetPosition (SCREEN, int, int);
+UINT ScreenPeekOrRead (SCREEN, int count, SCREEN_EVENT* buffer, BOOL remove);
+COMMAND_HANDLER ScreenSetCommand (SCREEN, WORD cmd, COMMAND_HANDLER handler);
+WORD ScreenSetBinding (SCREEN, char key, WORD command);
+VOID GetMinMaxSizes(HWND,LPPOINT,LPPOINT);
+VOID Screen_Clear (SCREEN,int);
+VOID GoModalDialogBoxParam (HINSTANCE, LPCSTR, HWND, DLGPROC, LPARAM);
+VOID FillComboBox (HINSTANCE, HWND, int, DWORD *, WORD, DWORD);
+BOOL SelectScreenFont (SCREEN, HWND);
+BOOL SettingsDlgInit (HWND);
+BOOL SettingsDlgTerm (HWND);
+
+LRESULT ScreenCommand_ChooseFont (HWND, WORD);
+
+VOID SetDebuggingTitle (SCREEN);
+
+SCREEN_EVENT  *alloc_event (SCREEN, SCREEN_EVENT_TYPE); //may return NULL
+int  GetControlKeyState(DWORD lKeyData);
+//void *xmalloc (int size);
+//void xfree (void*);
+#define xfree free
+#define xmalloc malloc
+
+LRESULT FAR PASCAL ScreenWndProc (HWND, UINT, WPARAM, LPARAM);
+BOOL FAR PASCAL SettingsDlgProc (HWND, UINT, WPARAM, LPARAM ) ;
+
+VOID RegisterScreen (SCREEN);
+VOID UnregisterScreen (SCREEN);
+
+
+//---------------------------------------------------------------------------
+//  BOOL Screen_InitApplication (HANDLE hInstance )
+//
+//  Description:
+//     First time initialization stuff for screen class.
+//     This registers information such as window classes.
+//
+//  Parameters:
+//     HANDLE hInstance
+//        Handle to this instance of the application.
+//
+//---------------------------------------------------------------------------
+
+BOOL Screen_InitApplication (HANDLE hInstance )
+{
+   WNDCLASS  wndclass ;
+
+   wndclass.style =         0;
+   wndclass.lpfnWndProc =   ScreenWndProc ;
+   wndclass.cbClsExtra =    0;
+   wndclass.cbWndExtra =    SCREENEXTRABYTES ;
+   wndclass.hInstance =     hInstance ;
+   wndclass.hIcon =         LoadIcon (hInstance, "TERMINALICON");
+   wndclass.hCursor =       LoadCursor (NULL, IDC_ARROW);
+   wndclass.hbrBackground = (HBRUSH) (COLOR_WINDOW + 1) ;
+   wndclass.lpszMenuName =  0;
+   wndclass.lpszClassName = "SCREEN";
+
+   return  RegisterClass (&wndclass) ;
+}
+
+//---------------------------------------------------------------------------
+//  BOOL Screen_InitInstance (HANDLE hInstance, int nCmdShow )
+//
+//  Description:
+//     Initializes instance specific information for the screen class.
+//     returns TRUE on sucess.
+//
+//  Parameters:
+//     HANDLE hInstance
+//        Handle to instance
+//
+//     int nCmdShow
+//        How do we show the window?
+//---------------------------------------------------------------------------
+
+static  HANDLE  ghInstance;
+
+BOOL Screen_InitInstance (HANDLE hInstance, int nCmdShow )
+{
+    ghInstance = hInstance;
+    return  TRUE;
+}
+
+
+//---------------------------------------------------------------------------
+//  SCREEN  Screen_Create (HANDLE hParent, LPCSTR title, int nCmdShow)
+//
+//  Description:
+//     Create a screen window with a given parent.
+//
+//  Parameters:
+//     hParent
+//        Handle to parent window
+//---------------------------------------------------------------------------
+
+HANDLE  Screen_Create (HANDLE hParent, LPCSTR title, int nCmdShow)
+{
+    HWND  hWnd;
+    hWnd = CreateWindow ("SCREEN", title,
+                         WS_OVERLAPPEDWINDOW,
+                         CW_USEDEFAULT, CW_USEDEFAULT,
+                         CW_USEDEFAULT, CW_USEDEFAULT,
+                         hParent, NULL, ghInstance, (LPVOID)nCmdShow);
+
+    if (NULL == hWnd)
+        return  NULL;
+
+    return  hWnd;
+}
+
+
+//---------------------------------------------------------------------------
+//  Registry of screen handles
+//---------------------------------------------------------------------------
+
+static SCREEN registered_screens = 0;
+
+static VOID RegisterScreen (SCREEN screen)
+{
+    screen->registry_link = registered_screens;
+    registered_screens = screen;
+}
+
+static SCREEN *head_to_registered_screen (HWND hWnd)
+{
+    SCREEN *link = &registered_screens;
+    while (*link)
+      if ((*link)->hWnd == hWnd)
+       return link;
+      else
+       link = &((*link)->registry_link);
+    return  0;
+}
+
+static VOID UnregisterScreen (SCREEN screen)
+{
+    SCREEN *link = head_to_registered_screen (screen->hWnd);
+//  if (link)
+      *link = screen->registry_link;
+}
+
+BOOL Screen_IsScreenHandle (HANDLE handle)
+{
+    return  head_to_registered_screen (handle) != 0;
+}
+
+//---------------------------------------------------------------------------
+//  LRESULT FAR PASCAL ScreenWndProc (HWND hWnd, UINT uMsg,
+//                                 WPARAM wParam, LPARAM lParam )
+//
+//  Description:
+//     This is the TTY Window Proc.  This handles ALL messages
+//     to the tty window.
+//
+//  Parameters:
+//     As documented for Window procedures.
+//
+//  Win-32 Porting Issues:
+//     - WM_HSCROLL and WM_VSCROLL packing is different under Win-32.
+//     - Needed LOWORD() of wParam for WM_CHAR messages.
+//
+//---------------------------------------------------------------------------
+
+LRESULT FAR PASCAL ScreenWndProc (HWND hWnd, UINT uMsg,
+                               WPARAM wParam, LPARAM lParam )
+{
+   SCREEN  screen = GETSCREEN (hWnd);
+
+   static  BOOL                vk_pending = FALSE;
+   static  int         vk_code;
+   static  LPARAM      vk_lparam;
+   
+   switch (uMsg)
+   {
+      case WM_CREATE:
+      {
+        LRESULT result = CreateScreenInfo (hWnd);
+        ShowWindow (hWnd, (int) ((LPCREATESTRUCT)lParam)->lpCreateParams);
+        UpdateWindow (hWnd);
+        return  result;
+      }
+
+
+
+      case SCREEN_SETPOSITION:
+        return  (LRESULT)Screen_SetPosition
+                              (screen, HIWORD(lParam), LOWORD(lParam));
+
+      case SCREEN_GETPOSITION:
+        return  MAKELRESULT(screen->column, screen->row);
+
+      case SCREEN_SETATTRIBUTE:
+        screen->write_attribute = (SCREEN_ATTRIBUTE) wParam;
+        return  0;
+        
+      case SCREEN_GETATTRIBUTE:
+        return  (LRESULT) screen->write_attribute;
+
+      case SCREEN_SETMODES:
+        screen->mode_flags = (WORD) wParam;
+        return  0;
+        
+      case SCREEN_GETMODES:
+        return  (LRESULT) screen->mode_flags;
+
+      case SCREEN_SETCOMMAND:
+        return  (LRESULT)
+          ScreenSetCommand(screen, LOWORD(wParam), (COMMAND_HANDLER)lParam);
+        
+      case SCREEN_GETCOMMAND:
+        return  (LRESULT)
+          ScreenSetCommand(screen, LOWORD(wParam), (COMMAND_HANDLER)-1);
+
+      case SCREEN_SETBINDING:
+        return  (LRESULT)
+          ScreenSetBinding(screen, LOBYTE(wParam), (WORD)lParam);
+        
+      case SCREEN_GETBINDING:
+        return  (LRESULT)
+          ScreenSetBinding(screen, LOBYTE(wParam), (WORD)-1);
+
+      case SCREEN_PEEKEVENT:
+        return  (LRESULT)
+          ScreenPeekOrRead(screen, (int)wParam, (SCREEN_EVENT*)lParam, FALSE);
+        
+      case SCREEN_READEVENT:
+        return  (LRESULT)
+          ScreenPeekOrRead(screen, (int)wParam, (SCREEN_EVENT*)lParam, TRUE);
+
+      case SCREEN_WRITE:
+        return  (LRESULT)WriteScreenBlock (hWnd, (LPSTR)lParam, (int)wParam);
+
+      case SCREEN_READ:
+        return  (LRESULT)ReadScreen (screen, (LPSTR)lParam, (int)wParam);
+        
+      case SCREEN_SETMENU:
+        Screen_SetMenu (hWnd, (HMENU)lParam);
+        return  0L;
+
+      case SCREEN_CLEAR:
+        Screen_Clear (screen, (int)wParam);
+        return  0L;
+        
+      case WM_COMMAND:
+      case WM_SYSCOMMAND:
+      {
+        WORD  wID = LOWORD (wParam);
+        int  i;
+        for (i=0;  i<screen->n_commands; i++)
+          if (screen->commands[i].wID == wID)
+            return  screen->commands[i].thunk(hWnd, wID);
+        return  DefWindowProc (hWnd, uMsg, wParam, lParam);
+        //return  DefWindowProc (hWnd, wID>=0xf000?WM_SYSCOMMAND:WM_COMMAND,
+        //                       wParam, lParam);
+      }
+      break ;
+
+      case WM_GETMINMAXINFO:
+      {
+        LPMINMAXINFO info = (LPMINMAXINFO) lParam;
+        GetMinMaxSizes (hWnd, &info->ptMinTrackSize, &info->ptMaxTrackSize);
+        return  0;
+      }
+      
+      case WM_PAINT:
+         PaintScreen (hWnd);
+         break ;
+
+      case WM_SIZE:
+      {
+        if (wParam!=SIZE_MINIMIZED)
+           SizeScreen (hWnd, HIWORD(lParam), LOWORD(lParam));
+      }
+      break ;
+
+      case WM_HSCROLL:
+         ScrollScreenHorz (hWnd, LOWORD(wParam), HIWORD(wParam));
+         break ;
+
+      case WM_VSCROLL:
+         ScrollScreenVert (hWnd, LOWORD(wParam), HIWORD(wParam));
+         break ;
+
+       
+      case WM_KEYDOWN:
+        if (vk_pending)
+          ProcessScreenCharacter (hWnd, vk_code, 0, vk_lparam);
+        vk_pending = TRUE;
+        vk_code    = wParam;
+        vk_lparam  = lParam;
+        return  DefWindowProc (hWnd, uMsg, wParam, lParam);
+        
+      case WM_KEYUP:
+        if (vk_pending)
+          ProcessScreenCharacter (hWnd, vk_code, 0, vk_lparam);
+        vk_pending = FALSE;
+        return  DefWindowProc (hWnd, uMsg, wParam, lParam);
+
+      case WM_DEADCHAR:
+        vk_pending = FALSE;
+        return  DefWindowProc (hWnd, uMsg, wParam, lParam);
+        
+      case WM_CHAR:
+         ProcessScreenCharacter (hWnd,
+                  vk_code, LOBYTE(LOWORD(wParam)), (DWORD)lParam);
+         vk_pending = FALSE;
+         break ;
+
+      case WM_SETFOCUS:
+         SetScreenFocus (hWnd);
+         break ;
+
+      case WM_KILLFOCUS:
+         KillScreenFocus (hWnd);
+         break ;
+
+      case WM_DESTROY:
+         DestroyScreenInfo (hWnd);
+         break ;
+
+      case WM_CLOSE:
+         if (IDOK != MessageBox (hWnd, "OK to close screen window?",
+                                "Screen Sample",
+                                 MB_ICONQUESTION | MB_OKCANCEL ))
+            break ;
+
+         // fall through
+
+      default:
+         return  DefWindowProc (hWnd, uMsg, wParam, lParam);
+   }
+   return 0L ;
+
+} 
+
+//---------------------------------------------------------------------------
+//  LRESULT CreateScreenInfo (HWND hWnd)
+//
+//  Description:
+//     Creates the tty information structure and sets
+//     menu option availability.  Returns -1 if unsuccessful.
+//
+//  Parameters:
+//     HWND  hWnd
+//
+//---------------------------------------------------------------------------
+
+static void ClearScreen_internal (SCREEN screen)
+{
+   screen->row                 = 0 ;
+   screen->column              = 0 ;
+   _fmemset (screen->chars, ' ', MAXROWS * MAXCOLS);
+   _fmemset (screen->attrs, screen->write_attribute,   MAXROWS * MAXCOLS * sizeof(SCREEN_ATTRIBUTE));}
+   
+static LRESULT CreateScreenInfo (HWND hWnd)
+{
+   HMENU   hMenu;
+   int     i;
+   SCREEN  screen;
+
+   if (NULL == (screen =
+                   (SCREEN) LocalAlloc (LPTR, sizeof(SCREEN_STRUCT) )))
+      return  (LRESULT) -1;
+
+   screen->hWnd                        = hWnd;
+   screen->chars               = NULL;
+   screen->attrs               = NULL;
+   screen->write_attribute     = 0;
+   screen->CursorState         = CS_HIDE ;
+   screen->mode_flags          = SCREEN_EVENT_TYPE_KEY
+                                | SCREEN_EVENT_TYPE_MOUSE
+                               | SCREEN_EVENT_TYPE_RESIZE
+                                | SCREEN_MODE_ECHO
+                            // | SCREEN_MODE_NEWLINE
+                               | SCREEN_MODE_AUTOWRAP
+                               | SCREEN_MODE_PROCESS_OUTPUT
+                               | SCREEN_MODE_LINE_INPUT
+                            // | SCREEN_MODE_LAZY_UPDATE
+                               ;
+   screen->xSize               = 0;
+   screen->ySize               = 0 ;
+   screen->xScroll             = 0 ;
+   screen->yScroll             = 0 ;
+   screen->xOffset             = 0 ;
+   screen->yOffset             = 0 ;
+   screen->hFont               = NULL;
+   screen->rgbFGColour         = RGB(0,0,0);
+   screen->width               = 0;
+   screen->height              = 0;
+      
+   screen->chars = xmalloc (MAXROWS * MAXCOLS);
+   screen->attrs = xmalloc (MAXROWS * MAXCOLS * sizeof(SCREEN_ATTRIBUTE));
+
+   ClearScreen_internal (screen);
+   // clear screen space
+
+   // setup default font information
+
+   screen->lfFont.lfHeight =         9 ;
+   screen->lfFont.lfWidth =          0 ;
+   screen->lfFont.lfEscapement =     0 ;
+   screen->lfFont.lfOrientation =    0 ;
+   screen->lfFont.lfWeight =         0 ;
+   screen->lfFont.lfItalic =         0 ;
+   screen->lfFont.lfUnderline =      0 ;
+   screen->lfFont.lfStrikeOut =      0 ;
+   screen->lfFont.lfCharSet =        OEM_CHARSET ;
+   screen->lfFont.lfOutPrecision =   OUT_DEFAULT_PRECIS ;
+   screen->lfFont.lfClipPrecision =  CLIP_DEFAULT_PRECIS ;
+   screen->lfFont.lfQuality =        DEFAULT_QUALITY ;
+   screen->lfFont.lfPitchAndFamily = FIXED_PITCH | FF_MODERN ;
+   lstrcpy (screen->lfFont.lfFaceName, "FixedSys");
+
+   // set handle before any further message processing.
+
+   SETSCREEN (hWnd, screen);
+   RegisterScreen (screen);
+
+   screen->n_events = 0;
+   screen->queue_head = screen->queue_tail = 0;
+   screen->events = xmalloc (sizeof(SCREEN_EVENT_LINK) * MAX_EVENTS);
+   screen->free_events = &screen->events[0];
+   for (i = 0; i<MAX_EVENTS; i++)
+     screen->events[i].next = &screen->events[i+1];
+   screen->events[MAX_EVENTS-1].next = 0;
+   screen->n_commands = 0;
+   screen->n_bindings = 0;
+   // reset the character information, etc.
+
+   ResetScreen (screen);
+
+   hMenu = GetSystemMenu (hWnd, FALSE);
+   AppendMenu (hMenu, MF_SEPARATOR, 0, 0);
+// AppendMenu (hMenu, MF_STRING, IDM_SETTINGS, "&Settings...");
+   AppendMenu (hMenu, MF_STRING, SCREEN_COMMAND_CHOOSEFONT,     "&Font...");
+    
+   SendMessage (hWnd, SCREEN_SETCOMMAND,
+                SCREEN_COMMAND_CHOOSEFONT, (LPARAM)ScreenCommand_ChooseFont);
+   SendMessage (hWnd, SCREEN_SETBINDING, 6, SCREEN_COMMAND_CHOOSEFONT);
+                 
+   screen->n_chars = 0;
+   screen->line_buffer = xmalloc (MAX_LINEINPUT+1);
+     
+   return  (LRESULT) TRUE;
+}
+
+//---------------------------------------------------------------------------
+//---------------------------------------------------------------------------
+
+VOID SetDebuggingTitle (SCREEN screen)
+{
+    char buf[80];
+    return;
+    wsprintf (buf, "%d@%d  q=%d  c=%d  b=%d",
+        screen->row, screen->column,
+       screen->n_events,
+       screen->n_commands,
+       screen->n_bindings,
+         0);
+    SendMessage (screen->hWnd, WM_SETTEXT, 0, (LPARAM) buf);
+}
+
+//---------------------------------------------------------------------------
+//  BOOL DestroyScreenInfo (HWND hWnd )
+//
+//  Description:
+//     Destroys block associated with TTY window handle.
+//
+//  Parameters:
+//     HWND hWnd
+//        handle to TTY window
+//
+//---------------------------------------------------------------------------
+
+static BOOL DestroyScreenInfo (HWND hWnd)
+{
+   SCREEN  screen = GETSCREEN (hWnd);
+
+   if (NULL == screen)
+      return  FALSE;
+
+   KillScreenFocus (hWnd);
+
+   UnregisterScreen (screen);
+
+   DeleteObject (screen->hFont);
+
+   if (screen->chars)   xfree (screen->chars);
+   if (screen->attrs)   xfree (screen->attrs);
+   if (screen->events) xfree (screen->events);
+   LocalFree (screen);
+   return  TRUE;
+}
+
+//---------------------------------------------------------------------------
+//  COMMAND_HANDLER  ScreenSetCommand (SCREEN, WORD cmd, COMMAND_HANDLER h)
+//---------------------------------------------------------------------------
+
+static COMMAND_HANDLER
+ScreenSetCommand (SCREEN screen, WORD cmd, COMMAND_HANDLER thunk)
+{
+    int i;
+    for (i = 0;  i<screen->n_commands;  i++)
+      if (screen->commands[i].wID == cmd) {
+       COMMAND_HANDLER  result = screen->commands[i].thunk;
+       if (thunk==0) { // remove by overwriting with last in list
+         screen->commands[i] = screen->commands[screen->n_commands-1];
+         screen->n_commands--;
+       } else if (thunk==(COMMAND_HANDLER)-1) {// just leave it alone
+       } else {        // redefine
+         screen->commands[i].thunk = thunk;
+        }
+       return  result;
+      }
+      
+    // didnt find it
+    if (thunk==0 || thunk==(COMMAND_HANDLER)-1)
+      return  0;
+    // add new command
+    if (screen->n_commands == MAX_COMMANDS)
+      return (COMMAND_HANDLER)-1;
+
+    screen->commands[screen->n_commands].wID   = cmd;
+    screen->commands[screen->n_commands].thunk = thunk;
+    screen->n_commands++;
+    
+    return  0;
+}
+
+//---------------------------------------------------------------------------
+//  WORD  ScreenSetBinding (SCREEN, char key, WORD command)
+//---------------------------------------------------------------------------
+
+static WORD  ScreenSetBinding (SCREEN screen, char key, WORD command)
+{
+    int i;
+    for (i=0;  i<screen->n_bindings;  i++)
+      if (screen->bindings[i].key == key) {
+       WORD  result = screen->bindings[i].command;
+       if (command==0) { // remove by blatting with last in list
+         screen->bindings[i] = screen->bindings[screen->n_bindings-1];
+         screen->n_bindings--;
+       } else if (command==(WORD)-1) { //let it be
+       } else { // redefine
+         screen->bindings[i].command = command;
+        }
+       return  result;
+      }
+      
+    // no existing binding for key
+    if (command==0 || command==(WORD)-1)
+      return 0;
+    // add new binding
+    if (screen->n_bindings == MAX_BINDINGS)
+      return  (WORD)-1;
+
+    screen->bindings[screen->n_bindings].key     = key;
+    screen->bindings[screen->n_bindings].command = command;
+    screen->n_bindings++;
+    
+    return  0;
+}
+
+//===========================================================================
+//  Standard commands
+//===========================================================================
+
+LRESULT  ScreenCommand_ChooseFont (HWND hWnd, WORD command)
+{
+    SCREEN  screen = GETSCREEN (hWnd);
+      if (screen == 0)
+       return  1L;
+    SelectScreenFont (screen, hWnd);
+    return  0L;
+}
+
+//---------------------------------------------------------------------------
+//  Screen_SetMenu (SCREEN, HMENU)
+//---------------------------------------------------------------------------
+
+VOID Screen_SetMenu (SCREEN screen, HMENU hMenu)
+{
+    HMENU hOld = GetMenu (screen->hWnd);
+    SetMenu (screen->hWnd, hMenu);
+    if (hOld)
+      DestroyMenu (hOld);
+}
+//---------------------------------------------------------------------------
+//  BOOL ResetScreen (SCREEN  screen)
+//
+//  Description:
+//     Resets the TTY character information and causes the
+//     screen to resize to update the scroll information.
+//
+//  Parameters:
+//     NPTTYINFO  npTTYInfo
+//        pointer to TTY info structure
+//
+//---------------------------------------------------------------------------
+
+static BOOL ResetScreen (SCREEN screen)
+{
+   HWND               hWnd;
+   HDC         hDC ;
+   TEXTMETRIC  tm ;
+   RECT        rcWindow ;
+   
+   if (NULL == screen)
+      return  FALSE;
+
+   hWnd = screen->hWnd;
+   
+   if (screen->hFont)
+      DeleteObject (screen->hFont);
+
+   screen->hFont = CreateFontIndirect (&screen->lfFont);
+
+   hDC = GetDC (hWnd);
+   SelectObject (hDC, screen->hFont);
+   GetTextMetrics (hDC, &tm);
+   ReleaseDC (hWnd, hDC);
+
+   screen->xChar = tm.tmAveCharWidth  ;
+   screen->yChar = tm.tmHeight + tm.tmExternalLeading ;
+
+   // a slimy hack to make the caret the correct size, un- and re- focus
+   if (screen->CursorState == CS_SHOW) {
+     KillScreenFocus (hWnd);
+     SetScreenFocus(hWnd);
+   }
+   // a slimy hack to force the scroll position, region to
+   // be recalculated based on the new character sizes
+   {
+     int width, height;
+     POINT minsz, maxsz;
+     GetWindowRect (hWnd, &rcWindow);
+     GetMinMaxSizes (hWnd, &minsz, &maxsz);
+     width  = rcWindow.right - rcWindow.left;
+     height = rcWindow.bottom - rcWindow.top
+            - GetSystemMetrics(SM_CYCAPTION)
+           - GetSystemMetrics(SM_CYFRAME)
+            - (GetMenu(hWnd) ? GetSystemMetrics(SM_CYMENU) : 0)
+           ;
+     if (width<minsz.x || width>maxsz.x || height<minsz.y || height>maxsz.y)
+       MoveWindow (hWnd, rcWindow.left, rcWindow.top,
+                  min(maxsz.x,max(minsz.x,width)),
+                  min(maxsz.y,max(minsz.y,height)), TRUE);
+     else
+     SendMessage (hWnd, WM_SIZE, SIZENORMAL, (LPARAM) MAKELONG(width,height));
+   }
+
+   return  TRUE;
+}
+
+//---------------------------------------------------------------------------
+//  BOOL PaintScreen (HWND hWnd )
+//
+//  Description:
+//     Paints the rectangle determined by the paint struct of
+//     the DC.
+//
+//  Parameters:
+//     HWND hWnd
+//        handle to TTY window (as always)
+//
+//---------------------------------------------------------------------------
+
+static BOOL PaintScreen (HWND hWnd)
+{
+   SCREEN      screen = GETSCREEN (hWnd);
+   HDC          hDC ;
+   PAINTSTRUCT  ps ;
+   RECT         rect ;
+
+   if (NULL == screen)  return  FALSE;
+
+   hDC = BeginPaint (hWnd, &ps);
+
+   if (IsIconic(hWnd)) {
+//      // draw a minature version of the window
+//      int  ICONSIZE = 36;
+//      int  row, col;
+//      HPEN hOldPen, hPen, hPen2;
+//
+//      hPen = CreatePen (PS_SOLID, 0,
+//                     /* average of two RGB colours */
+//                     ((GetSysColor (COLOR_ACTIVEBORDER)&0xfefefeL) >> 1) +
+//                     ((GetSysColor (COLOR_WINDOWFRAME)&0xfefefeL)  >> 1));
+//      hOldPen = SelectObject (hDC, hPen);
+//      MoveToEx (hDC, 0, 0, NULL);
+//      LineTo (hDC,0,ICONSIZE-1); LineTo (hDC,ICONSIZE-1,ICONSIZE-1);
+//      LineTo (hDC,ICONSIZE-1,0); LineTo (hDC,0,0);
+//      //Rectangle (hDC, 0, 0, ICONSIZE, ICONSIZE);
+//      hPen2 = CreatePen (PS_SOLID, 0, GetSysColor (COLOR_ACTIVECAPTION));
+//      SelectObject (hDC, hPen2);
+//      DeleteObject (hPen);
+//      MoveToEx (hDC, 1, 1, NULL);  LineTo (hDC, ICONSIZE-1, 1);
+//      MoveToEx (hDC, 1, 2, NULL);  LineTo (hDC, ICONSIZE-1, 2);
+//      MoveToEx (hDC, 1, 3, NULL);  LineTo (hDC, ICONSIZE-1, 3);
+//
+//      hPen = CreatePen (PS_SOLID, 0, screen->rgbFGColour);
+//      SelectObject (hDC, hPen);
+//      DeleteObject (hPen2);
+//      SetBkColor (hDC, GetSysColor (COLOR_WINDOW));
+//      rect = ps.rcPaint ;
+//      for (row = 0; row < (ICONSIZE-6)/2; row++) {
+//     if (row >= screen->height) break;
+//     for (col = 0; col < ICONSIZE-4; col++) {
+//       int  run_length = 0;
+//       char *s = & screen->chars[row*WIDTH(screen) + col];
+//       while (col+run_length < ICONSIZE-4 && s[run_length] != ' ')
+//         run_length++;
+//       if (run_length>0) {
+//          int x = col+2;
+//          int y = row*2+5;
+//          MoveToEx (hDC, x, y, NULL);
+//          LineTo (hDC, x+run_length, y);
+//       }
+//     }
+//      }
+//      SelectObject (hDC, hOldPen);
+//      DeleteObject (hPen);
+   } else {
+      int          nRow, nCol, nEndRow, nEndCol, nCount, nHorzPos, nVertPos ;
+      HFONT        hOldFont ;
+
+      hOldFont = SelectObject (hDC, screen->hFont);
+      SetTextColor (hDC, screen->rgbFGColour);
+      SetBkColor (hDC, GetSysColor (COLOR_WINDOW));
+      rect = ps.rcPaint ;
+
+//   nRow =
+//      min (MAXROWS - 1,
+//           max (0, (rect.top + screen->yOffset) / screen->yChar ));
+//   nEndRow =
+//      min (MAXROWS - 1,
+//           ((rect.bottom + screen->yOffset - 1) / screen->yChar ));
+      nRow =
+         min (screen->height - 1,
+              max (0, (rect.top + screen->yOffset) / screen->yChar ));
+      nEndRow =
+         min (screen->height - 1,
+              ((rect.bottom + screen->yOffset - 1) / screen->yChar ));
+//   nCol =
+//      min (MAXCOLS - 1,
+//           max (0, (rect.left + screen->xOffset) / screen->xChar ));
+//   nEndCol =
+//      min (MAXCOLS - 1,
+//           ((rect.right + screen->xOffset - 1) / screen->xChar ));
+      nCol =
+         min (screen->width - 1,
+              max (0, (rect.left + screen->xOffset) / screen->xChar ));
+      nEndCol =
+         min (screen->width - 1,
+              ((rect.right + screen->xOffset - 1) / screen->xChar ));
+      nCount = nEndCol - nCol + 1 ;
+      for (; nRow <= nEndRow; nRow++)
+      {
+         int   pos = 0;
+         while (pos < nCount)
+         {
+           // find consistent run of attributes
+           int bias = nRow*MAXCOLS + nCol;
+           SCREEN_ATTRIBUTE attrib = screen->attrs[bias + pos];
+           int  run_length = 1;
+           while (run_length+pos<nCount &&
+                  screen->attrs[bias + pos + run_length]==attrib)
+               run_length++;
+
+           nVertPos = (nRow * screen->yChar) - screen->yOffset;
+           nHorzPos = ((nCol + pos) * screen->xChar) - screen->xOffset;
+           rect.top = nVertPos ;
+           rect.bottom = nVertPos + screen->yChar;
+           rect.left = nHorzPos;
+           rect.right = nHorzPos + screen->xChar * run_length ;
+           SetBkMode (hDC, OPAQUE);
+           if (attrib)
+           {
+              SetTextColor (hDC, GetSysColor (COLOR_WINDOW));
+              SetBkColor (hDC, screen->rgbFGColour);
+           } else {
+              SetTextColor (hDC, screen->rgbFGColour);
+              SetBkColor (hDC, GetSysColor (COLOR_WINDOW));
+           }
+           ExtTextOut(hDC, nHorzPos, nVertPos, ETO_OPAQUE|ETO_CLIPPED, &rect,
+                      screen->chars + bias + pos,
+                      run_length, NULL);
+           pos += run_length;
+         }
+      }
+      SelectObject (hDC, hOldFont);
+   }
+   EndPaint (hWnd, &ps);
+   MoveScreenCursor(screen);
+   return  TRUE;
+
+}
+
+//---------------------------------------------------------------------------
+//  void SetCells (screen,r,col,count,char,attr)
+//
+//---------------------------------------------------------------------------
+
+static void SetCells (SCREEN screen, int row, int col, int count,
+                      char ch, SCREEN_ATTRIBUTE attr)
+{
+    int  address1 = row * MAXCOLS + col;
+    int  address2 = address1 + count;
+    int  i;
+    for (i = address1;  i<address2;  i++) {
+      screen->chars[i] = ch;
+      screen->attrs[i] = attr;
+    }
+}
+
+//---------------------------------------------------------------------------
+//  void ScrollScreenBufferUp (SCREEN  screen,  int count)
+//---------------------------------------------------------------------------
+
+static void ScrollScreenBufferUp (SCREEN  screen,  int count)
+{
+    //int  total_rows = MAXROWS;
+    int  total_rows = screen->height;
+    int  rows_copied = max (total_rows - count, 0);
+    count = min (count, total_rows);
+
+    _fmemmove ((LPSTR) (screen->chars),
+               (LPSTR) (screen->chars + count * MAXCOLS),
+              rows_copied * MAXCOLS);
+    _fmemmove ((LPSTR) (screen->attrs),
+               (LPSTR) (screen->attrs + count * MAXCOLS),
+              rows_copied * MAXCOLS);
+    _fmemset ((LPSTR)(screen->chars + rows_copied * MAXCOLS),
+               ' ', count*MAXCOLS);
+    _fmemset ((LPSTR)(screen->attrs + rows_copied * MAXCOLS),
+              screen->write_attribute, count*MAXCOLS);
+}
+
+//---------------------------------------------------------------------------
+//  BOOL SizeScreen (HWND hWnd, WORD wVertSize, WORD wHorzSize )
+//
+//  Description:
+//     Sizes TTY and sets up scrolling regions.
+//
+//---------------------------------------------------------------------------
+
+static BOOL SizeScreen (HWND hWnd, WORD wVertSize, WORD wHorzSize )
+{
+   //int        nScrollAmt ;
+   SCREEN     screen = GETSCREEN (hWnd);
+   int old_width, old_height;
+   int new_width, new_height;
+   
+   if (NULL == screen)
+      return  FALSE;
+
+//   if (GetMenu(hWnd)) wVertSize -= GetSystemMetrics(SM_CYMENU);
+   old_width  = screen->width;
+   old_height = screen->height;
+   new_width  = min (wHorzSize / screen->xChar, MAXCOLS);
+   new_height = min (wVertSize / screen->yChar, MAXROWS);
+
+   screen->width  = new_width;
+   screen->height = new_height;
+
+   { // queue event
+     SCREEN_EVENT  *event = alloc_event (screen, SCREEN_EVENT_TYPE_RESIZE);
+//     char buf[80];
+     if (event) {
+       event->event.resize.rows    = new_height;
+       event->event.resize.columns = new_width;
+//       wsprintf (buf, "[Resize %dx%d]", new_height, new_width);
+//       Screen_WriteText (screen->hWnd, buf);
+     }
+   }
+
+   // Clear out revealed character cells
+   if (new_width > old_width) {
+     int  row, rows = min (old_height, new_height);
+     for (row = 0; row < rows; row++)
+       SetCells (screen, row, old_width, new_width-old_width, ' ', 0);
+   }
+   if (new_height > old_height) {
+     int  row;
+     for (row = old_height; row < new_height; row++)
+       SetCells (screen, row, 0, new_width, ' ', 0);
+   }
+
+   // scroll window to fit in cursor
+   if (screen->column >= new_width) {
+     screen->column = 0;
+     screen->row += 1;
+   }
+   if (screen->row >= new_height) {
+     int  difference = screen->row - (new_height-1);
+     ScrollScreenBufferUp (screen, difference);
+     screen->row -= difference;
+     MoveScreenCursor (screen);
+   }
+   
+   screen->ySize = (int) wVertSize ;
+   screen->yScroll = max (0, (MAXROWS * screen->yChar) -
+                               screen->ySize);
+   screen->yScroll = 0;
+//   nScrollAmt = min (screen->yScroll, screen->yOffset ) -
+//                     screen->yOffset;
+//   ScrollWindow (hWnd, 0, -nScrollAmt, NULL, NULL);
+//   screen->yOffset = screen->yOffset + nScrollAmt ;
+//   SetScrollPos (hWnd, SB_VERT, screen->yOffset, FALSE);
+   SetScrollRange (hWnd, SB_VERT, 0, screen->yScroll, TRUE);
+
+   screen->xSize = (int) wHorzSize ;
+   screen->xScroll = max (0, (MAXCOLS * screen->xChar) -
+                                screen->xSize);
+   screen->xScroll = 0;                             
+//   nScrollAmt = min (screen->xScroll, screen->xOffset) -
+//                     screen->xOffset;
+//   ScrollWindow (hWnd, 0, -nScrollAmt, NULL, NULL);
+//   screen->xOffset = screen->xOffset + nScrollAmt ;
+//   SetScrollPos (hWnd, SB_HORZ, screen->xOffset, FALSE);
+   SetScrollRange (hWnd, SB_HORZ, 0, screen->xScroll, TRUE);
+
+   InvalidateRect (hWnd, NULL, TRUE);
+
+   return  TRUE;
+
+} // end of SizeTTY()
+
+//---------------------------------------------------------------------------
+//  BOOL ScrollScreenVert (HWND hWnd, WORD wScrollCmd, WORD wScrollPos )
+//
+//  Description:
+//     Scrolls TTY window vertically.
+//
+//  Parameters:
+//     HWND hWnd
+//        handle to TTY window
+//
+//     WORD wScrollCmd
+//        type of scrolling we're doing
+//
+//     WORD wScrollPos
+//        scroll position
+//
+//---------------------------------------------------------------------------
+
+static BOOL ScrollScreenVert (HWND hWnd, WORD wScrollCmd, WORD wScrollPos)
+{
+   int        nScrollAmt ;
+   SCREEN     screen = GETSCREEN (hWnd);
+
+   if (NULL == screen)
+      return  FALSE;
+
+   switch (wScrollCmd)
+   {
+      case SB_TOP:
+         nScrollAmt = -screen->yOffset;
+         break ;
+
+      case SB_BOTTOM:
+         nScrollAmt = screen->yScroll - screen->yOffset;
+         break ;
+
+      case SB_PAGEUP:
+         nScrollAmt = -screen->ySize;
+         break ;
+
+      case SB_PAGEDOWN:
+         nScrollAmt = screen->ySize;
+         break ;
+
+      case SB_LINEUP:
+         nScrollAmt = -screen->yChar;
+         break ;
+
+      case SB_LINEDOWN:
+         nScrollAmt = screen->yChar;
+         break ;
+
+      case SB_THUMBPOSITION:
+         nScrollAmt = wScrollPos - screen->yOffset;
+         break ;
+
+      default:
+         return  FALSE;
+   }
+   if ((screen->yOffset + nScrollAmt) > screen->yScroll)
+      nScrollAmt = screen->yScroll - screen->yOffset;
+   if ((screen->yOffset + nScrollAmt) < 0)
+      nScrollAmt = -screen->yOffset;
+   ScrollWindow (hWnd, 0, -nScrollAmt, NULL, NULL);
+   screen->yOffset = screen->yOffset + nScrollAmt ;
+   SetScrollPos (hWnd, SB_VERT, screen->yOffset, TRUE);
+
+   return  TRUE;
+}
+
+//---------------------------------------------------------------------------
+//  BOOL ScrollScreenHorz (HWND hWnd, WORD wScrollCmd, WORD wScrollPos )
+//
+//  Description:
+//     Scrolls TTY window horizontally.
+//
+//  Parameters:
+//     HWND hWnd
+//        handle to TTY window
+//
+//     WORD wScrollCmd
+//        type of scrolling we're doing
+//
+//     WORD wScrollPos
+//        scroll position
+//
+//---------------------------------------------------------------------------
+
+static BOOL ScrollScreenHorz (HWND hWnd, WORD wScrollCmd, WORD wScrollPos)
+{
+   int        nScrollAmt ;
+   SCREEN     screen = GETSCREEN (hWnd);
+
+   if (NULL == screen)
+      return  FALSE;
+
+   switch (wScrollCmd)
+   {
+      case SB_TOP:
+         nScrollAmt = -screen->xOffset;
+         break ;
+
+      case SB_BOTTOM:
+         nScrollAmt = screen->xScroll - screen->xOffset;
+         break ;
+
+      case SB_PAGEUP:
+         nScrollAmt = -screen->xSize;
+         break ;
+
+      case SB_PAGEDOWN:
+         nScrollAmt = screen->xSize;
+         break ;
+
+      case SB_LINEUP:
+         nScrollAmt = -screen->xChar;
+         break ;
+
+      case SB_LINEDOWN:
+         nScrollAmt = screen->xChar;
+         break ;
+
+      case SB_THUMBPOSITION:
+         nScrollAmt = wScrollPos - screen->xOffset;
+         break ;
+
+      default:
+         return  FALSE;
+   }
+   if ((screen->xOffset + nScrollAmt) > screen->xScroll)
+      nScrollAmt = screen->xScroll - screen->xOffset;
+   if ((screen->xOffset + nScrollAmt) < 0)
+      nScrollAmt = -screen->xOffset;
+   ScrollWindow (hWnd, -nScrollAmt, 0, NULL, NULL);
+   screen->xOffset = screen->xOffset + nScrollAmt ;
+   SetScrollPos (hWnd, SB_HORZ, screen->xOffset, TRUE);
+
+   return  TRUE;
+
+}
+
+//---------------------------------------------------------------------------
+//  BOOL SetScreenFocus (HWND hWnd )
+//
+//  Description:
+//     Sets the focus to the TTY window also creates caret.
+//
+//  Parameters:
+//     HWND hWnd
+//        handle to TTY window
+//
+//---------------------------------------------------------------------------
+
+static BOOL SetScreenFocus (HWND hWnd)
+{
+   SCREEN  screen = GETSCREEN (hWnd);
+
+   if (NULL == screen)  return  FALSE;
+
+   if (screen->CursorState != CS_SHOW)
+   {
+      CreateCaret (hWnd, NULL, max(screen->xChar/4,2), screen->yChar);
+      ShowCaret (hWnd);
+      screen->CursorState = CS_SHOW ;
+   }
+   MoveScreenCursor (screen);
+   return  TRUE ;
+
+}
+
+//---------------------------------------------------------------------------
+//  BOOL KillScreenFocus (HWND hWnd )
+//
+//  Description:
+//     Kills TTY focus and destroys the caret.
+//
+//  Parameters:
+//     HWND hWnd
+//        handle to TTY window
+//
+//---------------------------------------------------------------------------
+
+BOOL KillScreenFocus (HWND hWnd )
+{
+   SCREEN  screen = GETSCREEN (hWnd);
+
+   if (NULL == screen)  return  FALSE;
+
+   if (screen->CursorState != CS_HIDE)
+   {
+      HideCaret (hWnd);
+      DestroyCaret ();
+      screen->CursorState = CS_HIDE;
+   }
+   return  TRUE;
+
+}
+
+//---------------------------------------------------------------------------
+//  BOOL MoveScreenCursor (SCREEN screen)
+//
+//  Description:
+//     Moves caret to current position.
+//---------------------------------------------------------------------------
+
+static BOOL MoveScreenCursor (SCREEN screen)
+{
+   if (screen->CursorState & CS_SHOW)
+      SetCaretPos (screen->column * screen->xChar  -  screen->xOffset,
+                  screen->row    * screen->yChar  -  screen->yOffset);
+
+   SetDebuggingTitle (screen);          
+                
+   return  TRUE;
+}
+
+
+//---------------------------------------------------------------------------
+//  BOOL Screen_SetPosition (SCREEN, int row, int column);
+//
+//---------------------------------------------------------------------------
+
+static BOOL Screen_SetPosition (SCREEN screen, int row, int column)
+{
+   if (row < 0    || row >= screen->height)   return  FALSE;
+   if (column < 0 || column > screen->width)  return  FALSE;   //may be ==
+   screen->row    = row;
+   screen->column = column;
+   return  MoveScreenCursor (screen);
+}
+
+//---------------------------------------------------------------------------
+//  UINT ScreenPeekOrRead (SCREEN, count, SCREEN_EVENT* buffer, BOOL remove)
+//
+//  Copy events into buffer.  Return number of events processed.
+//  If remove=TRUE, remove events from screen queue (i.e. Read)
+//  If remove=FALSE, leave events in queue (i.e. Peek)
+//  If buffer=NULL, process without copying.
+//  If count<0, process all events.
+//   .  count=-1, buffer=NULL, remove=FALSE -> count of pending events
+//   .  count=-1, buffer=NULL, remove=TRUE  -> flush queue
+//   .  count=n,  buffer=NULL, remove=TRUE  -> discard n events
+//---------------------------------------------------------------------------
+
+static UINT
+ScreenPeekOrRead (SCREEN screen, int count, SCREEN_EVENT* buffer, BOOL remove)
+{
+    UINT  processed = 0;
+    SCREEN_EVENT_LINK  *current = screen->queue_head;
+    SCREEN_EVENT* entry = buffer;
+    
+    if (count<0)
+      count = MAX_EVENTS;
+    
+    while (count>0 && current) {
+      if (entry)
+       *entry++ = current->event;
+      current = current->next;
+      if (remove) {
+       screen->queue_head->next = screen->events;
+       screen->events     = screen->queue_head;
+       screen->queue_head = current;
+       screen->n_events--;
+      }
+    }
+    return  processed;
+}
+
+//---------------------------------------------------------------------------
+//  BOOL ProcessScreenCharacter (HWND hWnd, int vk_code, int ch, DWORD lKeyData)
+//
+//  Description:
+//     This simply writes a character to the port and echos it
+//     to the TTY screen if fLocalEcho is set.  Some minor
+//     keyboard mapping could be performed here.
+//
+//  Parameters:
+//     HWND hWnd
+//        handle to TTY window
+//
+//     BYTE bOut
+//        byte from keyboard
+//
+//  History:   Date       Author      Comment
+//              5/11/91   BryanW      Wrote it.
+//
+//---------------------------------------------------------------------------
+
+static BOOL ProcessScreenCharacter (HWND hWnd, int vk_code, int bOut,
+                                    DWORD lKeyData)
+{
+   SCREEN  screen = GETSCREEN (hWnd);
+   SCREEN_EVENT *event;
+   
+   if (NULL == screen)
+      return  FALSE;
+    
+   switch (vk_code) {
+     case VK_SHIFT:
+     case VK_CONTROL:
+     case VK_CAPITAL:
+     case VK_NUMLOCK:
+     case VK_SCROLL:
+       return  TRUE;
+   }
+
+   // check for bindings:
+   {
+     int  i;
+     for (i=0; i<screen->n_bindings; i++)
+       if (screen->bindings[i].key == bOut) {
+        SendMessage (screen->hWnd,
+                     WM_COMMAND,
+                     MAKEWPARAM(screen->bindings[i].command, 0),
+                     0);
+         return  TRUE;
+       }
+   } 
+   
+   event = alloc_event (screen, SCREEN_EVENT_TYPE_KEY);
+   if (event) {
+//     char buf[80];
+     event->event.key.repeat_count = lKeyData & 0xffff;
+     event->event.key.virtual_keycode = vk_code;
+     event->event.key.virtual_scancode = (lKeyData &0xff0000) >> 16;
+     event->event.key.ch = bOut;
+     event->event.key.control_key_state = GetControlKeyState(lKeyData);
+//     wsprintf(buf,"[key %dof %d %d %d %02x]",
+//       event->event.key.repeat_count,
+//       event->event.key.virtual_keycode,
+//       event->event.key.virtual_scancode,
+//       event->event.key.ch,
+//       event->event.key.control_key_state);
+//     Screen_WriteText (screen, buf);     
+   }
+   
+//   if (event && (screen->mode_flags & SCREEN_MODE_ECHO)) {
+//     if (bOut)
+//       WriteScreenBlock (hWnd, &bOut, 1);
+//     else {
+////       char name[20];
+////       char buf[80];
+////       GetKeyNameText(lKeyData, name, 20);
+////       wsprintf (buf, "[%08x %d %d %s]", lKeyData, vk_code, bOut, name);
+////       Screen_WriteText (screen, buf);
+//     }
+//   }
+
+   return  TRUE;
+
+}
+
+//---------------------------------------------------------------------------
+//  BOOL WriteScreenBlock (HWND hWnd, LPSTR lpBlock, int nLength )
+//
+//  Description:
+//     Writes block to TTY screen.  Nothing fancy - just
+//     straight TTY.
+//
+//  Parameters:
+//     HWND hWnd
+//        handle to TTY window
+//
+//     LPSTR lpBlock
+//        far pointer to block of data
+//
+//     int nLength
+//        length of block
+//
+//
+//---------------------------------------------------------------------------
+
+static VOID _fastcall Screen_BS (SCREEN screen)
+{
+    if (screen->column > 0)
+      screen->column -- ;
+    else if (screen->row > 0) {
+      screen->row --;
+      screen->column = screen->width-1;
+    }
+    MoveScreenCursor (screen);
+}
+
+static VOID _fastcall Screen_LF(SCREEN screen)
+{
+    if (screen->row++ >= screen->height-1)
+    {
+      ScrollScreenBufferUp (screen, 1);
+      ScrollWindow (screen->hWnd, 0, -screen->yChar, NULL, NULL);
+      //InvalidateRect (hWnd, NULL, FALSE);
+      //screen->row-- ;
+      screen->row = screen->height-1;
+    }
+    MoveScreenCursor (screen);
+    if (! (screen->mode_flags & SCREEN_MODE_LAZY_UPDATE))
+      UpdateWindow (screen->hWnd);
+}
+
+static VOID _fastcall Screen_CR (SCREEN screen)
+{
+    screen->column = 0 ;
+    if (screen->mode_flags & SCREEN_MODE_NEWLINE)
+      Screen_LF (screen);
+    else
+      MoveScreenCursor (screen);
+}
+
+static VOID _fastcall Screen_WriteCharUninterpreted (SCREEN screen, int ch)
+{
+    RECT       rect ;
+
+    screen->chars[screen->row * MAXCOLS + screen->column] =
+      ch;
+    screen->attrs[screen->row * MAXCOLS + screen->column] =
+      screen->write_attribute;
+    rect.left = (screen->column * screen->xChar) - screen->xOffset;
+    rect.right = rect.left + screen->xChar;
+    rect.top = (screen->row * screen->yChar) - screen->yOffset;
+    rect.bottom = rect.top + screen->yChar;
+    InvalidateRect (screen->hWnd, &rect, FALSE);
+
+    // Line wrap
+    //if (screen->column < MAXCOLS - 1)
+    if (screen->column < screen->width-1)
+      screen->column++ ;
+    else if (screen->mode_flags & SCREEN_MODE_AUTOWRAP) {
+      Screen_CR (screen);
+      if (! (screen->mode_flags & SCREEN_MODE_NEWLINE))
+       Screen_LF (screen);
+    }
+}
+
+static VOID _fastcall Screen_TAB (SCREEN screen)
+{
+    do {
+      Screen_WriteCharUninterpreted (screen, ' ');
+    } while (screen->column%8 != 0);
+}
+
+
+static BOOL WriteScreenBlock (HWND hWnd, LPSTR lpBlock, int nLength )
+{
+   int        i ;
+   SCREEN     screen = GETSCREEN(hWnd);
+
+   if (NULL == screen)
+      return  FALSE;
+
+   for (i = 0 ; i < nLength; i++)
+   {
+      if ((screen->mode_flags & SCREEN_MODE_PROCESS_OUTPUT)==0)
+       goto uninterpreted;
+      switch (lpBlock[ i ])
+      {
+         case ASCII_BEL:
+            MessageBeep (0);
+            break ;
+   
+         case ASCII_BS:
+           Screen_BS (screen);
+            break ;
+           
+        case '\t':
+           Screen_TAB (screen);
+           break;
+   
+         case ASCII_LF:
+           Screen_CR (screen);
+           Screen_LF (screen);
+            break ;
+
+         case ASCII_CR:
+           break;
+
+//      case ASCII_LF:
+//         Screen_LF (screen);
+//            break ;
+//
+//         case ASCII_CR:
+//         Screen_CR (screen);
+//         break;
+   
+        case ASCII_FF:
+           Screen_Clear (screen, 0);
+           break;
+           
+        uninterpreted:
+         default:
+           Screen_WriteCharUninterpreted (screen, lpBlock[i]);
+            break;
+      }
+   }
+    if (! (screen->mode_flags & SCREEN_MODE_LAZY_UPDATE))
+      UpdateWindow (screen->hWnd);
+   return  TRUE;
+}
+
+//---------------------------------------------------------------------------
+//  int  ReadScreen (SCREEN screen, LPSTR buffer, int buflen)
+//
+//  Read characters into buffer.
+//  If in line mode, collect characters into the line buffer.
+//  Return the number of characters read.
+//  If in line mode and not yet at end of line, return -1 (i.e. this
+//    is a non-blocking read
+//
+//---------------------------------------------------------------------------
+
+static void key_buffer_insert_self (SCREEN screen, int ch)
+{
+  if (screen->n_chars < MAX_LINEINPUT) {
+    screen->line_buffer[screen->n_chars++] = ch;
+    if (screen->mode_flags & SCREEN_MODE_ECHO) {
+      if (ch == '\n') {
+       Screen_CR (screen);
+       Screen_LF (screen);
+      } else
+       //Screen_WriteCharUninterpreted (screen, ch);
+       WriteScreenBlock (screen->hWnd, &ch, 1);
+    }
+  }
+}
+
+static void key_buffer_erase_character (SCREEN screen)
+{
+  if (screen->n_chars > 0) {
+    screen->n_chars -= 1;
+    if (screen->mode_flags & SCREEN_MODE_ECHO) {
+      Screen_BS (screen);
+      Screen_WriteCharUninterpreted (screen, ' ');
+      Screen_BS (screen);
+    }
+  }
+}
+
+static void buffered_key_command (SCREEN screen,  int ch)
+{
+  switch (ch) {
+    case '\n':
+    case '\r':
+      key_buffer_insert_self (screen, '\n');
+      break;
+    case '\b':
+    case 127:
+      key_buffer_erase_character (screen);
+      break;
+    default:
+      key_buffer_insert_self (screen, ch);
+      break;
+  }
+  if (! (screen->mode_flags & SCREEN_MODE_LAZY_UPDATE))
+    UpdateWindow (screen->hWnd);
+}
+
+static  int  ReadScreen_line_input (SCREEN screen, LPSTR buffer, int buflen)
+{
+    SCREEN_EVENT_LINK *current = screen->queue_head;
+    SCREEN_EVENT_LINK *previous = 0;
+
+    while (current) {
+
+      if (current->event.type == SCREEN_EVENT_TYPE_KEY) {
+       int  ch = current->event.event.key.ch;
+       
+       if (ch!=0)
+         buffered_key_command (screen, ch);
+         
+        { // dequeue
+         SCREEN_EVENT_LINK  *next = current->next;
+         if (current == screen->queue_tail)
+           screen->queue_tail = previous;
+         if (previous)
+           previous->next = next;
+         else
+           screen->queue_head = next;
+         current->next = screen->free_events;
+         screen->free_events = current;
+         screen->n_events -= 1;
+         current = next;
+       }
+         
+       // If end of line then copy buffer and return
+       if (ch == '\n' || ch == '\r') {
+         int  count = min (screen->n_chars, buflen);
+         int  i;
+         for (i = 0; i<count; i++)
+           buffer[i] = screen->line_buffer[i];
+         screen->n_chars = 0;
+         return  count;
+       }
+
+      } else /*not a key event*/ {
+       previous = current;
+       current = current->next;        
+      }        
+    }
+    //  We have copied all pending characters but there is no EOL yet
+    return  -1;
+}
+
+
+static  int  ReadScreen_raw (SCREEN screen, LPSTR buffer, int buflen)
+{
+    int  position = 0;
+    SCREEN_EVENT_LINK *current = screen->queue_head;
+    SCREEN_EVENT_LINK *previous = 0;
+
+    while (current) {
+
+      if (current->event.type == SCREEN_EVENT_TYPE_KEY) {
+       int  ch = current->event.event.key.ch;
+       
+        // stash away the character
+       if (position < buflen)
+         buffer[position++] = ch;
+       if (screen->mode_flags & SCREEN_MODE_ECHO)
+         Screen_WriteCharUninterpreted (screen, ch);
+       
+        { // dequeue
+         SCREEN_EVENT_LINK  *next = current->next;
+         if (current == screen->queue_tail)
+           screen->queue_tail = previous;
+         if (previous)
+           previous->next = next;
+         else
+           screen->queue_head = next;
+         current->next = screen->free_events;
+         screen->free_events = current;
+         screen->n_events -= 1;
+         current = next;
+       }
+         
+       // If end of line or the buffer is full then  return
+       if (ch == '\n' || ch == '\r' || position==buflen)
+         return  position;
+
+      } else /*not a key event*/ {
+       previous = current;
+       current = current->next;        
+      }        
+    }
+    //  We have copied all pending characters but there is no EOL yet
+    return  position;
+}
+
+
+static  int  ReadScreen (SCREEN screen, LPSTR buffer, int buflen)
+{
+    if (screen->mode_flags & SCREEN_MODE_LINE_INPUT)
+      return ReadScreen_line_input (screen, buffer, buflen);
+    else
+      return ReadScreen_raw (screen, buffer, buflen);
+}
+
+
+//---------------------------------------------------------------------------
+//---------------------------------------------------------------------------
+VOID Screen_Clear (SCREEN screen, int kind)
+{
+    if (kind==0) {
+      // clear whole screen
+      ClearScreen_internal(screen);
+      InvalidateRect (screen->hWnd, NULL, TRUE);
+      return;
+    }
+    if (kind==1) {
+      // clear to eol
+      return;
+    }
+}
+
+//---------------------------------------------------------------------------
+//  VOID GetMinMaxSizes (HWND hWnd, LPPOINT min_size, LPPOINT max_size)
+//
+//  Description:
+//     determine the minimum and maxinum sizes for a screen window.//
+//---------------------------------------------------------------------------
+
+static VOID GetMinMaxSizes (HWND hWnd, LPPOINT min_size, LPPOINT max_size)
+{
+    SCREEN  screen = GETSCREEN (hWnd);
+    int  extra_width, extra_height;
+
+    if (screen==0) return;
+    extra_width  = 2*GetSystemMetrics(SM_CXFRAME);
+    extra_height = 2*GetSystemMetrics(SM_CYFRAME)
+                 + GetSystemMetrics(SM_CYCAPTION)
+                + (GetMenu(hWnd) ? GetSystemMetrics(SM_CYMENU) : 0)
+                ;
+    min_size->x = screen->xChar + extra_width;
+    min_size->y = screen->yChar + extra_height;
+    max_size->x = screen->xChar * MAXCOLS  +  extra_width;
+    max_size->y = screen->yChar * MAXROWS  +  extra_height;
+}
+
+//---------------------------------------------------------------------------
+//  VOID GoModalDialogBoxParam (HINSTANCE hInstance,
+//                                   LPCSTR lpszTemplate, HWND hWnd,
+//                                   DLGPROC lpDlgProc, LPARAM lParam )
+//
+//  Description:
+//     It is a simple utility function that simply performs the
+//     MPI and invokes the dialog box with a DWORD paramter.
+//
+//  Parameters:
+//     similar to that of DialogBoxParam() with the exception
+//     that the lpDlgProc is not a procedure instance
+//
+//---------------------------------------------------------------------------
+
+static VOID GoModalDialogBoxParam (HINSTANCE hInstance, LPCSTR lpszTemplate,
+                                 HWND hWnd, DLGPROC lpDlgProc, LPARAM lParam )
+{
+   DLGPROC  lpProcInstance ;
+
+   lpProcInstance = (DLGPROC) MakeProcInstance ((FARPROC) lpDlgProc,
+                                                hInstance);
+   DialogBoxParam (hInstance, lpszTemplate, hWnd, lpProcInstance, lParam);
+   FreeProcInstance ((FARPROC) lpProcInstance);
+
+}
+
+
+
+//---------------------------------------------------------------------------
+//  BOOL SettingsDlgInit (HWND hDlg )
+//
+//  Description:
+//     Puts current settings into dialog box (via CheckRadioButton() etc.)
+//
+//  Parameters:
+//     HWND hDlg
+//        handle to dialog box
+//
+//  Win-32 Porting Issues:
+//     - Constants require DWORD arrays for baud rate table, etc.
+//     - There is no "MAXCOM" function in Win-32.  Number of COM ports
+//       is assumed to be 4.
+//
+//---------------------------------------------------------------------------
+
+static BOOL SettingsDlgInit (HWND hDlg )
+{
+#if 0
+   char       szBuffer[ MAXLEN_TEMPSTR ], szTemp[ MAXLEN_TEMPSTR ] ;
+   NPTTYINFO  npTTYInfo ;
+   WORD       wCount, wMaxCOM, wPosition ;
+
+   if (NULL == (npTTYInfo = (screen) GET_PROP (hDlg, ATOM_TTYINFO )))
+      return  FALSE;
+
+
+   wMaxCOM = MAXPORTS ;
+
+   // load the COM prefix from resources
+
+   LoadString (GETHINST (hDlg ), IDS_COMPREFIX, szTemp, sizeof (szTemp ));
+
+   // fill port combo box and make initial selection
+
+   for (wCount = 0; wCount < wMaxCOM; wCount++)
+   {
+      wsprintf (szBuffer, "%s%d", (LPSTR) szTemp, wCount + 1);
+      SendDlgItemMessage (hDlg, IDD_PORTCB, CB_ADDSTRING, 0,
+                          (LPARAM) (LPSTR) szBuffer);
+   }
+
+   // disable COM port combo box if connection has already been
+   // established (e.g. OpenComm() already successful)
+
+
+   // other TTY settings
+
+   CheckDlgButton (hDlg, IDD_AUTOWRAP, AUTOWRAP (screen));
+   CheckDlgButton (hDlg, IDD_NEWLINE, NEWLINE (screen));
+   CheckDlgButton (hDlg, IDD_LOCALECHO, LOCALECHO (screen));
+#endif /*0*/
+   return  TRUE;
+
+}
+
+//---------------------------------------------------------------------------
+//  BOOL SelectScreenFont (SCREEN screen, HWND owner)
+//
+//  Description:
+//     Selects the current font for the TTY screen.
+//     Uses the Common Dialog ChooseFont() API.
+//
+//  Parameters:
+//     HWND hDlg
+//
+//---------------------------------------------------------------------------
+
+static BOOL SelectScreenFont (SCREEN  screen,  HWND owner)
+{
+   CHOOSEFONT  cfTTYFont ;
+
+   if (NULL == screen)  return  FALSE;
+
+   cfTTYFont.lStructSize    = sizeof (CHOOSEFONT);
+   cfTTYFont.hwndOwner      = owner ;
+   cfTTYFont.hDC            = NULL ;
+   cfTTYFont.rgbColors      = screen->rgbFGColour;
+   cfTTYFont.lpLogFont      = &screen->lfFont;
+   cfTTYFont.Flags          = CF_SCREENFONTS | CF_FIXEDPITCHONLY |
+                              CF_EFFECTS | CF_INITTOLOGFONTSTRUCT ;
+   cfTTYFont.lCustData      = 0 ;
+   cfTTYFont.lpfnHook       = NULL ;
+   cfTTYFont.lpTemplateName = NULL ;
+   cfTTYFont.hInstance      = GETHINST (owner);
+
+   if (ChooseFont (&cfTTYFont ))
+   {
+     screen->rgbFGColour = cfTTYFont.rgbColors ;
+     ResetScreen (screen);
+   }
+
+   return  TRUE;
+}
+
+//---------------------------------------------------------------------------
+//  BOOL SettingsDlgTerm (HWND hDlg )
+//
+//  Description:
+//     Puts dialog contents into TTY info structure.
+//
+//  Parameters:
+//     HWND hDlg
+//        handle to settings dialog
+//
+//---------------------------------------------------------------------------
+
+static BOOL SettingsDlgTerm (HWND hDlg )
+{
+#if 0
+   NPTTYINFO  npTTYInfo ;
+   WORD       wSelection ;
+
+   if (NULL == (npTTYInfo = (screen) GET_PROP (hDlg, ATOM_TTYINFO )))
+      return  FALSE;
+
+   // get other various settings
+
+   AUTOWRAP (screen) = IsDlgButtonChecked (hDlg, IDD_AUTOWRAP);
+   NEWLINE (screen) = IsDlgButtonChecked (hDlg, IDD_NEWLINE);
+   LOCALECHO (screen) = IsDlgButtonChecked (hDlg, IDD_LOCALECHO);
+
+   // control options
+#endif /*0*/
+   return  TRUE;
+}
+
+//---------------------------------------------------------------------------
+//  BOOL FAR PASCAL SettingsDlgProc (HWND hDlg, UINT uMsg,
+//                                   WPARAM wParam, LPARAM lParam )
+//
+//  Description:
+//     This handles all of the user preference settings for
+//     the TTY.
+//
+//  Parameters:
+//     same as all dialog procedures
+//
+//  Win-32 Porting Issues:
+//     - npTTYInfo is a DWORD in Win-32.
+//
+//  History:   Date       Author      Comment
+//              5/10/91   BryanW      Wrote it.
+//             10/20/91   BryanW      Now uses window properties to
+//                                    store TTYInfo handle.  Also added
+//                                    font selection.
+//              6/15/92   BryanW      Ported to Win-32.
+//
+//---------------------------------------------------------------------------
+
+BOOL FAR PASCAL SettingsDlgProc (HWND hDlg, UINT uMsg,
+                                 WPARAM wParam, LPARAM lParam )
+{
+   switch (uMsg)
+   {
+      case WM_INITDIALOG:
+      {
+        SCREEN  screen;
+
+         // get & save pointer to TTY info structure
+
+         screen = (SCREEN) lParam ;
+         SET_PROP (hDlg, ATOM_TTYINFO, (HANDLE) screen);
+
+         return  SettingsDlgInit (hDlg);
+      }
+
+      case WM_COMMAND:
+         switch  (LOWORD(wParam))
+         {
+            case IDD_FONT:
+           {
+              SCREEN  screen = GET_PROP (hDlg, ATOM_TTYINFO);
+               return  SelectScreenFont (screen, hDlg);
+           }
+
+            case IDD_OK:
+               // Copy stuff into structure
+               SettingsDlgTerm (hDlg);
+               EndDialog (hDlg, TRUE);
+               return  TRUE;
+
+            case IDD_CANCEL:
+               // Just end
+               EndDialog (hDlg, TRUE);
+               return  TRUE;
+         }
+         break;
+
+      case WM_DESTROY:
+         REMOVE_PROP (hDlg, ATOM_TTYINFO);
+         break ;
+   }
+   return  FALSE;
+
+}
+
+//---------------------------------------------------------------------------
+
+static int  GetControlKeyState(DWORD lKeyData)
+{
+  return
+    (GetKeyState(VK_RMENU) < 0  ?      SCREEN_RIGHT_ALT_PRESSED        : 0) |
+    (GetKeyState(VK_LMENU) < 0  ?      SCREEN_LEFT_ALT_PRESSED         : 0) |
+    (GetKeyState(VK_RCONTROL) < 0  ?   SCREEN_RIGHT_CTRL_PRESSED       : 0) |
+    (GetKeyState(VK_LCONTROL) < 0  ?   SCREEN_LEFT_CTRL_PRESSED        : 0) |
+    (GetKeyState(VK_SHIFT) < 0  ?      SCREEN_SHIFT_PRESSED            : 0) |
+    (GetKeyState(VK_NUMLOCK) & 1   ?   SCREEN_NUMLOCK_ON               : 0) |
+    (GetKeyState(VK_SCROLL) & 1  ?     SCREEN_SCROLLLOCK_ON            : 0) |
+    (GetKeyState(VK_CAPITAL) & 1   ?   SCREEN_CAPSLOCK_ON              : 0) |
+    ((lKeyData & 0x01000000) ?         SCREEN_ENHANCED_KEY             : 0);
+}
+
+static SCREEN_EVENT  *alloc_event (SCREEN screen,  SCREEN_EVENT_TYPE type)
+{
+    SCREEN_EVENT_LINK *link;
+    if ((screen->mode_flags & type) == 0)
+      return 0;
+
+    if (screen->free_events==0) {
+      MessageBeep (0xFFFFFFFFUL);
+      Screen_WriteText (screen->hWnd, "[alloc_event=>0]");
+      return  0;
+    }
+    
+    link = screen->free_events;
+    screen->free_events = screen->free_events->next;
+    link->event.type = type;
+    link->next = 0;
+    if (screen->queue_head==0)
+      screen->queue_head = screen->queue_tail = link;
+    else
+      screen->queue_tail = screen->queue_tail->next = link;
+    screen->n_events += 1;
+
+    SetDebuggingTitle (screen);
+    
+    return  &link->event;
+}
+
+BOOL  Screen_GetEvent (SCREEN screen, SCREEN_EVENT *event)
+{
+    SCREEN_EVENT_LINK *link;
+    if (screen->n_events == 0)
+      return  FALSE;
+    screen->n_events -= 1;
+    link = screen->queue_head;
+    (*event) = link->event;
+    screen->queue_head = link->next;
+    link->next = screen->free_events;
+    screen->free_events = link;
+    return TRUE;
+}
+
+//---------------------------------------------------------------------------
+
+void  Screen_SetAttribute (HANDLE screen, SCREEN_ATTRIBUTE sa)
+{
+    SendMessage (screen, SCREEN_SETATTRIBUTE, (WPARAM)sa, 0);
+}
+
+void  Screen_WriteChar (HANDLE screen, char ch)
+{
+    SendMessage (screen, SCREEN_WRITE, 1, (LPARAM)(LPSTR) &ch);
+}
+
+void  Screen_WriteText (HANDLE screen, char *string)
+{
+    SendMessage (screen, SCREEN_WRITE, strlen(string), (LPARAM)(LPSTR)string);
+}
+
+void  Screen_SetCursorPosition (HANDLE screen, int line, int column)
+{
+    SendMessage(screen, SCREEN_SETPOSITION, 0, MAKELPARAM(column,line));
+}
+
+
+void  Screen_SetMode (HANDLE screen, int mode)
+{
+    SendMessage (screen, SCREEN_SETMODES, (LPARAM)mode, 0);
+}
+
+
+int  Screen_GetMode (HANDLE screen)
+{
+    return  SendMessage (screen, SCREEN_GETMODES, 0, 0);
+}
+
+
+int  Screen_Read (HANDLE screen, char *buffer, int buflen)
+{
+    return
+      SendMessage (screen, SCREEN_READ, (WPARAM)buflen, (LPARAM)buffer);
+}
+
+
+void  Screen_GetSize (HANDLE hWnd, int *rows, int *columns)
+{
+    SCREEN  screen = GETSCREEN (hWnd);
+    if (screen==0)
+      return;
+    *rows    = screen->height;
+    *columns = screen->width;
+}
\ No newline at end of file
diff --git a/v7/src/microcode/ntscreen.h b/v7/src/microcode/ntscreen.h
new file mode 100644 (file)
index 0000000..04e3e99
--- /dev/null
@@ -0,0 +1,209 @@
+//---------------------------------------------------------------------------
+//
+//  Module: screen.h
+//
+//  Purpose:
+//     This is the header file for the screen class
+//
+//---------------------------------------------------------------------------
+
+
+//#undef NO_STRICT    // be bold!
+
+
+//#ifndef WIN32
+//#define WIN31        // this is a Windows 3.1 application
+//#endif
+
+#include <windows.h>
+#include <commdlg.h>
+
+
+// screen.rh
+//  #defines for resources used in screen class
+#define IDD_OK         IDOK
+#define IDD_CANCEL     IDCANCEL
+#define IDD_FONT       0x500
+// end of screen.rh 
+
+
+typedef struct tagSCREENINFO *SCREEN;
+typedef unsigned char SCREEN_ATTRIBUTE;
+
+// Mode flags:
+//  a) mask of interesting events
+#define        SCREEN_EVENT_TYPE_RESIZE        0x0001
+#define        SCREEN_EVENT_TYPE_KEY           0x0002
+#define        SCREEN_EVENT_TYPE_MOUSE         0x0004
+#define SCREEN_EVENT_TYPE_ALL          0x0007
+//  b) flags for screen behaviour
+#define SCREEN_MODE_AUTOWRAP           0x0010
+#define SCREEN_MODE_ECHO               0x0020
+#define SCREEN_MODE_NEWLINE            0x0040
+#define SCREEN_MODE_LINE_INPUT         0x0080
+#define SCREEN_MODE_PROCESS_OUTPUT     0x0100
+#define SCREEN_MODE_LAZY_UPDATE                0x0200
+
+typedef WORD SCREEN_EVENT_TYPE;
+
+typedef struct {
+  int  repeat_count;
+  int  virtual_keycode;
+  int  virtual_scancode;
+  int  control_key_state;
+  char ch;
+  int  key_down : 1;
+} SCREEN_KEY_EVENT_RECORD;
+
+// control_key_state flags
+
+#define SCREEN_RIGHT_ALT_PRESSED     0x0001 // the right alt key is pressed.
+#define SCREEN_LEFT_ALT_PRESSED      0x0002 // the left alt key is pressed.
+#define SCREEN_RIGHT_CTRL_PRESSED    0x0004 // the right ctrl key is pressed.
+#define SCREEN_LEFT_CTRL_PRESSED     0x0008 // the left ctrl key is pressed.
+#define SCREEN_SHIFT_PRESSED         0x0010 // the shift key is pressed.
+#define SCREEN_NUMLOCK_ON            0x0020 // the numlock light is on.
+#define SCREEN_SCROLLLOCK_ON         0x0040 // the scrolllock light is on.
+#define SCREEN_CAPSLOCK_ON           0x0080 // the capslock light is on.
+#define SCREEN_ENHANCED_KEY          0x0100 // the key is enhanced.
+
+typedef struct {
+  int  rows;
+  int  columns;
+} SCREEN_RESIZE_EVENT_RECORD;
+
+typedef struct {
+  int  row;
+  int  column;
+  int  control_key_state;
+  int  button_state;
+  int  mouse_moved  : 1;       // if neither then single click
+  int  double_click : 1;
+} SCREEN_MOUSE_EVENT_RECORD;
+
+// button state flags
+#define  SCREEN_MOUSE_EVENT_LEFT_PRESSED       0x01
+#define  SCREEN_MOUSE_EVENT_RIGHT_PRESSED      0x02
+#define  SCREEN_MOUSE_EVENT_MIDDLE_PRESSED     0x04
+
+typedef struct {
+  SCREEN_EVENT_TYPE  type;
+  union {
+    SCREEN_KEY_EVENT_RECORD    key;
+    SCREEN_RESIZE_EVENT_RECORD resize;
+    SCREEN_MOUSE_EVENT_RECORD  mouse;
+  } event;
+} SCREEN_EVENT;
+
+BOOL Screen_InitApplication (HANDLE hInstance);
+BOOL Screen_InitInstance (HANDLE hInstance, int nCmdShow);
+
+
+HANDLE  Screen_Create (HANDLE hParent, LPCSTR title, int nCmdShow);
+
+void  Screen_Destroy (HANDLE);
+void  Screen_SetAttribute (HANDLE, SCREEN_ATTRIBUTE);
+void  Screen_WriteChar (HANDLE, char);
+void  Screen_WriteText (HANDLE, char*);
+int   Screen_Read (HANDLE, char*, int);
+void  Screen_SetCursorPosition (HANDLE, int line, int column);
+void  Screen_SetMenu (HANDLE, HMENU);
+void  Screen_SetMode (HANDLE, int);
+int   Screen_GetMode (HANDLE);
+void  Screen_GetSize (HANDLE, int *rows, int *columns);
+
+BOOL  Screen_GetEvent (HANDLE, SCREEN_EVENT*); // return false on no events
+
+
+//---------------------------------------------------------------------------
+//  Messages
+//---------------------------------------------------------------------------
+
+#ifndef SCREEN_COMMAND_FIRST
+#define SCREEN_COMMAND_FIRST   WM_USER
+#endif
+
+#define SCREEN_WRITE           (SCREEN_COMMAND_FIRST+0)
+  // text = (LPSTR)lParam
+  // len  = (int)wParam
+
+#define SCREEN_SETPOSITION     (SCREEN_COMMAND_FIRST+1)
+  // column = LOWORD(lParam)
+  // row    = HIWORD(lParam)
+
+#define SCREEN_GETPOSITION     (SCREEN_COMMAND_FIRST+2)
+  // return  column = LOWORD(retval)
+  // return  row    = HIWORD(retval)
+
+#define SCREEN_SETATTRIBUTE    (SCREEN_COMMAND_FIRST+3)
+  // attribute = wParam
+    
+#define SCREEN_GETATTRIBUTE    (SCREEN_COMMAND_FIRST+4)
+  // return  attribute = retval
+    
+#define SCREEN_PEEKEVENT       (SCREEN_COMMAND_FIRST+5)
+  // count  = wParam
+  // buffer = (SCREEN_EVENT*) lParam
+  // returns #of events peeked
+  // if buffer is NULL, can be used to count events pending
+
+#define SCREEN_READEVENT               (SCREEN_COMMAND_FIRST+6)
+  // count  = wParam
+  // buffer = (SCREEN_EVENT*) lParam
+  // returns #of events
+  // if buffer is NULL, events are discarded
+
+#define SCREEN_SETMODES                (SCREEN_COMMAND_FIRST+7)
+  // modes = (WORD) wParam
+
+#define SCREEN_GETMODES                (SCREEN_COMMAND_FIRST+8)
+  // return  modes
+
+    
+// A window has commands, which may be bound to thunks.
+// Control characters may be bound to commands
+// Thus commands may be invoked by keypress and by menu action
+
+typedef LRESULT (*COMMAND_HANDLER)(HWND,WORD command);
+
+#define SCREEN_SETCOMMAND      (SCREEN_COMMAND_FIRST+9)
+  // command = wParam
+  // handler = COMMAND_HANDLER = lParam;  NULL=disable
+  // returns old handler, or -1 on space error
+
+#define SCREEN_GETCOMMAND      (SCREEN_COMMAND_FIRST+10)
+  // command = wParam
+  // return  handler for char
+
+#define SCREEN_SETBINDING      (SCREEN_COMMAND_FIRST+11)
+  // char = wParam
+  // command = lParam;
+
+#define SCREEN_GETBINDING      (SCREEN_COMMAND_FIRST+12)
+  // char = wParam
+  // return command
+
+#define SCREEN_SETMENU         (SCREEN_COMMAND_FIRST+13)
+  // hMenu = (HMENU)lParam
+
+#define SCREEN_READ            (SCREEN_COMMAND_FIRST+14)
+  // buffer = (LPSTR) lParam
+  // length = wParam
+  // return  characters read
+  //   (-1) if read would block in line-mode
+
+#define SCREEN_CLEAR           (SCREEN_COMMAND_FIRST+15)
+  // kind = wParam
+  //    kind=0  : whole screen
+  //    kind=1  : to eol
+    
+//---------------------------------------------------------------------------
+//  Predefined commands for SCREEN_SETBINDING etc
+//---------------------------------------------------------------------------
+
+#define SCREEN_COMMAND_CHOOSEFONT      0x400
+#define SCREEN_COMMAND_CLOSE           0x401
+
+//---------------------------------------------------------------------------
+//  End of File: screen.h
+//---------------------------------------------------------------------------
diff --git a/v7/src/microcode/ntutl/ntgui.rc b/v7/src/microcode/ntutl/ntgui.rc
new file mode 100644 (file)
index 0000000..0a69f04
--- /dev/null
@@ -0,0 +1,53 @@
+#include "windows.h"
+#include "ntgui.h"
+
+Transcript MENU
+BEGIN
+       POPUP "&File"
+       {
+               MENUITEM "&New",            IDM_NEW,        GRAYED
+               MENUITEM "&Open...",        IDM_OPEN,       GRAYED
+               MENUITEM "&Save",           IDM_SAVE,       GRAYED
+               MENUITEM "Save &As...",     IDM_SAVEAS,     GRAYED
+               MENUITEM SEPARATOR
+               MENUITEM "&Print...",       IDM_PRINT,      GRAYED
+               MENUITEM "P&rint Setup...", IDM_PRINTSETUP, GRAYED
+               MENUITEM SEPARATOR
+               MENUITEM "E&xit",           IDM_EXIT
+       }
+       POPUP "&Edit"
+       {
+               MENUITEM "&Undo\tCtrl+Z",   IDM_UNDO,   GRAYED
+               MENUITEM SEPARATOR
+               MENUITEM "Cu&t\tCtrl+X",    IDM_CUT,    GRAYED
+               MENUITEM "&Copy\tCtrl+C",   IDM_COPY,   GRAYED
+               MENUITEM "&Paste\tCtrl+V",  IDM_PASTE,  GRAYED
+               MENUITEM "Paste &Link"      IDM_LINK,   GRAYED
+               MENUITEM SEPARATOR
+               MENUITEM "Lin&ks..."        IDM_LINKS,  GRAYED
+       }
+
+       POPUP "&Interrupt"
+       {
+               MENUITEM SEPARATOR
+               MENUITEM "Emergency &Kill",   IDM_EMERGENCYKILL
+       }
+
+       POPUP        "&Help"
+       {
+               MENUITEM "&Contents",               IDM_HELPCONTENTS, GRAYED
+               MENUITEM "&Search for Help On...",  IDM_HELPSEARCH,   GRAYED
+               MENUITEM "&How to Use Help",        IDM_HELPHELP,     GRAYED
+               MENUITEM SEPARATOR
+               MENUITEM "&About Generic...",       IDM_ABOUT,        GRAYED
+       }
+END
+
+
+
+
+; Bring in the dialogs:
+; RCINCLUDE GENERIC.DLG
+
+; Bring in the version stamping information:
+; RCINCLUDE GENERIC.RCV