1 /***********************************************************************/
5 /* Developed by Jacob Navia. */
6 /* Copyright 2001 Institut National de Recherche en Informatique et */
7 /* en Automatique. All rights reserved. This file is distributed */
8 /* under the terms of the GNU Library General Public License, with */
9 /* the special exception on linking described in file ../LICENSE. */
11 /***********************************************************************/
13 /***********************************************************************/
14 /* Changes made by Chris Watford to enhance the source editor */
15 /* Began 14 Sept 2003 - watford@uiuc.edu */
16 /***********************************************************************/
28 int CurrentFontFamily
= (FIXED_PITCH
| FF_MODERN
);
30 char CurrentFontName
[64] = "Courier";
32 /*------------------------------------------------------------------------
33 Procedure: OpenMlFile ID:1
34 Purpose: Opens a file, either a source file (*.ml) or an *.cmo
36 Input: A buffer where the name will be stored, and its
38 Output: The user's choice will be stored in the buffer.
40 ------------------------------------------------------------------------*/
41 int OpenMlFile(char *fname
,int lenbuf
)
45 char *p
,defext
[5],tmp
[512];
47 memset(&ofn
,0,sizeof(OPENFILENAME
));
48 memset(tmp
,0,sizeof(tmp
));
50 strcpy(tmp
,"ocaml sources|*.ml|bytecode object files|*.cmo|All files|*.*");
58 ofn
.lStructSize
= sizeof(OPENFILENAME
);
59 ofn
.hwndOwner
= hwndMain
;
60 ofn
.lpstrFilter
= tmp
;
62 ofn
.hInstance
= hInst
;
63 ofn
.lpstrFile
= fname
;
64 ofn
.lpstrTitle
= "Open file";
65 ofn
.lpstrInitialDir
= LibDir
;
66 ofn
.nMaxFile
= lenbuf
;
67 ofn
.Flags
= OFN_PATHMUSTEXIST
| OFN_NOCHANGEDIR
| OFN_LONGNAMES
|
68 OFN_HIDEREADONLY
|OFN_EXPLORER
;
69 r
= GetOpenFileName(&ofn
);
71 /* Replace backslashes by forward slashes in file name */
72 for (p
= fname
; *p
!= 0; p
++)
73 if (*p
== '\\') *p
= '/';
78 /*------------------------------------------------------------------------
79 Procedure: GetSaveName ID:1
80 Purpose: Get a name to save the current session (Save as menu
82 Input: A buffer where the name of the file will be stored,
84 Output: The name of the file choosen by the user will be
87 ------------------------------------------------------------------------*/
88 int GetSaveName(char *fname
,int lenbuf
)
92 char *p
,defext
[5],tmp
[512];
94 memset(&ofn
,0,sizeof(OPENFILENAME
));
95 memset(tmp
,0,sizeof(tmp
));
97 strcpy(tmp
,"Text files|*.txt");
104 strcpy(defext
,"txt");
105 ofn
.lStructSize
= sizeof(OPENFILENAME
);
106 ofn
.hwndOwner
= hwndMain
;
107 ofn
.lpstrFilter
= tmp
;
108 ofn
.nFilterIndex
= 1;
109 ofn
.hInstance
= hInst
;
110 ofn
.lpstrFile
= fname
;
111 ofn
.lpstrTitle
= "Save as";
112 ofn
.lpstrInitialDir
= LibDir
;
113 ofn
.nMaxFile
= lenbuf
;
114 ofn
.Flags
= OFN_NOCHANGEDIR
| OFN_LONGNAMES
|
115 OFN_HIDEREADONLY
|OFN_EXPLORER
;
116 r
= GetSaveFileName(&ofn
);
122 /*------------------------------------------------------------------------
123 Procedure: GetSaveMLName ID:1
124 Purpose: Get a name to save the current OCaml code to (Save as menu
126 Input: A buffer where the name of the file will be stored,
128 Output: The name of the file choosen by the user will be
131 ------------------------------------------------------------------------*/
132 int GetSaveMLName(char *fname
, int lenbuf
)
136 char *p
,defext
[5],tmp
[512];
138 memset(&ofn
,0,sizeof(OPENFILENAME
));
139 memset(tmp
,0,sizeof(tmp
));
141 strcpy(tmp
,"OCaml Source Files|*.ml");
149 ofn
.lStructSize
= sizeof(OPENFILENAME
);
150 ofn
.hwndOwner
= hwndMain
;
151 ofn
.lpstrFilter
= tmp
;
152 ofn
.nFilterIndex
= 1;
153 ofn
.hInstance
= hInst
;
154 ofn
.lpstrFile
= fname
;
155 ofn
.lpstrTitle
= "Save as";
156 ofn
.lpstrInitialDir
= LibDir
;
157 ofn
.nMaxFile
= lenbuf
;
158 ofn
.Flags
= OFN_NOCHANGEDIR
| OFN_LONGNAMES
|
159 OFN_HIDEREADONLY
|OFN_EXPLORER
;
160 r
= GetSaveFileName(&ofn
);
166 /*------------------------------------------------------------------------
167 Procedure: BrowseForFile ID:1
168 Purpose: Let's the user browse for a certain kind of file.
169 Currently this is only used when browsing for
171 Input: The name of the file to browse for, and the path
172 where the user's choice will be stored.
173 Output: 1 if user choosed a path, zero otherwise
175 ------------------------------------------------------------------------*/
176 int BrowseForFile(char *fname
,char *path
)
179 char *p
,tmp
[512],browsefor
[512];
182 memset(tmp
,0,sizeof(tmp
));
183 strncpy(tmp
,fname
,sizeof(tmp
)-1);
190 memset(&ofn
,0,sizeof(OPENFILENAME
));
191 ofn
.lpstrFilter
= tmp
;
192 ofn
.nFilterIndex
= 1;
193 ofn
.lStructSize
= sizeof(OPENFILENAME
);
194 ofn
.hwndOwner
= hwndMain
;
195 ofn
.hInstance
= hInst
;
196 ofn
.lpstrFilter
= tmp
;
197 ofn
.lpstrFile
= path
;
198 wsprintf(browsefor
,"Open %s",fname
);
199 ofn
.lpstrTitle
= browsefor
;
200 ofn
.lpstrInitialDir
= "c:\\";
201 ofn
.nMaxFile
= MAX_PATH
;
202 ofn
.Flags
= OFN_PATHMUSTEXIST
| OFN_NOCHANGEDIR
| OFN_LONGNAMES
|
203 OFN_HIDEREADONLY
|OFN_EXPLORER
;
204 r
= GetOpenFileName(&ofn
);
210 /*------------------------------------------------------------------------
211 Procedure: CallChangeFont ID:1
212 Purpose: Calls the standard windows font change dialog. If the
213 user validates a font, it will destroy the current
214 font, and recreate a new font with the given
216 Input: The calling window handle
217 Output: Zero if the user cancelled, 1 otherwise.
219 ------------------------------------------------------------------------*/
220 static int CallChangeFont(HWND hwnd
)
227 memset(&cf
, 0, sizeof(CHOOSEFONT
));
228 memcpy(&lf
, &CurrentFont
, sizeof(LOGFONT
));
229 cf
.lStructSize
= sizeof(CHOOSEFONT
);
232 cf
.Flags
= CF_SCREENFONTS
| CF_EFFECTS
| CF_APPLY
| CF_INITTOLOGFONTSTRUCT
;
233 cf
.nFontType
= SCREEN_FONTTYPE
;
237 DeleteObject(ProgramParams
.hFont
);
238 memcpy(&CurrentFont
, &lf
, sizeof(LOGFONT
));
239 ProgramParams
.hFont
= CreateFontIndirect(&CurrentFont
);
240 strcpy(CurrentFontName
, CurrentFont
.lfFaceName
);
241 CurrentFontFamily
= lf
.lfPitchAndFamily
;
242 CurrentFontStyle
= lf
.lfWeight
;
243 hwndChild
= (HWND
) GetWindowLongPtr(hwndSession
, DWLP_USER
);
244 SendMessage(hwndChild
,WM_SETFONT
,(WPARAM
)ProgramParams
.hFont
,0);
249 /*------------------------------------------------------------------------
250 Procedure: CallDlgProc ID:1
251 Purpose: Calls a dialog box procedure
252 Input: The function to call, and the numerical ID of the
253 resource where the dialog box is stored
254 Output: Returns the result of the dialog box.
256 ------------------------------------------------------------------------*/
257 int CallDlgProc(BOOL (CALLBACK
*fn
)(HWND
,UINT
,WPARAM
,LPARAM
), int id
)
261 result
= DialogBoxParam(hInst
, MAKEINTRESOURCE(id
), GetActiveWindow(),
267 /*------------------------------------------------------------------------
268 Procedure: CallChangeColor ID:1
269 Purpose: Calls the standard color dialog of windows, starting
270 with the given color reference. The result is the
271 same as the input if the user cancels, or another
272 color if the user validates another one.
273 Input: The starting color
274 Output: The color the user has choosen.
276 ------------------------------------------------------------------------*/
277 static COLORREF
CallChangeColor(COLORREF InitialColor
)
280 COLORREF CustColors
[16];
282 memset(&CC
, 0, sizeof(CHOOSECOLOR
));
284 for (i
= 0; i
< 16; i
++) {
285 CustColors
[i
] = RGB(r
, g
, b
);
293 CC
.lStructSize
= sizeof(CHOOSECOLOR
);
294 CC
.hwndOwner
= hwndMain
;
295 CC
.hInstance
= hInst
;
296 CC
.rgbResult
= InitialColor
;
297 CC
.lpCustColors
= CustColors
;
298 CC
.Flags
= CC_RGBINIT
;
299 if (!ChooseColor(&CC
))
300 return (InitialColor
);
301 return (CC
.rgbResult
);
304 /*------------------------------------------------------------------------
305 Procedure: CallPrintSetup ID:1
306 Purpose: Calls the printer setup dialog. Currently it is not
307 connected to the rest of the software, since printing
310 Output: 1 if OK, 0, user cancelled
312 ------------------------------------------------------------------------*/
313 static int CallPrintSetup(void)
318 memset(&sd
,0,sizeof(sd
));
319 sd
.lStructSize
= sizeof(sd
);
320 sd
.Flags
= PSD_RETURNDEFAULT
;
321 r
= PageSetupDlg(&sd
);
325 r
= PageSetupDlg(&sd
);
330 /*------------------------------------------------------------------------
332 Purpose: Send an UNDO command to the edit field.
333 Input: The parent window of the control
336 ------------------------------------------------------------------------*/
341 hEdit
= (HWND
)GetWindowLongPtr(hwnd
,DWLP_USER
);
342 SendMessage(hEdit
,EM_UNDO
,0,0);
345 /*------------------------------------------------------------------------
346 Procedure: ForceRepaint ID:1
347 Purpose: Forces a complete redraw of the edit control of the
352 ------------------------------------------------------------------------*/
353 void ForceRepaint(void)
355 HWND hwndEdit
= (HWND
)GetWindowLongPtr(hwndSession
,DWLP_USER
);
356 InvalidateRect(hwndEdit
,NULL
,1);
359 /*------------------------------------------------------------------------
360 Procedure: Add_Char_To_Queue ID:1
361 Purpose: Puts a character onto the buffer
362 Input: The char to be added
365 ------------------------------------------------------------------------*/
366 static void Add_Char_To_Queue(int c
)
368 HWND hwndEdit
= (HWND
)GetWindowLongPtr(hwndSession
,DWLP_USER
);
369 SendMessage(hwndEdit
,WM_CHAR
,c
,1);
372 /*------------------------------------------------------------------------
373 Procedure: AddLineToControl ID:1
374 Purpose: It will ad the given text at the end of the edit
375 control, then it will send a return character to it.
376 This simulates user input. The history will not be
377 modified by this procedure.
378 Input: The text to be added
380 Errors: If the line is empty, nothing will be done
381 ------------------------------------------------------------------------*/
382 void AddLineToControl(char *buf
)
389 hEditCtrl
= (HWND
)GetWindowLongPtr(hwndSession
,DWLP_USER
);
393 SendMessage(hEditCtrl
,EM_REPLACESEL
,0,(LPARAM
)buf
);
394 SendMessage(hEditCtrl
,WM_CHAR
,'\r',0);
397 /*------------------------------------------------------------------------
398 Procedure: AddStringToControl ID:1
399 Author: Chris Watford watford@uiuc.edu
400 Purpose: It will ad the given text at the end of the edit
401 control. This simulates user input. The history will not
402 be modified by this procedure.
403 Input: The text to be added
405 Errors: If the line is empty, nothing will be done
406 --------------------------------------------------------------------------
408 16 Sept 2003 - Chris Watford watford@uiuc.edu
409 - Basically this is AddLineToControl, but without appending a
411 ------------------------------------------------------------------------*/
412 void AddStringToControl(char* buf
)
422 hEditCtrl
= (HWND
)GetWindowLongPtr(hwndSession
, DWLP_USER
);
425 SendMessage(hEditCtrl
,EM_REPLACESEL
, (WPARAM
)FALSE
, (LPARAM
)buf
);
428 /*------------------------------------------------------------------------
429 Procedure: AboutDlgProc ID:1
430 Purpose: Shows the "About" dialog box
434 ------------------------------------------------------------------------*/
435 static BOOL CALLBACK
AboutDlgProc(HWND hDlg
, UINT message
, WPARAM wParam
, LPARAM lParam
)
437 if (message
== WM_CLOSE
)
442 /*------------------------------------------------------------------------
443 Procedure: HistoryDlgProc ID:1
444 Purpose: Shows the history of the session. Only input lines
445 are shown. A double click in a line will make this
446 dialog box procedure return the index of the selected
447 line (1 based). If the windows is closed (what is
448 equivalent to cancel), the return value is zero.
449 Input: Normal windows callback
452 --------------------------------------------------------------------------
454 15 Sept 2003 - Chris Watford watford@uiuc.edu
455 - Added support for my StatementHistory structure
456 - Added the ability to export it as its exact entry, rather than
458 ------------------------------------------------------------------------*/
459 static BOOL CALLBACK
HistoryDlgProc(HWND hDlg
, UINT message
, WPARAM wParam
, LPARAM lParam
)
461 StatementHistory
*histentry
;
467 SendDlgItemMessage(hDlg
,IDLIST
,WM_SETFONT
,(WPARAM
)ProgramParams
.hFont
,0);
468 histentry
= History
; // get our statement history object
471 // loop through each history entry adding it to the dialog
472 while (histentry
!= NULL
) {
473 SendDlgItemMessage(hDlg
,IDLIST
,LB_INSERTSTRING
,0,(LPARAM
)editbuffer_getasline(histentry
->Statement
));
474 SendDlgItemMessage(hDlg
,IDLIST
,LB_SETITEMDATA
,0,(LPARAM
)idx
);
475 histentry
= histentry
->Next
;
479 SendDlgItemMessage(hDlg
,IDLIST
,LB_SETCURSEL
,(LPARAM
)idx
-1,0);
482 switch(LOWORD(wParam
)) {
484 switch(HIWORD(wParam
)) {
486 idx
= SendDlgItemMessage(hDlg
,IDLIST
,LB_GETCURSEL
,0,0);
489 idx
= SendDlgItemMessage(hDlg
,IDLIST
,LB_GETITEMDATA
,idx
,0);
490 EndDialog(hDlg
,idx
+1);
497 GetClientRect(hDlg
,&rc
);
498 MoveWindow(GetDlgItem(hDlg
,IDLIST
),0,0,rc
.right
,rc
.bottom
,1);
508 /*------------------------------------------------------------------------
509 Procedure: SaveText ID:1
510 Purpose: Saves the contents of the session transcript. It will
511 loop for each line and write it to the specified file
512 Input: The name of the file where the session will be saved
513 Output: The session is saved
514 Errors: If it can't open the file for writing it will show an
516 --------------------------------------------------------------------------
518 06 Oct 2003 - Chris Watford watford@uiuc.edu
519 - Corrected wsprintf error
520 ------------------------------------------------------------------------*/
521 static void SaveText(char *fname
)
524 HWND hEdit
= (HWND
)GetWindowLongPtr(hwndSession
,DWLP_USER
);
525 int linesCount
= SendMessage(hEdit
,EM_GETLINECOUNT
,0,0);
527 char *buf
= SafeMalloc(8192);
529 f
= fopen(fname
,"wb");
532 // corrected error using wsprintf
533 wsprintf(buf
, "Impossible to open %s for writing", fname
);
539 for (i
= 0; i
< linesCount
; i
++)
541 *(unsigned short *)buf
= 8100;
542 len
= SendMessage(hEdit
, EM_GETLINE
, i
, (LPARAM
)buf
);
544 fprintf(f
, "%s\r\n", buf
+1);
545 //fwrite(buf,1,len+2,f);
552 /*------------------------------------------------------------------------
553 Procedure: SaveML ID:1
554 Author: Chris Watford watford@uiuc.edu
555 Purpose: Saves the ML source to a file, commenting out functions
556 that contained errors
557 Input: The name of the file where the session will be saved
558 Output: The session is saved
559 Errors: If it can't open the file for writing it will show an
561 ------------------------------------------------------------------------*/
562 static void SaveML(char *fname
)
565 char *buf
= SafeMalloc(8192);
567 f
= fopen(fname
, "wb");
571 wsprintf(buf
, "Impossible to open %s for writing", fname
);
576 fprintf(f
, "(* %s *)\r\n\r\n", fname
);
580 StatementHistory
*h
= NULL
;
581 EditBuffer
*stmt
= NULL
;
584 for(h
= History
; h
->Next
!= NULL
; h
= h
->Next
);
587 // this is NOT the fastest method, BUT this is the easiest
589 for(; h
!= NULL
; h
= h
->Prev
)
595 // comment out incorrect lines
598 char *buff
= editbuffer_getasbuffer(stmt
);
599 fprintf(f
, "%s\r\n", buff
);
602 char *buff
= editbuffer_getasbuffer(stmt
);
603 fprintf(f
, "(* Syntax Error or Unbound Value\r\n%s\r\n *)\r\n", buff
);
616 /*------------------------------------------------------------------------
617 Procedure: Add_Clipboard_To_Queue ID:1
618 Author: Chris Watford watford@uiuc.edu
619 Purpose: Adds the clipboard text to the control
623 --------------------------------------------------------------------------
625 16 Sept 2003 - Chris Watford watford@uiuc.edu
626 - Added method to update edit buffer with paste contents
627 ------------------------------------------------------------------------*/
628 static void Add_Clipboard_To_Queue(void)
630 if (IsClipboardFormatAvailable(CF_TEXT
) && OpenClipboard(hwndMain
))
632 HANDLE hClipData
= GetClipboardData(CF_TEXT
);
634 if (hClipData
!= NULL
)
636 char *str
= GlobalLock(hClipData
);
643 Add_Char_To_Queue(*str
);
648 // added to fix odd errors
649 RefreshCurrentEditBuffer();
652 GlobalUnlock(hClipData
);
659 /*------------------------------------------------------------------------
660 Procedure: CopyToClipboard ID:1
661 Purpose: Copies text to the clipboard
662 Input: Window with the edit control
665 ------------------------------------------------------------------------*/
666 static void CopyToClipboard(HWND hwnd
)
668 HWND hwndEdit
= (HWND
)GetWindowLongPtr(hwndSession
,DWLP_USER
);
669 SendMessage(hwndEdit
,WM_COPY
,0,0);
672 /*------------------------------------------------------------------------
673 Procedure: ResetText ID:1
674 Purpose: Resets the text? I'm not really sure
676 Output: Always returns 0
678 ------------------------------------------------------------------------*/
681 HWND hwndEdit
= (HWND
) GetWindowLongPtr(hwndSession
,DWLP_USER
);
683 int len
= SendMessage(hwndEdit
,WM_GETTEXTLENGTH
,0,0);
684 char *tmp
= malloc(len
+10),*p
;
686 memset(tmp
,0,len
+10);
690 SendMessage(hwndEdit
,EM_GETTEXTRANGE
,0,(LPARAM
)&cr
);
692 while (*p
&& *p
!= '\r')
694 SendMessage(hwndEdit
,EM_SETSEL
,0,(LPARAM
)-1);
695 SendMessage(hwndEdit
,EM_REPLACESEL
,0,(LPARAM
)p
);
696 InvalidateRect(hwndEdit
,0,1);
701 /*------------------------------------------------------------------------
702 Procedure: HandleCommand ID:1
703 Purpose: Handles all menu commands.
707 --------------------------------------------------------------------------
709 06 Oct 2003 - Chris Watford watford@uiuc.edu
710 - Removed entries that crashed OCaml
711 - Removed useless entries
712 - Added Save ML and Save Transcript
713 ------------------------------------------------------------------------*/
714 void HandleCommand(HWND hwnd
, WPARAM wParam
,LPARAM lParam
)
719 switch(LOWORD(wParam
)) {
721 fname
= SafeMalloc(512);
722 if (OpenMlFile(fname
,512)) {
723 char *buf
= SafeMalloc(512);
724 char *p
= strrchr(fname
,'.');
725 if (p
&& !stricmp(p
,".ml")) {
726 wsprintf(buf
, "#use \"%s\";;", fname
);
727 AddLineToControl(buf
);
729 else if (p
&& !stricmp(p
,".cmo")) {
730 wsprintf(buf
, "#load \"%s\";;", fname
);
731 AddLineToControl(buf
);
738 AddLineToControl("Gc.full_major();;");
744 Add_Clipboard_To_Queue();
747 CopyToClipboard(hwnd
);
750 // updated to save a transcript
752 fname
= SafeMalloc(512);
753 if (GetSaveName(fname
,512)) {
759 // updated to save an ML file
761 fname
= SafeMalloc(512);
762 if (GetSaveMLName(fname
,512))
769 // updated to work with new history system
771 r
= CallDlgProc(HistoryDlgProc
,IDD_HISTORY
);
775 AddLineToControl(GetHistoryLine(r
-1));
780 // Removed by Chris Watford
786 CallChangeFont(hwndMain
);
789 ProgramParams
.TextColor
= CallChangeColor(ProgramParams
.TextColor
);
793 BackColor
= CallChangeColor(BackColor
);
794 DeleteObject(BackgroundBrush
);
795 BackgroundBrush
= CreateSolidBrush(BackColor
);
802 /* Removed, really not very useful in this IDE
804 SendMessage(hwndMDIClient,WM_MDITILE,0,0);
806 case IDM_WINDOWCASCADE:
807 SendMessage(hwndMDIClient,WM_MDICASCADE,0,0);
809 case IDM_WINDOWICONS:
810 SendMessage(hwndMDIClient,WM_MDIICONARRANGE,0,0);
815 PostMessage(hwnd
,WM_CLOSE
,0,0);
818 CallDlgProc(AboutDlgProc
,IDD_ABOUT
);
821 if (LOWORD(wParam
) >= IDEDITCONTROL
&& LOWORD(wParam
) < IDEDITCONTROL
+5) {
822 switch (HIWORD(wParam
)) {