]> de.git.xonotic.org Git - voretournament/voretournament.git/blob - misc/mediasource/extra/fteqcc-src/qccgui.c
fteqcc source
[voretournament/voretournament.git] / misc / mediasource / extra / fteqcc-src / qccgui.c
1 #include <windows.h>
2 #include <windowsx.h>
3 #include <commctrl.h>
4 #include <commdlg.h>
5 #include <richedit.h>
6 #include <stdio.h>
7
8 #include "qcc.h"
9 #include "gui.h"
10
11
12
13
14 /*
15 ==============
16 LoadFile
17 ==============
18 */
19 unsigned char *QCC_ReadFile (char *fname, void *buffer, int len)
20 {
21         long    length;
22         FILE *f;
23         f = fopen(fname, "rb");
24         if (!f)
25                 return NULL;
26         length = fread(buffer, 1, len, f);
27         fclose(f);
28
29         if (length != len)
30                 return NULL;
31
32         return buffer;
33 }
34 int QCC_FileSize (char *fname)
35 {
36         long    length;
37         FILE *f;
38         f = fopen(fname, "rb");
39         if (!f)
40                 return -1;
41         fseek(f, 0, SEEK_END);
42         length = ftell(f);
43         fclose(f);
44
45         return length;
46 }
47
48 pbool QCC_WriteFile (char *name, void *data, int len)
49 {
50         long    length;
51         FILE *f;
52         f = fopen(name, "wb");
53         if (!f)
54                 return false;
55         length = fwrite(data, 1, len, f);
56         fclose(f);
57
58         if (length != len)
59                 return false;
60
61         return true;
62 }
63
64 #undef printf
65 #undef Sys_Error
66
67 void Sys_Error(const char *text, ...)
68 {
69         va_list argptr;
70         static char msg[2048];  
71
72         va_start (argptr,text);
73         QC_vsnprintf (msg,sizeof(msg)-1, text,argptr);
74         va_end (argptr);
75
76         QCC_Error(ERR_INTERNAL, "%s", msg);
77 }
78
79
80 FILE *logfile;
81 int logprintf(const char *format, ...)
82 {
83         va_list         argptr;
84         static char             string[1024];
85
86         va_start (argptr, format);
87 #ifdef _WIN32
88         _vsnprintf (string,sizeof(string)-1, format,argptr);
89 #else
90         vsnprintf (string,sizeof(string), format,argptr);
91 #endif
92         va_end (argptr);
93
94         printf("%s", string);
95         if (logfile)
96                 fputs(string, logfile);
97
98         return 0;
99 }
100
101
102
103
104
105
106
107
108
109
110
111 #define Edit_Redo(hwndCtl)                      ((BOOL)(DWORD)SNDMSG((hwndCtl), EM_REDO, 0L, 0L))
112
113
114 #define MAIN_WINDOW_CLASS_NAME "FTEMAINWINDOW"
115 #define MDI_WINDOW_CLASS_NAME "FTEMDIWINDOW"
116 #define EDIT_WINDOW_CLASS_NAME "FTEEDITWINDOW"
117 #define OPTIONS_WINDOW_CLASS_NAME "FTEOPTIONSWINDOW"
118
119 #define EM_GETSCROLLPOS  (WM_USER + 221)
120 #define EM_SETSCROLLPOS  (WM_USER + 222)
121
122
123
124 int GUIprintf(const char *msg, ...);
125 void GUIPrint(HWND wnd, char *msg);
126
127 char finddef[256];
128
129 void RunCompiler(char *args);
130
131 HINSTANCE ghInstance;
132 HMODULE richedit;
133
134 pbool resetprogssrc;    //progs.src was changed, reload project info.
135
136
137 HWND mainwindow;
138 HWND mdibox;
139 HWND outputwindow;
140 HWND outputbox;
141 HWND projecttree;
142 HWND gotodefbox;
143 HWND gotodefaccept;
144
145 FILE *logfile;
146
147 struct{
148         char *text;
149         HWND hwnd;
150         int washit;
151 } buttons[] = {
152         {"Compile"},
153         {"Edit"},
154         {"Options"},
155         {"Quit"}
156 };
157
158 #define ID_COMPILE      0
159 #define ID_EDIT 1
160 #define ID_OPTIONS 2
161 #define ID_QUIT 3
162
163 #define NUMBUTTONS sizeof(buttons)/sizeof(buttons[0])
164
165
166
167 void GUI_DialogPrint(char *title, char *text)
168 {
169         MessageBox(mainwindow, text, title, 0);
170 }
171
172 HWND CreateAnEditControl(HWND parent)
173 {
174         HWND newc;
175
176         if (!richedit)
177                 richedit = LoadLibrary("RICHED32.DLL");
178
179         newc=CreateWindowEx(WS_EX_CLIENTEDGE,
180                 richedit?RICHEDIT_CLASS:"EDIT",
181                 "",
182                 WS_CHILD /*| ES_READONLY*/ | WS_VISIBLE | 
183                 WS_HSCROLL | WS_VSCROLL | ES_LEFT | ES_WANTRETURN |
184                 ES_MULTILINE | ES_AUTOVSCROLL,
185                 0, 0, 0, 0,
186                 parent,
187                 NULL,
188                 ghInstance,
189                 NULL);
190
191         if (!newc)
192                 newc=CreateWindowEx(WS_EX_CLIENTEDGE,
193                         richedit?RICHEDIT_CLASS10A:"EDIT",      //fall back to the earlier version
194                         "",
195                         WS_CHILD /*| ES_READONLY*/ | WS_VISIBLE | 
196                         WS_HSCROLL | WS_VSCROLL | ES_LEFT | ES_WANTRETURN |
197                         ES_MULTILINE | ES_AUTOVSCROLL,
198                         0, 0, 0, 0,
199                         parent,
200                         NULL,
201                         ghInstance,
202                         NULL);
203
204         if (!newc)
205         {       //you've not got RICHEDIT installed properly, I guess
206                 FreeLibrary(richedit);
207                 richedit = NULL;
208                 newc=CreateWindowEx(WS_EX_CLIENTEDGE,
209                         "EDIT",
210                         "",
211                         WS_CHILD /*| ES_READONLY*/ | WS_VISIBLE | 
212                         WS_HSCROLL | WS_VSCROLL | ES_LEFT | ES_WANTRETURN |
213                         ES_MULTILINE | ES_AUTOVSCROLL,
214                         0, 0, 0, 0,
215                         parent,
216                         NULL,
217                         ghInstance,
218                         NULL);
219         }
220
221         //go to lucidia console, 10pt
222         {
223                 CHARFORMAT cf;
224                 memset(&cf, 0, sizeof(cf));
225                 cf.cbSize = sizeof(cf);
226                 cf.dwMask = CFM_BOLD | CFM_FACE;// | CFM_SIZE;
227                 strcpy(cf.szFaceName, "Lucida Console");
228                 cf.yHeight = 5;
229
230                 SendMessage(newc, EM_SETCHARFORMAT, SCF_ALL, (WPARAM)&cf);
231         }
232
233         if (richedit)
234         {
235                 SendMessage(newc, EM_EXLIMITTEXT, 0, 1<<20);
236         }
237
238         ShowWindow(newc, SW_SHOW);
239
240         return newc;
241 }
242
243
244
245
246 enum {
247         IDM_OPENDOCU=32,
248         IDM_OPENNEW,
249         IDM_GOTODEF,
250         IDM_SAVE,
251         IDM_FIND,
252         IDM_QUIT,
253         IDM_UNDO,
254         IDM_REDO,
255         IDM_ABOUT,
256         IDM_HIGHTLIGHT,
257         IDM_CASCADE,
258         IDM_TILE_HORIZ,
259         IDM_TILE_VERT,
260
261         IDI_O_LEVEL0,
262         IDI_O_LEVEL1,
263         IDI_O_LEVEL2,
264         IDI_O_LEVEL3,
265         IDI_O_DEFAULT,
266         IDI_O_DEBUG,
267         IDI_O_CHANGE_PROGS_SRC,
268         IDI_O_ADDITIONALPARAMETERS,
269         IDI_O_OPTIMISATION,
270         IDI_O_COMPILER_FLAG,
271         IDI_O_USE,
272         IDI_O_APPLY,
273         IDI_O_TARGET,
274         IDI_O_SYNTAX_HIGHLIGHTING,
275
276         IDM_FIRSTCHILD
277 };
278
279
280 typedef struct editor_s {
281         char filename[MAX_PATH];        //abs
282         HWND window;
283         HWND editpane;
284         struct editor_s *next;
285 } editor_t;
286
287 editor_t *editors;
288
289 int EditorSave(editor_t *edit);
290 void EditFile(char *name, int line);
291 pbool EditorModified(editor_t *e);
292 int Rehighlight(editor_t *edit);
293
294 void QueryOpenFile(void)
295 {
296         char filename[MAX_PATH];
297         char oldpath[MAX_PATH+10];
298         OPENFILENAME ofn;
299         memset(&ofn, 0, sizeof(ofn));
300         ofn.lStructSize = sizeof(ofn);
301         ofn.hInstance = ghInstance;
302         ofn.lpstrFile = filename;
303         ofn.nMaxFile = sizeof(filename)-1;
304         memset(filename, 0, sizeof(filename));
305         GetCurrentDirectory(sizeof(oldpath)-1, oldpath);
306         if (GetOpenFileName(&ofn))
307                 EditFile(filename, -1);
308         SetCurrentDirectory(oldpath);
309 }
310
311 //IDM_ stuff that needs no active menu
312 void GenericMenu(WPARAM wParam)
313 {
314         switch(LOWORD(wParam))
315         {
316         case IDM_OPENNEW:
317                 QueryOpenFile();
318                 break;
319
320         case IDM_ABOUT:
321                 MessageBox(NULL, "FTE QuakeC Compiler\nWritten by Forethough Entertainment.\nBasically that means it was written by Spike.\n\nIt has a few cool features, like a useful IDE.\n\nSupports:\nPrecompiler (with macros)\nArrays\n+= / -= / *= / /= operations.\nSwitch statements\nfor loops\nLots of optimisations.", "About", 0);
322                 break;
323
324         case IDM_CASCADE:
325                 SendMessage(mdibox, WM_MDICASCADE, 0, 0);
326                 break;
327         case IDM_TILE_HORIZ:
328                 SendMessage(mdibox, WM_MDITILE, MDITILE_HORIZONTAL, 0);
329                 break;
330         case IDM_TILE_VERT:
331                 SendMessage(mdibox, WM_MDITILE, MDITILE_VERTICAL, 0);
332                 break;
333         }
334 }
335
336 void EditorMenu(editor_t *editor, WPARAM wParam)
337 {
338         switch(LOWORD(wParam))
339         {
340         case IDM_OPENDOCU:
341                 {
342                         char buffer[1024];
343                         int total;
344                         total = SendMessage(editor->editpane, EM_GETSELTEXT, (WPARAM)sizeof(buffer)-1, (LPARAM)buffer);
345                         buffer[total]='\0';
346                         if (!total)
347                         {
348                                 MessageBox(NULL, "There is no name currently selected.", "Whoops", 0);
349                                 break;
350                         }
351                         else
352                                 EditFile(buffer, -1);
353                 }
354                 break;
355         case IDM_SAVE:
356                 EditorSave(editor);
357                 break;
358         case IDM_GOTODEF:
359                 {
360                         char buffer[1024];
361                         int total;
362                         total = SendMessage(editor->editpane, EM_GETSELTEXT, (WPARAM)sizeof(buffer)-1, (LPARAM)buffer);
363                         buffer[total]='\0';
364                         if (!total)
365                         {
366                                 MessageBox(NULL, "There is no name currently selected.", "Whoops", 0);
367                                 break;
368                         }
369                         else
370                                 GoToDefinition(buffer);
371                 }
372                 break;
373         case IDM_HIGHTLIGHT:
374                 Rehighlight(editor);
375                 break;
376
377         case IDM_UNDO:
378                 Edit_Undo(editor->editpane);
379                 break;
380         case IDM_REDO:
381                 Edit_Redo(editor->editpane);
382                 break;
383
384         default:
385                 GenericMenu(wParam);
386                 break;
387         }
388 }
389
390 static LONG CALLBACK EditorWndProc(HWND hWnd,UINT message,
391                                      WPARAM wParam,LPARAM lParam)
392 {
393         RECT rect;
394         HDC hdc;
395         PAINTSTRUCT ps;
396
397         editor_t *editor;
398         for (editor = editors; editor; editor = editor->next)
399         {
400                 if (editor->window == hWnd)
401                         break;
402                 if (editor->window == NULL)
403                         break;  //we're actually creating it now.
404         }
405         if (!editor)
406                 goto gdefault;
407
408         switch (message)
409         {
410         case WM_CLOSE:
411         case WM_QUIT:
412                 if (EditorModified(editor))
413                 {
414                         switch (MessageBox(hWnd, "Would you like to save?", editor->filename, MB_YESNOCANCEL))
415                         {
416                         case IDCANCEL:
417                                 return false;
418                         case IDYES:
419                                 if (!EditorSave(editor))
420                                         return false;
421                         case IDNO:
422                         default:
423                                 break;
424                         }
425                 }
426                 goto gdefault;
427         case WM_DESTROY:
428                 {
429                         editor_t *e;
430                         if (editor == editors)
431                         {
432                                 editors = editor->next;
433                                 free(editor);
434                                 return 0;
435                         }
436                         for (e = editors; e; e = e->next)
437                         {
438                                 if (e->next == editor)
439                                 {
440                                         e->next = editor->next;
441                                         free(editor);
442                                         return 0;
443                                 }
444                         }
445                         MessageBox(0, "Couldn't destroy file reference", "WARNING", 0);
446                 }
447                 goto gdefault;
448         case WM_CREATE:
449                 editor->editpane = CreateAnEditControl(hWnd);
450                 /*
451                 editor->editpane=CreateWindowEx(WS_EX_CLIENTEDGE,
452                         richedit?RICHEDIT_CLASS:"EDIT",
453                         "",
454                         WS_CHILD  | WS_VISIBLE | 
455                         WS_HSCROLL | WS_VSCROLL | ES_LEFT | ES_WANTRETURN |
456                         ES_MULTILINE | ES_AUTOVSCROLL,
457                         0, 0, 0, 0,
458                         hWnd,
459                         NULL,
460                         ghInstance,
461                         NULL);
462 */
463                 if (richedit)
464                 {
465                         SendMessage(editor->editpane, EM_EXLIMITTEXT, 0, 1<<31);
466
467                         SendMessage(editor->editpane, EM_SETUNDOLIMIT, 256, 256);
468                 }
469                 goto gdefault;
470         case WM_SIZE:
471                 GetClientRect(hWnd, &rect);
472                 SetWindowPos(editor->editpane, NULL, 0, 0, rect.right-rect.left, rect.bottom-rect.top, 0);
473                 goto gdefault;
474         case WM_PAINT:
475                 hdc=BeginPaint(hWnd,(LPPAINTSTRUCT)&ps);
476
477                 EndPaint(hWnd,(LPPAINTSTRUCT)&ps);
478                 return TRUE;
479                 break;
480         case WM_COMMAND:
481                 if (mdibox)
482                         goto gdefault;
483                 EditorMenu(editor, wParam);
484                 break;
485         case WM_NOTIFY:
486                 {
487                     NMHDR *nmhdr;
488                         SELCHANGE *sel;
489                         char message[2048];
490                         nmhdr = (NMHDR *)lParam;
491                         switch(nmhdr->code)
492                         {
493                         case EN_SELCHANGE:
494                                 sel = (SELCHANGE *)nmhdr;
495                                 sprintf(message, "%s:%i - FTEQCC Editor", editor->filename, 1+Edit_LineFromChar(editor->editpane, sel->chrg.cpMin));
496                                 SetWindowText(editor->window, message);
497                                 break;
498                         }
499                 }
500         default:
501         gdefault:
502                 if (mdibox)
503                         return DefMDIChildProc(hWnd,message,wParam,lParam);
504                 else
505                         return DefWindowProc(hWnd,message,wParam,lParam);
506         }
507         return 0;
508 }
509
510 #if 1
511 static DWORD lastcolour;
512 int GUIEmitText(HWND wnd, int start, char *text, int len)
513 {
514         int c, cr;
515         DWORD colour;
516         CHARFORMAT cf;
517
518         if (!len)
519                 return start;
520
521         c = text[len];
522         text[len] = '\0';
523         Edit_SetSel(wnd,start,start);
524         Edit_ReplaceSel(wnd,text);
525
526         if (!strcmp(text, "void"))
527                 colour = RGB(0, 0, 255);
528         else if (!strcmp(text, "float"))
529                 colour = RGB(0, 0, 255);
530         else if (!strcmp(text, "vector"))
531                 colour = RGB(0, 0, 255);
532         else if (!strcmp(text, "entity"))
533                 colour = RGB(0, 0, 255);
534         else if (!strcmp(text, "local"))
535                 colour = RGB(0, 0, 255);
536         else if (!strcmp(text, "string"))
537                 colour = RGB(0, 0, 255);
538         else if (!strcmp(text, "struct"))
539                 colour = RGB(0, 0, 255);
540         else if (!strcmp(text, "class"))
541                 colour = RGB(0, 0, 255);
542         else if (!strcmp(text, "union"))
543                 colour = RGB(0, 0, 255);
544         else if (!strcmp(text, "const"))
545                 colour = RGB(0, 0, 255);
546         else if (!strcmp(text, "var"))
547                 colour = RGB(0, 0, 255);
548         else if (!strcmp(text, "nosave"))
549                 colour = RGB(0, 0, 255);
550
551         else if (!strcmp(text, "goto"))
552                 colour = RGB(255, 0, 0);
553         else if (!strcmp(text, "thinktime"))
554                 colour = RGB(0, 0, 255);
555         else if (!strcmp(text, "if"))
556                 colour = RGB(0, 0, 255);
557         else if (!strcmp(text, "else"))
558                 colour = RGB(0, 0, 255);
559         else if (!strcmp(text, "switch"))
560                 colour = RGB(0, 0, 255);
561         else if (!strcmp(text, "case"))
562                 colour = RGB(0, 0, 255);
563         else if (!strcmp(text, "default"))
564                 colour = RGB(0, 0, 255);
565         else if (!strcmp(text, "break"))
566                 colour = RGB(0, 0, 255);
567         else if (!strcmp(text, "continue"))
568                 colour = RGB(0, 0, 255);
569         else if (!strcmp(text, "do"))
570                 colour = RGB(0, 0, 255);
571         else if (!strcmp(text, "while"))
572                 colour = RGB(0, 0, 255);
573         else if (!strcmp(text, "for"))
574                 colour = RGB(0, 0, 255);
575         else if (!strcmp(text, "return"))
576                 colour = RGB(0, 0, 255);
577
578         else if (!strcmp(text, "self"))
579                 colour = RGB(0, 0, 127);
580         else if (!strcmp(text, "this"))
581                 colour = RGB(0, 0, 127);
582         else if (!strcmp(text, "other"))
583                 colour = RGB(0, 0, 127);
584         else if (!strcmp(text, "world"))
585                 colour = RGB(0, 0, 127);
586         else if (!strcmp(text, "time"))
587                 colour = RGB(0, 0, 127);
588
589
590         else if (!strcmp(text, "#define"))
591                 colour = RGB(0, 128, 255);
592         else if (!strcmp(text, "#ifdef"))
593                 colour = RGB(0, 128, 255);
594         else if (!strcmp(text, "#ifndef"))
595                 colour = RGB(0, 128, 255);
596         else if (!strcmp(text, "#else"))
597                 colour = RGB(0, 128, 255);
598         else if (!strcmp(text, "#endif"))
599                 colour = RGB(0, 128, 255);
600         else if (!strcmp(text, "#undef"))
601                 colour = RGB(0, 128, 255);
602         else if (!strcmp(text, "#pragma"))
603                 colour = RGB(0, 128, 255);
604         else if (!strcmp(text, "#includelist"))
605                 colour = RGB(0, 128, 255);
606         else if (!strcmp(text, "#endlist"))
607                 colour = RGB(0, 128, 255);
608
609
610         else if (*text == '\"')
611                 colour = RGB(128, 0, 0);
612
613         else if (!strncmp(text, "//", 2))
614                 colour = RGB(0, 127, 0);
615         else if (!strncmp(text, "/*", 2))
616                 colour = RGB(0, 127, 0);
617         else
618                 colour = RGB(0, 0, 0);
619
620         text[len] = c;
621
622         cr = 0;
623         for (c = 0; c < len; c++)
624                 if (text[c] == '\r')
625                         cr++;
626         if (cr)
627                 len-=cr;
628
629         if (colour == lastcolour)
630                 return start+len;
631
632         lastcolour = colour;
633
634         Edit_SetSel(wnd,start,start+len);
635         memset(&cf, 0, sizeof(cf));
636         cf.cbSize = sizeof(cf);
637         cf.dwMask = CFM_COLOR;
638         cf.crTextColor = colour;
639         SendMessage(wnd, EM_SETCHARFORMAT, SCF_SELECTION, (LPARAM)&cf);
640         Edit_SetSel(wnd,start+len,start+len);
641
642         return start + len;
643 }
644 void GUIFormattingPrint(HWND wnd, char *msg)
645 {
646         int len=Edit_GetTextLength(wnd);
647         char *start;
648         CHARRANGE chrg;
649         lastcolour = RGB(0,0,0);
650         SendMessage(wnd, WM_SETREDRAW, false, 0);
651         chrg.cpMin = chrg.cpMax = 0;
652         SendMessage(wnd, EM_EXSETSEL, 0, (LPARAM) &chrg);
653
654         for(start = msg;;)
655         {
656                 if (!*msg)
657                         break;
658                 else if (*msg == '/' && msg[1] == '/')
659                 {
660                         len = GUIEmitText(wnd, len, start, msg - start);
661                         start = msg;
662
663                         msg+=2;
664                         while(*msg && *msg != '\n' && *msg != '\r')
665                                 msg++;
666                 }
667                 else if (*msg == '/' && msg[1] == '*')
668                 {
669                         len = GUIEmitText(wnd, len, start, msg - start);
670                         start = msg;
671                         msg+=2;
672                         while(*msg)
673                         {
674                                 if (msg[0] == '*' && msg[1] == '/')
675                                 {
676                                         msg+=2;
677                                         break;
678                                 }
679                                 msg++;
680                         }
681                 }
682                 else if (*msg == '#' || *msg == '_' || (*msg >= 'A' && *msg <= 'Z') || (*msg >= 'a' && *msg <= 'z'))
683                 {
684                         len = GUIEmitText(wnd, len, start, msg - start);
685                         start = msg;
686                         msg++;
687                         while (*msg == '_' || (*msg >= 'A' && *msg <= 'Z') || (*msg >= 'a' && *msg <= 'z' || *msg >= '0' && *msg <= '9'))
688                                 msg++;
689                 }
690                 else if (*msg == '\"')
691                 {
692                         len = GUIEmitText(wnd, len, start, msg - start);
693                         start = msg;
694                         msg++;
695                         while(*msg)
696                         {
697                                 if (*msg == '\\')
698                                         msg++;
699                                 else if (*msg == '\"')
700                                 {
701                                         msg++;
702                                         break;
703                                 }
704
705                                 msg++;
706                         }
707                 }
708 /*              else if (*msg <= ' ')
709                 {
710                         while (*msg <= ' ' && *msg)
711                                 msg++;
712                 }*/
713                 else
714                 {
715                         msg++;
716                         continue;
717                 }
718
719                 len = GUIEmitText(wnd, len, start, msg - start);
720                 start = msg;
721         }
722         len = GUIEmitText(wnd, len, start, msg - start);
723         start = msg;
724         SendMessage(wnd, WM_SETREDRAW, true, 0);
725 }
726
727 int Rehighlight(editor_t *edit)
728 {
729         int len;
730         char *file;
731
732         CHARRANGE chrg;
733         POINT scrollpos;
734
735         SendMessage(edit->editpane, EM_SETEVENTMASK, 0, 0);
736
737         SendMessage(edit->editpane, EM_GETSCROLLPOS, 0, (LPARAM)&scrollpos);
738         SendMessage(edit->editpane, EM_EXGETSEL, 0, (LPARAM) &chrg);
739
740         len = Edit_GetTextLength(edit->editpane);
741         file = malloc(len+1);
742         if (!file)
743         {
744                 MessageBox(NULL, "Save failed - not enough mem", "Error", 0);
745                 return false;
746         }
747         Edit_GetText(edit->editpane, file, len);
748         file[len] = '\0';
749
750         SetWindowText(edit->editpane,"");
751
752 //      GUIPrint(edit->editpane, file);
753         GUIFormattingPrint(edit->editpane, file);
754         free(file);
755
756 //      Edit_SetSel(edit->editpane, Edit_LineIndex(neweditor->editpane, 0), Edit_LineIndex(neweditor->editpane, 0));
757
758         InvalidateRect(edit->editpane, NULL, true);
759         InvalidateRect(edit->window, NULL, true);
760
761         SendMessage(edit->editpane, EM_SETEVENTMASK, 0, ENM_SELCHANGE);
762
763         SendMessage(edit->editpane, EM_SETSCROLLPOS, 0, (LPARAM)&scrollpos);
764         SendMessage(edit->editpane, EM_EXSETSEL, 0, (LPARAM) &chrg);
765
766         UpdateWindow(edit->editpane);
767         RedrawWindow(edit->window, NULL, NULL, 0);
768
769         return true;
770 }
771 #else
772 static void chunkcolour(HWND pane, int start, int end, DWORD colour)
773 {
774         CHARFORMAT cf;
775         if (colour == RGB(0,0,0))
776                 return; //don't need to
777         Edit_SetSel(pane,start,end);
778         memset(&cf, 0, sizeof(cf));
779         cf.cbSize = sizeof(cf);
780         cf.dwMask = CFM_COLOR;
781         cf.crTextColor = colour;
782         SendMessage(pane, EM_SETCHARFORMAT, SCF_SELECTION, (LPARAM)&cf);
783 }
784 void GUIFormattingPrint(HWND wnd, char *msg)
785 {
786 }
787 int Rehighlight(editor_t *edit)
788 {
789         char *file;
790         int c, last, len;
791         DWORD color;
792         CHARRANGE chrg;
793         POINT scrollpos;
794
795         //Dsiable redraws
796         SendMessage(edit->editpane, WM_SETREDRAW, false, 0);
797
798         //Don't notify us for a bit..
799         SendMessage(edit->editpane, EM_SETEVENTMASK, 0, 0);
800
801         //get state so we can restore scroll positions and things.
802         SendMessage(edit->editpane, EM_GETSCROLLPOS, 0, (LPARAM)&scrollpos);
803         SendMessage(edit->editpane, EM_EXGETSEL, 0, (LPARAM) &chrg);
804
805
806         len = Edit_GetTextLength(edit->editpane);
807         file = malloc(len+1);
808         if (!file)
809         {
810                 MessageBox(NULL, "Highlight failed - not enough mem", "Error", 0);
811                 return false;
812         }
813         Edit_GetText(edit->editpane, file, len);
814         file[len] = '\0';
815         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
816
817         color = RGB(0,0,0);
818         for (last = 0, c = 0; c < len; c++)
819         {
820                 if (file[c] == '/' && file[c+1] == '/') //do special syntax
821                 {
822                         chunkcolour(edit->editpane, last, c, color);
823                         last = c;
824
825                         while(file[c] != '\n')
826                                 c++;
827                         color = RGB(0, 127, 0);
828                 }
829                 else
830                 {
831                         chunkcolour(edit->editpane, last, c, color);
832                         last = c;
833
834                         while(file[c] >= 'a' && file[c] <= 'z' || file[c] >= 'A' && file[c] <= 'Z' || file[c] == '_')
835                                 c++;
836
837                         color = RGB(rand(), rand(), rand());
838                 }
839         }
840
841         free(file);
842
843         //reenable drawing
844         SendMessage(edit->editpane, WM_SETREDRAW, true, 0);
845 }
846 #endif
847
848 void EditFile(char *name, int line)
849 {
850         char title[1024];
851         int flen;
852         char *file;
853         editor_t *neweditor;
854         WNDCLASS wndclass;
855         HMENU menu, menufile, menuhelp, menunavig;
856
857         for (neweditor = editors; neweditor; neweditor = neweditor->next)
858         {
859                 if (neweditor->window && !strcmp(neweditor->filename, name))
860                 {
861                         if (line >= 0)
862                         {
863                                 Edit_SetSel(neweditor->editpane, Edit_LineIndex(neweditor->editpane, line), Edit_LineIndex(neweditor->editpane, line+1));
864                                 Edit_ScrollCaret(neweditor->editpane);
865                         }
866                         if (mdibox)
867                                 SendMessage(mdibox, WM_MDIACTIVATE, (WPARAM)neweditor->window, 0);
868                         SetFocus(neweditor->window);
869                         SetFocus(neweditor->editpane);
870                         return;
871                 }
872         }
873
874         flen = QCC_FileSize(name);
875         if (flen == -1)
876         {
877                 MessageBox(NULL, "File not found.", "Error", 0);
878                 return;
879         }
880
881         neweditor = malloc(sizeof(editor_t));
882         if (!neweditor)
883         {
884                 MessageBox(NULL, "Low memory", "Error", 0);
885                 return;
886         }
887
888         neweditor->next = editors;
889         editors = neweditor;
890
891         strncpy(neweditor->filename, name, sizeof(neweditor->filename)-1);
892
893         if (!mdibox)
894         {
895                 menu = CreateMenu();
896                 menufile = CreateMenu();
897                 menuhelp = CreateMenu();
898                 menunavig = CreateMenu();
899                 AppendMenu(menu, MF_POPUP, (UINT)menufile,      "&File");
900                 AppendMenu(menu, MF_POPUP, (UINT)menunavig,     "&Navigation");
901                 AppendMenu(menu, MF_POPUP, (UINT)menuhelp,      "&Help");
902                 AppendMenu(menufile, 0, IDM_OPENNEW,    "Open &new file ");
903                 AppendMenu(menufile, 0, IDM_SAVE,               "&Save          ");
904         //      AppendMenu(menufile, 0, IDM_FIND,               "&Find");
905                 AppendMenu(menufile, 0, IDM_UNDO,               "&Undo          Ctrl+Z");
906                 AppendMenu(menufile, 0, IDM_REDO,               "&Redo          Ctrl+Y");
907                 AppendMenu(menunavig, 0, IDM_GOTODEF, "Go to definition");
908                 AppendMenu(menunavig, 0, IDM_OPENDOCU, "Open selected file");
909                 AppendMenu(menuhelp, 0, IDM_ABOUT, "About");
910                 AppendMenu(menu, 0, IDM_HIGHTLIGHT, "H&ighlight");
911         }
912
913
914         
915         wndclass.style      = 0;
916     wndclass.lpfnWndProc   = (WNDPROC)EditorWndProc;
917     wndclass.cbClsExtra    = 0;
918     wndclass.cbWndExtra    = 0;
919     wndclass.hInstance     = ghInstance;
920     wndclass.hIcon         = 0;
921     wndclass.hCursor       = LoadCursor (NULL,IDC_ARROW);
922         wndclass.hbrBackground = (void *)COLOR_WINDOW;
923     wndclass.lpszMenuName  = 0;
924     wndclass.lpszClassName = EDIT_WINDOW_CLASS_NAME;
925         RegisterClass(&wndclass);
926
927         neweditor->window = NULL;
928         if (mdibox)
929         {
930                 MDICREATESTRUCT mcs;
931
932                 sprintf(title, "%s", name);
933
934                 mcs.szClass = EDIT_WINDOW_CLASS_NAME;
935                 mcs.szTitle = name;
936                 mcs.hOwner = ghInstance;
937                 mcs.x = mcs.cx = CW_USEDEFAULT;
938                 mcs.y = mcs.cy = CW_USEDEFAULT;
939                 mcs.style = WS_OVERLAPPEDWINDOW;
940                 mcs.lParam = 0;
941
942                 neweditor->window = (HWND) SendMessage (mdibox, WM_MDICREATE, 0, 
943                         (LONG) (LPMDICREATESTRUCT) &mcs); 
944         }
945         else
946         {
947                 sprintf(title, "%s - FTEEditor", name);
948
949                 neweditor->window=CreateWindow(EDIT_WINDOW_CLASS_NAME, title, WS_OVERLAPPEDWINDOW,
950                         0, 0, 640, 480, NULL, NULL, ghInstance, NULL);
951         }
952
953         if (!mdibox)
954                 SetMenu(neweditor->window, menu);
955
956         if (!neweditor->window)
957         {
958                 MessageBox(NULL, "Failed to create editor window", "Error", 0);
959                 return;
960         }
961
962         flen = QCC_FileSize(name);
963         file = malloc(flen+1);
964         QCC_ReadFile(name, file, flen);
965         file[flen] = 0;
966
967         SendMessage(neweditor->editpane, EM_SETEVENTMASK, 0, 0);
968
969         if (!fl_autohighlight)
970         {
971                 GUIPrint(neweditor->editpane, file);
972         }
973         else
974         {
975                 GUIFormattingPrint(neweditor->editpane, file);
976         }
977
978         SendMessage(neweditor->editpane, EM_SETEVENTMASK, 0, ENM_SELCHANGE);
979
980         if (line >= 0)
981                 Edit_SetSel(neweditor->editpane, Edit_LineIndex(neweditor->editpane, line), Edit_LineIndex(neweditor->editpane, line+1));
982         else
983                 Edit_SetSel(neweditor->editpane, Edit_LineIndex(neweditor->editpane, 0), Edit_LineIndex(neweditor->editpane, 0));
984
985         Edit_ScrollCaret(neweditor->editpane);
986
987         ShowWindow(neweditor->window, SW_SHOW);
988         SetFocus(mainwindow);
989         SetFocus(neweditor->window);
990         SetFocus(neweditor->editpane);
991 }
992
993 int EditorSave(editor_t *edit)
994 {
995         int len;
996         char *file;
997         len = Edit_GetTextLength(edit->editpane);
998         file = malloc(len+1);
999         if (!file)
1000         {
1001                 MessageBox(NULL, "Save failed - not enough mem", "Error", 0);
1002                 return false;
1003         }
1004         Edit_GetText(edit->editpane, file, len);
1005         if (!QCC_WriteFile(edit->filename, file, len))
1006         {
1007                 MessageBox(NULL, "Save failed\nCheck path and ReadOnly flags", "Failure", 0);
1008                 return false;
1009         }
1010         free(file);
1011
1012         return true;
1013 }
1014 void EditorsRun(void)
1015 {
1016 }
1017
1018
1019 char *GUIReadFile(char *fname, void *buffer, int blen)
1020 {
1021         editor_t *e;
1022         for (e = editors; e; e = e->next)
1023         {
1024                 if (e->window && !strcmp(e->filename, fname))
1025                 {
1026                         int elen = Edit_GetTextLength(e->editpane);
1027                         Edit_GetText(e->editpane, buffer, blen);
1028                         return buffer;
1029                 }
1030         }
1031
1032         return QCC_ReadFile(fname, buffer, blen);
1033 }
1034
1035 int GUIFileSize(char *fname)
1036 {
1037         editor_t *e;
1038         for (e = editors; e; e = e->next)
1039         {
1040                 if (e->window && !strcmp(e->filename, fname))
1041                 {
1042                         int len = Edit_GetTextLength(e->editpane);
1043                         return len;
1044                 }
1045         }
1046         return QCC_FileSize(fname);
1047 }
1048
1049 pbool EditorModified(editor_t *e)
1050 {
1051         char *buffer;
1052         int elen, flen;
1053         elen = Edit_GetTextLength(e->editpane);
1054         flen = QCC_FileSize(e->filename);
1055
1056         if (elen != flen)
1057                 return true;
1058
1059         buffer = malloc(elen+flen);
1060         Edit_GetText(e->editpane, buffer, elen);
1061         QCC_ReadFile(e->filename, buffer+elen, flen);
1062         if (memcmp(buffer, buffer+elen, elen))
1063         {
1064                 free(buffer);
1065                 return true;
1066         }
1067         free(buffer);
1068
1069         return false;
1070 }
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084 HWND optionsmenu;
1085 HWND hexen2item;
1086 HWND nokeywords_coexistitem;
1087 HWND autoprototype_item;
1088 HWND autohighlight_item;
1089 HWND extraparmsitem;
1090 static LONG CALLBACK OptionsWndProc(HWND hWnd,UINT message,
1091                                      WPARAM wParam,LPARAM lParam)
1092 {
1093         int i;
1094         switch (message)
1095         {
1096         case WM_DESTROY:
1097                 optionsmenu = NULL;
1098                 break;
1099
1100         case WM_COMMAND:
1101                 switch(wParam)
1102                 {
1103                 case IDI_O_USE:
1104                 case IDI_O_APPLY:
1105                         for (i = 0; optimisations[i].enabled; i++)
1106                         {
1107                                 if (optimisations[i].flags & FLAG_HIDDENINGUI)
1108                                         continue;
1109
1110                                 if (Button_GetCheck(optimisations[i].guiinfo))
1111                                         optimisations[i].flags |= FLAG_SETINGUI;
1112                                 else
1113                                         optimisations[i].flags &= ~FLAG_SETINGUI;
1114                         }
1115                         fl_hexen2 = Button_GetCheck(hexen2item);
1116                         for (i = 0; compiler_flag[i].enabled; i++)
1117                         {
1118                                 if (compiler_flag[i].flags & FLAG_HIDDENINGUI)
1119                                         continue;
1120                                 if (Button_GetCheck(compiler_flag[i].guiinfo))
1121                                         compiler_flag[i].flags |= FLAG_SETINGUI;
1122                                 else
1123                                         compiler_flag[i].flags &= ~FLAG_SETINGUI;
1124                         }
1125                         fl_autohighlight = Button_GetCheck(autohighlight_item);
1126                         Edit_GetText(extraparmsitem, parameters, sizeof(parameters)-1);
1127
1128                         if (wParam == IDI_O_USE)
1129                                 buttons[ID_COMPILE].washit = true;
1130                         break;
1131                 case IDI_O_CHANGE_PROGS_SRC:
1132                         {
1133                                 char *s, *s2;
1134                                 char filename[MAX_PATH];
1135                                 char oldpath[MAX_PATH+10];
1136                                 OPENFILENAME ofn;
1137                                 memset(&ofn, 0, sizeof(ofn));
1138                                 ofn.lStructSize = sizeof(ofn);
1139                                 ofn.hInstance = ghInstance;
1140                                 ofn.lpstrFile = filename;
1141                                 ofn.lpstrTitle = "Please find progs.src";
1142                                 ofn.nMaxFile = sizeof(filename)-1;
1143                                 ofn.lpstrFilter = "QuakeC source\0*.src\0All files\0*.*\0";
1144                                 memset(filename, 0, sizeof(filename));
1145                                 GetCurrentDirectory(sizeof(oldpath)-1, oldpath);
1146                                 ofn.lpstrInitialDir = oldpath;
1147                                 if (GetOpenFileName(&ofn))
1148                                 {
1149                                         strcpy(progssrcdir, filename);
1150                                         for(s = progssrcdir; s; s = s2)
1151                                         {
1152                                                 s2 = strchr(s+1, '\\');
1153                                                 if (!s2)
1154                                                         break;
1155                                                 s = s2;
1156                                         }
1157                                         if (s)
1158                                         {
1159                                                 *s = '\0';
1160                                                 strcpy(progssrcname, s+1);
1161                                         }
1162                                         else
1163                                                 strcpy(progssrcname, filename);
1164
1165                                         SetCurrentDirectory(progssrcdir);
1166                                         *progssrcdir = '\0';
1167                                 }
1168                                 resetprogssrc = true;
1169                         }
1170                         break;
1171                 case IDI_O_LEVEL0:
1172                 case IDI_O_LEVEL1:
1173                 case IDI_O_LEVEL2:
1174                 case IDI_O_LEVEL3:
1175                         for (i = 0; optimisations[i].enabled; i++)
1176                         {
1177                                 if (optimisations[i].flags & FLAG_HIDDENINGUI)
1178                                         continue;
1179
1180                                 if (optimisations[i].optimisationlevel<=(int)wParam-IDI_O_LEVEL0)
1181                                         Button_SetCheck(optimisations[i].guiinfo, 1);
1182                                 else
1183                                         Button_SetCheck(optimisations[i].guiinfo, 0);
1184                         }
1185                         break;
1186                 case IDI_O_DEBUG:
1187                         for (i = 0; optimisations[i].enabled; i++)
1188                         {
1189                                 if (optimisations[i].flags & FLAG_HIDDENINGUI)
1190                                         continue;
1191
1192                                 if (optimisations[i].flags&FLAG_KILLSDEBUGGERS)
1193                                         Button_SetCheck(optimisations[i].guiinfo, 0);
1194                         }
1195                         break;
1196                 case IDI_O_DEFAULT:
1197                         for (i = 0; optimisations[i].enabled; i++)
1198                         {
1199                                 if (optimisations[i].flags & FLAG_HIDDENINGUI)
1200                                         continue;
1201
1202                                 if (optimisations[i].flags & FLAG_ASDEFAULT)
1203                                         Button_SetCheck(optimisations[i].guiinfo, 1);
1204                                 else
1205                                         Button_SetCheck(optimisations[i].guiinfo, 0);
1206                         }
1207                         break;
1208                 }
1209                 break;
1210         case WM_HELP:
1211                 {
1212                         HELPINFO *hi;
1213                         hi = (HELPINFO *)lParam;
1214                         switch(hi->iCtrlId) 
1215                         {
1216                         case IDI_O_DEFAULT:
1217                                 MessageBox(hWnd, "Sets the default optimisations", "Help", MB_OK|MB_ICONINFORMATION);
1218                                 break;
1219                         case IDI_O_DEBUG:
1220                                 MessageBox(hWnd, "Clears all optimisations which can make your progs harder to debug", "Help", MB_OK|MB_ICONINFORMATION);
1221                                 break;
1222                         case IDI_O_LEVEL0:
1223                         case IDI_O_LEVEL1:
1224                         case IDI_O_LEVEL2:
1225                         case IDI_O_LEVEL3:
1226                                 MessageBox(hWnd, "Sets a specific optimisation level", "Help", MB_OK|MB_ICONINFORMATION);
1227                                 break;
1228                         case IDI_O_CHANGE_PROGS_SRC:
1229                                 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);
1230                                 break;
1231                         case IDI_O_ADDITIONALPARAMETERS:
1232                                 MessageBox(hWnd, "Type in additional commandline parameters here. Use -Dname to define a named precompiler constant before compiling.", "Help", MB_OK|MB_ICONINFORMATION);
1233                                 break;
1234                         case IDI_O_APPLY:
1235                                 MessageBox(hWnd, "Apply changes shown, but do not recompile yet.", "Help", MB_OK|MB_ICONINFORMATION);
1236                                 break;
1237                         case IDI_O_USE:
1238                                 MessageBox(hWnd, "Apply changes shown here and recompile.", "Help", MB_OK|MB_ICONINFORMATION);
1239                                 break;
1240                         case IDI_O_OPTIMISATION:
1241                                 for (i = 0; optimisations[i].enabled; i++)
1242                                 {
1243                                         if (optimisations[i].guiinfo == hi->hItemHandle)
1244                                         {
1245                                                 MessageBox(hWnd, optimisations[i].description, "Help", MB_OK|MB_ICONINFORMATION);
1246                                                 break;
1247                                         }
1248                                 }
1249                                 break;
1250                         case IDI_O_COMPILER_FLAG:
1251                                 for (i = 0; compiler_flag[i].enabled; i++)
1252                                 {
1253                                         if (compiler_flag[i].guiinfo == hi->hItemHandle)
1254                                         {
1255                                                 MessageBox(hWnd, compiler_flag[i].description, "Help", MB_OK|MB_ICONINFORMATION);
1256                                                 break;
1257                                         }
1258                                 }
1259                                 break;
1260                         case IDI_O_TARGET:
1261                                 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);
1262                                 break;
1263                         case IDI_O_SYNTAX_HIGHLIGHTING:
1264                                 MessageBox(hWnd, "Should syntax be highlighted automatically when a file is opened?", "Help", MB_OK|MB_ICONINFORMATION);
1265                                 break;
1266                         }
1267                 }
1268                 break;
1269         default:
1270                 return DefWindowProc(hWnd,message,wParam,lParam);
1271         }
1272         return 0;
1273 }
1274 void OptionsDialog(void)
1275 {
1276         HWND subsection;
1277         RECT r;
1278         WNDCLASS wndclass;
1279         HWND wnd;
1280         int i;
1281         int flagcolums=1;
1282
1283         int x;
1284         int y;
1285         int my;
1286         int height;
1287         int num;
1288         int cflagsshown;
1289
1290         if (optionsmenu)
1291         {
1292                 BringWindowToTop(optionsmenu);
1293                 return;
1294         }
1295
1296
1297         memset(&wndclass, 0, sizeof(wndclass));
1298         wndclass.style      = 0;
1299     wndclass.lpfnWndProc   = (WNDPROC)OptionsWndProc;
1300     wndclass.cbClsExtra    = 0;
1301     wndclass.cbWndExtra    = 0;
1302     wndclass.hInstance     = ghInstance;
1303     wndclass.hIcon         = 0;
1304     wndclass.hCursor       = LoadCursor (NULL,IDC_ARROW);
1305         wndclass.hbrBackground = (void *)COLOR_WINDOW;
1306     wndclass.lpszMenuName  = 0;
1307     wndclass.lpszClassName = OPTIONS_WINDOW_CLASS_NAME;
1308         RegisterClass(&wndclass);
1309
1310         height = 0;
1311         for (i = 0; optimisations[i].enabled; i++)
1312         {
1313                 if (optimisations[i].flags & FLAG_HIDDENINGUI)
1314                         continue;
1315
1316                 height++;
1317         }
1318
1319         cflagsshown = 2;
1320         for (i = 0; compiler_flag[i].enabled; i++)
1321         {
1322                 if (compiler_flag[i].flags & FLAG_HIDDENINGUI)
1323                         continue;
1324
1325                 cflagsshown++;
1326         }
1327
1328         height = (height-1)/2;
1329
1330         while (cflagsshown > ((480-(88+40))/16)*(flagcolums))
1331                 flagcolums++;
1332
1333         if (height < (cflagsshown+flagcolums-1)/flagcolums)
1334                 height = (cflagsshown+flagcolums-1)/flagcolums;
1335
1336         r.right = 408 + flagcolums*168;
1337         if (r.right < 640)
1338                 r.right = 640;
1339
1340         height *= 16;
1341
1342         height += 88+40;
1343
1344         r.left = GetSystemMetrics(SM_CXSCREEN)/2-320;
1345         r.top = GetSystemMetrics(SM_CYSCREEN)/2-240;
1346         r.bottom = r.top + height;
1347         r.right  += r.left;
1348
1349
1350
1351         AdjustWindowRectEx (&r, WS_CAPTION|WS_SYSMENU, FALSE, 0);
1352
1353         optionsmenu=CreateWindowEx(WS_EX_CONTEXTHELP, OPTIONS_WINDOW_CLASS_NAME, "Options - FTE QuakeC compiler", WS_CAPTION|WS_SYSMENU,
1354                 r.left, r.top, r.right-r.left, r.bottom-r.top, NULL, NULL, ghInstance, NULL);
1355
1356         subsection = CreateWindow("BUTTON", "Optimisations", WS_CHILD|WS_VISIBLE|BS_GROUPBOX,
1357                 0, 0, 400, height-48, optionsmenu, NULL, ghInstance, NULL);
1358
1359         num = 0;
1360         for (i = 0; optimisations[i].enabled; i++)
1361         {
1362                 if (optimisations[i].flags & FLAG_HIDDENINGUI)
1363                 {
1364                         optimisations[i].guiinfo = NULL;
1365                         continue;
1366                 }
1367
1368                 optimisations[i].guiinfo = wnd = CreateWindow("BUTTON",optimisations[i].fullname,
1369                            WS_CHILD | WS_VISIBLE | BS_AUTOCHECKBOX,
1370                            8+200*(num&1),16+16*(num/2),200-16,16,
1371                            subsection,
1372                            (HMENU)IDI_O_OPTIMISATION,
1373                            ghInstance,
1374                            NULL);
1375
1376                 if (optimisations[i].flags&FLAG_SETINGUI)
1377                         Button_SetCheck(wnd, 1);
1378                 else
1379                         Button_SetCheck(wnd, 0);
1380
1381                 num++;
1382         }
1383
1384         CreateWindow("BUTTON","O0",
1385                    WS_CHILD | WS_VISIBLE,
1386                    8,height-88,64,32,
1387                    optionsmenu,
1388                    (HMENU)IDI_O_LEVEL0,
1389                    ghInstance,
1390                    NULL);
1391         CreateWindow("BUTTON","O1",
1392                    WS_CHILD | WS_VISIBLE,
1393                    8+64,height-88,64,32,
1394                    optionsmenu,
1395                    (HMENU)IDI_O_LEVEL1,
1396                    ghInstance,
1397                    NULL);
1398         CreateWindow("BUTTON","O2",
1399                    WS_CHILD | WS_VISIBLE,
1400                    8+64*2,height-88,64,32,
1401                    optionsmenu,
1402                    (HMENU)IDI_O_LEVEL2,
1403                    ghInstance,
1404                    NULL);
1405         CreateWindow("BUTTON","O3",
1406                    WS_CHILD | WS_VISIBLE,
1407                    8+64*3,height-88,64,32,
1408                    optionsmenu,
1409                    (HMENU)IDI_O_LEVEL3,
1410                    ghInstance,
1411                    NULL);
1412         CreateWindow("BUTTON","Debug",
1413                    WS_CHILD | WS_VISIBLE,
1414                    8+64*4,height-88,64,32,
1415                    optionsmenu,
1416                    (HMENU)IDI_O_DEBUG,
1417                    ghInstance,
1418                    NULL);
1419         CreateWindow("BUTTON","Default",
1420                    WS_CHILD | WS_VISIBLE,
1421                    8+64*5,height-88,64,32,
1422                    optionsmenu,
1423                    (HMENU)IDI_O_DEFAULT,
1424                    ghInstance,
1425                    NULL);
1426         CreateWindow("BUTTON","Apply",
1427                    WS_CHILD | WS_VISIBLE,
1428                    8,height-40,64,32,
1429                    optionsmenu,
1430                    (HMENU)IDI_O_APPLY,
1431                    ghInstance,
1432                    NULL);
1433         CreateWindow("BUTTON","Use",
1434                    WS_CHILD | WS_VISIBLE,
1435                    8+64,height-40,64,32,
1436                    optionsmenu,
1437                    (HMENU)IDI_O_USE,
1438                    ghInstance,
1439                    NULL);
1440         CreateWindow("BUTTON","progs.src",
1441                    WS_CHILD | WS_VISIBLE,
1442                    8+64*2,height-40,64,32,
1443                    optionsmenu,
1444                    (HMENU)IDI_O_CHANGE_PROGS_SRC,
1445                    ghInstance,
1446                    NULL);
1447
1448
1449
1450                 y=4;
1451         hexen2item = wnd = CreateWindow("BUTTON","HexenC",
1452                    WS_CHILD | WS_VISIBLE | BS_AUTOCHECKBOX,
1453                    408,y,200-16,16,
1454                    optionsmenu,
1455                    (HMENU)IDI_O_TARGET,
1456                    ghInstance,
1457                    NULL);
1458         y+=16;
1459         if (fl_hexen2)
1460                 Button_SetCheck(wnd, 1);
1461         else
1462                 Button_SetCheck(wnd, 0);
1463
1464         autohighlight_item = wnd = CreateWindow("BUTTON","Syntax Highlighting",
1465                    WS_CHILD | WS_VISIBLE | BS_AUTOCHECKBOX,
1466                    408,y,200-16,16,
1467                    optionsmenu,
1468                    (HMENU)IDI_O_SYNTAX_HIGHLIGHTING,
1469                    ghInstance,
1470                    NULL);
1471         y+=16;
1472         if (fl_autohighlight)
1473                 Button_SetCheck(wnd, 1);
1474         else
1475                 Button_SetCheck(wnd, 0);
1476
1477         x = 408;
1478         my = y;
1479         for (i = 0; compiler_flag[i].enabled; i++)
1480         {
1481                 if (compiler_flag[i].flags & FLAG_HIDDENINGUI)
1482                 {
1483                         compiler_flag[i].guiinfo = NULL;
1484                         continue;
1485                 }
1486
1487                 if (y > height-(88+40))
1488                 {
1489                         y = 4;
1490                         x += 168;
1491                 }
1492
1493                 compiler_flag[i].guiinfo = wnd = CreateWindow("BUTTON",compiler_flag[i].fullname,
1494                            WS_CHILD | WS_VISIBLE | BS_AUTOCHECKBOX,
1495                            x,y,168,16,
1496                            optionsmenu,
1497                            (HMENU)IDI_O_COMPILER_FLAG,
1498                            ghInstance,
1499                            NULL);
1500                 y+=16;
1501
1502                 if (my < y)
1503                         my = y;
1504
1505                 if (compiler_flag[i].flags & FLAG_SETINGUI)
1506                         Button_SetCheck(wnd, 1);
1507                 else
1508                         Button_SetCheck(wnd, 0);
1509         }
1510
1511         CreateWindow("STATIC","Extra Parameters:",
1512                    WS_CHILD | WS_VISIBLE,
1513                    408,my,200-16,16,
1514                    optionsmenu,
1515                    (HMENU)0,
1516                    ghInstance,
1517                    NULL);
1518         my+=16;
1519         extraparmsitem = CreateWindowEx(WS_EX_CLIENTEDGE, "EDIT",parameters,
1520                    WS_CHILD | WS_VISIBLE|ES_LEFT | ES_WANTRETURN |
1521                 ES_MULTILINE | ES_AUTOVSCROLL,
1522                    408,my,r.right-r.left - 408 - 8,height-my-4,
1523                    optionsmenu,
1524                    (HMENU)IDI_O_ADDITIONALPARAMETERS,
1525                    ghInstance,
1526                    NULL);
1527
1528         ShowWindow(optionsmenu, SW_SHOWDEFAULT);
1529 }
1530
1531
1532
1533
1534
1535
1536
1537
1538
1539
1540
1541 #undef printf
1542
1543
1544
1545 static LONG CALLBACK MainWndProc(HWND hWnd,UINT message,
1546                                      WPARAM wParam,LPARAM lParam)
1547 {
1548         int width;
1549         int i;
1550         RECT rect;
1551         HDC hdc;
1552         PAINTSTRUCT ps;
1553         switch (message)
1554         {
1555         case WM_CREATE:
1556                 {
1557                         CLIENTCREATESTRUCT ccs;
1558
1559                         HMENU rootmenu, windowmenu, m;
1560                         rootmenu = CreateMenu();
1561                         
1562                                 AppendMenu(rootmenu, MF_POPUP, (UINT)(m = CreateMenu()),        "&File");
1563                                         AppendMenu(m, 0, IDM_OPENNEW,   "Open &new file ");
1564                                         AppendMenu(m, 0, IDM_SAVE,              "&Save          ");
1565                                 //      AppendMenu(m, 0, IDM_FIND,              "&Find");
1566                                         AppendMenu(m, 0, IDM_UNDO,              "&Undo          Ctrl+Z");
1567                                         AppendMenu(m, 0, IDM_REDO,              "&Redo          Ctrl+Y");
1568                                 AppendMenu(rootmenu, MF_POPUP, (UINT)(m = CreateMenu()),        "&Navigation");
1569                                         AppendMenu(m, 0, IDM_GOTODEF, "Go to definition");
1570                                         AppendMenu(m, 0, IDM_OPENDOCU, "Open selected file");
1571                                 AppendMenu(rootmenu, MF_POPUP, (UINT)(m = windowmenu = CreateMenu()),   "&Window");
1572                                         AppendMenu(m, 0, IDM_CASCADE, "&Cascade");
1573                                         AppendMenu(m, 0, IDM_TILE_HORIZ, "Tile &Horizontally");
1574                                         AppendMenu(m, 0, IDM_TILE_VERT, "Tile &Vertically");
1575                                 AppendMenu(rootmenu, MF_POPUP, (UINT)(m = CreateMenu()),        "&Help");
1576                                         AppendMenu(m, 0, IDM_ABOUT, "About");
1577
1578                         SetMenu(hWnd, rootmenu);
1579
1580                         // Retrieve the handle to the window menu and assign the
1581                         // first child window identifier.
1582
1583                         memset(&ccs, 0, sizeof(ccs));
1584                         ccs.hWindowMenu = windowmenu;
1585                         ccs.idFirstChild = IDM_FIRSTCHILD;
1586
1587                         // Create the MDI client window.
1588
1589                         mdibox = CreateWindow( "MDICLIENT", (LPCTSTR) NULL,
1590                                         WS_CHILD | WS_CLIPCHILDREN | WS_VSCROLL | WS_HSCROLL,
1591                                         0, 0, 320, 200, hWnd, (HMENU) 0xCAC, ghInstance, (LPSTR) &ccs);
1592                         ShowWindow(mdibox, SW_SHOW);
1593
1594                         projecttree = CreateWindow(WC_TREEVIEW, (LPCTSTR) NULL,
1595                                         WS_CHILD | WS_CLIPCHILDREN | WS_VSCROLL | WS_HSCROLL
1596                                         |       TVS_HASBUTTONS |TVS_LINESATROOT|TVS_HASLINES,
1597                         0, 0, 320, 200, hWnd, (HMENU) 0xCAC, ghInstance, (LPSTR) &ccs);
1598                         ShowWindow(projecttree, SW_SHOW);
1599
1600                         if (projecttree)
1601                         {
1602                                 gotodefbox = CreateWindowEx(WS_EX_CLIENTEDGE, "EDIT", (LPCTSTR) NULL,
1603                                                 WS_CHILD | WS_CLIPCHILDREN,
1604                                                 0, 0, 320, 200, hWnd, (HMENU) 0xCAC, ghInstance, (LPSTR) NULL);
1605                                 ShowWindow(gotodefbox, SW_SHOW);
1606
1607                                 gotodefaccept = CreateWindowEx(WS_EX_CLIENTEDGE, "BUTTON", "GO",
1608                                                 WS_CHILD | WS_CLIPCHILDREN | BS_DEFPUSHBUTTON,
1609                                                 0, 0, 320, 200, hWnd, (HMENU) 0x4404, ghInstance, (LPSTR) NULL);
1610                                 ShowWindow(gotodefaccept, SW_SHOW);
1611                         }
1612                 }
1613                 break;
1614
1615         case WM_DESTROY:
1616                 mainwindow = NULL;
1617                 break;
1618
1619         case WM_SIZE:
1620                 GetClientRect(mainwindow, &rect);
1621                 if (projecttree)
1622                 {
1623                         SetWindowPos(projecttree, NULL, 0, 0, 192, rect.bottom-rect.top - 34 - 24, 0);
1624
1625                         SetWindowPos(gotodefbox, NULL, 0, rect.bottom-rect.top - 33 - 24, 160, 24, 0);
1626                         SetWindowPos(gotodefaccept, NULL, 160, rect.bottom-rect.top - 33 - 24, 32, 24, 0);
1627                         SetWindowPos(mdibox?mdibox:outputbox, NULL, 192, 0, rect.right-rect.left-192, rect.bottom-rect.top - 32, 0);
1628                 }
1629                 else
1630                         SetWindowPos(mdibox?mdibox:outputbox, NULL, 0, 0, rect.right-rect.left, rect.bottom-rect.top - 32, 0);
1631                 width = (rect.right-rect.left);
1632                 width/=NUMBUTTONS;
1633                 for (i = 0; i < NUMBUTTONS; i++)
1634                 {
1635                         SetWindowPos(buttons[i].hwnd, NULL, width*i, rect.bottom-rect.top - 32, width, 32, 0);
1636                 }
1637                 break;
1638         case WM_PAINT:
1639                 hdc=BeginPaint(hWnd,(LPPAINTSTRUCT)&ps);
1640
1641                 EndPaint(hWnd,(LPPAINTSTRUCT)&ps);
1642                 return TRUE;
1643                 break;
1644         case WM_COMMAND:
1645                 if (wParam == 0x4404)
1646                 {
1647                         GetWindowText(gotodefbox, finddef, sizeof(finddef)-1);
1648                         return true;
1649                 }
1650                 if (LOWORD(wParam)>0 && LOWORD(wParam) <= NUMBUTTONS)
1651                 {
1652                         if (LOWORD(wParam))
1653                                 buttons[LOWORD(wParam)-1].washit = 1;
1654                         break;
1655                 }
1656                 if (LOWORD(wParam) < IDM_FIRSTCHILD)
1657                 {
1658                         HWND ew;
1659                         editor_t *editor;
1660         
1661                         ew = (HWND)SendMessage(mdibox, WM_MDIGETACTIVE, 0, 0);
1662
1663                         for (editor = editors; editor; editor = editor->next)
1664                         {
1665                                 if (editor->window == ew)
1666                                         break;
1667                         }
1668                         if (editor)
1669                                 EditorMenu(editor, wParam);
1670                         else
1671                                 GenericMenu(wParam);
1672                         break;
1673                 }
1674                 break;
1675         case WM_NOTIFY:
1676                 if (lParam)
1677                 {
1678                         NMHDR *nm;
1679                         HANDLE item;
1680                         TVITEM i;
1681                         char filename[256];
1682                         char itemtext[256];
1683                         int oldlen;
1684                         int newlen;
1685                         nm = (NMHDR*)lParam;
1686                         if (nm->hwndFrom == projecttree)
1687                         {
1688                                 switch(nm->code)
1689                                 {
1690                                 case NM_DBLCLK:
1691                                         item = TreeView_GetSelection(projecttree);
1692                                         i.hItem = item;
1693                                         i.mask = TVIF_TEXT;
1694                                         i.pszText = itemtext;
1695                                         i.cchTextMax = sizeof(itemtext)-1;
1696                                         if (!TreeView_GetItem(projecttree, &i))
1697                                                 return 0;
1698                                         strcpy(filename, i.pszText);
1699                                         while(item)
1700                                         {
1701                                                 item = TreeView_GetParent(projecttree, item);
1702                                                 i.hItem = item;
1703                                                 if (!TreeView_GetItem(projecttree, &i))
1704                                                         break;
1705                                                 if (!TreeView_GetParent(projecttree, item))
1706                                                         break;
1707
1708                                                 oldlen = strlen(filename);
1709                                                 newlen = strlen(i.pszText);
1710                                                 memmove(filename+newlen+1, filename, oldlen+1);
1711                                                 filename[newlen] = '/';
1712                                                 strncpy(filename, i.pszText, newlen);
1713                                         }
1714                                         EditFile(filename, -1);
1715                                         break;
1716                                 }
1717                         }
1718                 }
1719         default:
1720                 if (mdibox)
1721                         return DefFrameProc(hWnd,mdibox,message,wParam,lParam);
1722                 else
1723                         return DefWindowProc(hWnd,message,wParam,lParam);
1724         }
1725         return 0;
1726 }
1727
1728 static LONG CALLBACK OutputWindowProc(HWND hWnd,UINT message,
1729                                      WPARAM wParam,LPARAM lParam)
1730 {
1731         RECT rect;
1732         switch (message)
1733         {
1734         case WM_DESTROY:
1735                 outputwindow = NULL;
1736                 outputbox = NULL;
1737                 break;
1738         case WM_CREATE:
1739                 outputbox = CreateAnEditControl(hWnd);
1740         case WM_SIZE:
1741                 GetClientRect(hWnd, &rect);
1742                 SetWindowPos(outputbox, NULL, 0, 0, rect.right-rect.left, rect.bottom-rect.top, 0);
1743
1744         default:
1745                 return DefMDIChildProc(hWnd,message,wParam,lParam);
1746         }
1747         return 0;
1748 }
1749
1750 void GUIPrint(HWND wnd, char *msg)
1751 {
1752         MSG        wmsg;
1753         int len;
1754         static int writing;
1755
1756         if (writing)
1757                 return;
1758         if (!mainwindow)
1759         {
1760                 printf("%s", msg);
1761                 return;
1762         }
1763         writing=true;
1764         len=Edit_GetTextLength(wnd);
1765 /*      if ((unsigned)len>(32767-strlen(msg)))
1766                 Edit_SetSel(wnd,0,len);
1767         else*/
1768                 Edit_SetSel(wnd,len,len);
1769         Edit_ReplaceSel(wnd,msg);
1770
1771         while (PeekMessage (&wmsg, NULL, 0, 0, PM_NOREMOVE))
1772         {
1773                 if (!GetMessage (&wmsg, NULL, 0, 0))
1774                         break;
1775                 TranslateMessage (&wmsg);
1776                 DispatchMessage (&wmsg);
1777         }
1778         writing=false;
1779 }
1780 int GUIEmitOutputText(HWND wnd, int start, char *text, int len, DWORD colour)
1781 {
1782         int c, cr;
1783         CHARFORMAT cf;
1784
1785         if (!len)
1786                 return start;
1787
1788         c = text[len];
1789         text[len] = '\0';
1790         Edit_SetSel(wnd,start,start);
1791         Edit_ReplaceSel(wnd,text);
1792
1793         text[len] = c;
1794
1795         cr = 0;
1796         for (c = 0; c < len; c++)
1797                 if (text[c] == '\r')
1798                         cr++;
1799         if (cr)
1800                 len-=cr;
1801
1802         Edit_SetSel(wnd,start,start+len);
1803         memset(&cf, 0, sizeof(cf));
1804         cf.cbSize = sizeof(cf);
1805         cf.dwMask = CFM_COLOR;
1806         cf.crTextColor = colour;
1807         SendMessage(wnd, EM_SETCHARFORMAT, SCF_SELECTION, (LPARAM)&cf);
1808         Edit_SetSel(wnd,start+len,start+len);
1809
1810         return start + len;
1811 }
1812 int outlen;
1813 int GUIprintf(const char *msg, ...)
1814 {
1815         va_list         argptr;
1816         char            buf[1024];
1817         char rn[3] = "\n";
1818         char *st, *s;
1819         int args;
1820         MSG        wmsg;
1821
1822         DWORD col;
1823
1824         va_start (argptr,msg);
1825         args = QC_vsnprintf (buf,sizeof(buf)-1, msg,argptr);
1826         va_end (argptr);
1827
1828         printf("%s", buf);
1829         if (logfile)
1830                 fprintf(logfile, "%s", buf);
1831
1832         if (!*buf)
1833         {
1834                 SetWindowText(outputbox,"");
1835                 outlen = 0;
1836                 return 0;
1837         }
1838
1839         if (strstr(buf, "warning: "))
1840                 col = RGB(128, 128, 0);
1841         else if (strstr(buf, "error: "))
1842                 col = RGB(255, 0, 0);
1843         else
1844                 col = RGB(0, 0, 0);
1845
1846         s = st = buf;
1847         while(*s)
1848         {
1849                 if (*s == '\n')
1850                 {
1851                         *s = '\0';
1852                         if (*st)
1853                                 outlen = GUIEmitOutputText(outputbox, outlen, st, strlen(st), col);
1854                         outlen = GUIEmitOutputText(outputbox, outlen, rn, 1, col);
1855                         st = s+1;
1856                 }
1857
1858                 s++;
1859         }
1860         if (*st)
1861                 outlen = GUIEmitOutputText(outputbox, outlen, st, strlen(st), col);
1862
1863         while (PeekMessage (&wmsg, NULL, 0, 0, PM_NOREMOVE))
1864         {
1865                 if (!GetMessage (&wmsg, NULL, 0, 0))
1866                         break;
1867                 TranslateMessage (&wmsg);
1868                 DispatchMessage (&wmsg);
1869         }
1870 /*
1871         s = st = buf;
1872         while(*s)
1873         {
1874                 if (*s == '\n')
1875                 {
1876                         *s = '\0';
1877                         if (*st)
1878                                 GUIPrint(outputbox, st);
1879                         GUIPrint(outputbox, "\r\n");
1880                         st = s+1;
1881                 }
1882
1883                 s++;
1884         }
1885         if (*st)
1886                 GUIPrint(outputbox, st);
1887 */
1888         return args;
1889 }
1890
1891 #undef Sys_Error
1892
1893 void Sys_Error(const char *text, ...);
1894 void RunCompiler(char *args)
1895 {
1896         char *argv[64];
1897         int argc;
1898         progexterns_t ext;
1899         progfuncs_t funcs;
1900
1901         memset(&funcs, 0, sizeof(funcs));
1902         funcs.parms = &ext;
1903         memset(&ext, 0, sizeof(ext));
1904         funcs.parms->ReadFile = GUIReadFile;
1905         funcs.parms->FileSize = GUIFileSize;
1906         funcs.parms->WriteFile = QCC_WriteFile;
1907         funcs.parms->printf = GUIprintf;
1908         funcs.parms->Sys_Error = Sys_Error;
1909         GUIprintf("");
1910         
1911         if (logfile)
1912                 fclose(logfile);
1913         if (fl_log)
1914                 logfile = fopen("fteqcc.log", "wb");
1915         else
1916                 logfile = NULL;
1917
1918         argc = GUI_BuildParms(args, argv);
1919
1920         CompileParams(&funcs, true, argc, argv);
1921
1922         if (logfile)
1923                 fclose(logfile);
1924 }
1925
1926
1927 void CreateOutputWindow(void)
1928 {
1929         WNDCLASS wndclass;
1930         MDICREATESTRUCT mcs;
1931
1932         if (!mdibox)    //should already be created
1933                 return;
1934
1935         if (!outputwindow)
1936         {
1937                 wndclass.style      = 0;
1938                 wndclass.lpfnWndProc   = (WNDPROC)OutputWindowProc;
1939                 wndclass.cbClsExtra    = 0;
1940                 wndclass.cbWndExtra    = 0;
1941                 wndclass.hInstance     = ghInstance;
1942                 wndclass.hIcon         = 0;
1943                 wndclass.hCursor       = LoadCursor (NULL,IDC_ARROW);
1944                 wndclass.hbrBackground = (void *)COLOR_WINDOW;
1945                 wndclass.lpszMenuName  = 0;
1946                 wndclass.lpszClassName = MAIN_WINDOW_CLASS_NAME;
1947                 RegisterClass(&wndclass);
1948
1949
1950
1951                 mcs.szClass = MAIN_WINDOW_CLASS_NAME;
1952                 mcs.szTitle = "Compiler output";
1953                 mcs.hOwner = ghInstance;
1954                 mcs.x = mcs.cx = CW_USEDEFAULT;
1955                 mcs.y = mcs.cy = CW_USEDEFAULT;
1956                 mcs.style = WS_OVERLAPPEDWINDOW;
1957                 mcs.lParam = 0;
1958
1959                 outputwindow = (HWND) SendMessage (mdibox, WM_MDICREATE, 0, 
1960                 (LONG) (LPMDICREATESTRUCT) &mcs); 
1961
1962                 ShowWindow(outputwindow, SW_SHOW);
1963         }
1964
1965         //bring it to the front.
1966         SendMessage(mdibox, WM_MDIACTIVATE, (WPARAM)outputwindow, 0);
1967 }
1968
1969 //progssrcname should already have been set.
1970 void SetProgsSrc(void)
1971 {
1972         FILE *f;
1973
1974         HANDLE rootitem, pi;
1975         TVINSERTSTRUCT item;
1976         TV_ITEM parent;
1977         char parentstring[256];
1978         memset(&item, 0, sizeof(item));
1979         memset(&parent, 0, sizeof(parent));
1980
1981         if (projecttree)
1982         {
1983                 int size;
1984                 char *buffer;
1985                 char *slash;
1986
1987                 f = fopen (progssrcname, "rb");
1988                 if (!f)
1989                         return;
1990                 fseek(f, 0, SEEK_END);
1991                 size = ftell(f);
1992                 fseek(f, 0, SEEK_SET);
1993                 buffer = malloc(size+1);
1994                 if (!buffer)
1995                 {
1996                         fclose(f);
1997                         return;
1998                 }
1999                 buffer[size] = '\0';
2000                 fread(buffer, 1, size, f);
2001                 fclose(f);
2002
2003                 pr_file_p = QCC_COM_Parse(buffer);
2004                 if (*qcc_token == '#')
2005                 {
2006                         free(buffer);   //aaaahhh! newstyle!
2007                         return;
2008                 }
2009
2010                 pr_file_p = QCC_COM_Parse(pr_file_p);   //we dont care about the produced progs.dat
2011
2012
2013                 item.hParent = TVI_ROOT;
2014                 item.hInsertAfter = TVI_SORT;
2015                 item.item.pszText = progssrcname;
2016                 item.item.mask = TVIF_TEXT;
2017                 rootitem = (HANDLE)SendMessage(projecttree,TVM_INSERTITEM,0,(LPARAM)&item);
2018                 while(pr_file_p)
2019                 {
2020                         pi = item.hParent = rootitem;
2021                         item.item.pszText = qcc_token;
2022                         while(slash = strchr(item.item.pszText, '/'))
2023                         {
2024                                 *slash = '\0';
2025                                 item.hParent = TreeView_GetChild(projecttree, item.hParent);
2026                                 do
2027                                 {
2028                                         parent.hItem = item.hParent;
2029                                         parent.mask = TVIF_TEXT;
2030                                         parent.pszText = parentstring;
2031                                         parent.cchTextMax = sizeof(parentstring)-1;
2032                                         if (TreeView_GetItem(projecttree, &parent))
2033                                         {
2034                                                 if (!stricmp(parent.pszText, item.item.pszText))
2035                                                         break;
2036                                         }
2037                                 } while(item.hParent=TreeView_GetNextSibling(projecttree, item.hParent));
2038                                 if (!item.hParent)
2039                                 {       //add a directory.
2040                                         item.hParent = pi;
2041                                         pi = (HANDLE)SendMessage(projecttree,TVM_INSERTITEM,0,(LPARAM)&item);
2042                                         item.hParent = pi;
2043                                 }
2044                                 else pi = item.hParent;
2045
2046                                 item.item.pszText = slash+1;
2047                         }
2048                         SendMessage(projecttree,TVM_INSERTITEM,0,(LPARAM)&item);
2049                         pr_file_p = QCC_COM_Parse(pr_file_p);
2050                 }
2051
2052                 free(buffer);
2053         }
2054 }
2055
2056 int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
2057 {
2058         unsigned int i;
2059         WNDCLASS wndclass;
2060         ghInstance= hInstance;
2061
2062         GUI_SetDefaultOpts();
2063
2064         if(strstr(lpCmdLine, "-stdout"))
2065         {
2066                 GUI_ParseCommandLine(lpCmdLine);
2067                 RunCompiler(lpCmdLine);
2068                 return 0;
2069         }
2070
2071         if (!*lpCmdLine)
2072         {
2073                 int len;
2074                 FILE *f;
2075                 char *s;
2076
2077                 f = fopen("fteqcc.cfg", "rb");
2078                 if (f)
2079                 {
2080                         fseek(f, 0, SEEK_END);
2081                         len = ftell(f);
2082                         fseek(f, 0, SEEK_SET);
2083                         lpCmdLine = malloc(len+1);
2084                         fread(lpCmdLine, 1, len, f);
2085                         lpCmdLine[len] = '\0';
2086                         fclose(f);
2087
2088                         while(s = strchr(lpCmdLine, '\r'))
2089                                 *s = ' ';
2090                         while(s = strchr(lpCmdLine, '\n'))
2091                                 *s = ' ';
2092                 }
2093         }
2094
2095         GUI_ParseCommandLine(lpCmdLine);
2096
2097         GUI_RevealOptions();
2098
2099         if (/*!fl_acc &&*/ !*progssrcname)
2100         {
2101                 strcpy(progssrcname, "preprogs.src");
2102                 if (QCC_FileSize(progssrcname)==-1)
2103                         strcpy(progssrcname, "progs.src");
2104                 if (QCC_FileSize(progssrcname)==-1)
2105                 {
2106                         char *s, *s2;
2107                         char filename[MAX_PATH];
2108                         char oldpath[MAX_PATH+10];
2109                         OPENFILENAME ofn;
2110                         memset(&ofn, 0, sizeof(ofn));
2111                         ofn.lStructSize = sizeof(ofn);
2112                         ofn.hInstance = ghInstance;
2113                         ofn.lpstrFile = filename;
2114                         ofn.lpstrTitle = "Please find progs.src";
2115                         ofn.nMaxFile = sizeof(filename)-1;
2116                         ofn.lpstrFilter = "QuakeC source\0*.src\0All files\0*.*\0";
2117                         memset(filename, 0, sizeof(filename));
2118                         GetCurrentDirectory(sizeof(oldpath)-1, oldpath);
2119                         ofn.lpstrInitialDir = oldpath;
2120                         if (GetOpenFileName(&ofn))
2121                         {
2122                                 strcpy(progssrcdir, filename);
2123                                 for(s = progssrcdir; s; s = s2)
2124                                 {
2125                                         s2 = strchr(s+1, '\\');
2126                                         if (!s2)
2127                                                 break;
2128                                         s = s2;
2129                                 }
2130                                 if (s)
2131                                 {
2132                                         *s = '\0';
2133                                         strcpy(progssrcname, s+1);
2134                                 }
2135                                 else
2136                                         strcpy(progssrcname, filename);
2137                         }
2138                         else
2139                         {
2140                                 MessageBox(NULL, "You didn't select a file", "Error", 0);
2141                                 return 0;
2142                         }
2143                         SetCurrentDirectory(progssrcdir);
2144                         *progssrcdir = '\0';
2145                 }
2146         }
2147
2148         resetprogssrc = true;
2149
2150     wndclass.style      = 0;
2151     wndclass.lpfnWndProc   = (WNDPROC)MainWndProc;
2152     wndclass.cbClsExtra    = 0;
2153     wndclass.cbWndExtra    = 0;
2154     wndclass.hInstance     = ghInstance;
2155     wndclass.hIcon         = 0;
2156     wndclass.hCursor       = LoadCursor (NULL,IDC_ARROW);
2157         wndclass.hbrBackground = (void *)COLOR_WINDOW;
2158     wndclass.lpszMenuName  = 0;
2159     wndclass.lpszClassName = MDI_WINDOW_CLASS_NAME;
2160         RegisterClass(&wndclass);
2161
2162         mainwindow=CreateWindow(MDI_WINDOW_CLASS_NAME, "FTE QuakeC compiler", WS_OVERLAPPEDWINDOW,
2163                 0, 0, 640, 480, NULL, NULL, ghInstance, NULL);
2164
2165         if (mdibox)
2166         {
2167                 SetWindowText(mainwindow, "FTE QuakeC Development Suite");
2168         }
2169
2170         if (!mainwindow)
2171         {
2172                 MessageBox(NULL, "Failed to create main window", "Error", 0);
2173                 return 0;
2174         }
2175
2176         InitCommonControls();
2177 /*
2178         outputbox=CreateWindowEx(WS_EX_CLIENTEDGE,
2179                 "EDIT",
2180                 "",
2181                 WS_CHILD | ES_READONLY | WS_VISIBLE | 
2182                 WS_VSCROLL | ES_LEFT | ES_WANTRETURN |
2183                 ES_MULTILINE | ES_AUTOVSCROLL,
2184                 0, 0, 0, 0,
2185                 mainwindow,
2186                 NULL,
2187                 ghInstance,
2188                 NULL);
2189 */
2190
2191         if (!mdibox)
2192                 outputbox = CreateAnEditControl(mainwindow);
2193
2194         for (i = 0; i < NUMBUTTONS; i++)
2195         {
2196                 buttons[i].hwnd = CreateWindowEx(WS_EX_CLIENTEDGE,
2197                         "BUTTON",
2198                         buttons[i].text,
2199                         WS_CHILD | WS_VISIBLE,
2200                         0, 0, 5, 5,
2201                         mainwindow,
2202                         (HMENU)(i+1),
2203                         ghInstance,
2204                         NULL); 
2205         }
2206
2207         ShowWindow(mainwindow, SW_SHOWDEFAULT);
2208
2209         if (fl_compileonstart)
2210         {
2211                 CreateOutputWindow();
2212                 RunCompiler(lpCmdLine);
2213         }
2214         else
2215         {
2216                 if (mdibox)
2217                 {
2218                         buttons[ID_EDIT].washit = true;
2219                 }
2220                 else
2221                 {
2222                         GUIprintf("Welcome to FTE QCC\n");
2223                         GUIprintf("Source file: ");
2224                         GUIprintf(progssrcname);
2225                         GUIprintf("\n");
2226
2227                         RunCompiler("-?");
2228                 }
2229         }
2230
2231         while(mainwindow || editors)
2232         {
2233                 MSG        msg;
2234
2235                 if (resetprogssrc)
2236                 {       //this here, with the compiler below, means that we don't run recursivly.
2237                         resetprogssrc = false;
2238                         SetProgsSrc();
2239                 }
2240
2241                 EditorsRun();
2242
2243                 while (PeekMessage (&msg, NULL, 0, 0, PM_NOREMOVE))
2244                 {
2245                         if (!GetMessage (&msg, NULL, 0, 0))
2246                                 break;
2247                         if (!mdibox || !TranslateMDISysAccel(mdibox, &msg))
2248                         { 
2249                                 TranslateMessage (&msg);
2250                                 DispatchMessage (&msg);
2251                         }
2252                 }
2253
2254                 if (mainwindow)
2255                 {
2256                         i = Edit_GetSel(outputbox);
2257                         if ((i>>16) != (i&0xffff) && i != -1)   //some text is selected.
2258                         {
2259                                 int bytes;
2260                                 char line[1024];
2261                                 char *colon1, *colon2 = NULL;
2262
2263                                 int l1;
2264                                 int l2;
2265
2266                                 l1 = Edit_LineFromChar(outputbox, i&0xffff);
2267                                 l2 = Edit_LineFromChar(outputbox, (i>>16)&0xffff);
2268                                 if (l1 == l2)
2269                                 {
2270                                         bytes = Edit_GetLine(outputbox, Edit_LineFromChar(outputbox, i&0xffff), line, sizeof(line)-1);
2271                                         line[bytes] = 0;
2272
2273                                         for (colon1 = line+strlen(line)-1; *colon1 <= ' ' && colon1>=line; colon1--)
2274                                                 *colon1 = '\0';
2275                                         if (!strncmp(line, "warning: ", 9))
2276                                                 memmove(line, line+9, sizeof(line));
2277                                         colon1=line;
2278                                         do
2279                                         {
2280                                                 colon1 = strchr(colon1+1, ':');
2281                                         } while (colon1 && colon1[1] == '\\');
2282
2283                                         if (colon1)
2284                                         {
2285                                                 colon2 = strchr(colon1+1, ':');
2286                                                 while (colon2 && colon2[1] == '\\')
2287                                                 {
2288                                                         colon2 = strchr(colon2+1, ':');
2289                                                 }
2290                                                 if (colon2)
2291                                                 {
2292                                                         *colon1 = '\0';
2293                                                         *colon2 = '\0';
2294                                                         EditFile(line, atoi(colon1+1)-1);
2295                                                 }
2296                                                 else if (!strncmp(line, "Source file: ", 13))
2297                                                         EditFile(line+13, -1);
2298                                                 else if (!strncmp(line, "Including: ", 11))
2299                                                         EditFile(line+11, -1);
2300                                         }
2301                                         else if (!strncmp(line, "compiling ", 10))
2302                                                 EditFile(line+10, -1);
2303                                         else if (!strncmp(line, "prototyping ", 12))
2304                                                 EditFile(line+12, -1);
2305                                         Edit_SetSel(outputbox, i&0xffff, i&0xffff);     //deselect it.
2306                                 }
2307                         }
2308
2309                         if (buttons[ID_COMPILE].washit)
2310                         {
2311                                 CreateOutputWindow();
2312                                 RunCompiler(parameters);
2313
2314                                 buttons[ID_COMPILE].washit = false;
2315                         }
2316                         if (buttons[ID_EDIT].washit)
2317                         {
2318                                 buttons[ID_EDIT].washit = false;
2319                                 EditFile(progssrcname, -1);
2320                         }
2321                         if (buttons[ID_OPTIONS].washit)
2322                         {
2323                                 buttons[ID_OPTIONS].washit = false;
2324                                 OptionsDialog();
2325                         }
2326                         if (buttons[ID_QUIT].washit)
2327                         {
2328                                 buttons[ID_QUIT].washit = false;
2329                                 DestroyWindow(mainwindow);
2330                         }
2331                 }
2332
2333                 if (*finddef)
2334                 {
2335                         GoToDefinition(finddef);
2336                         *finddef = '\0';
2337                 }
2338
2339                 Sleep(10);
2340         }
2341
2342         return 0;
2343 }