[ Scintilla ] How do I save the current state of a file without affecting the current state of another saved file?

Just starting out? Need help? Post your questions and find answers here.
User avatar
skinkairewalker
Enthusiast
Enthusiast
Posts: 627
Joined: Fri Dec 04, 2015 9:26 pm

[ Scintilla ] How do I save the current state of a file without affecting the current state of another saved file?

Post by skinkairewalker »

Hi guys, I'm making an IDE for my code editor, however I'm having a problem....
in the purebasic IDE, each "tab" created is new code, right?
each tab has its status ( undos, redos, cursor position and others ),
I want to do something similar to this with scintilla, I created a Tab system using "viewtopic.php?f=12&t=47588" and in each "Tab" created I would like to have their own ( Undos, Redos and the position of the courses individually ), someone if the does scintilla have any function that makes it easier to do this?
User avatar
Tenaja
Addict
Addict
Posts: 1948
Joined: Tue Nov 09, 2010 10:15 pm

Re: [ Scintilla ] How do I save the current state of a file without affecting the current state of another saved file?

Post by Tenaja »

Each scintilla instance (each ide tab) gets it's own scintilla handle, so each also gets it's own undo memory. When you issue an undo command, make sure to reference the active tab/instance handle. You pretty much do this with every command.

https://www.scintilla.org/ScintillaDoc.html#UndoAndRedo
User avatar
skinkairewalker
Enthusiast
Enthusiast
Posts: 627
Joined: Fri Dec 04, 2015 9:26 pm

Re: [ Scintilla ] How do I save the current state of a file without affecting the current state of another saved file?

Post by skinkairewalker »

each tab, would i have to launch another scintilla gadget?
or do i have to initialize only 1 scintilla gadget and get the state of each code ?
User avatar
Tenaja
Addict
Addict
Posts: 1948
Joined: Tue Nov 09, 2010 10:15 pm

Re: [ Scintilla ] How do I save the current state of a file without affecting the current state of another saved file?

Post by Tenaja »

You can make the scintilla gadgets on each tabs "window", or you can make the tabs "virtual" and hide/show/give-focus-to the scintilla gadgets for the active tab.

The easiest, either way, is to have a separate scint gadget for reach tab. Otherwise, you have to manually track undo-redo, and you lose a lot of premade functionality.

Have you checked out gosci? It also makes things a lot easier.
User avatar
skinkairewalker
Enthusiast
Enthusiast
Posts: 627
Joined: Fri Dec 04, 2015 9:26 pm

Re: [ Scintilla ] How do I save the current state of a file without affecting the current state of another saved file?

Post by skinkairewalker »

i am using GoScintilla, I tried to make here the issue of creating a scintilla instance for each tab, but it gets too messy...

it would be easier if it had a function that I could save the state of Undo and Redo, before clearing it to load other code, that way I would be able to remove and return the UndoRedo state at any time...
User avatar
Tenaja
Addict
Addict
Posts: 1948
Joined: Tue Nov 09, 2010 10:15 pm

Re: [ Scintilla ] How do I save the current state of a file without affecting the current state of another saved file?

Post by Tenaja »

If it's messy, you are just doing it wrong... Sorry, but it's simple, whether you are allocating structure memory blocks, or using an array or a list to track your tabs and scintilla gadgets, it's a whole lot easier than trying to reinvent the "undo" wheel.

you have a structure for each tab, and that stores the gadget handle & other relevant data. Every time you change tabs, you activate the scintilla gadget of that tab. It's very easy. I'll try to pull out a sample next week, if you are still struggling with it. Trust me, this is a lot easier than managing a whole new Undo project.

You should be able to find samples on this on the forum, too. There's dozens of scintilla samples here. I did it first almost ten years ago, and most of the features I implemented had examples here back then.
User avatar
Tenaja
Addict
Addict
Posts: 1948
Joined: Tue Nov 09, 2010 10:15 pm

Re: [ Scintilla ] How do I save the current state of a file without affecting the current state of another saved file?

Post by Tenaja »

Read this
viewtopic.php?f=13&t=67294&p=499105&hil ... le#p499105
(Can't test that in my phone to see if it's what you need... Sorry)

Several here:
search.php?st=0&sk=t&sd=d&sr=posts&keyw ... e&start=45

And the open source japbe is another example... Surely you can find a link to it's source.
User avatar
skinkairewalker
Enthusiast
Enthusiast
Posts: 627
Joined: Fri Dec 04, 2015 9:26 pm

Re: [ Scintilla ] How do I save the current state of a file without affecting the current state of another saved file?

Post by skinkairewalker »

is there any way to manually add UndoRedo ?
User avatar
PartTimeCoder
User
User
Posts: 14
Joined: Sat Jun 03, 2017 10:26 am

Re: [ Scintilla ] How do I save the current state of a file without affecting the current state of another saved file?

Post by PartTimeCoder »

is there any way to manually add UndoRedo ?
Use Doc pointers, you only need a single Scintilla gadget for multiple documents, UnDo and Redo actions are preserved from doc to doc

To create, set and get new document pointers look at:
#SCI_GETDOCPOINTER
#SCI_SETDOCPOINTER
#SCI_CREATEDOCUMENT

when switching tabs you simply set the required doc pointer, create a structure pointer to hold the info and store it in the tab data

From memory, you will need to save caret position and selection state for each doc and reinstate it when selecting tabs, thats the only gotcha!

To create your own undo/redo stack look at:
#SCI_ADDUNDOACTION
#SCI_BEGINUNDOACTION
#SCI_ENDUNDOACTION
User avatar
PartTimeCoder
User
User
Posts: 14
Joined: Sat Jun 03, 2017 10:26 am

Re: [ Scintilla ] How do I save the current state of a file without affecting the current state of another saved file?

Post by PartTimeCoder »

Its a bit messy, but an example of what I'm saying

Add to GOSCI include

Code: Select all

  Procedure GOSCI_AddDocRef(id, *ptr)
    If IsGadget(id) And GadgetType(id) = #PB_GadgetType_Scintilla And *ptr
      ScintillaSendMessage(id, #SCI_ADDREFDOCUMENT, 0, *ptr)
    EndIf
  EndProcedure  
  
  Procedure GOSCI_GetDocPointer(id)
    If IsGadget(id) And GadgetType(id) = #PB_GadgetType_Scintilla
       Protected *ptr
      *ptr = ScintillaSendMessage(id, #SCI_GETDOCPOINTER)
      ProcedureReturn *ptr
    EndIf
  EndProcedure
  
  Procedure GOSCI_SetDocPointer(id, *ptr)
    If IsGadget(id) And GadgetType(id) = #PB_GadgetType_Scintilla And *ptr
      ScintillaSendMessage(id, #SCI_SETDOCPOINTER, 0, *ptr)
    EndIf
  EndProcedure  
  
  Procedure GOSCI_CreateDocPointer(id)
    If IsGadget(id) And GadgetType(id) = #PB_GadgetType_Scintilla
      Protected *ptr
      *ptr=ScintillaSendMessage(id, #SCI_CREATEDOCUMENT)
      ProcedureReturn *ptr
    EndIf
  EndProcedure  
  
  Procedure GOSCI_ReleaseDocPointer(id, *ptr)
    If IsGadget(id) And GadgetType(id) = #PB_GadgetType_Scintilla And *ptr
      ScintillaSendMessage(id, #SCI_RELEASEDOCUMENT, *ptr)
      ProcedureReturn 
    EndIf
  EndProcedure  
  
  
Example:

Code: Select all

;/////////////////////////////////////////////////////////////////////////////////
;***Go-Scintilla 2***
;*=================
;*
;*©nxSoftWare (www.nxSoftware.com) 2010.
;*======================================
;*    
;*  Commented demo program.
;/////////////////////////////////////////////////////////////////////////////////


IncludePath "../"
XIncludeFile "GoScintilla.pbi"


;Initialise the Scintilla library for Windows.
  CompilerIf  #PB_Compiler_OS = #PB_OS_Windows 
    InitScintilla()
  CompilerEndIf

If OpenWindow(0, 100, 200, 600, 300, "GoScintilla demo!", #PB_Window_SystemMenu | #PB_Window_MinimizeGadget | #PB_Window_ScreenCentered)
  
  RemoveKeyboardShortcut(0, #PB_Shortcut_Tab) ;Required for the tab key to function correctly when the Scintilla control has the focus.
  ;Create our Scintilla control. Note that we do not specify a callback; this is optional for GoSctintilla.
  GOSCI_Create(1, 10, 40, 580, 250, 0, #GOSCI_AUTOSIZELINENUMBERSMARGIN)
  ButtonGadget(2, 310, 10, 100, 30, "Add Tab")
  ButtonGadget(3, 420, 10, 100, 30, "Remove Tab")
  PanelGadget(4, 10, 10, 300, 30)
  ;AddGadgetItem(4, -1, "Inital")
  CloseGadgetList()
  
  ;Set the padding added to the width of the line-number margin.
  GOSCI_SetAttribute(1, #GOSCI_LINENUMBERAUTOSIZEPADDING, 10)

  ;Set folding symbols margin width.
  GOSCI_SetMarginWidth(1, #GOSCI_MARGINFOLDINGSYMBOLS, 24)

  ;Set the back color of the line containing the caret.
  GOSCI_SetColor(1, #GOSCI_CARETLINEBACKCOLOR, $B4FFFF)

  ;Set font.
  GOSCI_SetFont(1, "Courier New", 10)

  ;Set tabs. Here we use a 'hard' tab in which a tab character is physically inserted. Set the 3rd (optional) parameter to 1 to use soft-tabs.
  GOSCI_SetTabs(1, 2)

  ;Set styles for our syntax highlighting.
  ;=======================================
  ;First define some constants to identify our various styles.
  ;You can name these as we wish.
    Enumeration
      #STYLES_COMMANDS = 1
      #STYLES_COMMENTS
      #STYLES_LITERALSTRINGS
      #STYLES_NUMBERS
      #STYLES_CONSTANTS
      #STYLES_FUNCTIONS
    EndEnumeration

  ;Set individual styles for commands.
  GOSCI_SetStyleFont(1, #STYLES_COMMANDS, "", -1, #PB_Font_Bold)
  GOSCI_SetStyleColors(1, #STYLES_COMMANDS, $800000)  ;We have omitted the optional back color.

  ;Set individual styles for comments.
  GOSCI_SetStyleFont(1, #STYLES_COMMENTS, "", -1, #PB_Font_Italic)
  GOSCI_SetStyleColors(1, #STYLES_COMMENTS, $006400)  ;We have omitted the optional back color.

  ;Set individual styles for literal strings.
  GOSCI_SetStyleColors(1, #STYLES_LITERALSTRINGS, #Gray)  ;We have omitted the optional back color.

  ;Set individual styles for numbers.
  GOSCI_SetStyleColors(1, #STYLES_NUMBERS, #Red)  ;We have omitted the optional back color.

  ;Set individual styles for constants.
  GOSCI_SetStyleColors(1, #STYLES_CONSTANTS, $2193DE)  ;We have omitted the optional back color.

  ;Set individual styles for functions.
  GOSCI_SetStyleColors(1, #STYLES_FUNCTIONS, #Blue)  ;We have omitted the optional back color.

  ;Set delimiters and keywords for our syntax highlighting.
  ;========================================================
  ;Delimiters.
  ;First set up a ; symbol to denote a comment. Note the use of #GOSCI_DELIMITTOENDOFLINE.
  ;Note also that this symbol will act as an additional separator.
  GOSCI_AddDelimiter(1, ";", "", #GOSCI_DELIMITTOENDOFLINE, #STYLES_COMMENTS)
  GOSCI_AddDelimiter(1, "/", "", #GOSCI_DELIMITTOENDOFLINE, #STYLES_COMMENTS)
       
  ;Now set up quotes to denote literal strings.
  ;We do this by passing the beginning and end delimiting characters; in this case both are quotation marks. Note the use of #GOSCI_DELIMITBETWEEN.
  ;Note also that a quote will subsequently act as an additional separator.
  GOSCI_AddDelimiter(1, Chr(34), Chr(34), #GOSCI_DELIMITBETWEEN, #STYLES_LITERALSTRINGS)
  ;Now set up a # symbol to denote a constant. Note the use of #GOSCI_LEFTDELIMITWITHOUTWHITESPACE.
  GOSCI_AddDelimiter(1, "#", "", #GOSCI_LEFTDELIMITWITHOUTWHITESPACE, #STYLES_CONSTANTS)
  ;Now set up a ( symbol to denote a function. Note the use of #GOSCI_RIGHTDELIMITWITHWHITESPACE.
  GOSCI_AddDelimiter(1, "(", "", #GOSCI_RIGHTDELIMITWITHWHITESPACE, #STYLES_FUNCTIONS)
  ;We arrange for a ) symbol to match the coloring of the ( symbol.
  GOSCI_AddDelimiter(1, ")", "", 0, #STYLES_FUNCTIONS)

  ;Basic command keywords.
  GOSCI_AddKeywords(1, "Debug End If ElseIf Else EndIf For To Next Step Protected ProcedureReturn", #STYLES_COMMANDS)

  ;Add some folding keywords.
  GOSCI_AddKeywords(1, "Procedure Macro", #STYLES_COMMANDS, #GOSCI_OPENFOLDKEYWORD)
  GOSCI_AddKeywords(1, "EndProcedure EndMacro", #STYLES_COMMANDS, #GOSCI_CLOSEFOLDKEYWORD)

  ;Additional lexer options.
  ;=========================
  ;The lexer needs to know what separator characters we are using.
  GOSCI_SetLexerOption(1, #GOSCI_LEXEROPTION_SEPARATORSYMBOLS, @"=+-*/%()[],.") ;You would use GOSCI_AddKeywords() to set a style for some of these if required.
  ;We can also set a style for numbers.
  GOSCI_SetLexerOption(1, #GOSCI_LEXEROPTION_NUMBERSSTYLEINDEX, #STYLES_NUMBERS)
      
  ;Set some initial text.
  ;======================
  text$ = "; GoScintilla 2.0." + #CRLF$
  text$ + "#MyConstant$ = " + Chr(34) + "Version = 1.0" + Chr(34) + #CRLF$ + #CRLF$
  text$ + "Procedure.i AddIntegers(a, b)" + #CRLF$
  text$ + #TAB$ + "Protected result" + #CRLF$
  text$ + #TAB$ + "result = a + b  ; Calculate the sum of the 2 integers." + #CRLF$
  text$ + #TAB$ + "ProcedureReturn result" + #CRLF$
  text$ + "EndProcedure" + #CRLF$ + #CRLF$
  text$ + "Debug " + Chr(34) + "The sum of 10 and 20 is " + Chr(34) + " + Str(AddIntegers(10, 20))" + #CRLF$ + #CRLF$
  text$ + "End" + #CRLF$
  
     
  GOSCI_SetText(1, text$)
  
  ; inital doc already has a pointer, get it
  GOSCI_SetText(1, "This is tab 1 text")
  *tab1 = GOSCI_GetDocPointer(1)
  GOSCI_AddDocRef(1, *tab1)
  SetGadgetData(2, *tab1)
  
  ; crerate a new doc
  GOSCI_SetDocPointer(1, 0)
  *tab2 = GOSCI_GetDocPointer(1)
  GOSCI_AddDocRef(1, *tab2)
  ;GOSCI_SetDocPointer(1, *tab2)
  SetGadgetData(3, *tab2)
  GOSCI_SetText(1, "This is tab 2 text")
  
  Structure TAB_INFO
    *ref
    
    
  EndStructure
  
  oldsel = -1
  newsel=-1
  
  Repeat
    eventID = WaitWindowEvent()
    Select eventID
      Case #PB_Event_Gadget
        Select EventGadget()
          Case 2
            
            OpenGadgetList(4)
            count=CountGadgetItems(4)
            AddGadgetItem(4, -1, "New Tab "+Str(count))
            
            *tab.TAB_INFO = AllocateStructure(TAB_INFO)
            *tab\ref = GOSCI_CreateDocPointer(1)
            SetGadgetItemData(4, count, *tab)
            CloseGadgetList()
            SetGadgetState(4, count)
            
          Case 3
            
            state=GetGadgetState(4)
            If state <> -1
              *tab.TAB_INFO = GetGadgetItemData(4, state)
              GOSCI_ReleaseDocPointer(4, *tab)
              RemoveGadgetItem(4, state)
              FreeStructure(*tab)
            EndIf
            
          Case 4

             If oldsel<>-1
               *tab.TAB_INFO = GetGadgetItemData(4, oldsel)
               If *tab
                 *tab\ref=GOSCI_GetDocPointer(1)
                 GOSCI_AddDocRef(1, *tab\ref)
               EndIf
             EndIf
           
             newsel = GetGadgetState(4)
             If newsel<>-1
               *tab.TAB_INFO = GetGadgetItemData(4, newsel)
               If *tab
                 GOSCI_SetDocPointer(1, *tab\ref)
               EndIf
             EndIf
             
             oldsel = newsel
        EndSelect
    EndSelect
  Until eventID = #PB_Event_CloseWindow 

  ;Free the Scintilla gadget.
  ;This needs explicitly calling in order to free resources used by GoScintilla.
    GOSCI_Free(1)
EndIf

User avatar
skinkairewalker
Enthusiast
Enthusiast
Posts: 627
Joined: Fri Dec 04, 2015 9:26 pm

Re: [ Scintilla ] How do I save the current state of a file without affecting the current state of another saved file?

Post by skinkairewalker »

awesome PartTimeCoder !!
this solved my problem that I had been trying for more than a week...


thanks a lot !!!!! :D
User avatar
skinkairewalker
Enthusiast
Enthusiast
Posts: 627
Joined: Fri Dec 04, 2015 9:26 pm

Re: [ Scintilla ] How do I save the current state of a file without affecting the current state of another saved file?

Post by skinkairewalker »

I noticed a problem, every document I create using the code above, it doesn't save letter by letter every CTRL + Z (UNDO) or (REDO) below I have some gifs available, the purebasic example is how I would like it to be (each letter is equal to a REDO or UNDO , to make it easier for the user )

Purebasic Undo & Redo ( CTRL + Z ) :
Image

PartTimeCoder code ( CTRL + Z ) :
Image
Post Reply