diff --git a/src/ce_cdbcmd.pas b/src/ce_cdbcmd.pas index 08d364d2..4dd230b5 100644 --- a/src/ce_cdbcmd.pas +++ b/src/ce_cdbcmd.pas @@ -55,7 +55,10 @@ begin inherited; Enabled := exeInSysPath('cdb'); if Enabled then + begin EntitiesConnector.addObserver(self); + EntitiesConnector.endUpdate; + end; end; destructor TCECdbWidget.destroy; diff --git a/src/ce_editor.pas b/src/ce_editor.pas index 4b8eef1f..bee557eb 100644 --- a/src/ce_editor.pas +++ b/src/ce_editor.pas @@ -101,6 +101,7 @@ begin end; // EntitiesConnector.addObserver(self); + EntitiesConnector.endUpdate; end; destructor TCEEditorWidget.destroy; diff --git a/src/ce_main.pas b/src/ce_main.pas index 6706b9e3..0191818b 100644 --- a/src/ce_main.pas +++ b/src/ce_main.pas @@ -316,6 +316,8 @@ begin newProj; checkCompilo; getCMdParams; + // + EntitiesConnector.endUpdate; end; procedure TCEMainForm.checkCompilo; @@ -723,9 +725,10 @@ end; procedure TCEMainForm.ApplicationProperties1Exception(Sender: TObject;E: Exception); begin - //if fMesgWidg = nil then - //ce_common.dlgOkError(E.Message) - //else fMesgWidg.addCeErr(E.Message); + if fMesgWidg = nil then + ce_common.dlgOkError(E.Message) + else + fMesgWidg.lmStandard(E.Message, nil, amcApp, amkErr); end; procedure TCEMainForm.FormCloseQuery(Sender: TObject; var CanClose: boolean); diff --git a/src/ce_messages.pas b/src/ce_messages.pas index 091c47e4..97cd9140 100644 --- a/src/ce_messages.pas +++ b/src/ce_messages.pas @@ -148,6 +148,7 @@ begin btnSelAll.OnClick := @selCtxtClick; // EntitiesConnector.addObserver(self); + EntitiesConnector.endUpdate; end; destructor TCEMessagesWidget.destroy; @@ -317,8 +318,10 @@ end; procedure TCEMessagesWidget.projClosing(const aProject: TCEProject); begin - if fProj = aProject then - lmClearByData(@fProj); + if fProj <> aProject then + exit; + // + lmClearByData(aProject); fProj := nil; filterMessages(fCtxt); end; @@ -388,17 +391,17 @@ begin if not (poUsePipes in aValue.Options) then exit; // - aValue.Tag := (Byte(aCtxt) << 8) + Byte(aKind); + aValue.Tag := (Byte(aCtxt) shl 8) + Byte(aKind); // if (aValue is TAsyncProcess) then begin TAsyncProcess(aValue).OnReadData := @processOutput; TAsyncProcess(aValue).OnTerminate := @processTerminate; end; - // always process message: a TAsyncProcess may be already terminated. + if aValue.Output = nil then + exit; + // always process messages: a TAsyncProcess may be already terminated. logProcessOutput(aValue); - // - Application.ProcessMessages; end; procedure TCEMessagesWidget.processOutput(Sender: TObject); @@ -425,6 +428,7 @@ begin finally lst.Free; Application.ProcessMessages; + filterMessages(fCtxt); end; end; @@ -456,7 +460,7 @@ begin for i := List.Items.Count-1 downto 0 do begin msgdt := PMessageData(List.Items[i].Data); - if (msgdt^.data = aData) or (msgdt^.data = Pointer(aData^)) then + if (msgdt^.data = aData) then List.Items.Delete(List.Items[i]); end; end; @@ -520,11 +524,8 @@ begin continue; end else case msgdt^.ctxt of - // PMessageData.data can be either a reference or a pointer - amcEdit: itm.Visible := ((fDoc = TCESynMemo(msgdt^.data)) or (fDoc = TCESynMemo(msgdt^.data^))) - and (aCtxt = amcEdit); - amcProj: itm.Visible := ((fProj = TCEProject(msgdt^.data)) or (fProj = TCEProject(msgdt^.data^))) - and (aCtxt = amcProj); + amcEdit: itm.Visible := (fDoc = TCESynMemo(msgdt^.data)) and (aCtxt = amcEdit); + amcProj: itm.Visible := (fProj = TCEProject(msgdt^.data)) and (aCtxt = amcProj); amcApp: itm.Visible := aCtxt = amcApp; amcMisc: itm.Visible := aCtxt = amcMisc; end; diff --git a/src/ce_projconf.pas b/src/ce_projconf.pas index e9937e8b..c89e956f 100644 --- a/src/ce_projconf.pas +++ b/src/ce_projconf.pas @@ -52,6 +52,7 @@ begin Grid.OnEditorFilter := @GridFilter; // EntitiesConnector.addObserver(self); + EntitiesConnector.endUpdate; end; destructor TCEProjectConfigurationWidget.destroy; diff --git a/src/ce_project.pas b/src/ce_project.pas index 262cc4cf..e348fde5 100644 --- a/src/ce_project.pas +++ b/src/ce_project.pas @@ -47,6 +47,10 @@ type function getCurrConf: TCompilerConfiguration; function runPrePostProcess(const processInfo: TCompileProcOptions): Boolean; function getCanBeRun: boolean; + // passes pre/post/executed project/ outputs as bubles. + procedure runProcOutput(sender: TObject); + // passes compilation message as "to be guessed" + procedure compProcOutput(proc: TProcess); protected procedure afterSave; override; procedure afterLoad; override; @@ -91,6 +95,7 @@ uses constructor TCEProject.create(aOwner: TComponent); begin inherited create(aOwner); + // fLogMessager := TCELogMessageSubject.create; fProjectSubject := TCEProjectSubject.create; // @@ -102,6 +107,7 @@ begin // reset; addDefaults; + subjProjNew(TCEProjectSubject(fProjectSubject), self); subjProjChanged(TCEProjectSubject(fProjectSubject), self); // fModified := false; @@ -118,6 +124,7 @@ begin fSrcs.free; fSrcsCop.Free; fOptsColl.free; + killProcess(fRunner); inherited; end; @@ -476,13 +483,73 @@ begin while process.Running do if not (poWaitOnExit in process.Options) then if poUsePipes in process.Options then - subjLmProcess(TCELogMessageSubject(fLogMessager), process, @Self, amcProj, amkBub); + runProcOutput(process); finally result := process.ExitStatus = 0; process.Free; end; end; +function TCEProject.compileProject: Boolean; +var + config: TCompilerConfiguration; + compilproc: TProcess; + olddir, prjpath: string; + prjname: string; +begin + result := false; + config := currentConfiguration; + if config = nil then + begin + subjLmStandard(TCELogMessageSubject(fLogMessager), + 'unexpected project error: no active configuration', Self, amcProj, amkErr); + exit; + end; + // + subjLmClearByData(TCELogMessageSubject(fLogMessager), Self); + // + if not runPrePostProcess(config.preBuildProcess) then + subjLmStandard(TCELogMessageSubject(fLogMessager), + 'project warning: the pre-compilation process has not been properly executed', Self, amcProj, amkWarn); + // + prjname := shortenPath(filename, 25); + compilproc := TProcess.Create(nil); + olddir := ''; + getDir(0, olddir); + try + subjLmStandard(TCELogMessageSubject(fLogMessager), + 'compiling ' + prjname, Self, amcProj, amkInf); + prjpath := extractFilePath(fileName); + if directoryExists(prjpath) then + begin + chDir(prjpath); + compilproc.CurrentDirectory := prjpath; + end; + compilproc.Executable := DCompiler; + compilproc.Options := compilproc.Options + [poStderrToOutPut, poUsePipes]; + compilproc.ShowWindow := swoHIDE; + getOpts(compilproc.Parameters); + compilproc.Execute; + while compilProc.Running do + compProcOutput(compilproc); + if compilproc.ExitStatus = 0 then begin + subjLmStandard(TCELogMessageSubject(fLogMessager), + prjname + ' has been successfully compiled', Self, amcProj, amkInf); + result := true; + end else + subjLmStandard(TCELogMessageSubject(fLogMessager), + prjname + ' has not been compiled', Self, amcProj, amkWarn); + + if not runPrePostProcess(config.PostBuildProcess) then + subjLmStandard(TCELogMessageSubject(fLogMessager), + 'project warning: the post-compilation process has not been properly executed', Self, amcProj, amkWarn); + + finally + compilproc.Free; + chDir(olddir); + end; +end; + function TCEProject.runProject(const runArgs: string = ''): Boolean; var prm: string; @@ -506,74 +573,53 @@ begin if not fileExists(outputFilename) then begin subjLmStandard(TCELogMessageSubject(fLogMessager), - 'output executable missing: ' + shortenPath(outputFilename,25), @Self, amcProj, amkErr); + 'output executable missing: ' + shortenPath(outputFilename, 25), Self, amcProj, amkErr); exit; end; // fRunner.Executable := outputFilename; if fRunner.CurrentDirectory = '' then fRunner.CurrentDirectory := extractFilePath(fRunner.Executable); - subjLmProcess(TCELogMessageSubject(fLogMessager), fRunner, @Self, amcProj, amkBub); + if poUsePipes in fRunner.Options then begin + fRunner.OnReadData := @runProcOutput; + fRunner.OnTerminate := @runProcOutput; + end; fRunner.Execute; // result := true; end; -function TCEProject.compileProject: Boolean; +procedure TCEProject.runProcOutput(sender: TObject); var - config: TCompilerConfiguration; - compilproc: TProcess; - olddir, prjpath: string; - prjname: string; + proc: TProcess; + lst: TStringList; + str: string; begin - result := false; - config := currentConfiguration; - if config = nil then - begin - subjLmStandard(TCELogMessageSubject(fLogMessager), - 'unexpected project error: no active configuration', @Self, amcProj, amkErr); - exit; - end; - // - if not runPrePostProcess(config.preBuildProcess) then - subjLmStandard(TCELogMessageSubject(fLogMessager), - 'project warning: the pre-compilation process has not been executed', @Self, amcProj, amkWarn); - // - prjname := shortenPath(filename, 25); - compilproc := TProcess.Create(nil); - olddir := ''; - getDir(0, olddir); + proc := TProcess(sender); + lst := TStringList.Create; try - subjLmStandard(TCELogMessageSubject(fLogMessager), - 'compiling ' + prjname, @Self, amcProj, amkInf); - prjpath := extractFilePath(fileName); - if directoryExists(prjpath) then - begin - chDir(prjpath); - compilproc.CurrentDirectory := prjpath; - end; - compilproc.Executable := DCompiler; - compilproc.Options := compilproc.Options + [poStderrToOutPut, poUsePipes]; - compilproc.ShowWindow := swoHIDE; - getOpts(compilproc.Parameters); - compilproc.Execute; - while compilProc.Running do - subjLmProcess(TCELogMessageSubject(fLogMessager), compilproc, @Self, amcProj, amkBub); - if compilproc.ExitStatus = 0 then begin + processOutputToStrings(proc, lst); + for str in lst do subjLmStandard(TCELogMessageSubject(fLogMessager), - prjname + ' has been successfully compiled', @Self, amcProj, amkInf); - result := true; - end else - subjLmStandard(TCELogMessageSubject(fLogMessager), - prjname + ' has not been compiled', @Self, amcProj, amkWarn); - - if not runPrePostProcess(config.PostBuildProcess) then - subjLmStandard(TCELogMessageSubject(fLogMessager), - 'project warning: the post-compilation process has not been executed', @Self, amcProj, amkWarn); - + str, Self, amcProj, amkBub); finally - compilproc.Free; - chDir(olddir); + lst.Free; + end; +end; + +procedure TCEProject.compProcOutput(proc: TProcess); +var + lst: TStringList; + str: string; +begin + lst := TStringList.Create; + try + processOutputToStrings(proc, lst); + for str in lst do + subjLmStandard(TCELogMessageSubject(fLogMessager), + str, Self, amcProj, amkAuto); + finally + lst.Free; end; end; diff --git a/src/ce_projinspect.pas b/src/ce_projinspect.pas index cfc2652b..77f6da72 100644 --- a/src/ce_projinspect.pas +++ b/src/ce_projinspect.pas @@ -83,6 +83,7 @@ begin Tree.PopupMenu := contextMenu; // EntitiesConnector.addObserver(self); + EntitiesConnector.endUpdate; end; destructor TCEProjectInspectWidget.destroy; diff --git a/src/ce_search.pas b/src/ce_search.pas index 53f9ab85..33875e0c 100644 --- a/src/ce_search.pas +++ b/src/ce_search.pas @@ -92,6 +92,7 @@ begin fReplaceMru:= TMruList.Create; // EntitiesConnector.addObserver(self); + EntitiesConnector.endUpdate; end; destructor TCESearchWidget.Destroy; diff --git a/src/ce_staticexplorer.pas b/src/ce_staticexplorer.pas index 4bee56c9..f0b480a8 100644 --- a/src/ce_staticexplorer.pas +++ b/src/ce_staticexplorer.pas @@ -129,6 +129,7 @@ begin Tree.PopupMenu := contextMenu; // EntitiesConnector.addObserver(self); + EntitiesConnector.endUpdate; end; destructor TCEStaticExplorerWidget.destroy; diff --git a/src/ce_widget.pas b/src/ce_widget.pas index eb720a6a..013ce18c 100644 --- a/src/ce_widget.pas +++ b/src/ce_widget.pas @@ -128,6 +128,7 @@ begin PopupMenu := contextMenu; EntitiesConnector.addObserver(self); + EntitiesConnector.endUpdate; end; destructor TCEWidget.destroy;