; --------------------------------------------------------------------------------------------; 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.; --------------------------------------------------------------------------------------------Global IsIDEConfigPresent ; ugly way to do this, but works. to test if the source was ever loaded by the IDEGlobal MarkerLines$; Only for ChangeActiveSourceCode() to hide the previously visible gadget,; even when *ActiveSource does not actually represent the currently visible one.; (which is done while opening a new source file);Global VisibleScintillaGadget; only needed during file loading:; as there is a UpdateCursorPosition() somewhere in the process, we cannot use; the SourceFile fields dring this timeGlobal Loading_FirstVisibleLine, Loading_CurrentLine, Loading_CurrentColumnGlobal Loading_FoldingState$Procedure UpdateCursorPosition()GetCursorPosition() ; sets the SourceFile fields also used by other functionsStartPosition = SendEditorMessage(#SCI_GETSELECTIONSTART, 0, 0)EndPosition = SendEditorMessage(#SCI_GETSELECTIONEND, 0, 0)If StartPosition = EndPositionText$ = Language("Misc","Line")+": "+Str(*ActiveSource\CurrentLine)+" "+Language("Misc","Column")+": "+Str(*ActiveSource\CurrentColumnDisplay)ElseText$ = Language("Misc","Line")+": "+Str(*ActiveSource\CurrentLine)+" "+Language("Misc","Column")+": "+Str(*ActiveSource\CurrentColumnDisplay) + " - ["+Str(CountCharacters(*ActiveSource\EditorGadget, StartPosition, EndPosition))+"]" ; Use a short 'selection' marker, or the text line+column+selection will be too big for the statusbar field (need #SCI_COUNTCHARACTERS to handle UTF8 properly)EndIfStatusBarText(#STATUSBAR, 0, Text,ドル #PB_StatusBar_Center)EndProcedureProcedure RefreshSourceTitle(*Source.SourceFile)PushListPosition(FileList())ChangeCurrentElement(FileList(), *Source)Index = ListIndex(FileList())PopListPosition(FileList())SetTabBarGadgetItemText(#GADGET_FilesPanel, Index, GetSourceTitle(*Source))If *Source = *ProjectInfoSetTabBarGadgetItemColor(#GADGET_FilesPanel, Index, #PB_Gadget_FrontColor, #COLOR_FilePanelFront)SetTabBarGadgetItemColor(#GADGET_FilesPanel, Index, #PB_Gadget_BackColor, #COLOR_ProjectInfo)ElseIf *Source\IsForm And *Source\ProjectFileSetTabBarGadgetItemColor(#GADGET_FilesPanel, Index, #PB_Gadget_FrontColor, #COLOR_FilePanelFront)SetTabBarGadgetItemColor(#GADGET_FilesPanel, Index, #PB_Gadget_BackColor, #COLOR_FormProjectFile)ElseIf *Source\IsFormSetTabBarGadgetItemColor(#GADGET_FilesPanel, Index, #PB_Gadget_FrontColor, #COLOR_FilePanelFront)SetTabBarGadgetItemColor(#GADGET_FilesPanel, Index, #PB_Gadget_BackColor, #COLOR_FormFile)ElseIf *Source\ProjectFileSetTabBarGadgetItemColor(#GADGET_FilesPanel, Index, #PB_Gadget_FrontColor, #COLOR_FilePanelFront)SetTabBarGadgetItemColor(#GADGET_FilesPanel, Index, #PB_Gadget_BackColor, #COLOR_ProjectFile)Else; MacOS ColorsCompilerIf #CompileMacSetTabBarGadgetItemColor(#GADGET_FilesPanel, Index, #PB_Gadget_FrontColor, TabBarGadgetInclude\TextColor)SetTabBarGadgetItemColor(#GADGET_FilesPanel, Index, #PB_Gadget_BackColor, TabBarGadgetInclude\FaceColor)CompilerElseIf #CompileLinuxGtkSetTabBarGadgetItemColor(#GADGET_FilesPanel, Index, #PB_Gadget_FrontColor, TabBarGadgetInclude\TextColor)SetTabBarGadgetItemColor(#GADGET_FilesPanel, Index, #PB_Gadget_BackColor, TabBarGadgetInclude\FaceColor)CompilerElseSetTabBarGadgetItemColor(#GADGET_FilesPanel, Index, #PB_Gadget_FrontColor, #COLOR_FilePanelFront)SetTabBarGadgetItemColor(#GADGET_FilesPanel, Index, #PB_Gadget_BackColor, #PB_Default)CompilerEndIfEndIfEndProcedure; get the title string for the current element in FileList()Procedure.s GetSourceTitle(*Source.SourceFile)If *Source = *ProjectInfo;Title$ = "> " + Language("Project","TabTitle")Title$ = Language("Project","TabTitle")ElseModified = GetSourceModified(*Source)If *Source\FileName$ = "" And *Source\IsFormTitle$ = Language("FileStuff","NewForm")ElseIf *Source\FileName$ = ""Title$ = Language("FileStuff","NewSource")ElseTitle$ = GetFilePart(*Source\FileName$)EndIfIf ModifiedTitle$ + "*"EndIf; If *Source\ProjectFile; Title$ = "> " + Title$; EndIfEndIfProcedureReturn Title$EndProcedureProcedure UpdateSourceStatus(Modified)If Modified = -1Modified = GetSourceModified()ElseIf Modified <> GetSourceModified()SetSourceModified(Modified)EndIf; only do an actual refresh if needed.; this procedure is called many times during folding as it seems,; so limit the number of updates if nothing changedIf Modified <> *ActiveSource\DisplayModified*ActiveSource\DisplayModified = ModifiedRefreshSourceTitle(*ActiveSource)UpdateMenuStates()EndIfEndProcedure; Note: Do not call FlushEvents() in here as this procedure is called during file loading and processing; events could change the active source again and really mess things up!;Procedure ChangeActiveSourcecode(*OldSource.SourceFile = 0)If *OldSource = 0*OldSource = *ActiveSourceEndIf; Make sure the sorted data for the old source is up to date to ensure; a quick access. Does nothing if the data is up to dateIf *OldSource And *OldSource <> *ProjectInfo And *OldSource\IsForm = 0SortParserData(*OldSource\Parser, *OldSource)EndIf; preserve procedure browser scroll positionIf ProcedureBrowserMode = 1 And *OldSource And *OldSource <> *ProjectInfo*OldSource\ProcedureBrowserScroll = GetListViewScroll(#GADGET_ProcedureBrowser)EndIfAutoComplete_Close()If *ActiveSource And IsWindow(#WINDOW_Option) ; make sure the options are closedIf (*ActiveSource <> *ProjectInfo And *ActiveSource\ProjectFile = 0) Or (@FileList() <> *ProjectInfo And FileList()\ProjectFile = 0); close only if either the old or the new code do not belong to the projectOptionWindowEvents(#PB_Event_CloseWindow)EndIfEndIfCompilerIf #SpiderBasicIf *ActiveSource And IsWindow(#WINDOW_CreateApp) ; make sure the CreateApp window is closedIf (*ActiveSource <> *ProjectInfo And *ActiveSource\ProjectFile = 0) Or (@FileList() <> *ProjectInfo And FileList()\ProjectFile = 0); close only if either the old or the new code do not belong to the projectCreateAppWindowEvents(#PB_Event_CloseWindow)EndIfEndIfCompilerEndIf*ActiveSource = @FileList()SetTabBarGadgetState(#GADGET_FilesPanel, ListIndex(FileList()))HideLineNumbers(*ActiveSource, 1-EnableLineNumbers)UpdateMainWindowTitle()ClearList(BlockSelectionStack())BlockSelectionUpdated = #FalseErrorLog_Refresh() ; always update, even if hiddenErrorLog_SyncState(#False) ; update the display stateResizeMainWindow() ; make sure the EditorGadget is correctly sizedIf *ActiveSource = *ProjectInfoEnsureListIconSelection(#GADGET_ProjectInfo_Files)HideGadget(#GADGET_ProjectInfo, 0)SetActiveGadget(#GADGET_ProjectInfo_Files)ElseIf *ProjectInfoHideGadget(#GADGET_ProjectInfo, 1)EndIfSetActiveGadget(*ActiveSource\EditorGadget)HideEditorGadget(*ActiveSource\EditorGadget, 0) ; Show only when the resize is doneCompilerIf #CompileWindows;; Some weird touchpad driver has a problem with invisible windows being on top; in the z-order, so make sure the newly visible gadget is the topmost one; This is not a PB bug, its just a compatibility hack for that driver;SetWindowPos_(GadgetID(*ActiveSource\EditorGadget), #HWND_TOP, 0, 0, 0, 0, #SWP_NOMOVE|#SWP_NOOWNERZORDER|#SWP_NOSIZE)CompilerEndIfEndIfIf *ActiveSource = *ProjectInfoIf VisibleScintillaGadgetHideEditorGadget(VisibleScintillaGadget, 1)EndIfVisibleScintillaGadget = 0Else; We hide the previous editor gadget only when the new one is displayed, to remove flickering; NOTE: While a new source is created, the actually displayed gadget is not; from *ActiveSource (to avoid some flicker), so use a special variable for this check.;If VisibleScintillaGadget And VisibleScintillaGadget <> *ActiveSource\EditorGadgetHideEditorGadget(VisibleScintillaGadget, 1)EndIfVisibleScintillaGadget = *ActiveSource\EditorGadgetEndIf; show up the canvas for form drawing it the source is actually a form otherwise hide itIf *ActiveSource\IsFormcurrentwindow = *ActiveSource\IsFormFD_SelectWindow(currentwindow)FD_UpdateObjList()redraw = 1If FormWindows()\current_view = 0HideGadget(#GADGET_Form, 0)HideEditorGadget(*ActiveSource\EditorGadget, 1)RemoveKeyboardShortcut(#WINDOW_Main, #PB_Shortcut_Return)RemoveKeyboardShortcut(#WINDOW_Main, #PB_Shortcut_Tab)RemoveKeyboardShortcut(#WINDOW_Main, #PB_Shortcut_Shift | #PB_Shortcut_Tab)ElseHideGadget(#GADGET_Form, 1)HideEditorGadget(*ActiveSource\EditorGadget, 0)SetActiveGadget(*ActiveSource\EditorGadget)FD_SelectNone()CompilerIf #CompileWindows | #CompileMac | #CompileLinuxQtAddKeyboardShortcut(#WINDOW_Main, #PB_Shortcut_Return, #MENU_Scintilla_Enter)AddKeyboardShortcut(#WINDOW_Main, #PB_Shortcut_Tab, #MENU_Scintilla_Tab)AddKeyboardShortcut(#WINDOW_Main, #PB_Shortcut_Shift | #PB_Shortcut_Tab, #MENU_Scintilla_ShiftTab)CompilerEndIfEndIfElsecurrentwindow = 0 ; no more active formCompilerIf #CompileWindows | #CompileMac | #CompileLinuxQtAddKeyboardShortcut(#WINDOW_Main, #PB_Shortcut_Return, #MENU_Scintilla_Enter)AddKeyboardShortcut(#WINDOW_Main, #PB_Shortcut_Tab, #MENU_Scintilla_Tab)AddKeyboardShortcut(#WINDOW_Main, #PB_Shortcut_Shift | #PB_Shortcut_Tab, #MENU_Scintilla_ShiftTab)CompilerEndIfFD_SelectNone()If IsGadget(#Form_PropObjList)ClearGadgetItems(#Form_PropObjList)EndIfIf IsGadget(#GADGET_Form)HideGadget(#GADGET_Form, 1)EndIfEndIfUpdateCursorPosition(); enabled the folding update again, as strangely the fold mark in first line disappears otherwise !?If *ActiveSource <> *ProjectInfo And Not *ActiveSource\IsFormFullSourceScan(*ActiveSource)UpdateFolding(*ActiveSource, 0, -1)EndIfUpdateProcedureList(*ActiveSource\ProcedureBrowserScroll) ; apply previous scroll position (if any)UpdateVariableViewer()UpdateMenuStates()SetDebuggerMenuStates(); update quickhelpIf *ActiveSource = *ProjectInfoChangeStatus("", 0)ElseIf SendEditorMessage(#SCI_GETREADONLY, 0, 0) = 0 ; do not update quickhelp when in debugger modeChangeStatus("", 0)UpdateCursorPosition()selStart = SendEditorMessage(#SCI_GETSELECTIONSTART, 0, 0)selEnd = SendEditorMessage(#SCI_GETSELECTIONEND , 0, 0)If selStart = selEndQuickHelpFromLine(*ActiveSource\CurrentLine-1, *ActiveSource\CurrentColumnChars-1)EndIfEndIfUpdateSelectionRepeat()EndProcedureProcedure NewSource(FileName,ドル ExecuteTool)*OldSource = *ActiveSourceLastElement(FileList())AddElement(FileList()); Generate a unique ID for the target in this structure;FileList()\ID = GetUniqueID()If FileName$ = ""Title$ = Language("FileStuff","NewSource")ElseTitle$ = GetFilePart(FileName$)EndIfOpenGadgetList(#GADGET_SourceContainer)CreateEditorGadget()CloseGadgetList()If FileName$ = ""FileList()\IsCode = #True ; assume it is a code file until it is savedElseFileList()\IsCode = IsCodeFile(FileName$)EndIfFileList()\FileName$ = FileName$FileList()\Debugger = OptionDebugger ; set the default valuesFileList()\EnablePurifier = OptionPurifierFileList()\Optimizer = OptionOptimizerFileList()\EnableASM = OptionInlineASMFileList()\EnableXP = OptionXPSkinFileList()\EnableWayland = OptionWaylandFileList()\EnableAdmin = OptionVistaAdminFileList()\EnableUser = OptionVistaUserFileList()\DPIAware = OptionDPIAwareFileList()\DllProtection = OptionDllProtectionFileList()\SharedUCRT = OptionSharedUCRTFileList()\EnableThread = OptionThreadFileList()\EnableOnError = OptionOnErrorFileList()\ExecutableFormat = OptionExeFormatFileList()\CPU = OptionCPUFileList()\NewLineType = OptionNewLineTypeFileList()\SubSystem$ = OptionSubSystem$FileList()\ErrorLog = OptionErrorLogFileList()\Parser\Encoding = OptionEncodingFileList()\UseCreateExe = OptionUseCreateExeFileList()\UseBuildCount = OptionUseBuildCountFileList()\UseCompileCount = OptionUseCompileCountFileList()\TemporaryExePlace= OptionTemporaryExeFileList()\CustomCompiler = OptionCustomCompilerFileList()\CompilerVersion$ = OptionCompilerVersion$FileList()\CurrentDirectory$= ""FileList()\ToggleFolds = 1FileList()\PurifierGranularity$ = ""FileList()\ExistsOnDisk = #FalseIf OptionEncoding = 0ScintillaSendMessage(FileList()\EditorGadget, #SCI_SETCODEPAGE, 0, 0)ElseScintillaSendMessage(FileList()\EditorGadget, #SCI_SETCODEPAGE, #SC_CP_UTF8, 0)EndIfAddTabBarGadgetItem(#GADGET_FilesPanel, #PB_Default, Title$)ChangeActiveSourcecode(*OldSource); Link to project (if any); Do it as soon as possible, so the panel tab gets the right color very quickly.LinkSourceToProject(*ActiveSource)If EnableColoringSetBackgroundColor()EndIfSetTabBarGadgetState(#GADGET_FilesPanel, CountTabBarGadgetItems(#GADGET_FilesPanel)-1)UpdateSourceStatus(0)ResizeMainWindow(); if configured and needed, execute tool for new sourcesIf ExecuteToolAddTools_Execute(#TRIGGER_NewSource, *ActiveSource); reset the modified flag so this code can be closed without saving if nothing is changedUpdateSourceStatus(#False); place cursor at end of file (usually such tools add headers to a file)Pos = SendEditorMessage(#SCI_GETLENGTH, 0, 0)SendEditorMessage(#SCI_SETSEL, Pos, Pos)UpdateCursorPosition()EndIfEndProcedureProcedure DetectNewLineType(*Buffer, BufferSize)*Pointer.HighlightPTR = *Buffer*BufferEnd = *Buffer + BufferSizeDetectedType = -1While *Pointer < *BufferEndIf *Pointer\b = 13 And *Pointer\a[1] = 10; windows newlineIf DetectedType <> 0 And DetectedType <> -1 ; oops, a mixed up file, use os standardProcedureReturn #DEFAULT_NewLineTypeEndIfDetectedType = 0*Pointer + 1ElseIf *Pointer\b = 10 And *Pointer\a[1] = 13; unknown type, use os standardProcedureReturn #DEFAULT_NewLineTypeElseIf *Pointer\b = 10; linux newlineIf DetectedType <> 1 And DetectedType <> -1 ; oops, a mixed up file, use os standardProcedureReturn #DEFAULT_NewLineTypeEndIfDetectedType = 1ElseIf *Pointer\b = 13; mac newlineIf DetectedType <> 2 And DetectedType <> -1 ; oops, a mixed up file, use os standardProcedureReturn #DEFAULT_NewLineTypeEndIfDetectedType = 2EndIf*Pointer + 1WendIf DetectedType = -1DetectedType = #DEFAULT_NewLineTypeEndIfProcedureReturn DetectedTypeEndProcedureProcedure ChangeNewLineType(*ptrBuffer.INTEGER, *ptrBufferSize.INTEGER, NewLineType)*NewBuffer = AllocateMemory(*ptrBufferSize\i + 1000000)*BufferEnd = *ptrBuffer\i + *ptrBufferSize\i*ReadCursor.HighlightPTR = *ptrBuffer\i*WriteCursor.HighlightPTR = *NewBufferCopyMemoryString("", @*WriteCursor)If *NewBufferWhile *ReadCursor < *BufferEndIf (*ReadCursor\b = 13 And *ReadCursor\a[1] = 10) Or (*ReadCursor\b = 10 And *ReadCursor\a[1] = 13)If NewLineType = 0 ; to crlf*WriteCursor\b = 13*WriteCursor\a[1] = 10*ReadCursor + 1*WriteCursor + 1ElseIf NewLineType = 1 ; to lf*WriteCursor\b = 10*ReadCursor + 1Else ; to cr*WriteCursor\b = 13*ReadCursor + 1EndIfElseIf *ReadCursor\b = 13 Or *ReadCursor\b = 10If NewLineType = 0 ; crlf*WriteCursor\b = 13*WriteCursor\a[1] = 10*WriteCursor + 1ElseIf NewLineType = 1 ; to lf*WriteCursor\b = 10Else ; to cr*WriteCursor\b = 13EndIfElse*WriteCursor\b = *ReadCursor\bEndIf*ReadCursor + 1*WriteCursor + 1WendFreeMemory(*ptrBuffer\i) ; free the old buffer*ptrBuffer\i = *NewBuffer*ptrBufferSize\i = *WriteCursor - *NewBufferEndIfEndProcedure; Note: We do not use the SYS_AsciiToUTF8 etc anymore because:; The "�" and "`" Characters (91,ドル 92ドル) are not displayed by Scintilla.; Scintilla instead uses U+2018 and U+2019 characters when they get pasted.; So to avoid any confustion from a disappearing character we handle this conversion; as well when doing the Source encoding change.;; Let's hope there are no more such special characters.;; Some notes:; - unrepresentable chars become '?';Procedure AsciiToUTF8(*out.ASCII, *outlen.LONG, *in.ASCII, *inlen.LONG)*in_end = *in + *inlen\l ; copy to local vars for access speed*out_start = *outWhile *in < *in_end ; ascii rangeIf *in\a < 80ドル*out\a = *in\a*out + 1ElseIf *in\a = 91ドル ; `-char. Turn this into U+2018*out\a = $E2*out + 1*out\a = 80ドル*out + 1*out\a = 98ドル*out + 1ElseIf *in\a = 92ドル ; ï¿1⁄2-char. Turn this into U+2019*out\a = $E2*out + 1*out\a = 80ドル*out + 1*out\a = 99ドル*out + 1Else ; turn it into a 2byte sequence*out\a = ((*in\a >> 6) & %00011111) | %11000000*out + 1*out\a = (*in\a & %00111111) | %10000000*out + 1EndIf*in + 1Wend*outlen\l = *out - *out_startEndProcedureProcedure UTF8ToAscii(*out.ASCII, *outlen.LONG, *in.ASCII, *inlen.LONG)*in_end = *in + *inlen\l ; copy to local vars for access speed*out_start = *outWhile *in < *in_endc = *in\aIf c & %10000000 = 0 ; 1-byte char*out\a = c*out + 1*in + 1ElseIf c & %11100000 = %11000000 And *in+1 < *in_end ; 2-byte char*in + 1If *in\a & %11000000 = %10000000 ; check if the next is a followup bytec = ((c & %00011111) << 6) | (*in\a & %00111111)If c < 256*out\a = cElse*out\a = '?' ; unicode char outside of ascii rangeEndIf*out + 1*in + 1Else*out\a = '?' ; invalid utf8*out + 1EndIfElseIf c & %11110000 = %11100000 And *in+2 < *in_end ; 3-byte char, not representable in asciiIf c = $E2 And PeekC(*in+1) = 80ドル And PeekC(*in+2) = 98ドル*out\a = 91ドル*out + 1*in + 3ElseIf c = $E2 And PeekC(*in+1) = 80ドル And PeekC(*in+2) = 99ドル*out\a = 92ドル*out + 1*in + 3Else*out\a = '?'*out + 1; skip the next two bytes only if they are correct followup bytesIf PeekC(*in+1) & %11000000 = %10000000 And PeekC(*in+2) & %11000000 = %10000000*in + 3ElseIf PeekC(*in+1) & %11000000 = %10000000*in + 2 ; incomplete sequenceElse*in + 1 ; only start byte of sequenceEndIfEndIfElseIf c & %11111000 = %11110000 And *in+3 < *in_end ; 4-byte char, not representable in ascii*out\a = '?'*out + 1; skip the next three bytes only if they are correct followup bytesIf PeekC(*in+1) & %11000000 = %10000000 And PeekC(*in+2) & %11000000 = %10000000 And PeekC(*in+3) & %11000000 = %10000000*in + 4ElseIf PeekC(*in+1) & %11000000 = %10000000 And PeekC(*in+2) & %11000000 = %10000000*in + 3 ; incomplete sequenceElseIf PeekC(*in+1) & %11000000 = %10000000*in + 2 ; incomplete sequenceElse*in + 1 ; only start byte of sequenceEndIfElse*in + 1 ; invalid UTF-8, just skip itEndIfWend*outlen\l = *out - *out_startEndProcedureProcedure ChangeTextEncoding(*Source.SourceFile, NewEncoding)If NewEncoding <> *Source\Parser\Encoding; Its .l as the SYS function takes an int *OldLength.l = ScintillaSendMessage(*Source\EditorGadget, #SCI_GETLENGTH, 0, 0)*OldBuffer = AllocateMemory(OldLength+1)If *OldBufferScintillaSendMessage(*Source\EditorGadget, #SCI_GETTEXT, OldLength+1, *OldBuffer) ; #SCI_GETTEXT returns length-1 bytes... very inconsistent of scintillaIf NewEncoding = 1NewLength.l = OldLength*4 ; Utf8 can only be 4x as big as AsciiElseNewLength.l = OldLength ; Buffer can only get smaller for Utf8-AsciiEndIf*NewBuffer = AllocateMemory(NewLength+1)If *NewBufferIf NewEncoding = 1AsciiToUTF8(*NewBuffer, @NewLength, *OldBuffer, @OldLength)ElseUTF8ToAscii(*NewBuffer, @NewLength, *OldBuffer, @OldLength)EndIfScintillaSendMessage(*Source\EditorGadget, #SCI_CLEARALL, 0, 0) ; should completely erase the old document and create a new oneIf NewEncoding = 0ScintillaSendMessage(*Source\EditorGadget, #SCI_SETCODEPAGE, 0, 0)ElseScintillaSendMessage(*Source\EditorGadget, #SCI_SETCODEPAGE, #SC_CP_UTF8, 0)EndIfScintillaSendMessage(*Source\EditorGadget, #SCI_SETTEXT, 0, *NewBuffer)*Source\Parser\Encoding = NewEncoding ; finally update the flag in the structureFreeMemory(*NewBuffer)EndIfFreeMemory(*OldBuffer)EndIfEndIfEndProcedure; Use macro to ease the typing;Macro AddStringConfigLine(Key, Value)If Value And IsCodeFile ; Don't save empty value, as it's the defaultNbLines + 1ConfigLines$(NbLines) = Key + " = " + ValueEndIfEndMacroMacro AddFlagConfigLine(Key, Value)If Value And IsCodeFile ; Don't save empty value, as it's the defaultNbLines + 1ConfigLines$(NbLines) = KeyEndIfEndMacro; Also used to append Project settings to a temp file, so it must handle a CompileTarget input;Procedure SaveProjectSettings(*Target.CompileTarget, IsCodeFile, IsTempFile, ReportErrors)If SaveProjectSettings = #SAVESETTINGS_DoNotSave And IsTempFile = 0 ; don't save anythingProcedureReturnEndIfIf SaveProjectSettings = #SAVESETTINGS_EndOfFile And IsCodeFile = 0; Do not save settings at the end of non-code files; We do however save settings when they are not appended to the file to memorize cursor position etcProcedureReturnEndIf; If its not a target, we have more info from the extended sourcefile structureIf *Target\IsProject = 0*Source.SourceFile = *TargetElse*Source = 0EndIf; generate the config lines;If CommandlineBuild = 0 And *Target = *ActiveSourceUpdateCursorPosition()EndIf; Note: All entries with a fixed number of lines come first; (no array bounds check needed then);NbLines = 1ConfigLines$(NbLines) = "IDE Options = "+DefaultCompiler\VersionString$If IsCodeFileIf *Target\ExecutableFormat = 1NbLines + 1ConfigLines$(NbLines) = "ExecutableFormat = Console"ElseIf *Target\ExecutableFormat = 2NbLines + 1; Note: when writing, we make a difference, on reading we allow both for compatibility;CompilerIf #CompileWindowsConfigLines$(NbLines) = "ExecutableFormat = Shared dll"CompilerElseIf #CompileMacConfigLines$(NbLines) = "ExecutableFormat = Shared .dylib"CompilerElse ; LinuxConfigLines$(NbLines) = "ExecutableFormat = Shared .so"CompilerEndIfEndIf ; no need to write it when it's 0.. it will default to that anywayEndIfIf (MemorizeCursor Or IsTempFile) And *SourceIf *Source\CurrentLine > 1NbLines + 1ConfigLines$(NbLines) = "CursorPosition = "+Str(*Source\CurrentLine-1)EndIfIf IsTempFile ; this is saved for tempfiles onlyNbLines + 1ConfigLines$(NbLines) = "CursorColumn = "+Str(*Source\CurrentColumnBytes)EndIfIf *Source = *ActiveSourceFirstLine = GetFirstVisibleLine()EndIfIf FirstLine > 0NbLines + 1ConfigLines$(NbLines) = "FirstLine = "+Str(FirstLine)EndIfEndIfIf *Source And *Source = *ActiveSource And EnableFolding And IsCodeFileFoldingInfo$ = CreateFoldingInformation()If FoldingInfo$ <> ""NbLines + 1ConfigLines$(NbLines) = "Folding = "+FoldingInfo$EndIfEndIfIf CommandlineBuild = 0 And *Source = *ActiveSource And (MemorizeMarkers Or IsTempFile)Markers$ = GetMarkerString()If Markers$ <> ""NbLines + 1ConfigLines$(NbLines) = "Markers = "+Markers$EndIfEndIfCompilerIf #SpiderBasicAddStringConfigLine("WindowTheme", *Target\WindowTheme$)AddStringConfigLine("GadgetTheme", *Target\GadgetTheme$)AddStringConfigLine("WebServerAddress", *Target\WebServerAddress$); WebApp;AddStringConfigLine("WebAppName" , *Target\WebAppName$)AddStringConfigLine("WebAppIcon" , *Target\WebAppIcon$)AddStringConfigLine("HtmlFilename" , *Target\HtmlFilename$)AddStringConfigLine("JavaScriptFilename", *Target\JavaScriptFilename$)AddStringConfigLine("JavaScriptPath" , *Target\JavaScriptPath$)AddStringConfigLine("ExportCommandLine" , *Target\ExportCommandLine$)AddStringConfigLine("ExportArguments" , *Target\ExportArguments$)AddStringConfigLine("ResourceDirectory" , *Target\ResourceDirectory$)AddFlagConfigLine("EnableResourceDirectory", *Target\EnableResourceDirectory)AddFlagConfigLine("CopyJavaScriptLibrary", *Target\CopyJavaScriptLibrary)AddFlagConfigLine("WebAppEnableDebugger" , *Target\WebAppEnableDebugger); iOSApp;AddStringConfigLine("iOSAppName" , *Target\iOSAppName$)AddStringConfigLine("iOSAppIcon" , *Target\iOSAppIcon$)AddStringConfigLine("iOSAppVersion" , *Target\iOSAppVersion$)AddStringConfigLine("iOSAppPackageID" , *Target\iOSAppPackageID$)AddStringConfigLine("iOSAppStartupImage", *Target\iOSAppStartupImage$)AddStringConfigLine("iOSAppOutput" , *Target\iOSAppOutput$)AddStringConfigLine("iOSAppResourceDirectory" , *Target\iOSAppResourceDirectory$)AddFlagConfigLine("iOSAppEnableResourceDirectory", *Target\iOSAppEnableResourceDirectory)AddStringConfigLine("iOSAppOrientation", Str(*Target\iOSAppOrientation))AddFlagConfigLine("iOSAppFullScreen" , *Target\iOSAppFullScreen)AddFlagConfigLine("iOSAppAutoUpload" , *Target\iOSAppAutoUpload)AddFlagConfigLine("iOSAppEnableDebugger" , *Target\iOSAppEnableDebugger)AddFlagConfigLine("iOSAppKeepAppDirectory" , *Target\iOSAppKeepAppDirectory); AndroidApp;AddStringConfigLine("AndroidAppName" , *Target\AndroidAppName$)AddStringConfigLine("AndroidAppIcon" , *Target\AndroidAppIcon$)AddStringConfigLine("AndroidAppVersion" , *Target\AndroidAppVersion$)AddStringConfigLine("AndroidAppCode" , Str(*Target\AndroidAppCode))AddStringConfigLine("AndroidAppPackageID" , *Target\AndroidAppPackageID$)AddStringConfigLine("AndroidAppIAPKey" , *Target\AndroidAppIAPKey$)AddStringConfigLine("AndroidAppStartupImage", *Target\AndroidAppStartupImage$)AddStringConfigLine("AndroidAppStartupColor", *Target\AndroidAppStartupColor$)AddStringConfigLine("AndroidAppOutput" , *Target\AndroidAppOutput$)AddStringConfigLine("AndroidAppResourceDirectory" , *Target\AndroidAppResourceDirectory$)AddFlagConfigLine("AndroidAppEnableResourceDirectory", *Target\AndroidAppEnableResourceDirectory)AddStringConfigLine("AndroidAppOrientation" , Str(*Target\AndroidAppOrientation))AddFlagConfigLine("AndroidAppFullScreen" , *Target\AndroidAppFullScreen)AddFlagConfigLine("AndroidAppAutoUpload" , *Target\AndroidAppAutoUpload)AddFlagConfigLine("AndroidAppEnableDebugger", *Target\AndroidAppEnableDebugger)AddFlagConfigLine("AndroidAppKeepAppDirectory", *Target\AndroidAppKeepAppDirectory)AddFlagConfigLine("AndroidAppInsecureFileMode", *Target\AndroidAppInsecureFileMode)CompilerEndIfAddFlagConfigLine("Optimizer", *Target\Optimizer)If *Target\EnableASM And IsCodeFileNbLines + 1ConfigLines$(NbLines) = "EnableAsm"EndIfIf *Target\EnableThread And IsCodeFileNbLines + 1ConfigLines$(NbLines) = "EnableThread"EndIfIf *Target\EnableXP And IsCodeFileNbLines + 1ConfigLines$(NbLines) = "EnableXP"EndIfIf *Target\EnableWayland And IsCodeFileNbLines + 1ConfigLines$(NbLines) = "EnableWayland"EndIfIf *Target\EnableAdmin And IsCodeFileNbLines + 1ConfigLines$(NbLines) = "EnableAdmin"EndIfIf *Target\EnableUser And IsCodeFileNbLines + 1ConfigLines$(NbLines) = "EnableUser"EndIfIf *Target\DPIAware And IsCodeFileNbLines + 1ConfigLines$(NbLines) = "DPIAware"EndIfIf *Target\DllProtection And IsCodeFileNbLines + 1ConfigLines$(NbLines) = "DllProtection"EndIfIf *Target\SharedUCRT And IsCodeFileNbLines + 1ConfigLines$(NbLines) = "SharedUCRT"EndIfIf *Target\EnableOnError And IsCodeFileNbLines + 1ConfigLines$(NbLines) = "EnableOnError"EndIfIf *Target\UseIcon And IsCodeFileNbLines + 1ConfigLines$(NbLines) = "UseIcon = " + *Target\IconName$EndIfIf *Target\UseMainFile And IsCodeFileNbLines + 1ConfigLines$(NbLines) = "UseMainFile = " + *Target\MainFile$EndIfIf *Target\ExecutableName$ And IsCodeFileNbLines + 1ConfigLines$(NbLines) = "Executable = " + CreateRelativePath(GetPathPart(*Target\FileName$), *Target\ExecutableName$)EndIfIf *Target\CPU And IsCodeFileNbLines + 1ConfigLines$(NbLines) = "CPU = " + Str(*Target\CPU)EndIfIf *Target\SubSystem$ And IsCodeFileNbLines + 1ConfigLines$(NbLines) = "SubSystem = " + *Target\Subsystem$EndIfIf *Target\LinkerOptions$ And IsCodeFileNbLines + 1ConfigLines$(NbLines) = "LinkerOptions = " + *Target\LinkerOptions$EndIfIf *Target\Debugger = 0 And IsCodeFileNbLines + 1ConfigLines$(NbLines) = "DisableDebugger"EndIfIf *Source And *Source\ErrorLog = 0 And IsCodeFile ; this is only for source filesNbLines + 1ConfigLines$(NbLines) = "HideErrorLog"EndIfIf *Target\CommandLine$ And IsCodeFileNbLines + 1ConfigLines$(NbLines) = "CommandLine = " + *Target\CommandLine$EndIfIf *Target\CurrentDirectory$ And IsCodeFileNbLines + 1ConfigLines$(NbLines) = "CurrentDirectory = " + *Target\CurrentDirectory$EndIfIf *Target\TemporaryExePlace And IsCodeFileNbLines + 1ConfigLines$(NbLines) = "CompileSourceDirectory"EndIfIf *Target\EnabledTools$ And IsCodeFileNbLines + 1ConfigLines$(NbLines) = "EnabledTools = " + *Target\EnabledTools$EndIfIf *Target\CustomCompiler And IsCodeFileNbLines + 1ConfigLines$(NbLines) = "Compiler = "+*Target\CompilerVersion$EndIfIf *Target\CustomDebugger And IsCodeFile; do not save any of this if disabled; CompilerIf #CompileMac ; not supported on OSX yet OSX-debug; If *Source\DebuggerType = 1 Or *Source\DebuggerType = 2; Type = *Source\DebuggerType + 1; Else; Type = 0; EndIf; CompilerElseType = *Target\DebuggerType; CompilerEndIfIf Type = 1NbLines + 1ConfigLines$(NbLines) = "Debugger = IDE"ElseIf Type = 2NbLines + 1ConfigLines$(NbLines) = "Debugger = Standalone"ElseIf Type = 3NbLines + 1ConfigLines$(NbLines) = "Debugger = Console"EndIfEndIfIf *Target\CustomWarning And IsCodeFileIf *Target\WarningMode = 0NbLines + 1ConfigLines$(NbLines) = "Warnings = Ignore"ElseIf *Target\WarningMode = 1NbLines + 1ConfigLines$(NbLines) = "Warnings = Display"ElseIf *Target\WarningMode = 2NbLines + 1ConfigLines$(NbLines) = "Warnings = Error"EndIfEndIf; Save the granularity options even if the purifier is disabled;If *Target\EnablePurifier And *Target\PurifierGranularity$ And IsCodeFileNbLines + 1ConfigLines$(NbLines) = "EnablePurifier = " + *Target\PurifierGranularity$ElseIf *Target\EnablePurifier And IsCodeFileNbLines + 1ConfigLines$(NbLines) = "EnablePurifier"ElseIf *Target\PurifierGranularity$ And IsCodeFileNbLines + 1ConfigLines$(NbLines) = "DisablePurifier = " + *Target\PurifierGranularity$EndIfIf *Target\UseCompileCount And IsCodeFileNbLines + 1ConfigLines$(NbLines) = "EnableCompileCount = " + Str(*Target\CompileCount)ElseIf *Target\CompileCount > 0 And IsCodeFile ; only save when <> 0 in disabled modeNbLines + 1ConfigLines$(NbLines) = "DisableCompileCount = " + Str(*Target\CompileCount)EndIfIf *Target\UseBuildCount And IsCodeFileNbLines + 1ConfigLines$(NbLines) = "EnableBuildCount = " + Str(*Target\BuildCount)ElseIf *Target\BuildCount > 0 And IsCodeFile ; only save when <> 0 in disabled modeNbLines + 1ConfigLines$(NbLines) = "DisableBuildCount = " + Str(*Target\BuildCount)EndIfIf *Target\UseCreateExe And IsCodeFileNbLines + 1ConfigLines$(NbLines) = "EnableExeConstant"EndIfIf *Target\NbConstants > 0 And IsCodeFileFor i = 0 To *Target\NbConstants-1NbLines + 1If *Target\ConstantEnabled[i]ConfigLines$(NbLines) = "Constant = " + *Target\Constant$[i]ElseConfigLines$(NbLines) = "ConstantOff = " + *Target\Constant$[i]EndIfNext iEndIfIf *Target\VersionInfo And IsCodeFileNbLines + 1ConfigLines$(NbLines) = "IncludeVersionInfo"EndIf; add the version info, even in the disabled stateFor i = 0 To 23If *Target\VersionField$[i] <> "" And IsCodeFileNbLines + 1ConfigLines$(NbLines) = "VersionField"+Str(i)+" = " + *Target\VersionField$[i]EndIfNext i; Note: All entries with a variable number of lines follow here, we must; ensure that the array is not too small for these (sanity check, as its user input)If *Target\Watchlist$ <> "" And NbLines < #MAX_ConfigLines And IsCodeFileNbLines + 1ConfigLines$(NbLines) = "Watchlist = "index = 1While StringField(*Target\Watchlist,ドル index, ";") <> ""If Len(ConfigLines$(NbLines)) > 80 And NbLines < #MAX_ConfigLines ; break the line at 80 chars (or a little over that at least)ConfigLines$(NbLines) = Left(ConfigLines$(NbLines), Len(ConfigLines$(NbLines))-1) ; cut the last ";"NbLines + 1ConfigLines$(NbLines) = "Watchlist = "EndIfConfigLines$(NbLines) + StringField(*Target\Watchlist,ドル index, ";") + ";"index + 1WendConfigLines$(NbLines) = Left(ConfigLines$(NbLines), Len(ConfigLines$(NbLines))-1) ; cut the last ";"EndIfIf *Target\NbResourceFiles > 0 And IsCodeFileFor i = 0 To *Target\NbResourceFiles-1If NbLines < #MAX_ConfigLinesNbLines + 1ConfigLines$(NbLines) = "AddResource = "+*Target\ResourceFiles$[i]EndIfNext iEndIfIf IsTempFile = 0 And *SourceForEach *Source\UnknownIDEOptionsList$()If NbLines < #MAX_ConfigLinesNbLines + 1Configlines$(NbLines) = *Source\UnknownIDEOptionsList$()EndIfNextEndIf; save the config lines now;If SaveProjectSettings = #SAVESETTINGS_EndOfFile Or IsTempFile ; in source fileIf *SourceIf *Source\NewLineType = 0NewLine$ = Chr(13) + Chr(10)ElseIf *Source\NewLineType = 1NewLine$ = Chr(10)ElseNewLine$ = Chr(13)EndIfElseNewLine$ = #NewLineEndIfFor i = 1 To NbLinesIf *Source And *Source\Parser\Encoding = 0 ; ASCIIWriteString(#FILE_SaveSource, NewLine$ + "; " + ConfigLines$(i), #PB_Ascii)ElseWriteString(#FILE_SaveSource, NewLine$ + "; " + ConfigLines$(i), #PB_UTF8)EndIfNext iElseIf *Source And SaveProjectSettings = #SAVESETTINGS_PerFileCfg ; save in "filename.pb.cfg"If CreateFile(#FILE_SaveConfig, *Source\FileName$+".cfg")For i = 1 To NbLinesWriteStringN(#FILE_SaveConfig, ConfigLines$(i))Next iCloseFile(#FILE_SaveConfig)ElseIf ReportErrorsMessageRequester(#ProductName,ドル Language("FileStuff","SaveConfigError")+":"+#NewLine+*Source\FileName$+".cfg", #FLAG_Error)EndIfElseIf *Source And SaveProjectSettings = #SAVESETTINGS_PerFolderCfg ; save in "project.cfg"If CreateFile(#FILE_SaveConfig, GetPathPart(*Source\FileName$)+"project.cfg.new")If ReadFile(#FILE_ReadConfig, GetPathPart(*Source\FileName$)+"project.cfg")While Eof(#FILE_ReadConfig) = 0Line$ = ReadString(#FILE_ReadConfig)If UCase(Trim(Line$)) = "["+UCase(GetFilePart(*Source\FileName$))+"]" ; cut out the old file configWhile Eof(#FILE_ReadConfig) = 0Line$ = ReadString(#FILE_ReadConfig)If Left(LTrim(Line$), 1) = "["WriteStringN(#FILE_SaveConfig, "")WriteStringN(#FILE_SaveConfig, Line$)BreakEndIfWendElseIf Line$ <> ""WriteStringN(#FILE_SaveConfig, Line$)EndIfWendCloseFile(#FILE_ReadConfig)EndIfWriteStringN(#FILE_SaveConfig, "[" + GetFilePart(*Source\FileName$) + "]")For i = 1 To NbLines-1Debug ConfigLines$(i)WriteStringN(#FILE_SaveConfig, " "+ConfigLines$(i))Next iWriteString(#FILE_SaveConfig, " "+ConfigLines$(NbLines)) ; no newline at the end of the fileCloseFile(#FILE_SaveConfig)DeleteFile(GetPathPart(*Source\FileName$)+"project.cfg")If FileSize(GetPathPart(*Source\FileName$)+"project.cfg") >= 0If ReportErrorsMessageRequester(#ProductName,ドル Language("FileStuff","SaveConfigError")+":"+#NewLine+GetPathPart(*Source\FileName$)+"project.cfg", #FLAG_Error)EndIfElseIf RenameFile(GetPathPart(*Source\FileName$)+"project.cfg.new", GetPathPart(*Source\FileName$)+"project.cfg") = 0If ReportErrorsMessageRequester(#ProductName,ドル Language("FileStuff","SaveConfigError")+":"+#NewLine+GetPathPart(*Source\FileName$)+"project.cfg", #FLAG_Error)EndIfEndIfElseIf ReportErrorsMessageRequester(#ProductName,ドル Language("FileStuff","SaveConfigError")+":"+#NewLine+GetPathPart(*Source\FileName$)+"project.cfg.new", #FLAG_Error)EndIfEndIfEndProcedure; Handles source files with *old* settings format;Procedure AnalyzeSettings_Old(*Source.SourceFile, *Buffer, Length)ExecutableFormat$ = "WINDOWS"*Cursor.Ascii = *Buffer+LengthFound = 0If Length > 0While *Cursor >= *Buffer*LastPointer = *CursorWhile *Cursor >= *Buffer And *Cursor\a <> 10*Cursor-1WendIf *Cursor >= *BufferLine$ = PeekS(*Cursor+1, *LastPointer - *Cursor, #PB_Ascii)If Line$ = "; EOF" : Found = 1ElseIf Line$ = "; EnableAsm" : Found = 1 : *Source\EnableASM = 1ElseIf Line$ = "; EnableXP" : Found = 1 : *Source\EnableXP = 1ElseIf Line$ = "; EnableWayland" : Found = 1 : *Source\EnableWayland = 1ElseIf Line$ = "; EnableOnError" : Found = 1 : *Source\EnableOnError = 1ElseIf Line$ = "; DisableDebugger" : Found = 1 : *Source\Debugger = 0ElseIf Left(Line,13ドル) = "; Executable=" : Found = 1 : *Source\ExecutableName$ = Right(Line,ドル Len(Line$)-13)ElseIf Left(Line,19ドル) = "; ExecutableFormat=" : Found = 1 : ExecutableFormat$ = Right(Line,ドル Len(Line$)-19)ElseIf Left(Line,14ドル) = "; CommandLine=" : Found = 1 : *Source\CommandLine$ = Right(Line,ドル Len(Line$)-14)ElseIf Left(Line,10ドル) = "; UseIcon=" : Found = 1 : *Source\UseIcon = 1 : *Source\IconName$ = Right(Line,ドル Len(Line$)-10)ElseIf Left(Line,14ドル) = "; UseMainFile=" : Found = 1 : *Source\UseMainFile = 1 : *Source\MainFile$ = Right(Line,ドル Len(Line$)-14)ElseIf Left(Line,6ドル) = "; CPU=" : Found = 1 : *Source\CPU = Val(Right(Line,ドル Len(Line$)-6 ))ElseIf Left(line,17ドル) = "; CursorPosition=" : Found = 1 : Loading_CurrentLine = Val(Right(line,ドル Len(line$)-17)) + 1ElseIf Left(line,12ドル) = "; FirstLine=" : Found = 1 : Loading_FirstVisibleLine = Val(Right(line,ドル Len(line$)-12))ElseIf Left(line,12ドル) = "; SubSystem=" : Found = 1 : *Source\SubSystem$ = Right(Line,ドル Len(Line$)-12)ElseIf Left(line,10ドル) = "; Folding=" : Found = 1 : Loading_FoldingState$ = Right(Line,ドル Len(Line$)-10)Else: BreakEndIf*Cursor - 1If *Cursor >= *Buffer And *Cursor\a = 13*Cursor - 1EndIfEndIfWendEndIfSelect ExecutableFormat$Case "Windows" : *Source\ExecutableFormat = 0Case "Linux" : *Source\ExecutableFormat = 0Case "MacOS" : *Source\ExecutableFormat = 0Case "Console" : *Source\ExecutableFormat = 1Case "Shared Dll": *Source\ExecutableFormat = 2EndSelectIf FoundIsIDEConfigPresent = 1 ; we found settings (but from the old IDE), so use the standards for the options that are new*Source\SubSystem$ = OptionSubSystem$*Source\ErrorLog = OptionErrorLogPokeB(*LastPointer+1, 0) ; 0-terminate the bufferProcedureReturn *LastPointer - *Buffer + 1; cut the settings, return new lengthElseProcedureReturn Length ; return full buffer length, nothing should be cutEndIfEndProcedureProcedure AnalyzeSettings_Common(*Source.SourceFile, NbLines) ; analyze the ConfigLines$ arrayExecutableFormat$ = ""MarkerLines$ = ""*Source\NbResourceFiles = 0; These configs are enabled by default, so if not present, should be 0*Source\EnableXP = 0*Source\DPIAware = 0*Source\DllProtection = 0*Source\SharedUCRT = 0*Source\EnableWayland = 0ClearList(*Source\UnknownIDEOptionsList$())*Source\VersionInfo = 0For i = 0 To 15*Source\VersionField$[i] = ""Next i*Source\Watchlist$ = ""*Source\NbConstants = 0For i = 0 To #MAX_Constants-1*Source\Constant$[i] = ""*Source\ConstantEnabled[i] = 0Next iFor i = 1 To NbLinesindex = FindString(ConfigLines$(i), "=", 1)If index = 0Name$ = ConfigLines$(i)Value$ = ""ElseName$ = Left(ConfigLines$(i), index-1)Value$ = Right(ConfigLines$(i), Len(ConfigLines$(i))-index)EndIfName$ = Trim(RemoveString(UCase(Name$), Chr(9)))Value$ = Trim(RemoveString(Value,ドル Chr(9)))Select Name$Case "IDE OPTIONS"; ok, by this string we know that the options come from the IDEIsIDEConfigPresent = 1CompilerIf #SpiderBasicCase "WEBSERVERADDRESS" : *Source\WebServerAddress$ = Value$Case "WINDOWTHEME" : *Source\WindowTheme$ = Value$Case "GADGETTHEME" : *Source\GadgetTheme$ = Value$Case "OPTIMIZEJS" : *Source\Optimizer = 1 ; Backward compatibility with older sources (now named "Optimizer")Case "WEBAPPNAME" : *Source\WebAppName$ = Value$Case "WEBAPPICON" : *Source\WebAppIcon$ = Value$Case "HTMLFILENAME" : *Source\HtmlFilename$ = Value$Case "JAVASCRIPTFILENAME" : *Source\JavaScriptFilename$ = Value$Case "JAVASCRIPTPATH" : *Source\JavaScriptPath$ = Value$Case "COPYJAVASCRIPTLIBRARY": *Source\CopyJavaScriptLibrary = 1Case "EXPORTCOMMANDLINE" : *Source\ExportCommandLine$ = Value$Case "EXPORTARGUMENTS" : *Source\ExportArguments$ = Value$Case "RESOURCEDIRECTORY" : *Source\ResourceDirectory$ = Value$Case "ENABLERESOURCEDIRECTORY": *Source\EnableResourceDirectory = 1Case "WEBAPPENABLEDEBUGGER" : *Source\WebAppEnableDebugger = 1Case "IOSAPPNAME" : *Source\iOSAppName$ = Value$Case "IOSAPPICON" : *Source\iOSAppIcon$ = Value$Case "IOSAPPVERSION" : *Source\iOSAppVersion$ = Value$Case "IOSAPPPACKAGEID" : *Source\iOSAppPackageID$ = Value$Case "IOSAPPSTARTUPIMAGE" : *Source\iOSAppStartupImage$ = Value$Case "IOSAPPOUTPUT" : *Source\iOSAppOutput$ = Value$Case "IOSAPPORIENTATION" : *Source\iOSAppOrientation = Val(Value$)Case "IOSAPPFULLSCREEN" : *Source\iOSAppFullScreen = 1Case "IOSAPPAUTOUPLOAD" : *Source\iOSAppAutoUpload = 1Case "IOSAPPRESOURCEDIRECTORY" : *Source\iOSAppResourceDirectory$ = Value$Case "IOSAPPENABLERESOURCEDIRECTORY": *Source\iOSAppEnableResourceDirectory = 1Case "IOSAPPENABLEDEBUGGER" : *Source\iOSAppEnableDebugger = 1Case "IOSAPPKEEPAPPDIRECTORY" : *Source\iOSAppKeepAppDirectory = 1Case "ANDROIDAPPNAME" : *Source\AndroidAppName$ = Value$Case "ANDROIDAPPICON" : *Source\AndroidAppIcon$ = Value$Case "ANDROIDAPPVERSION" : *Source\AndroidAppVersion$ = Value$Case "ANDROIDAPPCODE" : *Source\AndroidAppCode = Val(Value$)Case "ANDROIDAPPPACKAGEID" : *Source\AndroidAppPackageID$ = Value$Case "ANDROIDAPPIAPKEY" : *Source\AndroidAppIAPKey$ = Value$Case "ANDROIDAPPSTARTUPIMAGE" : *Source\AndroidAppStartupImage$ = Value$Case "ANDROIDAPPSTARTUPCOLOR" : *Source\AndroidAppStartupColor$ = Value$Case "ANDROIDAPPOUTPUT" : *Source\AndroidAppOutput$ = Value$Case "ANDROIDAPPORIENTATION" : *Source\AndroidAppOrientation = Val(Value$)Case "ANDROIDAPPFULLSCREEN" : *Source\AndroidAppFullScreen = 1Case "ANDROIDAPPAUTOUPLOAD" : *Source\AndroidAppAutoUpload = 1Case "ANDROIDAPPRESOURCEDIRECTORY" : *Source\AndroidAppResourceDirectory$ = Value$Case "ANDROIDAPPENABLERESOURCEDIRECTORY": *Source\AndroidAppEnableResourceDirectory = 1Case "ANDROIDAPPENABLEDEBUGGER" : *Source\AndroidAppEnableDebugger = 1Case "ANDROIDAPPKEEPAPPDIRECTORY" : *Source\AndroidAppKeepAppDirectory = 1Case "ANDROIDAPPINSECUREFILEMODE" : *Source\AndroidAppInsecureFileMode = 1CompilerEndIfCase "OPTIMIZER": *Source\Optimizer = 1Case "ENABLEASM": *Source\EnableASM = 1Case "ENABLEXP": *Source\EnableXP = 1Case "ENABLEWAYLAND": *Source\EnableWayland = 1Case "ENABLEADMIN": *Source\EnableAdmin = 1Case "ENABLEUSER": *Source\EnableUser = 1Case "DPIAWARE": *Source\DPIAware = 1Case "DLLPROTECTION": *Source\DllProtection = 1Case "SHAREDUCRT": *Source\SharedUCRT = 1Case "ENABLETHREAD": *Source\EnableThread = 1Case "ENABLEONERROR": *Source\EnableOnError = 1Case "DISABLEDEBUGGER": *Source\Debugger = 0Case "HIDEERRORLOG": *Source\ErrorLog = 0Case "EXECUTABLE": *Source\ExecutableName$ = ResolveRelativePath(GetPathPart(*Source\FileName$), Value$)Case "EXECUTABLEFORMAT": ExecutableFormat$ = Value$Case "COMMANDLINE": *Source\CommandLine$ = Value$Case "USEICON": *Source\UseIcon = 1: *Source\IconName$ = Value$Case "USEMAINFILE": *Source\UseMainFile = 1: *Source\MainFile$ = Value$Case "CPU": *Source\CPU = Val(Value$)Case "CURSORPOSITION": Loading_CurrentLine = Val(Value$)Case "CURSORCOLUMN": Loading_CurrentColumn = Val(Value$) ; this is for tempfiles onlyCase "FIRSTLINE": Loading_FirstVisibleLine = Val(Value$)Case "SUBSYSTEM": *Source\SubSystem$ = Value$Case "FOLDING": Loading_FoldingState$ = Value$Case "INCLUDEVERSIONINFO": *Source\VersionInfo = 1Case "MARKERS": MarkerLines$ = RemoveString(Value,ドル " ") ; also remove spaces inbetreen (not like trim)Case "LINKEROPTIONS": *Source\LinkerOptions$ = Value$Case "CURRENTDIRECTORY": *Source\CurrentDirectory$ = Value$Case "COMPILESOURCEDIRECTORY": *Source\TemporaryExePlace = 1Case "ENABLEDTOOLS": *Source\EnabledTools$ = UCase(RemoveString(Value,ドル " ")) ; enforce our format for better searches laterCase "ENABLEEXECONSTANT":*Source\UseCreateExe = 1Case "COMPILER"*Source\CustomCompiler = #True*Source\CompilerVersion$ = Value$Case "ENABLECOMPILECOUNT"*Source\UseCompileCount = 1*Source\CompileCount = Val(Value$)Case "DISABLECOMPILECOUNT"*Source\UseCompileCount = 0*Source\CompileCount = Val(Value$)Case "ENABLEBUILDCOUNT"*Source\UseBuildCount = 1*Source\BuildCount = Val(Value$)Case "DISABLEBUILDCOUNT"*Source\UseBuildCount = 0*Source\BuildCount = Val(Value$)Case "DEBUGGER"*Source\CustomDebugger = 1Select UCase(Value$)Case "IDE" : *Source\DebuggerType = 1Case "STANDALONE": *Source\DebuggerType = 2Case "CONSOLE" : *Source\DebuggerType = 3Default : *Source\DebuggerType = 1EndSelect; CompilerIf #CompileMac ; OSX-debug; If *Source\DebuggerType > 1; *Source\DebuggerType - 1; EndIf; CompilerEndIfCase "WARNINGS"*Source\CustomWarning = 1Select UCase(Value$)Case "IGNORE" : *Source\WarningMode = 0Case "DISPLAY": *Source\WarningMode = 1Case "ERROR" : *Source\WarningMode = 2Default : *Source\WarningMode = 1EndSelectCase "ENABLEPURIFIER"*Source\EnablePurifier = 1*Source\PurifierGranularity$ = Value$Case "DISABLEPURIFIER"*Source\EnablePurifier = 0*Source\PurifierGranularity$ = Value$Case "CONSTANT"*Source\Constant$[*Source\NbConstants] = Value$*Source\ConstantEnabled[*Source\NbConstants] = #True*Source\NbConstants + 1Case "CONSTANTOFF"*Source\Constant$[*Source\NbConstants] = Value$*Source\ConstantEnabled[*Source\NbConstants] = #False*Source\NbConstants + 1Case "ADDRESOURCE"If *Source\NbResourceFiles < #MAX_ResourceFiles*Source\ResourceFiles$[*Source\NbResourceFiles] = Value$*Source\NbResourceFiles + 1EndIfCase "WATCHLIST": ; this can appear multiple time (to not have too long source lines)If *Source\Watchlist$ <> ""*Source\Watchlist$ + ";" ; add a separator between the linesEndIf*Source\Watchlist$ + RemoveString(Value,ドル " ") ; remove any spacesCase "" ; Ignore empty linesCase "FOLDLINES"; from jaPBe.. must be deleted, because jaPBe will get in trouble; if the source is modified without properly updating these!DefaultIf Left(Name,ドル 12) = "VERSIONFIELD"fieldnr = Val(Right(Name,ドル Len(Name$)-12))If fieldnr >= 0 And fieldnr <= 23*Source\VersionField$[fieldnr] = Value$EndIfElse; unknown setting.. save thisAddElement(*Source\UnknownIDEOptionsList$())*Source\UnknownIDEOptionsList$() = Trim(ConfigLines$(i))EndIfEndSelectNext i; The options are read from bottom to top, so reverse this list so it; looks right in the IDE again;If *Source\NbConstants > 0For i = 0 To Int(*Source\NbConstants/2)-1Swap *Source\Constant$[i], *Source\Constant$[*Source\NbConstants-i-1]Swap *Source\ConstantEnabled[i], *Source\ConstantEnabled[*Source\NbConstants-i-1]Next iEndIfSelect UCase(ExecutableFormat$)Case "CONSOLE"*Source\ExecutableFormat = 1Case "SHARED DLL", "SHARED .SO", "SHARED .DYLIB"*Source\ExecutableFormat = 2Default*Source\ExecutableFormat = 0 ; Default to executableEndSelectEndProcedureProcedure AnalyzeSettings_SourceFile(*Source.SourceFile, *Buffer, Length)*Cursor.Ascii = *Buffer+LengthNbLines = 0OptionsFound = 0If Length > 0While *Cursor >= *Buffer*LastPointer = *CursorWhile *Cursor >= *Buffer And (*Cursor\a <> 10 And *Cursor\a <> 13)*Cursor-1WendIf *Cursor >= *BufferIf *Source\Parser\Encoding = 1 ; UTF8Line$ = LTrim(PeekS(*Cursor+1, *LastPointer-*Cursor, #PB_UTF8 | #PB_ByteLength))Else ; AsciiLine$ = LTrim(PeekS(*Cursor+1, *LastPointer-*Cursor, #PB_Ascii))EndIfIf Line$ = "" ; ignore empty linesElseIf Left(Line,ドル 13) = "; IDE Options" ; marks the beginning of the block*Cursor - 1If *Cursor >= *Buffer And (*Cursor\a = 13 Or *Cursor\a = 10)*Cursor - 1EndIf*LastPointer = *Cursor; add this line too (important so the NbLines count is not zero even though something was found)NbLines + 1ConfigLines$(NbLines) = Right(Line,ドル Len(Line$)-1)OptionsFound = 1 ; only cut the options of this is found!BreakElseIf Left(Line,ドル 1) = ";" And NbLines < #MAX_ConfigLinesNbLines + 1ConfigLines$(NbLines) = Right(Line,ドル Len(Line$)-1)ElseBreakEndIf*Cursor - 1If *Cursor >= *Buffer And (*Cursor\a = 13 Or *Cursor\a = 10)*Cursor - 1EndIfEndIfWendEndIfIf NbLines > 0 And OptionsFoundAnalyzeSettings_Common(*Source, NbLines)PokeA(*LastPointer+1, 0) ; 0-terminate the bufferProcedureReturn *LastPointer - *Buffer + 1; cut the settings, return new lengthElseProcedureReturn LengthEndIfEndProcedureProcedure AnalyzeSettings_ConfigFile(*Source.SourceFile)If ReadFile(#FILE_ReadConfig, *Source\FileName$ + ".cfg")NbLines = 0While Eof(#FILE_ReadConfig) = 0 And NbLines < #MAX_ConfigLinesNbLines + 1ConfigLines$(NbLines) = ReadString(#FILE_ReadConfig)WendCloseFile(#FILE_ReadConfig)If NbLines = 0ProcedureReturn 0ElseAnalyzeSettings_Common(*Source, NbLines)ProcedureReturn 1EndIfElseProcedureReturn 0EndIfEndProcedureProcedure AnalyzeSettings_ProjectFile(*Source.SourceFile)If ReadFile(#FILE_ReadConfig, GetPathPart(*Source\FileName$) + "project.cfg")NbLines = 0While Eof(#FILE_ReadConfig) = 0Line$ = ReadString(#FILE_ReadConfig)If UCase(Trim(Line$)) = "[" + UCase(GetFilePart(*Source\FileName$)) + "]" ; found the configWhile Eof(#FILE_ReadConfig) = 0Line$ = ReadString(#FILE_ReadConfig)If Left(LTrim(Line$), 1) = "["BreakEndIfIf NbLines < #MAX_ConfigLinesNbLines + 1Configlines$(NbLines) = Line$ElseBreakEndIfWendBreakEndIfWendCloseFile(#FILE_ReadConfig)If NbLines = 0ProcedureReturn 0ElseAnalyzeSettings_Common(*Source, NbLines)ProcedureReturn 1EndIfElseProcedureReturn 0EndIfEndProcedureProcedure AnalyzeProjectSettings(*Source.SourceFile, *Buffer, Length, IsTempFile)If SaveProjectSettings = #SAVESETTINGS_DoNotSave And IsTempFile = 0 ; don't save anythingProcedureReturn LengthEndIfIf IsTempFile = 0*Source\Debugger = 1 ; default if the option isn't found*Source\ErrorLog = 1*Source\EnableASM = 0*Source\EnableThread = 0*Source\EnableXP = 1*Source\EnableWayland = 0*Source\EnableAdmin = 0*Source\EnableUser = 0*Source\DPIAware = 1*Source\DllProtection = 0*Source\SharedUCRT = 0*Source\EnableOnError = 0*Source\VersionInfo = 0*Source\ErrorLog = 1*Source\NbConstants = 0*Source\LastCompiledLines = 0*Source\CustomDebugger= 0*Source\DebuggerType = 1*Source\CustomWarning = 0*Source\WarningMode = 1*Source\CustomCompiler= 0*Source\EnablePurifier = 0*Source\PurifierGranularity$ = ""EndIfLoading_FirstVisibleLine = 0Loading_CurrentLine = 0Loading_CurrentColumn = 0Loading_FoldingState$ = ""IsIDEConfigPresent = 0ReturnValue = Length; old type source file;If Length > 20 And FindMemoryString(*Buffer+Length-20, 20, "; EOF", 1)ReturnValue = AnalyzeSettings_Old(*Source, *Buffer, Length)ElseIf IsTempFile ; for temp file, it is only inside the current source.ReturnValue = AnalyzeSettings_SourceFile(*Source, *Buffer, Length)ElseIf SaveProjectSettings = #SAVESETTINGS_EndOfFileResult = AnalyzeSettings_SourceFile(*Source, *Buffer, Length)If Result < Length ; settings were foundReturnValue = ResultElseIf AnalyzeSettings_ConfigFile(*Source) ; found in filename.pb.cfgReturnValue = LengthElseAnalyzeSettings_ProjectFile(*Source) ; check common config fileReturnValue = LengthEndIfElseIf SaveProjectSettings = #SAVESETTINGS_PerFileCfgIf AnalyzeSettings_ConfigFile(*Source)ReturnValue = LengthElseIf AnalyzeSettings_ProjectFile(*Source)ReturnValue = LengthElseReturnValue = AnalyzeSettings_SourceFile(*Source, *Buffer, Length)EndIfElseIf SaveProjectSettings = #SAVESETTINGS_PerFolderCfgIf AnalyzeSettings_ProjectFile(*Source)ReturnValue = LengthElseIf AnalyzeSettings_ConfigFile(*Source)ReturnValue = LengthElseReturnValue = AnalyzeSettings_SourceFile(*Source, *Buffer, Length)EndIfEndIfEndIf; if no config options are found, then use the defaultsIf IsIDEConfigPresent = 0SetCompileTargetDefaults(*Source) ; set the default values*Source\ErrorLog = OptionErrorLogEndIfProcedureReturn ReturnValueEndProcedureProcedure FindSourceFile(FileName$)ForEach FileList()If @FileList() <> *ProjectInfo And IsEqualFile(FileName,ドル FileList()\FileName$)ProcedureReturn @FileList()EndIfNext FileList()EndProcedureProcedure LoadSourceFile(FileName,ドル Activate = 1)success = 0; Check if this is a project file;If IsProjectFile(FileName$)LoadProject(FileName$)ProcedureReturn 0EndIf; check if the source is already opened...;If FindSourceFile(FileName$)If ActivateChangeActiveSourcecode()ChangeStatus("", 0)EndIfProcedureReturn 1EndIf; Check if this is a form (file extension only for now); NOTE: it needs to be after the already opened check !If LCase(GetExtensionPart(FileName$)) = "pbf"OpenForm(FileName$)RecentFiles_AddFile(FileName,ドル #False)AddTools_Execute(#TRIGGER_SourceLoad, *ActiveSource)LinkSourceToProject(*ActiveSource) ; Link To project (If any)ProcedureReturn 1EndIf; reset the current sourceIf *ActiveSourceChangeCurrentElement(FileList(), *ActiveSource)EndIfChangeStatus(Language("FileStuff","StatusLoading"), -1)If ReadFile(#FILE_LoadSource, FileName$); try to detect the encoding firstFormat = ReadStringFormat(#FILE_LoadSource)FileLength = Lof(#FILE_LoadSource)-Loc(#FILE_LoadSource) ; subtract the BOM size!If *ActiveSource And *ActiveSource\FileName$ = "" And GetSourceModified() = 0 And (ListSize(FileList()) = 1 Or (IsProject And ListSize(FileList()) = 2))*EmptySource = *ActiveSourceEndIfIf FileLength > 0*Buffer = AllocateMemory(FileLength+1)ElseNewSource(FileName,ドル #False) ; absolutely empty fileEndIfIf *BufferReadData(#FILE_LoadSource, *Buffer, FileLength); Don't check PB sources, as it can contains weird characters well handled by Scintilla: https://www.purebasic.fr/english/viewtopic.php?f=4&t=61467;If IsPureBasicFile(FileName$) = #FalseIsBinary = IsBinaryFile(*Buffer, FileLength);first check for OpenFile-TriggersIf IsCodeFile(FileName$) = 0 ;exclude all code files, even those the user addedAddTools_RunFileViewer = 1 ; to check if some tool has been executedAddTools_File$ = FileName$Ext$ = LCase(GetExtensionPart(FileName$))CloseFile(#FILE_LoadSource) ;better close the file here, or the tools might have problems to access itAddTools_Execute(#TRIGGER_OpenFile_Special, 0) ; special open file tools have highest priorityIf AddTools_RunFileViewerSelect IsBinaryCase 0AddTools_Execute(#TRIGGER_OpenFile_nonPB_Text, 0)Case 1AddTools_Execute(#TRIGGER_OpenFile_nonPB_Binary, 0)EndSelectEndIfIf AddTools_RunFileViewer = 0FreeMemory(*Buffer)ChangeStatus("", 0)ProcedureReturn 1EndIfEndIf;now check for common FileViewer tools;common FileViewer tools, will only trigger for binary files and non-PB files with an unknown BOMIf IsBinary Or (Format <> #PB_Ascii And Format <> #PB_UTF8)FreeMemory(*Buffer)If IsFile(#FILE_LoadSource)CloseFile(#FILE_LoadSource)EndIfChangeStatus("", 0)FileViewer_OpenFile(Filename$)ProcedureReturn 1EndIfEndIfNewSource(FileName,ドル #False)If Format = #PB_Ascii*ActiveSource\Parser\Encoding = 0SendEditorMessage(#SCI_SETCODEPAGE, 0, 0)Else*ActiveSource\Parser\Encoding = 1SendEditorMessage(#SCI_SETCODEPAGE, #SC_CP_UTF8, 0)EndIf; always call ChangeNewLineType(), even if the detected one is the os one,; because if the type can't be detected, the os standard is returned!;*ActiveSource\NewLineType = DetectNewLineType(*Buffer, FileLength)ChangeNewLineType(@*Buffer, @FileLength, #DEFAULT_NewLineType)FileLength = AnalyzeProjectSettings(*ActiveSource, *Buffer, FileLength, 0); get the settings and cut them offStreamTextIn(*Buffer, FileLength)FreeMemory(*Buffer)EndIfIf *Buffer Or FileLength = 0; update the file monitor info; Note that there could be a slight race condition here if the file is modified between loading; and getting this info, but since this is a GUI feature, such things should not be critical*ActiveSource\ExistsOnDisk = #True*ActiveSource\LastWriteDate = GetFileDate(*ActiveSource\Filename,ドル #PB_Date_Modified)*ActiveSource\DiskFileSize = FileSize(*ActiveSource\Filename$)DisableDebugger*ActiveSource\DiskChecksum = FileFingerprint(*ActiveSource\Filename,ドル #PB_Cipher_MD5)EnableDebuggerRecentFiles_AddFile(FileName,ドル #False)AddTools_Execute(#TRIGGER_SourceLoad, *ActiveSource)FullSourceScan(*ActiveSource)UpdateFolding(*ActiveSource, 0, -1)UpdateSelectionRepeat(); check if the first source was an empty new file and remove that..;If *EmptySourceRemoveSource(*EmptySource)EndIfIf EnableFoldingApplyFoldingInformation(Loading_FoldingState$)EndIfIf MemorizeCursorIf Loading_FirstVisibleLine > Loading_CurrentLineLoading_CurrentLine = Loading_FirstVisibleLineEndIfIf Loading_CurrentLine > 0 ; change the line, if it was written in the settings part of the fileChangeActiveLine(Loading_CurrentLine+1, Loading_FirstVisibleLine-Loading_CurrentLine-1) ;in the file, line is 0 based! (to support old behaviour)EndIfElseChangeActiveLine(1, 0)UpdateCursorPosition()EndIfIf MemorizeMarkers And MarkerLines$ <> ""ApplyMarkerString(MarkerLines$)EndIfChangeStatus(Language("FileStuff","StatusLoaded"), 1000)UpdateSourceStatus(0)success = 1*Debugger.DebuggerData = IsDebuggedFile(*ActiveSource) ; check if this is loaded for the debuggerIf *Debugger And *Debugger\ProgramState <> -1 ; must be a loaded exe!SetReadOnly(*ActiveSource\EditorGadget, 1); copy the error log from the file that created the debugger; for project related files, the log is always shared;If *ActiveSource\ProjectFile = 0*Source.SourceFile = FindTargetFromID(*Debugger\SourceID)If *Source = 0*Source = FindTargetFromID(*Debugger\TriggerTargetID)EndIfIf *Source And *Source\IsProject = 0 ; make sure its not a project target (in this case it is not a SourceFile struct at all!)*ActiveSource\LogSize = *Source\LogSizeFor i = 0 To *Source\LogSize-1*ActiveSource\LogLines$[i] = *Source\LogLines$[i]Next iEndIfEndIfEndIf; call this again to update the ErrorLog, ProcedureBrowser etc (and project stuff)ChangeActiveSourcecode()HistoryEvent(*ActiveSource, #HISTORY_Open)ElseMessageRequester(#ProductName,ドル Language("FileStuff","LoadError")+#NewLine+FileName,ドル #FLAG_Error)ChangeStatus(Language("FileStuff","LoadError"), 3000)EndIfIf IsFile(#FILE_LoadSource)CloseFile(#FILE_LoadSource)EndIfElseMessageRequester(#ProductName,ドル Language("FileStuff","LoadError")+#NewLine+FileName,ドル #FLAG_Error)ChangeStatus(Language("FileStuff","LoadError"), 3000)EndIf; If the first file can't be opened for any reasons, this pointer will be null;If *ActiveSourceSetActiveGadget(*ActiveSource\EditorGadget)EndIfProcedureReturn successEndProcedureProcedure SaveSourceFile(FileName$)If *ActiveSource = *ProjectInfoProcedureReturn 0EndIfIf *ActiveSource\ProjectFile = 0 And IsWindow(#WINDOW_Option) ; make sure the options are closed (for non-project files)OptionWindowEvents(#PB_Event_CloseWindow)EndIfIf *ActiveSource\IsFormFD_SelectWindow(*ActiveSource\IsForm)If FormWindows()\current_view = 0 ; Design view, we need to use the special form save routine. In code view, we just save the code as any other sourceFD_Save(FileName$)AddTools_Execute(#TRIGGER_SourceSave, *ActiveSource)ProcedureReturn 1EndIfEndIfChangeStatus(Language("FileStuff","StatusSaving"), -1)If CreateFile(#FILE_SaveSource, FileName$)If *ActiveSource\Parser\Encoding = 0WriteStringFormat(#FILE_SaveSource, #PB_Ascii)ElseWriteStringFormat(#FILE_SaveSource, #PB_UTF8)EndIfFileLength = GetSourceLength()If FileLength > 0*Buffer = AllocateMemory(FileLength+1)EndIfIf *BufferStreamTextOut(*Buffer, FileLength); set the newline back to what it was before in the fileChangeNewLineType(@*Buffer, @FileLength, *ActiveSource\NewLineType)WriteData(#FILE_SaveSource, *Buffer, FileLength)FreeMemory(*Buffer)EndIfIf *Buffer Or FileLength = 0*ActiveSource\FileName$ = FileName$ ; SaveProjectSettings() needs an updated FileName$ (https://www.purebasic.fr/english/viewtopic.php?f=4&t=59566)*ActiveSource\IsCode = IsCodeFile(FileName$)SaveProjectSettings(*ActiveSource, *ActiveSource\IsCode, 0, 1)CloseFile(#FILE_SaveSource); update the file monitor info*ActiveSource\ExistsOnDisk = #True*ActiveSource\LastWriteDate = GetFileDate(Filename,ドル #PB_Date_Modified)*ActiveSource\DiskFileSize = FileSize(Filename$)*ActiveSource\DiskChecksum = FileFingerprint(Filename,ドル #PB_Cipher_MD5)ChangeStatus(Language("FileStuff","StatusSaved"), 1000)Result = 1UpdateSourceStatus(0)RecentFiles_AddFile(FileName,ドル #False)AddTools_Execute(#TRIGGER_SourceSave, *ActiveSource)ElseCloseFile(#FILE_SaveSource)DeleteFile(FileName$)MessageRequester(#ProductName,ドル Language("FileStuff","SaveError")+#NewLine+FileName,ドル #FLAG_Error)ChangeStatus(Language("FileStuff","SaveError"), 3000)Result = 0EndIfElseMessageRequester(#ProductName,ドル Language("FileStuff","SaveError")+#NewLine+FileName,ドル #FLAG_Error)ChangeStatus(Language("FileStuff","SaveError"), 3000)Result = 0EndIfSetActiveGadget(*ActiveSource\EditorGadget)UpdateMenuStates() ; to notice the change from new file to unsaved file (#MENU_DiffCurrent)ProcedureReturn ResultEndProcedureProcedure LoadTempFile(FileName$) ; load the specified file over the current opened sourceIf *ActiveSource = *ProjectInfoProcedureReturn 0EndIfSuccess = 0If ReadFile(#FILE_LoadSource, FileName$)Format = ReadStringFormat(#FILE_LoadSource)FileLength = Lof(#FILE_LoadSource)-Loc(#FILE_LoadSource) ; subtract the BOM size!If FileLength > 0*Buffer = AllocateMemory(FileLength+1)EndIfIf Format = #PB_Ascii*ActiveSource\Parser\Encoding = 0SendEditorMessage(#SCI_SETCODEPAGE, 0, 0)Else*ActiveSource\Parser\Encoding = 1SendEditorMessage(#SCI_SETCODEPAGE, #SC_CP_UTF8, 0)EndIfIf FileLength > 0*Buffer = AllocateMemory(FileLength+1)Else ; For empty text, we need to clear the scintilla component (https://www.purebasic.fr/english/viewtopic.php?p=615379#p615379)StreamTextIn(ToUTF8(""), 0)EndIfIf *BufferReadData(#FILE_LoadSource, *Buffer, FileLength); always call ChangeNewLineType(), even if the detected one is the os one,; because if the type can't be detected, the os standard is returned!;ChangeNewLineType(@*Buffer, @FileLength, #DEFAULT_NewLineType)FileLength = AnalyzeProjectSettings(*ActiveSource, *Buffer, FileLength, 1); get the settings and cut them offStreamTextIn(*Buffer, FileLength)FreeMemory(*Buffer)EndIfIf *Buffer Or FileLength = 0Success = 1; HighlightArea(0, -1)FullSourceScan(*ActiveSource)UpdateFolding(*ActiveSource, 0, -1)UpdateSelectionRepeat()If EnableFoldingApplyFoldingInformation(Loading_FoldingState$)EndIfIf Loading_FirstVisibleLine > Loading_CurrentLineLoading_CurrentLine = Loading_FirstVisibleLineEndIfIf Loading_CurrentLine > 0 ; change the line, if it was written in the settings part of the fileChangeActiveLine(Loading_CurrentLine+1, Loading_FirstVisibleLine-Loading_CurrentLine-1) ;in the file, line is 0 based! (to support old behaviour)EndIf; this is only for tempfilesIf Loading_CurrentColumn > 1SendEditorMessage(#SCI_GOTOPOS, SendEditorMessage(#SCI_GETCURRENTPOS, 0, 0)+Loading_CurrentColumn-1, 0)UpdateCursorPosition()EndIf*Debugger.DebuggerData = IsDebuggedFile(*ActiveSource) ; check if this is loaded for the debuggerIf *Debugger And *Debugger\ProgramState <> -1 ; must be a loaded exe!SetReadOnly(*ActiveSource\EditorGadget, 1); copy the error log from the file that created the debugger; for project related files, the log is always shared;If *ActiveSource\ProjectFile = 0*Source.SourceFile = FindTargetFromID(*Debugger\SourceID)If *Source = 0*Source = FindTargetFromID(*Debugger\TriggerTargetID)EndIfIf *Source And *Source\IsProject = 0 ; make sure its not a project target (in this case it is not a SourceFile struct at all!)*ActiveSource\LogSize = *Source\LogSizeFor i = 0 To *Source\LogSize-1*ActiveSource\LogLines$[i] = *Source\LogLines$[i]Next iEndIfEndIfEndIfIf MarkerLines$ <> ""ApplyMarkerString(MarkerLines$)EndIf; call this again to update the ErrorLogChangeActiveSourcecode()EndIfCloseFile(#FILE_LoadSource)EndIfSetActiveGadget(*ActiveSource\EditorGadget); CompilerIf #CompileWindows; InvalidateRect_(WindowID(#WINDOW_Main), 0, 0); CompilerEndIfProcedureReturn SuccessEndProcedureProcedure SaveTempFile(FileName$)If *ActiveSource = *ProjectInfoProcedureReturn 0EndIfIf CreateFile(#FILE_SaveSource, FileName$)If *ActiveSource\Parser\Encoding = 0WriteStringFormat(#FILE_SaveSource, #PB_Ascii)ElseWriteStringFormat(#FILE_SaveSource, #PB_UTF8)EndIfFileLength = GetSourceLength()If FileLength > 0*Buffer = AllocateMemory(FileLength+1)EndIfIf *BufferStreamTextOut(*Buffer, FileLength); temp files are always in the OS newline formatChangeNewLineType(@*Buffer, @FileLength, #DEFAULT_NewLineType)WriteData(#FILE_SaveSource, *Buffer, FileLength)FreeMemory(*Buffer)EndIfIf *Buffer Or FileLength = 0SaveProjectSettings(*ActiveSource, *ActiveSource\IsCode, 1, 0)CloseFile(#FILE_SaveSource)Result = 1ElseCloseFile(#FILE_SaveSource)DeleteFile(FileName$)Result = 0EndIfElseResult = 0EndIfSetActiveGadget(*ActiveSource\EditorGadget)ProcedureReturn ResultEndProcedureProcedure LoadSource()If *ActiveSource = *ProjectInfo And IsProjectPath$ = GetPathPart(ProjectFile$)ElseIf *ActiveSource\FileName$Path$ = GetPathPart(*ActiveSource\FileName$)ElsePath$ = SourcePath$EndIfFileName$ = OpenFileRequester(Language("FileStuff","OpenFileTitle"), Path,ドル Language("FileStuff","Pattern"), SelectedFilePattern, #PB_Requester_MultiSelection)If FileName$ <> ""While WindowEvent() : WendSelectedFilePattern = SelectedFilePattern()While FileName$ <> ""LoadSourceFile(FileName$); Flush events. So when many sources are opened at once, the User can see a bit the; progress, instead of just an unresponsive window for quite a while.; There is almost no flicker anymore, so it actually looks quite good.;; Note: don't put this in the LoadSourceFile() routine as it can be call from the debugger and flushing the event will get another debug event !FlushEvents()FileName$ = NextSelectedFileName()WendEndIfEndProcedureProcedure OpenIncludeOnDoubleClick()UpdateCursorPosition()CurrentWord$ = LCase(GetCurrentWord())Line$ = GetCurrentLine()NameStart = *ActiveSource\CurrentColumnCharsWhile ValidCharacters(Asc(Mid(Line,ドル NameStart, 1))) = 1 ; skip the rest of 'IncludeFile'NameStart + 1WendWhile Mid(Line,ドル NameStart, 1) = " " ; skip spacesNameStart + 1WendIf Mid(Line,ドル NameStart, 1) = Chr(34) ; only if it is a literal string.. constants don't workNameStart + 1NameEnd = NameStartWhile Mid(Line,ドル NameEnd, 1) <> Chr(34) And NameEnd < Len(Line$)NameEnd + 1WendFileName$ = Mid(Line,ドル NameStart, NameEnd - NameStart)FileName$ = ResolveRelativePath(GetPathPart(*ActiveSource\FileName$), FileName$)If FileSize(FileName$) > -1 ; check if the result is valid..If CurrentWord$ = "includebinary"FileViewer_OpenFile(FileName$)ElseLoadSourceFile(FileName$)EndIfEndIfEndIfEndProcedureProcedure SaveSourceAs()Static NewSourcePath$If *ActiveSource = *ProjectInfoProcedureReturn 0EndIfIf *ActiveSource\FileName$; Uses the full filename as input like other software;NewSourcePath$ = *ActiveSource\FileName$ElseIf NewSourcePath$ = ""; if the file was already saved, use its path as a base.;NewSourcePath$ = GetPathPart(SourcePath$)ElseNewSourcePath$ = GetPathPart(NewSourcePath$) ; New file to save, don't specify a filenameEndIfFileName$ = SaveFileRequester(Language("FileStuff","SaveFileTitle"), NewSourcePath,ドル Language("FileStuff","Pattern"), SelectedFilePattern)If FileName$ <> ""SelectedFilePattern = SelectedFilePattern()NewSourcePath$ = GetPathPart(FileName$)If GetExtensionPart(GetFilePart(FileName$)) = ""If SelectedFilePattern <= 1 ; (=all pb files or pb sources only)If *ActiveSource\IsFormFileName$ + #FormFileExtensionElseFileName$ + #SourceFileExtensionEndIfForceFileCheck = 1ElseIf SelectedFilePattern = 2 ; (=pbi only)FileName$ + #IncludeFileExtensionForceFileCheck = 1ElseIf SelectedFilePattern = 4 ; (=pbf only)FileName$ + #FormFileExtensionForceFileCheck = 1EndIfEndIf; Check if file already open in IDE*SourceBeingClosed = 0ForEach FileList()If @FileList() <> *ActiveSourceIf IsEqualFile(FileList()\FileName,ドル FileName$)PromptedUser = 1If MessageRequester(#ProductName,ドル Language("FileStuff","FileIsOpen")+#NewLine+Language("FileStuff","CloseOverWrite"), #PB_MessageRequester_YesNo|#FLAG_Warning) = #PB_MessageRequester_Yes*SourceBeingClosed = @FileList()BreakElseProcedureReturn SaveSourceAs() ; try againEndIfEndIfEndIfNextIf *SourceBeingClosed <> 0RemoveSource(*SourceBeingClosed)EndIf; On Cocoa the file exists dialog is already in the SavePanel, so only popup if we added an extension;If (ForceFileCheck Or #CompileMacCocoa = 0) And *SourceBeingClosed = 0If FileSize(FileName$) > -1 And IsEqualFile(FileName,ドル *ActiveSource\FileName$) = 0 ; file exist checkIf MessageRequester(#ProductName,ドル Language("FileStuff","FileExists")+#NewLine+Language("FileStuff","OverWrite"), #PB_MessageRequester_YesNo|#FLAG_Warning) = #PB_MessageRequester_NoProcedureReturn SaveSourceAs() ; try againEndIfEndIfEndIfResult = SaveSourceFile(FileName$)If ResultUnlinkSourceFromProject(*ActiveSource, #True)*ActiveSource\FileName$ = FileName$LinkSourceToProject(*ActiveSource)UpdateMainWindowTitle() ; we now have a new filenameRefreshSourceTitle(*ActiveSource)HistoryEvent(*ActiveSource, #HISTORY_SaveAs)UpdateIsCodeStatus() ; re-scan/re-highlight in case the IsCode value has changedEndIfProcedureReturn ResultElseProcedureReturn -1 ; indicate user abort (needed when called by CheckSourceSaved())EndIfEndProcedureProcedure SaveSource()If *ActiveSource\FileName$ = ""ProcedureReturn SaveSourceAs()ElseResult = SaveSourceFile(*ActiveSource\FileName$)If ResultHistoryEvent(*ActiveSource, #HISTORY_Save)EndIfProcedureReturn ResultEndIfEndProcedureProcedure RemoveSource(*Source.SourceFile = 0)FlushEvents()If *Source = 0*Source = *ActiveSourceEndIfIf *Source = *ProjectInfoProcedureReturnEndIfIf *Source = *ActiveSourceDeleteCurrent = #TrueElseDeleteCurrent = #FalseEndIfHistoryEvent(*Source, #HISTORY_Close)AddTools_Execute(#TRIGGER_SourceClose, *Source); Make sure the diff window is closed if this source is part of the diff; (because then we loose the source for refreshes, which will crash then)If IsWindow(#WINDOW_Diff)CheckDiffFileClose(*Source)EndIfIf DeleteCurrent And *Source\ProjectFile = 0 And IsWindow(#WINDOW_Option) ; make sure the options are closed (for non-project files)OptionWindowEvents(#PB_Event_CloseWindow)EndIf; disconnect source from the project (if any)UnlinkSourceFromProject(*Source, #True); is this the mainfile for a debugger?*Debugger = FindDebuggerFromID(*Source\DebuggerID)If *DebuggerDebugger_Kill(*Debugger)EndIfIf *Source = *WarningWindowSource ; Is this the source that caused the Warning window to open ?WarningWindowEvents(#PB_Event_CloseWindow) ; will set *WarningWindowSource to 0EndIfGadget = *Source\EditorGadgetFreeSourceItemArray(@*Source\Parser)If FileSize(*Source\RunExecutable$) >= 0CompilerIf #CompileMacDeleteDirectory(*Source\RunExecutable,ドル "*", #PB_FileSystem_Recursive) ; a .app is a directory!CompilerElseDeleteFile(*Source\RunExecutable$)CompilerEndIfEndIf; Delete form specific dataIf *Source And *Source\IsFormIf propgridgrid_StopEditing(propgrid)EndIf; Closing a form source and switching to another opened form crashed the IDE with the following lines uncommentedChangeCurrentElement(FormWindows(),*Source\IsForm)DeleteElement(FormWindows(), #True) ; If the first element is deleted then the second one is selected to still have a current element.propgrid_gadget = 0propgrid_win = 0propgrid_menu = 0propgrid_toolbar = 0propgrid_statusbar = 0EndIfIf DeleteCurrentIndex = ListIndex(FileList())If Index = 0DeleteElement(FileList())FirstElement(FileList())ElseDeleteElement(FileList())EndIf*ActiveSource = 0ElsePushListPosition(FileList())ChangeCurrentElement(FileList(), *Source)Index = ListIndex(FileList())DeleteElement(FileList())PopListPosition(FileList())EndIfRemoveTabBarGadgetItem(#GADGET_FilesPanel, Index)If ListSize(FileList()) = 0 Or (ListSize(FileList()) = 1 And *ProjectInfo)NewSource("", #True)HistoryEvent(*ActiveSource, #HISTORY_Create)EndIfChangeActiveSourcecode(); make sure the options are closed (for non-project files); If this is true, we switched from a project file to non-project file while the options; are open. so close them now;If *ActiveSource\ProjectFile = 0 And IsWindow(#WINDOW_Option)OptionWindowEvents(#PB_Event_CloseWindow)EndIf; Activate the next EditorGadget;If *ActiveSourceSetActiveGadget(*ActiveSource\EditorGadget)EndIf; Flush events. So when many sources are closed at once, (close all, IDE close) the User can see a bit the; progress, instead of just an unresponsive window for quite a while.; There is almost no flicker anymore, so it actually looks quite good.FlushEvents(); Remove old EditorGadget; Fix a stack corruption on OSX, needs to be after FlushEvent().; All events must be processed before the EditorGadget is removed.FreeEditorGadget(Gadget)EndProcedureProcedure CheckSourceSaved(*Source.SourceFile = 0)If *Source = 0*Source = *ActiveSourceEndIfIf *Source = *ProjectInfoProcedureReturn 1EndIf; Decide if a save prompt is neededPromptUser = #FalseIf GetSourceModified(*Source)If *Source\FileName$ <> ""PromptUser = #TrueElse; Only prompt user to save a 'New' source if it's non-emptyIf ScintillaSendMessage(*Source\EditorGadget, #SCI_GETLENGTH) > 0PromptUser = #TrueEndIfEndIfEndIfIf PromptUser; need to make it current for display of the questionIf *Source <> *ActiveSourceChangeCurrentElement(FileList(), *Source)ChangeActiveSourcecode(*ActiveSource)FlushEvents()EndIfIf *ActiveSource\FileName$ = ""Text$ = Language("FileStuff","ModifiedNew")ElseText$ = LanguagePattern("FileStuff","Modified", "%filename%", GetFilePart(*ActiveSource\FileName$))EndIfResult = MessageRequester(#ProductName,ドル Text,ドル #PB_MessageRequester_YesNoCancel|#FLAG_Question)If Result = #PB_MessageRequester_YesStatus = SaveSource()If Status = 0 And *ActiveSource\FileName$ <> "" And (SaveProjectSettings = #SAVESETTINGS_PerFileCfg Or SaveProjectSettings = #SAVESETTINGS_PerFolderCfg); if the compiler options are not stored at the end of the sourcefile,; we save them even if the source is not saved.; Do not report an error though (for example if the source was loaded from CD)SaveProjectSettings(*ActiveSource, *ActiveSource\IsCode, 0, 0)EndIfProcedureReturn StatusElseIf Result = #PB_MessageRequester_NoIf *ActiveSource\FileName$ <> "" And (SaveProjectSettings = #SAVESETTINGS_PerFileCfg Or SaveProjectSettings = #SAVESETTINGS_PerFolderCfg); if the compiler options are not stored at the end of the sourcefile,; we save them even if the source is not saved.; Do not report an error though (for example if the source was loaded from CD)SaveProjectSettings(*ActiveSource, *ActiveSource\IsCode, 0, 0)EndIfProcedureReturn 1ElseIf Result = #PB_MessageRequester_CancelProcedureReturn -1EndIfElse; Why should we save the setting even if a source a not modified ?;If *Source\FileName$ <> "" And (SaveProjectSettings = #SAVESETTINGS_PerFileCfg Or SaveProjectSettings = #SAVESETTINGS_PerFolderCfg); if the compiler options are not stored at the end of the sourcefile,; we save them even if the source is not saved.; Do not report an error though (for example if the source was loaded from CD)SaveProjectSettings(*Source, *Source\IsCode, 0, 0)EndIfProcedureReturn 1EndIfEndProcedureProcedure SaveAll() ; saves all sources, but does not close them!*CurrentSource = *ActiveSource ; to restore at the end*DisplayedSource = *ActiveSource ; for switching to "Save as..." sourceForEach FileList()If @FileList() <> *ProjectInfo*ActiveSource = @FileList()If GetSourceModified()If *ActiveSource\FileName$ = ""; display the source we are about to save*ActiveSource = *DisplayedSource ; needed for the correct source switchChangeActiveSourcecode() ; *Activesource is correct again now*DisplayedSource = *ActiveSourceFlushEvents() ; update the displaySaveSourceAs(); save the sourceElseSaveSourceFile(*ActiveSource\FileName$)HistoryEvent(*ActiveSource, #HISTORY_Save)EndIfEndIfEndIfNext FileList(); go back to the viewed sourcecode*ActiveSource = *DisplayedSourceChangeCurrentElement(FileList(), *CurrentSource)ChangeActiveSourceCode()EndProcedure; this function is called when exiting the editor; Note: now does not remove the source!Procedure CheckAllSourcesSaved(); to avoid flicker, we only switch sources for real if there; is some user interaction needed (ie a "do you want to save" dialog);*Displayed = *ActiveSourceNbFiles = ListSize(FileList())If *ProjectInfoNbFiles - 1EndIfClearList(OpenFiles())LastElement(FileList())For i = 1 To NbFilesIf @FileList() = *ProjectInfoPreviousElement(FileList())Else*ActiveSource = @FileList()If GetSourceModified()*ActiveSource = *DisplayedChangeActiveSourcecode()*Displayed = *ActiveSourceEndIf; call this even if GetSourceModified() is false, so; we update the settings file;Result = CheckSourceSaved()If Result = 1If *ActiveSource\FileName$ <> "" And AutoReload And *ActiveSource\ProjectFile = 0 ; only save the filenames if autoreload is on (and not part of a project as a project will reopen itself its previously opened files)AddElement(OpenFiles())OpenFiles() = *ActiveSource\FileName$EndIfPreviousElement(FileList())Else*ActiveSource = *Displayed ; reset the active sourceChangeActiveSourcecode()ProcedureReturn 0EndIfEndIfNext i*ActiveSource = *Displayed ; reset the active sourceChangeActiveSourcecode()ProcedureReturn 1EndProcedureProcedure AutoSave() ; called before compiling / creating executable to do the autosaveProcedure AutoSave() ; called before compiling / creating executable to do the autosaveIf AutoSaveAll ; save all sources*RealActiveSource = *ActiveSource ; have to change the *ActiveSource for the GetSourceModified()ForEach FileList()If @FileList() <> *ProjectInfo*ActiveSource = @FileList()If *ActiveSource\FileName$ <> "" And GetSourceModified() ; don't save <new> filesSaveSourceFile(*ActiveSource\FileName$)HistoryEvent(*ActiveSource, #HISTORY_Save)EndIfEndIfNext FileList()*ActiveSource = *RealActiveSourceChangeCurrentElement(FileList(), *ActiveSource)Else ; save the current source onlyIf *ActiveSource <> *ProjectInfoIf *ActiveSource\FileName$ <> "" And GetSourceModified() ; don't save <new> filesSaveSourceFile(*ActiveSource\FileName$)HistoryEvent(*ActiveSource, #HISTORY_Save)EndIfEndIfEndIfEndProcedureProcedure ShowInFolder()If *ActiveSourceIf *ActiveSource = *ProjectInfoFileToShow$ = ProjectFile$ElseFileToShow$ = *ActiveSource\FileName$EndIfIf FileToShow$ShowExplorerFile(FileToShow$)EndIfEndIfEndProcedureProcedure ReloadSource()If *ActiveSource And *ActiveSource <> *ProjectInfo And *ActiveSource\Filename$If GetSourceModified() = #False Or MessageRequester(#ProductName,ドル Language("FileStuff","ReloadModified"), #PB_MessageRequester_YesNo|#FLAG_Warning) = #PB_MessageRequester_Yes; make sure the compiler options are closed if its not a project (as they get reloaded from file too);If IsWindow(#WINDOW_Option) ; make sure the options are closedIf (*ActiveSource <> *ProjectInfo And *ActiveSource\ProjectFile = 0)OptionWindowEvents(#PB_Event_CloseWindow)EndIfEndIf; Simply reload the file over the current source;If LoadTempFile(*ActiveSource\FileName$); we reverted to the disk state, so its no longer modifiedUpdateSourceStatus(#False)HistoryEvent(*ActiveSource, #HISTORY_Reload)EndIfEndIfEndIfEndProcedure; called also after prefs update;Procedure SetupFileMonitor()Static TimerRunning = 0If TimerRunning = 0 And MonitorFileChanges; need to setup the timer;; Note: we check once every 5 seconds which should be enough; we also check when the main window gets the focus, so when the user switches to; another program to make a change on disk, it is noticed immediately on return;; the timer events are only used to trigger an update when the IDE has the focus, so the; requester does not pop up out of nowhere (it will be noticed on the next focus change then); See UserInterface.pb for the timer event handling;AddWindowTimer(#WINDOW_Main, #TIMER_FileMonitor, 5000)TimerRunning = 1ElseIf TimerRunning And MonitorFileChanges = 0; need to stop the timerRemoveWindowTimer(#WINDOW_Main, #TIMER_FileMonitor)TimerRunning = 0EndIfEndProcedureGlobal FileMonitorWindowOpenProcedure FileMonitorWindowEvents(EventID)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()ElseGadgetID = EventGadget()EndIfIf EventID = #PB_Event_GadgetSelect GadgetIDCase #GADGET_FileMonitor_Reload; make sure the compiler options are closed if its not a project (as they get reloaded from file too);If IsWindow(#WINDOW_Option) ; make sure the options are closedIf (*ActiveSource <> *ProjectInfo And *ActiveSource\ProjectFile = 0)OptionWindowEvents(#PB_Event_CloseWindow)EndIfEndIf; Simply reload the file over the current source;If LoadTempFile(*ActiveSource\FileName$); we reverted to the disk state, so its no longer modifiedUpdateSourceStatus(#False)HistoryEvent(*ActiveSource, #HISTORY_Reload)EndIf; Update the on-disk info, as LoadTempFile() does not do it;*ActiveSource\LastWriteDate = GetFileDate(*ActiveSource\Filename,ドル #PB_Date_Modified)*ActiveSource\DiskFileSize = FileSize(*ActiveSource\Filename$)*ActiveSource\DiskChecksum = FileFingerprint(*ActiveSource\Filename,ドル #PB_Cipher_MD5)Quit = #TrueCase #GADGET_FileMonitor_Cancel; mark the file as modified, as it is now different from diskUpdateSourceStatus(#True); update the on-disk info*ActiveSource\LastWriteDate = GetFileDate(*ActiveSource\Filename,ドル #PB_Date_Modified)*ActiveSource\DiskFileSize = FileSize(*ActiveSource\Filename$)*ActiveSource\DiskChecksum = FileFingerprint(*ActiveSource\Filename,ドル #PB_Cipher_MD5)Quit = #TrueCase #GADGET_FileMonitor_ViewDiff; diff the current source to disk. do not swap, so it is Source -> Disk; do not close the requester just yetDiffSourceToFile(*ActiveSource, *ActiveSource\Filename,ドル #False)EndSelectElseIf EventID = #PB_Event_CloseWindow; this window has no close button, but this gets called; when the window should be closed because of a prefs update or IDE shutdownQuit = #TrueEndIfIf QuitDisableWindow(#WINDOW_Main, 0) ; this must be first, so the main window can get the focus!CloseWindow(#WINDOW_FileMonitor)FileMonitorWindowOpen = 0FileMonitorEvent() ; check again, in case there was more than one file changedEndIfEndProcedureProcedure FileMonitorEvent()If MonitorFileChanges And FileMonitorWindowOpen = 0 ; do not check when the requester is open!ForEach FileList()If @FileList() <> *ProjectInfo And FileList()\ExistsOnDisk And FileList()\FileName$ And FileList()\IsForm = #False ; only check saved files (ignore form files as they don't use the same save routines)Size = FileSize(FileList()\FileName$) ; check size first to know if it still existsIf Size < 0; file deleted on diskFileList()\ExistsOnDisk = #False ; fire no more monitor events from now on (until it is saved again)*Current = @FileList()ChangeActiveSourceCode() ; show the file to the userFlushEvents()If MessageRequester(#ProductName,ドル LanguagePattern("FileStuff","DeletedOnDisk", "%filename%", GetFilePart(FileList()\FileName$)), #PB_MessageRequester_YesNo) = #PB_MessageRequester_YesSaveSourceFile(*ActiveSource\Filename$)HistoryEvent(*ActiveSource, #HISTORY_Save)ElseUpdateSourceStatus(1) ; mark file as modified, so the user is promted to save it when he closes itEndIf; continue on with the next checkChangeCurrentElement(FileList(), *Current)ElseIf Size <> FileList()\DiskFileSize Or (FileList()\LastWriteDate <> GetFileDate(FileList()\FileName,ドル #PB_Date_Modified) And FileList()\DiskChecksum <> FileFingerprint(FileList()\FileName,ドル #PB_Cipher_MD5)); file modified on disk; Set this here before making the changes, otherwise FlushEvents() below causes a recursion and we miss updates to multiple filesFileMonitorWindowOpen = 1; update disk informationFileList()\LastWriteDate = GetFileDate(FileList()\Filename,ドル #PB_Date_Modified)FileList()\DiskFileSize = FileSize(FileList()\Filename$)FileList()\DiskChecksum = FileFingerprint(FileList()\Filename,ドル #PB_Cipher_MD5)ChangeActiveSourceCode() ; show the file to the userFlushEvents()If GetSourceModified() ; different message if the file is modifiedMessage$ = LanguagePattern("FileStuff","ModifiedOnDisk2", "%filename%", GetFilePart(FileList()\Filename$))ElseMessage$ = LanguagePattern("FileStuff","ModifiedOnDisk1", "%filename%", GetFilePart(FileList()\Filename$))EndIfFileMonitorWindowDialog = OpenDialog(?Dialog_FileMonitor, WindowID(#WINDOW_Main))If FileMonitorWindowDialogSetGadgetText(#GADGET_FileMonitor_Text, Message$)FileMonitorWindowDialog\GuiUpdate()StickyWindow(#WINDOW_FileMonitor, 1)DisableWindow(#WINDOW_Main, 1)SetActiveWindow(#WINDOW_FileMonitor)SetActiveGadget(#GADGET_FileMonitor_Reload)ProcedureReturn ; do not continue checking until the requester window is closed by the userElseFileMonitorWindowOpen = 0 ; should not happenEndIfEndIfEndIfNext FileList()ChangeCurrentElement(FileList(), *ActiveSource)EndIfEndProcedure
此处可能存在不合适展示的内容,页面不予展示。您可通过相关编辑功能自查并修改。
如您确认内容无涉及 不当用语 / 纯广告导流 / 暴力 / 低俗色情 / 侵权 / 盗版 / 虚假 / 无价值内容或违法国家有关法律法规的内容,可点击提交进行申诉,我们将尽快为您处理。