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