| /* |
| * 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; |
| } |
| |