; --------------------------------------------------------------------------------------------; 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.; --------------------------------------------------------------------------------------------; Diff tools for the PB IDE;;- Globals; Define this to true if the ScintillaGadget supports the following defined messages; to have a margin with text in it (needs a more recent scintilla version); If supported, we can show line numbers (with gaps) in the diff output which is very nice;#SCINTILLA_TEXT_MARGIN = #True; Represents one line in a file to diff; Used for the markers in the scintilla gadget;Enumeration#DIFF_Empty ; for empty lines when changes are made in other file#DIFF_Equal#DIFF_Added#DIFF_Removed#DIFF_Changed#DIFF_StateCountEndEnumeration#DIFF_ChangeMarker = #DIFF_StateCount * 2; future modes may be added here if we have a backup system etc;Enumeration#DIFF_FileToFile#DIFF_SourceToFileEndEnumeration; Represents a block of styled characters for the final diff documentStructure DiffStyleBlock*StartLength.lLines.lStyle.lEndStructure; represents a file entry in directory diffStructure DiffFileName$ ; may differ if FS is case insensitive, but we use only one name for display anywayStyle.lDateA.l ; last modifiedDateB.lEndStructure; information about the two files to diff;Global DiffA_Size, DiffB_SizeGlobal DiffA_Lines, DiffB_Lines ; # of linesGlobal DiffA_Utf8, DiffB_Utf8 ; is utf8 bom presentGlobal *DiffA_Buffer, *DiffB_Buffer ; memory buffer containing original files (stays allocated until diff is closed)Global *DiffA_Start, *DiffB_Start ; buffer offset after BOM (if any)Global NewList StyleA.DiffStyleBlock() ; resulting diff blocks (stays allocated until diff is closed)Global NewList StyleB.DiffStyleBlock()Global DiffA_Title,ドル DiffB_Title$Global DiffA_File,ドル DiffB_File$Global *DiffSource.SourceFile, DiffMode; for directory diff;Global DiffDirectoryMode ; 0=files only, 1=directory+files, 2=directory onlyGlobal DiffA_Base,ドル DiffB_Base,ドル DiffPattern$Global NewList DiffFiles.DiffFile(); For the scroll syncGlobal DiffScrollX, DiffScrollY, DiffZoom; For stylingGlobal DiffStyleGadget, DiffStyleBase, DiffSwappedGlobal DiffOpenPattern ; not stored in prefsDeclare UpdateDiffGadget(IsLeft, List Style.DiffStyleBlock(), SetText)Declare UpdateDiffFileList();- Diff window; Show/hide the progress gadgets and take other appropriate actions;Procedure ShowDiffProgress(ShowProgress)If ShowProgressState = 0ElseState = 1EndIfHideGadget(#GADGET_Diff_Busy, State)If DiffDirectoryMode = 0HideGadget(#GADGET_Diff_Splitter, 1-State)ElseHideGadget(#GADGET_Diff_FileTitle, 1-State)If DiffDirectoryMode = 1HideGadget(#GADGET_Diff_Splitter2, 1-State)ElseHideGadget(#GADGET_Diff_Files, 1-State)EndIfEndIfEndProcedureProcedure ResizeDiffSplitterContent() ; triggered on a splitter movetext = Max(GetRequiredHeight(#GADGET_Diff_Title1), 18)w = GadgetWidth(#GADGET_Diff_Container1)h = GadgetHeight(#GADGET_Diff_Container1)ResizeGadget(#GADGET_Diff_Title1, 0, 0, w, text)ResizeGadget(#GADGET_Diff_File1, 0, text+2, w, h-text-2)w = GadgetWidth(#GADGET_Diff_Container2)h = GadgetHeight(#GADGET_Diff_Container2)ResizeGadget(#GADGET_Diff_Title2, 0, 0, w, text)ResizeGadget(#GADGET_Diff_File2, 0, text+2, w, h-text-2)EndProcedureProcedure UpdateDiffToolbar(); open tool, swap, refresh, up/down is always onIf DiffDirectoryMode < 2 ; files visibleFileState = 0ElseFileState = 1EndIfDisableToolBarButton(#TOOLBAR_Diff, #MENU_Diff_Open1, FileState)DisableToolBarButton(#TOOLBAR_Diff, #MENU_Diff_Open2, FileState)DisableToolBarButton(#TOOLBAR_Diff, #MENU_Diff_Colors, FileState)DisableToolBarButton(#TOOLBAR_Diff, #MENU_Diff_Vertical, FileState)If DiffDirectoryMode > 0 ; directory visibleIf DiffDirectoryMode = 2DisableToolBarButton(#TOOLBAR_Diff, #MENU_Diff_HideFiles, 1)ElseDisableToolBarButton(#TOOLBAR_Diff, #MENU_Diff_HideFiles, 0)EndIfElseDisableToolBarButton(#TOOLBAR_Diff, #MENU_Diff_HideFiles, 1)EndIfEndProcedureProcedure SwitchDirectoryMode(TargetMode); adjust the splitters as needed;If DiffDirectoryMode <> TargetMode; required for the creation of the temp gadgets (when switching splitter content)UseGadgetList(WindowID(#WINDOW_Diff))Select DiffDirectoryModeCase 0 ; files only; need to create the required gadgets now;CompilerIf #CompileWindowsTextGadget(#GADGET_Diff_FileTitle, 0, 0, 0, 0, "")CompilerElseTextGadget(#GADGET_Diff_FileTitle, 0, 0, 0, 0, "", #PB_Text_Border)CompilerEndIfListIconGadget(#GADGET_Diff_Files, 0, 0, 250, 0, Language("Diff","Filename"), 250, #PB_ListIcon_GridLines|#PB_ListIcon_FullRowSelect|#PB_ListIcon_AlwaysShowSelection)AddGadgetColumn(#GADGET_Diff_Files, 1, Language("Diff","State"), 100)AddGadgetColumn(#GADGET_Diff_Files, 2, Language("Diff","Date1"), 130)AddGadgetColumn(#GADGET_Diff_Files, 3, Language("Diff","Date2"), 130)If TargetMode = 1SplitterGadget(#GADGET_Diff_Splitter2, 0, 0, 0, 0, #GADGET_Diff_Files, #GADGET_Diff_Splitter)SetGadgetAttribute(#GADGET_Diff_Splitter2, #PB_Splitter_FirstMinimumSize, 80)SetGadgetAttribute(#GADGET_Diff_Splitter2, #PB_Splitter_SecondMinimumSize, 80)ElseHideGadget(#GADGET_Diff_Splitter, 1)EndIfCase 1 ; files and directory; need to put dummy gadgets in the splitter so it can then be freed without freeing the old content;If TargetMode = 0SetGadgetAttribute(#GADGET_Diff_Splitter2, #PB_Splitter_SecondGadget, TextGadget(#PB_Any,0,0,0,0,""))FreeGadget(#GADGET_Diff_Splitter2) ; frees the splitter and the listiconFreeGadget(#GADGET_Diff_FileTitle)ElseSetGadgetAttribute(#GADGET_Diff_Splitter2, #PB_Splitter_FirstGadget, TextGadget(#PB_Any,0,0,0,0,""))SetGadgetAttribute(#GADGET_Diff_Splitter2, #PB_Splitter_SecondGadget, TextGadget(#PB_Any,0,0,0,0,""))FreeGadget(#GADGET_Diff_Splitter2) ; frees only the splitterHideGadget(#GADGET_Diff_Splitter, 1) ; this one is just hidden, never freedEndIfCase 2 ; directory onlyHideGadget(#GADGET_Diff_Splitter, 0)If TargetMode = 0FreeGadget(#GADGET_Diff_FileTitle)FreeGadget(#GADGET_Diff_Files)ElseUseGadgetList(WindowID(#WINDOW_Diff))SplitterGadget(#GADGET_Diff_Splitter2, 0, 0, 0, 0, #GADGET_Diff_Files, #GADGET_Diff_Splitter)SetGadgetAttribute(#GADGET_Diff_Splitter2, #PB_Splitter_FirstMinimumSize, 80)SetGadgetAttribute(#GADGET_Diff_Splitter2, #PB_Splitter_SecondMinimumSize, 80)EndIfEndSelectEndIfDiffDirectoryMode = TargetMode; Update toolbar accordinglyUpdateDiffToolbar(); resizeDiffWindowEvents(#PB_Event_SizeWindow)ResizeDiffSplitterContent()EndProcedureProcedure ShowNextDifference(Gadget, Forward, IsFirst)If Gadget = #GADGET_Diff_Files Or DiffDirectoryMode = 2 ; use it if only directories are visible too; directory modeindex = GetGadgetState(#GADGET_Diff_Files)If index = -1 Or IsFirstindex = 0ElseIf Forwardindex + 1Elseindex - 1EndIfIf SelectElement(DiffFiles(), index)RepeatIf DiffFiles()\Style <> #DIFF_EqualSetGadgetState(#GADGET_Diff_Files, ListIndex(DiffFiles())) ; mark thisBreakElseIf ForwardResult = NextElement(DiffFiles())ElseResult = PreviousElement(DiffFiles())EndIfUntil Result = 0EndIfSetActiveGadget(#GADGET_Diff_Files)Else; always fallback to File1 if none of the files is selectedIf Gadget <> #GADGET_Diff_File2Gadget = #GADGET_Diff_File1Other = #GADGET_Diff_File2ElseOther = #GADGET_Diff_File1EndIfIf IsFirstline = ScintillaSendMessage(Gadget, #SCI_MARKERNEXT, 0, 1 << #DIFF_ChangeMarker)Elseline = ScintillaSendMessage(Gadget, #SCI_LINEFROMPOSITION, ScintillaSendMessage(Gadget, #SCI_GETCURRENTPOS))If Forwardline = ScintillaSendMessage(Gadget, #SCI_MARKERNEXT, line+1, 1 << #DIFF_ChangeMarker)Elseline = ScintillaSendMessage(Gadget, #SCI_MARKERPREVIOUS, line-1, 1 << #DIFF_ChangeMarker)EndIfEndIfIf line <> -1ScintillaSendMessage(Gadget, #SCI_LINESCROLL, -99999, -99999)ScintillaSendMessage(Gadget, #SCI_LINESCROLL, 0, line-3)ScintillaSendMessage(Gadget, #SCI_GOTOLINE, line, 0); scroll the other to the same placeScintillaSendMessage(Other, #SCI_LINESCROLL, -99999, -99999)ScintillaSendMessage(Other, #SCI_LINESCROLL, 0, line-3)ScintillaSendMessage(Other, #SCI_GOTOLINE, line, 0)EndIfSetActiveGadget(Gadget)EndIfEndProcedureProcedure DiffWindowEvents(EventID)If EventID = #PB_Event_GadgetSelect EventGadget()Case #GADGET_Diff_Splitter, #GADGET_Diff_SplitterResizeDiffSplitterContent()Case #GADGET_Diff_FilesIf DiffDirectoryMode > 0 And EventType() = #PB_EventType_LeftDoubleClickindex = GetGadgetState(#GADGET_Diff_Files)If index <> -1 And SelectElement(DiffFiles(), index)If DiffFiles()\Style = #DIFF_Changed Or DiffFiles()\Style = #DIFF_Equal ; cannot compare against added/removed filesDiffFileToFile(DiffA_Base$+DiffFiles()\Name,ドル DiffB_Base$+DiffFiles()\Name,ドル #False, 1)EndIfEndIfElseUpdateDiffToolbar() ; update on selection changesEndIfEndSelectElseIf EventID = #PB_Event_MenuEventMenu = EventMenu()Select EventMenuCase #MENU_Diff_Open1, #MENU_Diff_Open2If EventMenu = #MENU_Diff_Open1If DiffSwapped = 0First = #TrueElseFirst = #FalseEndIfElseIf DiffSwapped = 0First = #FalseElseFirst = #TrueEndIfEndIfSelect DiffModeCase #DIFF_FileToFileIf FirstLoadSourceFile(DiffA_File$)ElseLoadSourceFile(DiffB_File$)EndIfCase #DIFF_SourceToFile ; A is a *Source, B is a fileIf FirstChangeCurrentElement(FileList(), *DiffSource)ChangeActiveSourceCode()ElseLoadSourceFile(DiffB_File$)EndIfEndSelectCase #MENU_Diff_RefreshIf DiffDirectoryMode > 0DiffDirectories(DiffA_Base,ドル DiffB_Base,ドル DiffPattern,ドル DiffSwapped, DiffDirectoryMode)EndIfIf DiffDirectoryMode < 2Select DiffModeCase #DIFF_FileToFileDiffFileToFile(DiffA_File,ドル DiffB_File,ドル DiffSwapped, DiffDirectoryMode)Case #DIFF_SourceToFileDiffSourceToFile(*DiffSource, DiffB_File,ドル DiffSwapped)EndSelectEndIfCase #MENU_Diff_ColorsIf DiffDirectoryMode < 2If DiffShowColorsDiffShowColors = 0ElseDiffShowColors = 1EndIfSetToolBarButtonState(#TOOLBAR_Diff, #MENU_Diff_Colors, DiffShowColors); update the gadget colorsUpdateDiffGadget(#True, StyleA(), #False)UpdateDiffGadget(#False, StyleB(), #False)EndIfCase #MENU_Diff_SwapIf DiffSwapped = 0DiffSwapped = 1ElseDiffSwapped = 0EndIfSetToolBarButtonState(#TOOLBAR_Diff, #MENU_Diff_Swap, DiffSwapped)If DiffDirectoryMode > 0; just update the viewUpdateDiffFileList()EndIfIf DiffDirectoryMode < 2; swapping the files produces the identical diff output, just; with inserts and deletes reversed, so no need to recalculate it all;If DiffSwapped = 0SetGadgetText(#GADGET_Diff_Title1, DiffA_Title$) ; set original titlesSetGadgetText(#GADGET_Diff_Title2, DiffB_Title$)ElseSetGadgetText(#GADGET_Diff_Title1, DiffB_Title$) ; swap the titlesSetGadgetText(#GADGET_Diff_Title2, DiffA_Title$)EndIf; now update the coloring+text, this takes care of the restUpdateDiffGadget(#True, StyleA(), #True)UpdateDiffGadget(#False, StyleB(), #True); mark the first difference againShowNextDifference(#GADGET_Diff_File1, #True, #True)EndIfCase #MENU_Diff_VerticalIf DiffDirectoryMode < 2If DiffVerticalDiffVertical = 0ElseDiffVertical = 1EndIfWidth = WindowWidth(#WINDOW_Diff)Height = WindowHeight(#WINDOW_Diff); required for the creation of the temp gadgets (when switching splitter content)UseGadgetList(WindowID(#WINDOW_Diff))If DiffDirectoryMode = 1; must get the splitter out of the outer splitter first. use a dummy for the replacementdummy = TextGadget(#PB_Any, 0, 0, 0, 0, "")SetGadgetAttribute(#GADGET_Diff_Splitter2, #PB_Splitter_SecondGadget, dummy)EndIf; remove the old splitter from the window, replace the content first with dummy gadgetsSetGadgetAttribute(#GADGET_Diff_Splitter, #PB_Splitter_FirstGadget, TextGadget(#PB_Any, 0, 0, 0, 0, ""))SetGadgetAttribute(#GADGET_Diff_Splitter, #PB_Splitter_SecondGadget, TextGadget(#PB_Any, 0, 0, 0, 0, ""))FreeGadget(#GADGET_Diff_Splitter)UseGadgetList(WindowID(#WINDOW_Diff))If DiffVerticalSplitterGadget(#GADGET_Diff_Splitter, 5, 5+ToolbarTopOffset, Width-10, Height-10-ToolbarHeight, #GADGET_Diff_Container1, #GADGET_Diff_Container2)ElseSplitterGadget(#GADGET_Diff_Splitter, 5, 5+ToolbarTopOffset, Width-10, Height-10-ToolbarHeight, #GADGET_Diff_Container1, #GADGET_Diff_Container2, #PB_Splitter_Vertical)EndIfIf DiffDirectoryMode = 1; put it back into the other splitter (and delete the dummy)SetGadgetAttribute(#GADGET_Diff_Splitter2, #PB_Splitter_SecondGadget, #GADGET_Diff_Splitter)FreeGadget(dummy)EndIfSetToolBarButtonState(#TOOLBAR_Diff, #MENU_Diff_Vertical, DiffVertical)ResizeDiffSplitterContent()EndIfCase #MENU_Diff_ShowToolOpenDiffDialogWindow()Case #MENU_Diff_ShowFiles; this is a shortcut, so check that it only works in the files listIf DiffDirectoryMode > 0 And GetActiveGadget() = #GADGET_Diff_Files; same action as for the listicon eventindex = GetGadgetState(#GADGET_Diff_Files)If index <> -1 And SelectElement(DiffFiles(), index)If DiffFiles()\Style = #DIFF_Changed Or DiffFiles()\Style = #DIFF_Equal ; cannot compare against added/removed filesDiffFileToFile(DiffA_Base$+DiffFiles()\Name,ドル DiffB_Base$+DiffFiles()\Name,ドル #False, 1)EndIfEndIfEndIfCase #MENU_Diff_HideFilesIf DiffDirectoryMode = 1SwitchDirectoryMode(2)UpdateDiffToolbar()EndIfCase #MENU_Diff_UpShowNextDifference(GetActiveGadget(), #False, #False)Case #MENU_Diff_DownShowNextDifference(GetActiveGadget(), #True, #False)EndSelectElseIf EventID = #PB_Event_SizeWindowWidth = WindowWidth(#WINDOW_Diff)Height = WindowHeight(#WINDOW_Diff)If DiffDirectoryMode = 0; only the file splitterResizeGadget(#GADGET_Diff_Splitter, 5, 5+ToolbarTopOffset, Width-10, Height-10-ToolbarHeight)Elseh = Max(GetRequiredHeight(#GADGET_Diff_FileTitle), 30)ResizeGadget(#GADGET_Diff_FileTitle, 5,5+ToolbarTopOffset, Width-10, h)If DiffDirectoryMode = 1; the directory splitter is the mainResizeGadget(#GADGET_Diff_Splitter2, 5, 7+ToolbarTopOffset+h, Width-10, Height-12-ToolbarHeight-h)Else; only the directory viewResizeGadget(#GADGET_Diff_Files, 5, 7+ToolbarTopOffset+h, Width-10, Height-12-ToolbarHeight-h)EndIfEndIfGetRequiredSize(#GADGET_Diff_Busy, @BusyW, @BusyH)ResizeGadget(#GADGET_Diff_Busy, (Width-BusyW)/2, ToolbarTopOffset + (Height-ToolBarHeight-BusyH) / 2, BusyW, BusyH)ElseIf EventID = #PB_Event_CloseWindowIf MemorizeWindow And IsWindowMinimized(#WINDOW_Diff) = 0DiffWindowPosition\IsMaximized = IsWindowMaximized(#WINDOW_Diff)If DiffWindowPosition\IsMaximized = 0DiffWindowPosition\x = WindowX(#WINDOW_Diff)DiffWindowPosition\y = WindowY(#WINDOW_Diff)DiffWindowPosition\Width = WindowWidth (#WINDOW_Diff)DiffWindowPosition\Height = WindowHeight(#WINDOW_Diff)EndIfEndIfCloseWindow(#WINDOW_Diff); free the no longer needed data;If *DiffA_BufferFreeMemory(*DiffA_Buffer)EndIfIf *DiffB_BufferFreeMemory(*DiffB_Buffer)EndIf*DiffA_Buffer = 0*DiffB_Buffer = 0ClearList(StyleA())ClearList(StyleB())EndIfEndProcedureProcedureDLL DiffScintillaCallback(Gadget, *scinotify.SCNotification)Select *scinotify\nmhdr\code; There is no separate (cross-platform) notification on scrolling events,; so use the paint message and check the scrolling position to update the; second gadget;Case #SCN_PAINTEDIf Gadget = #GADGET_Diff_File1OtherGadget = #GADGET_Diff_File2ElseOtherGadget = #GADGET_Diff_File1EndIfZoom = ScintillaSendMessage(Gadget, #SCI_GETZOOM)If Zoom <> DiffZoomDiffZoom = ZoomScintillaSendMessage(OtherGadget, #SCI_SETZOOM, DiffZoom)EndIfX = ScintillaSendMessage(Gadget, #SCI_GETXOFFSET)If X <> DiffScrollXDiffScrollX = XScintillaSendMessage(OtherGadget, #SCI_SETXOFFSET, DiffScrollX)EndIf; Note: this counts visible lines, not document lines; this needs to be adjusted if some kind of folding is allowedY = ScintillaSendMessage(Gadget, #SCI_GETFIRSTVISIBLELINE)If Y <> DiffScrollYDiffScrollY = Y; #SCI_SETFIRSTVISIBLELINE is not supported in our scintilla version, so emulate itScintillaSendMessage(OtherGadget, #SCI_LINESCROLL, 0, DiffScrollY - ScintillaSendMessage(OtherGadget, #SCI_GETFIRSTVISIBLELINE))EndIfEndSelectEndProcedureProcedure OpenDiffWindow();; This is not a DialogManager created Window, because of the toolbar etc;If IsWindow(#WINDOW_Diff) = 0Flags = #PB_Window_SystemMenu|#PB_Window_SizeGadget|#PB_Window_MinimizeGadget|#PB_Window_MaximizeGadget|#PB_Window_InvisibleIf DiffWindowPosition\x = -1 And DiffWindowPosition\y = -1Flags | #PB_Window_ScreenCenteredEndIfIf OpenWindow(#WINDOW_Diff, DiffWindowPosition\x, DiffWindowPosition\y, DiffWindowPosition\Width, DiffWindowPosition\Height, Language("Diff", "Title"), Flags, WindowID(#WINDOW_Main))WindowBounds(#WINDOW_Diff, 200, 200, #PB_Ignore, #PB_Ignore)CompilerIf #CompileMacIf OSVersion() >= #PB_OS_MacOSX_10_14; Fix Toolbar style from titlebar to expanded (Top Left)#NSWindowToolbarStyleExpanded = 1CocoaMessage(0, WindowID(#WINDOW_Diff), "setToolbarStyle:", #NSWindowToolbarStyleExpanded)EndIfCompilerEndIfCompilerIf #CompileMacflags = #PB_ToolBar_LargeCompilerElseflags = 0CompilerEndIfIf CreateToolBar(#TOOLBAR_Diff, WindowID(#WINDOW_Diff), Flags)ToolBarImageButton(#MENU_Diff_ShowTool, ImageID(#IMAGE_Diff_ShowTool))ToolBarImageButton(#MENU_Diff_Open1, ImageID(#IMAGE_Diff_Open1))ToolBarImageButton(#MENU_Diff_Open2, ImageID(#IMAGE_Diff_Open2))ToolBarSeparator()ToolBarImageButton(#MENU_Diff_Colors, ImageID(#IMAGE_Diff_Colors), #PB_ToolBar_Toggle)ToolBarImageButton(#MENU_Diff_Vertical, ImageID(#IMAGE_Diff_Vertical), #PB_ToolBar_Toggle)ToolBarImageButton(#MENU_Diff_HideFiles, ImageID(#IMAGE_Diff_HideFiles))ToolBarSeparator()ToolBarImageButton(#MENU_Diff_Swap, ImageID(#IMAGE_Diff_Swap))ToolBarImageButton(#MENU_Diff_Refresh, ImageID(#IMAGE_Diff_Refresh))ToolBarSeparator()ToolBarImageButton(#MENU_Diff_Up, ImageID(#IMAGE_Diff_Up))ToolBarImageButton(#MENU_Diff_Down, ImageID(#IMAGE_Diff_Down))ToolBarToolTip(#TOOLBAR_Diff, #MENU_Diff_Open1, Language("Diff","Open1"))ToolBarToolTip(#TOOLBAR_Diff, #MENU_Diff_Open2, Language("Diff","Open2"))ToolBarToolTip(#TOOLBAR_Diff, #MENU_Diff_Refresh, Language("Diff","Refresh"))ToolBarToolTip(#TOOLBAR_Diff, #MENU_Diff_Swap, Language("Diff","Swap"))ToolBarToolTip(#TOOLBAR_Diff, #MENU_Diff_Colors, Language("Diff","Colors"))ToolBarToolTip(#TOOLBAR_Diff, #MENU_Diff_Vertical, Language("Diff","Vertical"))ToolBarToolTip(#TOOLBAR_Diff, #MENU_Diff_ShowTool, Language("Diff","ShowTool"))ToolBarToolTip(#TOOLBAR_Diff, #MENU_Diff_HideFiles, Language("Diff","HideFiles"))ToolBarToolTip(#TOOLBAR_Diff, #MENU_Diff_Up, Language("Diff","Up"))ToolBarToolTip(#TOOLBAR_Diff, #MENU_Diff_Down, Language("Diff","Down"))SetToolBarButtonState(#TOOLBAR_Diff, #MENU_Diff_Colors, DiffShowColors)SetToolBarButtonState(#TOOLBAR_Diff, #MENU_Diff_Vertical, DiffVertical)EndIf; this one has no icon, only a shortcut (enter)AddKeyboardShortcut(#WINDOW_Diff, #PB_Shortcut_Return, #MENU_Diff_ShowFiles)TextGadget(#GADGET_Diff_Busy, 0, 0, 0, 0, Language("Diff","Busy"))HideGadget(#GADGET_Diff_Busy, 1); the default state is the File only mode, where there is no gadget for filename and filesDiffDirectoryMode = 0UpdateDiffToolbar(); Note: The TextGadget with border looks quite ugly in this context on modern Windows version as it has; the old style "client edge" border. It looks better without any borders at all here;ContainerGadget(#GADGET_Diff_Container1, 0, 0, 0, 0, #PB_Container_BorderLess)CompilerIf #CompileWindowsTextGadget(#GADGET_Diff_Title1, 0, 0, 0, 0, "")CompilerElseTextGadget(#GADGET_Diff_Title1, 0, 0, 0, 0, "", #PB_Text_Border)CompilerEndIfScintillaGadget(#GADGET_Diff_File1, 0, 0, 0, 0, @DiffScintillaCallback())CloseGadgetList()ContainerGadget(#GADGET_Diff_Container2, 0, 0, 0, 0, #PB_Container_BorderLess)CompilerIf #CompileWindowsTextGadget(#GADGET_Diff_Title2, 0, 0, 0, 0, "")CompilerElseTextGadget(#GADGET_Diff_Title2, 0, 0, 0, 0, "", #PB_Text_Border)CompilerEndIfScintillaGadget(#GADGET_Diff_File2, 0, 0, 0, 0, @DiffScintillaCallback())CloseGadgetList(); this variable is reversed from the splitter flag: vertical splitter = horizontal tilingIf DiffVerticalSplitterGadget(#GADGET_Diff_Splitter, 5, 5+ToolbarTopOffset, DiffWindowPosition\Width-10, DiffWindowPosition\Height-10-ToolbarHeight, #GADGET_Diff_Container1, #GADGET_Diff_Container2)ElseSplitterGadget(#GADGET_Diff_Splitter, 5, 5+ToolbarTopOffset, DiffWindowPosition\Width-10, DiffWindowPosition\Height-10-ToolbarHeight, #GADGET_Diff_Container1, #GADGET_Diff_Container2, #PB_Splitter_Vertical)EndIfSetGadgetAttribute(#GADGET_Diff_Splitter, #PB_Splitter_FirstMinimumSize, 80)SetGadgetAttribute(#GADGET_Diff_Splitter, #PB_Splitter_SecondMinimumSize, 80)DiffScrollX = 0DiffScrollY = 0DiffZoom = ScintillaSendMessage(#GADGET_Diff_File1, #SCI_GETZOOM)For Gadget = #GADGET_Diff_File1 To #GADGET_Diff_File2ScintillaSendMessage(Gadget, #SCI_CLEARCMDKEY, #SCK_TAB) ; to enable the window shortcutsScintillaSendMessage(Gadget, #SCI_CLEARCMDKEY, #SCK_RETURN)ApplyWordChars(Gadget)ScintillaSendMessage(Gadget, #SCI_SETCARETLINEVISIBLE, 0, 0); margin for line numbers, this is hidden in UpdateDiffGadget() if it is disabled; we cannot use the normal line numbers as we have gaps where stuff is inserted in another fileCompilerIf #SCINTILLA_TEXT_MARGINScintillaSendMessage(Gadget, #SCI_SETMARGINTYPEN, 1, #SC_MARGIN_RTEXT)ScintillaSendMessage(Gadget, #SCI_SETMARGINMASKN, 1, 0)ScintillaSendMessage(Gadget, #SCI_SETMARGINSENSITIVEN, 1, 0)CompilerEndIf; margin for the markersScintillaSendMessage(Gadget, #SCI_SETMARGINTYPEN, 2, #SC_MARGIN_SYMBOL)ScintillaSendMessage(Gadget, #SCI_SETMARGINMASKN, 2, ~#SC_MASK_FOLDERS)ScintillaSendMessage(Gadget, #SCI_SETMARGINSENSITIVEN, 2, 0)For i = 0 To #DIFF_StateCount-1ScintillaSendMessage(Gadget, #SCI_MARKERDEFINE, i, #SC_MARK_BACKGROUND)Next iScintillaSendMessage(Gadget, #SCI_MARKERDEFINE, #DIFF_StateCount+#DIFF_Empty, #SC_MARK_EMPTY)ScintillaSendMessage(Gadget, #SCI_MARKERDEFINE, #DIFF_StateCount+#DIFF_Equal, #SC_MARK_EMPTY)ScintillaSendMessage(Gadget, #SCI_MARKERDEFINE, #DIFF_StateCount+#DIFF_Added, #SC_MARK_PLUS)ScintillaSendMessage(Gadget, #SCI_MARKERDEFINE, #DIFF_StateCount+#DIFF_Removed, #SC_MARK_MINUS)ScintillaSendMessage(Gadget, #SCI_MARKERDEFINE, #DIFF_StateCount+#DIFF_Changed, #SC_MARK_SHORTARROW); for knowing where the next change startsScintillaSendMessage(Gadget, #SCI_MARKERDEFINE, #DIFF_ChangeMarker, #SC_MARK_EMPTY)Next GadgetEnsureWindowOnDesktop(#WINDOW_Diff)If DiffWindowPosition\IsMaximizedShowWindowMaximized(#WINDOW_Diff)ElseHideWindow(#WINDOW_Diff, 0)EndIfDiffWindowEvents(#PB_Event_SizeWindow)ResizeDiffSplitterContent()EndIfElseSetWindowForeground(#WINDOW_Diff)EndIfEndProcedureProcedure DiffHighlightCallback(*StringStart.BYTE, Length, *Color, IsBold, TextChanged)ScintillaSendMessage(DiffStyleGadget, #SCI_SETSTYLING, Length, *Color)EndProcedure; Update the coloring in the gadget and optionally set the text;Procedure UpdateDiffGadget(IsLeft, List Style.DiffStyleBlock(), SetText)If IsLeftIf DiffSwapped = 0Gadget = #GADGET_Diff_File1ElseGadget = #GADGET_Diff_File2EndIfElseIf DiffSwapped = 0Gadget = #GADGET_Diff_File2ElseGadget = #GADGET_Diff_File1EndIfEndIf; Gtk2 'Pango' need an "!" before the font name (else it will use GDK font);ScintillaSendMessage(Gadget, #SCI_STYLERESETDEFAULT, 0, 0)CompilerIf #CompileLinuxGtkFontName$ = "!"+EditorFontName$ScintillaSendMessage(Gadget, #SCI_STYLESETFONT, #STYLE_DEFAULT, ToAscii(FontName$))CompilerElseScintillaSendMessage(Gadget, #SCI_STYLESETFONT, #STYLE_DEFAULT, ToAscii(EditorFontName$))CompilerEndIfScintillaSendMessage(Gadget, #SCI_STYLESETSIZE, #STYLE_DEFAULT, EditorFontSize)If EditorFontStyle & #PB_Font_BoldScintillaSendMessage(Gadget, #SCI_STYLESETBOLD, #STYLE_DEFAULT, 1)ElseScintillaSendMessage(Gadget, #SCI_STYLESETBOLD, #STYLE_DEFAULT, 0)EndIfIf EditorFontStyle & #PB_Font_ItalicScintillaSendMessage(Gadget, #SCI_STYLESETITALIC, #STYLE_DEFAULT, 1)ElseScintillaSendMessage(Gadget, #SCI_STYLESETITALIC, #STYLE_DEFAULT, 0)EndIfScintillaSendMessage(Gadget, #SCI_STYLESETEOLFILLED, #STYLE_DEFAULT, #True); background markersScintillaSendMessage(Gadget, #SCI_MARKERSETBACK, #DIFF_Empty, $C0C0C0)ScintillaSendMessage(Gadget, #SCI_MARKERSETBACK, #DIFF_Equal, $FFFFFF)ScintillaSendMessage(Gadget, #SCI_MARKERSETBACK, #DIFF_Added, 90ドルEE90)ScintillaSendMessage(Gadget, #SCI_MARKERSETBACK, #DIFF_Removed, 507ドルFFF)ScintillaSendMessage(Gadget, #SCI_MARKERSETBACK, #DIFF_Changed, 80ドルFFFF); symbol markersScintillaSendMessage(Gadget, #SCI_MARKERSETBACK, #DIFF_StateCount+#DIFF_Empty, $C0C0C0)ScintillaSendMessage(Gadget, #SCI_MARKERSETBACK, #DIFF_StateCount+#DIFF_Equal, $FFFFFF)ScintillaSendMessage(Gadget, #SCI_MARKERSETBACK, #DIFF_StateCount+#DIFF_Added, 90ドルEE90)ScintillaSendMessage(Gadget, #SCI_MARKERSETBACK, #DIFF_StateCount+#DIFF_Removed, 507ドルFFF)ScintillaSendMessage(Gadget, #SCI_MARKERSETBACK, #DIFF_StateCount+#DIFF_Changed, 80ドルFFFF)If DiffShowColorsScintillaSendMessage(Gadget, #SCI_STYLESETBACK, #STYLE_DEFAULT, Colors(#COLOR_GlobalBackground)\DisplayValue)ScintillaSendMessage(Gadget, #SCI_STYLECLEARALL, 0, 0) ; to make the background & font change effective!If EnableKeywordBolding; Gtk2 'Pango' need an "!" before the font name (else it will use GDK font);CompilerIf #CompileLinuxGtkFontName$ = "!"+EditorBoldFontName$ScintillaSendMessage(Gadget, #SCI_STYLESETFONT, 2, ToAscii(FontName$))ScintillaSendMessage(Gadget, #SCI_STYLESETFONT, 14, ToAscii(FontName$))CompilerElseScintillaSendMessage(Gadget, #SCI_STYLESETFONT, 2, ToAscii(EditorBoldFontName$))ScintillaSendMessage(Gadget, #SCI_STYLESETFONT, 14, ToAscii(EditorBoldFontName$))CompilerEndIfScintillaSendMessage(Gadget, #SCI_STYLESETSIZE, #STYLE_DEFAULT, EditorFontSize)ScintillaSendMessage(Gadget, #SCI_STYLESETBOLD, 2, 1) ; Bold (no effect on linux, but maybe on windows later)ScintillaSendMessage(Gadget, #SCI_STYLESETBOLD, 14, 1)If EditorFontStyle & #PB_Font_ItalicScintillaSendMessage(Gadget, #SCI_STYLESETITALIC, 2, 1)ScintillaSendMessage(Gadget, #SCI_STYLESETITALIC, 14, 1)EndIfEndIfFor i = 0 To #DIFF_StateCount-1ScintillaSendMessage(Gadget, #SCI_MARKERSETFORE, #DIFF_StateCount+i, Colors(#COLOR_NormalText)\DisplayValue)Next i; applies to all marginsScintillaSendMessage(Gadget, #SCI_STYLESETFORE, #STYLE_LINENUMBER, Colors(#COLOR_LineNumber)\DisplayValue)ScintillaSendMessage(Gadget, #SCI_STYLESETBACK, #STYLE_LINENUMBER, Colors(#COLOR_LineNumberBack)\DisplayValue)ScintillaSendMessage(Gadget, #SCI_STYLESETFORE, 1, Colors(#COLOR_NormalText)\DisplayValue)ScintillaSendMessage(Gadget, #SCI_STYLESETFORE, 2, Colors(#COLOR_BasicKeyword)\DisplayValue)ScintillaSendMessage(Gadget, #SCI_STYLESETFORE, 3, Colors(#COLOR_Comment)\DisplayValue)ScintillaSendMessage(Gadget, #SCI_STYLESETFORE, 4, Colors(#COLOR_Constant)\DisplayValue)ScintillaSendMessage(Gadget, #SCI_STYLESETFORE, 5, Colors(#COLOR_String)\DisplayValue)ScintillaSendMessage(Gadget, #SCI_STYLESETFORE, 6, Colors(#COLOR_PureKeyword)\DisplayValue)ScintillaSendMessage(Gadget, #SCI_STYLESETFORE, 7, Colors(#COLOR_ASMKeyword)\DisplayValue)ScintillaSendMessage(Gadget, #SCI_STYLESETFORE, 8, Colors(#COLOR_Operator)\DisplayValue)ScintillaSendMessage(Gadget, #SCI_STYLESETFORE, 9, Colors(#COLOR_Structure)\DisplayValue)ScintillaSendMessage(Gadget, #SCI_STYLESETFORE, 10, Colors(#COLOR_Number)\DisplayValue)ScintillaSendMessage(Gadget, #SCI_STYLESETFORE, 11, Colors(#COLOR_Pointer)\DisplayValue)ScintillaSendMessage(Gadget, #SCI_STYLESETFORE, 12, Colors(#COLOR_Separator)\DisplayValue)ScintillaSendMessage(Gadget, #SCI_STYLESETFORE, 13, Colors(#COLOR_Label)\DisplayValue)ScintillaSendMessage(Gadget, #SCI_STYLESETFORE, 14, Colors(#COLOR_CustomKeyword)\DisplayValue)CompilerIf #CompileWindowsIf Colors(#COLOR_Selection)\DisplayValue = -1 Or EnableAccessibility; special accessibility schemeScintillaSendMessage(Gadget, #SCI_SETSELBACK, 1, GetSysColor_(#COLOR_HIGHLIGHT))ElseScintillaSendMessage(Gadget, #SCI_SETSELBACK, 1, Colors(#COLOR_Selection)\DisplayValue)EndIfIf Colors(#COLOR_SelectionFront)\DisplayValue = -1 Or EnableAccessibilityScintillaSendMessage(Gadget, #SCI_SETSELFORE, 1, GetSysColor_(#COLOR_HIGHLIGHTTEXT))ElseScintillaSendMessage(Gadget, #SCI_SETSELFORE, 1, Colors(#COLOR_SelectionFront)\DisplayValue)EndIfCompilerElseScintillaSendMessage(Gadget, #SCI_SETSELBACK, 1, Colors(#COLOR_Selection)\DisplayValue)ScintillaSendMessage(Gadget, #SCI_SETSELFORE, 1, Colors(#COLOR_SelectionFront)\DisplayValue)CompilerEndIfScintillaSendMessage(Gadget, #SCI_SETCARETFORE, Colors(#COLOR_Cursor)\DisplayValue, 0)ElseScintillaSendMessage(Gadget, #SCI_STYLESETBACK, #STYLE_DEFAULT, $FFFFFF)ScintillaSendMessage(Gadget, #SCI_STYLESETFORE, #STYLE_DEFAULT, 000000ドル)ScintillaSendMessage(Gadget, #SCI_STYLECLEARALL, 0, 0) ; to make the background & font change effective!For i = 0 To #DIFF_StateCount-1ScintillaSendMessage(Gadget, #SCI_MARKERSETFORE, #DIFF_StateCount+i, 000000ドル)Next iScintillaSendMessage(Gadget, #SCI_STYLESETFORE, #STYLE_LINENUMBER, 000000ドル)ScintillaSendMessage(Gadget, #SCI_STYLESETBACK, #STYLE_LINENUMBER, $FFFFFF)CompilerIf #CompileWindowsScintillaSendMessage(Gadget, #SCI_SETSELBACK, 1, GetSysColor_(#COLOR_HIGHLIGHT))ScintillaSendMessage(Gadget, #SCI_SETSELFORE, 1, GetSysColor_(#COLOR_HIGHLIGHTTEXT))CompilerElseScintillaSendMessage(Gadget, #SCI_SETSELBACK, 1, $C0C0C0)ScintillaSendMessage(Gadget, #SCI_SETSELFORE, 1, 000000ドル)CompilerEndIfScintillaSendMessage(Gadget, #SCI_SETCARETFORE, 000000ドル)EndIfScintillaSendMessage(Gadget, #SCI_SETTABWIDTH, TabLength)ScintillaSendMessage(Gadget, #SCI_SETUSETABS, RealTab)ScintillaSendMessage(Gadget, #SCI_SETMARGINWIDTHN, 2, ScintillaSendMessage(Gadget, #SCI_TEXTHEIGHT, 1, 0))CompilerIf #SCINTILLA_TEXT_MARGINLines = Max(Max(DiffA_Lines, DiffB_Lines), 10) ; use the same margin width on both filesLines$ = "_" + RSet("9", Len(Str(Lines)), "9")ScintillaSendMessage(Gadget, #SCI_SETMARGINWIDTHN, 1, ScintillaSendMessage(Gadget, #SCI_TEXTWIDTH, #STYLE_LINENUMBER, ToAscii(Lines$)))CompilerElse; hide this marginScintillaSendMessage(Gadget, #SCI_SETMARGINWIDTHN, 1, 0)CompilerEndIf; We need to build the full buffer for the coloring update and to set the text;Length = 1 ; for null byteForEach Style()Length + Style()\LengthNext Style()If SetTextScintillaSendMessage(Gadget, #SCI_SETREADONLY, 0) ; so it can be modified nowEndIf*Buffer = AllocateMemory(Length)If *Buffer*Pointer = *BufferForEach Style()If Style()\Start = #Null ; indicates that we need to add empty linesFor i = 1 To Style()\Length / #NewLineLengthPokeAscii(*Pointer, #NewLine)*Pointer + #NewLineLengthNext iElseCopyMemory(Style()\Start, *Pointer, Style()\Length)*Pointer + Style()\LengthEndIfNext Style()If SetText; adjust the utf8 mode as well (in case a swap took place);If IsLeftUtf8 = DiffA_Utf8ElseUtf8 = DiffB_Utf8EndIfIf Utf8ScintillaSendMessage(Gadget, #SCI_SETCODEPAGE, #SC_CP_UTF8)ElseScintillaSendMessage(Gadget, #SCI_SETCODEPAGE, 0)EndIf; set the new textScintillaSendMessage(Gadget, #SCI_SETTEXT, 0, *Buffer); the line numbers also only need updating when the text changedCompilerIf #SCINTILLA_TEXT_MARGINScintillaSendMessage(Gadget, #SCI_MARGINTEXTCLEARALL)CompilerEndIf; apply the markers for the diff background (only needed on text changes); also apply the line number text (if supported);ScintillaSendMessage(Gadget, #SCI_MARKERDELETEALL, -1)Line = 0DisplayLine = 1PreviousStyle = #DIFF_EqualForEach Style(); mark the beginning of each change block; note: a block with #DIFF_Empty is not a new change when it immediately follows a block of #DIFF_Changed; because then it is just an extension of that block to match the length in the other file;If Style()\Style <> #DIFF_Equal And (Not (Style()\Style = #DIFF_Empty And PreviousStyle = #DIFF_Changed))ScintillaSendMessage(Gadget, #SCI_MARKERADD, Line, #DIFF_ChangeMarker)EndIfIf DiffSwapped And Style()\Style = #DIFF_AddedStyle = #DIFF_RemovedElseIf DiffSwapped And Style()\Style = #DIFF_RemovedStyle = #DIFF_AddedElseStyle = Style()\StyleEndIfFor i = 1 To Style()\LinesIf Style <> #DIFF_Equal ; keep normal background for equal parts; the swapped display is exactly the same as the normal one, only; insers and deletes are reversed, so we can do a swap without changing the underlying dataScintillaSendMessage(Gadget, #SCI_MARKERADD, Line, Style) ; backgroundScintillaSendMessage(Gadget, #SCI_MARKERADD, Line, #DIFF_StateCount+Style) ; symbolEndIfCompilerIf #SCINTILLA_TEXT_MARGINIf Style <> #DIFF_EmptyText$ = Str(DisplayLine)ScintillaSendMessage(Gadget, #SCI_MARGINSETTEXT, Line, ToAscii(Text$))ScintillaSendMessage(Gadget, #SCI_MARGINSETSTYLE, Line, #STYLE_LINENUMBER)DisplayLine + 1EndIfCompilerEndIfLine + 1Next iPreviousStyle = Style()\StyleNext Style()EndIf; apply the styling;DiffStyleGadget = GadgetScintillaSendMessage(Gadget, #SCI_STARTSTYLING, 0, 1ドルF)If DiffShowColorsHighlightingEngine(*Buffer, Length-1, 0, @DiffHighlightCallback(), 0)Else; no highlighting engine used here. just set the text color for everythingScintillaSendMessage(Gadget, #SCI_SETSTYLING, Length-1, 1)EndIfFreeMemory(*Buffer)EndIfIf SetTextScintillaSendMessage(Gadget, #SCI_SETREADONLY, 1)EndIfEndProcedureProcedure UpdateDiffWindow()SetWindowTitle(#WINDOW_Diff, Language("Diff", "Title"))SetGadgetText(#GADGET_Diff_Busy, Language("Diff", "Busy")); Update the coloring in the gadgetsIf DiffDirectoryMode < 2UpdateDiffGadget(#True, StyleA(), #False)UpdateDiffGadget(#False, StyleB(), #False)EndIf; re-create the toolbar to apply theme changesFreeToolBar(#TOOLBAR_Diff)CompilerIf #CompileMacflags = #PB_ToolBar_LargeCompilerElseflags = 0CompilerEndIfIf CreateToolBar(#TOOLBAR_Diff, WindowID(#WINDOW_Diff), flags)ToolBarImageButton(#MENU_Diff_ShowTool, ImageID(#IMAGE_Diff_ShowTool))ToolBarImageButton(#MENU_Diff_Open1, ImageID(#IMAGE_Diff_Open1))ToolBarImageButton(#MENU_Diff_Open2, ImageID(#IMAGE_Diff_Open2))ToolBarSeparator()ToolBarImageButton(#MENU_Diff_Colors, ImageID(#IMAGE_Diff_Colors), #PB_ToolBar_Toggle)ToolBarImageButton(#MENU_Diff_Vertical, ImageID(#IMAGE_Diff_Vertical), #PB_ToolBar_Toggle)ToolBarImageButton(#MENU_Diff_HideFiles, ImageID(#IMAGE_Diff_HideFiles))ToolBarSeparator()ToolBarImageButton(#MENU_Diff_Swap, ImageID(#IMAGE_Diff_Swap))ToolBarImageButton(#MENU_Diff_Refresh, ImageID(#IMAGE_Diff_Refresh))ToolBarSeparator()ToolBarImageButton(#MENU_Diff_Up, ImageID(#IMAGE_Diff_Up))ToolBarImageButton(#MENU_Diff_Down, ImageID(#IMAGE_Diff_Down))ToolBarToolTip(#TOOLBAR_Diff, #MENU_Diff_Open1, Language("Diff","Open1"))ToolBarToolTip(#TOOLBAR_Diff, #MENU_Diff_Open2, Language("Diff","Open2"))ToolBarToolTip(#TOOLBAR_Diff, #MENU_Diff_Refresh, Language("Diff","Refresh"))ToolBarToolTip(#TOOLBAR_Diff, #MENU_Diff_Swap, Language("Diff","Swap"))ToolBarToolTip(#TOOLBAR_Diff, #MENU_Diff_Colors, Language("Diff","Colors"))ToolBarToolTip(#TOOLBAR_Diff, #MENU_Diff_Vertical, Language("Diff","Vertical"))ToolBarToolTip(#TOOLBAR_Diff, #MENU_Diff_ShowTool, Language("Diff","ShowTool"))ToolBarToolTip(#TOOLBAR_Diff, #MENU_Diff_HideFiles, Language("Diff","HideFiles"))ToolBarToolTip(#TOOLBAR_Diff, #MENU_Diff_Up, Language("Diff","Up"))ToolBarToolTip(#TOOLBAR_Diff, #MENU_Diff_Down, Language("Diff","Down"))SetToolBarButtonState(#TOOLBAR_Diff, #MENU_Diff_Colors, DiffShowColors)SetToolBarButtonState(#TOOLBAR_Diff, #MENU_Diff_Vertical, DiffVertical)EndIf; re-populate the file diff list to update language and themeIf DiffDirectoryMode > 0UpdateDiffFileList()EndIf; update the toolbar disabled statesUpdateDiffToolbar()EndProcedureProcedure AddStyleBlock(List Style.DiffStyleBlock(), *Start, Length, Lines, Style)AddElement(Style())Style()\Start = *StartStyle()\Length = LengthStyle()\Style = StyleStyle()\Lines = LinesEndProcedureProcedure AddEmptyStyleBlock(List Style.DiffStyleBlock(), Lines)AddElement(Style())Style()\Start = #Null ; indicates that this is an empty blockStyle()\Length = Lines * #NewLineLengthStyle()\Style = #DIFF_EmptyStyle()\Lines = LinesEndProcedureProcedure PerformDiff()ClearList(StyleA())ClearList(StyleB()); Show the busy line;ShowDiffProgress(#True)FlushEvents()DiffFlags = 0If DiffIgnoreCaseDiffFlags | #DIFF_IgnoreCaseEndIfIf DiffIgnoreSpaceAllDiffFlags | #DIFF_IgnoreSpaceAllEndIfIf DiffIgnoreSpaceLeftDiffFlags | #DIFF_IgnoreSpaceLeftEndIfIf DiffIgnoreSpaceRightDiffFlags | #DIFF_IgnoreSpaceRightEndIfCtx.DiffContextDiff(@Ctx, *DiffA_Start, DiffA_Size, *DiffB_Start, DiffB_Size, DiffFlags)DiffA_Lines = Ctx\LineCountADiffB_Lines = Ctx\LineCountB; Handle the special cases where one or both files are empty/not loadable;If DiffA_Lines = 0 And DiffB_Lines = 0AddEmptyStyleBlock(StyleA(), 1)AddEmptyStyleBlock(StyleB(), 1)ElseResetList(Ctx\Edits())While NextElement(Ctx\Edits())If Ctx\Edits()\Op = #DIFF_MatchAddStyleBlock(StyleA(), Ctx\Edits()\Start, Ctx\Edits()\Length, Ctx\Edits()\Lines, #DIFF_Equal)AddStyleBlock(StyleB(), Ctx\Edits()\Start, Ctx\Edits()\Length, Ctx\Edits()\Lines, #DIFF_Equal)Else; Combine Insert+Delete or Delete+Insert into a single "Change" blockOp = Ctx\Edits()\OpNextOp = -1PushListPosition(Ctx\Edits())If NextElement(Ctx\Edits())NextOp = Ctx\Edits()\OpEndIfPopListPosition(Ctx\Edits())If Op = #DIFF_Delete And NextOp = #DIFF_InsertLinesA = Ctx\Edits()\LinesAddStyleBlock(StyleA(), Ctx\Edits()\Start, Ctx\Edits()\Length, Ctx\Edits()\Lines, #DIFF_Changed)NextElement(Ctx\Edits())LinesB = Ctx\Edits()\LinesAddStyleBlock(StyleB(), Ctx\Edits()\Start, Ctx\Edits()\Length, Ctx\Edits()\Lines, #DIFF_Changed)If LinesA < LinesBAddEmptyStyleBlock(StyleA(), LinesB-LinesA)ElseIf LinesB < LinesAAddEmptyStyleBlock(StyleB(), LinesA-LinesB)EndIfElseIf Op = #DIFF_Insert And NextOp = #DIFF_DeleteLinesB = Ctx\Edits()\LinesAddStyleBlock(StyleB(), Ctx\Edits()\Start, Ctx\Edits()\Length, Ctx\Edits()\Lines, #DIFF_Changed)NextElement(Ctx\Edits())LinesA = Ctx\Edits()\LinesAddStyleBlock(StyleA(), Ctx\Edits()\Start, Ctx\Edits()\Length, Ctx\Edits()\Lines, #DIFF_Changed)If LinesA < LinesBAddEmptyStyleBlock(StyleA(), LinesB-LinesA)ElseIf LinesB < LinesAAddEmptyStyleBlock(StyleB(), LinesA-LinesB)EndIfElseIf Op = #DIFF_DeleteAddStyleBlock(StyleA(), Ctx\Edits()\Start, Ctx\Edits()\Length, Ctx\Edits()\Lines, #DIFF_Removed)AddEmptyStyleBlock(StyleB(), Ctx\Edits()\Lines)Else ; must be an insertAddEmptyStyleBlock(StyleA(), Ctx\Edits()\Lines)AddStyleBlock(StyleB(), Ctx\Edits()\Start, Ctx\Edits()\Length, Ctx\Edits()\Lines, #DIFF_Added)EndIfEndIfWendEndIfIf DiffSwappedSetGadgetText(#GADGET_Diff_Title1, DiffB_Title$)SetGadgetText(#GADGET_Diff_Title2, DiffA_Title$)ElseSetGadgetText(#GADGET_Diff_Title1, DiffA_Title$)SetGadgetText(#GADGET_Diff_Title2, DiffB_Title$)EndIfUpdateDiffGadget(#True, StyleA(), #True) ; set the text as wellUpdateDiffGadget(#False, StyleB(), #True)ShowDiffProgress(#False)UpdateDiffToolbar(); mark first differenceShowNextDifference(#GADGET_Diff_File1, #True, #True)EndProcedure; Set the left or right diff buffer.; *Buffer must be AllocateMemory() buffer and will belong to the Diff window then; *Buffer can be 0 if Length is 0;Procedure SetDiffBuffer(IsLeft, *Buffer, Length, Title,ドル IsUTF8); null buffer and length are accepted hereIf *Buffer = 0Length = 0EndIf; check for an utf8 bom. UTF8-mode is determined in two ways:; - with the IsUTF8 parameter (for ScintillaGadget source); - with a BOM in the data (for file source);*OriginalBuffer = BufferIf Length >= 3 And PeekA(*Buffer) = $EF And PeekA(*Buffer+1) = $BB And PeekA(*Buffer+2) = $BFIsUTF8 = 1*Buffer + 3Length - 3EndIf; do the actual scan for the correct sideIf IsLeftIf *DiffA_BufferFreeMemory(*DiffA_Buffer) ; free previous buffer (if any)EndIfDiffA_Utf8 = IsUTF8DiffA_Size = Length*DiffA_Buffer = *OriginalBuffer*DiffA_Start = *BufferDiffA_Title$ = Title$ElseIf *DiffB_BufferFreeMemory(*DiffB_Buffer)EndIfDiffB_Utf8 = IsUTF8DiffB_Size = Length*DiffB_Buffer = *OriginalBuffer*DiffB_Start = *BufferDiffB_Title$ = Title$EndIfProcedureReturn #TrueEndProcedureProcedure DiffFileToFile(File1,ドル File2,ドル SwapOutput = #False, DirectoryMode = 0)Abort = #FalseIf DirectoryMode > 1 ; only 0 and 1 show filesDirectoryMode = 0EndIf; Sanity check for file size;SizeMB.f = FileSize(File1$)/(1024*1024)If SizeMB > 3 ; since this is about text files, warn from 2mb onIf MessageRequester(#ProductName,ドルLanguage("FileViewer","SizeWarning")+" ("+StrF(SizeMB, 1)+" Mb)"+#NewLine+Language("FileViewer","SizeQuestion")+#NewLine+#NewLine+File1,ドル #FLAG_Warning|#PB_MessageRequester_YesNo) = #PB_MessageRequester_NoProcedureReturn #FalseEndIfEndIf; ask for the second file only if we did not ask for the first one.; we assume that if the user loads one big file, that the other is big as well (as it is compared to the big one); no need to be bothered with 2 questionsIf SizeMB < 3SizeMB.f = FileSize(File2$)/(1024*1024)If SizeMB > 3If MessageRequester(#ProductName,ドルLanguage("FileViewer","SizeWarning")+" ("+StrF(SizeMB, 1)+" Mb)"+#NewLine+Language("FileViewer","SizeQuestion")+#NewLine+#NewLine+File2,ドル #FLAG_Warning|#PB_MessageRequester_YesNo) = #PB_MessageRequester_NoProcedureReturn #FalseEndIfEndIfEndIfIf ReadFile(#FILE_Diff, File1$)Length1 = Lof(#FILE_Diff)If Length1 = 0*Buffer1 = #NullElse*Buffer1 = AllocateMemory(Length1)If *Buffer1Length1 = ReadData(#FILE_Diff, *Buffer1, Length1)EndIfEndIfCloseFile(#FILE_Diff)ElseMessageRequester(#ProductName,ドル LanguagePattern("Diff","FileError", "%file%", File1$))Abort = #TrueEndIfIf *Buffer1 And IsBinaryFile(*Buffer1, Length1)MessageRequester(#ProductName,ドル LanguagePattern("Diff","FileBinary", "%file%", File1$))Abort = #TrueEndIfIf Abort = #False ; only read the second file if the first is okIf ReadFile(#FILE_Diff, File2$)Length2 = Lof(#FILE_Diff)If Length2 = 0*Buffer2 = #NullElse*Buffer2 = AllocateMemory(Length2)If *Buffer2Length2 = ReadData(#FILE_Diff, *Buffer2, Length2)EndIfEndIfCloseFile(#FILE_Diff)ElseMessageRequester(#ProductName,ドル LanguagePattern("Diff","FileError", "%file%", File2$))Abort = #TrueEndIfEndIf; avoid multiple messages on multiple errorsIf Abort = #False And *Buffer2 And IsBinaryFile(*Buffer2, Length2)MessageRequester(#ProductName,ドル LanguagePattern("Diff","FileBinary", "%file%", File2$))Abort = #TrueEndIfIf AbortIf *Buffer1: FreeMemory(*Buffer1): EndIfIf *Buffer2: FreeMemory(*Buffer2): EndIfProcedureReturn #FalseElse; reset the optionsDiffSwapped = SwapOutputDiffMode = #DIFF_FileToFileDiffA_File$ = File1$DiffB_File$ = File2$; The buffer belongs to the diff window after these calls;SetDiffBuffer(#True, *Buffer1, Length1, File1,ドル #False)SetDiffBuffer(#False, *Buffer2, Length2, File2,ドル #False)OpenDiffWindow()SwitchDirectoryMode(DirectoryMode)PerformDiff()ProcedureReturn #TrueEndIfEndProcedureProcedure DiffSourceToFile(*Source.SourceFile, Filename,ドル SwapOutput = #False); Sanity check for file size;SizeMB.f = FileSize(Filename$)/(1024*1024)If SizeMB > 2 ; since this is about text files, warn from 2mb onIf MessageRequester(#ProductName,ドルLanguage("FileViewer","SizeWarning")+" ("+StrF(SizeMB, 1)+" Mb)"+#NewLine+Language("FileViewer","SizeQuestion")+#NewLine+#NewLine+Filename,ドル #FLAG_Warning|#PB_MessageRequester_YesNo) = #PB_MessageRequester_NoProcedureReturnEndIfEndIf; try the file first to check for errors;If ReadFile(#FILE_Diff, Filename$)Length2 = Lof(#FILE_Diff)If Length2 = 0*Buffer2 = #NullElse*Buffer2 = AllocateMemory(Length2)If *Buffer2Length2 = ReadData(#FILE_Diff, *Buffer2, Length2)EndIfEndIfCloseFile(#FILE_Diff)ElseMessageRequester(#ProductName,ドル LanguagePattern("Diff","FileError", "%file%", Filename$))ProcedureReturnEndIfIf *Buffer2 And IsBinaryFile(*Buffer2, Length2)MessageRequester(#ProductName,ドル LanguagePattern("Diff","FileBinary", "%file%", Filename$))FreeMemory(*Buffer2)ProcedureReturnEndIf; Errors in loading the file from the scintilla are ignored.; If there is an error here, we have a serious memory problem anyway.;IsUTF8 = #FalseIf *Source And *Source\IsProject = 0 And *Source\EditorGadgetIf *Source\Parser\Encoding <> 0IsUTF8 = #TrueEndIfLength1 = ScintillaSendMessage(*Source\EditorGadget, #SCI_GETLENGTH)*Buffer1 = AllocateMemory(Length1+1) ; null space needed by scintillaIf *Buffer1ScintillaSendMessage(*Source\EditorGadget, #SCI_GETTEXT, Length1, *Buffer1)EndIfIf *Source\FileName$ = ""Title$ = Language("FileStuff","NewSource")ElseTitle$ = *Source\FileName$EndIfTitle$ + " (" + Language("Diff","CurrentEdit") + ")"ElseLength1 = 0*Buffer1 = #NullTitle$ = ""EndIfDiffSwapped = SwapOutputDiffMode = #DIFF_SourceToFile*DiffSource = *SourceDiffB_File$ = Filename$SetDiffBuffer(#True, *Buffer1, Length1, Title,ドル IsUTF8) ; pass the scintilla utf8 modeSetDiffBuffer(#False, *Buffer2, Length2, Filename,ドル #False)OpenDiffWindow()SwitchDirectoryMode(0) ; files only modePerformDiff()EndProcedureProcedure CheckDiffFileClose(*Source.SourceFile); When the source that was part of the diff is closed, close the diff window; too because we loose the source for our data then;If DiffMode = #DIFF_SourceToFile And *Source = *DiffSourceDiffWindowEvents(#PB_Event_CloseWindow)EndIfEndProcedureProcedure ExamineDiffDirectory(Base,ドル Subdirectory,ドル List Output.s()); first, scan subdirectories if needed;If DiffRecurseID = ExamineDirectory(#PB_Any, Base$+Subdirectory,ドル "*")If IDWhile NextDirectoryEntry(ID)If DirectoryEntryType(ID) = #PB_DirectoryEntry_DirectoryName$ = DirectoryEntryName(ID)If Name$ <> "." And Name$ <> ".."ExamineDiffDirectory(Base,ドル Subdirectory$+Name$+#Separator, Output())EndIfEndIfWendFinishDirectory(ID)EndIfEndIf; now scan files. PatternList$ may be a list of patterns separated by ","; this produces double entries, which we will later remove;Index = 1RepeatPattern$ = Trim(StringField(DiffPattern,ドル Index, ","))If Pattern$ID = ExamineDirectory(#PB_Any, Base$+Subdirectory,ドル Pattern$)If IDWhile NextDirectoryEntry(ID)If DirectoryEntryType(ID) = #PB_DirectoryEntry_FileAddElement(Output())Output() = Subdirectory$+DirectoryEntryName(ID) ; do not include base in this listEndIfWendFinishDirectory(ID)EndIfEndIfIndex + 1Until Pattern$ = "" Or Pattern$ = "*" Or Pattern$ = "*.*" ; we also abort on these patterns, as then all files are scannedEndProcedureProcedure UpdateDiffFileList()ClearGadgetItems(#GADGET_Diff_Files)ForEach DiffFiles()Style = DiffFiles()\Style ; swap styles if files get swappedIf DiffSwappedIf Style = #DIFF_AddedStyle = #DIFF_RemovedElseIf Style = #DIFF_RemovedStyle = #DIFF_AddedEndIfDateA = DiffFiles()\DateBDateB = DiffFiles()\DateAElseDateA = DiffFiles()\DateADateB = DiffFiles()\DateBEndIfSelect StyleCase #DIFF_EqualState$ = Language("Diff","FileEqual")Image = #IMAGE_Diff_EqualColor = -1Case #DIFF_AddedState$ = Language("Diff","FileAdd")Image = #IMAGE_Diff_AddColor = 90ドルEE90Case #DIFF_RemovedState$ = Language("Diff","FileDelete")Image = #IMAGE_Diff_DeleteColor = 507ドルFFFCase #DIFF_ChangedState$ = Language("Diff","FileModify")Image = #IMAGE_Diff_ModifyColor = 80ドルFFFFEndSelectIf IsImage(Image) ; can be missing in the theme (its not in the classic theme for example)ImageID = ImageID(Image)ElseImageID = 0EndIfLine$ = DiffFiles()\Name$ + Chr(10) + State$If DateALine$ + Chr(10) + FormatDate(Language("Diff","DateFormat"), DateA)ElseLine$ + Chr(10)EndIfIf DateBLine$ + Chr(10) + FormatDate(Language("Diff","DateFormat"), DateB)ElseLine$ + Chr(10)EndIfAddGadgetItem(#GADGET_Diff_Files, ListIndex(DiffFiles()), Line,ドル ImageID)If Color <> -1SetGadgetItemColor(#GADGET_Diff_Files, ListIndex(DiffFiles()), #PB_Gadget_BackColor, Color, -1)CompilerIf #CompileMac; Fix text color for darkmodeSetGadgetItemColor(#GADGET_Diff_Files, ListIndex(DiffFiles()), #PB_Gadget_FrontColor, 0, -1)CompilerEndIfEndIfNext DiffFiles()If DiffSwappedText$ = Language("Diff","Directory1")+": "+DiffB_Base$+#NewLine+Language("Diff","Directory2")+": "+DiffA_Base$ElseText$ = Language("Diff","Directory1")+": "+DiffA_Base$+#NewLine+Language("Diff","Directory2")+": "+DiffB_Base$EndIfSetGadgetText(#GADGET_Diff_FileTitle, Text$); update toolbar state, as we killed the selectionUpdateDiffToolbar()DiffWindowEvents(#PB_Event_SizeWindow); mark the first differenceShowNextDifference(#GADGET_Diff_Files, #True, #True)EndProcedureProcedure DiffDirectories(Directory1,ドル Directory2,ドル Pattern,ドル SwapOutput = #False, DirectoryMode = 2)NewList FilesA.s()NewList FilesB.s()If DirectoryMode < 1 ; only 1 and 2 show the directoriesDirectoryMode = 1EndIfDiffSwapped = SwapOutputDiffA_Base$ = Directory1$DiffB_Base$ = Directory2$DiffPattern$ = Pattern$If Trim(DiffPattern$) = ""DiffPattern$ = "*"EndIf; first, examine the two directories to get a list of filesExamineDiffDirectory(DiffA_Base,ドル "", FilesA())ExamineDiffDirectory(DiffB_Base,ドル "", FilesB()); eliminate duplicates in each listSortList(FilesA(), #PB_Sort_Ascending)Last$ = ""ForEach FilesA()If Last$ = FilesA() ; can use simple compare, as the case should match for the same files because we just got it aboveDeleteElement(FilesA())ElseLast$ = FilesA()EndIfNext FilesA()SortList(FilesB(), #PB_Sort_Ascending)Last$ = ""ForEach FilesB()If Last$ = FilesB()DeleteElement(FilesB())ElseLast$ = FilesB()EndIfNext FilesB(); open output windowOpenDiffWindow()SwitchDirectoryMode(DirectoryMode)ShowDiffProgress(#True)FlushEvents()ClearList(DiffFiles()); look at files in A and compare to list BForEach FilesA()AddElement(DiffFiles())DiffFiles()\Name$ = FilesA()DiffFiles()\DateA = GetFileDate(DiffA_Base$+FilesA(), #PB_Date_Modified)found = 0ForEach FilesB()If IsEqualFile(FilesA(), FilesB()) ; here we need a full check, as case may differfound = 1BreakEndIfNext FilesB()If found = 0; file is only in ADiffFiles()\DateB = 0DiffFiles()\Style = #DIFF_RemovedElse; file found in both, need to compareDiffFiles()\DateB = GetFileDate(DiffB_Base$+FilesB(), #PB_Date_Modified); check the size first before doing the fingerprintingIf FileSize(DiffA_Base$+FilesA()) <> FileSize(DiffB_Base$+FilesB())DiffFiles()\Style = #DIFF_ChangedElseIf FileFingerprint(DiffA_Base$+FilesA(), #PB_Cipher_MD5) <> FileFingerprint(DiffB_Base$+FilesB(), #PB_Cipher_MD5)DiffFiles()\Style = #DIFF_ChangedElseDiffFiles()\Style = #DIFF_EqualEndIfDeleteElement(FilesB()) ; remove all files that exist in bothEndIfNext FilesA(); now everything left in FilesB() is not in FilesA()ForEach FilesB()AddElement(DiffFiles())DiffFiles()\Name$ = FilesB()DiffFiles()\DateA = 0DiffFiles()\DateB = GetFileDate(DiffB_Base$+FilesB(), #PB_Date_Modified)DiffFiles()\Style = #DIFF_AddedNext FilesB(); sort the output by directory name (with subdirectories); this is not the most efficient sort, but it does the job;If FirstElement(DiffFiles())Repeat*Current.DiffFile = @DiffFiles()*Smallest.DiffFile = @DiffFiles()While NextElement(DiffFiles())If CompareDirectories(DiffFiles()\Name,ドル *Smallest\Name$) = #PB_String_Lower*Smallest = @DiffFiles()EndIfWendIf *Current <> *SmallestSwapElements(DiffFiles(), *Current, *Smallest)ChangeCurrentElement(DiffFiles(), *Smallest)ElseChangeCurrentElement(DiffFiles(), *Current)EndIfUntil NextElement(DiffFiles()) = 0 ; end of the listEndIf; fill the output gadgetUpdateDiffFileList(); doneShowDiffProgress(#False)SetActiveGadget(#GADGET_Diff_Files)ProcedureReturn #TrueEndProcedure;- Diff dialogProcedure DiffDialogWindowEvents(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()EndIfSelect EventIDCase #PB_Event_CloseWindowQuit = 1Case #PB_Event_GadgetDropIf GadgetID = #GADGET_DiffDialog_File1 Or GadgetID = #GADGET_DiffDialog_File2SetGadgetText(#GADGET_Grep_Directory, StringField(EventDropFiles(), 1, Chr(10)))ElseIf GadgetID = #GADGET_DiffDialog_Directory1 Or GadgetID = #GADGET_DiffDialog_Directory2Path$ = StringField(EventDropFiles(), 1, Chr(10))If FileSize(Path$) <> -2 ; probably a file thenPath$ = GetPathPart(Path$)EndIfSetGadgetText(#GADGET_Grep_Directory, Path$)EndIfCase #PB_Event_GadgetSelect GadgetIDCase #GADGET_DiffDialog_ChooseFile1, #GADGET_DiffDialog_ChooseFile2If GadgetID = #GADGET_DiffDialog_ChooseFile1Gadget = #GADGET_DiffDialog_File1ElseGadget = #GADGET_DiffDialog_File2EndIfFilename$ = OpenFileRequester(Language("FileStuff","OpenFileTitle"), GetGadgetText(Gadget), Language("FileStuff","Pattern"), DiffOpenPattern)If Filename$DiffOpenPattern = SelectedFilePattern()SetGadgetText(Gadget, Filename$)EndIfCase #GADGET_DiffDialog_ChooseDirectory1, #GADGET_DiffDialog_ChooseDirectory2If GadgetID = #GADGET_DiffDialog_ChooseDirectory1Gadget = #GADGET_DiffDialog_Directory1ElseGadget = #GADGET_DiffDialog_Directory2EndIfDirectory$ = PathRequester("", GetGadgetText(Gadget))If Directory$SetGadgetText(Gadget, Directory$)EndIfCase #GADGET_DiffDialog_CurrentDirectory1, #GADGET_DiffDialog_CurrentDirectory2If GadgetID = #GADGET_DiffDialog_CurrentDirectory1Gadget = #GADGET_DiffDialog_Directory1ElseGadget = #GADGET_DiffDialog_Directory2EndIfIf *ActiveSource = *ProjectInfoDirectory$ = GetPathPart(ProjectFile$)ElseIf *ActiveSource And *ActiveSource\FileName$ <> ""Directory$ = GetPathPart(*ActiveSource\FileName$)ElseDirectory$ = GetCurrentDirectory()EndIfSetGadgetText(Gadget, Directory$)Case #GADGET_DiffDialog_IgnoreSpaceAllIf GetGadgetState(#GADGET_DiffDialog_IgnoreSpaceAll)DisableGadget(#GADGET_DiffDialog_IgnoreSpaceLeft, 1)DisableGadget(#GADGET_DiffDialog_IgnoreSpaceRight, 1)ElseDisableGadget(#GADGET_DiffDialog_IgnoreSpaceLeft, 0)DisableGadget(#GADGET_DiffDialog_IgnoreSpaceRight, 0)EndIfCase #GADGET_DiffDialog_CompareFiles, #GADGET_DiffDialog_CompareDirectories; update the comboboxesFor j = #GADGET_DiffDialog_File1 To #GADGET_DiffDialog_PatternUpdateFindComboBox(j)Next j; get the checkboxesDiffRecurse = GetGadgetState(#GADGET_DiffDialog_Recurse)DiffIgnoreCase = GetGadgetState(#GADGET_DiffDialog_IgnoreCase)DiffIgnoreSpaceAll = GetGadgetState(#GADGET_DiffDialog_IgnoreSpaceAll)DiffIgnoreSpaceLeft = GetGadgetState(#GADGET_DiffDialog_IgnoreSpaceLeft)DiffIgnoreSpaceRight = GetGadgetState(#GADGET_DiffDialog_IgnoreSpaceRight)If GadgetID = #GADGET_DiffDialog_CompareFiles; compare filesFile1$ = GetGadgetText(#GADGET_DiffDialog_File1)File2$ = GetGadgetText(#GADGET_DiffDialog_File2)If File1$ = "" Or File2$ = ""MessageRequester(#ProductName,ドル Language("Diff", "EmptyField"))ElseIf DiffFileToFile(File1,ドル File2$)Quit = 1EndIfElse; compare directoriesDirectory1$ = GetGadgetText(#GADGET_DiffDialog_Directory1)Directory2$ = GetGadgetText(#GADGET_DiffDialog_Directory2)If Directory1$ = "" Or Directory2$ = ""MessageRequester(#ProductName,ドル Language("Diff", "EmptyField"))ElseIf Right(Directory1,ドル 1) <> #SeparatorDirectory1$ + #SeparatorEndIfIf Right(Directory2,ドル 1) <> #SeparatorDirectory2$ + #SeparatorEndIfIf DiffDirectories(Directory1,ドル Directory2,ドル GetGadgetText(#GADGET_DiffDialog_Pattern))Quit = 1EndIfEndIfEndIfCase #GADGET_DiffDialog_CancelQuit = 1EndSelectEndSelectIf Quit And IsWindow(#WINDOW_DiffDialog) ; could be closed while processing the directory diff; abort any ongoing search;GrepAbort = 1; get the checkboxesDiffRecurse = GetGadgetState(#GADGET_DiffDialog_Recurse)DiffIgnoreCase = GetGadgetState(#GADGET_DiffDialog_IgnoreCase)DiffIgnoreSpaceAll = GetGadgetState(#GADGET_DiffDialog_IgnoreSpaceAll)DiffIgnoreSpaceLeft = GetGadgetState(#GADGET_DiffDialog_IgnoreSpaceLeft)DiffIgnoreSpaceRight = GetGadgetState(#GADGET_DiffDialog_IgnoreSpaceRight); save historyFor j = 0 To 4Gadget = #GADGET_DiffDialog_File1 + jCount = CountGadgetItems(Gadget)For i = 1 To FindHistorySizeIf Count >= iDiffDialogHistory(j, i) = GetGadgetItemText(Gadget, i-1, 0)ElseDiffDialogHistory(j, i) = ""EndIfNext iNext jIf MemorizeWindowDiffDialogWindowDialog\Close(@DiffDialogWindowPosition)ElseDiffDialogWindowDialog\Close()EndIfEndIfEndProcedureProcedure OpenDiffDialogWindow()If IsWindow(#WINDOW_DiffDialog) = 0DiffDialogWindowDialog = OpenDialog(?Dialog_DiffDialog, WindowID(#WINDOW_Main), @DiffDialogWindowPosition)If DiffDialogWindowDialogEnsureWindowOnDesktop(#WINDOW_DiffDialog)AddKeyboardShortcut(#WINDOW_DiffDialog, #PB_Shortcut_Escape, #GADGET_DiffDialog_Cancel)EnableGadgetDrop(#GADGET_DiffDialog_File1, #PB_Drop_Files, #PB_Drag_Copy)EnableGadgetDrop(#GADGET_DiffDialog_File2, #PB_Drop_Files, #PB_Drag_Copy)EnableGadgetDrop(#GADGET_DiffDialog_Directory1, #PB_Drop_Files, #PB_Drag_Copy)EnableGadgetDrop(#GADGET_DiffDialog_Directory2, #PB_Drop_Files, #PB_Drag_Copy)For j = 0 To 4For i = 1 To FindHistorySizeIf DiffDialogHistory(j, i) <> ""AddGadgetItem(#GADGET_DiffDialog_File1+j, -1, DiffDialogHistory(j, i))EndIfNext iNext jIf CountGadgetItems(#GADGET_DiffDialog_Pattern) = 0AddGadgetItem(#GADGET_DiffDialog_Pattern, -1, "*" + #SourceFileExtension) ; Default to *.pb files, else it will find nothingEndIfFor j = #GADGET_DiffDialog_File1 To #GADGET_DiffDialog_PatternSetGadgetState(j, 0)Next jSetGadgetState(#GADGET_DiffDialog_Recurse, DiffRecurse)SetGadgetState(#GADGET_DiffDialog_IgnoreCase, DiffIgnoreCase)SetGadgetState(#GADGET_DiffDialog_IgnoreSpaceAll, DiffIgnoreSpaceAll)SetGadgetState(#GADGET_DiffDialog_IgnoreSpaceLeft, DiffIgnoreSpaceLeft)SetGadgetState(#GADGET_DiffDialog_IgnoreSpaceRight, DiffIgnoreSpaceRight)If DiffIgnoreSpaceAllDisableGadget(#GADGET_DiffDialog_IgnoreSpaceLeft, 1)DisableGadget(#GADGET_DiffDialog_IgnoreSpaceRight, 1)EndIfHideWindow(#WINDOW_DiffDialog, 0); fix required for the centereing of non-resizable windows in the dialog manager; (works only if window is visible)CompilerIf #CompileLinuxGtkIf DiffDialogWindowPosition\x = -1 And DiffDialogWindowPosition\y = -1While WindowEvent(): Wendgtk_window_set_position_(WindowID(#WINDOW_DiffDialog), #GTK_WIN_POS_CENTER)EndIfCompilerEndIfEndIfElseSetWindowForeground(#WINDOW_DiffDialog)EndIfSelectComboBoxText(#GADGET_DiffDialog_File1)SetActiveGadget(#GADGET_DiffDialog_File1)EndProcedureProcedure UpdateDiffDialogWindow()DiffDialogWindowDialog\LanguageUpdate()For j = 0 To 4Gadget = #GADGET_DiffDialog_File1 + jWhile FindHistorySize < CountGadgetItems(Gadget)RemoveGadgetItem(Gadget, CountGadgetItems(Gadget)-1)WendNext jDiffDialogWindowDialog\GuiUpdate()EndProcedure
此处可能存在不合适展示的内容,页面不予展示。您可通过相关编辑功能自查并修改。
如您确认内容无涉及 不当用语 / 纯广告导流 / 暴力 / 低俗色情 / 侵权 / 盗版 / 虚假 / 无价值内容或违法国家有关法律法规的内容,可点击提交进行申诉,我们将尽快为您处理。