forked from gphilippot/purebasic
-
Notifications
You must be signed in to change notification settings - Fork 0
/
CompilerWindow.pb
1643 lines (1337 loc) · 57.3 KB
/
CompilerWindow.pb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
;--------------------------------------------------------------------------------------------
; Copyright (c) Fantaisie Software. All rights reserved.
; Dual licensed under the GPL and Fantaisie Software licenses.
; See LICENSE and LICENSE-FANTAISIE in the project root for license information.
;--------------------------------------------------------------------------------------------
; On Linux (gtk2) the font is usually much bigger, so make this larger there
CompilerIf #CompileLinux
#CompilerWindow_ListHeight = 250
CompilerElse
#CompilerWindow_ListHeight = 100
CompilerEndIf
Global Options_IsProjectMode
Global Options_CurrentBasePath$
Global *Options_CurrentTarget.CompileTarget
Procedure GetActiveCompileTarget()
If *ActiveSource
If *ActiveSource = *ProjectInfo Or *ActiveSource\ProjectFile ; active source is part of a project
ProcedureReturn *DefaultTarget
ElseIf *ActiveSource\IsCode
ProcedureReturn *ActiveSource ; the SourceFile structure extends the CompileTarget one
Else
ProcedureReturn 0 ; active source is a non-pb file
EndIf
ElseIf IsProject
ProcedureReturn *DefaultTarget
Else
ProcedureReturn 0
EndIf
EndProcedure
; Find a CompileTarget structure from its unique ID
;
Procedure FindTargetFromID(ID)
*Target.CompileTarget = 0
If ID ; 0 is considered invalid, so do no search
; Note: This function can be called inside another that loops on FileList(),
; so do not use *ActiveSource to restore the position!
Current = ListIndex(FileList())
ForEach FileList()
If @FileList() <> *ProjectInfo And FileList()\ID = ID
*Target = @FileList()
Break
EndIf
Next FileList()
SelectElement(FileList(), Current)
If *Target = 0
Current = ListIndex(ProjectTargets())
ForEach ProjectTargets()
If ProjectTargets()\ID = ID
*Target = @ProjectTargets()
Break
EndIf
Next ProjectTargets()
SelectElement(ProjectTargets(), Current)
EndIf
EndIf
ProcedureReturn *Target
EndProcedure
Procedure SetCompileTargetDefaults(*Target.CompileTarget)
*Target\Debugger = OptionDebugger
*Target\EnableASM = OptionInlineASM
*Target\EnableThread = OptionThread
*Target\EnableXP = OptionXPSkin
*Target\EnableAdmin = OptionVistaAdmin
*Target\EnableUser = OptionVistaUser
*Target\DPIAware = OptionDPIAware
*Target\EnableOnError = OptionOnError
*Target\ExecutableFormat = OptionExeFormat
*Target\CPU = OptionCPU
*Target\SubSystem$ = OptionSubSystem$
*Target\UseCompileCount = OptionUseCompileCount
*Target\UseBuildCount = OptionUseBuildCount
*Target\UseCreateExe = OptionUseCreateExe
*Target\TemporaryExePlace= OptionTemporaryExe
*Target\CurrentDirectory$= ""
*Target\EnablePurifier = OptionPurifier
*Target\PurifierGranularity$ = ""
EndProcedure
Procedure CompilerReady()
DisableMenuItem(#MENU, #MENU_StructureViewer, 0)
DisableMenuItem(#MENU, #MENU_CreateExecutable, 0)
DisableMenuAndToolbarItem(#MENU_CompileRun, 0)
DisableMenuAndToolbarItem(#MENU_SyntaxCheck, 0)
CompilerReady = 1
If *CurrentCompiler = @DefaultCompiler
HistoryCompilerLoaded()
InitSyntaxHighlighting()
; Set up the os specific color values
;
SetUpHighlightingColors()
; do this before scanning, as it affects saved data (known constants etc)
InitStructureViewer()
EndIf
; Ok, everything is loaded, now highlight any already open files.
;
If EnableColoring
If ListSize(FileList()) > 0 ; on Linux, this happens before any source is open
*CurrentFile = *ActiveSource
ForEach FileList()
If @FileList() <> *ProjectInfo
*ActiveSource = @FileList()
FullSourceScan(@FileList()) ; re-scan autocomplete + procedurebrowser
SortParserData(@FileList()\Parser, @FileList()) ; update sorted data in case its not the active source
UpdateFolding(@FileList(), 0, -1) ; redo all folding
SetBackgroundColor()
UpdateHighlighting()
EndIf
Next FileList()
ChangeCurrentElement(FileList(), *CurrentFile)
*ActiveSource = *CurrentFile
EndIf
EndIf
; Re-scan all non-loaded project files for changed options
;
If IsProject
ForEach ProjectFiles()
If ProjectFiles()\Source = 0 And ProjectFiles()\AutoScan ; not currently loaded, but scanning
ScanFile(ProjectFiles()\FileName$, @ProjectFiles()\Parser)
EndIf
Next ProjectFiles()
EndIf
If IsWindow(#WINDOW_StructureViewer)
DisplayStructureRootList()
EndIf
; reflect any source scan changes
UpdateProcedureList()
UpdateVariableViewer()
EndProcedure
Global CompilerWindowSmall, CompilerWindowBig
Procedure DisplayCompilerWindow()
; hide the warning window (if any), and clear the warning list (important)
HideCompilerWarnings()
If IsWindow(#WINDOW_MacroError)
MacroErrorWindowEvents(#PB_Event_CloseWindow)
EndIf
If OpenWindow(#WINDOW_Compiler, 0, 0, 200, 50, #ProductName$, #PB_Window_ScreenCentered | #PB_Window_TitleBar | #PB_Window_Invisible, WindowID(#WINDOW_Main))
Container = ContainerGadget(#PB_Any, 5, 5, 190, 40, #PB_Container_Single)
; add a dummy text for size calculation
TextGadget(#GADGET_Compiler_Text, 15, 15, 120, 20, Language("Compiler","Compiling") + " (999999 "+Language("Compiler","Lines")+")")
ButtonGadget(#GADGET_Compiler_Details, 240, 15, 50, 20, Language("Compiler", "Details"), #PB_Button_Toggle)
CloseGadgetList()
ListViewGadget(#GADGET_Compiler_List, 5, 55, 190, 100)
ProgressBarGadget(#GADGET_Compiler_Progress, 5, 160, 190, 20, 0, 1000)
ButtonGadget(#GADGET_Compiler_Abort, 145, 160, 50, 20, Language("Misc", "Abort"))
; calculate needed sizes
GetRequiredSize(#GADGET_Compiler_Text, @TextWidth, @TextHeight)
GetRequiredSize(#GADGET_Compiler_Details, @ButtonWidth, @ButtonHeight)
GetRequiredSize(#GADGET_Compiler_Abort, @AbortWidth, @ButtonHeight)
; special handling is needed for OSX Cocoa
CompilerIf #CompileMacCocoa
; border is large and not part of the client area
ContainerBorderWidth = 16
ContainerBorderHeight = 16
ContainerOffsetX = 0
ContainerOffsetY = 0
MinButtonHeight = 40
CompilerElse
; add some distance to the borders in the client area on other os
ContainerBorderWidth = 20
ContainerBorderHeight = 20
ContainerOffsetX = 10
ContainerOffsetY = 10
MinButtonHeight = 20
CompilerEndIf
ButtonWidth = Max(ButtonWidth, 60)
AbortWidth = Max(AbortWidth, 60)
ButtonHeight= Max(ButtonHeight, MinButtonHeight)
Width = Max(20+ContainerBorderWidth+TextWidth+ButtonWidth, 200)
Height = 10+ContainerBorderHeight+Max(TextHeight, ButtonHeight)
; for later resizing
CompilerWindowSmall = Height
CompilerWindowBig = Height + 15 + ButtonHeight + #CompilerWindow_ListHeight
ResizeGadget(Container, 5, 5, Width-10, Height-10)
ResizeGadget(#GADGET_Compiler_Text, ContainerOffsetX, ContainerOffsetY+(Height-30-TextHeight)/2, TextWidth, TextHeight)
ResizeGadget(#GADGET_Compiler_Details, Width-20-ContainerBorderWidth-ButtonWidth+20, ContainerOffsetY, ButtonWidth, Height-30)
ResizeGadget(#GADGET_Compiler_List, 5, Height+5, Width-10, #CompilerWindow_ListHeight)
ResizeGadget(#GADGET_Compiler_Progress, 5, Height+10+#CompilerWindow_ListHeight, Width-15-AbortWidth, ButtonHeight)
ResizeGadget(#GADGET_Compiler_Abort, Width-5-AbortWidth, Height+10+#CompilerWindow_ListHeight, AbortWidth, ButtonHeight)
; resize the window and re-center it as well
If ShowCompilerProgress
NewHeight = CompilerWindowBig
SetGadgetState(#GADGET_Compiler_Details, 1)
Else
NewHeight = CompilerWindowSmall
EndIf
ResizeWindow(#WINDOW_Compiler, WindowX(#WINDOW_Compiler)-(Width-200)/2, WindowY(#WINDOW_Compiler)-(NewHeight-50)/2, Width, NewHeight)
; set the real text to the textgadget
SetGadgetText(#GADGET_Compiler_Text, Language("Compiler","Compiling"))
AddGadgetItem(#GADGET_Compiler_List, 0, Language("Compiler","Compiling"))
SetGadgetState(#GADGET_Compiler_List, 0)
HideWindow(#WINDOW_Compiler, 0)
; StickyWindow(#WINDOW_Compiler, 1) ; Why sticky ? If we put the IDE to background it will stay above our browser for example, which is very annoying
EndIf
DisableMenuItem(#MENU, #MENU_CreateExecutable, 1)
DisableMenuAndToolbarItem(#MENU_CompileRun, 1)
DisableMenuAndToolbarItem(#MENU_SyntaxCheck, 1)
; important so the active source cannot be closed/switched during compiling
DisableWindow(#WINDOW_Main, 1)
FlushEvents() ; allow the window to be drawn for linux compiling
CompilerBusy = 1
EndProcedure
Procedure HideCompilerWindow()
; In build window mode, ignore the hide call on errors
If UseProjectBuildWindow = 0
If IsWindow(#WINDOW_Compiler)
CloseWindow(#WINDOW_Compiler)
DisableMenuItem(#MENU, #MENU_CreateExecutable, 0)
DisableMenuAndToolbarItem(#MENU_CompileRun, 0)
DisableMenuAndToolbarItem(#MENU_SyntaxCheck, 0)
EndIf
; re-enable the main window
DisableWindow(#WINDOW_Main, 0)
FlushEvents()
EndIf
CompilerBusy = 0
EndProcedure
Procedure CompilerWindowEvents(EventID)
If EventID = #PB_Event_Gadget
If EventGadget() = #GADGET_Compiler_Details
ShowCompilerProgress = GetGadgetState(#GADGET_Compiler_Details)
If ShowCompilerProgress
ResizeWindow(#WINDOW_Compiler, #PB_Ignore, #PB_Ignore, #PB_Ignore, CompilerWindowBig)
Else
ResizeWindow(#WINDOW_Compiler, #PB_Ignore, #PB_Ignore, #PB_Ignore, CompilerWindowSmall)
EndIf
ElseIf EventGadget() = #GADGET_Compiler_Abort
; set the flag, the rest is done from the Compiler_HandleCompilerResponse() (CompilerInterface.pb)
CompilationAborted = #True
EndIf
EndIf
EndProcedure
;- ------------------------------------------------
Procedure BuildLogEntry(Message$, InfoIndex = -1)
If UseProjectBuildWindow And BuildWindowDialog
Index = CountGadgetItems(#GADGET_Build_Log)
AddGadgetItem(#GADGET_Build_Log, Index, Message$)
SetGadgetItemData(#GADGET_Build_Log, Index, InfoIndex)
SetGadgetState(#GADGET_Build_Log, Index)
EndIf
EndProcedure
; Mode = 0: build target to OutputFile$
; Mode = 1: open requester to ask for output file (on SpiderBasic, the same as Mode 0)
; Mode = 2: build target to temporary exe
;
; Returns: success/failure
;
Procedure.s BuildProjectTarget(*Target.CompileTarget, Mode, CreateExe, CheckSyntax)
Protected OutputFile$
Protected Success = #False
; check if there is an input file for this target
If *Target\MainFile$ = ""
If CommandlineBuild
PrintN(LanguagePattern("Compiler", "NoInputFile", "%target%", *Target\Name$))
ElseIf UseProjectBuildWindow
BuildLogEntry(LanguagePattern("Compiler", "NoInputFile", "%target%", *Target\Name$))
Else
MessageRequester(#ProductName$, LanguagePattern("Compiler", "NoInputFile", "%target%", *Target\Name$), #FLAG_Error)
EndIf
ProcedureReturn ""
EndIf
*Target\FileName$ = ResolveRelativePath(GetPathPart(ProjectFile$), *Target\MainFile$)
If AutoSave And CommandlineBuild = 0
AutoSave()
EndIf
CompilerIf #SpiderBasic
If Mode = 1 : Mode = 0 : EndIf ; Mode 1 doesn't exists in SpiderBasic
CompilerEndIf
If Mode = 0 ; use fixed file
CompilerIf #SpiderBasic
If *Target\AppFormat = #AppFormatiOS
TargetOutputFile$ = *Target\iOSAppOutput$
ElseIf *Target\AppFormat = #AppFormatAndroid
TargetOutputFile$ = *Target\AndroidAppOutput$
Else
TargetOutputFile$ = *Target\HtmlFilename$
EndIf
CompilerElse
TargetOutputFile$ = *Target\OutputFile$
CompilerEndIf
If TargetOutputFile$ = ""
If CommandlineBuild
PrintN(LanguagePattern("Compiler", "NoOutputFile", "%target%", *Target\Name$))
ElseIf UseProjectBuildWindow
BuildLogEntry(LanguagePattern("Compiler", "NoOutputFile", "%target%", *Target\Name$))
Else
MessageRequester(#ProductName$, LanguagePattern("Compiler", "NoOutputFile", "%target%", *Target\Name$), #FLAG_Error)
EndIf
ProcedureReturn ""
Else
OutputFile$ = ResolveRelativePath(GetPathPart(ProjectFile$), TargetOutputFile$) ; this is relative
EndIf
; set this for later use and tools
*Target\ExecutableName$ = OutputFile$
ElseIf Mode = 1 ; ask for file
If *Target\OutputFile$
Path$ = ResolveRelativePath(GetPathPart(ProjectFile$), *Target\OutputFile$) ; this is relative
ElseIf *Target\ExecutableName$ ; last compiled exe
Path$ = *Target\ExecutableName$ ; this is full path
Else
Path$ = GetPathPart(ProjectFile$)
EndIf
If *Target\ExecutableFormat = 2 ; shared dll
CompilerIf #CompileWindows
Pattern$ = Language("Compiler","DllPattern")
Extension$ = ".dll"
CompilerElseIf #CompileMac
Pattern$ = "Shared Library (*.dylib)|*.dylib|All Files (*.*)|*.*"
Extension$ = ".dylib"
CompilerElse ; Linux
Pattern$ = "Shared Library (*.so)|*.so|All Files (*.*)|*.*"
Extension$ = ".so"
CompilerEndIf
Else
CompilerIf #CompileWindows
Pattern$ = Language("Compiler","ExePattern")
Extension$ = ".exe"
CompilerElseIf #CompileMac
Pattern$ = ""
If *Target\ExecutableFormat <> 1 ; console
Extension$ = ".app"
Else
Extension$ = ""
EndIf
CompilerElse ; Linux
Pattern$ = ""
Extension$ = ""
CompilerEndIf
EndIf
OutputFile$ = SaveFileRequester(Language("Compiler","CreateExe"), Path$, Pattern$, 0)
If OutputFile$ = ""
ProcedureReturn ""
EndIf
If LCase(Right(OutputFile$, Len(Extension$))) <> Extension$ And SelectedFilePattern() <> 1
OutputFile$+Extension$
EndIf
; set this for later use and tools
*Target\ExecutableName$ = OutputFile$
Else ; use temp file
OutputFile$ = Compiler_TemporaryFilename(*Target)
EndIf
CompilerIf #Demo
If *Target\ExecutableFormat = 2 ; shared dll
CompilerIf #CompileWindows
Message$ = "DLL creation is not available in the demo version."
CompilerElse
Message$ = "SO Library creation is not available in the demo version."
CompilerEndIf
If CommandlineBuild
PrintN(Message$)
ElseIf UseProjectBuildWindow
BuildLogEntry(Message$)
Else
MessageRequester("Information", Message$, #FLAG_Info)
EndIf
Else
CompilerEndIf
; for the addtools, we need a temporary file, so they can modify it...
If CopyFile(*Target\FileName$, TempPath$ + "PB_EditorOutput.pb")
CompilerIf #CompileWindows
; If the source file was readonly, so will be the temp file, so remove that!
SetFileAttributes(TempPath$ + "PB_EditorOutput.pb", GetFileAttributes(TempPath$ + "PB_EditorOutput.pb") & ~#PB_FileSystem_ReadOnly)
CompilerEndIf
; append the procects settings for the tools if needed
If SaveProjectSettings <> 0 And OpenFile(#FILE_SaveSource, TempPath$+"PB_EditorOutput.pb")
FileSeek(#FILE_SaveSource, Lof(#FILE_SaveSource)) ; to to the end of the file
SaveProjectSettings(*Target, #True, 1, 0)
CloseFile(#FILE_SaveSource)
EndIf
AddTools_CompiledFile$ = TempPath$ + "PB_EditorOutput.pb"; save for AddTools
If CreateExe
AddTools_Execute(#TRIGGER_BeforeCreateExe, *Target)
Else
AddTools_Execute(#TRIGGER_BeforeCompile, *Target)
EndIf
If UseProjectBuildWindow = 0 And CommandlineBuild = 0
DisplayCompilerWindow() ; hiding this window is done by the compiler functions if there is no error
EndIf
Success = Compiler_BuildTarget(TempPath$ + "PB_EditorOutput.pb", OutputFile$, *Target, CreateExe, CheckSyntax)
Else
; copy failed, just fallback and use the original file
; the most probable cause for this is that the source did not exist. this will raise a compiler error later
;
AddTools_CompiledFile$ = ""; no temporary file available
If CreateExe
AddTools_Execute(#TRIGGER_BeforeCreateExe, *Target)
Else
AddTools_Execute(#TRIGGER_BeforeCompile, *Target)
EndIf
If UseProjectBuildWindow = 0 And CommandlineBuild = 0
DisplayCompilerWindow() ; hiding this window is done by the compiler functions if there is no error
EndIf
Success = Compiler_BuildTarget(*Target\Filename$, OutputFile$, *Target, CreateExe, CheckSyntax)
EndIf
CompilerIf #Demo : EndIf : CompilerEndIf
If Success
ProcedureReturn OutputFile$
Else
ProcedureReturn ""
EndIf
EndProcedure
Procedure BuildWindowEvents(EventID)
Quit = 0
If EventID = #PB_Event_Menu ; Little wrapper to map the shortcut events (identified as menu)
EventID = #PB_Event_Gadget ; to normal gadget events...
GadgetID = EventMenu()
Else
GadgetID = EventGadget()
EndIf
If EventID = #PB_Event_Gadget
Select EventGadget()
Case #GADGET_Build_Targets
Case #GADGET_Build_Log
If EventType() = #PB_EventType_LeftDoubleClick
Index = GetGadgetState(#GADGET_Build_Log)
If Index <> -1
InfoIndex = GetGadgetItemData(#GADGET_Build_Log, Index)
If InfoIndex <> -1 And SelectElement(BuildInfo(), InfoIndex)
; will simply switch if the file is open already
If LoadSourceFile(BuildInfo()\File$)
ChangeActiveLine(BuildInfo()\Line, -5)
SetSelection(BuildInfo()\Line, 1, BuildInfo()\Line, -1)
EndIf
EndIf
EndIf
EndIf
Case #GADGET_Build_Abort
; set the flag, the rest is done from the Compiler_HandleCompilerResponse()
CompilationAborted = #True
Case #GADGET_Build_Copy
Content$ = ""
Count = CountGadgetItems(#GADGET_Build_Log)
For i = 0 To Count-1
Content$ + GetGadgetItemText(#GADGET_Build_Log, i, 0) + #NewLine
Next i
SetClipboardText(Content$)
Case #GADGET_Build_Save
FileName$ = GetPathPart(ProjectFile$)
Pattern = 0
Repeat
FileName$ = SaveFileRequester(Language("Debugger","SaveFileTitle"), FileName$, Language("Debugger","SaveFilePattern"), Pattern)
Pattern = SelectedFilePattern()
If FileName$ = ""
Break
ElseIf Pattern = 0 And GetExtensionPart(FileName$) = ""
FileName$ + ".txt"
EndIf
If FileSize(FileName$) <> -1
result = MessageRequester(#ProductName$,Language("FileStuff","FileExists")+#NewLine+Language("FileStuff","OverWrite"), #FLAG_Warning|#PB_MessageRequester_YesNoCancel)
If result = #PB_MessageRequester_Cancel
Break ; abort
ElseIf result = #PB_MessageRequester_No
Continue ; ask again
EndIf
EndIf
File = CreateFile(#PB_Any, FileName$)
If File
Count = CountGadgetItems(#GADGET_Build_Log)
For i = 0 To Count-1
WriteStringN(File, GetGadgetItemText(#GADGET_Build_Log, i, 0))
Next i
CloseFile(File)
Else
MessageRequester(#ProductName$,LanguagePattern("Debugger","SaveError", "%filename%", FileName$), #FLAG_Error)
EndIf
Break ; if we got here, then do not try again
ForEver
Case #GADGET_Build_Close
; CompilerBusy goes to 0 after each target
; UseProjectBuildWindow goes to 0 when all are done
If (Not CompilerBusy) And (Not UseProjectBuildWindow)
Quit = 1
EndIf
EndSelect
ElseIf EventID = #PB_Event_SizeWindow
BuildWindowDialog\SizeUpdate()
ElseIf EventID = #PB_Event_CloseWindow
; we have no systemmenu, but this can be sent by code to close the window
Quit = 1
EndIf
If Quit
AutoCloseBuildWindow = GetGadgetState(#GADGET_Build_CloseWhenDone)
If MemorizeWindow
BuildWindowDialog\Close(@BuildWindowPosition)
Else
BuildWindowDialog\Close()
EndIf
BuildWindowDialog = 0
EndIf
EndProcedure
Procedure UpdateBuildWindow()
; theme update
Count = CountGadgetItems(#GADGET_Build_Targets)
For i = 0 To Count-1
Select GetGadgetItemData(#GADGET_Build_Targets, i)
Case 0: SetGadgetItemImage(#GADGET_Build_Targets, i, ImageID(#IMAGE_Build_TargetNotDone))
Case 1: SetGadgetItemImage(#GADGET_Build_Targets, i, ImageID(#IMAGE_Build_TargetError))
Case 2: SetGadgetItemImage(#GADGET_Build_Targets, i, ImageID(#IMAGE_Build_TargetWarning))
Case 3: SetGadgetItemImage(#GADGET_Build_Targets, i, ImageID(#IMAGE_Build_TargetOK))
EndSelect
Next i
BuildWindowDialog\LanguageUpdate()
BuildWindowDialog\GuiUpdate()
EndProcedure
Procedure OpenBuildWindow(List *Targets.CompileTarget())
; hide the windows from the normal mode compiling
;
HideCompilerWarnings()
If IsWindow(#WINDOW_MacroError)
MacroErrorWindowEvents(#PB_Event_CloseWindow)
EndIf
If IsWindow(#WINDOW_Option)
OptionWindowEvents(#PB_Event_CloseWindow)
EndIf
If IsWindow(#WINDOW_Build) = 0
BuildWindowDialog = OpenDialog(?Dialog_Build, WindowID(#WINDOW_Main), @BuildWindowPosition)
SetGadgetState(#GADGET_Build_CloseWhenDone, AutoCloseBuildWindow)
CompilerIf #CompileWindows
; it looks just much better this way
SetGadgetFont(#GADGET_Build_Log, GetStockObject_(#ANSI_FIXED_FONT))
CompilerEndIf
Else
ClearGadgetItems(#GADGET_Build_Targets)
ClearGadgetItems(#GADGET_Build_Log)
HideGadget(#GADGET_Build_DoneContainer, 1)
HideGadget(#GADGET_Build_WorkContainer, 0)
SetWindowForeground(#WINDOW_Build)
EndIf
EnsureWindowOnDesktop(#WINDOW_Build)
ForEach *Targets()
AddGadgetItem(#GADGET_Build_Targets, -1, *Targets()\Name$+Chr(10)+"-", ImageID(#IMAGE_Build_TargetNotDone))
Next *Targets()
; During the build process, disable the main window so the user cannot initiate another compile etc
;
DisableWindow(#WINDOW_Main, #True)
; This causes the compile functions to output to our build window
;
UseProjectBuildWindow = #True
CompilerBusy = 1
ClearList(BuildInfo())
OldWarningCount = 0
SuccessCount = 0
FailCount = 0
ForEach *Targets()
BuildLogEntry(RSet("", 80, "-"))
BuildLogEntry(" " + LanguagePattern("Compiler","BuildStart", "%target%", *Targets()\Name$))
BuildLogEntry(RSet("", 80, "-"))
SetGadgetState(#GADGET_Build_Targets, ListIndex(*Targets()))
Result$ = BuildProjectTarget(*Targets(), 0, #True, #False)
; count the emitted warnings during this compile
WarningCount = 0
ForEach BuildInfo()
If BuildInfo()\IsWarning
WarningCount + 1
EndIf
Next BuildInfo()
If Result$ <> "" And WarningCount = OldWarningCount
; Failures are logged as errors and warnings give a "success with warnings" line, so add a line for success here too
; do this before executing the tools for a consistent log output
BuildLogEntry(Language("Compiler","BuildSuccess"))
EndIf
; Update the target's build counts and execute any tools
If Result$ <> ""
If *Targets()\UseCompileCount ; this increases both compile+build count
*Targets()\CompileCount + 1
EndIf
If *Targets()\UseBuildCount
*Targets()\BuildCount + 1
EndIf
AddTools_ExecutableName$ = Result$
AddTools_Execute(#TRIGGER_AfterCreateExe, *Targets())
EndIf
Index = ListIndex(*Targets())
If Result$ = ""
SetGadgetItemText(#GADGET_Build_Targets, Index, Language("Compiler","StatusError"), 1)
SetGadgetItemImage(#GADGET_Build_Targets, Index, ImageID(#IMAGE_Build_TargetError))
SetGadgetItemData(#GADGET_Build_Targets, Index, 1) ; for UpdateBuildWindow()
FailCount + 1
ElseIf WarningCount > OldWarningCount
SetGadgetItemText(#GADGET_Build_Targets, Index, LanguagePattern("Compiler","StatusWarning", "%count%", Str(WarningCount - OldWarningCount)), 1)
SetGadgetItemImage(#GADGET_Build_Targets, Index, ImageID(#IMAGE_Build_TargetWarning))
SetGadgetItemData(#GADGET_Build_Targets, Index, 2)
SuccessCount + 1 ; this is a success too
Else
SetGadgetItemText(#GADGET_Build_Targets, Index, Language("Compiler","StatusOk"), 1)
SetGadgetItemImage(#GADGET_Build_Targets, Index, ImageID(#IMAGE_Build_TargetOK))
SetGadgetItemData(#GADGET_Build_Targets, Index, 3)
SuccessCount + 1
EndIf
OldWarningCount = WarningCount
BuildLogEntry("")
If CompilationAborted
Break
EndIf
Next *Targets()
; Display some stats
;
BuildLogEntry(RSet("", 80, "-"))
BuildLogEntry("")
If SuccessCount > 0
BuildLogEntry(" " + LanguagePattern("Compiler", "BuildStatsNoError", "%count%", Str(SuccessCount)))
EndIf
If FailCount > 0
BuildLogEntry(" " + LanguagePattern("Compiler", "BuildStatsError", "%count%", Str(FailCount)))
EndIf
If WarningCount > 0
BuildLogEntry(" " + LanguagePattern("Compiler", "BuildStatsWarning", "%count%", Str(WarningCount)))
EndIf
If CompilationAborted
BuildLogEntry(" " + Language("Compiler","BuildStatsAborted"))
EndIf
BuildLogEntry("")
; Compiling is done, enable the main window again
;
DisableWindow(#WINDOW_Main, #False)
CompilerBusy = 0
UseProjectBuildWindow = #False
UpdateProjectInfo() ; reflect build count change in project info
If GetGadgetState(#GADGET_Build_CloseWhenDone) And FailCount = 0
BuildWindowEvents(#PB_Event_CloseWindow)
Else
; Go to "finished mode"
HideGadget(#GADGET_Build_WorkContainer, 1)
HideGadget(#GADGET_Build_DoneContainer, 0)
SetGadgetState(#GADGET_Build_Targets, -1)
SetGadgetState(#GADGET_Build_Log, -1)
EndIf
EndProcedure
;- ------------------------------------------------
Procedure CompileRun(CheckSyntax)
UseProjectBuildWindow = #False
If *ActiveSource\IsCode = 0
ProcedureReturn
EndIf
If CompilerReady And CompilerBusy = 0
If AutoClearLog
ClearGadgetItems(#GADGET_ErrorLog)
*ActiveSource\LogSize = 0
SetDebuggerMenuStates()
EndIf
ClearList(CompileSource\UnknownIDEOptionsList$())
If AutoSave
AutoSave() ; do the autosave stuff
EndIf
If *ActiveSource\UseMainFile
; make sure the compile source is clean and does not have settings from a previous compile
ClearStructure(@CompileSource, SourceFile)
InitializeStructure (@CompileSource, SourceFile) ; We use complex type in this structure like 'List' so we need to reinit again
; create a new SourceFile structure to represent the MainFile settings
; the CompileSource structure is global for the Windows compiler to access it too
;
CompileSource\FileName$ = ResolveRelativePath(GetPathPart(*ActiveSource\FileName$), *ActiveSource\MainFile$)
If ReadFile(#FILE_Compile, CompileSource\FileName$)
If Lof(#FILE_Compile) < 5000
Length = Lof(#FILE_Compile)
Else
Length = 5000
FileSeek(#FILE_Compile, Lof(#FILE_Compile)-5000)
EndIf
*Buffer = AllocateMemory(Length+10) ; we only need the project settings.. (+10 to avoid error on empty files for 0-size alloc!)
If *Buffer
ReadData(#FILE_Compile, *Buffer, Length)
CloseFile(#FILE_Compile)
AnalyzeProjectSettings(@CompileSource, *Buffer, Length, 0)
FreeMemory(*Buffer)
CompileSource\Debugger = *ActiveSource\Debugger ; these are set by the current file
CompileSource\CommandLine$ = *ActiveSource\CommandLine$
CompileSource\FileName$ = ResolveRelativePath(GetPathPart(*ActiveSource\FileName$), *ActiveSource\MainFile$) ; this is important to compile from the right directory
Success = #False
; for the addtools, we need a temporary file, so they can modify it...
If CopyFile(CompileSource\FileName$, TempPath$ + "PB_EditorOutput.pb")
CompilerIf #CompileWindows
; If the source file was readonly, so will be the temp file, so remove that!
SetFileAttributes(TempPath$ + "PB_EditorOutput.pb", GetFileAttributes(TempPath$ + "PB_EditorOutput.pb") & ~#PB_FileSystem_ReadOnly)
CompilerEndIf
; append the procects settings for the tools if needed
If SaveProjectSettings <> 0 And OpenFile(#FILE_SaveSource, TempPath$+"PB_EditorOutput.pb")
FileSeek(#FILE_SaveSource, Lof(#FILE_SaveSource)) ; to to the end of the file
SaveProjectSettings(@CompileSource, #True, 1, 0)
CloseFile(#FILE_SaveSource)
EndIf
; call the compiler function with this new structure and main source name
AddTools_CompiledFile$ = TempPath$ + "PB_EditorOutput.pb"; save for AddTools
AddTools_Execute(#TRIGGER_BeforeCompile, *ActiveSource)
DisplayCompilerWindow() ; hiding this window is done by the compiler functions if there is no error
Success = Compiler_CompileRun(TempPath$ + "PB_EditorOutput.pb", @CompileSource, CheckSyntax)
Else
; call the compiler function with this new structure and main source name
AddTools_CompiledFile$ = ""; no temporary file available
AddTools_Execute(#TRIGGER_BeforeCompile, *ActiveSource)
DisplayCompilerWindow() ; hiding this window is done by the compiler functions if there is no error
Success = Compiler_CompileRun(CompileSource\FileName$, @CompileSource, CheckSyntax)
EndIf
; update the build counter for this main file.
; This can be tricky as the file may not be loaded in the IDE at this time.
;
If Success And CompileSource\UseCompileCount And CheckSyntax = #False
; first check if this source is loaded in the IDE
IsLoaded = 0
*RealActiveSource = *ActiveSource ; *ActiveSource is modified below as well!
ForEach FileList()
If @FileList() <> *ProjectInfo And IsEqualFile(FileList()\FileName$, CompileSource\FileName$)
IsLoaded = 1
FileList()\CompileCount + 1
If AutoSave And AutoSaveAll ; as it is not the active source, only save With "autosave all" on
*ActiveSource = @FileList() ; must be done for the SaveSourceFile() !
SaveSourceFile(*ActiveSource\FileName$)
HistoryEvent(*ActiveSource, #HISTORY_Save)
Else
; mark as modified (do manually as the function is only for *ActiveSource
FileList()\ScintillaModified = 1
FileList()\DisplayModified = 1
SetTabBarGadgetItemText(#GADGET_FilesPanel, ListIndex(FileList()), GetFilePart(CompileSource\FileName$)+"*")
EndIf
Break
EndIf
Next FileList()
ChangeCurrentElement(FileList(), *RealActiveSource)
*ActiveSource = *RealActiveSource
; ok, we have to update the file on disk
; Note: SaveProjectSettings() actually works if we do not append the options to the source,
; but some settings are lost (folding, currentline etc) as the source is not shown,
; so we do not use it as it may be annoying to lose this data often.
;
; Note: do not report errors, as the media could be readonly and we do not want to annoy the user then on each compile
;
If IsLoaded = 0
NewCount = CompileSource\CompileCount + 1
Select SaveProjectSettings
Case 0 ; end of source
*Buffer = 0
If ReadFile(#FILE_ReadConfig, CompileSource\FileName$)
Length = Lof(#FILE_ReadConfig)
*Buffer = AllocateMemory(Length+10) ; avoid the 0size-buffer problem
If *Buffer
ReadData(#FILE_ReadConfig, *Buffer, Length)
EndIf
CloseFile(#FILE_ReadConfig)
EndIf
If *Buffer
Select DetectNewLineType(*Buffer, Length)
Case 0: NewLine$ = Chr(13)+Chr(10)
Case 1: NewLine$ = Chr(10)
Case 2: NewLine$ = Chr(13)
EndSelect
*Cursor.BYTE = *Buffer
IsCorrectSection = 0
Lookup$ = NewLine$ + "; IDE Options"
LookupLength = Len(Lookup$)
While *Cursor < *Buffer + Length
If CompareMemoryString(*Cursor, ToAscii(Lookup$), 0, LookupLength) = 0 ; this is case sensitive!
IsCorrectSection = 1
ElseIf IsCorrectSection And CompareMemoryString(*Cursor, ToAscii("EnableCompileCount"), 1, 18) = 0
*Start = *Cursor
While *Cursor < *Buffer + Length And *Cursor\b <> 10 And *Cursor\b <> 13
*Cursor + 1
Wend
; now we can directly write the new file
If CreateFile(#FILE_SaveConfig, CompileSource\FileName$)
WriteData(#FILE_SaveConfig, *Buffer, *Start-*Buffer)
WriteString(#FILE_SaveConfig, "EnableCompileCount = " + Str(NewCount)); no newline as we write it with the last block!
WriteData(#FILE_SaveConfig, *Cursor, Length - (*Cursor-*Buffer))
CloseFile(#FILE_SaveConfig)
EndIf
EndIf
*Cursor + 1
Wend
FreeMemory(*Buffer)
EndIf
Case 1 ; filename.pb.cfg
Success = 0
If ReadFile(#FILE_ReadConfig, CompileSource\FileName$+".cfg")
If CreateFile(#FILE_SaveConfig, CompileSource\FileName$+".cfg.new")
While Not Eof(#FILE_ReadConfig)
Line$ = ReadString(#FILE_ReadConfig)
If FindString(UCase(Line$), "ENABLECOMPILECOUNT", 1) <> 0
Line$ = "EnableCompileCount = " + Str(NewCount)
Success = 1
EndIf
If Eof(#FILE_ReadConfig)
WriteString(#FILE_SaveConfig, Line$) ; no newline at the end
Else
WriteStringN(#FILE_SaveConfig, Line$)
EndIf
Wend
CloseFile(#FILE_SaveConfig)
EndIf
CloseFile(#FILE_ReadConfig)
EndIf
If Success And DeleteFile(CompileSource\FileName$+".cfg")
RenameFile(CompileSource\FileName$+".cfg.new", CompileSource\FileName$+".cfg")
Else
DeleteFile(CompileSource\FileName$+".cfg.new")
EndIf
Case 2 ; project.cfg
Success = 0
IsCorrectSection = 0
If ReadFile(#FILE_ReadConfig, GetPathPart(CompileSource\FileName$)+"project.cfg")
If CreateFile(#FILE_SaveConfig, GetPathPart(CompileSource\FileName$)+"project.cfg.new")
While Not Eof(#FILE_ReadConfig)
Line$ = ReadString(#FILE_ReadConfig)
If UCase(Trim(Line$)) = "["+UCase(GetFilePart(CompileSource\FileName$))+"]"
IsCorrectSection = 1
ElseIf Left(Trim(Line$), 1) = "["
IsCorrectSection = 0
ElseIf IsCorrectSection And FindString(UCase(Line$), "ENABLECOMPILECOUNT", 1) <> 0
Line$ = " EnableCompileCount = " + Str(NewCount)
Success = 1