Back to index

plt-scheme  4.2.1
de_win.c
Go to the documentation of this file.
00001 /*
00002  * Copyright (c) 1994 by Xerox Corporation.  All rights reserved.
00003  *
00004  * THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED
00005  * OR IMPLIED.  ANY USE IS AT YOUR OWN RISK.
00006  *
00007  * Permission is hereby granted to use or copy this program
00008  * for any purpose,  provided the above notices are retained on all copies.
00009  * Permission to modify the code and to distribute modified code is granted,
00010  * provided the above notices are retained, and a notice that the code was
00011  * modified is included with the above copyright notice.
00012  */
00013 /* Boehm, February 6, 1995 12:29 pm PST */
00014 
00015 /*
00016  * The MS Windows specific part of de.  
00017  * This started as the generic Windows application template
00018  * made available by Rob Haack (rhaack@polaris.unm.edu), but
00019  * significant parts didn't survive to the final version.
00020  *
00021  * This was written by a nonexpert windows programmer.
00022  */
00023 
00024 
00025 #include "windows.h"
00026 #include "gc.h"
00027 #include "cord.h"
00028 #include "de_cmds.h"
00029 #include "de_win.h"
00030 
00031 int LINES = 0;
00032 int COLS = 0;
00033 
00034 char       szAppName[]     = "DE";
00035 char       FullAppName[]   = "Demonstration Editor";
00036 
00037 HWND        hwnd;
00038 
00039 void de_error(char *s)
00040 {
00041     MessageBox( hwnd, (LPSTR) s,
00042                 (LPSTR) FullAppName,
00043                 MB_ICONINFORMATION | MB_OK );
00044     InvalidateRect(hwnd, NULL, TRUE);
00045 }
00046 
00047 int APIENTRY WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance,
00048                       LPSTR command_line, int nCmdShow)
00049 {
00050    MSG         msg;
00051    WNDCLASS    wndclass;
00052    HANDLE      hAccel;
00053 
00054    if (!hPrevInstance)
00055    {
00056       wndclass.style          = CS_HREDRAW | CS_VREDRAW;
00057       wndclass.lpfnWndProc    = WndProc;
00058       wndclass.cbClsExtra     = 0;
00059       wndclass.cbWndExtra     = DLGWINDOWEXTRA;
00060       wndclass.hInstance      = hInstance;
00061       wndclass.hIcon          = LoadIcon (hInstance, szAppName);
00062       wndclass.hCursor        = LoadCursor (NULL, IDC_ARROW);
00063       wndclass.hbrBackground  = GetStockObject(WHITE_BRUSH);
00064       wndclass.lpszMenuName   = "DE";
00065       wndclass.lpszClassName  = szAppName;
00066 
00067       if (RegisterClass (&wndclass) == 0) {
00068           char buf[50];
00069        
00070          sprintf(buf, "RegisterClass: error code: 0x%X", GetLastError());
00071          de_error(buf);
00072          return(0);
00073       }
00074    }
00075    
00076    /* Empirically, the command line does not include the command name ...
00077    if (command_line != 0) {
00078        while (isspace(*command_line)) command_line++;
00079        while (*command_line != 0 && !isspace(*command_line)) command_line++;
00080        while (isspace(*command_line)) command_line++;
00081    } */
00082    
00083    if (command_line == 0 || *command_line == 0) {
00084         de_error("File name argument required");
00085         return( 0 );
00086    } else {
00087         char *p = command_line;
00088         
00089         while (*p != 0 && !isspace(*p)) p++;
00090        arg_file_name = CORD_to_char_star(
00091                          CORD_substr(command_line, 0, p - command_line));
00092    }
00093 
00094    hwnd = CreateWindow (szAppName,
00095                      FullAppName,
00096                      WS_OVERLAPPEDWINDOW | WS_CAPTION, /* Window style */
00097                      CW_USEDEFAULT, 0, /* default pos. */
00098                      CW_USEDEFAULT, 0, /* default width, height */
00099                      NULL,  /* No parent */
00100                      NULL,  /* Window class menu */
00101                      hInstance, NULL);
00102    if (hwnd == NULL) {
00103        char buf[50];
00104        
00105        sprintf(buf, "CreateWindow: error code: 0x%X", GetLastError());
00106        de_error(buf);
00107        return(0);
00108    }
00109 
00110    ShowWindow (hwnd, nCmdShow);
00111 
00112    hAccel = LoadAccelerators( hInstance, szAppName );
00113    
00114    while (GetMessage (&msg, NULL, 0, 0))
00115    {
00116       if( !TranslateAccelerator( hwnd, hAccel, &msg ) )
00117       {
00118          TranslateMessage (&msg);
00119          DispatchMessage (&msg);
00120       }
00121    }
00122    return msg.wParam;
00123 }
00124 
00125 /* Return the argument with all control characters replaced by blanks.       */
00126 char * plain_chars(char * text, size_t len)
00127 {
00128     char * result = GC_MALLOC_ATOMIC(len + 1);
00129     register size_t i;
00130     
00131     for (i = 0; i < len; i++) {
00132        if (iscntrl(text[i])) {
00133            result[i] = ' ';
00134        } else {
00135            result[i] = text[i];
00136        }
00137     }
00138     result[len] = '\0';
00139     return(result);
00140 }
00141 
00142 /* Return the argument with all non-control-characters replaced by    */
00143 /* blank, and all control characters c replaced by c + 32.            */
00144 char * control_chars(char * text, size_t len)
00145 {
00146     char * result = GC_MALLOC_ATOMIC(len + 1);
00147     register size_t i;
00148     
00149     for (i = 0; i < len; i++) {
00150        if (iscntrl(text[i])) {
00151            result[i] = text[i] + 0x40;
00152        } else {
00153            result[i] = ' ';
00154        }
00155     }
00156     result[len] = '\0';
00157     return(result);
00158 }
00159 
00160 int char_width;
00161 int char_height;
00162 
00163 void get_line_rect(int line, int win_width, RECT * rectp)
00164 {
00165     rectp -> top = line * char_height;
00166     rectp -> bottom = rectp->top + char_height;
00167     rectp -> left = 0;
00168     rectp -> right = win_width;
00169 }
00170 
00171 int caret_visible = 0;      /* Caret is currently visible.     */
00172 
00173 int screen_was_painted = 0;/* Screen has been painted at least once.  */
00174 
00175 void update_cursor(void);
00176 
00177 LRESULT CALLBACK WndProc (HWND hwnd, UINT message,
00178                           WPARAM wParam, LPARAM lParam)
00179 {
00180    static FARPROC lpfnAboutBox;
00181    static HANDLE  hInstance;
00182    HDC dc;
00183    PAINTSTRUCT ps;
00184    RECT client_area;
00185    RECT this_line;
00186    RECT dummy;
00187    TEXTMETRIC tm;
00188    register int i;
00189    int id;
00190 
00191    switch (message)
00192    {
00193       case WM_CREATE:
00194            hInstance = ( (LPCREATESTRUCT) lParam)->hInstance;
00195            lpfnAboutBox = MakeProcInstance( (FARPROC) AboutBox, hInstance );
00196            dc = GetDC(hwnd);
00197            SelectObject(dc, GetStockObject(SYSTEM_FIXED_FONT));
00198            GetTextMetrics(dc, &tm);
00199            ReleaseDC(hwnd, dc);
00200            char_width = tm.tmAveCharWidth;
00201            char_height = tm.tmHeight + tm.tmExternalLeading;
00202            GetClientRect(hwnd, &client_area);
00203           COLS = (client_area.right - client_area.left)/char_width;
00204           LINES = (client_area.bottom - client_area.top)/char_height;
00205           generic_init();
00206            return(0);
00207 
00208       case WM_CHAR:
00209           if (wParam == QUIT) {
00210               SendMessage( hwnd, WM_CLOSE, 0, 0L );
00211           } else {
00212               do_command(wParam);
00213           }
00214           return(0);
00215       
00216       case WM_SETFOCUS:
00217           CreateCaret(hwnd, NULL, char_width, char_height);
00218           ShowCaret(hwnd);
00219           caret_visible = 1;
00220           update_cursor();
00221           return(0);
00222           
00223       case WM_KILLFOCUS:
00224           HideCaret(hwnd);
00225           DestroyCaret();
00226           caret_visible = 0;
00227           return(0);
00228           
00229       case WM_LBUTTONUP:
00230           {
00231               unsigned xpos = LOWORD(lParam);    /* From left  */
00232               unsigned ypos = HIWORD(lParam);    /* from top */
00233               
00234               set_position( xpos/char_width, ypos/char_height );
00235               return(0);
00236           }
00237           
00238       case WM_COMMAND:
00239           id = LOWORD(wParam);
00240           if (id & EDIT_CMD_FLAG) {
00241                if (id & REPEAT_FLAG) do_command(REPEAT);
00242                do_command(CHAR_CMD(id));
00243                return( 0 );
00244            } else {
00245              switch(id) {
00246                case IDM_FILEEXIT:
00247                   SendMessage( hwnd, WM_CLOSE, 0, 0L );
00248                   return( 0 );
00249 
00250                case IDM_HELPABOUT:
00251                   if( DialogBox( hInstance, "ABOUTBOX",
00252                                  hwnd, lpfnAboutBox ) )
00253                      InvalidateRect( hwnd, NULL, TRUE );
00254                   return( 0 );
00255               case IDM_HELPCONTENTS:
00256                 de_error(
00257                      "Cursor keys: ^B(left) ^F(right) ^P(up) ^N(down)\n"
00258                      "Undo: ^U    Write: ^W   Quit:^D  Repeat count: ^R[n]\n"
00259                      "Top: ^T   Locate (search, find): ^L text ^L\n");
00260                 return( 0 );
00261             }
00262           }
00263            break;
00264 
00265       case WM_CLOSE:
00266            DestroyWindow( hwnd );
00267            return 0;
00268 
00269       case WM_DESTROY:
00270            PostQuitMessage (0);
00271           GC_win32_free_heap();
00272            return 0;
00273       
00274       case WM_PAINT:
00275           dc = BeginPaint(hwnd, &ps);
00276           GetClientRect(hwnd, &client_area);
00277           COLS = (client_area.right - client_area.left)/char_width;
00278           LINES = (client_area.bottom - client_area.top)/char_height;
00279           SelectObject(dc, GetStockObject(SYSTEM_FIXED_FONT));
00280           for (i = 0; i < LINES; i++) {
00281               get_line_rect(i, client_area.right, &this_line);
00282               if (IntersectRect(&dummy, &this_line, &ps.rcPaint)) {
00283                   CORD raw_line = retrieve_screen_line(i);
00284                   size_t len = CORD_len(raw_line);
00285                   char * text = CORD_to_char_star(raw_line);
00286                             /* May contain embedded NULLs      */
00287                   char * plain = plain_chars(text, len);
00288                   char * blanks = CORD_to_char_star(CORD_chars(' ',
00289                                                           COLS - len));
00290                   char * control = control_chars(text, len);
00291 #                define RED RGB(255,0,0)
00292                   
00293                   SetBkMode(dc, OPAQUE);
00294                   SetTextColor(dc, GetSysColor(COLOR_WINDOWTEXT));
00295                   
00296                   TextOut(dc, this_line.left, this_line.top,
00297                         plain, len);
00298                   TextOut(dc, this_line.left + len * char_width, this_line.top,
00299                         blanks, COLS - len);
00300                   SetBkMode(dc, TRANSPARENT);
00301                   SetTextColor(dc, RED);
00302                   TextOut(dc, this_line.left, this_line.top,
00303                         control, strlen(control));
00304               }
00305           }
00306           EndPaint(hwnd, &ps);
00307           screen_was_painted = 1;
00308           return 0;
00309    }
00310    return DefWindowProc (hwnd, message, wParam, lParam);
00311 }
00312 
00313 int last_col;
00314 int last_line;
00315 
00316 void move_cursor(int c, int l)
00317 {
00318     last_col = c;
00319     last_line = l;
00320     
00321     if (caret_visible) update_cursor();
00322 }
00323 
00324 void update_cursor(void)
00325 {
00326     SetCaretPos(last_col * char_width, last_line * char_height);
00327     ShowCaret(hwnd);
00328 }
00329 
00330 void invalidate_line(int i)
00331 {
00332     RECT line;
00333     
00334     if (!screen_was_painted) return;
00335        /* Invalidating a rectangle before painting seems result in a  */
00336        /* major performance problem.                                  */
00337     get_line_rect(i, COLS*char_width, &line);
00338     InvalidateRect(hwnd, &line, FALSE);
00339 }
00340 
00341 LRESULT CALLBACK AboutBox( HWND hDlg, UINT message,
00342                            WPARAM wParam, LPARAM lParam )
00343 {
00344    switch( message )
00345    {
00346       case WM_INITDIALOG:
00347            SetFocus( GetDlgItem( hDlg, IDOK ) );
00348            break;
00349 
00350       case WM_COMMAND:
00351            switch( wParam )
00352            {
00353               case IDOK:
00354                    EndDialog( hDlg, TRUE );
00355                    break;
00356            }
00357            break;
00358 
00359       case WM_CLOSE:
00360            EndDialog( hDlg, TRUE );
00361            return TRUE;
00362 
00363    }
00364    return FALSE;
00365 }
00366