home *** CD-ROM | disk | FTP | other *** search
- #ifdef MSW /** WHOLE FILE **/
-
- /*
- This is a quickie port of MG2a (MicroEMACS derived) to MsWindows 3.1.
- The original code ran under DOS to a bios interface
- with direct hardware access to the keyboard and system clock. This
- version and the following w3 files have been (mostly) hooked in underneath
- the original code, which thankfully had most of the terminal io (screen
- access) and keyboard input at a level distinct from the core editor. Not
- every function is relegated to the absolute best .C file location (for
- example, a system call is implemented inside w3win.c since it is, after
- all, a WinExec call.... In addition, much bashing was done to make
- this Emacs look more like GNU-Emacs (make/next-error functions), automatic
- timed backups, timestamp checking, and a large assortment of functions
- implemented to extend the editor and move it away from MicroEMACS to
- GNU-emacs feel. It's a reasonable result given the amount of time spent. :)
-
- The goal was not to make emacs window-aware. Instead, the window specific
- code was to act like a terminal. That is why the startup code (windows code)
- executes first; to create a window, etc such that when EmaxMain is called,
- the 'terminal' (ie window) exists. The input handling is done by creating
- an internal queue at the 'terminal' level and emacs just reads chars from
- the 'keyboard' buffer. Special window-specific things happen without core
- code being aware (ie focus events, etc). Events which require a core code
- response, like window resize, generate emacs recognizable keycodes (or
- entire command strings) which the editor can get. Resize in specific
- generates redraw-display and the core code already did a terminal size
- query for that command.
-
- Mouse events are funny; window specific code handles them as far as
- determining double click, etc. But window level code only goes as far
- as converting mouse events to emacs commands for left, right, up/down,
- etc. In other words, emacs is now mouse-aware, but in an abstract way.
- A wayward user can use the keyboard to send mouse actions, though not
- easily. Only window level code can parse a mouse click/motion to rows
- and columns that emacs needs. This is based on font, window size, etc.
- I'm considering making the DOS version support the mouse since most
- of the code is there; just a couple of things to hook to the mouse.
- (Could also do the system clock for time, auto backups, etc but I don't
- want to kill Windows and I have to figure out how to get the interrupt
- w/o zapping Windows so gnu would run safely in a DOS window. Same
- cavet goes with making DOS-gnu use XMS.)
-
- Things to make better: foremost is the desire of the core editor to
- write a single character at a time; and the windows level implementation is
- being faithful to that request BUT it really should cache some consecutive
- characters when it can! (DONE!) Next would be a cleanup of the ifdef's, and
- re-org of function-to-file mapping.
-
- w3 source files:
-
- jam.h version defines, includes, etc
- w3win.c (this file) main, event loop, window proc, window creation, etc
- w3io.c (aka ttyio.c) character output, scrolling, etc
- w3key.c map keypress event to some EMACS virtual key for
- extended commands
- w3font.c support for fonts, emax.ini file support
- w3mem.c 32 bit global memory mangler
- w3ext.c support for drag&drop, print, cut/copy/paste (to
- Window's clipboard)
- dos.c not windows really, but new dos things
- */
-
- #define W3WIN_C /* prevent multiple define of globals */
-
- #include "jam.h"
- #include "windowsx.h" /* windows/nt extension macros */
- #include "def.h"
- #include "keyname.h"
- #include "stdio.h"
- #include "ttydef.h"
- #include "chrdef.h"
- #include "malloc.h"
- #include "time.h"
- #include "commdlg.h" /* font and open/save file dialogs */
- #include "shellapi.h" /* drag & drop */
-
- extern void FAR _cdecl exit(int); /* to keep compiler happy */
-
- /* Globals, externed in jam.h
- */
- HANDLE g_hInstance;
- HWND g_hWnd = 0; /* the 1 and only window */
- HDC g_hDC;
- int g_nLineHeight, g_nCharWidth;
- UINT g_idTimer = 0;
- int g_caret_x = -1, g_caret_y = -1;
- HFONT g_hfont = 0;
- HFONT g_oldFont = 0;
- BOOL g_caret = FALSE;
- BOOL g_update = FALSE;
- BOOL edInited = FALSE;
- BOOL g_hasFocus = FALSE;
- BOOL g_menu = FALSE;
-
- /* Misc contants
- */
- #define FONT_CHOICE 100 /* menu ids for system menu */
- #define ABOUT_CHOICE 110
- #define SAVE_CHOICE 120
- #define TOGGLE_CHOICE 130
- #define ABORT_CHOICE 140
- #define COLORS_CHOICE 150
-
- /* pullrights...
- */
- #define TCOLOR_CHOICE 200
- #define WCOLOR_CHOICE 210
- #define CCOLOR_CHOICE 220 /* changes color */
-
- #define OPEN_CHOICE 300 /* menu ids for main window menu */
- #define OPEN_CHOICE2 310
- #define INSERT_CHOICE 320
- #define REVERT_CHOICE 330
- #define SAVEAS_CHOICE 340
- #define PRINT_CHOICE 350
-
- #define COPY_CHOICE 360 /* clipboard functions */
- #define CUT_CHOICE 370
- #define PASTE_CHOICE 380
-
- #define HELP_APROPOS 390
- #define HELP_ABOUT 400
-
- #define KEXTEND_CHOICE 500 /* menu ids for main window menu */
-
- #define LEFT 0x1
- #define RIGHT 0x2
-
- /* Local statics
- */
- #ifdef WIN32
- # include <winbase.h>
- static STARTUPINFO s_sInfo = { 0 };
- static PROCESS_INFORMATION s_pInfo = { 0 };
- #else
- static HWND s_appwindow = 0;
- #endif
- static int s_scrollTicks = 0; /* autoscroll */
- static HCURSOR s_loadedcursor = 0;
- static BOOL s_waitingforapp = FALSE;
- static BOOL s_fatal = FALSE;
- static int s_btndown = 0;
- static int s_sleep = 0;
- static int s_sTicks = 0; /* inc-save interval */
- static HRGN s_hrgn = 0;
- static char s_timestr[35] = {0};
- static char *s_APPNAMEQUESTION = AppQuestion;
- static char *s_APPNAMEMSG = AppMsg;
- static char *APPCLASS = "MyToy Class";
- static char *curname = 0;
- static char *blank = " ";
- static char s_spawnbuf[NFILEN];
-
- /* Array of pulldown menus.
- */
- #define PARENT 0
- #define FILEM 1
- #define EDITM 2
- #define WINDOWM 3
- #define EXECM 4
- #define HELPM 5
- #define NUMBERM 6
-
- #define FreeLoadedCursor(c)\
- if (c)\
- {\
- DestroyCursor(c);\
- c = 0;\
- }
-
- static HMENU s_menu[NUMBERM];
- static UINT s_choices = 0;
-
- /* Local function prototypes
- */
- BOOL FAR PASCAL findWindow(HWND hWnd, LONG lParam);
- static void SetTheTitle(void);
- static void WindowAddMenu(void);
- static void getthetime(void);
- static void DoMenuThing(void);
- static void chooseColor(WPARAM wParam);
- static void ReverseCaret(void);
-
- BOOL WindowFatalState(void)
- {
- return(s_fatal);
- }
- /* Set window title as appropriate.
- */
- static void SetTheTitle()
- {
- char buffer[200], dir[100];
- static char lastTitle[200] = {0};
-
- strcpy(buffer, g_APPNAME);
- strcat(buffer, " ");
-
- /* short vs long title
- */
- if (!IsIconic(g_hWnd) && wdir)
- {
- strcat(buffer, shortversion());
- strcpy(dir, wdir);
- adjustnamecase(dir);
- strcat(buffer, " (");
- strcat(buffer, dir);
- strcat(buffer, ") ");
- }
-
- strcat(buffer, s_timestr); /* update when needed */
- if (strcmp(buffer, lastTitle) != 0)
- {
- SetWindowText(g_hWnd, buffer);
- strcpy(lastTitle, buffer); /* save last time */
- }
- }
-
- /* Update the time string, used for window title
- */
- static void getthetime(void)
- {
- long currtime;
- struct tm *timestruct;
- BOOL am = TRUE;
- int hour;
-
- time(&currtime);
- timestruct = localtime(&currtime);
- hour = timestruct->tm_hour;
- if (hour > 12)
- {
- hour -= 12;
- am = FALSE;
- }
- sprintf(s_timestr, " %d:%02d%s\0",
- hour, timestruct->tm_min, am ? "am" : "pm");
- }
-
- /*
- * WinMain
- *
- * Arguments:
- *
- * hInstance - handle of this instance of notgnu.exe
- * hPrevInstance - handle to a previous instance
- * lpCmdLine - string containing command line arguments
- * nCmdShow - argument to ShowWindow that controls how
- * Windows would like to start this application.
- *
- * Return value:
- *
- * an integer with the final result of the application
- */
- int PASCAL WinMain(hInstance, hPrevInstance, lpCmdLine, nCmdShow)
- HANDLE hInstance;
- HANDLE hPrevInstance;
- LPSTR lpCmdLine;
- int nCmdShow;
- {
- int argc = 0;
- #define NARGS 50
- char *argv[50], *p;
- WNDCLASS wc;
- char progname[NFILEN];
- DWORD flags;
-
- /* who are we?
- */
- if (!GetModuleFileName(hInstance, progname, NFILEN))
- progname[0] = '\0';
-
- /* first thing to do is init the internal heap manager
- * and the message queue
- */
- #ifndef WIN32
- W3memLocalInitialize();
-
- /* Set the max size of the message queue; default is 8.
- */
- {
- int queue_size = 300;
- while (!SetMessageQueue(queue_size--))
- ;
- }
- #endif
-
- /*
- * Move some of the arguments into global variables so that
- * editor can use them later.
- */
- g_hInstance = hInstance;
-
- /*
- * Set up argc and argv.
- */
- argv[argc++] = progname;
-
- p = lpCmdLine;
-
- /* Gather file names
- */
- if (argc >= NARGS)
- {
- /* printf("Number of input args too large! Truncating to %d\n", NARGS); */
- argc = NARGS - 1;
- }
- while(p && *p)
- {
- while (*p && ISWHITE(*p)) /* get to start of this param */
- p++;
- argv[argc++] = p;
- while (*p && !ISWHITE(*p)) /* get to end of this param */
- p++;
-
- /* properly terminate it for 'main'
- */
- if (ISWHITE(*p)) /* more stuff may follow */
- {
- *p = '\0';
- p++;
- }
- }
-
- /* Fill in window class structure with parameters that describe the
- * main window. Only need to do this if no previous task did it..
- */
- if (!hPrevInstance)
- {
- wc.style = CS_DBLCLKS; /* Class style(s). */
- wc.lpfnWndProc = MainWndProc; /* Function to retrieve messages */
- wc.cbClsExtra = 0; /* No per-class extra data.*/
- wc.cbWndExtra = 0; /* No per-window extra data.*/
- wc.hInstance = hInstance; /* Application that owns the class.*/
- wc.hCursor = LoadCursor(NULL, IDC_ARROW);
- wc.hbrBackground = GetStockObject(WHITE_BRUSH);
- wc.lpszMenuName = NULL;
- wc.hIcon = LoadIcon(hInstance, "ID_NOTICON");
- wc.lpszClassName = APPCLASS; /* Name used in call to CreateWindow. */
-
- /* Register the window class and check success/failure code.
- */
- if (!RegisterClass(&wc))
- {
- WindowMessage("Failed to create window class!", FALSE);
- return(FALSE);
- }
- }
-
- /* create a window
- */
- flags = WS_OVERLAPPEDWINDOW;
- #ifdef VBAR
- flags |= WS_VSCROLL;
- #endif
- g_hWnd = CreateWindow(APPCLASS, g_APPNAME, flags,
- CW_USEDEFAULT, /* Default horizontal position.*/
- CW_USEDEFAULT, /* Default vertical position. */
- CW_USEDEFAULT, /* Default width. */
- CW_USEDEFAULT, /* Default height.*/
- NULL, /* Overlapped windows have no parent.*/
- NULL, /* Use the window class menu. */
- hInstance,
- NULL /* Pointer not needed. */
- );
-
- /* If window could not be created, return "failure"
- */
- if (!g_hWnd)
- {
- WindowMessage("Failed to create window!", FALSE);
- return(FALSE);
- }
-
- /* Init internal input buffer(s)
- */
- InitInput();
-
- /* Grab the hdc, get a default font
- */
- g_hDC = GetDC(g_hWnd);
- SetBkMode(g_hDC, OPAQUE);
- WindowInitFont(FONTSIZE);
-
- /* Size window based on font, find menubar setting
- */
- InitWindow(START_COLS, START_LINES);
- UpdateWindow(g_hWnd);
-
- /* Make the window visible; update its client area
- * and add things to default system menu
- */
- ShowWindow(g_hWnd, nCmdShow);
- ttresize();
- s_menu[PARENT] = (HMENU)0;
- WindowAddMenu();
- DragAcceptFiles(g_hWnd, TRUE); /* allow some drag/drop stuff */
-
- /*
- * Call 'main' body of editor
- */
- edInited = TRUE; /* any message after this is ok to process */
- if (newUser())
- MakeBanner();
- EmaxMain(argc, argv); /* return from here is exit editor */
-
- /* Free resources
- */
- if (g_idTimer)
- KillTimer(g_hWnd, g_idTimer); /* Stops the timer */
- if (g_hfont)
- {
- SelectObject(g_hDC, g_oldFont);
- DeleteObject(g_hfont);
- }
- ReleaseDC(g_hWnd, g_hDC);
- if (s_menu[0])
- {
- SetMenu(g_hWnd, 0);
- DestroyMenu(s_menu[0]);
- }
- DestroyWindow(g_hWnd);
-
- /* Cleanup the heap. Any memory not free-ed gets released
- * since part of managed heap.
- */
- #ifndef WIN32
- W3memLocalTerminate();
- #endif
- return 1;
- }
-
- /* Pending event during screen refresh?
- */
- BOOL WindowLookaheadEvent(void)
- {
- MSG msg;
-
- if (PeekMessage(&msg, NULL, WM_PAINT, WM_PAINT, PM_NOREMOVE))
- return(TRUE);
- if (PeekMessage(&msg, NULL, WM_SIZE, WM_SIZE, PM_NOREMOVE))
- return(TRUE);
-
- return(FALSE);
- }
-
- /* Return a cached event; wait if none pending.
- */
- void WindowGetEvent(void *ptr)
- {
- MSG msg;
- BOOL result;
-
- /* Make sure something is there
- */
- for (result = FALSE; !result; )
- if (!(result = WindowReturnKCHAR((KCHAR *)ptr)))
- {
- /* See if Windows has any; process and return if
- * result of Windows event yields a KCHAR, or if
- * other KCHARs were waiting.
- *
- * Cursor on during wait...
- */
- if (IsCaretCreated() && (s_btndown == 0))
- SetCaretVis(TRUE);
-
- if (GetMessage(&msg, NULL, NULL, NULL))
- {
- /* Cursor off during processing
- */
- if (IsCaretCreated())
- SetCaretVis(FALSE);
-
- TranslateMessage(&msg);
- DispatchMessage(&msg);
- }
- }
- }
-
- /* Dump a string to a message box. If fatal,
- * leave ungracefully...
- */
- void WindowMessage(s, fatal)
- char *s;
- BOOL fatal;
- {
- BOOL wasVis;
-
- if (wasVis = IsCaretVis())
- SetCaretVis(FALSE);
- MessageBox(0, s, s_APPNAMEMSG, MB_OK | MB_APPLMODAL);
- if (wasVis)
- SetCaretVis(TRUE);
- if (fatal)
- {
- s_fatal = TRUE;
- ealtmsg = TRUE;
- IncrementalSave();
- exit(1);
- }
- }
-
- /* Simple-minded stub to exec something
- */
- int winspawn(char *s, BOOL windows)
- {
- char buf[NLINE];
- BOOL sync;
- #ifdef WIN32
- char *sh = "cmd.exe";
- #else
- char *sh = "command.com";
- FARPROC proc;
- int appHandle;
- #endif
- sync = FALSE;
-
- /* From 'shell-window' command (create a shell window)
- */
- if (!s) /* lack of command string implies shell window */
- {
- #ifdef WIN32
- strcpy(buf, sh);
- #else
- strcpy(buf, apppath());
- strcat(buf, "meshell.pif");
- if (!fileisok(buf)) /* is 'our' shell here? */
- strcpy(buf, sh); /* default shell */
- #endif
- }
-
- /* From 'shell-command' or 'window-command' (spawn background job)
- */
- else if (s_waitingforapp && !windows)
- {
- /* Feeble - should be able to spawn multiple background
- * processes, but I'm not managing multiple logs...
- */
- ewprintf("Pending shell-command already running in background.");
- return (FALSE);
- }
-
- /* build command string
- */
- else
- {
- if (windows)
- strcpy(buf, s);
- else
- {
- /* destroy log first so won't read old log by accident
- */
- strcpy(buf, dirpath());
- strcat(buf, spawnfilename);
- unlink(buf);
-
- strcpy(buf, sh);
- strcat(buf, " /c ");
- strcat(buf, s);
- strcat(buf, " > ");
- strcat(buf, spawnfilename);
- sync = TRUE;
-
- /* create name for reading in after
- * task completes
- */
- strcpy(s_spawnbuf, dirpath());
- strcat(s_spawnbuf, spawnfilename);
- }
- }
-
- #ifdef WIN32
- ewprintf("CreateProcess: %s", buf);
- s_sInfo.cb = sizeof(STARTUPINFO);
- s_sInfo.lpTitle = AppJob;
- s_sInfo.wShowWindow = (sync ? SW_SHOWMINNOACTIVE : SW_SHOWNORMAL);
- s_sInfo.dwFlags = STARTF_USESHOWWINDOW;
-
- if (CreateProcess(NULL, buf, NULL, NULL, DETACHED_PROCESS,
- FALSE, NULL, NULL, &s_sInfo, &s_pInfo))
- {
- if (sync)
- s_waitingforapp = TRUE;
- }
- else
- {
- sprintf(buf, "CreateProcess error: %s", buf);
- WindowMessage(buf, FALSE);
- ewprintf(blank);
- noop();
- return (FALSE);
- }
- #else
- ewprintf("WinExec: %s", buf);
- SetCaretVis(FALSE);
- appHandle = WinExec(buf, sync ? SW_SHOWMINNOACTIVE : SW_SHOW);
- if (appHandle < 32) /* error */
- {
- sprintf(buf, "WinExec error %d", appHandle);
- WindowMessage(buf, FALSE);
- ewprintf(blank);
- noop();
- return (FALSE);
- }
- else if (sync)
- {
- /* job running, find window handle to wait for completion
- */
- proc = MakeProcInstance((FARPROC)findWindow, g_hInstance);
- EnumWindows(proc, (DWORD)appHandle);
- FreeProcInstance(proc);
-
- if (s_appwindow != 0)
- s_waitingforapp = TRUE;
- }
- #endif
- noop();
- return(TRUE);
- }
-
- /*
- * Main window procedure for the one and only window
- * we create.
- */
- long FAR PASCAL MainWndProc(hWnd, message, wParam, lParam)
- HWND hWnd;
- UINT message;
- WPARAM wParam;
- LPARAM lParam;
- {
- int status;
- char buff[40];
- int downcol, downrow;
- int cmd_param;
-
- switch (message)
- {
- case WM_CREATE:
- g_idTimer = SetTimer(hWnd, NULL, TIME_INC, (FARPROC) NULL);
- break;
-
- case WM_DROPFILES:
- HandleDroppedFiles((HANDLE)wParam); /* w3ext.c */
- break;
-
- case WM_TIMER:
- if (edInited)
- {
- static int tTicks = 0; /* title update interval */
-
- /* Any messages printed by routines called
- * from a WM_TIMER message must not use standard
- * output method.
- */
- ealtmsg = TRUE;
-
- /* Counter for titlebar update; also use this increment to
- * check for spawned shells
- */
- tTicks++;
- if (tTicks > INCS_PER_UPDATE)
- {
- getthetime(); /* get current clock time */
- SetTheTitle(); /* fix window title */
- tTicks = 0;
-
- /* Spawned app running?
- */
- #ifdef DOGRINDER
- if (!s_btndown && s_waitingforapp)
- WindowGrinderCursor();
- #endif
- #ifdef WIN32
- if (!isearching && !eprompting && !s_btndown &&
- (s_waitingforapp &&
- !(WaitForSingleObject(s_pInfo.hProcess, 0) == WAIT_TIMEOUT)))
- {
- CloseHandle(s_pInfo.hThread);
- CloseHandle(s_pInfo.hProcess);
- #else
- if (!isearching && !eprompting && !s_btndown &&
- (s_waitingforapp && !IsWindow(s_appwindow)))
- {
- #endif
- s_waitingforapp = FALSE;
- ttbeep();
- #ifdef DOGRINDER
- WindowNormalCursor();
- #endif
- status = MessageBox(0, "Shell command completed, read log?",
- s_APPNAMEQUESTION,
- MB_YESNO | MB_APPLMODAL | MB_ICONQUESTION);
- if (status == IDYES)
- {
- BUFFER *bp = bfind(spawnfilename, FALSE);
-
- /* Nuke any old logs from different dirs
- */
- if (bp)
- {
- bp->b_flag &= ~BFCHG;
- if (strcmp(bp->b_fname, s_spawnbuf) != 0)
- nukebuffer(bp);
- }
- #if 1
- ExtendedFunction(function_name(poptofilequiet));
- AddString(s_spawnbuf);
- AddKchar(CCHR('J'));
- #else
- AddString(s_spawnbuf);
- AddKchar(CCHR('J'));
- poptofilequiet(0, 1); /* go get it */
- ExtendedFunction(function_name(donothing));
-
- /* Mark the file to be deleted when buffer is
- * nuked
- */
- if (bp = bfind(spawnfilename, FALSE))
- bp->b_flag |= BFDELETE;
- #endif
- }
- }
-
- /* Any user defined alarms to execute?
- */
- {
- static BOOL incallback = FALSE;
-
- if (!incallback)
- {
- incallback = TRUE;
- AnyPendingAlarms();
- incallback = FALSE;
- }
- }
- } /* incs per update */
-
- /* Auto scroll current window if left button
- * down and control key is also
- */
- if ((s_btndown & LEFT) && (GetKeyState(VK_CONTROL) < 0))
- {
- s_scrollTicks++;
- if (s_scrollTicks >= DELAY_TO_SCROLL)
- {
- char buff[8];
-
- ExtendedFunction(function_name(mousecmd));
- AddString(MouseTimer);
- sprintf(buff, " %d ", GetKeyState(VK_SHIFT) < 0 ? 1: 0);
- AddString(buff);
- s_scrollTicks = DELAY_TO_SCROLL; /* prevent overflow */
- }
- }
- else
- s_scrollTicks = 0; /* force reset */
-
- /* Counter for incremental save (keyboard input delays this)
- * and pending prompt postpones this indefinitly!!!
- */
- s_sTicks++;
- if ((s_sTicks > INCS_PER_SAVE) && !eprompting)
- {
- static BOOL incallback = FALSE;
-
- if (!incallback)
- {
- incallback = TRUE;
- IncrementalSave(); /* autosave in file.c */
- incallback = FALSE;
- s_sTicks = 0;
- }
- }
- ealtmsg = FALSE;
- }
- break;
-
- case WM_SYSCOLORCHANGE:
- return (0); /* basically ignored. */
-
- case WM_SYSCOMMAND:
- switch (wParam)
- {
- case FONT_CHOICE:
- WindowNewFont();
- break;
- case ABOUT_CHOICE:
- MakeBanner();
- break;
- case SAVE_CHOICE:
- SaveAllSettings();
- break;
- case TOGGLE_CHOICE:
- togglemenu(0, 1);
- break;
- case ABORT_CHOICE:
- status = MessageBox(0, "Shoot me dead now?\n (This is equal to a crash!)",
- s_APPNAMEQUESTION, MB_YESNO | MB_APPLMODAL |
- MB_ICONSTOP);
- if (status == IDYES)
- ExtendedFunction(function_name(shootmedead));
- break;
-
- case TCOLOR_CHOICE:
- case WCOLOR_CHOICE:
- case CCOLOR_CHOICE:
- chooseColor(wParam);
- break;
- default:
- return (DefWindowProc(hWnd, message, wParam, lParam));
- }
- break;
-
- case WM_SETFOCUS:
- #ifdef WINDOWS_CURSOR
- CreateCaret(hWnd, NULL, g_nCharWidth, g_nLineHeight);
- SetCaretPos(g_caret_x, g_caret_y);
- #endif
- SetCaretCreated(TRUE);
- g_hasFocus = TRUE;
- break;
-
- case WM_KILLFOCUS:
- SetCaretVis(FALSE);
- #ifdef WINDOWS_CURSOR
- DestroyCaret();
- #endif
- SetCaretCreated(FALSE);
- g_hasFocus = FALSE;
- break;
-
- #ifdef VBAR /* never completed, not 1/buffer, etc */
- case WM_VSCROLL:
- if (edInited)
- switch(wParam)
- {
- case SB_TOP:
- ExtendedFunction(function_name(gotobob));
- break;
- case SB_BOTTOM:
- ExtendedFunction(function_name(gotoeob));
- break;
- case SB_LINEUP:
- ExtendedFunction(function_name(back1page));
- break;
- case SB_LINEDOWN:
- ExtendedFunction(function_name(forw1page));
- break;
- case SB_PAGEUP:
- ExtendedFunction(function_name(backpage));
- break;
- case SB_PAGEDOWN:
- ExtendedFunction(function_name(forwpage));
- break;
- default:
- noop();
- }
- break;
- #endif
-
- case WM_RBUTTONDOWN:
- GetRowCol(&downrow, &downcol, LOWORD(lParam), HIWORD(lParam));
- s_btndown |= RIGHT;
- ExtendedFunction(function_name(mousecmd));
- if (s_btndown & LEFT)
- {
- AddString(MouseAbort);
- AddKchar(' ');
- }
- else
- {
- AddString(RightDwn);
- sprintf(buff, posFormat, downrow, downcol);
- AddString(buff);
- }
- break;
-
- case WM_RBUTTONUP:
- if (s_btndown & RIGHT) /* was it down in our window?? */
- s_btndown &= ~RIGHT;
- noop();
- break;
-
- case WM_MOUSEMOVE:
- GetRowCol(&downrow, &downcol, LOWORD(lParam), HIWORD(lParam));
- if ((s_btndown & LEFT) && !(s_btndown & RIGHT))
- {
- s_scrollTicks = 0; /* stop autoscroll */
- ExtendedFunction(function_name(mousecmd));
- AddString(MoveStr);
- sprintf(buff, posFormat, downrow, downcol);
- AddString(buff);
- }
- break;
-
- #if 1 /* there is a redraw marker bug :( */
- case WM_MOUSEACTIVATE:
- return (MA_ACTIVATEANDEAT);
- #endif
-
- case WM_LBUTTONDOWN:
- GetRowCol(&downrow, &downcol, LOWORD(lParam), HIWORD(lParam));
- s_btndown |= LEFT;
- ExtendedFunction(function_name(mousecmd));
- if (s_btndown & RIGHT)
- {
- AddString(MouseAbort);
- AddKchar(' ');
- }
- else
- {
- if (wParam & MK_SHIFT)
- AddString(LeftDwnShift);
- else
- AddString(LeftDwn);
- sprintf(buff, posFormat, downrow, downcol);
- AddString(buff);
- SetCapture(g_hWnd);
- }
- break;
-
- case WM_LBUTTONUP:
- GetRowCol(&downrow, &downcol, LOWORD(lParam), HIWORD(lParam));
- if (s_btndown & LEFT) /* was it down in our window?? */
- {
- s_btndown &= ~LEFT;
- ExtendedFunction(function_name(mousecmd));
- AddString(LeftUp);
- sprintf(buff, posFormat, downrow, downcol);
- AddString(buff);
- ReleaseCapture();
- }
- break;
-
- case WM_LBUTTONDBLCLK:
- GetRowCol(&downrow, &downcol, LOWORD(lParam), HIWORD(lParam));
- if ((s_btndown & RIGHT) == 0)
- {
- ExtendedFunction(function_name(mousecmd));
- AddString(DoubleClick);
- AddKchar(' ');
- }
- else
- {
- AddString(MouseAbort);
- AddKchar(' ');
- }
- ReleaseCapture();
- break;
-
- case WM_COMMAND:
- cmd_param = (int)LOWORD(wParam);
- if ((cmd_param >= KEXTEND_CHOICE) && (cmd_param <= (int)s_choices))
- {
- char cmd[NLINE + 1];
- register int i;
-
- /* This hacky loop let me move menu items anywhere I
- * wanted w/o having to know which pulldown it belonged to (or
- * care for that matter). All 'extendable' functions have an
- * id between KEXTEND_CHOICE and s_choices (s_choices is incremented
- * after each moveable, extendable menu item is added). Ok, so it's
- * a little ughly, but it was quick and easy!
- */
- for (i = 1; i <= NUMBERM; i++)
- if (GetMenuString(s_menu[i], cmd_param, cmd, NLINE,
- MF_BYCOMMAND) > 0)
- {
- ExtendedFunction(cmd);
- break;
- }
- }
- else /* special case pre-processed events */
- switch(cmd_param)
- {
- case HELP_APROPOS:
- ExtendedFunction(function_name(apropos_command));
- AddKchar('a');
- AddKchar(CCHR('J'));
- break;
-
- case HELP_ABOUT:
- MakeBanner();
- break;
-
- case COPY_CHOICE:
- case CUT_CHOICE:
- HandleCutCopy(cmd_param == CUT_CHOICE ? TRUE : FALSE);
- break;
-
- case PASTE_CHOICE: /* NOTE Not dimming choices yet! */
- HandlePaste();
- break;
-
- #ifdef DOPRINT
- case PRINT_CHOICE:
- HandlePrint();
- break;
- #endif
-
- case OPEN_CHOICE:
- case INSERT_CHOICE:
- case OPEN_CHOICE2:
- case SAVEAS_CHOICE:
- {
- OPENFILENAME openfile;
- char fname[NFILEN+1];
- BOOL result = FALSE;
-
- memset(fname, '\0', sizeof(fname));
- memset(&openfile, '\0', sizeof(OPENFILENAME));
- strcpy(fname, "*.c;*.h;*.txt");
- openfile.lStructSize = sizeof(openfile);
- openfile.lpstrFilter = "*.*";
- openfile.lpstrFile = fname;
- openfile.nMaxFile = sizeof(fname);
- if (cmd_param == SAVEAS_CHOICE)
- openfile.Flags = OFN_OVERWRITEPROMPT;
- openfile.Flags |= OFN_PATHMUSTEXIST;
- openfile.Flags |= OFN_HIDEREADONLY;
-
- EnableWindow(g_hWnd, FALSE);
- if (cmd_param == SAVEAS_CHOICE)
- result = GetSaveFileName(&openfile);
- else
- result = GetOpenFileName(&openfile);
- EnableWindow(g_hWnd, TRUE);
- SetActiveWindow(g_hWnd);
-
- if (result)
- {
- disable_preload(); /* full name already supplied */
- if (cmd_param == OPEN_CHOICE)
- ExtendedFunction(function_name(filevisit));
- else if (cmd_param == OPEN_CHOICE2)
- ExtendedFunction(function_name(poptofile));
- else if (cmd_param == SAVEAS_CHOICE)
- ExtendedFunction(function_name(filewrite));
- else
- ExtendedFunction(function_name(fileinsert));
- AddString(fname);
- AddKchar(CCHR('J'));
- }
- }
- default:
- break;
- }
- break;
-
- case WM_SYSKEYDOWN:
- case WM_SYSCHAR:
- case WM_CHAR:
- case WM_KEYDOWN:
- if (edInited)
- {
- /* SPECIAL CASE TO ALLOW TASK SWITCHING AND ACCESS
- * TO SYSTEM MENU
- */
- if ((message == WM_SYSKEYDOWN) && (wParam == VK_TAB))
- return (DefWindowProc(hWnd, message, wParam, lParam));
- if ((message == WM_SYSCHAR) && (wParam == ' '))
- return (DefWindowProc(hWnd, message, wParam, lParam));
-
- /* Regular input events cause some delay to autosave
- */
- s_sTicks -= SAVE_DELAY;
- if (s_sTicks < 0)
- s_sTicks = 0;
-
- /* Prevent garbled commands interrupting mouse
- */
- if (!s_btndown)
- WindowMapKey(message, wParam, lParam);
- }
- break;
-
- case WM_PAINT:
- {
- HDC hDC;
- PAINTSTRUCT ps;
- RECT r;
-
- /* satisfy windows, get the update region
- */
- hDC = BeginPaint (hWnd, &ps);
- r = ps.rcPaint;
- EndPaint(hWnd, &ps);
-
- /* Draw...
- */
- if (!IsIconic(g_hWnd) && edInited)
- {
- int row = ttrow;
- int col = ttcol;
-
- sgarbf = TRUE;
- s_hrgn = CreateRectRgn(r.left, r.top, r.right, r.bottom);
- SelectClipRgn(g_hDC, s_hrgn);
-
- /* Fix in-progress stuff after redraw; in all cases
- * some event gets into the input queue to get the
- * cursor updated after processing. Not pretty!
- */
- update();
- if (isearching)
- noop(); /* jumpSearch(); hacky research to refresh */
- else if (eprompting)
- erepair(); /* fix prompt+msg */
- else
- ExtendedFunction(function_name(donothing));
- SelectClipRgn(g_hDC, NULL);
- DeleteObject(s_hrgn);
- ttmove(row, col); /* restore cursor */
- }
- break;
- }
-
- case WM_SIZE:
- if (!IsIconic(g_hWnd))
- {
- if (edInited)
- {
- RECT rect;
-
- GetClientRect(g_hWnd, &rect);
- ValidateRect(g_hWnd, &rect);
- ExtendedFunction(function_name(myrefresh));
- }
- }
- SetTheTitle();
- break;
-
- case WM_QUERYENDSESSION:
- if (!anycb(ABORT))
- {
- ExitCleanup(); /* cleanup work files */
- return(1); /* all clear to exit */
- }
-
- /* Modified files, tell user and request dispostion (love them
- * big words!)
- */
- ShowWindow(g_hWnd, SW_SHOW);
- status = MessageBox(0, "Saved modified buffers?", s_APPNAMEQUESTION,
- MB_YESNOCANCEL | MB_SYSTEMMODAL | MB_ICONQUESTION);
- if (status == IDNO)
- {
- ExitCleanup(); /* cleanup work files */
- return(1); /* let windows go */
- }
- else if (status == IDYES)
- {
- savebuffers(TRUE, 0);
- ExitCleanup(); /* cleanup work files */
- return(1);
- }
- break;
-
- case WM_CLOSE:
- ExtendedFunction(function_name(quit));
- break;
-
- default:
- return (DefWindowProc(hWnd, message, wParam, lParam));
- }
- return (NULL);
- }
-
- /* find row col from pos
- */
- void GetRowCol(int *prow, int *pcol, int x, int y)
- {
- register int row, col;
-
- col = (x + 1)/g_nCharWidth;
- row = (y + 1)/g_nLineHeight;
-
- if (col < 0)
- col = 0;
- else if (col > ncol)
- col = ncol;
- if (row < 0)
- row = 0;
- else if (row > nrow)
- row = nrow;
-
- *pcol = col;
- *prow = row;
- }
-
- /* add things to system menu
- */
- static void WindowAddMenu(void)
- {
- HMENU sysmenu = (HMENU) 0;
- HMENU pop;
-
- /* return Window's default menu
- */
- if (!(sysmenu = GetSystemMenu(g_hWnd, FALSE)))
- {
- WindowMessage("Can't add to system menu!", FALSE);
- return;
- }
- AppendMenu(sysmenu, MF_SEPARATOR, 0, 0L);
- AppendMenu(sysmenu, MF_STRING, TOGGLE_CHOICE, "Window Men&u");
- AppendMenu(sysmenu, MF_STRING, FONT_CHOICE, "&Font...");
-
- /* Choice + pullright
- */
- pop = CreateMenu();
- AppendMenu(sysmenu, MF_ENABLED|MF_POPUP, (UINT)pop, "C&olors");
- AppendMenu(pop, MF_STRING, TCOLOR_CHOICE, "&Text Color...");
- AppendMenu(pop, MF_STRING, CCOLOR_CHOICE, "T&ouched Text Color...");
- AppendMenu(pop, MF_STRING, WCOLOR_CHOICE, "&Window Color...");
-
- AppendMenu(sysmenu, MF_STRING, SAVE_CHOICE, "&Save Settings");
- AppendMenu(sysmenu, MF_SEPARATOR, 0, 0L);
- AppendMenu(sysmenu, MF_STRING, ABOUT_CHOICE, "&About...");
- AppendMenu(sysmenu, MF_STRING, ABORT_CHOICE, "Shoot Me &Dead!");
- }
- /* Draw cursor; s_cur_* set on draw, used on un-draw.
- * Needed because ttmove moves g_caret_* w/o turning
- * off caret.
- */
- static int s_cur_x, s_cur_y;
- void DoShowCaret(HANDLE hwnd)
- {
- MakeCaretVis(TRUE);
- s_cur_x = g_caret_x;
- s_cur_y = g_caret_y;
- #ifdef WINDOWS_CURSOR
- ShowCaret(hwnd);
- #else
- ReverseCaret();
- #endif
- }
- /* Erase cursor
- */
- void DoHideCaret(HANDLE hwnd)
- {
- MakeCaretVis(FALSE);
- #ifdef WINDOWS_CURSOR
- HideCaret(hwnd);
- #else
- ReverseCaret();
- #endif
- }
- /* Cursor engine stuff if non-windows caret
- */
- static void ReverseCaret()
- {
- RECT rect;
-
- rect.left = s_cur_x;
- rect.top = s_cur_y;
- rect.bottom = rect.top + g_nLineHeight;
- rect.right = rect.left + g_nCharWidth;
- InvertRect(g_hDC, &rect);
- }
-
- /* Manage pointer switching for some operations
- */
- void WindowSizeCursor(void)
- {
- HCURSOR cursor = LoadCursor(NULL, IDC_SIZENS);
-
- if (cursor)
- SetCursor(cursor);
- }
- void WindowDragCursor(void)
- {
- HCURSOR cursor = LoadCursor(NULL, IDC_IBEAM);
-
- if (cursor)
- SetCursor(cursor);
- }
- void WindowArrowCursor(void)
- {
- FreeLoadedCursor(s_loadedcursor);
- s_loadedcursor = LoadCursor(g_hInstance, "ID_HANDE");
- if (s_loadedcursor)
- SetCursor(s_loadedcursor);
- else
- ewprintf("Can't load hand cursor.");
- }
- void WindowSleepCursor(void)
- {
- HCURSOR cursor = LoadCursor(NULL, IDC_WAIT);
-
- if (cursor)
- SetCursor(cursor);
- }
- #ifdef DOGRINDER
- void WindowGrinderCursor(void)
- {
- char buff[100];
- static firstfailure = TRUE;
- HCURSOR saved = s_loadedcursor;
-
- s_sleep++; /* check for wrap */
- if (s_sleep > 8) /* hard coded numbers, ick! */
- s_sleep = 1;
-
- sprintf(buff, "ID_GRINDER%d", s_sleep);
- s_loadedcursor = LoadCursor(g_hInstance, buff);
-
- if (s_loadedcursor)
- SetCursor(s_loadedcursor);
- else
- {
- if (firstfailure)
- ewprintf("Can't load sleep cursor");
- firstfailure = FALSE;
- }
- FreeLoadedCursor(saved);
- }
- #endif
- void WindowNormalCursor(void)
- {
- HCURSOR cursor = LoadCursor(NULL, IDC_ARROW);
-
- if (cursor)
- {
- SetCursor(cursor);
-
- /* check for old special cursor lying around
- */
- FreeLoadedCursor(s_loadedcursor);
- }
- s_sleep = 0;
- }
- #ifndef WIN32
- /* Used to find the shell window created when
- * a background job was spawned. On NT, use the
- * real process id
- */
- BOOL FAR PASCAL findWindow(HWND hWnd, LONG lParam)
- {
- if (GetWindowInstance(hWnd) == (HINSTANCE)lParam)
- {
- s_appwindow = hWnd;
- return FALSE; /* found it, stop enumerating */
- }
- return TRUE;
- }
- #endif
-
- /* toggle existance of application menu bar
- */
- int togglemenu(int f, int n)
- {
- g_menu = (g_menu ? FALSE: TRUE);
- DoMenuThing();
- return TRUE;
- }
- /* This is the application window menubar - as opposed
- * to the system menu on the window
- */
- static void DoMenuThing()
- {
- /* normal app menu?
- */
- if (!g_menu)
- SetMenu(g_hWnd, 0);
- else if (g_menu)
- {
- if (s_menu[PARENT] == (HMENU)0)
- {
- HMENU pop;
-
- s_choices = KEXTEND_CHOICE;
-
- /* FILE (note open commands unique id)
- */
- s_menu[PARENT] = CreateMenu();
- pop = s_menu[FILEM] = CreatePopupMenu();
- AppendMenu(pop, MF_STRING, OPEN_CHOICE, function_name(filevisit));
- AppendMenu(pop, MF_STRING, OPEN_CHOICE2, function_name(poptofile));
- AppendMenu(pop, MF_STRING, INSERT_CHOICE, function_name(fileinsert));
- AppendMenu(pop, MF_STRING, s_choices++, function_name(filesave));
- AppendMenu(pop, MF_STRING, SAVEAS_CHOICE, function_name(filewrite));
- AppendMenu(pop, MF_STRING, s_choices++, function_name(savebuffers));
- AppendMenu(pop, MF_SEPARATOR, 0, 0L);
- AppendMenu(pop, MF_STRING, REVERT_CHOICE, function_name(reverto));
- AppendMenu(pop, MF_SEPARATOR, 0, 0L);
- AppendMenu(pop, MF_STRING, s_choices++, function_name(quit));
- #ifdef DOPRINT
- AppendMenu(pop, MF_SEPARATOR, 0, 0L);
- AppendMenu(pop, MF_STRING, PRINT_CHOICE, (LPCSTR)"Print...");
- #endif
- AppendMenu(s_menu[PARENT], MF_ENABLED | MF_POPUP,
- (UINT)pop, (LPCSTR)"File");
-
- /* EDIT
- */
- pop = s_menu[EDITM]= CreatePopupMenu();
- AppendMenu(pop, MF_STRING, s_choices++, function_name(forwsearch));
- AppendMenu(pop, MF_STRING, s_choices++, function_name(backsearch));
- AppendMenu(pop, MF_STRING, s_choices++, function_name(queryrepl));
- AppendMenu(pop, MF_SEPARATOR, 0, 0L);
- AppendMenu(pop, MF_STRING, s_choices++, function_name(setmark));
- AppendMenu(pop, MF_STRING, s_choices++, function_name(swapmark));
- AppendMenu(pop, MF_STRING, s_choices++, function_name(killregion));
- AppendMenu(pop, MF_STRING, s_choices++, function_name(copyregion));
- AppendMenu(pop, MF_STRING, s_choices++, function_name(yank));
- AppendMenu(pop, MF_SEPARATOR, 0, 0L);
- AppendMenu(pop, MF_STRING, s_choices++, function_name(definemacro));
- AppendMenu(pop, MF_STRING, s_choices++, function_name(finishmacro));
- AppendMenu(pop, MF_STRING, s_choices++, function_name(executemacro));
- AppendMenu(pop, MF_STRING, s_choices++, function_name(extend));
- AppendMenu(pop, MF_SEPARATOR, 0, 0L);
- AppendMenu(pop, MF_STRING, CUT_CHOICE, (LPCSTR)"Cut Region");
- AppendMenu(pop, MF_STRING, COPY_CHOICE, (LPCSTR)"Copy Region");
- AppendMenu(pop, MF_STRING, PASTE_CHOICE, (LPCSTR)"Paste");
-
- AppendMenu(s_menu[PARENT], MF_ENABLED | MF_POPUP,
- (UINT)pop, (LPCSTR)"Edit");
-
- /* WINDOW
- */
- pop = s_menu[WINDOWM] = CreatePopupMenu();
- AppendMenu(pop, MF_STRING, s_choices++, function_name(usebuffer));
- AppendMenu(pop, MF_STRING, s_choices++, function_name(killbuffer));
- AppendMenu(pop, MF_STRING, s_choices++, function_name(listbuffers));
- AppendMenu(pop, MF_SEPARATOR, 0, 0L);
- AppendMenu(pop, MF_STRING, s_choices++, function_name(nextwind));
- AppendMenu(pop, MF_STRING, s_choices++, function_name(prevwind));
- AppendMenu(pop, MF_STRING, s_choices++, function_name(splitwind));
- AppendMenu(pop, MF_STRING, s_choices++, function_name(onlywind));
-
- AppendMenu(s_menu[PARENT], MF_ENABLED | MF_POPUP, (UINT)pop,
- (LPCSTR)"Window");
-
- /* EXEC
- */
- pop = s_menu[EXECM] = CreatePopupMenu();
- AppendMenu(pop, MF_STRING, s_choices++, function_name(windowprog));
- AppendMenu(pop, MF_STRING, s_choices++, function_name(spawncli2));
- AppendMenu(pop, MF_STRING, s_choices++, function_name(spawncli));
- AppendMenu(pop, MF_SEPARATOR, 0, 0L);
- AppendMenu(pop, MF_STRING, s_choices++, function_name(sysmake));
- AppendMenu(pop, MF_STRING, s_choices++, function_name(makeerror));
-
- AppendMenu(s_menu[PARENT], MF_ENABLED | MF_POPUP, (UINT)pop,
- "Execute");
-
- /* HELP
- */
- pop = s_menu[HELPM] = CreatePopupMenu();
- AppendMenu(pop, MF_STRING, HELP_APROPOS,
- function_name(apropos_command));
- AppendMenu(pop, MF_STRING, HELP_ABOUT, "about...");
-
- AppendMenu(s_menu[PARENT], MF_ENABLED | MF_POPUP, (UINT)pop,
- (LPCSTR)"Help");
- }
- SetMenu(g_hWnd, s_menu[PARENT]);
- }
- DrawMenuBar(g_hWnd);
- }
- static void chooseColor(wParam)
- WPARAM wParam;
- {
- CHOOSECOLOR colors;
- COLORREF extra[16];
- BOOL s;
-
- /* Use special common dialog for chosing color. Note
- * that I didn't feel like doing the work of managing
- * special mixed colors; you get the ones windows gives
- * you. Note also that you can choose non-pure colors
- * and on displays with limited colors, it looks crummy
- */
- memset(&colors, 0, sizeof(colors));
- colors.lStructSize = sizeof(CHOOSECOLOR);
- colors.hwndOwner = g_hWnd;
- colors.rgbResult = (wParam == TCOLOR_CHOICE ?
- GetForeColor() : (wParam == CCOLOR_CHOICE ?
- GetHighColor() : GetBackColor()));
-
- colors.Flags |= CC_RGBINIT | CC_PREVENTFULLOPEN;
- colors.lpCustColors = extra; /* Crash if this is NULL, even
- * though the flag does not say to use
- * them. Bogus that it is required.. */
-
- EnableWindow(g_hWnd, FALSE);
- s = ChooseColor(&colors);
- EnableWindow(g_hWnd, TRUE);
- SetActiveWindow(g_hWnd);
-
- if (s)
- {
- if (wParam == TCOLOR_CHOICE)
- SetForeColor(colors.rgbResult);
- else if (wParam == WCOLOR_CHOICE)
- SetBackColor(colors.rgbResult);
- else if (wParam == CCOLOR_CHOICE)
- SetHighColor(colors.rgbResult);
- ExtendedFunction(function_name(myrefresh));
- }
- }
-
- /* Wrappers to get to support from menu
- */
- int NewFont(f, n)
- int f, n;
- {
- WindowNewFont();
- return(TRUE);
- }
- int NewTextColor(f, n)
- int f, n;
- {
- chooseColor(TCOLOR_CHOICE);
- return(TRUE);
- }
- int NewTouchedTextColor(f, n)
- int f, n;
- {
- chooseColor(CCOLOR_CHOICE);
- return(TRUE);
- }
- int NewWindowColor(f, n)
- int f, n;
- {
- chooseColor(WCOLOR_CHOICE);
- return(TRUE);
- }
- #endif /** JAM **/
-