]>
Commit | Line | Data |
---|---|---|
73ffefd0 TT |
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 | if (!hPrevInstance) | |
55 | { | |
56 | wndclass.style = CS_HREDRAW | CS_VREDRAW; | |
57 | wndclass.lpfnWndProc = WndProc; | |
58 | wndclass.cbClsExtra = 0; | |
59 | wndclass.cbWndExtra = DLGWINDOWEXTRA; | |
60 | wndclass.hInstance = hInstance; | |
61 | wndclass.hIcon = LoadIcon (hInstance, szAppName); | |
62 | wndclass.hCursor = LoadCursor (NULL, IDC_ARROW); | |
63 | wndclass.hbrBackground = GetStockObject(WHITE_BRUSH); | |
64 | wndclass.lpszMenuName = "DE"; | |
65 | wndclass.lpszClassName = szAppName; | |
66 | ||
67 | if (RegisterClass (&wndclass) == 0) { | |
68 | char buf[50]; | |
69 | ||
70 | sprintf(buf, "RegisterClass: error code: 0x%X", GetLastError()); | |
71 | de_error(buf); | |
72 | return(0); | |
73 | } | |
74 | } | |
75 | ||
76 | /* Empirically, the command line does not include the command name ... | |
77 | if (command_line != 0) { | |
78 | while (isspace(*command_line)) command_line++; | |
79 | while (*command_line != 0 && !isspace(*command_line)) command_line++; | |
80 | while (isspace(*command_line)) command_line++; | |
81 | } */ | |
82 | ||
83 | if (command_line == 0 || *command_line == 0) { | |
84 | de_error("File name argument required"); | |
85 | return( 0 ); | |
86 | } else { | |
87 | char *p = command_line; | |
88 | ||
89 | while (*p != 0 && !isspace(*p)) p++; | |
90 | arg_file_name = CORD_to_char_star( | |
91 | CORD_substr(command_line, 0, p - command_line)); | |
92 | } | |
93 | ||
94 | hwnd = CreateWindow (szAppName, | |
95 | FullAppName, | |
96 | WS_OVERLAPPEDWINDOW | WS_CAPTION, /* Window style */ | |
97 | CW_USEDEFAULT, 0, /* default pos. */ | |
98 | CW_USEDEFAULT, 0, /* default width, height */ | |
99 | NULL, /* No parent */ | |
100 | NULL, /* Window class menu */ | |
101 | hInstance, NULL); | |
102 | if (hwnd == NULL) { | |
103 | char buf[50]; | |
104 | ||
105 | sprintf(buf, "CreateWindow: error code: 0x%X", GetLastError()); | |
106 | de_error(buf); | |
107 | return(0); | |
108 | } | |
109 | ||
110 | ShowWindow (hwnd, nCmdShow); | |
111 | ||
112 | hAccel = LoadAccelerators( hInstance, szAppName ); | |
113 | ||
114 | while (GetMessage (&msg, NULL, 0, 0)) | |
115 | { | |
116 | if( !TranslateAccelerator( hwnd, hAccel, &msg ) ) | |
117 | { | |
118 | TranslateMessage (&msg); | |
119 | DispatchMessage (&msg); | |
120 | } | |
121 | } | |
122 | return msg.wParam; | |
123 | } | |
124 | ||
125 | /* Return the argument with all control characters replaced by blanks. */ | |
126 | char * plain_chars(char * text, size_t len) | |
127 | { | |
128 | char * result = GC_MALLOC_ATOMIC(len + 1); | |
129 | register size_t i; | |
130 | ||
131 | for (i = 0; i < len; i++) { | |
132 | if (iscntrl(text[i])) { | |
133 | result[i] = ' '; | |
134 | } else { | |
135 | result[i] = text[i]; | |
136 | } | |
137 | } | |
138 | result[len] = '\0'; | |
139 | return(result); | |
140 | } | |
141 | ||
142 | /* Return the argument with all non-control-characters replaced by */ | |
143 | /* blank, and all control characters c replaced by c + 32. */ | |
144 | char * control_chars(char * text, size_t len) | |
145 | { | |
146 | char * result = GC_MALLOC_ATOMIC(len + 1); | |
147 | register size_t i; | |
148 | ||
149 | for (i = 0; i < len; i++) { | |
150 | if (iscntrl(text[i])) { | |
151 | result[i] = text[i] + 0x40; | |
152 | } else { | |
153 | result[i] = ' '; | |
154 | } | |
155 | } | |
156 | result[len] = '\0'; | |
157 | return(result); | |
158 | } | |
159 | ||
160 | int char_width; | |
161 | int char_height; | |
162 | ||
163 | void get_line_rect(int line, int win_width, RECT * rectp) | |
164 | { | |
165 | rectp -> top = line * char_height; | |
166 | rectp -> bottom = rectp->top + char_height; | |
167 | rectp -> left = 0; | |
168 | rectp -> right = win_width; | |
169 | } | |
170 | ||
171 | int caret_visible = 0; /* Caret is currently visible. */ | |
172 | ||
173 | int screen_was_painted = 0;/* Screen has been painted at least once. */ | |
174 | ||
175 | void update_cursor(void); | |
176 | ||
177 | LRESULT CALLBACK WndProc (HWND hwnd, UINT message, | |
178 | WPARAM wParam, LPARAM lParam) | |
179 | { | |
180 | static FARPROC lpfnAboutBox; | |
181 | static HANDLE hInstance; | |
182 | HDC dc; | |
183 | PAINTSTRUCT ps; | |
184 | RECT client_area; | |
185 | RECT this_line; | |
186 | RECT dummy; | |
187 | TEXTMETRIC tm; | |
188 | register int i; | |
189 | int id; | |
190 | ||
191 | switch (message) | |
192 | { | |
193 | case WM_CREATE: | |
194 | hInstance = ( (LPCREATESTRUCT) lParam)->hInstance; | |
195 | lpfnAboutBox = MakeProcInstance( (FARPROC) AboutBox, hInstance ); | |
196 | dc = GetDC(hwnd); | |
197 | SelectObject(dc, GetStockObject(SYSTEM_FIXED_FONT)); | |
198 | GetTextMetrics(dc, &tm); | |
199 | ReleaseDC(hwnd, dc); | |
200 | char_width = tm.tmAveCharWidth; | |
201 | char_height = tm.tmHeight + tm.tmExternalLeading; | |
202 | GetClientRect(hwnd, &client_area); | |
203 | COLS = (client_area.right - client_area.left)/char_width; | |
204 | LINES = (client_area.bottom - client_area.top)/char_height; | |
205 | generic_init(); | |
206 | return(0); | |
207 | ||
208 | case WM_CHAR: | |
209 | if (wParam == QUIT) { | |
210 | SendMessage( hwnd, WM_CLOSE, 0, 0L ); | |
211 | } else { | |
212 | do_command(wParam); | |
213 | } | |
214 | return(0); | |
215 | ||
216 | case WM_SETFOCUS: | |
217 | CreateCaret(hwnd, NULL, char_width, char_height); | |
218 | ShowCaret(hwnd); | |
219 | caret_visible = 1; | |
220 | update_cursor(); | |
221 | return(0); | |
222 | ||
223 | case WM_KILLFOCUS: | |
224 | HideCaret(hwnd); | |
225 | DestroyCaret(); | |
226 | caret_visible = 0; | |
227 | return(0); | |
228 | ||
229 | case WM_LBUTTONUP: | |
230 | { | |
231 | unsigned xpos = LOWORD(lParam); /* From left */ | |
232 | unsigned ypos = HIWORD(lParam); /* from top */ | |
233 | ||
234 | set_position( xpos/char_width, ypos/char_height ); | |
235 | return(0); | |
236 | } | |
237 | ||
238 | case WM_COMMAND: | |
239 | id = LOWORD(wParam); | |
240 | if (id & EDIT_CMD_FLAG) { | |
241 | if (id & REPEAT_FLAG) do_command(REPEAT); | |
242 | do_command(CHAR_CMD(id)); | |
243 | return( 0 ); | |
244 | } else { | |
245 | switch(id) { | |
246 | case IDM_FILEEXIT: | |
247 | SendMessage( hwnd, WM_CLOSE, 0, 0L ); | |
248 | return( 0 ); | |
249 | ||
250 | case IDM_HELPABOUT: | |
251 | if( DialogBox( hInstance, "ABOUTBOX", | |
30c3de1f | 252 | hwnd, lpfnAboutBox ) ) |
73ffefd0 TT |
253 | InvalidateRect( hwnd, NULL, TRUE ); |
254 | return( 0 ); | |
255 | case IDM_HELPCONTENTS: | |
256 | de_error( | |
257 | "Cursor keys: ^B(left) ^F(right) ^P(up) ^N(down)\n" | |
258 | "Undo: ^U Write: ^W Quit:^D Repeat count: ^R[n]\n" | |
259 | "Top: ^T Locate (search, find): ^L text ^L\n"); | |
260 | return( 0 ); | |
261 | } | |
262 | } | |
263 | break; | |
264 | ||
265 | case WM_CLOSE: | |
266 | DestroyWindow( hwnd ); | |
267 | return 0; | |
268 | ||
269 | case WM_DESTROY: | |
270 | PostQuitMessage (0); | |
56ba54b4 | 271 | GC_win32_free_heap(); |
73ffefd0 TT |
272 | return 0; |
273 | ||
274 | case WM_PAINT: | |
275 | dc = BeginPaint(hwnd, &ps); | |
276 | GetClientRect(hwnd, &client_area); | |
277 | COLS = (client_area.right - client_area.left)/char_width; | |
278 | LINES = (client_area.bottom - client_area.top)/char_height; | |
279 | SelectObject(dc, GetStockObject(SYSTEM_FIXED_FONT)); | |
280 | for (i = 0; i < LINES; i++) { | |
281 | get_line_rect(i, client_area.right, &this_line); | |
282 | if (IntersectRect(&dummy, &this_line, &ps.rcPaint)) { | |
283 | CORD raw_line = retrieve_screen_line(i); | |
284 | size_t len = CORD_len(raw_line); | |
285 | char * text = CORD_to_char_star(raw_line); | |
286 | /* May contain embedded NULLs */ | |
287 | char * plain = plain_chars(text, len); | |
288 | char * blanks = CORD_to_char_star(CORD_chars(' ', | |
289 | COLS - len)); | |
290 | char * control = control_chars(text, len); | |
291 | # define RED RGB(255,0,0) | |
292 | ||
293 | SetBkMode(dc, OPAQUE); | |
294 | SetTextColor(dc, GetSysColor(COLOR_WINDOWTEXT)); | |
295 | ||
296 | TextOut(dc, this_line.left, this_line.top, | |
297 | plain, len); | |
298 | TextOut(dc, this_line.left + len * char_width, this_line.top, | |
299 | blanks, COLS - len); | |
300 | SetBkMode(dc, TRANSPARENT); | |
301 | SetTextColor(dc, RED); | |
302 | TextOut(dc, this_line.left, this_line.top, | |
303 | control, strlen(control)); | |
304 | } | |
305 | } | |
306 | EndPaint(hwnd, &ps); | |
307 | screen_was_painted = 1; | |
308 | return 0; | |
309 | } | |
310 | return DefWindowProc (hwnd, message, wParam, lParam); | |
311 | } | |
312 | ||
313 | int last_col; | |
314 | int last_line; | |
315 | ||
316 | void move_cursor(int c, int l) | |
317 | { | |
318 | last_col = c; | |
319 | last_line = l; | |
320 | ||
321 | if (caret_visible) update_cursor(); | |
322 | } | |
323 | ||
324 | void update_cursor(void) | |
325 | { | |
326 | SetCaretPos(last_col * char_width, last_line * char_height); | |
327 | ShowCaret(hwnd); | |
328 | } | |
329 | ||
330 | void invalidate_line(int i) | |
331 | { | |
332 | RECT line; | |
333 | ||
334 | if (!screen_was_painted) return; | |
335 | /* Invalidating a rectangle before painting seems result in a */ | |
336 | /* major performance problem. */ | |
337 | get_line_rect(i, COLS*char_width, &line); | |
338 | InvalidateRect(hwnd, &line, FALSE); | |
339 | } | |
340 | ||
341 | LRESULT CALLBACK AboutBox( HWND hDlg, UINT message, | |
342 | WPARAM wParam, LPARAM lParam ) | |
343 | { | |
344 | switch( message ) | |
345 | { | |
346 | case WM_INITDIALOG: | |
347 | SetFocus( GetDlgItem( hDlg, IDOK ) ); | |
348 | break; | |
349 | ||
350 | case WM_COMMAND: | |
351 | switch( wParam ) | |
352 | { | |
353 | case IDOK: | |
354 | EndDialog( hDlg, TRUE ); | |
355 | break; | |
356 | } | |
357 | break; | |
358 | ||
359 | case WM_CLOSE: | |
360 | EndDialog( hDlg, TRUE ); | |
361 | return TRUE; | |
362 | ||
363 | } | |
364 | return FALSE; | |
365 | } | |
366 |