Implement EnumPrinterDataEx{A|W}.
[wine.git] / programs / notepad / main.c
blob098473819b8b0d2ff10e753b8f7ae54c203b576c
1 /*
2 * Notepad
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
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 * - seperate view code and document code
21 * This program is intended as a testbed for winelib as much as
22 * a useful application.
25 #include <stdio.h>
26 #include "windows.h"
28 #ifdef LCC
29 #include "lcc.h"
30 #endif
32 #include "main.h"
33 #include "license.h"
34 #include "dialog.h"
35 #include "language.h"
37 extern BOOL DoCloseFile(void);
38 extern void DoOpenFile(LPCSTR szFileName);
40 NOTEPAD_GLOBALS Globals;
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 */
48 #define BUFFERCHUNKSIZE 0xe0
49 typedef struct TAGLine {
50 LPSTR lpLine;
51 DWORD dwWidth;
52 DWORD dwMaxWidth;
53 } LINE, *LPLINE;
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 */
67 VOID InitFontInfo(HWND hWnd)
69 HDC hDC = GetDC(hWnd);
71 if(hDC)
73 GetTextMetrics(hDC, &tm);
74 ReleaseDC(hWnd,hDC);
78 void InitBuffer(void)
80 lpBuffer = NULL;
81 dwLines = 0;
82 dwMaxLines = 0;
83 dwXpos=0;
84 dwYpos=0;
87 /* convert x,y character co-ords into x pixel co-ord */
88 DWORD CalcStringWidth(HDC hDC, DWORD x, DWORD y)
90 DWORD len;
91 SIZE size;
93 size.cx = 0;
94 size.cy = 0;
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);
106 return size.cx;
109 void CalcCaretPos(HDC hDC, DWORD dwXpos, DWORD dwYpos)
111 dwCaretXpos = CalcStringWidth(hDC, dwXpos, dwYpos);
112 dwCaretYpos = tm.tmHeight*(dwYpos-dwVOffset);
113 SetCaretPos(dwCaretXpos,dwCaretYpos);
116 DWORD GetLinesPerPage(HWND hWnd)
118 return (rectClient.bottom/tm.tmHeight); /* round down */
121 /* render one line of text and blank space */
122 void RenderLine(HDC hDC, DWORD lineno)
124 RECT rect;
125 HBRUSH hPrev;
127 if(!hDC)
128 return;
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);
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;
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);
145 if(lpBuffer && lpBuffer[lineno].lpLine)
147 TextOut(hDC, 0, rect.top, lpBuffer[lineno].lpLine,
148 lpBuffer[lineno].dwWidth);
153 * Paint the buffer onto the window.
155 void RenderWindow(HDC hDC) {
156 DWORD i;
158 if(!hDC)
159 return;
161 /* FIXME: render only necessary lines */
162 for(i = dwVOffset; i < (dwVOffset+GetLinesPerPage(0)); i++)
164 RenderLine(hDC,i);
169 * Check that correct buffers exist to access line y pos x
170 * Only manages memory.
172 * Returns TRUE if the line is accessable
173 * FALSE if there is a problem
175 BOOL ValidateLine(DWORD y,DWORD x)
177 DWORD max;
179 /* check to see that the BUFFER has enough lines */
180 max = dwMaxLines;
181 if( (max<=y) || (lpBuffer == NULL))
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;
197 /* check to see that the LINE is wide enough */
198 max = lpBuffer[y].dwMaxWidth;
199 if( (max <= x) || (lpBuffer[y].lpLine == NULL) )
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;
214 return TRUE;
217 /* inserts a new line into the buffer */
218 BOOL DoNewLine(HDC hDC)
220 DWORD i,cnt;
221 LPSTR src,dst;
223 /* check to see if we need more memory for the buffer pointers */
224 if(!ValidateLine(dwLines,0))
225 return FALSE;
227 /* shuffle up all the lines */
228 for(i=dwLines; i>(dwYpos+1); i--)
230 lpBuffer[i] = lpBuffer[i-1];
231 RenderLine(hDC,i);
233 ZeroMemory(&lpBuffer[dwYpos+1],sizeof(LINE));
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;
245 /* move the cursor */
246 dwLines++;
247 dwXpos = 0;
248 dwYpos++;
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);
257 return TRUE;
261 * Attempt a basic edit buffer
263 BOOL AddCharToBuffer(HDC hDC, char ch)
265 /* we can use lpBuffer[dwYpos] */
266 if(!ValidateLine(dwYpos,0))
267 return FALSE;
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);
277 /* add the character */
278 lpBuffer[dwYpos].lpLine[dwXpos] = ch;
279 if(dwLines == 0)
280 dwLines++;
281 dwXpos++;
283 /* update the window and cursor position */
284 RenderLine(hDC,dwYpos);
285 CalcCaretPos(hDC,dwXpos,dwYpos);
287 return TRUE;
291 /* erase a character */
292 BOOL DoBackSpace(HDC hDC)
294 DWORD i;
296 if(lpBuffer == NULL)
297 return FALSE;
298 if(lpBuffer[dwYpos].lpLine && (dwXpos>0))
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];
305 lpBuffer[dwYpos].dwWidth--;
306 RenderLine(hDC, dwYpos);
307 CalcCaretPos(hDC,dwXpos,dwYpos);
309 else
311 /* Erase a newline. To do this we join two lines */
312 LPSTR src, dest;
313 DWORD len, oldlen;
315 if(dwYpos==0)
316 return FALSE;
318 oldlen = lpBuffer[dwYpos-1].dwWidth;
319 if(lpBuffer[dwYpos-1].lpLine&&lpBuffer[dwYpos].lpLine)
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;
326 /* check the length of the new line */
327 if(!ValidateLine(dwYpos-1,lpBuffer[dwYpos-1].dwWidth + len))
328 return FALSE;
330 memcpy(dest,src,len);
331 lpBuffer[dwYpos-1].dwWidth+=len;
332 GlobalFree( (HGLOBAL)lpBuffer[dwYpos].lpLine);
334 else if (!lpBuffer[dwYpos-1].lpLine)
336 lpBuffer[dwYpos-1]=lpBuffer[dwYpos];
337 } /* else both are NULL */
338 RenderLine(hDC,dwYpos-1);
340 /* don't zero - it's going to get trashed anyhow */
342 /* shuffle up all the lines below this one */
343 for(i=dwYpos; i<(dwLines-1); i++)
345 lpBuffer[i] = lpBuffer[i+1];
346 RenderLine(hDC,i);
349 /* clear the last line */
350 ZeroMemory(&lpBuffer[dwLines-1],sizeof (LINE));
351 RenderLine(hDC,dwLines-1);
352 dwLines--;
354 /* adjust the cursor position to joining point */
355 dwYpos--;
356 dwXpos = oldlen;
358 CalcCaretPos(hDC,dwXpos,dwYpos);
359 SetScrollRange(Globals.hMainWnd, SB_VERT, 0, dwLines, TRUE);
361 return TRUE;
364 /* as used by File->New */
365 void TrashBuffer(void)
367 DWORD i;
369 /* variables belonging to the buffer */
370 if(lpBuffer)
372 for(i=0; i<dwLines; i++)
374 if(lpBuffer[i].lpLine)
375 GlobalFree ((HGLOBAL)lpBuffer[i].lpLine);
376 ZeroMemory(&lpBuffer[i],sizeof (LINE));
378 GlobalFree((HGLOBAL)lpBuffer);
379 lpBuffer=NULL;
381 dwLines = 0;
382 dwMaxLines = 0;
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);
395 * Add a line to the buffer
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)
403 DWORD i;
405 if(size == 0)
406 return 0;
408 for(i=0; i<size; i++)
410 if(buffer[i]==0x0a)
412 if(ValidateLine(dwLines,i))
414 memcpy(&lpBuffer[dwLines].lpLine[0],&buffer[0],i);
415 lpBuffer[dwLines].dwWidth = i;
416 dwLines++;
418 return i+1;
422 /* make a line of the rest */
423 if( (i == BUFFERCHUNKSIZE) || nomore )
425 if(ValidateLine(dwLines,i))
427 memcpy(&lpBuffer[dwLines].lpLine[0],&buffer[0],i);
428 lpBuffer[dwLines].dwWidth = i;
429 dwLines++;
431 return i;
434 return 0;
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.
444 void LoadBufferFromFile(LPCSTR szFileName)
446 HANDLE hFile;
447 CHAR *pTemp;
448 DWORD size,i,len,bytes_left,bytes_read;
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)
462 if(!ReadFile(hFile,
463 &pTemp[bytes_left],
464 size-bytes_left,
465 &bytes_read, NULL))
466 break;
467 bytes_left+=bytes_read;
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 );
475 /* move leftover to front of buffer */
476 if(bytes_left)
477 memmove(&pTemp[0],&pTemp[i], bytes_left);
479 CloseHandle(hFile);
480 MessageBox(Globals.hMainWnd, "Finished", "Info", MB_OK);
483 BOOL DoInput(HDC hDC, WPARAM wParam, LPARAM lParam)
485 switch(wParam)
487 case 0x08:
488 return DoBackSpace(hDC);
489 case 0x0d:
490 return DoNewLine(hDC);
491 default:
492 return AddCharToBuffer(hDC,wParam);
496 BOOL GotoHome(HWND hWnd)
498 dwXpos = 0;
499 dwYpos = 0;
500 dwVOffset = 0;
501 return TRUE;
504 BOOL GotoEndOfLine(HWND hWnd)
506 dwXpos = lpBuffer[dwYpos].dwWidth;
507 return TRUE;
510 BOOL GotoDown(HWND hWnd)
512 if((dwYpos+1) >= dwLines)
514 return FALSE;
516 dwYpos++;
517 if (dwXpos>lpBuffer[dwYpos].dwWidth)
518 GotoEndOfLine(hWnd);
519 return TRUE;
522 BOOL GotoUp(HWND hWnd)
524 if(dwYpos==0)
525 return FALSE;
526 dwYpos--;
527 if (dwXpos>lpBuffer[dwYpos].dwWidth)
528 GotoEndOfLine(hWnd);
529 return TRUE;
532 BOOL GotoLeft(HWND hWnd)
534 if(dwXpos > 0)
536 dwXpos--;
537 return TRUE;
539 if(GotoUp(hWnd))
540 return GotoEndOfLine(hWnd);
541 return FALSE;
544 BOOL GotoRight(HWND hWnd)
546 if(dwXpos<lpBuffer[dwYpos].dwWidth)
548 dwXpos++;
549 return TRUE;
551 if(!GotoDown(hWnd))
552 return FALSE;
553 dwXpos=0;
554 return TRUE;
557 /* check the caret is still on the screen */
558 BOOL ScrollABit(HWND hWnd)
560 if(dwYpos<dwVOffset)
562 dwVOffset = dwYpos;
563 return TRUE;
565 if(dwYpos>(dwVOffset+GetLinesPerPage(hWnd)))
567 dwVOffset = dwYpos - GetLinesPerPage(hWnd) + 1;
568 return TRUE;
570 return FALSE;
573 /* FIXME: move the window around so we can still see the caret */
574 VOID DoEdit(HWND hWnd, WPARAM wParam, LPARAM lParam)
576 HDC hDC;
578 if(lpBuffer==NULL)
579 return;
580 switch(wParam)
582 case VK_HOME: GotoHome(hWnd);
583 break;
585 case VK_END: GotoEndOfLine(hWnd);
586 break;
588 case VK_LEFT: GotoLeft(hWnd);
589 break;
591 case VK_RIGHT: GotoRight(hWnd);
592 break;
594 case VK_DOWN: GotoDown(hWnd);
595 break;
597 case VK_UP: GotoUp(hWnd);
598 break;
600 default:
601 return;
604 hDC = GetDC(hWnd);
605 if(hDC)
607 CalcCaretPos(hDC, dwXpos, dwYpos);
608 ReleaseDC(hWnd,hDC);
610 if(ScrollABit(hWnd))
611 InvalidateRect(hWnd, NULL, FALSE);
614 void ButtonDownToCaretPos(HWND hWnd, WPARAM wParam, LPARAM lParam)
616 DWORD x, y, caretx, carety;
617 BOOL refine_guess = TRUE;
618 HDC hDC;
620 x = LOWORD(lParam);
621 y = HIWORD(lParam);
623 caretx = x/tm.tmAveCharWidth; /* guess */
624 carety = dwVOffset + y/tm.tmHeight;
626 hDC = GetDC(hWnd);
628 if(lpBuffer == NULL)
630 caretx = 0;
631 carety = 0;
632 refine_guess = FALSE;
635 /* if the cursor is past the bottom, put it after the last char */
636 if(refine_guess && (carety>=dwLines) )
638 carety=dwLines-1;
639 caretx=lpBuffer[carety].dwWidth;
640 refine_guess = FALSE;
643 /* cursor past end of line? */
644 if(refine_guess && (x>CalcStringWidth(hDC,lpBuffer[carety].dwWidth,carety)))
646 caretx = lpBuffer[carety].dwWidth;
647 refine_guess = FALSE;
650 /* FIXME: doesn't round properly */
651 if(refine_guess)
653 if(CalcStringWidth(hDC,caretx,carety)<x)
655 while( (caretx<lpBuffer[carety].dwWidth) &&
656 (CalcStringWidth(hDC,caretx+1,carety)<x))
657 caretx++;
659 else
661 while((caretx>0)&&(CalcStringWidth(hDC,caretx-1,carety)>x))
662 caretx--;
666 /* set the caret's position */
667 dwXpos = caretx;
668 dwYpos = carety;
669 CalcCaretPos(hDC, caretx, carety);
670 ReleaseDC(hWnd,hDC);
673 void DoScroll(HWND hWnd, WPARAM wParam, LPARAM lParam)
675 DWORD dy = GetLinesPerPage(hWnd);
677 switch(wParam) /* vscroll code */
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;
696 /* position scroll */
697 SetScrollPos(hWnd, SB_VERT, dwVOffset, TRUE);
700 /***********************************************************************
702 * NOTEPAD_MenuCommand
704 * All handling of main menu events
707 int NOTEPAD_MenuCommand (WPARAM wParam)
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;
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;
728 case NP_SEARCH_SEARCH: DIALOG_Search(); break;
729 case NP_SEARCH_NEXT: DIALOG_SearchNext(); break;
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;
738 /* Handle languages */
739 default:
740 LANGUAGE_DefaultHandle(wParam);
742 return 0;
747 /***********************************************************************
749 * NOTEPAD_WndProc
752 LRESULT WINAPI NOTEPAD_WndProc (HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
754 PAINTSTRUCT ps;
755 HDC hContext;
756 HANDLE hDrop; /* drag & drop */
757 CHAR szFileName[MAX_STRING_LEN];
758 RECT Windowsize;
760 lstrcpy(szFileName, "");
762 switch (msg) {
764 case WM_CREATE:
765 GetClientRect(hWnd, &rectClient);
766 InitFontInfo(hWnd);
767 break;
769 case WM_SETFOCUS:
770 CreateCaret(Globals.hMainWnd, 0, 1, tm.tmHeight);
771 SetCaretPos(dwCaretXpos, dwCaretYpos);
772 ShowCaret(Globals.hMainWnd);
773 break;
775 case WM_KILLFOCUS:
776 DestroyCaret();
777 break;
779 case WM_PAINT:
780 GetClientRect(hWnd, &rectClient);
781 hContext = BeginPaint(hWnd, &ps);
782 RenderWindow(hContext);
783 EndPaint(hWnd, &ps);
784 break;
786 case WM_KEYDOWN:
787 DoEdit(hWnd, wParam, lParam);
788 break;
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;
799 case WM_LBUTTONDOWN:
800 /* figure out where the mouse was clicked */
801 ButtonDownToCaretPos(hWnd, wParam, lParam);
802 break;
804 case WM_VSCROLL:
805 DoScroll(hWnd, wParam, lParam);
806 InvalidateRect(hWnd, NULL, FALSE); /* force a redraw */
807 break;
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;
818 case WM_DESTROYCLIPBOARD:
819 MessageBox(Globals.hMainWnd, "Empty clipboard", "Debug", MB_ICONEXCLAMATION);
820 break;
822 case WM_CLOSE:
823 if (DoCloseFile()) {
824 PostQuitMessage(0);
826 break;
828 case WM_DESTROY:
829 PostQuitMessage (0);
830 break;
832 case WM_SIZE:
833 GetClientRect(Globals.hMainWnd, &Windowsize);
834 break;
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;
844 default:
845 return DefWindowProc (hWnd, msg, wParam, lParam);
847 return 0l;
852 /***********************************************************************
854 * WinMain
857 int PASCAL WinMain (HINSTANCE hInstance, HINSTANCE prev, LPSTR cmdline, int show)
859 MSG msg;
860 WNDCLASS class;
861 char className[] = "NPClass"; /* To make sure className >= 0x10000 */
862 char winName[] = "Notepad";
864 /* setup buffer */
865 InitBuffer();
867 /* Setup Globals */
869 Globals.lpszIniFile = "notepad.ini";
870 Globals.lpszIcoFile = "notepad.ico";
872 Globals.hInstance = hInstance;
874 #ifndef LCC
875 Globals.hMainIcon = ExtractIcon(Globals.hInstance,
876 Globals.lpszIcoFile, 0);
877 #endif
878 if (!Globals.hMainIcon) {
879 Globals.hMainIcon = LoadIcon(0, MAKEINTRESOURCE(DEFAULTICON));
882 lstrcpy(Globals.szFindText, "");
883 lstrcpy(Globals.szFileName, "");
884 lstrcpy(Globals.szMarginTop, "25 mm");
885 lstrcpy(Globals.szMarginBottom, "25 mm");
886 lstrcpy(Globals.szMarginLeft, "20 mm");
887 lstrcpy(Globals.szMarginRight, "20 mm");
888 lstrcpy(Globals.szHeader, "&n");
889 lstrcpy(Globals.szFooter, "Page &s");
890 lstrcpy(Globals.Buffer, "Hello World");
892 if (!prev){
893 class.style = CS_HREDRAW | CS_VREDRAW;
894 class.lpfnWndProc = NOTEPAD_WndProc;
895 class.cbClsExtra = 0;
896 class.cbWndExtra = 0;
897 class.hInstance = Globals.hInstance;
898 class.hIcon = LoadIcon (0, IDI_APPLICATION);
899 class.hCursor = LoadCursor (0, IDC_ARROW);
900 class.hbrBackground = GetStockObject (WHITE_BRUSH);
901 class.lpszMenuName = 0;
902 class.lpszClassName = className;
905 if (!RegisterClass (&class)) return FALSE;
907 /* Setup windows */
910 Globals.hMainWnd = CreateWindow (className, winName,
911 WS_OVERLAPPEDWINDOW + WS_HSCROLL + WS_VSCROLL,
912 CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, 0,
913 LoadMenu(Globals.hInstance, STRING_MENU_Xx),
914 Globals.hInstance, 0);
916 Globals.hFindReplaceDlg = 0;
918 LANGUAGE_SelectByNumber(0);
920 SetMenu(Globals.hMainWnd, Globals.hMainMenu);
922 ShowWindow (Globals.hMainWnd, show);
923 UpdateWindow (Globals.hMainWnd);
925 /* Set up dialogs */
927 /* Identify Messages originating from FindReplace */
929 Globals.nCommdlgFindReplaceMsg = RegisterWindowMessage("commdlg_FindReplace");
930 if (Globals.nCommdlgFindReplaceMsg==0) {
931 MessageBox(Globals.hMainWnd, "Could not register commdlg_FindReplace window message",
932 "Error", MB_ICONEXCLAMATION);
935 /* now handle command line */
937 while (*cmdline && (*cmdline == ' ' || *cmdline == '-'))
940 CHAR option;
941 /* LPCSTR topic_id; */
943 if (*cmdline++ == ' ') continue;
945 option = *cmdline;
946 if (option) cmdline++;
947 while (*cmdline && *cmdline == ' ') cmdline++;
949 switch(option)
951 case 'p':
952 case 'P': printf("Print file: ");
953 /* Not yet able to print a file */
954 break;
958 /* Set up Drag&Drop */
960 DragAcceptFiles(Globals.hMainWnd, TRUE);
962 /* now enter mesage loop */
964 while (GetMessage (&msg, 0, 0, 0)) {
965 if (IsDialogMessage(Globals.hFindReplaceDlg, &msg)!=0) {
966 /* Message belongs to FindReplace dialog */
967 /* We just let IsDialogMessage handle it */
969 else
971 /* Message belongs to the Notepad Main Window */
972 TranslateMessage (&msg);
973 DispatchMessage (&msg);
976 return 0;