Merge commit 'ocaml3102'
[ocaml.git] / win32caml / menu.c
blob850f21ade0c36be8df0b33e3294966a8dc62e27e
1 /***********************************************************************/
2 /* */
3 /* Objective Caml */
4 /* */
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. */
10 /* */
11 /***********************************************************************/
13 /***********************************************************************/
14 /* Changes made by Chris Watford to enhance the source editor */
15 /* Began 14 Sept 2003 - watford@uiuc.edu */
16 /***********************************************************************/
18 /* $Id$ */
20 #include <stdio.h>
21 #include <windows.h>
22 #include <Richedit.h>
23 #include "inria.h"
24 #include "inriares.h"
25 #include "history.h"
27 LOGFONT CurrentFont;
28 int CurrentFontFamily = (FIXED_PITCH | FF_MODERN);
29 int CurrentFontStyle;
30 char CurrentFontName[64] = "Courier";
32 /*------------------------------------------------------------------------
33 Procedure: OpenMlFile ID:1
34 Purpose: Opens a file, either a source file (*.ml) or an *.cmo
35 file.
36 Input: A buffer where the name will be stored, and its
37 length
38 Output: The user's choice will be stored in the buffer.
39 Errors: None
40 ------------------------------------------------------------------------*/
41 int OpenMlFile(char *fname,int lenbuf)
43 OPENFILENAME ofn;
44 int r;
45 char *p,defext[5],tmp[512];
47 memset(&ofn,0,sizeof(OPENFILENAME));
48 memset(tmp,0,sizeof(tmp));
49 fname[0] = 0;
50 strcpy(tmp,"ocaml sources|*.ml|bytecode object files|*.cmo|All files|*.*");
51 p = tmp;
52 while (*p) {
53 if (*p == '|')
54 *p = 0;
55 p++;
57 strcpy(defext,"ml");
58 ofn.lStructSize = sizeof(OPENFILENAME);
59 ofn.hwndOwner = hwndMain;
60 ofn.lpstrFilter = tmp;
61 ofn.nFilterIndex = 1;
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);
70 if (r) {
71 /* Replace backslashes by forward slashes in file name */
72 for (p = fname; *p != 0; p++)
73 if (*p == '\\') *p = '/';
75 return r;
78 /*------------------------------------------------------------------------
79 Procedure: GetSaveName ID:1
80 Purpose: Get a name to save the current session (Save as menu
81 item)
82 Input: A buffer where the name of the file will be stored,
83 and its length
84 Output: The name of the file choosen by the user will be
85 stored in the buffer
86 Errors: none
87 ------------------------------------------------------------------------*/
88 int GetSaveName(char *fname,int lenbuf)
90 OPENFILENAME ofn;
91 int r;
92 char *p,defext[5],tmp[512];
94 memset(&ofn,0,sizeof(OPENFILENAME));
95 memset(tmp,0,sizeof(tmp));
96 fname[0] = 0;
97 strcpy(tmp,"Text files|*.txt");
98 p = tmp;
99 while (*p) {
100 if (*p == '|')
101 *p = 0;
102 p++;
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);
117 if (r == 0)
118 return 0;
119 else return 1;
122 /*------------------------------------------------------------------------
123 Procedure: GetSaveMLName ID:1
124 Purpose: Get a name to save the current OCaml code to (Save as menu
125 item)
126 Input: A buffer where the name of the file will be stored,
127 and its length
128 Output: The name of the file choosen by the user will be
129 stored in the buffer
130 Errors: none
131 ------------------------------------------------------------------------*/
132 int GetSaveMLName(char *fname, int lenbuf)
134 OPENFILENAME ofn;
135 int r;
136 char *p,defext[5],tmp[512];
138 memset(&ofn,0,sizeof(OPENFILENAME));
139 memset(tmp,0,sizeof(tmp));
140 fname[0] = 0;
141 strcpy(tmp,"OCaml Source Files|*.ml");
142 p = tmp;
143 while (*p) {
144 if (*p == '|')
145 *p = 0;
146 p++;
148 strcpy(defext,"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);
161 if (r == 0)
162 return 0;
163 else return 1;
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
170 ocaml.exe.
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
174 Errors: None
175 ------------------------------------------------------------------------*/
176 int BrowseForFile(char *fname,char *path)
178 OPENFILENAME ofn;
179 char *p,tmp[512],browsefor[512];
180 int r;
182 memset(tmp,0,sizeof(tmp));
183 strncpy(tmp,fname,sizeof(tmp)-1);
184 p = tmp;
185 while (*p) {
186 if (*p == '|')
187 *p = 0;
188 p++;
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);
205 if (r == 0)
206 return 0;
207 else return 1;
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
215 parameters.
216 Input: The calling window handle
217 Output: Zero if the user cancelled, 1 otherwise.
218 Errors: None
219 ------------------------------------------------------------------------*/
220 static int CallChangeFont(HWND hwnd)
222 LOGFONT lf;
223 CHOOSEFONT cf;
224 int r;
225 HWND hwndChild;
227 memset(&cf, 0, sizeof(CHOOSEFONT));
228 memcpy(&lf, &CurrentFont, sizeof(LOGFONT));
229 cf.lStructSize = sizeof(CHOOSEFONT);
230 cf.hwndOwner = hwnd;
231 cf.lpLogFont = &lf;
232 cf.Flags = CF_SCREENFONTS | CF_EFFECTS | CF_APPLY | CF_INITTOLOGFONTSTRUCT;
233 cf.nFontType = SCREEN_FONTTYPE;
234 r = ChooseFont(&cf);
235 if (!r)
236 return (0);
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);
245 ForceRepaint();
246 return (1);
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.
255 Errors: None
256 ------------------------------------------------------------------------*/
257 int CallDlgProc(BOOL (CALLBACK *fn)(HWND,UINT,WPARAM,LPARAM), int id)
259 int result;
261 result = DialogBoxParam(hInst, MAKEINTRESOURCE(id), GetActiveWindow(),
262 fn, 0);
263 return result;
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.
275 Errors: None
276 ------------------------------------------------------------------------*/
277 static COLORREF CallChangeColor(COLORREF InitialColor)
279 CHOOSECOLOR CC;
280 COLORREF CustColors[16];
281 int r, g, b, i;
282 memset(&CC, 0, sizeof(CHOOSECOLOR));
283 r = g = b = 0;
284 for (i = 0; i < 16; i++) {
285 CustColors[i] = RGB(r, g, b);
286 if (r < 255)
287 r += 127;
288 else if (g < 255)
289 g += 127;
290 else if (b < 255)
291 g += 127;
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
308 is not done yet
309 Input: None
310 Output: 1 if OK, 0, user cancelled
311 Errors: None
312 ------------------------------------------------------------------------*/
313 static int CallPrintSetup(void)
315 PAGESETUPDLG sd;
316 int r;
318 memset(&sd,0,sizeof(sd));
319 sd.lStructSize = sizeof(sd);
320 sd.Flags = PSD_RETURNDEFAULT;
321 r = PageSetupDlg(&sd);
322 if (!r)
323 return 0;
324 sd.Flags = 0;
325 r = PageSetupDlg(&sd);
326 return r;
330 /*------------------------------------------------------------------------
331 Procedure: Undo ID:1
332 Purpose: Send an UNDO command to the edit field.
333 Input: The parent window of the control
334 Output: None
335 Errors: None
336 ------------------------------------------------------------------------*/
337 void Undo(HWND hwnd)
339 HWND hEdit;
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
348 current session.
349 Input: None
350 Output: None
351 Errors: None
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
363 Output: None
364 Errors:
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
379 Output: None
380 Errors: If the line is empty, nothing will be done
381 ------------------------------------------------------------------------*/
382 void AddLineToControl(char *buf)
384 HWND hEditCtrl;
386 if (*buf == 0)
387 return;
389 hEditCtrl = (HWND)GetWindowLongPtr(hwndSession,DWLP_USER);
391 GotoEOF();
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
404 Output: None
405 Errors: If the line is empty, nothing will be done
406 --------------------------------------------------------------------------
407 Edit History:
408 16 Sept 2003 - Chris Watford watford@uiuc.edu
409 - Basically this is AddLineToControl, but without appending a
410 newline
411 ------------------------------------------------------------------------*/
412 void AddStringToControl(char* buf)
414 HWND hEditCtrl;
416 if(buf == NULL)
417 return;
419 if((*buf) == 0)
420 return;
422 hEditCtrl = (HWND)GetWindowLongPtr(hwndSession, DWLP_USER);
423 GotoEOF();
425 SendMessage(hEditCtrl ,EM_REPLACESEL, (WPARAM)FALSE, (LPARAM)buf);
428 /*------------------------------------------------------------------------
429 Procedure: AboutDlgProc ID:1
430 Purpose: Shows the "About" dialog box
431 Input:
432 Output:
433 Errors:
434 ------------------------------------------------------------------------*/
435 static BOOL CALLBACK AboutDlgProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
437 if (message == WM_CLOSE)
438 EndDialog(hDlg,1);
439 return 0;
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
450 Output:
451 Errors:
452 --------------------------------------------------------------------------
453 Edit History:
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
457 just a 1 liner
458 ------------------------------------------------------------------------*/
459 static BOOL CALLBACK HistoryDlgProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
461 StatementHistory *histentry;
462 int idx;
463 RECT rc;
465 switch (message) {
466 case WM_INITDIALOG:
467 SendDlgItemMessage(hDlg,IDLIST,WM_SETFONT,(WPARAM)ProgramParams.hFont,0);
468 histentry = History; // get our statement history object
469 idx = 0;
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;
476 idx++;
479 SendDlgItemMessage(hDlg,IDLIST,LB_SETCURSEL,(LPARAM)idx-1,0);
480 return 1;
481 case WM_COMMAND:
482 switch(LOWORD(wParam)) {
483 case IDLIST:
484 switch(HIWORD(wParam)) {
485 case LBN_DBLCLK:
486 idx = SendDlgItemMessage(hDlg,IDLIST,LB_GETCURSEL,0,0);
487 if (idx == LB_ERR)
488 break;
489 idx = SendDlgItemMessage(hDlg,IDLIST,LB_GETITEMDATA,idx,0);
490 EndDialog(hDlg,idx+1);
491 return 1;
493 break;
495 break;
496 case WM_SIZE:
497 GetClientRect(hDlg,&rc);
498 MoveWindow(GetDlgItem(hDlg,IDLIST),0,0,rc.right,rc.bottom,1);
499 break;
501 case WM_CLOSE:
502 EndDialog(hDlg,0);
503 break;
505 return 0;
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
515 error box
516 --------------------------------------------------------------------------
517 Edit History:
518 06 Oct 2003 - Chris Watford watford@uiuc.edu
519 - Corrected wsprintf error
520 ------------------------------------------------------------------------*/
521 static void SaveText(char *fname)
523 int i,len;
524 HWND hEdit = (HWND)GetWindowLongPtr(hwndSession,DWLP_USER);
525 int linesCount = SendMessage(hEdit,EM_GETLINECOUNT,0,0);
526 FILE *f;
527 char *buf = SafeMalloc(8192);
529 f = fopen(fname,"wb");
530 if (f == NULL)
532 // corrected error using wsprintf
533 wsprintf(buf, "Impossible to open %s for writing", fname);
535 ShowDbgMsg(buf);
536 return;
539 for (i = 0; i < linesCount; i++)
541 *(unsigned short *)buf = 8100;
542 len = SendMessage(hEdit, EM_GETLINE, i, (LPARAM)buf);
543 buf[len] = '\0';
544 fprintf(f, "%s\r\n", buf+1);
545 //fwrite(buf,1,len+2,f);
548 fclose(f);
549 free(buf);
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
560 error box
561 ------------------------------------------------------------------------*/
562 static void SaveML(char *fname)
564 FILE *f;
565 char *buf = SafeMalloc(8192);
567 f = fopen(fname, "wb");
569 if(f == NULL)
571 wsprintf(buf, "Impossible to open %s for writing", fname);
572 ShowDbgMsg(buf);
573 return;
576 fprintf(f, "(* %s *)\r\n\r\n", fname);
578 if(History != NULL)
580 StatementHistory *h = NULL;
581 EditBuffer *stmt = NULL;
583 // get to the end
584 for(h = History; h->Next != NULL; h = h->Next);
586 // go back :(
587 // this is NOT the fastest method, BUT this is the easiest
588 // on the subsystem
589 for(; h != NULL; h = h->Prev)
591 stmt = h->Statement;
593 if(stmt != NULL)
595 // comment out incorrect lines
596 if(stmt->isCorrect)
598 char *buff = editbuffer_getasbuffer(stmt);
599 fprintf(f, "%s\r\n", buff);
600 free(buff);
601 } else {
602 char *buff = editbuffer_getasbuffer(stmt);
603 fprintf(f, "(* Syntax Error or Unbound Value\r\n%s\r\n *)\r\n", buff);
604 free(buff);
608 fprintf(f, "\r\n");
612 fclose(f);
613 free(buf);
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
620 Input:
621 Output:
622 Errors:
623 --------------------------------------------------------------------------
624 Edit History:
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);
638 if (str != NULL)
640 while ((*str) != 0)
642 if (*str != '\r')
643 Add_Char_To_Queue(*str);
645 str++;
648 // added to fix odd errors
649 RefreshCurrentEditBuffer();
652 GlobalUnlock(hClipData);
655 CloseClipboard();
659 /*------------------------------------------------------------------------
660 Procedure: CopyToClipboard ID:1
661 Purpose: Copies text to the clipboard
662 Input: Window with the edit control
663 Output:
664 Errors:
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
675 Input:
676 Output: Always returns 0
677 Errors:
678 ------------------------------------------------------------------------*/
679 int ResetText(void)
681 HWND hwndEdit = (HWND) GetWindowLongPtr(hwndSession,DWLP_USER);
682 TEXTRANGE cr;
683 int len = SendMessage(hwndEdit,WM_GETTEXTLENGTH,0,0);
684 char *tmp = malloc(len+10),*p;
686 memset(tmp,0,len+10);
687 cr.chrg.cpMin = 0;
688 cr.chrg.cpMax = -1;
689 cr.lpstrText = tmp;
690 SendMessage(hwndEdit,EM_GETTEXTRANGE,0,(LPARAM)&cr);
691 p = tmp+len/2;
692 while (*p && *p != '\r')
693 p++;
694 SendMessage(hwndEdit,EM_SETSEL,0,(LPARAM)-1);
695 SendMessage(hwndEdit,EM_REPLACESEL,0,(LPARAM)p);
696 InvalidateRect(hwndEdit,0,1);
697 free(tmp);
698 return 0;
701 /*------------------------------------------------------------------------
702 Procedure: HandleCommand ID:1
703 Purpose: Handles all menu commands.
704 Input:
705 Output:
706 Errors:
707 --------------------------------------------------------------------------
708 Edit History:
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)
716 char *fname;
717 int r;
719 switch(LOWORD(wParam)) {
720 case IDM_OPEN:
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);
733 free(buf);
735 free(fname);
736 break;
737 case IDM_GC:
738 AddLineToControl("Gc.full_major();;");
739 break;
740 case IDCTRLC:
741 InterruptOcaml();
742 break;
743 case IDM_EDITPASTE:
744 Add_Clipboard_To_Queue();
745 break;
746 case IDM_EDITCOPY:
747 CopyToClipboard(hwnd);
748 break;
750 // updated to save a transcript
751 case IDM_SAVEAS:
752 fname = SafeMalloc(512);
753 if (GetSaveName(fname,512)) {
754 SaveText(fname);
756 free(fname);
757 break;
759 // updated to save an ML file
760 case IDM_SAVE:
761 fname = SafeMalloc(512);
762 if (GetSaveMLName(fname,512))
764 SaveML(fname);
766 free(fname);
767 break;
769 // updated to work with new history system
770 case IDM_HISTORY:
771 r = CallDlgProc(HistoryDlgProc,IDD_HISTORY);
773 if (r)
775 AddLineToControl(GetHistoryLine(r-1));
777 break;
779 case IDM_PRINTSU:
780 // Removed by Chris Watford
781 // seems to die
782 // CallPrintSetup();
783 break;
785 case IDM_FONT:
786 CallChangeFont(hwndMain);
787 break;
788 case IDM_COLORTEXT:
789 ProgramParams.TextColor = CallChangeColor(ProgramParams.TextColor);
790 ForceRepaint();
791 break;
792 case IDM_BACKCOLOR:
793 BackColor = CallChangeColor(BackColor);
794 DeleteObject(BackgroundBrush);
795 BackgroundBrush = CreateSolidBrush(BackColor);
796 ForceRepaint();
797 break;
798 case IDM_EDITUNDO:
799 Undo(hwnd);
800 break;
802 /* Removed, really not very useful in this IDE
803 case IDM_WINDOWTILE:
804 SendMessage(hwndMDIClient,WM_MDITILE,0,0);
805 break;
806 case IDM_WINDOWCASCADE:
807 SendMessage(hwndMDIClient,WM_MDICASCADE,0,0);
808 break;
809 case IDM_WINDOWICONS:
810 SendMessage(hwndMDIClient,WM_MDIICONARRANGE,0,0);
811 break;
814 case IDM_EXIT:
815 PostMessage(hwnd,WM_CLOSE,0,0);
816 break;
817 case IDM_ABOUT:
818 CallDlgProc(AboutDlgProc,IDD_ABOUT);
819 break;
820 default:
821 if (LOWORD(wParam) >= IDEDITCONTROL && LOWORD(wParam) < IDEDITCONTROL+5) {
822 switch (HIWORD(wParam)) {
823 case EN_ERRSPACE:
824 ResetText();
825 break;
828 break;