anchor.diff:      FreeAndNil(items2);
       FreeAndNil(items);
     end;
  +end;
  +
  +procedure TEditorFrame.DoSaveHistory_Bookmarks(Ed: TATSynEdit; c: TJsonConfig; const path: UnicodeString);
  +var
  +  items, items2: TStringList;
  +  bookmark: PATBookmarkItem;
  +  i: integer;
  +begin
  +  items:= TStringList.Create;
  +  items2:= TStringList.Create;
  +  try
  +    for i:= 0 to Ed.Strings.Bookmarks.Count-1 do
  +    begin
  +      bookmark:= Ed.Strings.Bookmarks[i];
  +      //save usual bookmarks and numbered bookmarks (kind=1..10)
  +      if (bookmark^.Data.Kind>10) then Continue;
  +      items.Add(IntToStr(bookmark^.Data.LineNum));
  +      items2.Add(IntToStr(bookmark^.Data.Kind));
  +    end;
  +
  +    if items.Count>0 then
  +      c.SetValue(path+cHistory_Bookmark, items)
  +    else
  +      c.DeleteValue(path+cHistory_Bookmark);
  +
  +    if items2.Count>0 then
  +      c.SetValue(path+cHistory_BookmarkKind, items2)
  +    else
  +      c.DeleteValue(path+cHistory_BookmarkKind);
  +
  +  finally
  +    FreeAndNil(items2);
  +    FreeAndNil(items);
  +  end;
  +end;
  +
  +procedure TEditorFrame.DoSaveHistoryEx(Ed: TATSynEdit; c: TJsonConfig; const path: UnicodeString);
  +begin
  +  //save 'split' value only when we have single file splitted,
  +  //but not 2 different files (like user.json + default.json)
  +  if FileName2='' then
  +  if UiOps.HistoryItems[ahhTabSplit] then
  +  begin
  +    if Splitted then
  +      c.SetValue(path+cHistory_TabSplit, Format('%s,%d', [
  +        BoolToStr(SplitHorz, '1', '0'),
  +        Round(SplitPos*cHistory_TabSplit_Mul)
  +        ]))
  +    else
  +      c.DeleteValue(path+cHistory_TabSplit);
  +  end;
  +
  +  if UiOps.HistoryItems[ahhLexer] then
  +    c.SetDeleteValue(path+cHistory_Lexer, LexerName[Ed], '');
  +
  +  if UiOps.HistoryItems[ahhEncoding] then
  +    c.SetValue(path+cHistory_Enc, Ed.EncodingName);
  +
  +  if UiOps.HistoryItems[ahhTopLine] then
  +  begin
  +    c.SetDeleteValue(path+cHistory_TopLine, Ed.LineTop, 0);
  +    if EditorsLinked and Splitted then
  +      c.SetDeleteValue(path+cHistory_TopLine2, Ed2.LineTop, 0);
  +  end;
  +
  +  if UiOps.HistoryItems[ahhWordWrap] then
  +    c.SetDeleteValue(path+cHistory_Wrap, Ord(Ed.OptWrapMode), Ord(EditorOps.OpWrapMode));
  +
  +  if not Ed.IsReadOnlyAutodetected then
  +    c.SetDeleteValue(path+cHistory_ReadOnly, ReadOnly[Ed], false);
  +
  +  if UiOps.HistoryItems[ahhRuler] then
  +    c.SetDeleteValue(path+cHistory_Ruler, Ord(Ed.OptRulerVisible), Ord(EditorOps.OpRulerShow));
  +
  +  if UiOps.HistoryItems[ahhMinimap] then
  +    c.SetDeleteValue(path+cHistory_Minimap, Ord(Ed.OptMinimapVisible), Ord(EditorOps.OpMinimapShow));
  +
  +  if UiOps.HistoryItems[ahhMicromap] then
  +    c.SetDeleteValue(path+cHistory_Micromap, Ord(Ed.OptMicromapVisible), Ord(EditorOps.OpMicromapShow));
  +
  +  if UiOps.HistoryItems[ahhTabSize] then
  +  begin
  +    c.SetValue(path+cHistory_TabSize, Ed.OptTabSize);
  +    c.SetValue(path+cHistory_TabSpace, Ed.OptTabSpaces);
  +  end;
  +
  +  if UiOps.HistoryItems[ahhUnprinted] then
  +  begin
  +    c.SetDeleteValue(path+cHistory_Unpri, Ord(Ed.OptUnprintedVisible), Ord(EditorOps.OpUnprintedShow));
  +    c.SetDeleteValue(path+cHistory_Unpri_Spaces, Ord(Ed.OptUnprintedSpaces),      Ord(Pos('s', EditorOps.OpUnprintedContent)>0));
  +    c.SetDeleteValue(path+cHistory_Unpri_Ends, Ord(Ed.OptUnprintedEnds),          Ord(Pos('e', EditorOps.OpUnprintedContent)>0));
  +    c.SetDeleteValue(path+cHistory_Unpri_Detail, Ord(Ed.OptUnprintedEndsDetails), Ord(Pos('d', EditorOps.OpUnprintedContent)>0));
  +  end;
  +
  +  if UiOps.HistoryItems[ahhLineNumbers] then
  +    c.SetDeleteValue(path+cHistory_LineNums, Ord(Ed.Gutter[Ed.GutterBandNumbers].Visible), 1);
  +
  +  if UiOps.HistoryItems[ahhScale] then
  +    c.SetDeleteValue(path+cHistory_FontScale, Ed.OptScaleFont, 0);
  +
  +  if UiOps.HistoryItems[ahhFolding] then
  +  begin
  +    c.SetDeleteValue(path+cHistory_FoldingShow, Ord(Ed.Gutter[Ed.GutterBandFolding].Visible), 1);
  +    c.SetDeleteValue(path+cHistory_FoldedRanges, Ed.FoldingAsString, '');
  +  end;
  +
  +  if UiOps.HistoryItems[ahhTabColor] then
  +  begin
  +    if TabColor=clNone then
  +      c.DeleteValue(path+cHistory_TabColor)
  +    else
  +      c.SetValue(path+cHistory_TabColor, ColorToString(TabColor));
  +  end;
  +
  +  if UiOps.HistoryItems[ahhCaret] then
  +    DoSaveHistory_Caret(Ed, c, path);
  +
  +  {
  +  //it's bad to save markers along with other history items,
  +  //because if a snippet (with markers) inserted + file was not saved after it,
  +  //we have wrong markers to save
  +  if UiOps.HistoryItems[ahhMarkers] then
  +    c.SetDeleteValue(path+cHistory_Markers, Ed.Markers.AsString, '');
  +  }
  +
  +  if UiOps.HistoryItems[ahhBookmarks] then
  +    DoSaveHistory_Bookmarks(Ed, c, path);
  +
  +  if UiOps.HistoryItems[ahhCodeTreeFilter] then
  +  begin
  +    c.SetDeleteValue(path+cHistory_CodeTreeFilter, FCodetreeFilter, '');
  +
  +    if FCodetreeFilterHistory.Count>0 then
  +      c.SetValue(path+cHistory_CodeTreeFilters, FCodetreeFilterHistory)
  +    else
  +      c.DeleteValue(path+cHistory_CodeTreeFilters);
  +  end;
  +end;
  +
  +procedure _WriteStringToFileInHiddenDir(const fn, s: string);
  +var
  +  dir: string;
  +begin
  +  if s<>'' then
  +  begin
  +    dir:= ExtractFileDir(fn);
  +    if not DirectoryExists(dir) then
  +    begin
  +      CreateDir(dir);
  +      {$ifdef windows}
  +      FileSetAttr(dir, faHidden);
  +      {$endif}
  +    end;
  +    DoWriteStringToFile(fn, s);
  +  end
  +  else
  +  begin
  +    if FileExists(fn) then
  +      DeleteFile(fn);
  +  end;
  +end;
  +
  +procedure TEditorFrame.DoSaveUndo(Ed: TATSynEdit; const AFileName: string);
  +begin
  +  if IsFilenameListedInExtensionList(AFileName, UiOps.UndoPersistent) then
  +  begin
  +    _WriteStringToFileInHiddenDir(GetAppUndoFilename(AFileName, false), Ed.UndoAsString);
  +    _WriteStringToFileInHiddenDir(GetAppUndoFilename(AFileName, true), Ed.RedoAsString);
  +  end;
  +end;
  +
  +procedure TEditorFrame.DoLoadHistory(Ed: TATSynEdit; AllowEnc: boolean);
  +var
  +  cfg: TJSONConfig;
  +  SFileName: string;
  +  path: string;
  +begin
  +  SFileName:= GetFileName(Ed);
  +  if SFileName='' then exit;
  +  path:= SMaskFilenameSlashes(SFileName);
  +
  +  if UiOps.MaxHistoryFiles<2 then exit;
  +
  +  cfg:= TJsonConfig.Create(nil);
  +  try
  +    try
  +      cfg.Formatted:= true;
  +      cfg.Filename:= AppFile_HistoryFiles;
  +    except
  +      MsgBadConfig(AppFile_HistoryFiles);
  +      exit
  +    end;
  +
  +    DoLoadHistoryEx(Ed, cfg, path, AllowEnc);
  +  finally
  +    cfg.Free;
  +  end;
  +end;
  +
  +
  +procedure TEditorFrame.DoLoadHistoryEx(Ed: TATSynEdit; c: TJsonConfig;
  +  const path: UnicodeString; AllowEnc: boolean);
  +var
  +  str, str0, sFileName, sCaretString: string;
  +  Caret: TATCaretItem;
  +  NCaretPosX, NCaretPosY,
  +  NCaretEndX, NCaretEndY: integer;
  +  nTop, nKind, i: integer;
  +  items, items2: TStringlist;
  +  Sep: TATStringSeparator;
  +  NFlag: integer;
  +begin
  +  sFileName:= GetFileName(Ed);
  +
  +  //file not listed in history file? exit
  +  sCaretString:= c.GetValue(path+cHistory_Caret, '');
  +  if sCaretString='' then exit;
  +
  +  {
  +  //markers
  +  //it's bad to save markers along with other history items,
  +  //so this is commented
  +  Ed.Markers.AsString:= c.GetValue(path+cHistory_Markers, '');
  +  }
  +
  +  //split state
  +  str:= c.GetValue(path+cHistory_TabSplit, '');
  +  if str<>'' then
  +  begin
  +    Sep.Init(str);
  +    Sep.GetItemInt(i, 0);
  +    SplitHorz:= i=1;
  +    Splitted:= true;
  +    Sep.GetItemInt(i, 0);
  +    if i>0 then
  +      SplitPos:= i/cHistory_TabSplit_Mul;
  +  end;
  +
  +  //lexer
  +  str0:= LexerName[Ed];
  +  str:= c.GetValue(path+cHistory_Lexer, ''); //missed value means none-lexer (for Cud 1.104 or older)
  +  if (str='') or (str<>str0) then //better call it for none-lexer to apply "keys lexer -.json"
  +    LexerName[Ed]:= str;
  +
  +  //encoding
  +  if AllowEnc then
  +  begin
  +    str0:= Ed.EncodingName;
  +    str:= c.GetValue(path+cHistory_Enc, str0);
  +    if str<>str0 then
  +    begin
  +      Ed.EncodingName:= str;
  +      //reread in encoding
  +      //but only if not modified (modified means other text is loaded)
  +      if sFileName<>'' then
  +        if not Ed.Modified then
  +        begin
  +          Ed.Strings.EncodingDetect:= false;
  +          Ed.LoadFromFile(sFileName);
  +          Ed.Strings.EncodingDetect:= true;
  +        end;
  +    end;
  +  end;
  +
  +  TabColor:= StringToColorDef(c.GetValue(path+cHistory_TabColor, ''), clNone);
  +
  +  if not Ed.IsReadOnlyAutodetected then
  +    ReadOnly[Ed]:= c.GetValue(path+cHistory_ReadOnly, ReadOnly[Ed]);
  +
  +  if not FileWasBig[Ed] then
  +  begin
  +    NFlag:= c.GetValue(path+cHistory_Wrap, -1);
  +    if NFlag>=0 then
  +      if Ed.OptWrapMode<>TATEditorWrapMode(NFlag) then
  +      begin
  +        Ed.OptWrapMode:= TATEditorWrapMode(NFlag);
  +        Ed.IsModifiedWrapMode:= true;
  +        //DoPyEventState(Ed, EDSTATE_WRAP); //is not needed for session loading
  +      end;
  +
  +    NFlag:= c.GetValue(path+cHistory_Minimap, -1);
  +    if NFlag>=0 then
  +    begin
  +      Ed.OptMinimapVisible:= NFlag=1;
  +      Ed.IsModifiedMinimapVisible:= true;
  +    end;
  +
  +    NFlag:= c.GetValue(path+cHistory_Micromap, -1);
  +    if NFlag>=0 then
  +    begin
  +      Ed.OptMicromapVisible:= NFlag=1;
  +      Ed.IsModifiedMicromapVisible:= true;
  +    end;
  +  end;
  +
  +  NFlag:= c.GetValue(path+cHistory_Ruler, -1);
  +  if NFlag>=0 then
  +  begin
  +    Ed.OptRulerVisible:= NFlag=1;
  +    Ed.IsModifiedRulerVisible:= true;
  +  end;
  +
  +  Ed.OptTabSize:= c.GetValue(path+cHistory_TabSize, Ed.OptTabSize);
  +  Ed.OptTabSpaces:= c.GetValue(path+cHistory_TabSpace, Ed.OptTabSpaces);
  +
  +  NFlag:= c.GetValue(path+cHistory_Unpri, -1);
  +  if NFlag>=0 then
  +  begin
  +    Ed.OptUnprintedVisible:= NFlag=1;
  +    Ed.IsModifiedUnprintedVisible:= true;
  +  end;
  +
  +  NFlag:= c.GetValue(path+cHistory_Unpri_Spaces, -1);
  +  if NFlag>=0 then
  +  begin
  +    Ed.OptUnprintedSpaces:= NFlag=1;
  +    Ed.IsModifiedUnprintedSpaces:= true;
  +  end;
  +
  +  NFlag:= c.GetValue(path+cHistory_Unpri_Ends, -1);
  +  if NFlag>=0 then
  +  begin
  +    Ed.OptUnprintedEnds:= NFlag=1;
  +    Ed.IsModifiedUnprintedEnds:= true;
  +  end;
  +
  +  NFlag:= c.GetValue(path+cHistory_Unpri_Detail, -1);
  +  if NFlag>=0 then
  +  begin
  +    Ed.OptUnprintedEndsDetails:= NFlag=1;
  +    Ed.IsModifiedUnprintedEndDetails:= true;
  +  end;
  +
  +  with Ed.Gutter[Ed.GutterBandNumbers] do
  +  begin
  +    NFlag:= c.GetValue(path+cHistory_LineNums, -1);
  +    if NFlag>=0 then
  +    begin
  +      Visible:= NFlag=1;
  +      Ed.IsModifiedGutterNumbersVisible:= true;
  +    end;
  +  end;
  +
  +  with Ed.Gutter[Ed.GutterBandFolding] do
  +  begin
  +    NFlag:= c.GetValue(path+cHistory_FoldingShow, -1);
  +    if NFlag>=0 then
  +    begin
  +      Visible:= NFlag=1;
  +      Ed.IsModifiedGutterFoldingVisible:= true;
  +    end;
  +  end;
  +
  +  Ed.OptScaleFont:= c.GetValue(path+cHistory_FontScale, 0);
  +
  +  if Assigned(Lexer[Ed]) then
  +    Ed.FoldingAsStringTodo:= c.GetValue(path+cHistory_FoldedRanges, '');
  +
  +  nTop:= c.GetValue(path+cHistory_TopLine, 0);
  +  if nTop>0 then
  +    Ed.LineTop:= nTop;
  +
  +  if EditorsLinked and Splitted then
  +  begin
  +    nTop:= c.GetValue(path+cHistory_TopLine2, 0);
  +    if nTop>0 then
  +      Ed2.LineTop:= nTop;
  +  end;
  +
  +  //caret
  +  Sep.Init(sCaretString);
  +  Sep.GetItemInt(NCaretPosX, 0);
  +  Sep.GetItemInt(NCaretPosY, 0);
  +  Sep.GetItemInt(NCaretEndX, -1);
  +  Sep.GetItemInt(NCaretEndY, -1);
  +
  +  if Ed.Carets.Count<>1 then
  +    Ed.DoCaretSingle(0, 0);
  +  Caret:= Ed.Carets[0];
  +  if Caret.Change(NCaretPosX, NCaretPosY, NCaretEndX, NCaretEndY) then
  +  begin
  +    Ed.DoCaretsFixIncorrectPos(true);
  +    Ed.DoEventCarets;
  +  end;
  +
  +  //solve CudaText #3288, so Undo jumps to initial caret pos
  +  Ed.Strings.ActionSaveLastEditionPos(NCaretPosX, NCaretPosY);
  +
  +  //bookmarks
  +  DoLoadHistory_Bookmarks(Ed, c, path);
   
     FCodetreeFilter:= c.GetValue(path+cHistory_CodeTreeFilter, '');
     c.GetValue(path+cHistory_CodeTreeFilters, FCodetreeFilterHistory, '');
  
positive.code:    end;
  end;
  
  procedure TEditorFrame.DoSaveHistory_Bookmarks(Ed: TATSynEdit; c: TJsonConfig; const path: UnicodeString);
  var
    items, items2: TStringList;
    bookmark: PATBookmarkItem;
    i: integer;
  begin
    items:= TStringList.Create;
    items2:= TStringList.Create;
    try
      for i:= 0 to Ed.Strings.Bookmarks.Count-1 do
      begin
        bookmark:= Ed.Strings.Bookmarks[i];
        //save usual bookmarks and numbered bookmarks (kind=1..10)
        if (bookmark^.Data.Kind>10) then Continue;
        items.Add(IntToStr(bookmark^.Data.LineNum));
        items2.Add(IntToStr(bookmark^.Data.Kind));
      end;
  
      if items.Count>0 then
        c.SetValue(path+cHistory_Bookmark, items)
      else
        c.DeleteValue(path+cHistory_Bookmark);
  
      if items2.Count>0 then
        c.SetValue(path+cHistory_BookmarkKind, items2)
      else
        c.DeleteValue(path+cHistory_BookmarkKind);
  
    finally
      FreeAndNil(items2);
      FreeAndNil(items);
    end;
  end;
  
  procedure TEditorFrame.DoSaveHistoryEx(Ed: TATSynEdit; c: TJsonConfig; const path: UnicodeString);
  begin
    //save 'split' value only when we have single file splitted,
    //but not 2 different files (like user.json + default.json)
    if FileName2='' then
    if UiOps.HistoryItems[ahhTabSplit] then
    begin
      if Splitted then
        c.SetValue(path+cHistory_TabSplit, Format('%s,%d', [
          BoolToStr(SplitHorz, '1', '0'),
          Round(SplitPos*cHistory_TabSplit_Mul)
          ]))
      else
        c.DeleteValue(path+cHistory_TabSplit);
    end;
  
    if UiOps.HistoryItems[ahhLexer] then
      c.SetDeleteValue(path+cHistory_Lexer, LexerName[Ed], '');
  
    if UiOps.HistoryItems[ahhEncoding] then
      c.SetValue(path+cHistory_Enc, Ed.EncodingName);
  
    if UiOps.HistoryItems[ahhTopLine] then
    begin
      c.SetDeleteValue(path+cHistory_TopLine, Ed.LineTop, 0);
      if EditorsLinked and Splitted then
        c.SetDeleteValue(path+cHistory_TopLine2, Ed2.LineTop, 0);
    end;
  
    if UiOps.HistoryItems[ahhWordWrap] then
      c.SetDeleteValue(path+cHistory_Wrap, Ord(Ed.OptWrapMode), Ord(EditorOps.OpWrapMode));
  
    if not Ed.IsReadOnlyAutodetected then
      c.SetDeleteValue(path+cHistory_ReadOnly, ReadOnly[Ed], false);
  
    if UiOps.HistoryItems[ahhRuler] then
      c.SetDeleteValue(path+cHistory_Ruler, Ord(Ed.OptRulerVisible), Ord(EditorOps.OpRulerShow));
  
    if UiOps.HistoryItems[ahhMinimap] then
      c.SetDeleteValue(path+cHistory_Minimap, Ord(Ed.OptMinimapVisible), Ord(EditorOps.OpMinimapShow));
  
    if UiOps.HistoryItems[ahhMicromap] then
      c.SetDeleteValue(path+cHistory_Micromap, Ord(Ed.OptMicromapVisible), Ord(EditorOps.OpMicromapShow));
  
    if UiOps.HistoryItems[ahhTabSize] then
    begin
      c.SetValue(path+cHistory_TabSize, Ed.OptTabSize);
      c.SetValue(path+cHistory_TabSpace, Ed.OptTabSpaces);
    end;
  
    if UiOps.HistoryItems[ahhUnprinted] then
    begin
      c.SetDeleteValue(path+cHistory_Unpri, Ord(Ed.OptUnprintedVisible), Ord(EditorOps.OpUnprintedShow));
      c.SetDeleteValue(path+cHistory_Unpri_Spaces, Ord(Ed.OptUnprintedSpaces),      Ord(Pos('s', EditorOps.OpUnprintedContent)>0));
      c.SetDeleteValue(path+cHistory_Unpri_Ends, Ord(Ed.OptUnprintedEnds),          Ord(Pos('e', EditorOps.OpUnprintedContent)>0));
      c.SetDeleteValue(path+cHistory_Unpri_Detail, Ord(Ed.OptUnprintedEndsDetails), Ord(Pos('d', EditorOps.OpUnprintedContent)>0));
    end;
  
    if UiOps.HistoryItems[ahhLineNumbers] then
      c.SetDeleteValue(path+cHistory_LineNums, Ord(Ed.Gutter[Ed.GutterBandNumbers].Visible), 1);
  
    if UiOps.HistoryItems[ahhScale] then
      c.SetDeleteValue(path+cHistory_FontScale, Ed.OptScaleFont, 0);
  
    if UiOps.HistoryItems[ahhFolding] then
    begin
      c.SetDeleteValue(path+cHistory_FoldingShow, Ord(Ed.Gutter[Ed.GutterBandFolding].Visible), 1);
      c.SetDeleteValue(path+cHistory_FoldedRanges, Ed.FoldingAsString, '');
    end;
  
    if UiOps.HistoryItems[ahhTabColor] then
    begin
      if TabColor=clNone then
        c.DeleteValue(path+cHistory_TabColor)
      else
        c.SetValue(path+cHistory_TabColor, ColorToString(TabColor));
    end;
  
    if UiOps.HistoryItems[ahhCaret] then
      DoSaveHistory_Caret(Ed, c, path);
  
    {
    //it's bad to save markers along with other history items,
    //because if a snippet (with markers) inserted + file was not saved after it,
    //we have wrong markers to save
    if UiOps.HistoryItems[ahhMarkers] then
      c.SetDeleteValue(path+cHistory_Markers, Ed.Markers.AsString, '');
    }
  
    if UiOps.HistoryItems[ahhBookmarks] then
      DoSaveHistory_Bookmarks(Ed, c, path);
  
    if UiOps.HistoryItems[ahhCodeTreeFilter] then
    begin
      c.SetDeleteValue(path+cHistory_CodeTreeFilter, FCodetreeFilter, '');
  
      if FCodetreeFilterHistory.Count>0 then
        c.SetValue(path+cHistory_CodeTreeFilters, FCodetreeFilterHistory)
      else
        c.DeleteValue(path+cHistory_CodeTreeFilters);
    end;
  end;
  
  procedure _WriteStringToFileInHiddenDir(const fn, s: string);
  var
    dir: string;
  begin
    if s<>'' then
    begin
      dir:= ExtractFileDir(fn);
      if not DirectoryExists(dir) then
      begin
        CreateDir(dir);
        {$ifdef windows}
        FileSetAttr(dir, faHidden);
        {$endif}
      end;
      DoWriteStringToFile(fn, s);
    end
    else
    begin
      if FileExists(fn) then
        DeleteFile(fn);
    end;
  end;
  
  procedure TEditorFrame.DoSaveUndo(Ed: TATSynEdit; const AFileName: string);
  begin
    if IsFilenameListedInExtensionList(AFileName, UiOps.UndoPersistent) then
    begin
      _WriteStringToFileInHiddenDir(GetAppUndoFilename(AFileName, false), Ed.UndoAsString);
      _WriteStringToFileInHiddenDir(GetAppUndoFilename(AFileName, true), Ed.RedoAsString);
    end;
  end;
  
  procedure TEditorFrame.DoLoadHistory(Ed: TATSynEdit; AllowEnc: boolean);
  var
    cfg: TJSONConfig;
    SFileName: string;
    path: string;
  begin
    SFileName:= GetFileName(Ed);
    if SFileName='' then exit;
    path:= SMaskFilenameSlashes(SFileName);
  
    if UiOps.MaxHistoryFiles<2 then exit;
  
    cfg:= TJsonConfig.Create(nil);
    try
      try
        cfg.Formatted:= true;
        cfg.Filename:= AppFile_HistoryFiles;
      except
        MsgBadConfig(AppFile_HistoryFiles);
        exit
      end;
  
      DoLoadHistoryEx(Ed, cfg, path, AllowEnc);
    finally
      cfg.Free;
    end;
  end;
  
  
  procedure TEditorFrame.DoLoadHistoryEx(Ed: TATSynEdit; c: TJsonConfig;
    const path: UnicodeString; AllowEnc: boolean);
  var
    str, str0, sFileName, sCaretString: string;
    Caret: TATCaretItem;
    NCaretPosX, NCaretPosY,
    NCaretEndX, NCaretEndY: integer;
    nTop, nKind, i: integer;
    items, items2: TStringlist;
    BmData: TATBookmarkData;
    Sep: TATStringSeparator;
    NFlag: integer;
  begin
    sFileName:= GetFileName(Ed);
  
    FillChar(BmData, SizeOf(BmData), 0);
    BmData.ShowInBookmarkList:= true;
  
    //file not listed in history file? exit
    sCaretString:= c.GetValue(path+cHistory_Caret, '');
    if sCaretString='' then exit;
  
    {
    //markers
    //it's bad to save markers along with other history items,
    //so this is commented
    Ed.Markers.AsString:= c.GetValue(path+cHistory_Markers, '');
    }
  
    //split state
    str:= c.GetValue(path+cHistory_TabSplit, '');
    if str<>'' then
    begin
      Sep.Init(str);
      Sep.GetItemInt(i, 0);
      SplitHorz:= i=1;
      Splitted:= true;
      Sep.GetItemInt(i, 0);
      if i>0 then
        SplitPos:= i/cHistory_TabSplit_Mul;
    end;
  
    //lexer
    str0:= LexerName[Ed];
    str:= c.GetValue(path+cHistory_Lexer, ''); //missed value means none-lexer (for Cud 1.104 or older)
    if (str='') or (str<>str0) then //better call it for none-lexer to apply "keys lexer -.json"
      LexerName[Ed]:= str;
  
    //encoding
    if AllowEnc then
    begin
      str0:= Ed.EncodingName;
      str:= c.GetValue(path+cHistory_Enc, str0);
      if str<>str0 then
      begin
        Ed.EncodingName:= str;
        //reread in encoding
        //but only if not modified (modified means other text is loaded)
        if sFileName<>'' then
          if not Ed.Modified then
          begin
            Ed.Strings.EncodingDetect:= false;
            Ed.LoadFromFile(sFileName);
            Ed.Strings.EncodingDetect:= true;
          end;
      end;
    end;
  
    TabColor:= StringToColorDef(c.GetValue(path+cHistory_TabColor, ''), clNone);
  
    if not Ed.IsReadOnlyAutodetected then
      ReadOnly[Ed]:= c.GetValue(path+cHistory_ReadOnly, ReadOnly[Ed]);
  
    if not FileWasBig[Ed] then
    begin
      NFlag:= c.GetValue(path+cHistory_Wrap, -1);
      if NFlag>=0 then
        if Ed.OptWrapMode<>TATEditorWrapMode(NFlag) then
        begin
          Ed.OptWrapMode:= TATEditorWrapMode(NFlag);
          Ed.IsModifiedWrapMode:= true;
          //DoPyEventState(Ed, EDSTATE_WRAP); //is not needed for session loading
        end;
  
      NFlag:= c.GetValue(path+cHistory_Minimap, -1);
      if NFlag>=0 then
      begin
        Ed.OptMinimapVisible:= NFlag=1;
        Ed.IsModifiedMinimapVisible:= true;
      end;
  
      NFlag:= c.GetValue(path+cHistory_Micromap, -1);
      if NFlag>=0 then
      begin
        Ed.OptMicromapVisible:= NFlag=1;
        Ed.IsModifiedMicromapVisible:= true;
      end;
    end;
  
    NFlag:= c.GetValue(path+cHistory_Ruler, -1);
    if NFlag>=0 then
    begin
      Ed.OptRulerVisible:= NFlag=1;
      Ed.IsModifiedRulerVisible:= true;
    end;
  
    Ed.OptTabSize:= c.GetValue(path+cHistory_TabSize, Ed.OptTabSize);
    Ed.OptTabSpaces:= c.GetValue(path+cHistory_TabSpace, Ed.OptTabSpaces);
  
    NFlag:= c.GetValue(path+cHistory_Unpri, -1);
    if NFlag>=0 then
    begin
      Ed.OptUnprintedVisible:= NFlag=1;
      Ed.IsModifiedUnprintedVisible:= true;
    end;
  
    NFlag:= c.GetValue(path+cHistory_Unpri_Spaces, -1);
    if NFlag>=0 then
    begin
      Ed.OptUnprintedSpaces:= NFlag=1;
      Ed.IsModifiedUnprintedSpaces:= true;
    end;
  
    NFlag:= c.GetValue(path+cHistory_Unpri_Ends, -1);
    if NFlag>=0 then
    begin
      Ed.OptUnprintedEnds:= NFlag=1;
      Ed.IsModifiedUnprintedEnds:= true;
    end;
  
    NFlag:= c.GetValue(path+cHistory_Unpri_Detail, -1);
    if NFlag>=0 then
    begin
      Ed.OptUnprintedEndsDetails:= NFlag=1;
      Ed.IsModifiedUnprintedEndDetails:= true;
    end;
  
    with Ed.Gutter[Ed.GutterBandNumbers] do
    begin
      NFlag:= c.GetValue(path+cHistory_LineNums, -1);
      if NFlag>=0 then
      begin
        Visible:= NFlag=1;
        Ed.IsModifiedGutterNumbersVisible:= true;
      end;
    end;
  
    with Ed.Gutter[Ed.GutterBandFolding] do
    begin
      NFlag:= c.GetValue(path+cHistory_FoldingShow, -1);
      if NFlag>=0 then
      begin
        Visible:= NFlag=1;
        Ed.IsModifiedGutterFoldingVisible:= true;
      end;
    end;
  
    Ed.OptScaleFont:= c.GetValue(path+cHistory_FontScale, 0);
  
    if Assigned(Lexer[Ed]) then
      Ed.FoldingAsStringTodo:= c.GetValue(path+cHistory_FoldedRanges, '');
  
    nTop:= c.GetValue(path+cHistory_TopLine, 0);
    if nTop>0 then
      Ed.LineTop:= nTop;
  
    if EditorsLinked and Splitted then
    begin
      nTop:= c.GetValue(path+cHistory_TopLine2, 0);
      if nTop>0 then
        Ed2.LineTop:= nTop;
    end;
  
    //caret
    Sep.Init(sCaretString);
    Sep.GetItemInt(NCaretPosX, 0);
    Sep.GetItemInt(NCaretPosY, 0);
    Sep.GetItemInt(NCaretEndX, -1);
    Sep.GetItemInt(NCaretEndY, -1);
  
    if Ed.Carets.Count<>1 then
      Ed.DoCaretSingle(0, 0);
    Caret:= Ed.Carets[0];
    if Caret.Change(NCaretPosX, NCaretPosY, NCaretEndX, NCaretEndY) then
    begin
      Ed.DoCaretsFixIncorrectPos(true);
      Ed.DoEventCarets;
    end;
  
    //solve CudaText #3288, so Undo jumps to initial caret pos
    Ed.Strings.ActionSaveLastEditionPos(NCaretPosX, NCaretPosY);
  
    //bookmarks
    items:= TStringList.create;
    items2:= TStringList.create;
    try
      c.GetValue(path+cHistory_Bookmark, items, '');
      c.GetValue(path+cHistory_BookmarkKind, items2, '');
  
negative.code:     procedure DoSaveHistoryEx(Ed: TATSynEdit; c: TJsonConfig; const path: UnicodeString);
      procedure DoLoadHistory(Ed: TATSynEdit; AllowEnc: boolean);
      procedure DoLoadHistoryEx(Ed: TATSynEdit; c: TJsonConfig; const path: UnicodeString; AllowEnc: boolean);
      procedure DoLoadHistory_Bookmarks(Ed: TATSynEdit; c: TJsonConfig; const path: UnicodeString);
      //misc
      function DoPyEvent(AEd: TATSynEdit; AEvent: TAppPyEvent; const AParams: TAppVariantArray): TAppPyEventResult;
      procedure DoPyEventState(Ed: TATSynEdit; AState: integer);
  