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