18 unsigned char *QCC_ReadFile (const char *fname, void *buffer, int len)
22 f = fopen(fname, "rb");
25 length = fread(buffer, 1, len, f);
33 int QCC_FileSize (const char *fname)
37 f = fopen(fname, "rb");
40 fseek(f, 0, SEEK_END);
47 pbool QCC_WriteFile (const char *name, void *data, int len)
51 f = fopen(name, "wb");
54 length = fwrite(data, 1, len, f);
66 void Sys_Error(const char *text, ...)
69 static char msg[2048];
71 va_start (argptr,text);
72 QC_vsnprintf (msg,sizeof(msg)-1, text,argptr);
75 QCC_Error(ERR_INTERNAL, "%s", msg);
80 int logprintf(const char *format, ...)
83 static char string[1024];
85 va_start (argptr, format);
87 _vsnprintf (string,sizeof(string)-1, format,argptr);
89 vsnprintf (string,sizeof(string), format,argptr);
95 fputs(string, logfile);
110 #define Edit_Redo(hwndCtl) ((BOOL)(DWORD)SNDMSG((hwndCtl), EM_REDO, 0L, 0L))
113 #define MAIN_WINDOW_CLASS_NAME "FTEMAINWINDOW"
114 #define MDI_WINDOW_CLASS_NAME "FTEMDIWINDOW"
115 #define EDIT_WINDOW_CLASS_NAME "FTEEDITWINDOW"
116 #define OPTIONS_WINDOW_CLASS_NAME "FTEOPTIONSWINDOW"
118 #define EM_GETSCROLLPOS (WM_USER + 221)
119 #define EM_SETSCROLLPOS (WM_USER + 222)
123 int GUIprintf(const char *msg, ...);
124 void GUIPrint(HWND wnd, char *msg);
128 void RunCompiler(char *args);
130 HINSTANCE ghInstance;
133 pbool resetprogssrc; //progs.src was changed, reload project info.
162 #define NUMBUTTONS sizeof(buttons)/sizeof(buttons[0])
166 void GUI_DialogPrint(char *title, char *text)
168 MessageBox(mainwindow, text, title, 0);
171 HWND CreateAnEditControl(HWND parent)
176 richedit = LoadLibrary("RICHED32.DLL");
178 newc=CreateWindowEx(WS_EX_CLIENTEDGE,
179 richedit?RICHEDIT_CLASS:"EDIT",
181 WS_CHILD /*| ES_READONLY*/ | WS_VISIBLE |
182 WS_HSCROLL | WS_VSCROLL | ES_LEFT | ES_WANTRETURN |
183 ES_MULTILINE | ES_AUTOVSCROLL,
191 newc=CreateWindowEx(WS_EX_CLIENTEDGE,
192 richedit?RICHEDIT_CLASS10A:"EDIT", //fall back to the earlier version
194 WS_CHILD /*| ES_READONLY*/ | WS_VISIBLE |
195 WS_HSCROLL | WS_VSCROLL | ES_LEFT | ES_WANTRETURN |
196 ES_MULTILINE | ES_AUTOVSCROLL,
204 { //you've not got RICHEDIT installed properly, I guess
205 FreeLibrary(richedit);
207 newc=CreateWindowEx(WS_EX_CLIENTEDGE,
210 WS_CHILD /*| ES_READONLY*/ | WS_VISIBLE |
211 WS_HSCROLL | WS_VSCROLL | ES_LEFT | ES_WANTRETURN |
212 ES_MULTILINE | ES_AUTOVSCROLL,
220 //go to lucidia console, 10pt
223 memset(&cf, 0, sizeof(cf));
224 cf.cbSize = sizeof(cf);
225 cf.dwMask = CFM_BOLD | CFM_FACE;// | CFM_SIZE;
226 strcpy(cf.szFaceName, "Lucida Console");
229 SendMessage(newc, EM_SETCHARFORMAT, SCF_ALL, (WPARAM)&cf);
234 SendMessage(newc, EM_EXLIMITTEXT, 0, 1<<20);
237 ShowWindow(newc, SW_SHOW);
266 IDI_O_CHANGE_PROGS_SRC,
267 IDI_O_ADDITIONALPARAMETERS,
273 IDI_O_SYNTAX_HIGHLIGHTING,
279 typedef struct editor_s {
280 char filename[MAX_PATH]; //abs
284 time_t filemodifiedtime;
285 struct editor_s *next;
290 void EditorReload(editor_t *editor);
291 int EditorSave(editor_t *edit);
292 void EditFile(char *name, int line);
293 pbool EditorModified(editor_t *e);
294 int Rehighlight(editor_t *edit);
296 void QueryOpenFile(void)
298 char filename[MAX_PATH];
299 char oldpath[MAX_PATH+10];
301 memset(&ofn, 0, sizeof(ofn));
302 ofn.lStructSize = sizeof(ofn);
303 ofn.hInstance = ghInstance;
304 ofn.lpstrFile = filename;
305 ofn.nMaxFile = sizeof(filename)-1;
306 memset(filename, 0, sizeof(filename));
307 GetCurrentDirectory(sizeof(oldpath)-1, oldpath);
308 if (GetOpenFileName(&ofn))
309 EditFile(filename, -1);
310 SetCurrentDirectory(oldpath);
313 //IDM_ stuff that needs no active menu
314 void GenericMenu(WPARAM wParam)
316 switch(LOWORD(wParam))
323 MessageBox(NULL, "FTE QuakeC Compiler\nWritten by Forethough Entertainment.\n\nIt has a few cool features, like a semi-useful IDE.\n\nSupports:\nPrecompiler (with macros)\nArrays\n+= / -= / *= / /= operations.\nSwitch statements\nfor loops\nLots of optimisations.", "About", 0);
327 SendMessage(mdibox, WM_MDICASCADE, 0, 0);
330 SendMessage(mdibox, WM_MDITILE, MDITILE_HORIZONTAL, 0);
333 SendMessage(mdibox, WM_MDITILE, MDITILE_VERTICAL, 0);
338 void EditorMenu(editor_t *editor, WPARAM wParam)
340 switch(LOWORD(wParam))
346 total = SendMessage(editor->editpane, EM_GETSELTEXT, (WPARAM)sizeof(buffer)-1, (LPARAM)buffer);
350 MessageBox(NULL, "There is no name currently selected.", "Whoops", 0);
354 EditFile(buffer, -1);
364 total = SendMessage(editor->editpane, EM_GETSELTEXT, (WPARAM)sizeof(buffer)-1, (LPARAM)buffer);
368 MessageBox(NULL, "There is no name currently selected.", "Whoops", 0);
372 GoToDefinition(buffer);
380 Edit_Undo(editor->editpane);
383 Edit_Redo(editor->editpane);
392 static LONG CALLBACK EditorWndProc(HWND hWnd,UINT message,
393 WPARAM wParam,LPARAM lParam)
400 for (editor = editors; editor; editor = editor->next)
402 if (editor->window == hWnd)
404 if (editor->window == NULL)
405 break; //we're actually creating it now.
414 if (editor->modified)
416 switch (MessageBox(hWnd, "Would you like to save?", editor->filename, MB_YESNOCANCEL))
421 if (!EditorSave(editor))
432 if (editor == editors)
434 editors = editor->next;
438 for (e = editors; e; e = e->next)
440 if (e->next == editor)
442 e->next = editor->next;
447 MessageBox(0, "Couldn't destroy file reference", "WARNING", 0);
451 editor->editpane = CreateAnEditControl(hWnd);
453 editor->editpane=CreateWindowEx(WS_EX_CLIENTEDGE,
454 richedit?RICHEDIT_CLASS:"EDIT",
456 WS_CHILD | WS_VISIBLE |
457 WS_HSCROLL | WS_VSCROLL | ES_LEFT | ES_WANTRETURN |
458 ES_MULTILINE | ES_AUTOVSCROLL,
467 SendMessage(editor->editpane, EM_EXLIMITTEXT, 0, 1<<31);
469 SendMessage(editor->editpane, EM_SETUNDOLIMIT, 256, 256);
473 GetClientRect(hWnd, &rect);
474 SetWindowPos(editor->editpane, NULL, 0, 0, rect.right-rect.left, rect.bottom-rect.top, 0);
477 hdc=BeginPaint(hWnd,(LPPAINTSTRUCT)&ps);
479 EndPaint(hWnd,(LPPAINTSTRUCT)&ps);
483 if (HIWORD(wParam) == EN_CHANGE && (HWND)lParam == editor->editpane)
485 if (!editor->modified)
490 editor->modified = true;
491 if (EditorModified(editor))
492 if (MessageBox(NULL, "warning: file was modified externally. reload?", "Modified!", MB_YESNO) == IDYES)
493 EditorReload(editor);
496 SendMessage(editor->editpane, EM_EXGETSEL, 0, (LPARAM) &chrg);
497 if (editor->modified)
498 sprintf(title, "*%s:%i - FTEQCC Editor", editor->filename, 1+Edit_LineFromChar(editor->editpane, chrg.cpMin));
500 sprintf(title, "%s:%i - FTEQCC Editor", editor->filename, 1+Edit_LineFromChar(editor->editpane, chrg.cpMin));
501 SetWindowText(editor->window, title);
508 EditorMenu(editor, wParam);
516 nmhdr = (NMHDR *)lParam;
520 sel = (SELCHANGE *)nmhdr;
521 if (editor->modified)
522 sprintf(title, "*%s:%i - FTEQCC Editor", editor->filename, 1+Edit_LineFromChar(editor->editpane, sel->chrg.cpMin));
524 sprintf(title, "%s:%i - FTEQCC Editor", editor->filename, 1+Edit_LineFromChar(editor->editpane, sel->chrg.cpMin));
525 SetWindowText(editor->window, title);
532 return DefMDIChildProc(hWnd,message,wParam,lParam);
534 return DefWindowProc(hWnd,message,wParam,lParam);
540 static DWORD lastcolour;
541 int GUIEmitText(HWND wnd, int start, char *text, int len)
552 Edit_SetSel(wnd,start,start);
553 Edit_ReplaceSel(wnd,text);
555 if (!strcmp(text, "void"))
556 colour = RGB(0, 0, 255);
557 else if (!strcmp(text, "float"))
558 colour = RGB(0, 0, 255);
559 else if (!strcmp(text, "vector"))
560 colour = RGB(0, 0, 255);
561 else if (!strcmp(text, "entity"))
562 colour = RGB(0, 0, 255);
563 else if (!strcmp(text, "local"))
564 colour = RGB(0, 0, 255);
565 else if (!strcmp(text, "string"))
566 colour = RGB(0, 0, 255);
567 else if (!strcmp(text, "struct"))
568 colour = RGB(0, 0, 255);
569 else if (!strcmp(text, "class"))
570 colour = RGB(0, 0, 255);
571 else if (!strcmp(text, "union"))
572 colour = RGB(0, 0, 255);
573 else if (!strcmp(text, "const"))
574 colour = RGB(0, 0, 255);
575 else if (!strcmp(text, "var"))
576 colour = RGB(0, 0, 255);
577 else if (!strcmp(text, "nosave"))
578 colour = RGB(0, 0, 255);
580 else if (!strcmp(text, "goto"))
581 colour = RGB(255, 0, 0);
582 else if (!strcmp(text, "thinktime"))
583 colour = RGB(0, 0, 255);
584 else if (!strcmp(text, "if"))
585 colour = RGB(0, 0, 255);
586 else if (!strcmp(text, "else"))
587 colour = RGB(0, 0, 255);
588 else if (!strcmp(text, "switch"))
589 colour = RGB(0, 0, 255);
590 else if (!strcmp(text, "case"))
591 colour = RGB(0, 0, 255);
592 else if (!strcmp(text, "default"))
593 colour = RGB(0, 0, 255);
594 else if (!strcmp(text, "break"))
595 colour = RGB(0, 0, 255);
596 else if (!strcmp(text, "continue"))
597 colour = RGB(0, 0, 255);
598 else if (!strcmp(text, "do"))
599 colour = RGB(0, 0, 255);
600 else if (!strcmp(text, "while"))
601 colour = RGB(0, 0, 255);
602 else if (!strcmp(text, "for"))
603 colour = RGB(0, 0, 255);
604 else if (!strcmp(text, "return"))
605 colour = RGB(0, 0, 255);
607 else if (!strcmp(text, "self"))
608 colour = RGB(0, 0, 127);
609 else if (!strcmp(text, "this"))
610 colour = RGB(0, 0, 127);
611 else if (!strcmp(text, "other"))
612 colour = RGB(0, 0, 127);
613 else if (!strcmp(text, "world"))
614 colour = RGB(0, 0, 127);
615 else if (!strcmp(text, "time"))
616 colour = RGB(0, 0, 127);
619 else if (!strcmp(text, "#define"))
620 colour = RGB(0, 128, 255);
621 else if (!strcmp(text, "#ifdef"))
622 colour = RGB(0, 128, 255);
623 else if (!strcmp(text, "#ifndef"))
624 colour = RGB(0, 128, 255);
625 else if (!strcmp(text, "#else"))
626 colour = RGB(0, 128, 255);
627 else if (!strcmp(text, "#endif"))
628 colour = RGB(0, 128, 255);
629 else if (!strcmp(text, "#undef"))
630 colour = RGB(0, 128, 255);
631 else if (!strcmp(text, "#pragma"))
632 colour = RGB(0, 128, 255);
633 else if (!strcmp(text, "#includelist"))
634 colour = RGB(0, 128, 255);
635 else if (!strcmp(text, "#endlist"))
636 colour = RGB(0, 128, 255);
639 else if (*text == '\"')
640 colour = RGB(128, 0, 0);
642 else if (!strncmp(text, "//", 2))
643 colour = RGB(0, 127, 0);
644 else if (!strncmp(text, "/*", 2))
645 colour = RGB(0, 127, 0);
647 colour = RGB(0, 0, 0);
652 for (c = 0; c < len; c++)
658 if (colour == lastcolour)
663 Edit_SetSel(wnd,start,start+len);
664 memset(&cf, 0, sizeof(cf));
665 cf.cbSize = sizeof(cf);
666 cf.dwMask = CFM_COLOR;
667 cf.crTextColor = colour;
668 SendMessage(wnd, EM_SETCHARFORMAT, SCF_SELECTION, (LPARAM)&cf);
669 Edit_SetSel(wnd,start+len,start+len);
673 void GUIFormattingPrint(HWND wnd, char *msg)
675 int len=Edit_GetTextLength(wnd);
678 lastcolour = RGB(0,0,0);
679 SendMessage(wnd, WM_SETREDRAW, false, 0);
680 chrg.cpMin = chrg.cpMax = 0;
681 SendMessage(wnd, EM_EXSETSEL, 0, (LPARAM) &chrg);
687 else if (*msg == '/' && msg[1] == '/')
689 len = GUIEmitText(wnd, len, start, msg - start);
693 while(*msg && *msg != '\n' && *msg != '\r')
696 else if (*msg == '/' && msg[1] == '*')
698 len = GUIEmitText(wnd, len, start, msg - start);
703 if (msg[0] == '*' && msg[1] == '/')
711 else if (*msg == '#' || *msg == '_' || (*msg >= 'A' && *msg <= 'Z') || (*msg >= 'a' && *msg <= 'z'))
713 len = GUIEmitText(wnd, len, start, msg - start);
716 while (*msg == '_' || (*msg >= 'A' && *msg <= 'Z') || (*msg >= 'a' && *msg <= 'z' || *msg >= '0' && *msg <= '9'))
719 else if (*msg == '\"')
721 len = GUIEmitText(wnd, len, start, msg - start);
728 else if (*msg == '\"')
737 /* else if (*msg <= ' ')
739 while (*msg <= ' ' && *msg)
748 len = GUIEmitText(wnd, len, start, msg - start);
751 len = GUIEmitText(wnd, len, start, msg - start);
753 SendMessage(wnd, WM_SETREDRAW, true, 0);
756 int Rehighlight(editor_t *edit)
764 SendMessage(edit->editpane, EM_SETEVENTMASK, 0, 0);
766 SendMessage(edit->editpane, EM_GETSCROLLPOS, 0, (LPARAM)&scrollpos);
767 SendMessage(edit->editpane, EM_EXGETSEL, 0, (LPARAM) &chrg);
769 len = Edit_GetTextLength(edit->editpane);
770 file = malloc(len+1);
773 MessageBox(NULL, "Save failed - not enough mem", "Error", 0);
776 Edit_GetText(edit->editpane, file, len);
779 SetWindowText(edit->editpane,"");
781 // GUIPrint(edit->editpane, file);
782 GUIFormattingPrint(edit->editpane, file);
785 // Edit_SetSel(edit->editpane, Edit_LineIndex(neweditor->editpane, 0), Edit_LineIndex(neweditor->editpane, 0));
787 InvalidateRect(edit->editpane, NULL, true);
788 InvalidateRect(edit->window, NULL, true);
790 SendMessage(edit->editpane, EM_SETEVENTMASK, 0, ENM_SELCHANGE|ENM_CHANGE);
792 SendMessage(edit->editpane, EM_SETSCROLLPOS, 0, (LPARAM)&scrollpos);
793 SendMessage(edit->editpane, EM_EXSETSEL, 0, (LPARAM) &chrg);
795 UpdateWindow(edit->editpane);
796 RedrawWindow(edit->window, NULL, NULL, 0);
801 static void chunkcolour(HWND pane, int start, int end, DWORD colour)
804 if (colour == RGB(0,0,0))
805 return; //don't need to
806 Edit_SetSel(pane,start,end);
807 memset(&cf, 0, sizeof(cf));
808 cf.cbSize = sizeof(cf);
809 cf.dwMask = CFM_COLOR;
810 cf.crTextColor = colour;
811 SendMessage(pane, EM_SETCHARFORMAT, SCF_SELECTION, (LPARAM)&cf);
813 void GUIFormattingPrint(HWND wnd, char *msg)
816 int Rehighlight(editor_t *edit)
825 SendMessage(edit->editpane, WM_SETREDRAW, false, 0);
827 //Don't notify us for a bit..
828 SendMessage(edit->editpane, EM_SETEVENTMASK, 0, 0);
830 //get state so we can restore scroll positions and things.
831 SendMessage(edit->editpane, EM_GETSCROLLPOS, 0, (LPARAM)&scrollpos);
832 SendMessage(edit->editpane, EM_EXGETSEL, 0, (LPARAM) &chrg);
835 len = Edit_GetTextLength(edit->editpane);
836 file = malloc(len+1);
839 MessageBox(NULL, "Highlight failed - not enough mem", "Error", 0);
842 Edit_GetText(edit->editpane, file, len);
844 SetWindowText(edit->editpane,file); //this is so that we guarentee that the \rs or whatever that windows insists on inserting don't get in the way
847 for (last = 0, c = 0; c < len; c++)
849 if (file[c] == '/' && file[c+1] == '/') //do special syntax
851 chunkcolour(edit->editpane, last, c, color);
854 while(file[c] != '\n')
856 color = RGB(0, 127, 0);
860 chunkcolour(edit->editpane, last, c, color);
863 while(file[c] >= 'a' && file[c] <= 'z' || file[c] >= 'A' && file[c] <= 'Z' || file[c] == '_')
866 color = RGB(rand(), rand(), rand());
873 SendMessage(edit->editpane, WM_SETREDRAW, true, 0);
877 void EditorReload(editor_t *editor)
883 flen = QCC_FileSize(editor->filename);
886 file = malloc(flen+1);
887 QCC_ReadFile(editor->filename, file, flen);
891 SendMessage(editor->editpane, EM_SETEVENTMASK, 0, 0);
894 Edit_SetSel(editor->editpane,0,Edit_GetTextLength(editor->editpane));
895 Edit_ReplaceSel(editor->editpane,"");
897 if (!fl_autohighlight)
899 GUIPrint(editor->editpane, file);
903 GUIFormattingPrint(editor->editpane, file);
907 editor->modified = false;
908 stat(editor->filename, &sbuf);
909 editor->filemodifiedtime = sbuf.st_mtime;
911 SendMessage(editor->editpane, EM_SETEVENTMASK, 0, ENM_SELCHANGE|ENM_CHANGE);
914 void EditFile(char *name, int line)
919 HMENU menu, menufile, menuhelp, menunavig;
921 for (neweditor = editors; neweditor; neweditor = neweditor->next)
923 if (neweditor->window && !strcmp(neweditor->filename, name))
927 Edit_SetSel(neweditor->editpane, Edit_LineIndex(neweditor->editpane, line), Edit_LineIndex(neweditor->editpane, line+1));
928 Edit_ScrollCaret(neweditor->editpane);
931 SendMessage(mdibox, WM_MDIACTIVATE, (WPARAM)neweditor->window, 0);
932 SetFocus(neweditor->window);
933 SetFocus(neweditor->editpane);
938 if (QCC_FileSize(name) == -1)
940 MessageBox(NULL, "File not found.", "Error", 0);
944 neweditor = malloc(sizeof(editor_t));
947 MessageBox(NULL, "Low memory", "Error", 0);
951 neweditor->next = editors;
954 strncpy(neweditor->filename, name, sizeof(neweditor->filename)-1);
959 menufile = CreateMenu();
960 menuhelp = CreateMenu();
961 menunavig = CreateMenu();
962 AppendMenu(menu, MF_POPUP, (UINT_PTR)menufile, "&File");
963 AppendMenu(menu, MF_POPUP, (UINT_PTR)menunavig, "&Navigation");
964 AppendMenu(menu, MF_POPUP, (UINT_PTR)menuhelp, "&Help");
965 AppendMenu(menufile, 0, IDM_OPENNEW, "Open &new file ");
966 AppendMenu(menufile, 0, IDM_SAVE, "&Save ");
967 // AppendMenu(menufile, 0, IDM_FIND, "&Find");
968 AppendMenu(menufile, 0, IDM_UNDO, "&Undo Ctrl+Z");
969 AppendMenu(menufile, 0, IDM_REDO, "&Redo Ctrl+Y");
970 AppendMenu(menunavig, 0, IDM_GOTODEF, "Go to definition");
971 AppendMenu(menunavig, 0, IDM_OPENDOCU, "Open selected file");
972 AppendMenu(menuhelp, 0, IDM_ABOUT, "About");
973 AppendMenu(menu, 0, IDM_HIGHTLIGHT, "H&ighlight");
979 wndclass.lpfnWndProc = (WNDPROC)EditorWndProc;
980 wndclass.cbClsExtra = 0;
981 wndclass.cbWndExtra = 0;
982 wndclass.hInstance = ghInstance;
984 wndclass.hCursor = LoadCursor (NULL,IDC_ARROW);
985 wndclass.hbrBackground = (void *)COLOR_WINDOW;
986 wndclass.lpszMenuName = 0;
987 wndclass.lpszClassName = EDIT_WINDOW_CLASS_NAME;
988 RegisterClass(&wndclass);
990 neweditor->window = NULL;
995 sprintf(title, "%s", name);
997 mcs.szClass = EDIT_WINDOW_CLASS_NAME;
999 mcs.hOwner = ghInstance;
1000 mcs.x = mcs.cx = CW_USEDEFAULT;
1001 mcs.y = mcs.cy = CW_USEDEFAULT;
1002 mcs.style = WS_OVERLAPPEDWINDOW;
1005 neweditor->window = (HWND) SendMessage (mdibox, WM_MDICREATE, 0,
1006 (LONG_PTR) (LPMDICREATESTRUCT) &mcs);
1010 sprintf(title, "%s - FTEEditor", name);
1012 neweditor->window=CreateWindow(EDIT_WINDOW_CLASS_NAME, title, WS_OVERLAPPEDWINDOW,
1013 0, 0, 640, 480, NULL, NULL, ghInstance, NULL);
1017 SetMenu(neweditor->window, menu);
1019 if (!neweditor->window)
1021 MessageBox(NULL, "Failed to create editor window", "Error", 0);
1025 EditorReload(neweditor);
1028 Edit_SetSel(neweditor->editpane, Edit_LineIndex(neweditor->editpane, line), Edit_LineIndex(neweditor->editpane, line+1));
1030 Edit_SetSel(neweditor->editpane, Edit_LineIndex(neweditor->editpane, 0), Edit_LineIndex(neweditor->editpane, 0));
1032 Edit_ScrollCaret(neweditor->editpane);
1034 ShowWindow(neweditor->window, SW_SHOW);
1035 SetFocus(mainwindow);
1036 SetFocus(neweditor->window);
1037 SetFocus(neweditor->editpane);
1040 int EditorSave(editor_t *edit)
1045 len = Edit_GetTextLength(edit->editpane);
1046 file = malloc(len+1);
1049 MessageBox(NULL, "Save failed - not enough mem", "Error", 0);
1052 Edit_GetText(edit->editpane, file, len);
1053 if (!QCC_WriteFile(edit->filename, file, len))
1055 MessageBox(NULL, "Save failed\nCheck path and ReadOnly flags", "Failure", 0);
1060 /*now whatever is on disk should have the current time*/
1061 edit->modified = false;
1062 stat(edit->filename, &sbuf);
1063 edit->filemodifiedtime = sbuf.st_mtime;
1067 void EditorsRun(void)
1072 char *GUIReadFile(const char *fname, void *buffer, int blen)
1075 for (e = editors; e; e = e->next)
1077 if (e->window && !strcmp(e->filename, fname))
1079 int elen = Edit_GetTextLength(e->editpane);
1080 Edit_GetText(e->editpane, buffer, blen);
1085 return QCC_ReadFile(fname, buffer, blen);
1088 int GUIFileSize(const char *fname)
1091 for (e = editors; e; e = e->next)
1093 if (e->window && !strcmp(e->filename, fname))
1095 int len = Edit_GetTextLength(e->editpane);
1099 return QCC_FileSize(fname);
1102 /*checks if the file has been modified externally*/
1103 pbool EditorModified(editor_t *e)
1106 stat(e->filename, &sbuf);
1107 if (e->filemodifiedtime != sbuf.st_mtime)
1127 HWND nokeywords_coexistitem;
1128 HWND autoprototype_item;
1129 HWND autohighlight_item;
1130 HWND extraparmsitem;
1131 static LONG CALLBACK OptionsWndProc(HWND hWnd,UINT message,
1132 WPARAM wParam,LPARAM lParam)
1146 for (i = 0; optimisations[i].enabled; i++)
1148 if (optimisations[i].flags & FLAG_HIDDENINGUI)
1151 if (Button_GetCheck(optimisations[i].guiinfo))
1152 optimisations[i].flags |= FLAG_SETINGUI;
1154 optimisations[i].flags &= ~FLAG_SETINGUI;
1156 fl_hexen2 = Button_GetCheck(hexen2item);
1157 for (i = 0; compiler_flag[i].enabled; i++)
1159 if (compiler_flag[i].flags & FLAG_HIDDENINGUI)
1161 if (Button_GetCheck(compiler_flag[i].guiinfo))
1162 compiler_flag[i].flags |= FLAG_SETINGUI;
1164 compiler_flag[i].flags &= ~FLAG_SETINGUI;
1166 fl_autohighlight = Button_GetCheck(autohighlight_item);
1167 Edit_GetText(extraparmsitem, parameters, sizeof(parameters)-1);
1169 if (wParam == IDI_O_USE)
1170 buttons[ID_COMPILE].washit = true;
1172 case IDI_O_CHANGE_PROGS_SRC:
1175 char filename[MAX_PATH];
1176 char oldpath[MAX_PATH+10];
1178 memset(&ofn, 0, sizeof(ofn));
1179 ofn.lStructSize = sizeof(ofn);
1180 ofn.hInstance = ghInstance;
1181 ofn.lpstrFile = filename;
1182 ofn.lpstrTitle = "Please find progs.src";
1183 ofn.nMaxFile = sizeof(filename)-1;
1184 ofn.lpstrFilter = "QuakeC source\0*.src\0All files\0*.*\0";
1185 memset(filename, 0, sizeof(filename));
1186 GetCurrentDirectory(sizeof(oldpath)-1, oldpath);
1187 ofn.lpstrInitialDir = oldpath;
1188 if (GetOpenFileName(&ofn))
1190 strcpy(progssrcdir, filename);
1191 for(s = progssrcdir; s; s = s2)
1193 s2 = strchr(s+1, '\\');
1201 strcpy(progssrcname, s+1);
1204 strcpy(progssrcname, filename);
1206 SetCurrentDirectory(progssrcdir);
1207 *progssrcdir = '\0';
1209 resetprogssrc = true;
1216 for (i = 0; optimisations[i].enabled; i++)
1218 if (optimisations[i].flags & FLAG_HIDDENINGUI)
1221 if (optimisations[i].optimisationlevel<=(int)wParam-IDI_O_LEVEL0)
1222 Button_SetCheck(optimisations[i].guiinfo, 1);
1224 Button_SetCheck(optimisations[i].guiinfo, 0);
1228 for (i = 0; optimisations[i].enabled; i++)
1230 if (optimisations[i].flags & FLAG_HIDDENINGUI)
1233 if (optimisations[i].flags&FLAG_KILLSDEBUGGERS)
1234 Button_SetCheck(optimisations[i].guiinfo, 0);
1238 for (i = 0; optimisations[i].enabled; i++)
1240 if (optimisations[i].flags & FLAG_HIDDENINGUI)
1243 if (optimisations[i].flags & FLAG_ASDEFAULT)
1244 Button_SetCheck(optimisations[i].guiinfo, 1);
1246 Button_SetCheck(optimisations[i].guiinfo, 0);
1254 hi = (HELPINFO *)lParam;
1258 MessageBox(hWnd, "Sets the default optimisations", "Help", MB_OK|MB_ICONINFORMATION);
1261 MessageBox(hWnd, "Clears all optimisations which can make your progs harder to debug", "Help", MB_OK|MB_ICONINFORMATION);
1267 MessageBox(hWnd, "Sets a specific optimisation level", "Help", MB_OK|MB_ICONINFORMATION);
1269 case IDI_O_CHANGE_PROGS_SRC:
1270 MessageBox(hWnd, "Use this button to change your root source file.\nNote that fteqcc compiles sourcefiles from editors first, rather than saving. This means that changes are saved ONLY when you save them, but means that switching project mid-compile can result in problems.", "Help", MB_OK|MB_ICONINFORMATION);
1272 case IDI_O_ADDITIONALPARAMETERS:
1273 MessageBox(hWnd, "Type in additional commandline parameters here. Use -Dname to define a named precompiler constant before compiling.", "Help", MB_OK|MB_ICONINFORMATION);
1276 MessageBox(hWnd, "Apply changes shown, but do not recompile yet.", "Help", MB_OK|MB_ICONINFORMATION);
1279 MessageBox(hWnd, "Apply changes shown here and recompile.", "Help", MB_OK|MB_ICONINFORMATION);
1281 case IDI_O_OPTIMISATION:
1282 for (i = 0; optimisations[i].enabled; i++)
1284 if (optimisations[i].guiinfo == hi->hItemHandle)
1286 MessageBox(hWnd, optimisations[i].description, "Help", MB_OK|MB_ICONINFORMATION);
1291 case IDI_O_COMPILER_FLAG:
1292 for (i = 0; compiler_flag[i].enabled; i++)
1294 if (compiler_flag[i].guiinfo == hi->hItemHandle)
1296 MessageBox(hWnd, compiler_flag[i].description, "Help", MB_OK|MB_ICONINFORMATION);
1302 MessageBox(hWnd, "Click here to compile a hexen2 compatible progs. Note that this uses the -Thexen2. There are other targets available.", "Help", MB_OK|MB_ICONINFORMATION);
1304 case IDI_O_SYNTAX_HIGHLIGHTING:
1305 MessageBox(hWnd, "Should syntax be highlighted automatically when a file is opened?", "Help", MB_OK|MB_ICONINFORMATION);
1311 return DefWindowProc(hWnd,message,wParam,lParam);
1315 void OptionsDialog(void)
1333 BringWindowToTop(optionsmenu);
1338 memset(&wndclass, 0, sizeof(wndclass));
1340 wndclass.lpfnWndProc = (WNDPROC)OptionsWndProc;
1341 wndclass.cbClsExtra = 0;
1342 wndclass.cbWndExtra = 0;
1343 wndclass.hInstance = ghInstance;
1345 wndclass.hCursor = LoadCursor (NULL,IDC_ARROW);
1346 wndclass.hbrBackground = (void *)COLOR_WINDOW;
1347 wndclass.lpszMenuName = 0;
1348 wndclass.lpszClassName = OPTIONS_WINDOW_CLASS_NAME;
1349 RegisterClass(&wndclass);
1352 for (i = 0; optimisations[i].enabled; i++)
1354 if (optimisations[i].flags & FLAG_HIDDENINGUI)
1361 for (i = 0; compiler_flag[i].enabled; i++)
1363 if (compiler_flag[i].flags & FLAG_HIDDENINGUI)
1369 height = (height-1)/2;
1371 while (cflagsshown > ((480-(88+40))/16)*(flagcolums))
1374 if (height < (cflagsshown+flagcolums-1)/flagcolums)
1375 height = (cflagsshown+flagcolums-1)/flagcolums;
1377 r.right = 408 + flagcolums*168;
1385 r.left = GetSystemMetrics(SM_CXSCREEN)/2-320;
1386 r.top = GetSystemMetrics(SM_CYSCREEN)/2-240;
1387 r.bottom = r.top + height;
1392 AdjustWindowRectEx (&r, WS_CAPTION|WS_SYSMENU, FALSE, 0);
1394 optionsmenu=CreateWindowEx(WS_EX_CONTEXTHELP, OPTIONS_WINDOW_CLASS_NAME, "Options - FTE QuakeC compiler", WS_CAPTION|WS_SYSMENU,
1395 r.left, r.top, r.right-r.left, r.bottom-r.top, NULL, NULL, ghInstance, NULL);
1397 subsection = CreateWindow("BUTTON", "Optimisations", WS_CHILD|WS_VISIBLE|BS_GROUPBOX,
1398 0, 0, 400, height-48, optionsmenu, NULL, ghInstance, NULL);
1401 for (i = 0; optimisations[i].enabled; i++)
1403 if (optimisations[i].flags & FLAG_HIDDENINGUI)
1405 optimisations[i].guiinfo = NULL;
1409 optimisations[i].guiinfo = wnd = CreateWindow("BUTTON",optimisations[i].fullname,
1410 WS_CHILD | WS_VISIBLE | BS_AUTOCHECKBOX,
1411 8+200*(num&1),16+16*(num/2),200-16,16,
1413 (HMENU)IDI_O_OPTIMISATION,
1417 if (optimisations[i].flags&FLAG_SETINGUI)
1418 Button_SetCheck(wnd, 1);
1420 Button_SetCheck(wnd, 0);
1425 CreateWindow("BUTTON","O0",
1426 WS_CHILD | WS_VISIBLE,
1429 (HMENU)IDI_O_LEVEL0,
1432 CreateWindow("BUTTON","O1",
1433 WS_CHILD | WS_VISIBLE,
1434 8+64,height-88,64,32,
1436 (HMENU)IDI_O_LEVEL1,
1439 CreateWindow("BUTTON","O2",
1440 WS_CHILD | WS_VISIBLE,
1441 8+64*2,height-88,64,32,
1443 (HMENU)IDI_O_LEVEL2,
1446 CreateWindow("BUTTON","O3",
1447 WS_CHILD | WS_VISIBLE,
1448 8+64*3,height-88,64,32,
1450 (HMENU)IDI_O_LEVEL3,
1453 CreateWindow("BUTTON","Debug",
1454 WS_CHILD | WS_VISIBLE,
1455 8+64*4,height-88,64,32,
1460 CreateWindow("BUTTON","Default",
1461 WS_CHILD | WS_VISIBLE,
1462 8+64*5,height-88,64,32,
1464 (HMENU)IDI_O_DEFAULT,
1467 CreateWindow("BUTTON","Apply",
1468 WS_CHILD | WS_VISIBLE,
1474 CreateWindow("BUTTON","Use",
1475 WS_CHILD | WS_VISIBLE,
1476 8+64,height-40,64,32,
1481 CreateWindow("BUTTON","progs.src",
1482 WS_CHILD | WS_VISIBLE,
1483 8+64*2,height-40,64,32,
1485 (HMENU)IDI_O_CHANGE_PROGS_SRC,
1492 hexen2item = wnd = CreateWindow("BUTTON","HexenC",
1493 WS_CHILD | WS_VISIBLE | BS_AUTOCHECKBOX,
1496 (HMENU)IDI_O_TARGET,
1501 Button_SetCheck(wnd, 1);
1503 Button_SetCheck(wnd, 0);
1505 autohighlight_item = wnd = CreateWindow("BUTTON","Syntax Highlighting",
1506 WS_CHILD | WS_VISIBLE | BS_AUTOCHECKBOX,
1509 (HMENU)IDI_O_SYNTAX_HIGHLIGHTING,
1513 if (fl_autohighlight)
1514 Button_SetCheck(wnd, 1);
1516 Button_SetCheck(wnd, 0);
1520 for (i = 0; compiler_flag[i].enabled; i++)
1522 if (compiler_flag[i].flags & FLAG_HIDDENINGUI)
1524 compiler_flag[i].guiinfo = NULL;
1528 if (y > height-(88+40))
1534 compiler_flag[i].guiinfo = wnd = CreateWindow("BUTTON",compiler_flag[i].fullname,
1535 WS_CHILD | WS_VISIBLE | BS_AUTOCHECKBOX,
1538 (HMENU)IDI_O_COMPILER_FLAG,
1546 if (compiler_flag[i].flags & FLAG_SETINGUI)
1547 Button_SetCheck(wnd, 1);
1549 Button_SetCheck(wnd, 0);
1552 CreateWindow("STATIC","Extra Parameters:",
1553 WS_CHILD | WS_VISIBLE,
1560 extraparmsitem = CreateWindowEx(WS_EX_CLIENTEDGE, "EDIT",parameters,
1561 WS_CHILD | WS_VISIBLE|ES_LEFT | ES_WANTRETURN |
1562 ES_MULTILINE | ES_AUTOVSCROLL,
1563 408,my,r.right-r.left - 408 - 8,height-my-4,
1565 (HMENU)IDI_O_ADDITIONALPARAMETERS,
1569 ShowWindow(optionsmenu, SW_SHOWDEFAULT);
1586 static LONG CALLBACK MainWndProc(HWND hWnd,UINT message,
1587 WPARAM wParam,LPARAM lParam)
1598 CLIENTCREATESTRUCT ccs;
1600 HMENU rootmenu, windowmenu, m;
1601 rootmenu = CreateMenu();
1603 AppendMenu(rootmenu, MF_POPUP, (UINT_PTR)(m = CreateMenu()), "&File");
1604 AppendMenu(m, 0, IDM_OPENNEW, "Open &new file ");
1605 AppendMenu(m, 0, IDM_SAVE, "&Save ");
1606 // AppendMenu(m, 0, IDM_FIND, "&Find");
1607 AppendMenu(m, 0, IDM_UNDO, "&Undo Ctrl+Z");
1608 AppendMenu(m, 0, IDM_REDO, "&Redo Ctrl+Y");
1609 AppendMenu(rootmenu, MF_POPUP, (UINT_PTR)(m = CreateMenu()), "&Navigation");
1610 AppendMenu(m, 0, IDM_GOTODEF, "Go to definition");
1611 AppendMenu(m, 0, IDM_OPENDOCU, "Open selected file");
1612 AppendMenu(rootmenu, MF_POPUP, (UINT_PTR)(m = windowmenu = CreateMenu()), "&Window");
1613 AppendMenu(m, 0, IDM_CASCADE, "&Cascade");
1614 AppendMenu(m, 0, IDM_TILE_HORIZ, "Tile &Horizontally");
1615 AppendMenu(m, 0, IDM_TILE_VERT, "Tile &Vertically");
1616 AppendMenu(rootmenu, MF_POPUP, (UINT_PTR)(m = CreateMenu()), "&Help");
1617 AppendMenu(m, 0, IDM_ABOUT, "About");
1619 SetMenu(hWnd, rootmenu);
1621 // Retrieve the handle to the window menu and assign the
1622 // first child window identifier.
1624 memset(&ccs, 0, sizeof(ccs));
1625 ccs.hWindowMenu = windowmenu;
1626 ccs.idFirstChild = IDM_FIRSTCHILD;
1628 // Create the MDI client window.
1630 mdibox = CreateWindow( "MDICLIENT", (LPCTSTR) NULL,
1631 WS_CHILD | WS_CLIPCHILDREN | WS_VSCROLL | WS_HSCROLL,
1632 0, 0, 320, 200, hWnd, (HMENU) 0xCAC, ghInstance, (LPSTR) &ccs);
1633 ShowWindow(mdibox, SW_SHOW);
1635 projecttree = CreateWindow(WC_TREEVIEW, (LPCTSTR) NULL,
1636 WS_CHILD | WS_CLIPCHILDREN | WS_VSCROLL | WS_HSCROLL
1637 | TVS_HASBUTTONS |TVS_LINESATROOT|TVS_HASLINES,
1638 0, 0, 320, 200, hWnd, (HMENU) 0xCAC, ghInstance, (LPSTR) &ccs);
1639 ShowWindow(projecttree, SW_SHOW);
1643 gotodefbox = CreateWindowEx(WS_EX_CLIENTEDGE, "EDIT", (LPCTSTR) NULL,
1644 WS_CHILD | WS_CLIPCHILDREN,
1645 0, 0, 320, 200, hWnd, (HMENU) 0xCAC, ghInstance, (LPSTR) NULL);
1646 ShowWindow(gotodefbox, SW_SHOW);
1648 gotodefaccept = CreateWindowEx(WS_EX_CLIENTEDGE, "BUTTON", "GO",
1649 WS_CHILD | WS_CLIPCHILDREN | BS_DEFPUSHBUTTON,
1650 0, 0, 320, 200, hWnd, (HMENU) 0x4404, ghInstance, (LPSTR) NULL);
1651 ShowWindow(gotodefaccept, SW_SHOW);
1661 GetClientRect(mainwindow, &rect);
1664 SetWindowPos(projecttree, NULL, 0, 0, 192, rect.bottom-rect.top - 34 - 24, 0);
1666 SetWindowPos(gotodefbox, NULL, 0, rect.bottom-rect.top - 33 - 24, 160, 24, 0);
1667 SetWindowPos(gotodefaccept, NULL, 160, rect.bottom-rect.top - 33 - 24, 32, 24, 0);
1668 SetWindowPos(mdibox?mdibox:outputbox, NULL, 192, 0, rect.right-rect.left-192, rect.bottom-rect.top - 32, 0);
1671 SetWindowPos(mdibox?mdibox:outputbox, NULL, 0, 0, rect.right-rect.left, rect.bottom-rect.top - 32, 0);
1672 width = (rect.right-rect.left);
1674 for (i = 0; i < NUMBUTTONS; i++)
1676 SetWindowPos(buttons[i].hwnd, NULL, width*i, rect.bottom-rect.top - 32, width, 32, 0);
1680 hdc=BeginPaint(hWnd,(LPPAINTSTRUCT)&ps);
1682 EndPaint(hWnd,(LPPAINTSTRUCT)&ps);
1686 if (wParam == 0x4404)
1688 GetWindowText(gotodefbox, finddef, sizeof(finddef)-1);
1691 if (LOWORD(wParam)>0 && LOWORD(wParam) <= NUMBUTTONS)
1694 buttons[LOWORD(wParam)-1].washit = 1;
1697 if (LOWORD(wParam) < IDM_FIRSTCHILD)
1702 ew = (HWND)SendMessage(mdibox, WM_MDIGETACTIVE, 0, 0);
1704 for (editor = editors; editor; editor = editor->next)
1706 if (editor->window == ew)
1710 EditorMenu(editor, wParam);
1712 GenericMenu(wParam);
1726 nm = (NMHDR*)lParam;
1727 if (nm->hwndFrom == projecttree)
1732 item = TreeView_GetSelection(projecttree);
1735 i.pszText = itemtext;
1736 i.cchTextMax = sizeof(itemtext)-1;
1737 if (!TreeView_GetItem(projecttree, &i))
1739 strcpy(filename, i.pszText);
1742 item = TreeView_GetParent(projecttree, item);
1744 if (!TreeView_GetItem(projecttree, &i))
1746 if (!TreeView_GetParent(projecttree, item))
1749 oldlen = strlen(filename);
1750 newlen = strlen(i.pszText);
1751 memmove(filename+newlen+1, filename, oldlen+1);
1752 filename[newlen] = '/';
1753 strncpy(filename, i.pszText, newlen);
1755 EditFile(filename, -1);
1762 return DefFrameProc(hWnd,mdibox,message,wParam,lParam);
1764 return DefWindowProc(hWnd,message,wParam,lParam);
1769 static LONG CALLBACK OutputWindowProc(HWND hWnd,UINT message,
1770 WPARAM wParam,LPARAM lParam)
1776 outputwindow = NULL;
1780 outputbox = CreateAnEditControl(hWnd);
1782 GetClientRect(hWnd, &rect);
1783 SetWindowPos(outputbox, NULL, 0, 0, rect.right-rect.left, rect.bottom-rect.top, 0);
1786 return DefMDIChildProc(hWnd,message,wParam,lParam);
1791 void GUIPrint(HWND wnd, char *msg)
1805 len=Edit_GetTextLength(wnd);
1806 /* if ((unsigned)len>(32767-strlen(msg)))
1807 Edit_SetSel(wnd,0,len);
1809 Edit_SetSel(wnd,len,len);
1810 Edit_ReplaceSel(wnd,msg);
1812 while (PeekMessage (&wmsg, NULL, 0, 0, PM_NOREMOVE))
1814 if (!GetMessage (&wmsg, NULL, 0, 0))
1816 TranslateMessage (&wmsg);
1817 DispatchMessage (&wmsg);
1821 int GUIEmitOutputText(HWND wnd, int start, char *text, int len, DWORD colour)
1831 Edit_SetSel(wnd,start,start);
1832 Edit_ReplaceSel(wnd,text);
1837 for (c = 0; c < len; c++)
1838 if (text[c] == '\r')
1843 Edit_SetSel(wnd,start,start+len);
1844 memset(&cf, 0, sizeof(cf));
1845 cf.cbSize = sizeof(cf);
1846 cf.dwMask = CFM_COLOR;
1847 cf.crTextColor = colour;
1848 SendMessage(wnd, EM_SETCHARFORMAT, SCF_SELECTION, (LPARAM)&cf);
1849 Edit_SetSel(wnd,start+len,start+len);
1854 int GUIprintf(const char *msg, ...)
1865 va_start (argptr,msg);
1866 args = QC_vsnprintf (buf,sizeof(buf)-1, msg,argptr);
1871 fprintf(logfile, "%s", buf);
1875 SetWindowText(outputbox,"");
1880 if (strstr(buf, "warning: "))
1881 col = RGB(128, 128, 0);
1882 else if (strstr(buf, "error: "))
1883 col = RGB(255, 0, 0);
1894 outlen = GUIEmitOutputText(outputbox, outlen, st, strlen(st), col);
1895 outlen = GUIEmitOutputText(outputbox, outlen, rn, 1, col);
1902 outlen = GUIEmitOutputText(outputbox, outlen, st, strlen(st), col);
1904 while (PeekMessage (&wmsg, NULL, 0, 0, PM_NOREMOVE))
1906 if (!GetMessage (&wmsg, NULL, 0, 0))
1908 TranslateMessage (&wmsg);
1909 DispatchMessage (&wmsg);
1919 GUIPrint(outputbox, st);
1920 GUIPrint(outputbox, "\r\n");
1927 GUIPrint(outputbox, st);
1934 void Sys_Error(const char *text, ...);
1935 void RunCompiler(char *args)
1943 for (editor = editors; editor; editor = editor->next)
1945 if (editor->modified)
1947 if (EditorModified(editor))
1950 sprintf(msg, "%s is modified in both memory and on disk. Overwrite external modification? (saying no will reload from disk)", editor->filename);
1951 switch(MessageBox(NULL, msg, "Modification conflict", MB_YESNOCANCEL))
1957 EditorReload(editor);
1960 break; /*compiling will use whatever is in memory*/
1965 /*not modified on disk, but modified in memory? try and save it, cos we might as well*/
1971 /*modified on disk but not in memory? just reload it off disk*/
1972 if (EditorModified(editor))
1973 EditorReload(editor);
1977 memset(&funcs, 0, sizeof(funcs));
1979 memset(&ext, 0, sizeof(ext));
1980 funcs.parms->ReadFile = GUIReadFile;
1981 funcs.parms->FileSize = GUIFileSize;
1982 funcs.parms->WriteFile = QCC_WriteFile;
1983 funcs.parms->printf = GUIprintf;
1984 funcs.parms->Sys_Error = Sys_Error;
1990 logfile = fopen("fteqcc.log", "wb");
1994 argc = GUI_BuildParms(args, argv);
1996 CompileParams(&funcs, true, argc, argv);
2003 void CreateOutputWindow(void)
2006 MDICREATESTRUCT mcs;
2008 if (!mdibox) //should already be created
2014 wndclass.lpfnWndProc = (WNDPROC)OutputWindowProc;
2015 wndclass.cbClsExtra = 0;
2016 wndclass.cbWndExtra = 0;
2017 wndclass.hInstance = ghInstance;
2019 wndclass.hCursor = LoadCursor (NULL,IDC_ARROW);
2020 wndclass.hbrBackground = (void *)COLOR_WINDOW;
2021 wndclass.lpszMenuName = 0;
2022 wndclass.lpszClassName = MAIN_WINDOW_CLASS_NAME;
2023 RegisterClass(&wndclass);
2027 mcs.szClass = MAIN_WINDOW_CLASS_NAME;
2028 mcs.szTitle = "Compiler output";
2029 mcs.hOwner = ghInstance;
2030 mcs.x = mcs.cx = CW_USEDEFAULT;
2031 mcs.y = mcs.cy = CW_USEDEFAULT;
2032 mcs.style = WS_OVERLAPPEDWINDOW;
2035 outputwindow = (HWND) SendMessage (mdibox, WM_MDICREATE, 0,
2036 (LONG_PTR) (LPMDICREATESTRUCT) &mcs);
2038 ShowWindow(outputwindow, SW_SHOW);
2041 //bring it to the front.
2042 SendMessage(mdibox, WM_MDIACTIVATE, (WPARAM)outputwindow, 0);
2045 //progssrcname should already have been set.
2046 void SetProgsSrc(void)
2050 HANDLE rootitem, pi;
2051 TVINSERTSTRUCT item;
2053 char parentstring[256];
2054 memset(&item, 0, sizeof(item));
2055 memset(&parent, 0, sizeof(parent));
2063 f = fopen (progssrcname, "rb");
2066 fseek(f, 0, SEEK_END);
2068 fseek(f, 0, SEEK_SET);
2069 buffer = malloc(size+1);
2075 buffer[size] = '\0';
2076 fread(buffer, 1, size, f);
2079 pr_file_p = QCC_COM_Parse(buffer);
2080 if (*qcc_token == '#')
2082 free(buffer); //aaaahhh! newstyle!
2086 pr_file_p = QCC_COM_Parse(pr_file_p); //we dont care about the produced progs.dat
2089 item.hParent = TVI_ROOT;
2090 item.hInsertAfter = TVI_SORT;
2091 item.item.pszText = progssrcname;
2092 item.item.mask = TVIF_TEXT;
2093 rootitem = (HANDLE)SendMessage(projecttree,TVM_INSERTITEM,0,(LPARAM)&item);
2096 pi = item.hParent = rootitem;
2097 item.item.pszText = qcc_token;
2098 while(slash = strchr(item.item.pszText, '/'))
2101 item.hParent = TreeView_GetChild(projecttree, item.hParent);
2104 parent.hItem = item.hParent;
2105 parent.mask = TVIF_TEXT;
2106 parent.pszText = parentstring;
2107 parent.cchTextMax = sizeof(parentstring)-1;
2108 if (TreeView_GetItem(projecttree, &parent))
2110 if (!stricmp(parent.pszText, item.item.pszText))
2113 } while(item.hParent=TreeView_GetNextSibling(projecttree, item.hParent));
2115 { //add a directory.
2117 pi = (HANDLE)SendMessage(projecttree,TVM_INSERTITEM,0,(LPARAM)&item);
2120 else pi = item.hParent;
2122 item.item.pszText = slash+1;
2124 SendMessage(projecttree,TVM_INSERTITEM,0,(LPARAM)&item);
2125 pr_file_p = QCC_COM_Parse(pr_file_p);
2132 int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
2136 ghInstance= hInstance;
2138 GUI_SetDefaultOpts();
2140 if(strstr(lpCmdLine, "-stdout"))
2142 GUI_ParseCommandLine(lpCmdLine);
2143 RunCompiler(lpCmdLine);
2153 f = fopen("fteqcc.cfg", "rb");
2156 fseek(f, 0, SEEK_END);
2158 fseek(f, 0, SEEK_SET);
2159 lpCmdLine = malloc(len+1);
2160 fread(lpCmdLine, 1, len, f);
2161 lpCmdLine[len] = '\0';
2164 while(s = strchr(lpCmdLine, '\r'))
2166 while(s = strchr(lpCmdLine, '\n'))
2171 GUI_ParseCommandLine(lpCmdLine);
2173 GUI_RevealOptions();
2175 if (/*!fl_acc &&*/ !*progssrcname)
2177 strcpy(progssrcname, "preprogs.src");
2178 if (QCC_FileSize(progssrcname)==-1)
2179 strcpy(progssrcname, "progs.src");
2180 if (QCC_FileSize(progssrcname)==-1)
2183 char filename[MAX_PATH];
2184 char oldpath[MAX_PATH+10];
2186 memset(&ofn, 0, sizeof(ofn));
2187 ofn.lStructSize = sizeof(ofn);
2188 ofn.hInstance = ghInstance;
2189 ofn.lpstrFile = filename;
2190 ofn.lpstrTitle = "Please find progs.src";
2191 ofn.nMaxFile = sizeof(filename)-1;
2192 ofn.lpstrFilter = "QuakeC source\0*.src\0All files\0*.*\0";
2193 memset(filename, 0, sizeof(filename));
2194 GetCurrentDirectory(sizeof(oldpath)-1, oldpath);
2195 ofn.lpstrInitialDir = oldpath;
2196 if (GetOpenFileName(&ofn))
2198 strcpy(progssrcdir, filename);
2199 for(s = progssrcdir; s; s = s2)
2201 s2 = strchr(s+1, '\\');
2209 strcpy(progssrcname, s+1);
2212 strcpy(progssrcname, filename);
2216 MessageBox(NULL, "You didn't select a file", "Error", 0);
2219 SetCurrentDirectory(progssrcdir);
2220 *progssrcdir = '\0';
2224 resetprogssrc = true;
2227 wndclass.lpfnWndProc = (WNDPROC)MainWndProc;
2228 wndclass.cbClsExtra = 0;
2229 wndclass.cbWndExtra = 0;
2230 wndclass.hInstance = ghInstance;
2232 wndclass.hCursor = LoadCursor (NULL,IDC_ARROW);
2233 wndclass.hbrBackground = (void *)COLOR_WINDOW;
2234 wndclass.lpszMenuName = 0;
2235 wndclass.lpszClassName = MDI_WINDOW_CLASS_NAME;
2236 RegisterClass(&wndclass);
2238 mainwindow=CreateWindow(MDI_WINDOW_CLASS_NAME, "FTE QuakeC compiler", WS_OVERLAPPEDWINDOW,
2239 0, 0, 640, 480, NULL, NULL, ghInstance, NULL);
2243 SetWindowText(mainwindow, "FTE QuakeC Development Suite");
2248 MessageBox(NULL, "Failed to create main window", "Error", 0);
2252 InitCommonControls();
2254 outputbox=CreateWindowEx(WS_EX_CLIENTEDGE,
2257 WS_CHILD | ES_READONLY | WS_VISIBLE |
2258 WS_VSCROLL | ES_LEFT | ES_WANTRETURN |
2259 ES_MULTILINE | ES_AUTOVSCROLL,
2268 outputbox = CreateAnEditControl(mainwindow);
2270 for (i = 0; i < NUMBUTTONS; i++)
2272 buttons[i].hwnd = CreateWindowEx(WS_EX_CLIENTEDGE,
2275 WS_CHILD | WS_VISIBLE,
2283 ShowWindow(mainwindow, SW_SHOWDEFAULT);
2285 if (fl_compileonstart)
2287 CreateOutputWindow();
2288 RunCompiler(lpCmdLine);
2294 buttons[ID_EDIT].washit = true;
2298 GUIprintf("Welcome to FTE QCC\n");
2299 GUIprintf("Source file: ");
2300 GUIprintf(progssrcname);
2307 while(mainwindow || editors)
2312 { //this here, with the compiler below, means that we don't run recursivly.
2313 resetprogssrc = false;
2319 while (PeekMessage (&msg, NULL, 0, 0, PM_NOREMOVE))
2321 if (!GetMessage (&msg, NULL, 0, 0))
2323 if (!mdibox || !TranslateMDISysAccel(mdibox, &msg))
2325 TranslateMessage (&msg);
2326 DispatchMessage (&msg);
2332 i = Edit_GetSel(outputbox);
2333 if ((i>>16) != (i&0xffff) && i != -1) //some text is selected.
2337 char *colon1, *colon2 = NULL;
2342 l1 = Edit_LineFromChar(outputbox, i&0xffff);
2343 l2 = Edit_LineFromChar(outputbox, (i>>16)&0xffff);
2346 bytes = Edit_GetLine(outputbox, Edit_LineFromChar(outputbox, i&0xffff), line, sizeof(line)-1);
2349 for (colon1 = line+strlen(line)-1; *colon1 <= ' ' && colon1>=line; colon1--)
2351 if (!strncmp(line, "warning: ", 9))
2352 memmove(line, line+9, sizeof(line));
2356 colon1 = strchr(colon1+1, ':');
2357 } while (colon1 && colon1[1] == '\\');
2361 colon2 = strchr(colon1+1, ':');
2362 while (colon2 && colon2[1] == '\\')
2364 colon2 = strchr(colon2+1, ':');
2370 EditFile(line, atoi(colon1+1)-1);
2372 else if (!strncmp(line, "Source file: ", 13))
2373 EditFile(line+13, -1);
2374 else if (!strncmp(line, "Including: ", 11))
2375 EditFile(line+11, -1);
2377 else if (!strncmp(line, "compiling ", 10))
2378 EditFile(line+10, -1);
2379 else if (!strncmp(line, "prototyping ", 12))
2380 EditFile(line+12, -1);
2381 Edit_SetSel(outputbox, i&0xffff, i&0xffff); //deselect it.
2385 if (buttons[ID_COMPILE].washit)
2387 CreateOutputWindow();
2388 RunCompiler(parameters);
2390 buttons[ID_COMPILE].washit = false;
2392 if (buttons[ID_EDIT].washit)
2394 buttons[ID_EDIT].washit = false;
2395 EditFile(progssrcname, -1);
2397 if (buttons[ID_OPTIONS].washit)
2399 buttons[ID_OPTIONS].washit = false;
2402 if (buttons[ID_QUIT].washit)
2404 buttons[ID_QUIT].washit = false;
2405 DestroyWindow(mainwindow);
2411 GoToDefinition(finddef);