implemented Setup.hs to build boehm cpp libs and install them;
[hs-boehmgc.git] / gc-7.2 / cord / de_win.c
1 /*
2  * Copyright (c) 1994 by Xerox Corporation.  All rights reserved.
3  *
4  * THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED
5  * OR IMPLIED.  ANY USE IS AT YOUR OWN RISK.
6  *
7  * Permission is hereby granted to use or copy this program
8  * for any purpose,  provided the above notices are retained on all copies.
9  * Permission to modify the code and to distribute modified code is granted,
10  * provided the above notices are retained, and a notice that the code was
11  * modified is included with the above copyright notice.
12  */
13 /* Boehm, February 6, 1995 12:29 pm PST */
14
15 /*
16  * The MS Windows specific part of de.  
17  * This started as the generic Windows application template
18  * made available by Rob Haack (rhaack@polaris.unm.edu), but
19  * significant parts didn't survive to the final version.
20  *
21  * This was written by a nonexpert windows programmer.
22  */
23
24
25 #include "windows.h"
26 #include "gc.h"
27 #include "cord.h"
28 #include "de_cmds.h"
29 #include "de_win.h"
30
31 int LINES = 0;
32 int COLS = 0;
33
34 char       szAppName[]     = "DE";
35 char       FullAppName[]   = "Demonstration Editor";
36
37 HWND        hwnd;
38
39 void de_error(char *s)
40 {
41     MessageBox( hwnd, (LPSTR) s,
42                 (LPSTR) FullAppName,
43                 MB_ICONINFORMATION | MB_OK );
44     InvalidateRect(hwnd, NULL, TRUE);
45 }
46
47 int APIENTRY WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance,
48                       LPSTR command_line, int nCmdShow)
49 {
50    MSG         msg;
51    WNDCLASS    wndclass;
52    HANDLE      hAccel;
53
54 #  ifdef THREAD_LOCAL_ALLOC
55      GC_INIT();  /* Required if GC is built with THREAD_LOCAL_ALLOC     */
56                  /* Always safe, but this is used as a GC test.         */
57 #  endif
58
59    if (!hPrevInstance)
60    {
61       wndclass.style          = CS_HREDRAW | CS_VREDRAW;
62       wndclass.lpfnWndProc    = WndProc;
63       wndclass.cbClsExtra     = 0;
64       wndclass.cbWndExtra     = DLGWINDOWEXTRA;
65       wndclass.hInstance      = hInstance;
66       wndclass.hIcon          = LoadIcon (hInstance, szAppName);
67       wndclass.hCursor        = LoadCursor (NULL, IDC_ARROW);
68       wndclass.hbrBackground  = GetStockObject(WHITE_BRUSH);
69       wndclass.lpszMenuName   = "DE";
70       wndclass.lpszClassName  = szAppName;
71
72       if (RegisterClass (&wndclass) == 0) {
73           char buf[50];
74         
75           sprintf(buf, "RegisterClass: error code: 0x%X", GetLastError());
76           de_error(buf);
77           return(0);
78       }
79    }
80    
81    /* Empirically, the command line does not include the command name ...
82    if (command_line != 0) {
83        while (isspace(*command_line)) command_line++;
84        while (*command_line != 0 && !isspace(*command_line)) command_line++;
85        while (isspace(*command_line)) command_line++;
86    } */
87    
88    if (command_line == 0 || *command_line == 0) {
89         de_error("File name argument required");
90         return( 0 );
91    } else {
92         char *p = command_line;
93         
94         while (*p != 0 && !isspace(*p)) p++;
95         arg_file_name = CORD_to_char_star(
96                             CORD_substr(command_line, 0, p - command_line));
97    }
98
99    hwnd = CreateWindow (szAppName,
100                         FullAppName,
101                         WS_OVERLAPPEDWINDOW | WS_CAPTION, /* Window style */
102                         CW_USEDEFAULT, 0, /* default pos. */
103                         CW_USEDEFAULT, 0, /* default width, height */
104                         NULL,   /* No parent */
105                         NULL,   /* Window class menu */
106                         hInstance, NULL);
107    if (hwnd == NULL) {
108         char buf[50];
109         
110         sprintf(buf, "CreateWindow: error code: 0x%X", GetLastError());
111         de_error(buf);
112         return(0);
113    }
114
115    ShowWindow (hwnd, nCmdShow);
116
117    hAccel = LoadAccelerators( hInstance, szAppName );
118    
119    while (GetMessage (&msg, NULL, 0, 0))
120    {
121       if( !TranslateAccelerator( hwnd, hAccel, &msg ) )
122       {
123          TranslateMessage (&msg);
124          DispatchMessage (&msg);
125       }
126    }
127    return msg.wParam;
128 }
129
130 /* Return the argument with all control characters replaced by blanks.  */
131 char * plain_chars(char * text, size_t len)
132 {
133     char * result = GC_MALLOC_ATOMIC(len + 1);
134     register size_t i;
135     
136     for (i = 0; i < len; i++) {
137        if (iscntrl(text[i])) {
138            result[i] = ' ';
139        } else {
140            result[i] = text[i];
141        }
142     }
143     result[len] = '\0';
144     return(result);
145 }
146
147 /* Return the argument with all non-control-characters replaced by      */
148 /* blank, and all control characters c replaced by c + 32.              */
149 char * control_chars(char * text, size_t len)
150 {
151     char * result = GC_MALLOC_ATOMIC(len + 1);
152     register size_t i;
153     
154     for (i = 0; i < len; i++) {
155        if (iscntrl(text[i])) {
156            result[i] = text[i] + 0x40;
157        } else {
158            result[i] = ' ';
159        }
160     }
161     result[len] = '\0';
162     return(result);
163 }
164
165 int char_width;
166 int char_height;
167
168 void get_line_rect(int line, int win_width, RECT * rectp)
169 {
170     rectp -> top = line * char_height;
171     rectp -> bottom = rectp->top + char_height;
172     rectp -> left = 0;
173     rectp -> right = win_width;
174 }
175
176 int caret_visible = 0;  /* Caret is currently visible.  */
177
178 int screen_was_painted = 0;/* Screen has been painted at least once.    */
179
180 void update_cursor(void);
181
182 INT_PTR CALLBACK AboutBoxCallback( HWND hDlg, UINT message,
183                            WPARAM wParam, LPARAM lParam )
184 {
185    switch( message )
186    {
187       case WM_INITDIALOG:
188            SetFocus( GetDlgItem( hDlg, IDOK ) );
189            break;
190
191       case WM_COMMAND:
192            switch( wParam )
193            {
194               case IDOK:
195                    EndDialog( hDlg, TRUE );
196                    break;
197            }
198            break;
199
200       case WM_CLOSE:
201            EndDialog( hDlg, TRUE );
202            return TRUE;
203
204    }
205    return FALSE;
206 }
207
208 LRESULT CALLBACK WndProc (HWND hwnd, UINT message,
209                           WPARAM wParam, LPARAM lParam)
210 {
211    static HANDLE  hInstance;
212    HDC dc;
213    PAINTSTRUCT ps;
214    RECT client_area;
215    RECT this_line;
216    RECT dummy;
217    TEXTMETRIC tm;
218    register int i;
219    int id;
220
221    switch (message)
222    {
223       case WM_CREATE:
224            hInstance = ( (LPCREATESTRUCT) lParam)->hInstance;
225            dc = GetDC(hwnd);
226            SelectObject(dc, GetStockObject(SYSTEM_FIXED_FONT));
227            GetTextMetrics(dc, &tm);
228            ReleaseDC(hwnd, dc);
229            char_width = tm.tmAveCharWidth;
230            char_height = tm.tmHeight + tm.tmExternalLeading;
231            GetClientRect(hwnd, &client_area);
232            COLS = (client_area.right - client_area.left)/char_width;
233            LINES = (client_area.bottom - client_area.top)/char_height;
234            generic_init();
235            return(0);
236
237       case WM_CHAR:
238            if (wParam == QUIT) {
239                SendMessage( hwnd, WM_CLOSE, 0, 0L );
240            } else {
241                do_command((int)wParam);
242            }
243            return(0);
244       
245       case WM_SETFOCUS:
246            CreateCaret(hwnd, NULL, char_width, char_height);
247            ShowCaret(hwnd);
248            caret_visible = 1;
249            update_cursor();
250            return(0);
251            
252       case WM_KILLFOCUS:
253            HideCaret(hwnd);
254            DestroyCaret();
255            caret_visible = 0;
256            return(0);
257            
258       case WM_LBUTTONUP:
259            {
260                unsigned xpos = LOWORD(lParam);  /* From left    */
261                unsigned ypos = HIWORD(lParam);  /* from top */
262                
263                set_position( xpos/char_width, ypos/char_height );
264                return(0);
265            }
266            
267       case WM_COMMAND:
268            id = LOWORD(wParam);
269            if (id & EDIT_CMD_FLAG) {
270                if (id & REPEAT_FLAG) do_command(REPEAT);
271                do_command(CHAR_CMD(id));
272                return( 0 );
273            } else {
274              switch(id) {
275                case IDM_FILEEXIT:
276                   SendMessage( hwnd, WM_CLOSE, 0, 0L );
277                   return( 0 );
278
279                case IDM_HELPABOUT:
280                   if( DialogBox( hInstance, "ABOUTBOX",
281                                  hwnd, AboutBoxCallback ) )
282                      InvalidateRect( hwnd, NULL, TRUE );
283                   return( 0 );
284                case IDM_HELPCONTENTS:
285                   de_error(
286                        "Cursor keys: ^B(left) ^F(right) ^P(up) ^N(down)\n"
287                        "Undo: ^U    Write: ^W   Quit:^D  Repeat count: ^R[n]\n"
288                        "Top: ^T   Locate (search, find): ^L text ^L\n");
289                   return( 0 );
290              }
291            }
292            break;
293
294       case WM_CLOSE:
295            DestroyWindow( hwnd );
296            return 0;
297
298       case WM_DESTROY:
299            PostQuitMessage (0);
300            GC_win32_free_heap();
301            return 0;
302       
303       case WM_PAINT:
304            dc = BeginPaint(hwnd, &ps);
305            GetClientRect(hwnd, &client_area);
306            COLS = (client_area.right - client_area.left)/char_width;
307            LINES = (client_area.bottom - client_area.top)/char_height;
308            SelectObject(dc, GetStockObject(SYSTEM_FIXED_FONT));
309            for (i = 0; i < LINES; i++) {
310                get_line_rect(i, client_area.right, &this_line);
311                if (IntersectRect(&dummy, &this_line, &ps.rcPaint)) {
312                    CORD raw_line = retrieve_screen_line(i);
313                    size_t len = CORD_len(raw_line);
314                    char * text = CORD_to_char_star(raw_line);
315                                 /* May contain embedded NULLs   */
316                    char * plain = plain_chars(text, len);
317                    char * blanks = CORD_to_char_star(CORD_chars(' ',
318                                                                 COLS - len));
319                    char * control = control_chars(text, len);
320 #                  define RED RGB(255,0,0)
321                    
322                    SetBkMode(dc, OPAQUE);
323                    SetTextColor(dc, GetSysColor(COLOR_WINDOWTEXT));
324                    
325                    TextOut(dc, this_line.left, this_line.top,
326                            plain, (int)len);
327                    TextOut(dc, this_line.left + (int)len * char_width,
328                            this_line.top,
329                            blanks, (int)(COLS - len));
330                    SetBkMode(dc, TRANSPARENT);
331                    SetTextColor(dc, RED);
332                    TextOut(dc, this_line.left, this_line.top,
333                            control, (int)strlen(control));
334                }
335            }
336            EndPaint(hwnd, &ps);
337            screen_was_painted = 1;
338            return 0;
339    }
340    return DefWindowProc (hwnd, message, wParam, lParam);
341 }
342
343 int last_col;
344 int last_line;
345
346 void move_cursor(int c, int l)
347 {
348     last_col = c;
349     last_line = l;
350     
351     if (caret_visible) update_cursor();
352 }
353
354 void update_cursor(void)
355 {
356     SetCaretPos(last_col * char_width, last_line * char_height);
357     ShowCaret(hwnd);
358 }
359
360 void invalidate_line(int i)
361 {
362     RECT line;
363     
364     if (!screen_was_painted) return;
365         /* Invalidating a rectangle before painting seems result in a   */
366         /* major performance problem.                                   */
367     get_line_rect(i, COLS*char_width, &line);
368     InvalidateRect(hwnd, &line, FALSE);
369 }
370