home *** CD-ROM | disk | FTP | other *** search
- # Stuff for MS-Windows 3.1
- # Bruno Haible 22.9.1994
-
- #include "lispbibl.c"
-
- # Any Windows program needs this:
- #define _STDDEF_H_INCLUDED # WATCOM: avoid clash because of offsetof()
- #define _STDDEF_H # EMX: avoid warning because of offsetof()
- #define BYTE WINDOWS_BYTE
- #define WORD WINDOWS_WORD
- #define INCLUDE_SHELLAPI_H # include <shellapi.h> for drag&drop support
- #include <windows.h>
- #undef WORD
- #undef BYTE
-
- # Some useful definitions:
- # define min(x,y) ((x) < (y) ? (x) : (y))
- # define max(x,y) ((x) > (y) ? (x) : (y))
- struct xy { int x; int y; };
-
- # A couple of magic identifiers used to access the elements of the resource:
- #include "clispwin.h"
-
- # Debugging support:
- /* #define WIN_DEBUG */
- #ifdef WIN_DEBUG
- #define WINDEBUG(x) x
- local void event_out (const char * caller, HWND hWnd, mywindow w, UINT message, WPARAM wParam, LPARAM lParam);
- #else
- #define WINDEBUG(x)
- #endif
-
-
- # Accessing the "command line":
- # There is no such thing. (Well, the RSXWIN startup code saves something as
- # __argc and __argv, but I don't know what it is.)
- # We load the arguments from a file called CLISPWIN.INI, in the Windows
- # directory.
- #
- # Its layout is roughly like this:
- # [CLISP]
- # Arglist="[the command line arguments]"
- # Language="english"
- # Lines=25
- # Columns=80
- # Font="Fixedsys"
- # Fontsize=16
- # Leading=-1
- # Fonts should be fixed width (such as "Courier New", "Fixedsys",
- # or "Lucinda Sans Typewriter").
- # Font sizes should be in the 10..20 point range.
- # Leading specifies an adjustment for inter-line spacing.
-
- #define ini_filename "CLISPWIN.INI"
- #define ini_section "CLISP"
-
- # Retrieve the value of a "ini file environment variable".
- local char* getenv_ini_string (char* name);
- local int getenv_ini_int (char* name);
- local char* getenv_ini_string(name)
- var char* name;
- { var uintL bufsize = 50;
- var char* buf;
- while (1)
- { buf = malloc(bufsize);
- if (!buf) return NULL;
- if (GetPrivateProfileString(ini_section, name, "",
- buf, bufsize,
- ini_filename
- )
- < bufsize-1
- )
- return buf;
- free(buf);
- bufsize *= 2; # retry with larger buffer
- }
- }
- local int getenv_ini_int(name)
- var char* name;
- { return GetPrivateProfileInt(ini_section, name, 0,
- ini_filename
- );
- }
-
-
- # The program's "instance" and "command line".
- local HINSTANCE global_hInstance;
- local LPSTR global_lpszCmdLine;
-
- # Our (modified) command line arguments.
- local char* * argv;
- local int argc;
-
- # Get the command line args, maybe from the ini file.
- local void extend_args (void);
- local void extend_args()
- { local var char* dummy_argv[] = { "CLISPWIN" };
- var char* arglist;
- argv = dummy_argv; argc = 1;
- if (!(global_lpszCmdLine[0]=='\0'))
- # If args have been given, they override the INI file args.
- { begin_system_call();
- arglist = malloc(strlen(global_lpszCmdLine)+1);
- end_system_call();
- if (!arglist) return;
- strcpy(arglist,global_lpszCmdLine);
- }
- else
- { begin_system_call();
- arglist = getenv_ini_string("Arglist");
- end_system_call();
- if (!arglist) return;
- }
- # Split up into arguments, separated by whitespace:
- #define whitespacep(c) (((c)==' ') || ((c)=='\t') || ((c)=='\n'))
- { var char* ptr = arglist;
- var uintC count = 0;
- loop
- { if (*ptr=='\0') break;
- if (whitespacep(*ptr))
- { ptr++; }
- else
- { count++;
- until ((*ptr=='\0') || whitespacep(*ptr))
- { ptr++; }
- }
- }
- if (count==0)
- return; # no new arguments
- begin_system_call();
- {var int new_argc = 1 + count;
- var char* * new_argv = malloc(new_argc*sizeof(char*));
- end_system_call();
- if (!new_argv) return;
- new_argv[0] = argv[0]; count = 1;
- ptr = arglist;
- loop
- { if (*ptr=='\0') break;
- if (whitespacep(*ptr))
- { ptr++; }
- else
- { new_argv[count] = ptr;
- until ((*ptr=='\0') || whitespacep(*ptr))
- { ptr++; }
- if (*ptr=='\0') break;
- *ptr = '\0';
- ptr++;
- count++;
- }
- }
- argc = new_argc; argv = new_argv;
- }}
- #undef whitespacep
- }
-
-
- # The type of our event handler functions:
- typedef long (*eventhandler) (mywindow w, UINT message, WPARAM wParam, LPARAM lParam);
-
- # The type of our events:
- typedef enum { ev_key, ev_menu, ev_drop, ev_paste, ev_eof } event_type;
- typedef struct event { event_type type;
- union { cint key; WPARAM wParam; char* pastebuf; } u;
- }
- event;
-
- # The type of our windows:
- struct mywindow
- { HWND hWnd; # its MS-Windows handle
- boolean in_focus; # whether this window holds the focus
- boolean for_output; # whether this window is an output stream
- # or only presents static text
- boolean for_input; # whether this window is an input stream
- # or only presents output
- # a list of event handlers, most specific first
- eventhandler eventhandler1, eventhandler2, eventhandler3, eventhandler4;
- # data for text windows:
- struct {
- int width; # text width, in characters
- int height; # text height, in characters
- # The text displayed in the window:
- char* * contents; # an array of length height,
- # each of length width
- # User feedback during Cut&Paste operation:
- # Some of the text may be selected, inverted on the screen.
- struct xy selpoint1, selpoint2;
- enum { none, # nothing selected, selpoint1/2 invalid
- notmoved, # one mouse click, no move, selpoint1 = selpoint2
- marking, # mouse is moving
- marked # selection done
- }
- in_marking;
- # data for text windows which support output:
- # To focus the user's attention, we place a text cursor at
- # a point we call the "current line/column".
- struct xy cursor;
- boolean cursor_visible; # is the cursor currently visible?
- }
- text;
- # data for windows which support input:
- struct { # keyboard typeahead buffer, event queue
- event* ev_fifo;
- uintL ev_fifo_size;
- event* ev_fifo_out;
- event* ev_fifo_in;
- # The current state of a finite state machine:
- boolean in_paste; # getting our input from a paste buffer
- event paste_ev; # the current paste event
- char* paste_ptr; # pointer into the paste buffer
- }
- input;
- # data for text windows which support input:
- struct {
- char* line; # current line
- uintL line_size; # its malloc() size
- uintL count; # number of characters in the line
- uintL index; # number of characters already consumed
- }
- textinput;
- # linked list of windows:
- struct mywindow * next;
- };
-
-
- # This is the list of all windows we are managing.
- local mywindow all_windows = NULL;
-
- # Add a window to the list all_windows:
- local void register_window (mywindow w);
- local void register_window(w)
- var mywindow w;
- { w->next = all_windows; all_windows = w; }
- # The converse:
- local void unregister_window (mywindow w);
- local void unregister_window(w)
- var mywindow w;
- { var mywindow * p = &all_windows;
- until (*p == NULL) if (*p == w) { *p = w->next; return; }
- }
-
- # Lookup a window, given its handle:
- local mywindow find_window (HWND hWnd);
- local mywindow find_window(hWnd)
- var HWND hWnd;
- { var mywindow w;
- for (w = all_windows; !(w==NULL); w = w->next)
- { if (w->hWnd == hWnd)
- { return w; }
- }
- # If hWnd wasn't found, it belongs to a window that is being created.
- return NULL;
- }
-
- # The event handler for the whole application, see below.
- local long _export FAR PASCAL all_event (HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam);
-
- # The default event handler, see below.
- local long default_event (mywindow w, UINT message, WPARAM wParam, LPARAM lParam);
-
-
- # A library for text windows:
-
- #include "wintext.c"
-
-
- # A status window:
-
- #include "winstat.c"
-
-
- # The main window:
-
- #include "winmain.c"
-
-
- # A default event handler:
- local long default_event (w,message,wParam,lParam)
- var mywindow w;
- var UINT message;
- var WPARAM wParam;
- var LPARAM lParam;
- { switch (message)
- { case WM_SETFOCUS:
- in_focus = TRUE;
- show_mouse_cursor();
- break;
- case WM_KILLFOCUS:
- in_focus = FALSE;
- break;
- default:
- break;
- }
- return DefWindowProc(w->hWnd,message,wParam,lParam);
- }
-
- # The event handler for the whole application.
- local long _export FAR PASCAL all_event(hWnd,message,wParam,lParam)
- var HWND hWnd;
- var UINT message;
- var WPARAM wParam;
- var LPARAM lParam;
- { var mywindow w = find_window(hWnd);
- WINDEBUG( event_out("all_event",hWnd,w,message,wParam,lParam); )
- if (w)
- return w->eventhandler1(w,message,wParam,lParam);
- # If hWnd wasn't found, it belongs to a window that is being created.
- # We haven't yet had a chance to call register_window().
- return DefWindowProc(hWnd,message,wParam,lParam);
- }
-
-
- # This is the main program, called by Windows.
- # You may also call it the application's INITIALIZE-INSTANCE method.
- global int PASCAL WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpszCmdLine, int nCmdShow);
- extern int main (int argc, char* argv[]);
- global int PASCAL WinMain(hInstance,hPrevInstance,lpszCmdLine,nCmdShow)
- var HINSTANCE hInstance;
- var HINSTANCE hPrevInstance;
- var LPSTR lpszCmdLine;
- var int nCmdShow;
- { var int retval;
-
- #ifdef EMUNIX
- # Initialize SP_start so that begin_system_call() will work.
- # SP() = %esp = 0x0000FE38 here.
- SP_start = (void*)(SP() - 0x4000);
- # This is preliminary:
- # The system stack is 16 KB below the normal stack, for now.
- #endif
-
- global_hInstance = hInstance;
- global_lpszCmdLine = lpszCmdLine;
- # hPrevInstance will be NULL since we have only one thread running.
-
- # Look up the INI environment.
- extend_args();
-
- # Mouse cursors.
- init_cursors();
- in_focus = FALSE; in_wait = FALSE; in_gc = FALSE; mouse_hidden = FALSE;
-
- # Load accelerator table.
- begin_system_call();
- hAccel = LoadAccelerators(global_hInstance,"ACCELERATORS_1");
- end_system_call();
-
- if (!init_text_class())
- return FALSE;
-
- # Determine character sizes and colours.
- get_char_info();
-
- # Main window.
- { var int main_width, main_height;
- begin_system_call();
- main_width = getenv_ini_int("Columns");
- if (!main_width) { main_width = 80; }
- main_height = getenv_ini_int("Lines");
- if (!main_height) { main_height = 25; }
- end_system_call();
- if (!main_create(main_width,main_height))
- return FALSE;
- }
-
- # Status window.
- status_create(main_window->hWnd);
-
- # Display the main window.
- begin_system_call();
- ShowWindow(main_window->hWnd,nCmdShow);
- UpdateWindow(main_window->hWnd);
- end_system_call();
-
- # Go, CLISP, go!
- retval = main(argc,argv);
-
- begin_system_call();
- DestroyWindow(main_window->hWnd);
- end_system_call();
-
- return retval;
- }
-
-
- # Other auxiliary functions:
-
- #include "winaux.c"
-
-
- # TODO:
- # Fix Cut&Paste. It does not work yet.
- # ANSI to OEM and back?!?!? This is a mess:
- # - files may be in ISO or DOS character set. What do we assume?
- # - Type Alt-128 at the keyboard, get C-cedilla, which has code 199.
- # The up-/downcase tables in io.d do not correctly downcase this.
- # - The mode of a font can be enquired using GetTextMetrics.
- # Support for several/switchable font.
- # ev_eof shall terminate the application. Currently (sys::%exit) is the only way.
- # Endless loop WM_QUIT -> end_of_main -> WM_DESTROY -> WM_QUIT ...
- # About and Copyright boxes are too large, choose help text or something else.
- # Update status_window more regularly, use interruptp() macro for this.
- # Define an "interrupt event" which is acknowledged by interruptp().
- # Mouse click into the line during winterm_readchar shall position the cursor.
- # Menu points for LOAD, DRIBBLE, STEP, ABORT, CONTINUE and many more.
- # CLOSE rectangle for the status window.
- # SCREEN::MAKE-WINDOW crashes.
- # Translate the menu into 3 languages, choose it at runtime.
-
-