367 lines
10 KiB
C
367 lines
10 KiB
C
/*
|
|
* Copyright (c) 1994 by Xerox Corporation. All rights reserved.
|
|
*
|
|
* THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED
|
|
* OR IMPLIED. ANY USE IS AT YOUR OWN RISK.
|
|
*
|
|
* Permission is hereby granted to use or copy this program
|
|
* for any purpose, provided the above notices are retained on all copies.
|
|
* Permission to modify the code and to distribute modified code is granted,
|
|
* provided the above notices are retained, and a notice that the code was
|
|
* modified is included with the above copyright notice.
|
|
*/
|
|
/* Boehm, February 6, 1995 12:29 pm PST */
|
|
|
|
/*
|
|
* The MS Windows specific part of de.
|
|
* This started as the generic Windows application template
|
|
* made available by Rob Haack (rhaack@polaris.unm.edu), but
|
|
* significant parts didn't survive to the final version.
|
|
*
|
|
* This was written by a nonexpert windows programmer.
|
|
*/
|
|
|
|
|
|
#include "windows.h"
|
|
#include "gc.h"
|
|
#include "cord.h"
|
|
#include "de_cmds.h"
|
|
#include "de_win.h"
|
|
|
|
int LINES = 0;
|
|
int COLS = 0;
|
|
|
|
char szAppName[] = "DE";
|
|
char FullAppName[] = "Demonstration Editor";
|
|
|
|
HWND hwnd;
|
|
|
|
void de_error(char *s)
|
|
{
|
|
MessageBox( hwnd, (LPSTR) s,
|
|
(LPSTR) FullAppName,
|
|
MB_ICONINFORMATION | MB_OK );
|
|
InvalidateRect(hwnd, NULL, TRUE);
|
|
}
|
|
|
|
int APIENTRY WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance,
|
|
LPSTR command_line, int nCmdShow)
|
|
{
|
|
MSG msg;
|
|
WNDCLASS wndclass;
|
|
HANDLE hAccel;
|
|
|
|
if (!hPrevInstance)
|
|
{
|
|
wndclass.style = CS_HREDRAW | CS_VREDRAW;
|
|
wndclass.lpfnWndProc = WndProc;
|
|
wndclass.cbClsExtra = 0;
|
|
wndclass.cbWndExtra = DLGWINDOWEXTRA;
|
|
wndclass.hInstance = hInstance;
|
|
wndclass.hIcon = LoadIcon (hInstance, szAppName);
|
|
wndclass.hCursor = LoadCursor (NULL, IDC_ARROW);
|
|
wndclass.hbrBackground = GetStockObject(WHITE_BRUSH);
|
|
wndclass.lpszMenuName = "DE";
|
|
wndclass.lpszClassName = szAppName;
|
|
|
|
if (RegisterClass (&wndclass) == 0) {
|
|
char buf[50];
|
|
|
|
sprintf(buf, "RegisterClass: error code: 0x%X", GetLastError());
|
|
de_error(buf);
|
|
return(0);
|
|
}
|
|
}
|
|
|
|
/* Empirically, the command line does not include the command name ...
|
|
if (command_line != 0) {
|
|
while (isspace(*command_line)) command_line++;
|
|
while (*command_line != 0 && !isspace(*command_line)) command_line++;
|
|
while (isspace(*command_line)) command_line++;
|
|
} */
|
|
|
|
if (command_line == 0 || *command_line == 0) {
|
|
de_error("File name argument required");
|
|
return( 0 );
|
|
} else {
|
|
char *p = command_line;
|
|
|
|
while (*p != 0 && !isspace(*p)) p++;
|
|
arg_file_name = CORD_to_char_star(
|
|
CORD_substr(command_line, 0, p - command_line));
|
|
}
|
|
|
|
hwnd = CreateWindow (szAppName,
|
|
FullAppName,
|
|
WS_OVERLAPPEDWINDOW | WS_CAPTION, /* Window style */
|
|
CW_USEDEFAULT, 0, /* default pos. */
|
|
CW_USEDEFAULT, 0, /* default width, height */
|
|
NULL, /* No parent */
|
|
NULL, /* Window class menu */
|
|
hInstance, NULL);
|
|
if (hwnd == NULL) {
|
|
char buf[50];
|
|
|
|
sprintf(buf, "CreateWindow: error code: 0x%X", GetLastError());
|
|
de_error(buf);
|
|
return(0);
|
|
}
|
|
|
|
ShowWindow (hwnd, nCmdShow);
|
|
|
|
hAccel = LoadAccelerators( hInstance, szAppName );
|
|
|
|
while (GetMessage (&msg, NULL, 0, 0))
|
|
{
|
|
if( !TranslateAccelerator( hwnd, hAccel, &msg ) )
|
|
{
|
|
TranslateMessage (&msg);
|
|
DispatchMessage (&msg);
|
|
}
|
|
}
|
|
return msg.wParam;
|
|
}
|
|
|
|
/* Return the argument with all control characters replaced by blanks. */
|
|
char * plain_chars(char * text, size_t len)
|
|
{
|
|
char * result = GC_MALLOC_ATOMIC(len + 1);
|
|
register size_t i;
|
|
|
|
for (i = 0; i < len; i++) {
|
|
if (iscntrl(text[i])) {
|
|
result[i] = ' ';
|
|
} else {
|
|
result[i] = text[i];
|
|
}
|
|
}
|
|
result[len] = '\0';
|
|
return(result);
|
|
}
|
|
|
|
/* Return the argument with all non-control-characters replaced by */
|
|
/* blank, and all control characters c replaced by c + 32. */
|
|
char * control_chars(char * text, size_t len)
|
|
{
|
|
char * result = GC_MALLOC_ATOMIC(len + 1);
|
|
register size_t i;
|
|
|
|
for (i = 0; i < len; i++) {
|
|
if (iscntrl(text[i])) {
|
|
result[i] = text[i] + 0x40;
|
|
} else {
|
|
result[i] = ' ';
|
|
}
|
|
}
|
|
result[len] = '\0';
|
|
return(result);
|
|
}
|
|
|
|
int char_width;
|
|
int char_height;
|
|
|
|
void get_line_rect(int line, int win_width, RECT * rectp)
|
|
{
|
|
rectp -> top = line * char_height;
|
|
rectp -> bottom = rectp->top + char_height;
|
|
rectp -> left = 0;
|
|
rectp -> right = win_width;
|
|
}
|
|
|
|
int caret_visible = 0; /* Caret is currently visible. */
|
|
|
|
int screen_was_painted = 0;/* Screen has been painted at least once. */
|
|
|
|
void update_cursor(void);
|
|
|
|
LRESULT CALLBACK WndProc (HWND hwnd, UINT message,
|
|
WPARAM wParam, LPARAM lParam)
|
|
{
|
|
static FARPROC lpfnAboutBox;
|
|
static HANDLE hInstance;
|
|
HDC dc;
|
|
PAINTSTRUCT ps;
|
|
RECT client_area;
|
|
RECT this_line;
|
|
RECT dummy;
|
|
TEXTMETRIC tm;
|
|
register int i;
|
|
int id;
|
|
|
|
switch (message)
|
|
{
|
|
case WM_CREATE:
|
|
hInstance = ( (LPCREATESTRUCT) lParam)->hInstance;
|
|
lpfnAboutBox = MakeProcInstance( (FARPROC) AboutBox, hInstance );
|
|
dc = GetDC(hwnd);
|
|
SelectObject(dc, GetStockObject(SYSTEM_FIXED_FONT));
|
|
GetTextMetrics(dc, &tm);
|
|
ReleaseDC(hwnd, dc);
|
|
char_width = tm.tmAveCharWidth;
|
|
char_height = tm.tmHeight + tm.tmExternalLeading;
|
|
GetClientRect(hwnd, &client_area);
|
|
COLS = (client_area.right - client_area.left)/char_width;
|
|
LINES = (client_area.bottom - client_area.top)/char_height;
|
|
generic_init();
|
|
return(0);
|
|
|
|
case WM_CHAR:
|
|
if (wParam == QUIT) {
|
|
SendMessage( hwnd, WM_CLOSE, 0, 0L );
|
|
} else {
|
|
do_command(wParam);
|
|
}
|
|
return(0);
|
|
|
|
case WM_SETFOCUS:
|
|
CreateCaret(hwnd, NULL, char_width, char_height);
|
|
ShowCaret(hwnd);
|
|
caret_visible = 1;
|
|
update_cursor();
|
|
return(0);
|
|
|
|
case WM_KILLFOCUS:
|
|
HideCaret(hwnd);
|
|
DestroyCaret();
|
|
caret_visible = 0;
|
|
return(0);
|
|
|
|
case WM_LBUTTONUP:
|
|
{
|
|
unsigned xpos = LOWORD(lParam); /* From left */
|
|
unsigned ypos = HIWORD(lParam); /* from top */
|
|
|
|
set_position( xpos/char_width, ypos/char_height );
|
|
return(0);
|
|
}
|
|
|
|
case WM_COMMAND:
|
|
id = LOWORD(wParam);
|
|
if (id & EDIT_CMD_FLAG) {
|
|
if (id & REPEAT_FLAG) do_command(REPEAT);
|
|
do_command(CHAR_CMD(id));
|
|
return( 0 );
|
|
} else {
|
|
switch(id) {
|
|
case IDM_FILEEXIT:
|
|
SendMessage( hwnd, WM_CLOSE, 0, 0L );
|
|
return( 0 );
|
|
|
|
case IDM_HELPABOUT:
|
|
if( DialogBox( hInstance, "ABOUTBOX",
|
|
hwnd, lpfnAboutBox ) )
|
|
InvalidateRect( hwnd, NULL, TRUE );
|
|
return( 0 );
|
|
case IDM_HELPCONTENTS:
|
|
de_error(
|
|
"Cursor keys: ^B(left) ^F(right) ^P(up) ^N(down)\n"
|
|
"Undo: ^U Write: ^W Quit:^D Repeat count: ^R[n]\n"
|
|
"Top: ^T Locate (search, find): ^L text ^L\n");
|
|
return( 0 );
|
|
}
|
|
}
|
|
break;
|
|
|
|
case WM_CLOSE:
|
|
DestroyWindow( hwnd );
|
|
return 0;
|
|
|
|
case WM_DESTROY:
|
|
PostQuitMessage (0);
|
|
GC_win32_free_heap();
|
|
return 0;
|
|
|
|
case WM_PAINT:
|
|
dc = BeginPaint(hwnd, &ps);
|
|
GetClientRect(hwnd, &client_area);
|
|
COLS = (client_area.right - client_area.left)/char_width;
|
|
LINES = (client_area.bottom - client_area.top)/char_height;
|
|
SelectObject(dc, GetStockObject(SYSTEM_FIXED_FONT));
|
|
for (i = 0; i < LINES; i++) {
|
|
get_line_rect(i, client_area.right, &this_line);
|
|
if (IntersectRect(&dummy, &this_line, &ps.rcPaint)) {
|
|
CORD raw_line = retrieve_screen_line(i);
|
|
size_t len = CORD_len(raw_line);
|
|
char * text = CORD_to_char_star(raw_line);
|
|
/* May contain embedded NULLs */
|
|
char * plain = plain_chars(text, len);
|
|
char * blanks = CORD_to_char_star(CORD_chars(' ',
|
|
COLS - len));
|
|
char * control = control_chars(text, len);
|
|
# define RED RGB(255,0,0)
|
|
|
|
SetBkMode(dc, OPAQUE);
|
|
SetTextColor(dc, GetSysColor(COLOR_WINDOWTEXT));
|
|
|
|
TextOut(dc, this_line.left, this_line.top,
|
|
plain, len);
|
|
TextOut(dc, this_line.left + len * char_width, this_line.top,
|
|
blanks, COLS - len);
|
|
SetBkMode(dc, TRANSPARENT);
|
|
SetTextColor(dc, RED);
|
|
TextOut(dc, this_line.left, this_line.top,
|
|
control, strlen(control));
|
|
}
|
|
}
|
|
EndPaint(hwnd, &ps);
|
|
screen_was_painted = 1;
|
|
return 0;
|
|
}
|
|
return DefWindowProc (hwnd, message, wParam, lParam);
|
|
}
|
|
|
|
int last_col;
|
|
int last_line;
|
|
|
|
void move_cursor(int c, int l)
|
|
{
|
|
last_col = c;
|
|
last_line = l;
|
|
|
|
if (caret_visible) update_cursor();
|
|
}
|
|
|
|
void update_cursor(void)
|
|
{
|
|
SetCaretPos(last_col * char_width, last_line * char_height);
|
|
ShowCaret(hwnd);
|
|
}
|
|
|
|
void invalidate_line(int i)
|
|
{
|
|
RECT line;
|
|
|
|
if (!screen_was_painted) return;
|
|
/* Invalidating a rectangle before painting seems result in a */
|
|
/* major performance problem. */
|
|
get_line_rect(i, COLS*char_width, &line);
|
|
InvalidateRect(hwnd, &line, FALSE);
|
|
}
|
|
|
|
LRESULT CALLBACK AboutBox( HWND hDlg, UINT message,
|
|
WPARAM wParam, LPARAM lParam )
|
|
{
|
|
switch( message )
|
|
{
|
|
case WM_INITDIALOG:
|
|
SetFocus( GetDlgItem( hDlg, IDOK ) );
|
|
break;
|
|
|
|
case WM_COMMAND:
|
|
switch( wParam )
|
|
{
|
|
case IDOK:
|
|
EndDialog( hDlg, TRUE );
|
|
break;
|
|
}
|
|
break;
|
|
|
|
case WM_CLOSE:
|
|
EndDialog( hDlg, TRUE );
|
|
return TRUE;
|
|
|
|
}
|
|
return FALSE;
|
|
}
|
|
|