install script for wine dlls and programs
[reactos.git] / reactos / apps / utils / notepad / main.c
1 /*
2 * Notepad
3 *
4 * Copyright 2000 Mike McCormack <Mike_McCormack@looksmart.com.au>
5 * Copyright 1997,98 Marcel Baur <mbaur@g26.ethz.ch>
6 * To be distributed under the Wine License
7 *
8 * FIXME,TODO list:
9 * - Use wine Heap instead of malloc/free (done)
10 * - use scroll bars (vertical done)
11 * - cut 'n paste (clipboard)
12 * - save file
13 * - print file
14 * - find dialog
15 * - encapsulate data structures (?) - half done
16 * - free unused memory
17 * - solve Open problems
18 * - smoother scrolling
19 * - separate view code and document code
20 *
21 * This program is intended as a testbed for winelib as much as
22 * a useful application.
23 */
24
25 #include <stdio.h>
26 #include "windows.h"
27
28 #ifdef LCC
29 #include "lcc.h"
30 #endif
31
32 #include "main.h"
33 #include "license.h"
34 #include "dialog.h"
35 #include "language.h"
36
37 extern BOOL DoCloseFile(void);
38 extern void DoOpenFile(LPCSTR szFileName);
39
40 NOTEPAD_GLOBALS Globals;
41
42
43 /* Using a pointer to pointer data structure to
44 achieve a little more efficiency. Hopefully
45 it will be worth it, because it complicates the
46 code - mjm 26 Jun 2000 */
47
48 #define BUFFERCHUNKSIZE 0xe0
49 typedef struct TAGLine {
50 LPSTR lpLine;
51 DWORD dwWidth;
52 DWORD dwMaxWidth;
53 } LINE, *LPLINE;
54
55 /* FIXME: make this info into a structure */
56 /* typedef struct tagBUFFER { */
57 DWORD dwVOffset=0;
58 DWORD dwLines=0;
59 DWORD dwMaxLines=0;
60 LPLINE lpBuffer=NULL;
61 DWORD dwXpos=0,dwYpos=0; /* position of caret in char coords */
62 DWORD dwCaretXpos=0,dwCaretYpos=0; /* position of caret in pixel coords */
63 TEXTMETRIC tm; /* textmetric for current font */
64 RECT rectClient; /* client rectangle of the window we're drawing in */
65 /* } BUFFER, *LPBUFFER */
66
67 VOID InitFontInfo(HWND hWnd)
68 {
69 HDC hDC = GetDC(hWnd);
70
71 if(hDC)
72 {
73 GetTextMetrics(hDC, &tm);
74 ReleaseDC(hWnd,hDC);
75 }
76 }
77
78 void InitBuffer(void)
79 {
80 lpBuffer = NULL;
81 dwLines = 0;
82 dwMaxLines = 0;
83 dwXpos=0;
84 dwYpos=0;
85 }
86
87 /* convert x,y character co-ords into x pixel co-ord */
88 DWORD CalcStringWidth(HDC hDC, DWORD x, DWORD y)
89 {
90 DWORD len;
91 SIZE size;
92
93 size.cx = 0;
94 size.cy = 0;
95
96 if(y>dwLines)
97 return size.cx;
98 if(lpBuffer == NULL)
99 return size.cx;
100 if(lpBuffer[y].lpLine == NULL)
101 return size.cx;
102 len = (x<lpBuffer[y].dwWidth) ?
103 x : lpBuffer[y].dwWidth;
104 GetTextExtentPoint(hDC, lpBuffer[y].lpLine, len, &size);
105
106 return size.cx;
107 }
108
109 void CalcCaretPos(HDC hDC, DWORD dwXpos, DWORD dwYpos)
110 {
111 dwCaretXpos = CalcStringWidth(hDC, dwXpos, dwYpos);
112 dwCaretYpos = tm.tmHeight*(dwYpos-dwVOffset);
113 SetCaretPos(dwCaretXpos,dwCaretYpos);
114 }
115
116 DWORD GetLinesPerPage(HWND hWnd)
117 {
118 return (rectClient.bottom/tm.tmHeight); /* round down */
119 }
120
121 /* render one line of text and blank space */
122 void RenderLine(HDC hDC, DWORD lineno)
123 {
124 RECT rect;
125 HBRUSH hPrev;
126
127 if(!hDC)
128 return;
129
130 /* erase the space at the end of a line using a white rectangle */
131 rect.top = tm.tmHeight*(lineno-dwVOffset);
132 rect.bottom = tm.tmHeight*(lineno-dwVOffset+1);
133
134 if(lpBuffer && (lineno<dwLines))
135 rect.left = CalcStringWidth(hDC, lpBuffer[lineno].dwWidth,lineno);
136 else
137 rect.left = 0;
138 rect.right = rectClient.right;
139
140 /* use the white pen so there's not outline */
141 hPrev = SelectObject(hDC, GetStockObject(WHITE_PEN));
142 Rectangle(hDC, rect.left, rect.top, rect.right, rect.bottom);
143 SelectObject(hDC, hPrev);
144
145 if(lpBuffer && lpBuffer[lineno].lpLine)
146 {
147 TextOut(hDC, 0, rect.top, lpBuffer[lineno].lpLine,
148 lpBuffer[lineno].dwWidth);
149 }
150 }
151
152 /*
153 * Paint the buffer onto the window.
154 */
155 void RenderWindow(HDC hDC) {
156 DWORD i;
157
158 if(!hDC)
159 return;
160
161 /* FIXME: render only necessary lines */
162 for(i = dwVOffset; i < (dwVOffset+GetLinesPerPage(0)); i++)
163 {
164 RenderLine(hDC,i);
165 }
166 }
167
168 /*
169 * Check that correct buffers exist to access line y pos x
170 * Only manages memory.
171 *
172 * Returns TRUE if the line is accessable
173 * FALSE if there is a problem
174 */
175 BOOL ValidateLine(DWORD y,DWORD x)
176 {
177 DWORD max;
178
179 /* check to see that the BUFFER has enough lines */
180 max = dwMaxLines;
181 if( (max<=y) || (lpBuffer == NULL))
182 {
183 while(max<=y)
184 max += BUFFERCHUNKSIZE;
185 /* use GlobalAlloc first time round */
186 if(lpBuffer)
187 lpBuffer = (LPLINE) GlobalReAlloc((HGLOBAL)lpBuffer,GMEM_FIXED,
188 max*sizeof(LINE)) ;
189 else
190 lpBuffer = (LPLINE) GlobalAlloc(GMEM_FIXED, max*sizeof(LINE));
191 if(lpBuffer == NULL)
192 return FALSE;
193 ZeroMemory(&lpBuffer[dwLines], sizeof(LINE)*(max-dwLines) );
194 dwMaxLines = max;
195 }
196
197 /* check to see that the LINE is wide enough */
198 max = lpBuffer[y].dwMaxWidth;
199 if( (max <= x) || (lpBuffer[y].lpLine == NULL) )
200 {
201 while(max <= x)
202 max += BUFFERCHUNKSIZE;
203 /* use GlobalAlloc first */
204 if(lpBuffer[y].lpLine)
205 lpBuffer[y].lpLine = (LPSTR)GlobalReAlloc((HGLOBAL)lpBuffer[y].lpLine,
206 GMEM_FIXED, max) ;
207 else
208 lpBuffer[y].lpLine = (LPSTR)GlobalAlloc( GMEM_FIXED, max);
209 if(lpBuffer[y].lpLine == NULL)
210 return FALSE;
211 lpBuffer[y].dwWidth = 0;
212 lpBuffer[y].dwMaxWidth = max;
213 }
214 return TRUE;
215 }
216
217 /* inserts a new line into the buffer */
218 BOOL DoNewLine(HDC hDC)
219 {
220 DWORD i,cnt;
221 LPSTR src,dst;
222
223 /* check to see if we need more memory for the buffer pointers */
224 if(!ValidateLine(dwLines,0))
225 return FALSE;
226
227 /* shuffle up all the lines */
228 for(i=dwLines; i>(dwYpos+1); i--)
229 {
230 lpBuffer[i] = lpBuffer[i-1];
231 RenderLine(hDC,i);
232 }
233 ZeroMemory(&lpBuffer[dwYpos+1],sizeof(LINE));
234
235 /* copy the characters after the carat (if any) to the next line */
236 src = &lpBuffer[dwYpos].lpLine[dwXpos];
237 cnt = lpBuffer[dwYpos].dwWidth-dwXpos;
238 if(!ValidateLine(dwYpos+1,cnt)) /* allocates the buffer */
239 return FALSE; /* FIXME */
240 dst = &lpBuffer[dwYpos+1].lpLine[0];
241 memcpy(dst, src, cnt);
242 lpBuffer[dwYpos+1].dwWidth = cnt;
243 lpBuffer[dwYpos].dwWidth -= cnt;
244
245 /* move the cursor */
246 dwLines++;
247 dwXpos = 0;
248 dwYpos++;
249
250 /* update the window */
251 RenderLine(hDC, dwYpos-1);
252 RenderLine(hDC, dwYpos);
253 CalcCaretPos(hDC, dwXpos, dwYpos);
254 /* FIXME: don't use globals */
255 SetScrollRange(Globals.hMainWnd, SB_VERT, 0, dwLines, TRUE);
256
257 return TRUE;
258 }
259
260 /*
261 * Attempt a basic edit buffer
262 */
263 BOOL AddCharToBuffer(HDC hDC, char ch)
264 {
265 /* we can use lpBuffer[dwYpos] */
266 if(!ValidateLine(dwYpos,0))
267 return FALSE;
268
269 /* shuffle the rest of the line*/
270 if(!ValidateLine(dwYpos, lpBuffer[dwYpos].dwWidth))
271 return FALSE;
272 lpBuffer[dwYpos].dwWidth++;
273 memmove(&lpBuffer[dwYpos].lpLine[dwXpos+1],
274 &lpBuffer[dwYpos].lpLine[dwXpos],
275 lpBuffer[dwYpos].dwWidth-dwXpos);
276
277 /* add the character */
278 lpBuffer[dwYpos].lpLine[dwXpos] = ch;
279 if(dwLines == 0)
280 dwLines++;
281 dwXpos++;
282
283 /* update the window and cursor position */
284 RenderLine(hDC,dwYpos);
285 CalcCaretPos(hDC,dwXpos,dwYpos);
286
287 return TRUE;
288 }
289
290
291 /* erase a character */
292 BOOL DoBackSpace(HDC hDC)
293 {
294 DWORD i;
295
296 if(lpBuffer == NULL)
297 return FALSE;
298 if(lpBuffer[dwYpos].lpLine && (dwXpos>0))
299 {
300 dwXpos --;
301 /* FIXME: use memmove */
302 for(i=dwXpos; i<(lpBuffer[dwYpos].dwWidth-1); i++)
303 lpBuffer[dwYpos].lpLine[i]=lpBuffer[dwYpos].lpLine[i+1];
304
305 lpBuffer[dwYpos].dwWidth--;
306 RenderLine(hDC, dwYpos);
307 CalcCaretPos(hDC,dwXpos,dwYpos);
308 }
309 else
310 {
311 /* Erase a newline. To do this we join two lines */
312 LPSTR src, dest;
313 DWORD len, oldlen;
314
315 if(dwYpos==0)
316 return FALSE;
317
318 oldlen = lpBuffer[dwYpos-1].dwWidth;
319 if(lpBuffer[dwYpos-1].lpLine&&lpBuffer[dwYpos].lpLine)
320 {
321 /* concatonate to the end of the line above line */
322 src = &lpBuffer[dwYpos].lpLine[0];
323 dest = &lpBuffer[dwYpos-1].lpLine[lpBuffer[dwYpos-1].dwWidth];
324 len = lpBuffer[dwYpos].dwWidth;
325
326 /* check the length of the new line */
327 if(!ValidateLine(dwYpos-1,lpBuffer[dwYpos-1].dwWidth + len))
328 return FALSE;
329
330 memcpy(dest,src,len);
331 lpBuffer[dwYpos-1].dwWidth+=len;
332 GlobalFree( (HGLOBAL)lpBuffer[dwYpos].lpLine);
333 }
334 else if (!lpBuffer[dwYpos-1].lpLine)
335 {
336 lpBuffer[dwYpos-1]=lpBuffer[dwYpos];
337 } /* else both are NULL */
338 RenderLine(hDC,dwYpos-1);
339
340 /* don't zero - it's going to get trashed anyhow */
341
342 /* shuffle up all the lines below this one */
343 for(i=dwYpos; i<(dwLines-1); i++)
344 {
345 lpBuffer[i] = lpBuffer[i+1];
346 RenderLine(hDC,i);
347 }
348
349 /* clear the last line */
350 ZeroMemory(&lpBuffer[dwLines-1],sizeof (LINE));
351 RenderLine(hDC,dwLines-1);
352 dwLines--;
353
354 /* adjust the cursor position to joining point */
355 dwYpos--;
356 dwXpos = oldlen;
357
358 CalcCaretPos(hDC,dwXpos,dwYpos);
359 SetScrollRange(Globals.hMainWnd, SB_VERT, 0, dwLines, TRUE);
360 }
361 return TRUE;
362 }
363
364 /* as used by File->New */
365 void TrashBuffer(void)
366 {
367 DWORD i;
368
369 /* variables belonging to the buffer */
370 if(lpBuffer)
371 {
372 for(i=0; i<dwLines; i++)
373 {
374 if(lpBuffer[i].lpLine)
375 GlobalFree ((HGLOBAL)lpBuffer[i].lpLine);
376 ZeroMemory(&lpBuffer[i],sizeof (LINE));
377 }
378 GlobalFree((HGLOBAL)lpBuffer);
379 lpBuffer=NULL;
380 }
381 dwLines = 0;
382 dwMaxLines = 0;
383
384 /* variables belonging to the view */
385 dwXpos = 0;
386 dwYpos = 0;
387 dwVOffset = 0 ;
388 /* FIXME: don't use globals */
389 SetScrollPos(Globals.hMainWnd, SB_VERT, dwVOffset, FALSE);
390 SetScrollRange(Globals.hMainWnd, SB_VERT, 0, dwLines, TRUE);
391 }
392
393
394 /*
395 * Add a line to the buffer
396 */
397 /* FIXME: this breaks lines longer than BUFFERCHUNKSIZE */
398 DWORD CreateLine(
399 LPSTR buffer, /* pointer to buffer with file data */
400 DWORD size, /* number of bytes available in buffer */
401 BOOL nomore)
402 {
403 DWORD i;
404
405 if(size == 0)
406 return 0;
407
408 for(i=0; i<size; i++)
409 {
410 if(buffer[i]==0x0a)
411 {
412 if(ValidateLine(dwLines,i))
413 {
414 memcpy(&lpBuffer[dwLines].lpLine[0],&buffer[0],i);
415 lpBuffer[dwLines].dwWidth = i;
416 dwLines++;
417 }
418 return i+1;
419 }
420 }
421
422 /* make a line of the rest */
423 if( (i == BUFFERCHUNKSIZE) || nomore )
424 {
425 if(ValidateLine(dwLines,i))
426 {
427 memcpy(&lpBuffer[dwLines].lpLine[0],&buffer[0],i);
428 lpBuffer[dwLines].dwWidth = i;
429 dwLines++;
430 }
431 return i;
432 }
433
434 return 0;
435 }
436
437
438 /*
439 * This is probably overcomplicated by lpBuffer data structure...
440 * Read blocks from the file, then add each line from the
441 * block to the buffer until there is none left. If all
442 * a slab isn't used, try load some more data from the file.
443 */
444 void LoadBufferFromFile(LPCSTR szFileName)
445 {
446 HANDLE hFile;
447 CHAR *pTemp;
448 DWORD size,i,len,bytes_left,bytes_read;
449
450 hFile = CreateFile(szFileName, GENERIC_READ, FILE_SHARE_READ, NULL,
451 OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
452 if(hFile == INVALID_HANDLE_VALUE)
453 return;
454 size = BUFFERCHUNKSIZE;
455 pTemp = (LPSTR) GlobalAlloc(GMEM_FIXED, size);
456 if(!pTemp)
457 return;
458 bytes_read = 1; /* anything non-zero */
459 bytes_left = 0;
460 while(bytes_read)
461 {
462 if(!ReadFile(hFile,
463 &pTemp[bytes_left],
464 size-bytes_left,
465 &bytes_read, NULL))
466 break;
467 bytes_left+=bytes_read;
468
469 /* add strings to buffer */
470 for(i = 0;
471 (i<size) &&
472 (len = CreateLine(&pTemp[i], bytes_left, !bytes_read));
473 i+= len,bytes_left-=len );
474
475 /* move leftover to front of buffer */
476 if(bytes_left)
477 memmove(&pTemp[0],&pTemp[i], bytes_left);
478 }
479 CloseHandle(hFile);
480 MessageBox(Globals.hMainWnd, "Finished", "Info", MB_OK);
481 }
482
483 BOOL DoInput(HDC hDC, WPARAM wParam, LPARAM lParam)
484 {
485 switch(wParam)
486 {
487 case 0x08:
488 return DoBackSpace(hDC);
489 case 0x0d:
490 return DoNewLine(hDC);
491 default:
492 return AddCharToBuffer(hDC,wParam);
493 }
494 }
495
496 BOOL GotoHome(HWND hWnd)
497 {
498 dwXpos = 0;
499 dwYpos = 0;
500 dwVOffset = 0;
501 return TRUE;
502 }
503
504 BOOL GotoEndOfLine(HWND hWnd)
505 {
506 dwXpos = lpBuffer[dwYpos].dwWidth;
507 return TRUE;
508 }
509
510 BOOL GotoDown(HWND hWnd)
511 {
512 if((dwYpos+1) >= dwLines)
513 {
514 return FALSE;
515 }
516 dwYpos++;
517 if (dwXpos>lpBuffer[dwYpos].dwWidth)
518 GotoEndOfLine(hWnd);
519 return TRUE;
520 }
521
522 BOOL GotoUp(HWND hWnd)
523 {
524 if(dwYpos==0)
525 return FALSE;
526 dwYpos--;
527 if (dwXpos>lpBuffer[dwYpos].dwWidth)
528 GotoEndOfLine(hWnd);
529 return TRUE;
530 }
531
532 BOOL GotoLeft(HWND hWnd)
533 {
534 if(dwXpos > 0)
535 {
536 dwXpos--;
537 return TRUE;
538 }
539 if(GotoUp(hWnd))
540 return GotoEndOfLine(hWnd);
541 return FALSE;
542 }
543
544 BOOL GotoRight(HWND hWnd)
545 {
546 if(dwXpos<lpBuffer[dwYpos].dwWidth)
547 {
548 dwXpos++;
549 return TRUE;
550 }
551 if(!GotoDown(hWnd))
552 return FALSE;
553 dwXpos=0;
554 return TRUE;
555 }
556
557 /* check the caret is still on the screen */
558 BOOL ScrollABit(HWND hWnd)
559 {
560 if(dwYpos<dwVOffset)
561 {
562 dwVOffset = dwYpos;
563 return TRUE;
564 }
565 if(dwYpos>(dwVOffset+GetLinesPerPage(hWnd)))
566 {
567 dwVOffset = dwYpos - GetLinesPerPage(hWnd) + 1;
568 return TRUE;
569 }
570 return FALSE;
571 }
572
573 /* FIXME: move the window around so we can still see the caret */
574 VOID DoEdit(HWND hWnd, WPARAM wParam, LPARAM lParam)
575 {
576 HDC hDC;
577
578 if(lpBuffer==NULL)
579 return;
580 switch(wParam)
581 {
582 case VK_HOME: GotoHome(hWnd);
583 break;
584
585 case VK_END: GotoEndOfLine(hWnd);
586 break;
587
588 case VK_LEFT: GotoLeft(hWnd);
589 break;
590
591 case VK_RIGHT: GotoRight(hWnd);
592 break;
593
594 case VK_DOWN: GotoDown(hWnd);
595 break;
596
597 case VK_UP: GotoUp(hWnd);
598 break;
599
600 default:
601 return;
602 }
603
604 hDC = GetDC(hWnd);
605 if(hDC)
606 {
607 CalcCaretPos(hDC, dwXpos, dwYpos);
608 ReleaseDC(hWnd,hDC);
609 }
610 if(ScrollABit(hWnd))
611 InvalidateRect(hWnd, NULL, FALSE);
612 }
613
614 void ButtonDownToCaretPos(HWND hWnd, WPARAM wParam, LPARAM lParam)
615 {
616 DWORD x, y, caretx, carety;
617 BOOL refine_guess = TRUE;
618 HDC hDC;
619
620 x = LOWORD(lParam);
621 y = HIWORD(lParam);
622
623 caretx = x/tm.tmAveCharWidth; /* guess */
624 carety = dwVOffset + y/tm.tmHeight;
625
626 hDC = GetDC(hWnd);
627
628 if(lpBuffer == NULL)
629 {
630 caretx = 0;
631 carety = 0;
632 refine_guess = FALSE;
633 }
634
635 /* if the cursor is past the bottom, put it after the last char */
636 if(refine_guess && (carety>=dwLines) )
637 {
638 carety=dwLines-1;
639 caretx=lpBuffer[carety].dwWidth;
640 refine_guess = FALSE;
641 }
642
643 /* cursor past end of line? */
644 if(refine_guess && (x>CalcStringWidth(hDC,lpBuffer[carety].dwWidth,carety)))
645 {
646 caretx = lpBuffer[carety].dwWidth;
647 refine_guess = FALSE;
648 }
649
650 /* FIXME: doesn't round properly */
651 if(refine_guess)
652 {
653 if(CalcStringWidth(hDC,caretx,carety)<x)
654 {
655 while( (caretx<lpBuffer[carety].dwWidth) &&
656 (CalcStringWidth(hDC,caretx+1,carety)<x))
657 caretx++;
658 }
659 else
660 {
661 while((caretx>0)&&(CalcStringWidth(hDC,caretx-1,carety)>x))
662 caretx--;
663 }
664 }
665
666 /* set the caret's position */
667 dwXpos = caretx;
668 dwYpos = carety;
669 CalcCaretPos(hDC, caretx, carety);
670 ReleaseDC(hWnd,hDC);
671 }
672
673 void DoScroll(HWND hWnd, WPARAM wParam, LPARAM lParam)
674 {
675 DWORD dy = GetLinesPerPage(hWnd);
676
677 switch(wParam) /* vscroll code */
678 {
679 case SB_LINEUP:
680 if(dwVOffset)
681 dwVOffset--;
682 break;
683 case SB_LINEDOWN:
684 if(dwVOffset<dwLines)
685 dwVOffset++;
686 break;
687 case SB_PAGEUP:
688 if( (dy+dwVOffset) > dwLines)
689 dwVOffset = dwLines - 1;
690 break;
691 case SB_PAGEDOWN:
692 if( dy > dwVOffset)
693 dwVOffset=0;
694 break;
695 }
696 /* position scroll */
697 SetScrollPos(hWnd, SB_VERT, dwVOffset, TRUE);
698 }
699
700 /***********************************************************************
701 *
702 * NOTEPAD_MenuCommand
703 *
704 * All handling of main menu events
705 */
706
707 int NOTEPAD_MenuCommand (WPARAM wParam)
708 {
709 switch (wParam) {
710 case NP_FILE_NEW: DIALOG_FileNew(); break;
711 case NP_FILE_OPEN: DIALOG_FileOpen(); break;
712 case NP_FILE_SAVE: DIALOG_FileSave(); break;
713 case NP_FILE_SAVEAS: DIALOG_FileSaveAs(); break;
714 case NP_FILE_PRINT: DIALOG_FilePrint(); break;
715 case NP_FILE_PAGESETUP: DIALOG_FilePageSetup(); break;
716 case NP_FILE_PRINTSETUP: DIALOG_FilePrinterSetup();break;
717 case NP_FILE_EXIT: DIALOG_FileExit(); break;
718
719 case NP_EDIT_UNDO: DIALOG_EditUndo(); break;
720 case NP_EDIT_CUT: DIALOG_EditCut(); break;
721 case NP_EDIT_COPY: DIALOG_EditCopy(); break;
722 case NP_EDIT_PASTE: DIALOG_EditPaste(); break;
723 case NP_EDIT_DELETE: DIALOG_EditDelete(); break;
724 case NP_EDIT_SELECTALL: DIALOG_EditSelectAll(); break;
725 case NP_EDIT_TIMEDATE: DIALOG_EditTimeDate();break;
726 case NP_EDIT_WRAP: DIALOG_EditWrap(); break;
727
728 case NP_SEARCH_SEARCH: DIALOG_Search(); break;
729 case NP_SEARCH_NEXT: DIALOG_SearchNext(); break;
730
731 case NP_HELP_CONTENTS: DIALOG_HelpContents(); break;
732 case NP_HELP_SEARCH: DIALOG_HelpSearch(); break;
733 case NP_HELP_ON_HELP: DIALOG_HelpHelp(); break;
734 case NP_HELP_LICENSE: DIALOG_HelpLicense(); break;
735 case NP_HELP_NO_WARRANTY: DIALOG_HelpNoWarranty(); break;
736 case NP_HELP_ABOUT_WINE: DIALOG_HelpAboutWine(); break;
737
738 /* Handle languages */
739 default:
740 LANGUAGE_DefaultHandle(wParam);
741 }
742 return 0;
743 }
744
745
746
747 /***********************************************************************
748 *
749 * NOTEPAD_WndProc
750 */
751
752 LRESULT WINAPI NOTEPAD_WndProc (HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
753 {
754 PAINTSTRUCT ps;
755 HDC hContext;
756 HANDLE hDrop; /* drag & drop */
757 CHAR szFileName[MAX_STRING_LEN];
758 RECT Windowsize;
759
760 lstrcpy(szFileName, "");
761
762 switch (msg) {
763
764 case WM_CREATE:
765 GetClientRect(hWnd, &rectClient);
766 InitFontInfo(hWnd);
767 break;
768
769 case WM_SETFOCUS:
770 CreateCaret(Globals.hMainWnd, 0, 1, tm.tmHeight);
771 SetCaretPos(dwCaretXpos, dwCaretYpos);
772 ShowCaret(Globals.hMainWnd);
773 break;
774
775 case WM_KILLFOCUS:
776 DestroyCaret();
777 break;
778
779 case WM_PAINT:
780 GetClientRect(hWnd, &rectClient);
781 hContext = BeginPaint(hWnd, &ps);
782 RenderWindow(hContext);
783 EndPaint(hWnd, &ps);
784 break;
785
786 case WM_KEYDOWN:
787 DoEdit(hWnd, wParam, lParam);
788 break;
789
790 case WM_CHAR:
791 GetClientRect(hWnd, &rectClient);
792 HideCaret(hWnd);
793 hContext = GetDC(hWnd);
794 DoInput(hContext,wParam,lParam);
795 ReleaseDC(hWnd,hContext);
796 ShowCaret(hWnd);
797 break;
798
799 case WM_LBUTTONDOWN:
800 /* figure out where the mouse was clicked */
801 ButtonDownToCaretPos(hWnd, wParam, lParam);
802 break;
803
804 case WM_VSCROLL:
805 DoScroll(hWnd, wParam, lParam);
806 InvalidateRect(hWnd, NULL, FALSE); /* force a redraw */
807 break;
808
809 case WM_COMMAND:
810 /* FIXME: this is a bit messy */
811 NOTEPAD_MenuCommand(wParam);
812 InvalidateRect(hWnd, NULL, FALSE); /* force a redraw */
813 hContext = GetDC(hWnd);
814 CalcCaretPos(hContext,dwXpos,dwYpos);
815 ReleaseDC(hWnd,hContext);
816 break;
817
818 case WM_DESTROYCLIPBOARD:
819 MessageBox(Globals.hMainWnd, "Empty clipboard", "Debug", MB_ICONEXCLAMATION);
820 break;
821
822 case WM_CLOSE:
823 if (DoCloseFile()) {
824 PostQuitMessage(0);
825 }
826 break;
827
828 case WM_DESTROY:
829 PostQuitMessage (0);
830 break;
831
832 case WM_SIZE:
833 GetClientRect(Globals.hMainWnd, &Windowsize);
834 break;
835
836 case WM_DROPFILES:
837 /* User has dropped a file into main window */
838 hDrop = (HANDLE) wParam;
839 DragQueryFile(hDrop, 0, (CHAR *) &szFileName, sizeof(szFileName));
840 DragFinish(hDrop);
841 DoOpenFile(szFileName);
842 break;
843
844 default:
845 return DefWindowProc (hWnd, msg, wParam, lParam);
846 }
847 return 0l;
848 }
849
850
851
852 /***********************************************************************
853 *
854 * WinMain
855 */
856
857 int PASCAL WinMain (HINSTANCE hInstance, HINSTANCE prev, LPSTR cmdline, int show)
858 {
859 MSG msg;
860 WNDCLASS class;
861 char className[] = "NPClass"; /* To make sure className >= 0x10000 */
862 char winName[] = "Notepad";
863
864 /* setup buffer */
865 InitBuffer();
866
867 /* Setup Globals */
868
869 Globals.lpszIniFile = "notepad.ini";
870 Globals.lpszIcoFile = "notepad.ico";
871
872 Globals.hInstance = hInstance;
873
874 #ifndef LCC
875 Globals.hMainIcon = ExtractIcon(Globals.hInstance,
876 Globals.lpszIcoFile, 0);
877 #endif
878 /* icon breakage in ros
879 if (!Globals.hMainIcon) {
880 Globals.hMainIcon = LoadIcon(0, MAKEINTRESOURCE(DEFAULTICON));
881 }
882 */
883
884 lstrcpy(Globals.szFindText, "");
885 lstrcpy(Globals.szFileName, "");
886 lstrcpy(Globals.szMarginTop, "25 mm");
887 lstrcpy(Globals.szMarginBottom, "25 mm");
888 lstrcpy(Globals.szMarginLeft, "20 mm");
889 lstrcpy(Globals.szMarginRight, "20 mm");
890 lstrcpy(Globals.szHeader, "&n");
891 lstrcpy(Globals.szFooter, "Page &s");
892 lstrcpy(Globals.Buffer, "Hello World");
893
894 if (!prev){
895 class.style = CS_HREDRAW | CS_VREDRAW;
896 class.lpfnWndProc = NOTEPAD_WndProc;
897 class.cbClsExtra = 0;
898 class.cbWndExtra = 0;
899 class.hInstance = Globals.hInstance;
900 class.hIcon = LoadIcon (0, IDI_APPLICATION);
901 class.hCursor = LoadCursor (0, IDC_ARROW);
902 class.hbrBackground = GetStockObject (WHITE_BRUSH);
903 class.lpszMenuName = 0;
904 class.lpszClassName = className;
905 }
906
907 if (!RegisterClass (&class)) return FALSE;
908
909 /* Setup windows */
910
911
912 Globals.hMainWnd = CreateWindow (className, winName,
913 WS_OVERLAPPEDWINDOW + WS_HSCROLL + WS_VSCROLL,
914 CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, 0,
915 LoadMenu(Globals.hInstance, STRING_MENU_Xx),
916 Globals.hInstance, 0);
917
918 Globals.hFindReplaceDlg = 0;
919
920 LANGUAGE_SelectByNumber(0);
921
922 SetMenu(Globals.hMainWnd, Globals.hMainMenu);
923
924 ShowWindow (Globals.hMainWnd, show);
925 UpdateWindow (Globals.hMainWnd);
926
927 /* Set up dialogs */
928
929 /* Identify Messages originating from FindReplace */
930
931 Globals.nCommdlgFindReplaceMsg = RegisterWindowMessage("commdlg_FindReplace");
932 if (Globals.nCommdlgFindReplaceMsg==0) {
933 MessageBox(Globals.hMainWnd, "Could not register commdlg_FindReplace window message",
934 "Error", MB_ICONEXCLAMATION);
935 }
936
937 /* now handle command line */
938
939 while (*cmdline && (*cmdline == ' ' || *cmdline == '-'))
940
941 {
942 CHAR option;
943 /* LPCSTR topic_id; */
944
945 if (*cmdline++ == ' ') continue;
946
947 option = *cmdline;
948 if (option) cmdline++;
949 while (*cmdline && *cmdline == ' ') cmdline++;
950
951 switch(option)
952 {
953 case 'p':
954 case 'P': printf("Print file: ");
955 /* Not yet able to print a file */
956 break;
957 }
958 }
959
960 /* Set up Drag&Drop */
961
962 DragAcceptFiles(Globals.hMainWnd, TRUE);
963
964 /* now enter mesage loop */
965
966 while (GetMessage (&msg, 0, 0, 0)) {
967
968 /* Message belongs to FindReplace dialog */
969 /* We just let IsDialogMessage handle it */
970 /* BTW - DnD is broken under ROS */
971
972 /* if (IsDialogMessage(Globals.hFindReplaceDlg, &msg)!=0) {
973 }
974 else */
975 {
976 /* Message belongs to the Notepad Main Window */
977 TranslateMessage (&msg);
978 DispatchMessage (&msg);
979 }
980 }
981 return 0;
982 }