(* This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. If a copy of the MPL was not distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/. Copyright (c) Alexey Torgashin *) {$ifdef nn}begin end;{$endif} const cPyEditorHandleMin = 10; cPyEditorHandleMax = 10000; //maximal API editor handle; (max-min) limits count of opened ui-tabs cPyTokenKind: array[TATTokenKind] of string = ('a', 'c', 's'); cPyUniqueTag: Int64 = 120; //initial value returned by app_proc(PROC_GET_UNIQUE_TAG) var PyEscapeFlag: boolean; //Esc key was pressed in application PyEditorMaybeDeleted: boolean; //command plugin maybe deleted the editor, e.g. 'close file' command does it PyCurrentProject: string; //full path of active Project Manager project (*.cuda-proj) PyCurrentProjectFolder: string; //currently opened folder in Project Manager var AppEmmet: TEmmet; procedure MsgLogConsoleOnDuplicateTreeNode(ANode: TTreeNode; const AFileName: string); var Obj: TObject; NLine: integer; S: string; begin //skip notes about HTML lexer, which has stupid node names like '
' S:= ANode.Text; if (Length(S)>=3) and (S[1]='<') and (S[Length(S)]='>') and IsCharWordA(S[2]) then exit; S:= 'NOTE: Duplicate code-tree caption, cannot restore its folding: '; Obj:= TObject(ANode.Data); if Obj is TATRangeInCodeTree then begin NLine:= (Obj as TATRangeInCodeTree).PosBegin.Y; S+= Format('file "%s", line %d, ', [ExtractFileName(AFileName), NLine+1]); end; S+= Format('node "%s"', [ANode.Text]); MsgLogConsole(S); end; procedure AppSessionName_Set(const S: string); begin if AppSessionName_<>S then begin AppSessionName_:= S; fmMain.DoPyEvent(nil, TAppPyEvent.OnState, [AppVariant(APPSTATE_SESSION_SET)]); end; end; function PyHelper_ObjectHandle(Obj: TObject): PPyObject; inline; begin Result:= AppPython.ObjectToPyInt(Obj); end; function PyHelper_SendMessageFromString(const AText: string): integer; var H: Int64; Msg: DWord; Param1, Param2: integer; Sep: TATStringSeparator; begin Sep.Init(AText); Sep.GetItemInt64(H, 0); if H=0 then exit(0); Sep.GetItemDWord(Msg, 0); if Msg=0 then exit(0); Sep.GetItemInt(Param1, 0); Sep.GetItemInt(Param2, 0); Result:= SendMessage(HWND(H), Cardinal(Msg), Param1, Param2); end; procedure PyHelper_EditorFocus(Ed: TATSynEdit); var F: TEditorFrame; begin F:= TGroupsHelper.GetEditorFrame(Ed); //support editors in frames, activate tab too if Assigned(F) then //don't check F.Visible and F.Enabled, issue #3543 begin fmMain.SetFrame(F); F.SetFocus; EditorFocus(Ed); fmMain.UpdateFrameEx(F, false); fmMain.UpdateStatusbar; end else //support editors from dlg_proc EditorFocus(Ed); end; //func at begin function PyHelper_EditorFromHandle(Handle: Int64): TATSynEdit; var Obj: TObject; nTab: Integer; Frame: TEditorFrame; begin Result:= nil; if not Assigned(fmMain) then exit; if (Handle<0) or (Handle>cPyEditorHandleMax) then begin Obj:= TObject(PtrInt(Handle)); if not (Obj is TATSynEdit) then begin MsgLogConsole('ERROR: Editor() gets bad handle, of type '+Obj.ClassName); exit; end; exit(TATSynEdit(Obj)); //Access Violation for incorrect handle end; case Handle of 0: //"ed" begin Result:= fmMain.CurrentEditor; if Result=nil then begin if fmMain.FrameCount>0 then begin Frame:= fmMain.Frames[0]; TGroupsHelper.ForceFrameVisible(Frame); Frame.SetFocus(); Result:= Frame.EdFirst; end else MsgLogConsole('ERROR: API "ed" is Nil, and no frames; report to author what you are doing'); end; end; 1: begin Frame:= fmMain.FrameOfPopup; if Assigned(Frame) then Result:= Frame.EdFirst else Result:= fmMain.CurrentEditor; end; cPyEditorHandleMin..cPyEditorHandleMax: begin nTab:= Handle-cPyEditorHandleMin; if (nTab>=0) and (nTab=0) and (N0 then begin Obj:= TObject(N); if Obj is TImageList then exit(TImageList(Obj)); end; end; function PyHelper_MenuItemFromId(const Str: string; const ApiFunctionName: string = 'menu_proc'): TMenuItem; const cPrefixToolmenu = 'toolmenu:'; var Obj: TObject; TempPopup: TPopupMenu; N: PtrInt; begin Result:= nil; N:= StrToInt64Def(Str, 0); if N<>0 then begin Obj:= TObject(N); if Obj is TMenuItem then exit(TMenuItem(Obj)) else begin MsgLogConsole(Format('ERROR: %s() gets bad handle, of type %s', [ApiFunctionName, Obj.ClassName])); exit; end; end; if Str=PyMenuId_Top then exit(fmMain.MainMenu.Items); if Str=PyMenuId_TopEdit then exit(fmMain.mnuEdit); if Str=PyMenuId_TopSel then exit(fmMain.mnuSel); if Str=PyMenuId_TopSearch then exit(fmMain.mnuFind); if Str=PyMenuId_TopFile then exit(fmMain.mnuFile); if Str=PyMenuId_TopView then exit(fmMain.mnuView); if Str=PyMenuId_TopOptions then exit(fmMain.mnuOp); if Str=PyMenuId_TopHelp then exit(fmMain.mnuHelp); if Str=PyMenuId_TopGroups then exit(fmMain.mnuSplit); if Str=PyMenuId_Text then exit(fmMain.PopupText.Items); if Str=PyMenuId_Tab then begin fmMain.InitPopupTab; exit(fmMain.PopupTab.Items); end; if SBeginsWith(Str, cPrefixToolmenu) then begin for N:= 0 to fmMain.ToolbarMain.ButtonCount-1 do if fmMain.ToolbarMain.Buttons[N].DataString=Str then begin TempPopup:= fmMain.ToolbarMain.Buttons[N].PopupDropdown; if Assigned(TempPopup) then Result:= TempPopup.Items; exit; end; end; end; procedure TfmMain.PythonIOSendUniData(Sender: TObject; const Data: UnicodeString); // procedure MaybeWriteln(const S: UnicodeString); inline; begin {$ifdef unix} if UiOps.PyOutputCopyToStdout then Writeln(S); {$endif} end; // var Sep: TATStringSeparator; S: UnicodeString; begin if Pos(#10, Data)=0 then begin AppConsoleQueue.Push(Data); MaybeWriteln(Data); end else begin Sep.Init(Data, #10); while Sep.GetItemStr(S) do begin AppConsoleQueue.Push(S); MaybeWriteln(S); end; end; end; function api_app_ver(Self, Args : PPyObject): PPyObject; cdecl; begin with AppPython.Engine do Result:= Py_BuildValue('(ss)', cAppApiVersion, cAppExeVersion ); end; function api_app_path(Self, Args : PPyObject): PPyObject; cdecl; var Id: integer; begin with AppPython.Engine do if Bool(PyArg_ParseTuple(Args, 'i:app_path', @Id)) then case Id of APP_DIR_EXE: Result:= PyUnicodeFromString(ExtractFileDir(Application.ExeName)); APP_DIR_SETTINGS: Result:= PyUnicodeFromString(AppDir_Settings); APP_DIR_SETTINGS_DEF: Result:= PyUnicodeFromString(AppDir_SettingsDefault); APP_DIR_DATA: Result:= PyUnicodeFromString(AppDir_Data); APP_DIR_PY: Result:= PyUnicodeFromString(AppDir_Py); APP_FILE_SESSION: Result:= PyUnicodeFromString(AppFile_Session); APP_DIR_INSTALLED_ADDON: Result:= PyUnicodeFromString(AppDir_LastInstalledAddon); APP_FILE_RECENT_LIST: Result:= StringsToPyList(AppListRecents); else Result:= ReturnNone; end else Result:= ReturnNone; end; function api_app_idle(Self, Args: PPyObject): PPyObject; cdecl; { TODO 2026.09 or .10 - add here Console message "ERROR: app_idle is deprecated, avoid it" 2026.12 - update all plugins and delete app_idle } var Flag: LongBool; begin with AppPython.Engine do if Bool(PyArg_ParseTuple(Args, 'i:app_idle', @Flag)) then begin Application.ProcessMessages; Application.Idle(Flag); Result:= AppPython.Engine.ReturnNone; end else Result:= ReturnNone; end; function api_dlg_input(Self, Args : PPyObject): PPyObject; cdecl; var P1, P2: PChar; StrCaption, StrVal: string; begin with AppPython.Engine do if Bool(PyArg_ParseTuple(Args, 'ss:dlg_input', @P1, @P2)) then begin StrCaption:= string(P1); StrVal:= string(P2); if InputQuery(msgTitle, StrCaption, StrVal) then Result:= PyUnicodeFromString(StrVal) else Result:= ReturnNone; end else Result:= ReturnNone; end; function api_dlg_input_ex(Self, Args : PPyObject): PPyObject; cdecl; var Number, i: integer; PCaption: PChar; PLabel, PText: array[1..10] of PChar; SCaption: string; Labels, Values: array of string; List: TStringList; begin with AppPython.Engine do if Bool(PyArg_ParseTuple(Args, 'isssssssssssssssssssss:dlg_input_ex', @Number, @PCaption, @PLabel[1], @PText[1], @PLabel[2], @PText[2], @PLabel[3], @PText[3], @PLabel[4], @PText[4], @PLabel[5], @PText[5], @PLabel[6], @PText[6], @PLabel[7], @PText[7], @PLabel[8], @PText[8], @PLabel[9], @PText[9], @PLabel[10], @PText[10])) then begin Number:= Max(1, Min(10, Number)); SCaption:= string(PCaption); Labels:= nil; Values:= nil; SetLength(Labels, Number); SetLength(Values, Number); for i:= 1 to Number do begin Labels[i-1]:= string(PLabel[i]); Values[i-1]:= string(PText[i]); end; if InputQuery(SCaption, Labels, Values) then begin List:= TStringList.Create; try for i:= 0 to Number-1 do List.Add(Values[i]); Result:= StringsToPyList(List); finally FreeAndNil(List); end; end else Result:= ReturnNone; end; end; //this is not exported in API function api_dlg_charmap(Self, Args : PPyObject): PPyObject; cdecl; var str: string; begin with AppPython.Engine do if Bool(PyArg_ParseTuple(Args, ':dlg_charmap')) then begin str:= DoDialogCharmapModal; if str<>'' then Result:= PyUnicodeFromString(str) else Result:= ReturnNone; end else Result:= ReturnNone; end; function api_msg_status(Self, Args: PPyObject): PPyObject; cdecl; var PtrText: PChar; StrText: string; NFlag: integer; begin with AppPython.Engine do begin if Bool(PyArg_ParseTuple(Args, 'si:msg_status', @PtrText, @NFlag)) then begin StrText:= string(PtrText); fmMain.MsgStatus(StrText); if Bool(NFlag) then Application.ProcessMessages; //PluginManager calls loop with msg_status end; Result:= ReturnNone; end; end; function api_msg_status_alt(Self, Args: PPyObject): PPyObject; cdecl; var PtrText: PChar; StrText: string; NPause, NPos, NX, NY: integer; TooltipPos: TAppTooltipPos; bGotoBracket: boolean; begin with AppPython.Engine do begin if Bool(PyArg_ParseTuple(Args, 'siiii:msg_status_alt', @PtrText, @NPause, @NPos, @NX, @NY)) then begin StrText:= string(PtrText); bGotoBracket:= false; case NPos of HINTPOS_CARET: begin TooltipPos:= TAppTooltipPos.EditorCaret; end; HINTPOS_CARET_BRACKET: begin TooltipPos:= TAppTooltipPos.EditorCaret; bGotoBracket:= true; end; HINTPOS_TEXT: begin TooltipPos:= TAppTooltipPos.CustomTextPos; end; HINTPOS_TEXT_BRACKET: begin TooltipPos:= TAppTooltipPos.CustomTextPos; bGotoBracket:= true; end; HINTPOS_WINDOW_TOP: begin TooltipPos:= TAppTooltipPos.WindowTop; end; HINTPOS_WINDOW_BOTTOM: begin TooltipPos:= TAppTooltipPos.WindowBottom; end; else exit(ReturnNone); end; fmMain.DoTooltipShow(StrText, NPause, TooltipPos, bGotoBracket, NX, NY); Application.ProcessMessages; end; Result:= ReturnNone; end; end; function api_msg_box(Self, Args: PPyObject): PPyObject; cdecl; var Ptr: PChar; Str: string; Flags: integer; begin with AppPython.Engine do if Bool(PyArg_ParseTuple(Args, 'si:msg_box', @Ptr, @Flags)) then begin Str:= string(Ptr); Result:= PyLong_FromLong(MsgBox(Str, Flags)); end else Result:= ReturnNone; end; function PyHelper_ConvertButtonIcon_MB_to_ID(N: integer): integer; begin case N of MB_ICONWARNING: Result:= idDialogWarning; MB_ICONERROR: Result:= idDialogError; MB_ICONQUESTION: Result:= idDialogConfirm; else Result:= idDialogInfo; end; end; function api_msg_box_ex(Self, Args: PPyObject): PPyObject; cdecl; const cResultDelta = 100; var PtrCaption, PtrText, PtrButtons: PChar; StrCaption, StrText, StrButtons, StrBtn: string; NIcon, NFocused: Longint; Buttons: TDialogButtons; Res: Longint; Sep: TATStringSeparator; begin with AppPython.Engine do if Bool(PyArg_ParseTuple(Args, 'sssii:msg_box_ex', @PtrCaption, @PtrText, @PtrButtons, @NIcon, @NFocused)) then begin StrCaption:= string(PtrCaption); StrText:= string(PtrText); StrButtons:= string(PtrButtons); if StrButtons='' then exit(ReturnNone); Buttons:= TDialogButtons.Create(TDialogButton); Sep.Init(StrButtons, #1); repeat if not Sep.GetItemStr(StrBtn) then Break; with Buttons.Add do begin Caption:= StrBtn; ModalResult:= cResultDelta+Buttons.Count-1; end; until false; if (NFocused>=0) and (NFocused=0) and (Num<=cAppMaxGroup) then begin Pages:= TGroupsHelper.GetPagesOfGroupIndex(Num); if Pages=nil then Pages:= fmMain.GroupsMain.Pages[0]; end; Ok:= fmMain.DoFileOpen(StrFile, StrFile2, Pages, StrArgs)<>nil; if Ok then if (StrFile<>'') or (StrFile2<>'') then Application.ProcessMessages; //fixes https://github.com/kvichans/cuda_find_in_files4/issues/44 Result:= PyBool_FromLong(Ord(Ok)); end else Result:= ReturnNone; end; function api_ed_save(Self, Args: PPyObject): PPyObject; cdecl; var H: Int64; Ed: TATSynEdit; PtrName: PChar; StrName: string; bSaveAsCopy: LongBool; Frame: TEditorFrame; Ok: boolean; begin with AppPython.Engine do if Bool(PyArg_ParseTuple(Args, 'Lsi:save', @H, @PtrName, @bSaveAsCopy)) then begin Ed:= PyHelper_EditorFromHandle(H); StrName:= string(PtrName); if bSaveAsCopy then begin //save copy, don't use new filename if StrName='' then Ok:= false else try Ed.Strings.SaveToFile(StrName, true); Ok:= true; except on E: Exception do begin Ok:= false; MsgBox(E.Message, MB_OK or MB_ICONERROR); end; end; end else begin //save + use new filename Frame:= TGroupsHelper.GetEditorFrame(Ed); if Frame=nil then exit(ReturnNone); if StrName<>'' then begin Frame.SetFileName(Ed, StrName); Frame.DoLexerFromFilename(Ed, StrName); end; Ok:= Frame.DoFileSave_Ex(Ed, false); end; Result:= PyBool_FromLong(Ord(Ok)); end else Result:= ReturnNone; end; type TAppEditorLoadResult = ( Ok, FileNotFound, ReadError, SizeTooBig ); function api_ed_load(Self, Args: PPyObject): PPyObject; cdecl; var H: Int64; Ed: TATSynEdit; Frame: TEditorFrame; PtrFilename: PChar; StrFilename: string; NResultCode: TAppEditorLoadResult; NEditorIndex: integer; const cMaxFileSize = MaxLongint-1; begin with AppPython.Engine do if Bool(PyArg_ParseTuple(Args, 'Ls:load', @H, @PtrFilename)) then //if Bool(PyArg_ParseTuple(Args, 'Lss:load', @H, @PtrFilename, @PtrOptions)) then begin Ed:= PyHelper_EditorFromHandle(H); if Ed=nil then exit(ReturnNone); StrFilename:= string(PtrFilename); //StrOptions:= string(PtrOptions); if not FileExists(StrFilename) then NResultCode:= TAppEditorLoadResult.FileNotFound else if FileSize(StrFilename)>cMaxFileSize then NResultCode:= TAppEditorLoadResult.SizeTooBig else try Frame:= TGroupsHelper.GetEditorFrame(Ed); if Assigned(Frame) then begin NEditorIndex:= Frame.EditorObjToIndex(Ed); Frame.NotifEnabled:= false; Frame.SetFileName(Ed, ''); Ed.Modified:= false; Frame.UpdateModified(Ed, false); Frame.LexerName[Ed]:= ''; end; Ed.LoadFromFile(StrFilename, []); NResultCode:= TAppEditorLoadResult.Ok; if Assigned(Frame) then begin if NEditorIndex=0 then Frame.FileName:= StrFilename else Frame.FileName2:= StrFilename; Frame.UpdateCaptionFromFilename; Frame.NotifEnabled:= true; Frame.DoOnUpdateStatusbar(TAppStatusbarUpdateReason.FileOpen); end; except NResultCode:= TAppEditorLoadResult.ReadError; end; Result:= PyLong_FromLong(Ord(NResultCode)); end else Result:= ReturnNone; end; function api_ed_get_text_sel(Self, Args: PPyObject): PPyObject; cdecl; var H: Int64; begin with AppPython.Engine do if Bool(PyArg_ParseTuple(Args, 'L:get_text_sel', @H)) then Result:= PyUnicodeFromString(PyHelper_EditorFromHandle(H).TextSelected) else Result:= ReturnNone; end; function api_ed_get_text_line(Self, Args: PPyObject): PPyObject; cdecl; var H: Int64; Index, MaxLen: Integer; Ed: TATSynEdit; Strs: TATStrings; begin with AppPython.Engine do if Bool(PyArg_ParseTuple(Args, 'Lii:get_text_line', @H, @Index, @MaxLen)) then begin Ed:= PyHelper_EditorFromHandle(H); Strs:= Ed.Strings; if Strs.IsIndexValid(Index) then begin if (MaxLen=0) or (Strs.LinesLen[Index]<=MaxLen) then Result:= PyUnicodeFromString(Strs.Lines[Index]) else Result:= PyUnicodeFromString(''); end else Result:= ReturnNone; end else Result:= ReturnNone; end; function api_ed_get_line_len(Self, Args: PPyObject): PPyObject; cdecl; var H: Int64; Index: Integer; Ed: TATSynEdit; Strs: TATStrings; begin with AppPython.Engine do if Bool(PyArg_ParseTuple(Args, 'Li:get_line_len', @H, @Index)) then begin Ed:= PyHelper_EditorFromHandle(H); Strs:= Ed.Strings; if Strs.IsIndexValid(Index) then Result:= PyLong_FromLong(Strs.LinesLen[Index]) else Result:= ReturnNone; end else Result:= ReturnNone; end; function api_ed_get_line_end(Self, Args: PPyObject): PPyObject; cdecl; var H: Int64; Ed: TATSynEdit; Strs: TATStrings; Index: LongInt; begin with AppPython.Engine do if Bool(PyArg_ParseTuple(Args, 'Li:get_line_end', @H, @Index)) then begin Ed:= PyHelper_EditorFromHandle(H); Strs:= Ed.Strings; if Strs.IsIndexValid(Index) then Result:= PyLong_FromLong(Ord(Strs.LinesEnds[Index])) else Result:= ReturnNone; end else Result:= ReturnNone; end; function api_ed_set_line_end(Self, Args: PPyObject): PPyObject; cdecl; var H: Int64; Ed: TATSynEdit; Strs: TATStrings; NIndex, NValue: LongInt; begin with AppPython.Engine do if Bool(PyArg_ParseTuple(Args, 'Lii:set_line_end', @H, @NIndex, @NValue)) then begin Ed:= PyHelper_EditorFromHandle(H); Strs:= Ed.Strings; if Strs.IsIndexValid(NIndex) and (NValue>=0) and (NValue<=Ord(High(TATLineEnds))) then Strs.LinesEnds[NIndex]:= TATLineEnds(NValue); Result:= ReturnNone; end else Result:= ReturnNone; end; function api_ed_get_text_all(Self, Args: PPyObject): PPyObject; cdecl; var H: Int64; Ed: TATSynEdit; bEnds: LongBool; begin with AppPython.Engine do if Bool(PyArg_ParseTuple(Args, 'Li:get_text_all', @H, @bEnds)) then begin Ed:= PyHelper_EditorFromHandle(H); Result:= PyUnicodeFromString( Ed.Strings.TextString_Unicode(0, not bEnds) ); end else Result:= ReturnNone; end; function api_ed_get_text_substr(Self, Args: PPyObject): PPyObject; cdecl; var H: Int64; X1, Y1, X2, Y2: Integer; Str: atString; Ed: TATSynEdit; begin with AppPython.Engine do if Bool(PyArg_ParseTuple(Args, 'Liiii:get_text_substr', @H, @X1, @Y1, @X2, @Y2)) then begin Ed:= PyHelper_EditorFromHandle(H); Str:= Ed.Strings.TextSubstring(X1, Y1, X2, Y2); Result:= PyUnicodeFromString(Str); end else Result:= ReturnNone; end; function api_ed_set_caret(Self, Args: PPyObject): PPyObject; cdecl; var H: Int64; Id, NCaret, NOptions: Integer; X1, Y1, X2, Y2: Integer; Ed: TATSynEdit; begin with AppPython.Engine do if Bool(PyArg_ParseTuple(Args, 'Liiiiii:set_caret', @H, @X1, @Y1, @X2, @Y2, @Id, @NOptions)) then begin Ed:= PyHelper_EditorFromHandle(H); case Id of CARET_ADD: begin Ed.Carets.Add(X1, Y1, X2, Y2); if (NOptions and CARET_OPTION_NO_SORT)=0 then Ed.Carets.Sort; Result:= PyLong_FromLong(Ed.Carets.Count); end; CARET_DELETE_ALL: begin Ed.Carets.Clear; Result:= ReturnNone; end; CARET_SET_ONE: begin Ed.DoCaretSingle(X1, Y1, X2, Y2); if (NOptions and CARET_OPTION_NO_SCROLL)=0 then begin { //tried to fix issue in FindInFiles 4, but it don't help // https://github.com/kvichans/cuda_find_in_files4/issues/44 Ed.DoShowPos( Point(X1, Y1), UiOps.FindIndentHorz, UiOps.FindIndentVert, true, //AUnfold true, //AllowUpdate true //AllowProximity ); } Ed.DoGotoPos( Point(X1, Y1), Point(X2, Y2), UiOps.FindIndentHorz, UiOps.FindIndentVert, false, //APlaceCaret TATEditorActionIfFolded.Unfold //ADoUnfold ); end; Result:= ReturnNone; end; CARET_SET_INDEX..CARET_DELETE_INDEX-1: begin NCaret:= Id-CARET_SET_INDEX; if Ed.Carets.IsIndexValid(NCaret) then with Ed.Carets[NCaret] do begin PosX:= X1; PosY:= Y1; EndX:= X2; EndY:= Y2; if (NOptions and CARET_OPTION_NO_SORT)=0 then Ed.Carets.Sort; end; Result:= ReturnNone; end; CARET_DELETE_INDEX..MaxLongint: begin NCaret:= Id-CARET_DELETE_INDEX; if Ed.Carets.IsIndexValid(NCaret) then begin Ed.Carets.Delete(NCaret); if (NOptions and CARET_OPTION_NO_SORT)=0 then Ed.Carets.Sort; end; Result:= ReturnNone; end; CARET_SORT: begin Ed.Carets.Sort; Result:= ReturnNone; end else Result:= ReturnNone; end; //don't fire on_caret when no carets left, //plugin must add caret ASAP, and it will fire on_caret if Ed.Carets.Count>0 then if (NOptions and CARET_OPTION_NO_EVENT)=0 then Ed.DoEventCarets; end else Result:= ReturnNone; end; function api_ed_get_carets(Self, Args: PPyObject): PPyObject; cdecl; var H: Int64; Ed: TATSynEdit; Caret: TATCaretItem; NLen, i: Integer; begin with AppPython.Engine do if Bool(PyArg_ParseTuple(Args, 'L:get_carets', @H)) then begin Ed:= PyHelper_EditorFromHandle(H); if Ed=nil then begin MsgLogConsole('ERROR: API "ed" is Nil, report to author what are you doing please'); exit(PyList_New(0)); end; NLen:= Ed.Carets.Count; Result:= PyList_New(NLen); if not Assigned(Result) then raise EPythonError.Create(msgPythonListError); for i:= 0 to NLen-1 do begin Caret:= Ed.Carets[i]; PyList_SetItem(Result, i, Py_BuildValue('(iiii)', Caret.PosX, Caret.PosY, Caret.EndX, Caret.EndY)); end; end else Result:= ReturnNone; end; function api_ed_markers(Self, Args: PPyObject): PPyObject; cdecl; var H: Int64; Id: Integer; Ed: TATSynEdit; Mark: PATMarkerItem; X, Y, NTag, NLenX, NLenY, NLineLen, NMarkCount, i: integer; begin with AppPython.Engine do if Bool(PyArg_ParseTuple(Args, 'Liiiiiii:markers', @H, @Id, @X, @Y, @NTag, @NLenX, @NLenY, @NLineLen)) then begin Ed:= PyHelper_EditorFromHandle(H); case Id of MARKERS_GET_DICT: begin NMarkCount:= Ed.Markers.Count; Result:= PyList_New(NMarkCount); if not Assigned(Result) then raise EPythonError.Create(msgPythonListError); for i:= 0 to NMarkCount-1 do begin Mark:= Ed.Markers.ItemPtr(i); PyList_SetItem(Result, i, Py_BuildValue('{sisisisisisisi}', PChar(string('x')), Mark^.PosX, PChar(string('y')), Mark^.PosY, 'len_x', Mark^.SelX, 'len_y', Mark^.SelY, 'tag', Longint(Mark^.Tag), 'line_len', Longint(Mark^.LineLen), 'micromap', Ord(Mark^.MicromapMode) )); end; end; MARKERS_ADD: begin if (NLenX<0) or (NLenY<0) then exit(ReturnNone); Ed.Markers.Add( Point(X, Y), Point(NLenX, NLenY), TATMarkerTags.Init(NTag, 0), nil, TATMarkerMicromapMode.TextOnly, NLineLen ); Ed.Update; Result:= PyLong_FromLong(Ed.Markers.Count); end; MARKERS_DELETE_ALL: begin if Ed.Markers.Count>0 then begin Ed.Markers.Clear; Ed.Update; end; Result:= ReturnNone; end; MARKERS_DELETE_LAST: begin if Ed.Markers.Count>0 then begin Ed.Markers.Delete(Ed.Markers.Count-1); Ed.Update; end; Result:= ReturnNone; end; MARKERS_DELETE_BY_TAG: begin if Ed.Markers.Count>0 then begin if Ed.Markers.DeleteWithTag(NTag) then Ed.Update; end; Result:= ReturnNone; end; MARKERS_DELETE_BY_INDEX: begin if Ed.Markers.IsIndexValid(NTag) then begin Ed.Markers.Delete(NTag); Ed.Update; end; Result:= ReturnNone; end; MARKERS_DELETE_BY_POS: begin if Ed.Markers.DeleteByPos(X, Y) then Ed.Update; Result:= ReturnNone; end; MARKERS_SET_DUPS: begin Ed.Markers.Duplicates:= Bool(NTag); Result:= ReturnNone; end; MARKERS_GET_DUPS: begin Result:= PyBool_FromLong(Ord(Ed.Markers.Duplicates)); end; else Result:= ReturnNone; end; end else Result:= ReturnNone; end; function api_ed_attr(Self, Args: PPyObject): PPyObject; cdecl; var H: Int64; Ed: TATSynEdit; Mark: TATMarkerItem; LinePart: TATLinePart; PtrX, PtrY, PtrLen: PChar; PtrColorFont, PtrColorBg, PtrColorBorder, PtrFontBold, PtrFontItalic, PtrFontStrike: PChar; StrX, StrY, StrLen: string; StrColorFont, StrColorBg, StrColorBorder, StrFontBold, StrFontItalic, StrFontStrike: string; Id, X, Y, NTag, NLen, i: integer; NColorFont, NColorBg, NColorBorder: integer; NColorFont_1st, NColorBg_1st, NColorBorder_1st: integer; NBorderL, NBorderR, NBorderD, NBorderU: integer; NFontBold, NFontItalic, NFontStrike: integer; NFontBold_1st, NFontItalic_1st, NFontStrike_1st: integer; NColumn, NMicromapMode: integer; SepX, SepY, SepLen: TATStringSeparator; SepColorFont, SepColorBg, SepColorBorder, SepFontBold, SepFontItalic, SepFontStrike: TATStringSeparator; NStyles: byte; begin with AppPython.Engine do if Bool(PyArg_ParseTuple(Args, 'Liisssssssssiiiiii:attr', @H, @Id, @NTag, @PtrX, @PtrY, @PtrLen, @PtrColorFont, @PtrColorBg, @PtrColorBorder, @PtrFontBold, @PtrFontItalic, @PtrFontStrike, @NBorderL, @NBorderR, @NBorderD, @NBorderU, @NColumn, @NMicromapMode )) then begin Ed:= PyHelper_EditorFromHandle(H); { type for 'x', 'y', 'len' is string, to support this API: * MARKERS_ADD_MANY: Adds one or multiple fragments at once. ** "x", "y", "len": The same as for MARKERS_ADD, but can be also list/tuple of int. } StrX:= string(PtrX); StrY:= string(PtrY); StrLen:= string(PtrLen); StrColorFont:= string(PtrColorFont); StrColorBg:= string(PtrColorBg); StrColorBorder:= string(PtrColorBorder); StrFontBold:= string(PtrFontBold); StrFontItalic:= string(PtrFontItalic); StrFontStrike:= string(PtrFontStrike); case Id of MARKERS_GET_DICT: begin NLen:= Ed.Attribs.Count; Result:= PyList_New(NLen); if not Assigned(Result) then raise EPythonError.Create(msgPythonListError); for i:= 0 to NLen-1 do begin Mark:= Ed.Attribs[i]; PyList_SetItem(Result, i, Py_BuildValue('{sisisisisisisisOsOsOsisisisisisi}', 'tag', Mark.Tag, PChar(string('x')), Mark.PosX, PChar(string('y')), Mark.PosY, 'len', Mark.SelX, 'color_font', Mark.LinePart.ColorFont, 'color_bg', Mark.LinePart.ColorBG, 'color_border', Mark.LinePart.ColorBorder, 'font_bold', PyBool_FromLong(Ord((Mark.LinePart.FontStyles and afsFontBold)<>0)), 'font_italic', PyBool_FromLong(Ord((Mark.LinePart.FontStyles and afsFontItalic)<>0)), 'font_strikeout', PyBool_FromLong(Ord((Mark.LinePart.FontStyles and afsFontCrossed)<>0)), 'border_left', Ord(Mark.LinePart.BorderLeft), 'border_right', Ord(Mark.LinePart.BorderRight), 'border_down', Ord(Mark.LinePart.BorderDown), 'border_up', Ord(Mark.LinePart.BorderUp), 'show_on_map', Longint(Mark.TagEx), 'map_only', Ord(Mark.MicromapMode) )); end; end; MARKERS_ADD: begin NColorFont:= StrToIntDef(StrColorFont, clNone); NColorBg:= StrToIntDef(StrColorBg, clNone); NColorBorder:= StrToIntDef(StrColorBorder, clNone); NFontBold:= StrToIntDef(StrFontBold, 0); NFontItalic:= StrToIntDef(StrFontItalic, 0); NFontStrike:= StrToIntDef(StrFontStrike, 0); InitLinePart(LinePart); LinePart.ColorFont:= NColorFont; LinePart.ColorBG:= NColorBg; if NColorBorder<>clNone then LinePart.ColorBorder:= NColorBorder else LinePart.ColorBorder:= Ed.Colors.TextFont; NStyles:= 0; if Bool(NFontBold) then NStyles:= NStyles or afsFontBold; if Bool(NFontItalic) then NStyles:= NStyles or afsFontItalic; if Bool(NFontStrike) then NStyles:= NStyles or afsFontCrossed; LinePart.FontStyles:= NStyles; LinePart.BorderLeft:= TATLineStyle(NBorderL); LinePart.BorderRight:= TATLineStyle(NBorderR); LinePart.BorderDown:= TATLineStyle(NBorderD); LinePart.BorderUp:= TATLineStyle(NBorderU); X:= StrToIntDef(StrX, MaxInt); Y:= StrToIntDef(StrY, MaxInt); NLen:= StrToIntDef(StrLen, 1); if (XclNone then LinePart.ColorBorder:= NColorBorder else LinePart.ColorBorder:= Ed.Colors.TextFont; NStyles:= 0; if Bool(NFontBold) then NStyles:= NStyles or afsFontBold; if Bool(NFontItalic) then NStyles:= NStyles or afsFontItalic; if Bool(NFontStrike) then NStyles:= NStyles or afsFontCrossed; LinePart.FontStyles:= NStyles; LinePart.BorderLeft:= TATLineStyle(NBorderL); LinePart.BorderRight:= TATLineStyle(NBorderR); LinePart.BorderDown:= TATLineStyle(NBorderD); LinePart.BorderUp:= TATLineStyle(NBorderU); Ed.Attribs.Add( Point(X, Y), Point(NLen, 0), TATMarkerTags.Init(NTag, NColumn), @LinePart, TATMarkerMicromapMode(NMicromapMode) ); until false; Ed.Update; Result:= PyLong_FromLong(Ed.Attribs.Count); end; MARKERS_DELETE_ALL: begin //Ed.InvalidateHilitingCache; if Ed.Attribs.Count>0 then begin Ed.Attribs.Clear; Ed.Update; end; Result:= ReturnNone; end; MARKERS_DELETE_LAST: begin //Ed.InvalidateHilitingCache; if Ed.Attribs.Count>0 then begin Ed.Attribs.Delete(Ed.Attribs.Count-1); Ed.Update; end; Result:= ReturnNone; end; MARKERS_DELETE_BY_TAG: begin //Ed.InvalidateHilitingCache; if Ed.Attribs.Count>0 then begin if Ed.Attribs.DeleteWithTag(NTag) then Ed.Update; end; Result:= ReturnNone; end; MARKERS_DELETE_BY_INDEX: begin if Ed.Attribs.IsIndexValid(NTag) then begin Ed.Attribs.Delete(NTag); Ed.Update; end; Result:= ReturnNone; end; MARKERS_DELETE_BY_POS: begin if Ed.Attribs.Count>0 then begin X:= StrToIntDef(StrX, MaxInt); Y:= StrToIntDef(StrY, MaxInt); if (X0 then Ed.Hotspots.Delete(Ed.Hotspots.Count-1); Result:= ReturnNone; end; HOTSPOT_DELETE_BY_TAG: begin Ed.Hotspots.DeleteByTag(NTag); Result:= ReturnNone; end; HOTSPOT_ADD: begin Sep.Init(StrPos); Sep.GetItemInt(FItem.PosX, -1); Sep.GetItemInt(FItem.PosY, -1); Sep.GetItemInt(FItem.EndX, -1); Sep.GetItemInt(FItem.EndY, -1); if (FItem.PosX<0) or (FItem.PosY<0) or (FItem.EndX<0) or (FItem.EndY<0) then exit(ReturnFalse); FItem.Tag:= NTag; FItem.TagString:= StrTag; Ed.Hotspots.Add(FItem); Result:= ReturnTrue; end; HOTSPOT_GET_LIST: begin NLen:= Ed.Hotspots.Count; Result:= PyList_New(NLen); if not Assigned(Result) then raise EPythonError.Create(msgPythonListError); for i:= 0 to NLen-1 do begin FItem:= Ed.Hotspots[i]; PyList_SetItem(Result, i, Py_BuildValue('{s(iiii)siss}', 'pos', FItem.PosX, FItem.PosY, FItem.EndX, FItem.EndY, 'tag', FItem.Tag, 'tag_str', PChar(FItem.TagString) )); end; end; else Result:= ReturnNone; end; end else Result:= ReturnNone; end; function api_ed_get_sel_mode(Self, Args: PPyObject): PPyObject; cdecl; var H: Int64; Ed: TATSynEdit; cSelModes: array[boolean] of integer = (SEL_NORMAL, SEL_COLUMN); begin with AppPython.Engine do if Bool(PyArg_ParseTuple(Args, 'L:get_sel_mode', @H)) then begin Ed:= PyHelper_EditorFromHandle(H); Result:= PyLong_FromLong(cSelModes[Ed.IsSelColumn]); end else Result:= ReturnNone; end; function api_ed_get_sel_rect(Self, Args: PPyObject): PPyObject; cdecl; var H: Int64; R: TRect; begin with AppPython.Engine do if Bool(PyArg_ParseTuple(Args, 'L:get_sel_rect', @H)) then begin R:= PyHelper_EditorFromHandle(H).SelRect; Result:= Py_BuildValue('(iiii)', R.Left, R.Top, R.Right, R.Bottom); end else Result:= ReturnNone; end; function api_ed_get_sel_lines(Self, Args: PPyObject): PPyObject; cdecl; var H: Int64; N1, N2: Integer; Ed: TATSynEdit; begin with AppPython.Engine do if Bool(PyArg_ParseTuple(Args, 'L:get_sel_lines', @H)) then begin Ed:= PyHelper_EditorFromHandle(H); if Ed.Carets.Count=0 then begin N1:= -1; N2:= -1; end else Ed.Carets[0].GetSelLines(N1, N2, false); Result:= Py_BuildValue('(ii)', N1, N2); end else Result:= ReturnNone; end; function api_ed_set_sel_rect(Self, Args: PPyObject): PPyObject; cdecl; var H: Int64; X1, Y1, X2, Y2: Integer; Ed: TATSynEdit; begin with AppPython.Engine do if Bool(PyArg_ParseTuple(Args, 'Liiii:set_sel_rect', @H, @X1, @Y1, @X2, @Y2)) then begin Ed:= PyHelper_EditorFromHandle(H); Ed.DoSelect_None; Ed.DoSelect_ColumnBlock_FromPoints(Point(X1, Y1), Point(X2, Y2)); Ed.DoEventCarets; Ed.Update; Result:= ReturnNone; end else Result:= ReturnNone; end; function api_ed_set_text_all(Self, Args: PPyObject): PPyObject; cdecl; var H: Int64; Ed: TATSynEdit; PtrText: PChar; begin with AppPython.Engine do if Bool(PyArg_ParseTuple(Args, 'Ls:set_text_all', @H, @PtrText)) then begin Ed:= PyHelper_EditorFromHandle(H); if not Ed.ModeReadOnly then EditorSetAllTextFromAPI(Ed, string(PtrText)); Result:= ReturnNone; end else Result:= ReturnNone; end; function api_ed_set_text_line(Self, Args: PPyObject): PPyObject; cdecl; var H: Int64; Ed: TATSynEdit; NIndex: Integer; Ptr: PChar; Str: atString; begin with AppPython.Engine do if Bool(PyArg_ParseTuple(Args, 'Lis:set_text_line', @H, @NIndex, @Ptr)) then begin Ed:= PyHelper_EditorFromHandle(H); Str:= UTF8Decode(string(Ptr)); if SStringHasEol(Str) then Exit(ReturnFalse); if not Ed.ModeReadOnly then EditorSetLineFromAPI(Ed, NIndex, Str); Result:= ReturnNone; end else Result:= ReturnNone; end; function api_ed_delete(Self, Args: PPyObject): PPyObject; cdecl; var H: Int64; Ed: TATSynEdit; X1, Y1, X2, Y2: Integer; begin with AppPython.Engine do if Bool(PyArg_ParseTuple(Args, 'Liiii:delete', @H, @X1, @Y1, @X2, @Y2)) then begin Ed:= PyHelper_EditorFromHandle(H); if not Ed.ModeReadOnly then EditorDeleteRangeFromAPI(Ed, X1, Y1, X2, Y2); Result:= ReturnNone; end else Result:= ReturnNone; end; function api_ed_insert(Self, Args: PPyObject): PPyObject; cdecl; var H: Int64; Ed: TATSynEdit; Ptr: PChar; Str: atString; X1, Y1: Integer; PosAfter: TPoint; begin with AppPython.Engine do if Bool(PyArg_ParseTuple(Args, 'Liis:insert', @H, @X1, @Y1, @Ptr)) then begin Ed:= PyHelper_EditorFromHandle(H); if Ed.ModeReadOnly then exit(ReturnNone); Str:= UTF8Decode(string(Ptr)); if EditorInsertFromAPI(Ed, X1, Y1, Str, PosAfter) then Result:= Py_BuildValue('(ii)', PosAfter.X, PosAfter.Y) else Result:= ReturnNone; end else Result:= ReturnNone; end; function api_ed_replace(Self, Args: PPyObject): PPyObject; cdecl; var H: Int64; X1, Y1, X2, Y2: Integer; Ed: TATSynEdit; Shift, PosAfter: TPoint; PtrText: PChar; StrText: string; Strs: TATStrings; bAllText: boolean; begin with AppPython.Engine do if Bool(PyArg_ParseTuple(Args, 'Liiiis:replace', @H, @X1, @Y1, @X2, @Y2, @PtrText)) then begin Ed:= PyHelper_EditorFromHandle(H); StrText:= string(PtrText); if Ed.ModeReadOnly then exit(ReturnNone); Strs:= Ed.Strings; Strs.SetNewCommandMark; bAllText:= (X1=0) and (Y1=0) and (X2=0) and (Y2>=Strs.Count); Strs.TextReplaceRange(X1, Y1, X2, Y2, UTF8Decode(StrText), Shift, PosAfter, true); Ed.UpdateMarkersOnDeleting(X1, Y1, X2, Y2); Ed.UpdateCaretsAndMarkersOnEditing(0, Point(X1, Y1), Point(X2, Y2), Shift, PosAfter); //must update the saved 'carets after last edition' (like EditorSetLineFromAPI //does), it's used by Undo/Redo to restore caret pos; without it, the value //stays from some older API call (e.g. set_text_all gives (0,0)) and Redo //jumps the caret to that stale position Strs.ActionSaveLastEditionPos(X1, Y1); //reset ScrollHorz.Max, it's needed because CudaFormatter can replace long one-liner to short lines if bAllText then EditorResetHorizontalScrollbarMax(Ed); Ed.DoEventChange(Y1); Ed.UpdateWrapInfo(true); //fixing #4173 Ed.Update(true); Result:= Py_BuildValue('(ii)', PosAfter.X, PosAfter.Y); end else Result:= ReturnNone; end; function api_ed_replace_lines(Self, Args: PPyObject): PPyObject; cdecl; var H: Int64; Y1, Y2: Integer; Ed: TATSynEdit; Strs: TATStrings; Lines: TStringList; ListPy: PPyObject; NCount: integer; Res: boolean; begin with AppPython.Engine do if Bool(PyArg_ParseTuple(Args, 'LiiO:replace_lines', @H, @Y1, @Y2, @ListPy)) then begin Ed:= PyHelper_EditorFromHandle(H); if Ed.ModeReadOnly then exit(ReturnNone); Strs:= Ed.Strings; Strs.SetNewCommandMark; NCount:= 0; Lines:= TStringList.Create; try PyListToStrings(ListPy, Lines); Res:= Strs.TextReplaceLines_UTF8(Y1, Y2, Lines); NCount:= Lines.Count; finally FreeAndNil(Lines); end; if Res then begin Ed.UpdateMarkersOnDeleting(0, Y1, 0, Y2+1); Ed.UpdateCaretsAndMarkersOnEditing(0, Point(0, Y1), Point(0, Y2+1), Point(0, NCount-(Y2-Y1+1)), Point(0, Y1+NCount)); //must update the saved 'carets after last edition' (like EditorSetLineFromAPI //does), it's used by Undo/Redo to restore caret pos; without it, the value //stays from some older API call (e.g. set_text_all gives (0,0)) and Redo //jumps the caret to that stale position Strs.ActionSaveLastEditionPos(0, Y1); Ed.DoEventChange(Y1); //2026.09.12 (perf): update word-wrap info at API time, like api_ed_replace //does ("fixing #4173"), instead of deferring it to the first paint: //Update(true) only sets FWrapUpdateNeeded, so the whole wrap recalculation //was blocking the first idle-paint after a big replace_lines (1M lines: //~8s hang). Same total work, different placement: the API call returns //with WrapInfo already consistent, and the first paint early-exits. //UpdateWrapInfo(true,true): force it now, allow cached/incremental path //(block ops recorded by LineBlockDelete/LineBlockInsert are applied as //index shifts + wrap calc for the new lines only). Update(false): wrap //flag is already consumed, only the repaint is needed. Ed.UpdateWrapInfo(true, true); Ed.Update(false); end; Result:= PyBool_FromLong(Ord(Res)); end; end; function api_ed_get_line_count(Self, Args: PPyObject): PPyObject; cdecl; var H: Int64; Ed: TATSynEdit; begin with AppPython.Engine do if Bool(PyArg_ParseTuple(Args, 'L:get_line_count', @H)) then begin Ed:= PyHelper_EditorFromHandle(H); Result:= PyLong_FromLong(Ed.Strings.Count); end else Result:= ReturnNone; end; function api_ed_get_filename(Self, Args: PPyObject): PPyObject; cdecl; var H: Int64; Ed: TATSynEdit; PtrOps: PChar; StrOps: string; F: TEditorFrame; Str: string; begin with AppPython.Engine do if Bool(PyArg_ParseTuple(Args, 'Ls:get_filename', @H, @PtrOps)) then begin Ed:= PyHelper_EditorFromHandle(H); F:= TGroupsHelper.GetEditorFrame(Ed); StrOps:= string(PtrOps); if F=nil then Str:= '' else if (F.FrameKind=TAppFrameKind.Editor) or (Pos('*', StrOps)>0) then Str:= F.GetFileName(Ed) else Str:= '?'; Result:= PyUnicodeFromString(Str); end else Result:= ReturnNone; end; function api_ed_cmd(Self, Args: PPyObject): PPyObject; cdecl; var H: Int64; Ed: TATSynEdit; NCode: integer; Ptr: PChar; Str: string; begin with AppPython.Engine do if Bool(PyArg_ParseTuple(Args, 'Lis:cmd', @H, @NCode, @Ptr)) then begin Ed:= PyHelper_EditorFromHandle(H); Str:= string(Ptr); Ed.DoCommand(NCode, TATCommandInvoke.AppAPI, UTF8Decode(Str)); //many commands use timer, so immediate quit is not ok, app didn't finish command yet. //example of bug: plugin Differ uses ed.cmd(cmd_FileClose) and immediately after that it calls //file_open for file-pair with the same file, it failed if IsCommandNeedTimer(NCode) then begin Sleep(UiOps.PyCommandSleepInterval); Application.ProcessMessages; end; Result:= ReturnNone; end else Result:= ReturnNone; end; function api_ed_focus(Self, Args: PPyObject): PPyObject; cdecl; var H: Int64; Ed: TATSynEdit; begin with AppPython.Engine do if Bool(PyArg_ParseTuple(Args, 'L:focus', @H)) then begin Ed:= PyHelper_EditorFromHandle(H); PyHelper_EditorFocus(Ed); Result:= ReturnNone; end else Result:= ReturnNone; end; function PyHelper_BookmarkGetItem(BmItem: PATBookmarkItem): PPyObject; begin with AppPython.Engine do Result:= Py_BuildValue('{sisisisssisO}', 'line', BmItem^.Data.LineNum, 'tag', BmItem^.Data.Tag, 'kind', Integer(BmItem^.Data.Kind), 'hint', PChar(string(BmItem^.Data.Hint)), 'auto_delx', Ord(BmItem^.Data.AutoDelete), 'show_in_list', PyBool_FromLong(Ord(BmItem^.Data.ShowInBookmarkList)) ); end; function PyHelper_BookmarkGetAll(ABookmarks: TATBookmarks): PPyObject; var NCount, i: integer; BmItem: PATBookmarkItem; begin with AppPython.Engine do begin NCount:= ABookmarks.Count; Result:= PyList_New(NCount); if not Assigned(Result) then raise EPythonError.Create(msgPythonListError); for i:= 0 to NCount-1 do begin BmItem:= ABookmarks[i]; PyList_SetItem(Result, i, PyHelper_BookmarkGetItem(BmItem)); end; end; end; function api_ed_bookmark(Self, Args: PPyObject): PPyObject; cdecl; var H: Int64; PtrText: PChar; StrText: string; Ed: TATSynEdit; NId, NLine, NKind, NColor, NAutoDelete, NShowInList: integer; NTag: integer; AutoDel: TATBookmarkAutoDelete; begin with AppPython.Engine do if Bool(PyArg_ParseTuple(Args, 'Liiiisiii:bookmark', @H, @NId, @NLine, @NKind, @NColor, @PtrText, @NAutoDelete, @NShowInList, @NTag)) then begin Ed:= PyHelper_EditorFromHandle(H); StrText:= string(PtrText); //check range of NKind if NKindHigh(AppBookmarkSetup) then NKind:= High(AppBookmarkSetup); if Bool(NAutoDelete) then AutoDel:= TATBookmarkAutoDelete.Delete else AutoDel:= TATBookmarkAutoDelete.ByOption; case NId of BOOKMARK_APPEND: begin Ed.BookmarkAppendEx(NLine, NKind, StrText, AutoDel, Bool(NShowInList), NTag, Ed.Strings.Bookmarks ); Result:= ReturnNone; end; BOOKMARK2_APPEND: begin Ed.BookmarkAppendEx(NLine, NKind, StrText, AutoDel, Bool(NShowInList), NTag, Ed.Strings.Bookmarks2 ); Result:= ReturnNone; end; BOOKMARK_SET: begin Ed.BookmarkSetForLine(NLine, NKind, StrText, AutoDel, Bool(NShowInList), NTag ); Result:= ReturnNone; end; BOOKMARK2_SET: begin Ed.BookmarkSetForLine_2(NLine, NKind, StrText, AutoDel, Bool(NShowInList), NTag ); Result:= ReturnNone; end; BOOKMARK_CLEAR: begin Ed.BookmarkDeleteForLine(NLine); Result:= ReturnNone; end; BOOKMARK2_CLEAR: begin Ed.BookmarkDeleteForLine_2(NLine); Result:= ReturnNone; end; BOOKMARK_CLEAR_ALL: begin Ed.BookmarkDeleteAll; Result:= ReturnNone; end; BOOKMARK2_CLEAR_ALL: begin Ed.BookmarkDeleteAll_2; Result:= ReturnNone; end; BOOKMARK_SETUP: begin AppBookmarkSetup[NKind].ImageIndex:= UpdateImagelistWithIconFromFile(AppBookmarkImagelist, StrText, 'Editor.bookmark(...BOOKMARK_SETUP...)'); AppBookmarkSetup[NKind].Color:= NColor; Result:= ReturnNone; end; BOOKMARK_GET_ALL: begin Result:= PyHelper_BookmarkGetAll(Ed.Strings.Bookmarks); end; BOOKMARK2_GET_ALL: begin Result:= PyHelper_BookmarkGetAll(Ed.Strings.Bookmarks2); end; BOOKMARK_DELETE_BY_TAG: begin Result:= PyBool_FromLong(Ord(Ed.BookmarkDeleteByTag(NTag))); end; BOOKMARK2_DELETE_BY_TAG: begin Result:= PyBool_FromLong(Ord(Ed.BookmarkDeleteByTag_2(NTag))); end; else Result:= ReturnNone; end; end else Result:= ReturnNone; end; function PyHelper_DecorGetItem(Item: PATGutterDecorItem): PPyObject; begin with AppPython.Engine do Result:= Py_BuildValue('{sisisssOsOsisisO}', 'line', Item^.Data.LineNum, 'tag', Item^.Data.Tag, 'text', PChar(string(Item^.Data.TextAll)), 'bold', PyBool_FromLong(Ord(Item^.Data.TextBold)), 'italic', PyBool_FromLong(Ord(Item^.Data.TextItalic)), 'color', Item^.Data.TextColor, 'image', Item^.Data.ImageIndex, 'auto_del', PyBool_FromLong(Ord(Item^.Data.DeleteOnDelLine)) ); end; function api_ed_decor(Self, Args: PPyObject): PPyObject; cdecl; var H: Int64; Ed: TATSynEdit; PtrText, PtrStyle: PChar; StrStyle: string; NId, NLine, NImageIndex, NColor, NAutoDelete: integer; NTag: integer; Data: TATGutterDecorData; ItemPtr: PATGutterDecorItem; NCount, i: integer; begin with AppPython.Engine do if Bool(PyArg_ParseTuple(Args, 'Liiisisii:decor', @H, @NId, @NLine, @NTag, @PtrText, @NColor, @PtrStyle, @NImageIndex, @NAutoDelete)) then begin Ed:= PyHelper_EditorFromHandle(H); case NId of DECOR_GET_ALL: begin if NLine<0 then begin //return all items NCount:= Ed.GutterDecor.Count; Result:= PyList_New(NCount); if not Assigned(Result) then raise EPythonError.Create(msgPythonListError); for i:= 0 to NCount-1 do PyList_SetItem(Result, i, PyHelper_DecorGetItem(Ed.GutterDecor.ItemPtr(i)) ); end else begin //return items for given line index Result:= PyList_New(0); if not Assigned(Result) then raise EPythonError.Create(msgPythonListError); for i:= 0 to Ed.GutterDecor.Count-1 do begin ItemPtr:= Ed.GutterDecor.ItemPtr(i); if ItemPtr^.Data.LineNum=NLine then PyList_Append(Result, PyHelper_DecorGetItem(ItemPtr)); end; end; end; DECOR_SET: begin if not Ed.Strings.IsIndexValid(NLine) then exit(ReturnFalse); StrStyle:= string(PtrStyle); Data:= Default(TATGutterDecorData); Data.LineNum:= NLine; Data.Tag:= NTag; Data.DeleteOnDelLine:= Bool(NAutoDelete); Data.ImageIndex:= NImageIndex; Data.TextAll:= string(PtrText); Data.TextBold:= Pos('b', StrStyle)>0; Data.TextItalic:= Pos('i', StrStyle)>0; data.TextColor:= NColor; Ed.GutterDecor.Add(Data); Ed.Update; Result:= ReturnTrue; end; DECOR_DELETE_ALL: begin if Ed.GutterDecor.Count>0 then begin Ed.GutterDecor.Clear; Ed.Update; end; Result:= ReturnNone; end; DECOR_DELETE_BY_LINE: begin i:= Ed.GutterDecor.Find(NLine); if i>=0 then begin Ed.GutterDecor.Delete(i); Ed.Update; end; Result:= ReturnNone; end; DECOR_DELETE_BY_TAG: begin if Ed.GutterDecor.DeleteByTag(NTag) then Ed.Update; Result:= ReturnNone; end; DECOR_GET_IMAGELIST: begin if Ed.ImagesGutterDecor=nil then Ed.ImagesGutterDecor:= TImageList.Create(Ed); Result:= PyHelper_ObjectHandle(Ed.ImagesGutterDecor); end; else Result:= ReturnNone; end; end else Result:= ReturnNone; end; function api_ed_handles(Self, Args : PPyObject): PPyObject; cdecl; var nMin, nMax: integer; begin nMin:= cPyEditorHandleMin; nMax:= Min(cPyEditorHandleMin + fmMain.FrameCount - 1, cPyEditorHandleMax); with AppPython.Engine do Result:= Py_BuildValue('(ii)', nMin, nMax); end; function api_ed_group(Self, Args: PPyObject): PPyObject; cdecl; var Index: Longint; Ed: TATSynEdit; begin with AppPython.Engine do if Bool(PyArg_ParseTuple(Args, 'i:ed_group', @Index)) then begin Ed:= TGroupsHelper.GetEditorActiveInGroup(Index); if Ed=nil then Result:= ReturnNone else Result:= PyHelper_ObjectHandle(Ed); end else Result:= ReturnNone; end; function api_dlg_file(Self, Args: PPyObject): PPyObject; cdecl; var PtrFilename, PtrFolder, PtrFilter, PtrCaption: PChar; StrFilename, StrFolder, StrFilter, StrCaption: string; IsOpen: LongBool; IsAllowAny: boolean; Dlg: TOpenDialog; begin with AppPython.Engine do if Bool(PyArg_ParseTuple(Args, 'issss:dlg_file', @IsOpen, @PtrFilename, @PtrFolder, @PtrFilter, @PtrCaption)) then begin StrFilename:= string(PtrFilename); StrFolder:= string(PtrFolder); StrFilter:= string(PtrFilter); StrCaption:= string(PtrCaption); IsAllowAny:= SBeginsWith(StrFilename, '!'); if IsAllowAny then Delete(StrFilename, 1, 1); if IsOpen then begin Dlg:= TOpenDialog.Create(nil); Dlg.Title:= msgDialogTitleOpen; Dlg.Options:= Dlg.Options+[ofHideReadOnly, ofPathMustExist]; if not IsAllowAny then Dlg.Options:= Dlg.Options+[ofFileMustExist]; end else begin Dlg:= TSaveDialog.Create(nil); Dlg.Title:= msgDialogTitleSaveAs; Dlg.Options:= Dlg.Options+[ofHideReadOnly, ofPathMustExist, ofOverwritePrompt]; end; try if StrFilename='*' then begin StrFilename:= ''; Dlg.Options:= Dlg.Options+[ofAllowMultiSelect]; end; if StrCaption<>'' then Dlg.Title:= StrCaption; Dlg.FileName:= StrFilename; Dlg.InitialDir:= StrFolder; Dlg.Filter:= StrFilter; if Dlg.Execute then begin if (ofAllowMultiSelect in Dlg.Options) and (Dlg.Files.Count>1) then Result:= StringsToPyList(Dlg.Files) else Result:= PyUnicodeFromString(Dlg.FileName); end else Result:= ReturnNone; finally FreeAndNil(Dlg); end; end; end; function api_dlg_dir(Self, Args: PPyObject): PPyObject; cdecl; var PtrFolder, PtrCaption: PChar; StrFolder, StrCaption: string; Dlg: TSelectDirectoryDialog; begin with AppPython.Engine do if Bool(PyArg_ParseTuple(Args, 'ss:dlg_dir', @PtrFolder, @PtrCaption)) then begin StrFolder:= string(PtrFolder); StrCaption:= string(PtrCaption); Dlg:= TSelectDirectoryDialog.Create(nil); try if StrCaption<>'' then Dlg.Title:= StrCaption else begin with TIniFile.Create(AppFile_Language) do try Dlg.Title:= ReadString('ui', 'dl_fld', 'Select folder'); finally Free; end; end; Dlg.InitialDir:= StrFolder; if Dlg.Execute then Result:= PyUnicodeFromString(Dlg.FileName) else Result:= ReturnNone; finally FreeAndNil(Dlg); end; end; end; procedure TfmMain.TimerConsoleCompletionTick(Sender: TObject); begin TimerConsoleCmp.Enabled:= false; DoPyEvent(nil, TAppPyEvent.OnConsoleComplete, []); end; procedure TfmMain.PyCompletionOnGetProp(Sender: TObject; AContent: TStringList; out ACharsLeft, ACharsRight: integer); var Ed: TATSynEdit; Caret: TATCaretItem; PrevCharsLeft: integer; begin AContent.Clear; ACharsLeft:= 0; ACharsRight:= 0; Ed:= FPyCompletionProps.Editor; //can be not CurrentEditor if Ed=nil then exit; if Ed.Carets.Count=0 then exit; Caret:= Ed.Carets[0]; //if caret moved by 1 char: repeat auto-complete if (Caret.PosX<>FPyCompletionProps.CaretPos.X) and (Caret.PosY=FPyCompletionProps.CaretPos.Y) then begin PrevCharsLeft:= FPyCompletionProps.CharsLeft; AppAutocompleteInvoke:= TAppAutocompleteInvoke.ShowAgain; if Assigned(fmConsole) and (Ed=fmConsole.EdInput) then begin if TimerConsoleCmp=nil then begin TimerConsoleCmp:= TTimer.Create(Self); TimerConsoleCmp.Enabled:= false; TimerConsoleCmp.Interval:= CompletionOps.ClosingTimerInverval+50; TimerConsoleCmp.OnTimer:= @TimerConsoleCompletionTick; end; TimerConsoleCmp.Enabled:= false; TimerConsoleCmp.Enabled:= true; exit; end else DoPyEvent(Ed, TAppPyEvent.OnComplete, []); //this check- to close listbox when no more matches after typing too much //MsgStatus(Format('prev %d now %d', [PrevCharsLeft, FPyComplete_CharsLeft])); if Abs(PrevCharsLeft-FPyCompletionProps.CharsLeft)<>1 then exit; AContent.Text:= FPyCompletionProps.Text; ACharsLeft:= FPyCompletionProps.CharsLeft; ACharsRight:= FPyCompletionProps.CharsRight; exit end; //stop doing, if caret moved if (Caret.PosX<>FPyCompletionProps.CaretPos.X) or (Caret.PosY<>FPyCompletionProps.CaretPos.Y) then exit; AContent.Text:= FPyCompletionProps.Text; ACharsLeft:= FPyCompletionProps.CharsLeft; ACharsRight:= FPyCompletionProps.CharsRight; end; procedure TfmMain.PyCompletionOnResult(Sender: TObject; const ASnippetId: string; ASnippetIndex: integer); var Sep: TATStringSeparator; StrLine, StrSnippet: string; i: integer; begin if FPyCompletionProps.Text='' then //fix #4475 exit; //find index-th line StrLine:= ''; Sep.Init(FPyCompletionProps.Text, #10); for i:= 0 to ASnippetIndex do Sep.GetItemStr(StrLine); //in line: snippet is 3rd column, skip 2 columns Sep.Init(StrLine, #9); for i:= 1 to 3 do Sep.GetItemStr(StrSnippet); //ShowMessage('id: '+ASnippetId+#10+'text:'#10+StrSnippet); DoPyEvent(FPyCompletionProps.Editor, TAppPyEvent.OnSnippet, [ AppVariant(ASnippetId), AppVariant(StrSnippet) ]); FPyCompletionProps.Clear; end; procedure DoApplyCompletionListboxStyle(Alt: boolean); begin if Alt then begin //id|prefix|desc CompletionOps.IndexOfText:= 0; end else begin //prefix|id|desc CompletionOps.IndexOfText:= 1; end; end; function api_ed_complete(Self, Args: PPyObject): PPyObject; cdecl; var H: Int64; Ptr: PChar; Ed: TATSynEdit; Caret: TATCaretItem; Str: string; NChars1, NChars2, NSelIndex, NAltOrder: integer; begin with AppPython.Engine do if Bool(PyArg_ParseTuple(Args, 'Lsiiii:complete', @H, @Ptr, @NChars1, @NChars2, @NSelIndex, @NAltOrder)) then begin Ed:= PyHelper_EditorFromHandle(H); Str:= string(Ptr); if Ed.Carets.Count=0 then exit(ReturnNone); Caret:= Ed.Carets[0]; fmMain.DoApplyCompletionOps(Ed); fmMain.FPyCompletionProps.Clear; fmMain.FPyCompletionProps.Editor:= Ed; fmMain.FPyCompletionProps.Text:= Str; fmMain.FPyCompletionProps.CharsLeft:= NChars1; fmMain.FPyCompletionProps.CharsRight:= NChars2; fmMain.FPyCompletionProps.CaretPos:= Caret.AsPoint; DoApplyCompletionListboxStyle(Bool(NAltOrder)); EditorShowCompletionListbox(Ed, @fmMain.PyCompletionOnGetProp, nil, nil, '_', NSelIndex); Result:= ReturnNone; end else Result:= ReturnNone; end; function api_ed_complete_alt(Self, Args: PPyObject): PPyObject; cdecl; var H: Int64; PtrText, PtrId: PChar; Ed: TATSynEdit; Caret: TATCaretItem; StrText, StrId: string; NChars, NSelIndex: integer; begin with AppPython.Engine do if Bool(PyArg_ParseTuple(Args, 'Lssii:complete_alt', @H, @PtrText, @PtrId, @NChars, @NSelIndex)) then begin Ed:= PyHelper_EditorFromHandle(H); StrText:= string(PtrText); StrId:= string(PtrId); if Ed.Carets.Count=0 then exit(ReturnNone); Caret:= Ed.Carets[0]; fmMain.DoApplyCompletionOps(Ed); fmMain.FPyCompletionProps.Clear; fmMain.FPyCompletionProps.Editor:= Ed; fmMain.FPyCompletionProps.Text:= StrText; fmMain.FPyCompletionProps.CharsLeft:= NChars; fmMain.FPyCompletionProps.CharsRight:= 0; fmMain.FPyCompletionProps.CaretPos:= Caret.AsPoint; DoApplyCompletionListboxStyle(false); EditorShowCompletionListbox(Ed, @fmMain.PyCompletionOnGetProp, @fmMain.PyCompletionOnResult, nil, StrId, NSelIndex); Result:= ReturnNone; end else Result:= ReturnNone; end; function PyHelper_IniReadWrite(Self, Args: PPyObject; AWrite: boolean): PPyObject; cdecl; const cFuncName: array[boolean] of string = ('ini_read', 'ini_write'); var P1, P2, P3, P4: PChar; StrFN, StrSess, StrKey, StrVal: string; ini: TIniFile; fn: string; begin with AppPython.Engine do begin if Bool(PyArg_ParseTuple(Args, PChar('ssss:'+cFuncName[AWrite]), @P1, @P2, @P3, @P4)) then begin StrFN:= string(P1); StrSess:= string(P2); StrKey:= string(P3); StrVal:= string(P4); fn:= StrFN; if ExtractFileDir(fn)='' then fn:= AppDir_Settings+DirectorySeparator+fn; ini:= TIniFile.Create(fn); //FreePascal 3.0.4 sets StripQuotes:=True in TIniFile.Create, but plugins need to keep quotes ini.Options:= ini.Options-[ifoStripComments, ifoStripQuotes]; try if AWrite then begin ini.WriteString(StrSess, StrKey, StrVal); Result:= ReturnNone; end else begin StrVal:= ini.ReadString(StrSess, StrKey, StrVal); Result:= PyUnicodeFromString(StrVal); end; finally FreeAndNil(ini); end; end else Result:= ReturnNone; end; end; function api_ini_read(Self, Args: PPyObject): PPyObject; cdecl; begin Result:= PyHelper_IniReadWrite(Self, Args, false); end; function api_ini_write(Self, Args: PPyObject): PPyObject; cdecl; begin Result:= PyHelper_IniReadWrite(Self, Args, true); end; function api_ini_proc(Self, Args: PPyObject): PPyObject; cdecl; var Id: Longint; PtrFN, PtrSection, PtrKey: PChar; StrFN, StrSection, StrKey: string; L: TStringList; Ini: TIniFile; begin with AppPython.Engine do begin if Bool(PyArg_ParseTuple(Args, 'isss:ini_proc', @Id, @PtrFN, @PtrSection, @PtrKey)) then begin StrFN:= string(PtrFN); StrSection:= string(PtrSection); StrKey:= string(PtrKey); if ExtractFileDir(StrFN)='' then StrFN:= AppDir_Settings+DirectorySeparator+StrFN; Ini:= TIniFile.Create(StrFN); try case Id of INI_GET_SECTIONS: begin L:= TStringList.Create; try Ini.ReadSections(L); Result:= StringsToPyList(L); finally FreeAndNil(L); end; end; INI_GET_KEYS: begin L:= TStringList.Create; try Ini.ReadSection(StrSection, L); Result:= StringsToPyList(L); finally FreeAndNil(L); end; end; INI_DELETE_KEY: begin Ini.DeleteKey(StrSection, StrKey); Result:= ReturnNone; end; INI_DELETE_SECTION: begin Ini.EraseSection(StrSection); Result:= ReturnNone; end; else Result:= ReturnNone; end; finally FreeAndNil(Ini); end; end; end; end; function api_dlg_color(Self, Args : PPyObject): PPyObject; cdecl; var NCode: Longint; begin with AppPython.Engine do if Bool(PyArg_ParseTuple(Args, 'i:dlg_color', @NCode)) then begin if not Assigned(fmMain.FColorDialog) then fmMain.FColorDialog:= TColorDialog.Create(fmMain); with TIniFile.Create(AppFile_Language) do try fmMain.FColorDialog.Title:= ReadString('d_about', '_clr', 'Colors'); finally Free; end; fmMain.FColorDialog.Color:= NCode; if fmMain.FColorDialog.Execute then Result:= PyLong_FromLong(fmMain.FColorDialog.Color) else Result:= ReturnNone; end else Result:= ReturnNone; end; function api_dlg_menu(Self, Args: PPyObject): PPyObject; cdecl; var PtrItems, PtrCaption: PChar; StrItems, StrCaption: string; NId, NIndex: integer; NCollapse, NSizeW, NSizeH: integer; Props: TDlgMenuProps; begin with AppPython.Engine do if Bool(PyArg_ParseTuple(Args, 'isisiii:dlg_menu', @NId, @PtrItems, @NIndex, @PtrCaption, @NCollapse, @NSizeW, @NSizeH)) then begin StrItems:= string(PtrItems); StrCaption:= string(PtrCaption); case (NId and 1) of DMENU_LIST, DMENU_LIST_ALT: begin Props:= Default(TDlgMenuProps); Props.ItemsText:= StrItems; Props.Caption:= StrCaption; Props.InitialIndex:= NIndex; Props.Multiline:= (NId and 1)=DMENU_LIST_ALT; Props.NoFuzzy:= (NId and DMENU_NO_FUZZY)<>0; Props.NoFullFilter:= (NId and DMENU_NO_FULLFILTER)<>0; Props.ShowCentered:= (NId and DMENU_CENTERED)<>0; Props.UseEditorFont:= (NId and DMENU_EDITORFONT)<>0; Props.Collapse:= TATCollapseStringMode(NCollapse); Props.W:= NSizeW; Props.H:= NSizeH; NIndex:= fmMain.DoDialogMenuApi(Props); Application.ProcessMessages; //force hide dialog if NIndex>=0 then Result:= PyLong_FromLong(NIndex) else Result:= ReturnNone; end else Result:= ReturnNone; end; end else Result:= ReturnNone; end; var AppPanelActive: string = '0'; function FindBottomForm_ByCaption(const ACaption: string): TAppFormWithEditor; begin case ACaption of '0': Result:= fmOutput; '1': Result:= fmValidate; else Result:= nil; end; end; function FindBottomForm_ByEditor(Ed: TATSynEdit): TAppFormWithEditor; begin Result:= nil; if Ed=fmOutput.Ed then Result:= fmOutput else if Ed=fmValidate.Ed then Result:= fmValidate; end; function api_app_log(Self, Args: PPyObject): PPyObject; cdecl; var PtrText, PtrPanel: PChar; StrText, StrPanel: string; Id, NLen, i: integer; Form: TAppFormWithEditor; List: TStringList; begin with AppPython.Engine do if Bool(PyArg_ParseTuple(Args, 'iss:app_log', @Id, @PtrText, @PtrPanel)) then begin StrText:= string(PtrText); StrPanel:= string(PtrPanel); if StrPanel<>'' then Form:= FindBottomForm_ByCaption(StrPanel) else Form:= FindBottomForm_ByCaption(AppPanelActive); if Form=nil then exit(ReturnNone); case Id of LOG_CLEAR: begin Form.Clear; Result:= ReturnNone; end; LOG_ADD: begin Form.Add(StrText); Result:= ReturnNone; end; LOG_SET_REGEX: begin Form.RegexStr:= StrText; Result:= ReturnNone; end; LOG_SET_LINE_ID: begin Form.RegexIdLine:= StrToIntDef(StrText, 0); Result:= ReturnNone; end; LOG_SET_COL_ID: begin Form.RegexIdCol:= StrToIntDef(StrText, 0); Result:= ReturnNone; end; LOG_SET_NAME_ID: begin Form.RegexIdName:= StrToIntDef(StrText, 0); Result:= ReturnNone; end; LOG_SET_FILENAME: begin Form.DefFilename:= StrText; Result:= ReturnNone; end; LOG_SET_ZEROBASE: begin Form.ZeroBase:= Bool(StrToIntDef(StrText, 0)); Result:= ReturnNone; end; LOG_GET_LINES_LIST: begin NLen:= Form.Ed.Strings.Count; Result:= PyList_New(NLen); if not Assigned(Result) then raise EPythonError.Create(msgPythonListError); for i:= 0 to NLen-1 do begin PyList_SetItem(Result, i, Py_BuildValue('(sL)', PChar(string(Form.Ed.Strings.Lines[i])), 0 )); end; end; LOG_GET_LINEINDEX: begin if Form.Ed.Carets.Count>0 then Result:= PyLong_FromLong(Form.Ed.Carets[0].PosY) else Result:= PyLong_FromLong(-1); end; LOG_SET_LINEINDEX: begin Form.Ed.DoGotoPos( Point(0, StrToIntDef(StrText, 0)), Point(-1, -1), UiOps.FindIndentHorz, UiOps.FindIndentVert, true, TATEditorActionIfFolded.Unfold ); Result:= ReturnNone; end; LOG_CONSOLE_CLEAR: begin if Assigned(fmConsole) then begin if (StrText='') or (Pos('m', StrText)>0) then fmConsole.DoClearMemo(nil); if (StrText='') or (Pos('e', StrText)>0) then fmConsole.DoClearInput(nil); if (StrText='') or (Pos('h', StrText)>0) then fmConsole.DoClearHistory; end; Result:= ReturnNone; end; LOG_CONSOLE_ADD: begin if Assigned(fmConsole) then begin MsgLogConsole(cConsolePrompt+StrText); fmConsole.EdInput.DoAddLineToHistory(StrText, cConsoleMaxComboboxItems); fmConsole.EdInput.Text:= ''; fmConsole.EdInput.Update(true); end; Result:= ReturnNone; end; LOG_CONSOLE_GET_COMBO_LINES: begin if Assigned(fmConsole) then Result:= StringsToPyList(fmConsole.EdInput.Items) else Result:= ReturnNone; end; LOG_CONSOLE_GET_MEMO_LINES: begin List:= TStringList.Create; try List.TextLineBreakStyle:= tlbsLF; if Assigned(fmConsole) then List.Text:= UTF8Encode(fmConsole.EdMemo.Text); Result:= StringsToPyList(List); finally FreeAndNil(List); end; end; else Result:= ReturnNone; end; fmMain.UpdateSidebarButtonOverlay; end; end; function api_dlg_hotkey(Self, Args: PPyObject): PPyObject; cdecl; var Ptr: PChar; S: string; begin with AppPython.Engine do if Bool(PyArg_ParseTuple(Args, 's:dlg_hotkey', @Ptr)) then begin S:= string(Ptr); S:= DoDialogHotkeyInput(S); if S<>'' then Result:= PyUnicodeFromString(S) else Result:= ReturnNone; end else Result:= ReturnNone; end; function api_dlg_hotkeys(Self, Args : PPyObject): PPyObject; cdecl; var PtrCommand, PtrLexer: PChar; StrCommand, StrLexer: string; NCommand: integer; Ok: boolean; begin with AppPython.Engine do if Bool(PyArg_ParseTuple(Args, 'ss:dlg_hotkeys', @PtrCommand, @PtrLexer)) then begin StrCommand:= string(PtrCommand); StrLexer:= string(PtrLexer); NCommand:= StrToIntDef(StrCommand, 0); if NCommand>0 then Ok:= DoDialogHotkeys(AppKeymapMain, NCommand, StrLexer) else Ok:= DoDialogHotkeys_Plugin(AppKeymapMain, StrCommand, StrLexer); Result:= PyBool_FromLong(Ord(Ok)); end else Result:= ReturnNone; end; function api_dlg_commands(Self, Args : PPyObject): PPyObject; cdecl; var NOps: integer; PtrTitle: PChar; StrTitle, Str: string; W, H: integer; Props: TDlgCommandsProps; begin with AppPython.Engine do if Bool(PyArg_ParseTuple(Args, 'isii:dlg_commands', @NOps, @PtrTitle, @W, @H)) then begin StrTitle:= string(PtrTitle); TKeymapHelperMain.UpdateDynamic(TAppCommandCategory.Lexer); TKeymapHelperMain.UpdateDynamic(TAppCommandCategory.OpenedFile); TKeymapHelperMain.UpdateDynamic(TAppCommandCategory.RecentFile); Props:= Default(TDlgCommandsProps); Props.Caption:= StrTitle; Props.ShowUsual:= (NOps and COMMANDS_USUAL)<>0; Props.ShowPlugins:= (NOps and COMMANDS_PLUGINS)<>0; Props.ShowLexers:= (NOps and COMMANDS_LEXERS)<>0; Props.ShowFiles:= (NOps and COMMANDS_FILES)<>0; Props.ShowRecents:= (NOps and COMMANDS_RECENTS)<>0; Props.AllowConfig:= (NOps and COMMANDS_CONFIG)<>0; Props.AllowConfigForLexer:= (NOps and COMMANDS_CONFIG_LEXER)<>0; Props.ShowCentered:= (NOps and COMMANDS_CENTERED)<>0; Props.W:= W; Props.H:= H; Str:= fmMain.DoDialogCommands_Py(Props); if Str='' then Result:= ReturnNone else Result:= PyUnicodeFromString(Str); end else Result:= ReturnNone; end; (* procedure DoLogDialog(ASizeX, ASizeY: integer; const AText: string); var STime, SLog: string; begin if AText='' then exit; STime:= FormatDateTime('yyyy-mm-dd_hh-mm-ss', Now); SLog:= Format(GetTempDir+'dlg_'+STime+'_%dx%d.txt', [ASizeX, ASizeY]); MsgLogConsole('Dialog logged: '+SLog); with TFileStream.Create(SLog, fmCreate) do try WriteBuffer(AText[1], Length(AText)); finally Free; end; end; *) function api_dlg_custom(Self, Args : PPyObject): PPyObject; cdecl; var PtrTitle, PtrText: PChar; StrTitle, StrText, StrResult: string; NSizeX, NSizeY, NFocused, NButton: integer; begin with AppPython.Engine do if Bool(PyArg_ParseTuple(Args, 'siisi:dlg_custom', @PtrTitle, @NSizeX, @NSizeY, @PtrText, @NFocused)) then begin StrTitle:= string(PtrTitle); StrText:= string(PtrText); //if UiOps.LogCustomDialogs then // DoLogDialog(NSizeX, NSizeY, StrText); DoDialogCustom(StrTitle, NSizeX, NSizeY, StrText, NFocused, NButton, StrResult); if NButton<0 then Result:= ReturnNone else Result:= Py_BuildValue('(is)', NButton, PChar(StrResult)); end else Result:= ReturnNone; end; function PyHelper_GetWrapInfo(Ed: TATSynEdit; AParam1, AParam2: integer): PPyObject; var WrapItem: PATWrapItem; PItems: PATWrapItem; PDict, Template: PPyObject; KeyLine, KeyChar, KeyLen, KeyIndent, KeyFinal, KeyInitial: PPyObject; NIndex1, NIndex2: integer; NLen, NValid, i: integer; //2026.09 fix (memory leak): PyDict_SetItem() does NOT steal the value's //reference (unlike PyList_SetItem() which does) - it increfs's the value, //so the new reference returned by PyLong_FromLong()/PyBool_FromLong() must //be decref'd after insertion. Passing the temp directly, // PyDict_SetItem(D, K, PyLong_FromLong(V)); //leaks that reference on every call: for values outside CPython's small-int //cache (-5..256) it leaks a real 28-byte PyLong per item, and the leaked //blocks pin whole pymalloc pools/arenas after the caller frees the resulting //list (measured ~2GB retained instead of ~600MB on a 1M-lines doc) procedure SetItemLong(ADict, AKey: PPyObject; AValue: LongInt); var Val: PPyObject; begin with AppPython.Engine do begin Val:= PyLong_FromLong(AValue); if Val=nil then raise EPythonError.Create('Cannot create int object'); try PyDict_SetItem(ADict, AKey, Val); finally Py_DECREF(Val); end; end; end; procedure SetItemBool(ADict, AKey: PPyObject; AValue: LongInt); var Val: PPyObject; begin with AppPython.Engine do begin Val:= PyBool_FromLong(AValue); if Val=nil then raise EPythonError.Create('Cannot create bool object'); try PyDict_SetItem(ADict, AKey, Val); finally Py_DECREF(Val); end; end; end; begin with AppPython.Engine do begin if AParam20 then begin Ed.WrapInfo.FindIndexesOfLineNumber(AParam1, NIndex1, i); if NIndex1<0 then exit(PyList_New(0)); end else NIndex1:= 0; if AParam2>=0 then begin Ed.WrapInfo.FindIndexesOfLineNumber(AParam2, i, NIndex2); if NIndex2<0 then NIndex2:= Ed.WrapInfo.Count-1; end else NIndex2:= Ed.WrapInfo.Count-1; NLen:= Max(0, NIndex2-NIndex1+1); Result:= PyList_New(NLen); if not Assigned(Result) then raise EPythonError.Create(msgPythonListError); if NLen=0 then exit; //2026.09 (CudaText perf): old code called Py_BuildValue() per item, which //created 6 key strings + one dict per item (for a 1M-lines document: over //2s per call). Now one template dict is created, each item is a fast //PyDict_Copy of it, and only keys with non-default values are set. //Skipped values are CPython cached singletons (0, 1, True), so resulting //dicts hold the same objects as before. Gives ~4x speedup. KeyLine:= PyUnicode_FromString('line'); KeyChar:= PyUnicode_FromString('char'); KeyLen:= PyUnicode_FromString('len'); KeyIndent:= PyUnicode_FromString('indent'); KeyFinal:= PyUnicode_FromString('final'); KeyInitial:= PyUnicode_FromString('initial'); Template:= nil; try Template:= PyDict_New(); if Template=nil then raise EPythonError.Create('Cannot create dict object'); SetItemLong(Template, KeyLine, 0); SetItemLong(Template, KeyChar, 1); SetItemLong(Template, KeyLen, 0); SetItemLong(Template, KeyIndent, 0); SetItemLong(Template, KeyFinal, 0); SetItemBool(Template, KeyInitial, 1); //2026.09 (CudaText perf): one bulk read of wrap items instead of NLen //property calls (each one: bounds checks + property call chain) GetMem(PItems, SizeInt(NLen)*SizeOf(TATWrapItem)); try NValid:= Ed.WrapInfo.FillItems(NIndex1, NLen, PItems); //mimic WrapInfo[i] which returns zeroed items for out-of-range indexes if NValid1 then SetItemLong(PDict, KeyChar, LongInt(WrapItem^.NCharIndex)); if WrapItem^.NIndent<>0 then SetItemLong(PDict, KeyIndent, LongInt(WrapItem^.NIndent)); if WrapItem^.NFinal<>TATWrapItemFinal.Final then SetItemLong(PDict, KeyFinal, Ord(WrapItem^.NFinal)); if not WrapItem^.bInitial then SetItemBool(PDict, KeyInitial, Ord(WrapItem^.bInitial)); PyList_SetItem(Result, i, PDict); end; finally FreeMem(PItems); end; finally Py_XDECREF(Template); Py_XDECREF(KeyLine); Py_XDECREF(KeyChar); Py_XDECREF(KeyLen); Py_XDECREF(KeyIndent); Py_XDECREF(KeyFinal); Py_XDECREF(KeyInitial); end; end end; function api_ed_get_wrapinfo(Self, Args: PPyObject): PPyObject; cdecl; var H: Int64; Ed: TATSynEdit; NParam1, NParam2: integer; begin with AppPython.Engine do if Bool(PyArg_ParseTuple(Args, 'Lii:get_wrapinfo', @H, @NParam1, @NParam2)) then begin Ed:= PyHelper_EditorFromHandle(H); Result:= PyHelper_GetWrapInfo(Ed, NParam1, NParam2); end else Result:= ReturnNone; end; function PyHelper_GetScrollInfo(const AInfo: TATEditorScrollInfo): PPyObject; begin with AppPython.Engine do begin Result:= Py_BuildValue('{sLsLsLsLsLsLsLsLsLsL}', 'pos', AInfo.NPos, 'pos_last', AInfo.NPosLast, 'max', AInfo.NMax, 'page', AInfo.NPage, 'pixels', AInfo.NPixelOffset, 'char_size', AInfo.CharSizeScaled div ATEditorCharXScale, 'smooth_pos', AInfo.SmoothPos, 'smooth_pos_last', AInfo.SmoothPosLast, 'smooth_max', AInfo.SmoothMax, 'smooth_page', AInfo.SmoothPage ); end; end; function PyHelper_GetCommandLog(Ed: TATSynEdit): PPyObject; var Item: TATCommandLogItem; NCount, i: integer; begin with AppPython.Engine do begin NCount:= Ed.CommandLog.Size(); Result:= PyList_New(NCount); for i:= 0 to NCount-1 do begin Item:= Ed.CommandLog.Items[i]; PyList_SetItem(Result, i, Py_BuildValue('{sissss}', 'code', Item.ItemCode, 'invoke', PChar(cEditorCommandInvoke[Item.ItemInvoke]), 'text', PChar(string(Item.ItemText)) )); end; end; end; function PyHelper_GetEventItem(EvInfo: TAppEventInfo): PPyObject; var ObjEvents, ObjList: PPyObject; Sep: TATStringSeparator; EvId: TAppPyEvent; S: string; begin with AppPython.Engine do begin Result:= PyDict_New(); PyDict_SetItemString(Result, 'module', PyUnicodeFromString(EvInfo.ItemModule)); ObjList:= PyList_New(0); if StartsStr(AppLexerPrefixRegex, EvInfo.ItemLexers) then begin S:= EvInfo.ItemLexers; PyList_Append(ObjList, PyUnicodeFromString(S)); end else begin Sep.Init(EvInfo.ItemLexers); while Sep.GetItemStr(S) do PyList_Append(ObjList, PyUnicodeFromString(S)); end; PyDict_SetItemString(Result, 'lex', ObjList); ObjList:= PyList_New(0); Sep.Init(EvInfo.ItemKeys); while Sep.GetItemStr(S) do PyList_Append(ObjList, PyUnicodeFromString(S)); PyDict_SetItemString(Result, 'keys', ObjList); ObjEvents:= PyList_New(0); PyDict_SetItemString(Result, 'ev', ObjEvents); for EvId:= Low(TAppPyEvent) to High(TAppPyEvent) do if EvId in EvInfo.ItemEvents then PyList_Append(ObjEvents, Py_BuildValue('{sssOsi}', 'id', PChar(cAppPyEvent[EvId]), 'lazy', PyBool_FromLong(Ord(EvInfo.ItemEventsLazy[EvId])), 'pr', Longint(EvInfo.ItemEventsPrior[EvId]) )); end; end; function PyHelper_GetEvents(const AModuleNeeded: string): PPyObject; (* Returns list of dicts: [ {'module': 'cuda_nn', 'lex': ['C'], 'keys': ['9', '32'], 'ev': [{'id': 'on_key', 'lazy': False, 'pr': 0}, ...], ... ] *) // function IsModuleOk(const S: string): boolean; begin Result:= (AModuleNeeded='') or (S=AModuleNeeded); end; // var EvInfo: TAppEventInfo; NCountItems, iItemTotal, iItemCurrent: integer; begin NCountItems:= 0; for iItemTotal:= 0 to AppEventList.Count-1 do begin EvInfo:= TAppEventInfo(AppEventList[iItemTotal]); if not IsModuleOk(EvInfo.ItemModule) then Continue; Inc(NCountItems); end; with AppPython.Engine do begin Result:= PyList_New(NCountItems); iItemCurrent:= 0; for iItemTotal:= 0 to AppEventList.Count-1 do begin EvInfo:= TAppEventInfo(AppEventList[iItemTotal]); if not IsModuleOk(EvInfo.ItemModule) then Continue; PyList_SetItem(Result, iItemCurrent, PyHelper_GetEventItem(EvInfo)); Inc(iItemCurrent); end; end; end; function api_ed_get_prop(Self, Args: PPyObject): PPyObject; cdecl; var H: Int64; Id, Num1, Num2: integer; Ptr: PChar; Str: string; Ed: TATSynEdit; Frame: TEditorFrame; Pnt: TPoint; Adapter: TATAdapterEControl; An: TecSyntAnalyzer; Sep: TATStringSeparator; CharSize: TATEditorCharSize; bValue: boolean; begin with AppPython.Engine do if Bool(PyArg_ParseTuple(Args, 'Lis:get_prop', @H, @Id, @Ptr)) then begin Ed:= PyHelper_EditorFromHandle(H); if Ed=nil then exit(ReturnNone); Str:= string(Ptr); Frame:= TGroupsHelper.GetEditorFrame(Ed); case Id of PROP_FN: begin if Assigned(Frame) then begin if Frame.FrameKind=TAppFrameKind.Editor then Result:= PyUnicodeFromString(Ed.FileName) else if Str='*' then Result:= PyUnicodeFromString(Frame.GetFileName(Ed)) else Result:= PyUnicodeFromString(string('?')); end else Result:= PyUnicodeFromString(Ed.FileName); end; PROP_GUTTER_ALL: Result:= PyBool_FromLong(Ord(Ed.OptGutterVisible)); PROP_GUTTER_STATES: begin bValue:= Ed.Gutter[Ed.Gutter.FindIndexByTag(ATEditorOptions.GutterTagLineStates)].Visible; Result:= PyBool_FromLong(Ord(bValue)); end; PROP_GUTTER_NUM: begin bValue:= Ed.Gutter[Ed.Gutter.FindIndexByTag(ATEditorOptions.GutterTagNumbers)].Visible; Result:= PyBool_FromLong(Ord(bValue)); end; PROP_GUTTER_FOLD: begin bValue:= Ed.Gutter[Ed.Gutter.FindIndexByTag(ATEditorOptions.GutterTagFolding)].Visible; Result:= PyBool_FromLong(Ord(bValue)); end; PROP_GUTTER_BM: begin bValue:= Ed.Gutter[Ed.Gutter.FindIndexByTag(ATEditorOptions.GutterTagBookmarks)].Visible; Result:= PyBool_FromLong(Ord(bValue)); end; PROP_GUTTER_EMPTY: begin bValue:= Ed.Gutter[Ed.Gutter.FindIndexByTag(ATEditorOptions.GutterTagEmpty)].Visible; Result:= PyBool_FromLong(Ord(bValue)); end; PROP_WRAP: Result:= PyLong_FromLong(Ord(Ed.OptWrapMode)); PROP_RO: Result:= PyBool_FromLong(Ord(Ed.ModeReadOnly)); PROP_TAB_SPACES: Result:= PyBool_FromLong(Ord(Ed.OptTabSpaces)); PROP_TAB_SIZE: Result:= PyLong_FromLong(Ed.OptTabSize); PROP_TAB_SMART: Result:= PyBool_FromLong(Ord(Ed.OptTabSmart)); PROP_MARGIN: Result:= PyLong_FromLong(Ed.OptMarginRight); PROP_MARGIN_STRING: Result:= PyUnicodeFromString(Ed.OptMarginString); PROP_INSERT: Result:= PyBool_FromLong(Ord(not Ed.ModeOverwrite)); PROP_MODIFIED: Result:= PyBool_FromLong(Ord(Ed.Modified)); PROP_MODIFIED_VERSION: Result:= PyLong_FromLongLong(Ed.Strings.ModifiedVersion); PROP_RULER: Result:= PyBool_FromLong(Ord(Ed.OptRulerVisible)); PROP_LINE_STATE: begin Num1:= StrToIntDef(Str, -1); if Ed.Strings.IsIndexValid(Num1) then Result:= PyLong_FromLong(Ord(Ed.Strings.LinesState[Num1])) else Result:= ReturnNone; end; PROP_LINE_STATES: Result:= PyHelper_GetLineStateList(Ed); PROP_LINE_STATES_UPDATED: Result:= PyHelper_GetLineUpdatedList(Ed); PROP_GUTTER_EMPTY_WIDTH: Result:= PyLong_FromLong(Ed.OptGutterWidthEmpty); PROP_GUTTER_BM_WIDTH: Result:= PyLong_FromLong(Ed.OptGutterWidthBookmarks); PROP_GUTTER_STATES_WIDTH: Result:= PyLong_FromLong(Ed.OptGutterWidthLineStates); PROP_GUTTER_FOLD_WIDTH: Result:= PyLong_FromLong(Ed.OptGutterWidthFolding); PROP_ZEBRA: begin if Ed.OptZebraActive then Num1:= Ed.OptZebraAlphaBlend else Num1:= 0; Result:= PyLong_FromLong(Num1); end; PROP_ZEBRA_STEP: Result:= PyLong_FromLong(Ed.OptZebraStep); PROP_COLOR: begin Num1:= EditorGetColorById(Ed, Str); if Num1<>-1 then Result:= PyLong_FromLong(Num1) else Result:= ReturnNone; end; PROP_LINE_TOP: Result:= PyLong_FromLong(Ed.LineTop); PROP_LINE_NUMBERS: Result:= PyLong_FromLong(Ord(Ed.OptNumbersStyle)); PROP_LEXER_FILE: begin //if editor in frame, use frame's prop if Assigned(Frame) then begin Str:= Frame.LexerName[Ed]; Result:= PyUnicodeFromString(Str); end else if Ed.AdapterForHilite is TATAdapterEControl then begin Adapter:= Ed.AdapterForHilite as TATAdapterEControl; An:= Adapter.Lexer; if Assigned(An) then Result:= PyUnicodeFromString(An.LexerName) else Result:= PyUnicodeFromString(''); end else if Ed.AdapterForHilite is TATLiteLexer then begin Result:= PyUnicodeFromString(TATLiteLexer(Ed.AdapterForHilite).LexerName+msgLiteLexerSuffix); end else Result:= PyUnicodeFromString(''); end; PROP_LEXER_POS: begin Sep.Init(Str, ','); Sep.GetItemInt(Pnt.X, 0); Sep.GetItemInt(Pnt.Y, 0); Result:= PyUnicodeFromString(EditorLexerNameAtPos(Ed, Pnt)); end; PROP_LEXER_CARET: begin if Ed.Carets.Count=0 then exit(ReturnNone); with Ed.Carets[0] do begin Pnt.X:= PosX; Pnt.Y:= PosY; end; Result:= PyUnicodeFromString(EditorLexerNameAtPos(Ed, Pnt)); end; PROP_TAB_COLOR: begin if Assigned(Frame) then Result:= PyLong_FromLong(Frame.TabColor) else Result:= ReturnNone; end; PROP_TAB_COLOR_FONT: begin if Assigned(Frame) then Result:= PyLong_FromLong(Frame.TabFontColor) else Result:= ReturnNone; end; PROP_TAB_TITLE: begin if Assigned(Frame) then Result:= PyUnicodeFromString(TrimLeftSet(Frame.TabCaption, ['*'])) else Result:= ReturnNone; end; PROP_TAB_TITLE_REASON: begin if Assigned(Frame) then Result:= PyUnicodeFromString(ConvertTabCaptionReasonToString(Frame.TabCaptionReason)) else Result:= ReturnNone; end; PROP_TAB_PINNED: begin if Assigned(Frame) then Result:= PyBool_FromLong(Ord(Frame.TabPinned)) else Result:= ReturnNone; end; PROP_TAB_ID: begin if Assigned(Frame) then Result:= PyLong_FromLongLong(Frame.UniqueCounter) else Result:= PyLong_FromLong(0); end; PROP_TAB_UI_SHOW: begin if Assigned(Frame) then Result:= PyBool_FromLong(Ord(Frame.TabVisible)) else Result:= ReturnNone; end; PROP_ENC: begin Str:= AppEncodingFullnameToShortname(Ed.EncodingName); Result:= PyUnicodeFromString(Str); end; PROP_IN_SESSION: begin if Assigned(Frame) then Result:= PyBool_FromLong(Ord(Frame.IsLoadedFromSession)) else Result:= ReturnFalse; end; PROP_NEWLINE: begin case Ed.Strings.Endings of TATLineEnds.Windows: Str:= 'crlf'; TATLineEnds.Mac: Str:= 'cr'; else Str:= 'lf'; end; Result:= PyUnicodeFromString(Str); end; PROP_INDEX_GROUP: begin TGroupsHelper.GetGroupAndTabIndexes(Ed, Num1, Num2); Result:= PyLong_FromLongLong(Num1); end; PROP_INDEX_TAB: begin TGroupsHelper.GetGroupAndTabIndexes(Ed, Num1, Num2); Result:= PyLong_FromLongLong(Num2); end; PROP_KIND: begin if not Assigned(Frame) then exit(ReturnNone); Str:= cAppFrameKindStr[Frame.FrameKind]; Result:= PyUnicodeFromString(Str); end; PROP_TAG: begin Result:= PyUnicodeFromString(Ed.TagString); end; PROP_UNPRINTED_SHOW: Result:= PyBool_FromLong(Ord(Ed.OptUnprintedVisible)); PROP_UNPRINTED_SPACES: Result:= PyBool_FromLong(Ord(Ed.OptUnprintedSpaces)); PROP_UNPRINTED_SPACES_TRAILING: Result:= PyBool_FromLong(Ord(Ed.OptUnprintedSpacesTrailing)); PROP_UNPRINTED_ENDS: Result:= PyBool_FromLong(Ord(Ed.OptUnprintedEnds)); PROP_UNPRINTED_WRAPS: Result:= PyBool_FromLong(Ord(Ed.OptUnprintedWraps)); PROP_UNPRINTED_END_DETAILS: Result:= PyBool_FromLong(Ord(Ed.OptUnprintedEndsDetails)); PROP_TAB_ICON: begin if Assigned(Frame) then Result:= PyLong_FromLongLong(Frame.TabImageIndex) else Result:= ReturnNone; end; PROP_TAB_COLLECT_MARKERS: begin if Assigned(Frame) then Result:= PyBool_FromLong(Ord(Frame.TabKeyCollectMarkers)) else Result:= ReturnNone; end; PROP_MACRO_REC: begin if Assigned(Frame) then Result:= PyBool_FromLong(Ord(Frame.MacroRecord)) else Result:= ReturnNone; end; PROP_MARKED_RANGE: begin Ed.DoGetMarkedLines(Num1, Num2); Result:= Py_BuildValue('(ii)', Num1, Num2); end; PROP_CARET_VIRTUAL: Result:= PyBool_FromLong(Ord(Ed.OptCaretVirtual)); PROP_CARET_STOP_UNFOCUSED: Result:= PyBool_FromLong(Ord(Ed.OptCaretStopUnfocused)); PROP_CARET_VIEW: Result:= PyHelper_GetCaretShape(Ed.CaretShapeNormal); PROP_CARET_VIEW_OVR: Result:= PyHelper_GetCaretShape(Ed.CaretShapeOverwrite); PROP_CARET_VIEW_RO: Result:= PyHelper_GetCaretShape(Ed.CaretShapeReadonly); PROP_MINIMAP: Result:= PyBool_FromLong(Ord(Ed.OptMinimapVisible)); PROP_MINIMAP_CHAR_WIDTH: Result:= PyLong_FromLong(Ed.OptMinimapCharWidth); PROP_MINIMAP_AT_LEFT: Result:= PyBool_FromLong(Ord(Ed.OptMinimapAtLeft)); PROP_MINIMAP_SCALE: Result:= PyLong_FromLong(Ed.OptMinimapCustomScale); PROP_MICROMAP: Result:= PyBool_FromLong(Ord(Ed.OptMicromapVisible)); PROP_MICROMAP_WIDTH: Result:= PyLong_FromLong(Ed.OptMicromapWidthInAvgChars); PROP_MICROMAP_ON_SCROLLBAR: Result:= PyBool_FromLong(Ord(Ed.OptMicromapOnScrollbar)); PROP_MICROMAP_AT_LEFT: Result:= PyBool_FromLong(Ord(Ed.OptMicromapAtLeft)); PROP_VISIBLE_LINES: Result:= PyLong_FromLong(Ed.GetVisibleLines); PROP_VISIBLE_COLUMNS: Result:= PyLong_FromLong(Ed.GetVisibleColumns); PROP_LINE_BOTTOM: Result:= PyLong_FromLong(Ed.LineBottom); PROP_SCROLL_VERT_INFO: Result:= PyHelper_GetScrollInfo(Ed.ScrollVert); PROP_SCROLL_HORZ_INFO: Result:= PyHelper_GetScrollInfo(Ed.ScrollHorz); PROP_SCALE_FONT: Result:= PyLong_FromLong(Ed.OptScaleFont); PROP_LAST_LINE_ON_TOP: Result:= PyBool_FromLong(Ord(Ed.OptLastLineOnTop)); PROP_FOCUSED: Result:= PyBool_FromLong(Ord(Ed.Focused)); PROP_HILITE_CUR_COL: Result:= PyBool_FromLong(Ord(Ed.OptShowCurColumn)); PROP_HILITE_CUR_LINE: Result:= PyBool_FromLong(Ord(Ed.OptShowCurLine)); PROP_HILITE_CUR_LINE_MINIMAL: Result:= PyBool_FromLong(Ord(Ed.OptShowCurLineMinimal)); PROP_HILITE_CUR_LINE_IF_FOCUS: Result:= PyBool_FromLong(Ord(Ed.OptShowCurLineOnlyFocused)); PROP_CODETREE: begin if Assigned(Frame) then Result:= PyBool_FromLong(Ord(Frame.EnabledCodeTree[Ed])) else Result:= ReturnFalse; end; PROP_EDITORS_LINKED: begin if Assigned(Frame) then Result:= PyBool_FromLong(Ord(Frame.EditorsLinked)) else Result:= ReturnFalse; end; PROP_ACTIVATION_TIME: begin Result:= PyLong_FromLongLong(Ed.ActivationTime); end; PROP_LINK_AT_POS: begin Sep.Init(Str); Sep.GetItemInt(Pnt.X, -1); Sep.GetItemInt(Pnt.Y, -1); Str:= Ed.DoGetLinkAtPos(Pnt.X, Pnt.Y); Result:= PyUnicodeFromString(Str); end; PROP_HANDLE_IMAGE: begin if Assigned(Frame) and Assigned(Frame.ImageBox) then Result:= PyHelper_ObjectHandle(Frame.ImageBox.Image) else Result:= ReturnNone; end; PROP_COORDS: begin Result:= PyHelper_RectOfControl(Ed); end; PROP_ONE_LINE: begin Result:= PyBool_FromLong(Ord(Ed.ModeOneLine)); end; PROP_INDENT_SIZE: begin Result:= PyLong_FromLong(Ed.OptIndentSize); end; PROP_INDENT_KEEP_ALIGN: begin Result:= PyBool_FromLong(Ord(Ed.OptIndentKeepsAlign)); end; PROP_INDENT_AUTO: begin Result:= PyBool_FromLong(Ord(Ed.OptAutoIndent)); end; PROP_INDENT_KIND: begin Result:= PyLong_FromLong(Ord(Ed.OptAutoIndentKind)); end; PROP_CELL_SIZE: begin CharSize:= Ed.TextCharSize; Result:= Py_BuildValue('(ii)', integer(CharSize.XScaled div ATEditorCharXScale) {$if defined(LCLQT5) or defined(LCLQT6)}+1{$endif}, integer(CharSize.Y)); end; PROP_MODERN_SCROLLBAR: begin Result:= PyBool_FromLong(Ord(Ed.OptScrollbarsNew)); end; PROP_SAVE_HISTORY: begin if Assigned(Frame) then Result:= PyBool_FromLong(Ord(Frame.SaveHistory)) else Result:= ReturnFalse; end; PROP_PREVIEW: begin if Assigned(Frame) then Result:= PyBool_FromLong(Ord(Frame.TabIsPreview)) else Result:= ReturnFalse; end; PROP_UNDO_GROUPED: Result:= PyBool_FromLong(Ord(Ed.OptUndoGrouped)); PROP_UNDO_LIMIT: Result:= PyLong_FromLong(Ed.OptUndoLimit); PROP_UNDO_DATA: Result:= PyUnicodeFromString(Ed.UndoAsString); PROP_REDO_DATA: Result:= PyUnicodeFromString(Ed.RedoAsString); PROP_SPLIT: begin if Assigned(Frame) then begin if not Frame.Splitted then Str:= '-' else if Frame.SplitHorz then Str:= 'h' else Str:= 'v'; Result:= Py_BuildValue('(si)', PChar(Str), Round(Frame.SplitPos*1000)); end else Result:= ReturnNone; end; PROP_SAVING_FORCE_FINAL_EOL: Result:= PyBool_FromLong(Ord(Ed.OptSavingForceFinalEol)); PROP_SAVING_TRIM_SPACES: Result:= PyBool_FromLong(Ord(Ed.OptSavingTrimSpaces)); PROP_SAVING_TRIM_FINAL_EMPTY_LINES: Result:= PyBool_FromLong(Ord(Ed.OptSavingTrimFinalEmptyLines)); PROP_FOLD_TOOLTIP_SHOW: begin Result:= PyBool_FromLong(Ord(Ed.OptFoldTooltipVisible)); end; PROP_FOLD_ALWAYS: begin Result:= PyBool_FromLong(Ord(Ed.OptGutterShowFoldAlways)); end; PROP_FOLD_ICONS: begin Result:= PyBool_FromLong(Ord(Ed.OptGutterIcons)); end; PROP_HANDLE_SELF: begin Result:= PyHelper_ObjectHandle(Ed); end; PROP_HANDLE_PRIMARY: begin if Assigned(Frame) then Result:= PyHelper_ObjectHandle(Frame.EdFirst) else Result:= ReturnNone; end; PROP_HANDLE_SECONDARY: begin if Assigned(Frame) then Result:= PyHelper_ObjectHandle(Frame.EdSecond) else Result:= ReturnNone; end; PROP_HANDLE_PARENT: begin if Assigned(Frame) then Result:= PyHelper_ObjectHandle(Frame.FormForPy) else Result:= PyLong_FromLong(0); end; PROP_HANDLE_PARENT2: begin if Assigned(Frame) then Result:= PyHelper_ObjectHandle(Frame) else Result:= PyLong_FromLong(0); end; PROP_SCROLLSTYLE_HORZ: begin Result:= PyLong_FromLong(Ord(Ed.OptScrollStyleHorz)); end; PROP_SCROLLSTYLE_VERT: begin Result:= PyLong_FromLong(Ord(Ed.OptScrollStyleVert)); end; PROP_LINKS_SHOW: Result:= PyBool_FromLong(Ord(Ed.OptShowURLs)); PROP_LINKS_REGEX: Result:= PyUnicodeFromString(Ed.OptShowURLsRegex); PROP_LINKS_CLICKS: begin Num1:= 0; if Ed.OptMouseClickOpensURL then Num1:= 1 else if Ed.OptMouse2ClickOpensURL then Num1:= 2; Result:= PyLong_FromLong(Num1); end; PROP_RECT_CLIENT: begin Result:= PyHelper_Rect(Ed.ClientRect); end; PROP_RECT_TEXT: begin Result:= PyHelper_Rect(Ed.RectMain); end; PROP_RECT_GUTTER: begin Result:= PyHelper_Rect(Ed.RectGutter); end; PROP_RECT_MINIMAP: begin Result:= PyHelper_Rect(Ed.RectMinimap); end; PROP_RECT_MICROMAP: begin Result:= PyHelper_Rect(Ed.RectMicromap); end; PROP_RECT_RULER: begin Result:= PyHelper_Rect(Ed.RectRuler); end; PROP_THEMED: begin Result:= PyBool_FromLong(Ord(Ed.OptThemed)); end; PROP_COMBO_ITEMS: begin if Ed is TATComboEdit then Result:= StringsToPyList(TATComboEdit(Ed).Items) else Result:= ReturnNone; end; PROP_CODETREE_MODIFIED_VERSION: begin Result:= PyLong_FromLongLong(AppCodetreeState.EditorVersion); end; PROP_CODETREE_SUBLEXER: begin if Ed.AdapterForHilite is TATAdapterEControl then Result:= PyBool_FromLong(Ord((Ed.AdapterForHilite as TATAdapterEControl).EnabledSublexerTreeNodes)) else Result:= ReturnFalse; end; PROP_FONT: Result:= PyHelper_GetFontProps(Ed.Font); PROP_FONT_B: Result:= PyHelper_GetFontProps(Ed.FontBold); PROP_FONT_I: Result:= PyHelper_GetFontProps(Ed.FontItalic); PROP_FONT_BI: Result:= PyHelper_GetFontProps(Ed.FontBoldItalic); PROP_WHEEL_ZOOMS: Result:= PyBool_FromLong(Ord(Ed.OptMouseWheelZooms)); PROP_MASKCHAR: Result:= PyUnicodeFromString(Ed.OptMaskChar); PROP_MASKCHAR_USED: Result:= PyBool_FromLong(Ord(Ed.OptMaskCharUsed)); PROP_NUMBERS_ONLY: Result:= PyBool_FromLong(Ord(Ed.OptInputNumberOnly)); PROP_NUMBERS_NEGATIVE: Result:= PyBool_FromLong(Ord(Ed.OptInputNumberAllowNegative)); PROP_COMMAND_LOG: Result:= PyHelper_GetCommandLog(Ed); PROP_COMMAND_LOG_LIMIT: Result:= PyLong_FromLong(Ed.CommandLog.MaxCount); PROP_DIM_UNFOCUSED: Result:= PyLong_FromLong(Ed.OptDimUnfocusedBack); PROP_CARET_MULTI: Result:= PyBool_FromLong(Ord(Ed.OptCaretManyAllowed)); PROP_RULER_TEXT: Result:= PyUnicodeFromString(Ed.OptRulerText); PROP_LEXER_BUSY: begin bValue:= Assigned(Ed.AdapterForHilite) and (Ed.AdapterForHilite is TATAdapterEControl) and TATAdapterEControl(Ed.AdapterForHilite).IsParsingBusy; Result:= PyBool_FromLong(Ord(bValue)); end; PROP_LINE_SPACE1: Result:= PyLong_FromLong(Ed.OptSpacingTop); PROP_LINE_SPACE2: Result:= PyLong_FromLong(Ed.OptSpacingBottom); PROP_CORNER_TEXT: Result:= PyUnicodeFromString(Ed.OptCornerText); PROP_CORNER_COLOR_FONT: Result:= PyLong_FromLong(Ed.OptCornerColorFont); PROP_CORNER_COLOR_BACK: Result:= PyLong_FromLong(Ed.OptCornerColorBack); PROP_CORNER_COLOR_BORDER: Result:= PyLong_FromLong(Ed.OptCornerColorBorder); PROP_CORNER2_TEXT: Result:= PyUnicodeFromString(Ed.OptCorner2Text); PROP_CORNER2_COLOR_FONT: Result:= PyLong_FromLong(Ed.OptCorner2ColorFont); PROP_CORNER2_COLOR_BACK: Result:= PyLong_FromLong(Ed.OptCorner2ColorBack); PROP_CORNER2_COLOR_BORDER: Result:= PyLong_FromLong(Ed.OptCorner2ColorBorder); PROP_CORNER_FONT_NAME: Result:= PyUnicodeFromString(Ed.OptCornerFontName); PROP_CORNER_FONT_SIZE: Result:= PyLong_FromLong(Ed.OptCornerFontSize); PROP_CORNER2_FONT_NAME: Result:= PyUnicodeFromString(Ed.OptCorner2FontName); PROP_CORNER2_FONT_SIZE: Result:= PyLong_FromLong(Ed.OptCorner2FontSize); PROP_BORDER_COLOR: Result:= PyLong_FromLong(Ed.OptBorderColor); PROP_BORDER_COLOR_WIDTH: Result:= PyLong_FromLong(Ed.OptBorderWidthWithColor); PROP_V_MODE: begin if Assigned(Frame) and (Frame.FrameKind=TAppFrameKind.BinaryViewer) then Num1:= Ord(Frame.Viewer.Mode) else Num1:= VMODE_NONE; Result:= PyLong_FromLong(Num1); end; PROP_V_POS: begin if not Assigned(Frame) then exit(ReturnNone); if Frame.FrameKind=TAppFrameKind.BinaryViewer then Result:= PyLong_FromLongLong(Frame.Viewer.PosOffset) else Result:= ReturnNone; end; PROP_V_SEL_START: begin if not Assigned(Frame) then exit(ReturnNone); if Frame.FrameKind=TAppFrameKind.BinaryViewer then Result:= PyLong_FromLongLong(Frame.Viewer.SelStart) else Result:= ReturnNone; end; PROP_V_SEL_LEN: begin if not Assigned(Frame) then exit(ReturnNone); if Frame.FrameKind=TAppFrameKind.BinaryViewer then Result:= PyLong_FromLongLong(Frame.Viewer.SelLength) else Result:= ReturnNone; end; PROP_V_WIDTH: begin if not Assigned(Frame) then exit(ReturnNone); if Frame.FrameKind=TAppFrameKind.BinaryViewer then Result:= PyLong_FromLong(Frame.Viewer.TextWidth) else Result:= ReturnNone; end; PROP_V_WIDTH_HEX: begin if not Assigned(Frame) then exit(ReturnNone); if Frame.FrameKind=TAppFrameKind.BinaryViewer then Result:= PyLong_FromLong(Frame.Viewer.TextWidthHex) else Result:= ReturnNone; end; PROP_V_WIDTH_UHEX: begin if not Assigned(Frame) then exit(ReturnNone); if Frame.FrameKind=TAppFrameKind.BinaryViewer then Result:= PyLong_FromLong(Frame.Viewer.TextWidthUHex) else Result:= ReturnNone; end; PROP_V_ENC: begin if not Assigned(Frame) then exit(ReturnNone); if Frame.FrameKind=TAppFrameKind.BinaryViewer then Result:= PyUnicodeFromString(cEncConvNames[Frame.Viewer.TextEncoding]) else Result:= ReturnNone; end else Result:= ReturnNone; end; end else Result:= ReturnNone; end; function api_ed_set_prop(Self, Args: PPyObject): PPyObject; cdecl; var H: Int64; Id: integer; Ptr: PChar; Str, Str1, Str2: string; Ed: TATSynEdit; Frame: TEditorFrame; An, AnOut: TecSyntAnalyzer; ValueBool: boolean; ValueInt: Int64; //ScrollInfo: TATEditorScrollInfo; TempGroup: TATGroups; TempPages, TempPagesTo: TATPages; NLocalGroup, NGlobalGroup, NTab, NIndexNew, N1, N2: integer; LineEnd: TATLineEnds; NCaptionReason: TAppTabCaptionReason; begin with AppPython.Engine do if Bool(PyArg_ParseTuple(Args, 'Lis:set_prop', @H, @Id, @Ptr)) then begin Ed:= PyHelper_EditorFromHandle(H); if Ed=nil then exit(ReturnNone); Frame:= TGroupsHelper.GetEditorFrame(Ed); Str:= string(Ptr); ValueBool:= AppStrToBool(Str); ValueInt:= StrToInt64Def(Str, 0); case Id of PROP_GUTTER_ALL: Ed.OptGutterVisible:= ValueBool; PROP_GUTTER_STATES: begin Ed.Gutter[Ed.Gutter.FindIndexByTag(ATEditorOptions.GutterTagLineStates)].Visible:= ValueBool; Include(Ed.ModifiedOptions, TATEditorModifiedOption.GutterLineStates); end; PROP_GUTTER_NUM: begin Ed.Gutter[Ed.Gutter.FindIndexByTag(ATEditorOptions.GutterTagNumbers)].Visible:= ValueBool; Include(Ed.ModifiedOptions, TATEditorModifiedOption.GutterNumbers); end; PROP_GUTTER_FOLD: begin Ed.Gutter[Ed.Gutter.FindIndexByTag(ATEditorOptions.GutterTagFolding)].Visible:= ValueBool; Include(Ed.ModifiedOptions, TATEditorModifiedOption.GutterFolding); end; PROP_GUTTER_BM: begin Ed.Gutter[Ed.Gutter.FindIndexByTag(ATEditorOptions.GutterTagBookmarks)].Visible:= ValueBool; Include(Ed.ModifiedOptions, TATEditorModifiedOption.GutterBookmarks); end; PROP_GUTTER_EMPTY: Ed.Gutter[Ed.Gutter.FindIndexByTag(ATEditorOptions.GutterTagEmpty)].Visible:= ValueBool; PROP_WRAP: begin Ed.OptWrapMode:= TATEditorWrapMode(ValueInt); Include(Ed.ModifiedOptions, TATEditorModifiedOption.WordWrap); end; PROP_RO: begin Ed.ModeReadOnly:= ValueBool; Include(Ed.ModifiedOptions, TATEditorModifiedOption.ReadOnly); end; PROP_TAB_SPACES: begin Ed.OptTabSpaces:= ValueBool; Include(Ed.ModifiedOptions, TATEditorModifiedOption.TabSpaces); end; PROP_TAB_SIZE: begin Ed.OptTabSize:= ValueInt; Include(Ed.ModifiedOptions, TATEditorModifiedOption.TabSize); end; PROP_TAB_SMART: begin Ed.OptTabSmart:= ValueBool; end; PROP_MARGIN: Ed.OptMarginRight:= ValueInt; PROP_MARGIN_STRING: Ed.OptMarginString:= Str; PROP_INSERT: Ed.ModeOverwrite:= not ValueBool; PROP_MODIFIED: begin Ed.Modified:= ValueBool; if Assigned(Frame) then Frame.UpdateModified(Ed); end; PROP_RULER: begin Ed.OptRulerVisible:= ValueBool; Include(Ed.ModifiedOptions, TATEditorModifiedOption.RulerVisible); end; PROP_LEXER_FILE: begin //for editors inside TEditorFrame if Assigned(Frame) then begin Frame.LexerName[Ed]:= Str; fmMain.UpdateStatusbar; end else //for other editors if Assigned(Ed.AdapterForHilite) then begin An:= AppManager.FindLexerByName(Str); //apply syntax theme if Assigned(An) then DoApplyLexerStylesMap(An, AnOut); (Ed.AdapterForHilite as TATAdapterEControl).Lexer:= An; Ed.DoEventChange(0); end; end; PROP_COLOR: begin SSplitByChar(Str, ',', Str1, Str2); N1:= StrToIntDef(Str2, -1); if N1<>-1 then EditorSetColorById(Ed, Str1, N1); end; PROP_LINE_TOP: begin Ed.LineTop:= ValueInt; end; PROP_LINE_NUMBERS: begin Ed.OptNumbersStyle:= TATEditorNumbersStyle(ValueInt); end; PROP_LINE_STATE: begin SSplitByChar(Str, ',', Str1, Str2); N1:= StrToIntDef(Str1, -1); N2:= StrToIntDef(Str2, -1); if Ed.Strings.IsIndexValid(N1) and (N2>=0) then Ed.Strings.LinesState[N1]:= TATLineState(N2); end; PROP_LINE_STATES_UPDATED: begin if Str='' then Ed.Strings.ClearLineStatesUpdated; end; PROP_GUTTER_EMPTY_WIDTH: Ed.OptGutterWidthEmpty:= ValueInt; PROP_GUTTER_BM_WIDTH: Ed.OptGutterWidthBookmarks:= ValueInt; PROP_GUTTER_STATES_WIDTH: Ed.OptGutterWidthLineStates:= ValueInt; PROP_GUTTER_FOLD_WIDTH: Ed.OptGutterWidthFolding:= ValueInt; PROP_ZEBRA: begin N1:= StrToIntDef(Str, -1); if N1=0 then Ed.OptZebraActive:= false else if N1>0 then begin Ed.OptZebraActive:= true; Ed.OptZebraAlphaBlend:= N1; end; end; PROP_ZEBRA_STEP: Ed.OptZebraStep:= Max(2, ValueInt); PROP_TAB_COLOR: begin if Assigned(Frame) then Frame.TabColor:= ValueInt; end; PROP_TAB_COLOR_FONT: begin if Assigned(Frame) then Frame.TabFontColor:= ValueInt; end; PROP_TAB_TITLE: begin if Assigned(Frame) then begin if Str<>'' then begin Frame.TabCaptionReason:= TAppTabCaptionReason.FromPlugin; Frame.TabCaption:= Str; end else begin if Frame.TabCaptionReason=TAppTabCaptionReason.FromPlugin then begin if Frame.FileName<>'' then begin Frame.TabCaptionReason:= TAppTabCaptionReason.FromFilename; Frame.UpdateCaptionFromFilename; end else begin Frame.TabCaption:= fmMain.GetUntitledNumberedCaption; Frame.TabCaptionReason:= TAppTabCaptionReason.Unsaved; end; end; end; end; end; PROP_TAB_TITLE_REASON: begin if Assigned(Frame) then if ConvertStringToTabCaptionReason(Str, NCaptionReason) then Frame.TabCaptionReason:= NCaptionReason; end; PROP_TAB_PINNED: begin if Assigned(Frame) then Frame.TabPinned:= ValueBool; end; PROP_TAB_UI_SHOW: begin if Assigned(Frame) then Frame.TabVisible:= ValueBool; end; PROP_ENC: begin if Assigned(Frame) then fmMain.SetFrameEncoding(Ed, AppEncodingShortnameToFullname(Str), false) else Ed.EncodingName:= AppEncodingShortnameToFullname(Str); end; PROP_ENC_RELOAD: begin if Assigned(Frame) then fmMain.SetFrameEncoding(Ed, AppEncodingShortnameToFullname(Str), true); end; PROP_NEWLINE: begin if Str='lf' then LineEnd:= TATLineEnds.Unix else if Str='crlf' then LineEnd:= TATLineEnds.Windows else if Str='cr' then LineEnd:= TATLineEnds.Mac else LineEnd:= TATLineEnds.None; if LineEnd<>TATLineEnds.None then begin if Assigned(Frame) then fmMain.UpdateFrameLineEnds(Frame, Ed, LineEnd) else begin Ed.Strings.Endings:= LineEnd; Ed.Update; end; end; end; PROP_TAG: Ed.TagString:= Str; PROP_UNPRINTED_SHOW: begin Ed.OptUnprintedVisible:= ValueBool; Include(Ed.ModifiedOptions, TATEditorModifiedOption.UnprintedVisible); end; PROP_UNPRINTED_SPACES: begin Ed.OptUnprintedSpaces:= ValueBool; Include(Ed.ModifiedOptions, TATEditorModifiedOption.UnprintedSpaces); end; PROP_UNPRINTED_SPACES_TRAILING: begin Ed.OptUnprintedSpacesTrailing:= ValueBool; Include(Ed.ModifiedOptions, TATEditorModifiedOption.UnprintedTrailingOnly); end; PROP_UNPRINTED_ENDS: begin Ed.OptUnprintedEnds:= ValueBool; Include(Ed.ModifiedOptions, TATEditorModifiedOption.UnprintedEnds); end; PROP_UNPRINTED_WRAPS: begin Ed.OptUnprintedWraps:= ValueBool; Include(Ed.ModifiedOptions, TATEditorModifiedOption.UnprintedWraps); end; PROP_UNPRINTED_END_DETAILS: begin Ed.OptUnprintedEndsDetails:= ValueBool; Include(Ed.ModifiedOptions, TATEditorModifiedOption.UnprintedEndDetails); end; PROP_TAB_ICON: begin if Assigned(Frame) then Frame.TabImageIndex:= ValueInt; end; PROP_TAB_COLLECT_MARKERS: begin if Assigned(Frame) then Frame.TabKeyCollectMarkers:= ValueBool; end; PROP_INDEX_GROUP: begin if Assigned(Frame) then begin NIndexNew:= ValueInt; GetFrameLocation(Frame, TempGroup, TempPages, NLocalGroup, NGlobalGroup, NTab); if (NTab>=0) and (NGlobalGroup<>NIndexNew) then begin TempPagesTo:= TGroupsHelper.GetPagesOfGroupIndex(NIndexNew, true{AShowFloatingGroup}); if Assigned(TempPagesTo) then TempGroup.MoveTab(TempPages, NTab, TempPagesTo, -1, true); end; end; end; PROP_INDEX_TAB: begin if Assigned(Frame) then begin NIndexNew:= ValueInt; GetFrameLocation(Frame, TempGroup, TempPages, NLocalGroup, NGlobalGroup, NTab); if NTab>=0 then begin TempPages.Tabs.MoveTab(NTab, NIndexNew, true); fmMain.DoPyEvent(Ed, TAppPyEvent.OnTabMove, []); end; end; end; PROP_CARET_VIEW: begin EditorCaretShapeFromPyTuple(Ed.CaretShapeNormal, Str); Include(Ed.ModifiedOptions, TATEditorModifiedOption.CaretShapeNormal); end; PROP_CARET_VIEW_OVR: begin EditorCaretShapeFromPyTuple(Ed.CaretShapeOverwrite, Str); Include(Ed.ModifiedOptions, TATEditorModifiedOption.CaretShapeOverwrite); end; PROP_CARET_VIEW_RO: begin EditorCaretShapeFromPyTuple(Ed.CaretShapeReadonly, Str); Include(Ed.ModifiedOptions, TATEditorModifiedOption.CaretShapeReadonly); end; PROP_CARET_VIRTUAL: Ed.OptCaretVirtual:= ValueBool; PROP_CARET_STOP_UNFOCUSED: Ed.OptCaretStopUnfocused:= ValueBool; PROP_MINIMAP: begin Ed.OptMinimapVisible:= ValueBool; Include(Ed.ModifiedOptions, TATEditorModifiedOption.MinimapVisible); end; PROP_MINIMAP_CHAR_WIDTH: Ed.OptMinimapCharWidth:= ValueInt; PROP_MINIMAP_AT_LEFT: Ed.OptMinimapAtLeft:= ValueBool; PROP_MINIMAP_SCALE: Ed.OptMinimapCustomScale:= ValueInt; PROP_MICROMAP: begin Ed.OptMicromapVisible:= ValueBool; Include(Ed.ModifiedOptions, TATEditorModifiedOption.MicromapVisible); end; PROP_MICROMAP_WIDTH: Ed.OptMicromapWidthInAvgChars:= ValueInt; PROP_MICROMAP_ON_SCROLLBAR: Ed.OptMicromapOnScrollbar:= ValueBool; PROP_MICROMAP_AT_LEFT: Ed.OptMicromapAtLeft:= ValueBool; PROP_SCROLL_VERT_INFO: begin EditorStringToScrollInfo(Ed, Str, true); end; PROP_SCROLL_HORZ_INFO: begin EditorStringToScrollInfo(Ed, Str, false); end; PROP_SCALE_FONT: Ed.OptScaleFont:= ValueInt; PROP_LAST_LINE_ON_TOP: begin Ed.OptLastLineOnTop:= ValueBool; Include(Ed.ModifiedOptions, TATEditorModifiedOption.LastLineOnTop); end; PROP_FOCUSED: begin if ValueBool then PyHelper_EditorFocus(Ed); end; PROP_HILITE_CUR_COL: Ed.OptShowCurColumn:= ValueBool; PROP_HILITE_CUR_LINE: Ed.OptShowCurLine:= ValueBool; PROP_HILITE_CUR_LINE_MINIMAL: Ed.OptShowCurLineMinimal:= ValueBool; PROP_HILITE_CUR_LINE_IF_FOCUS: Ed.OptShowCurLineOnlyFocused:= ValueBool; PROP_CODETREE: begin if Assigned(Frame) then Frame.EnabledCodeTree[Ed]:= ValueBool; end; PROP_EDITORS_LINKED: begin if Assigned(Frame) then Frame.EditorsLinked:= ValueBool; end; PROP_ONE_LINE: Ed.ModeOneLine:= ValueBool; PROP_FN: begin if Assigned(Frame) then begin Frame.NotifEnabled:= false; Frame.SetFileName(Ed, Str); Frame.UpdateCaptionFromFilename; Frame.DoLexerFromFilename(Ed, Str); Frame.NotifEnabled:= Str<>''; if Frame.Visible then fmMain.UpdateStatusbar; end else Ed.FileName:= Str; end; PROP_INDENT_SIZE: Ed.OptIndentSize:= ValueInt; PROP_INDENT_KEEP_ALIGN: Ed.OptIndentKeepsAlign:= ValueBool; PROP_INDENT_AUTO: Ed.OptAutoIndent:= ValueBool; PROP_INDENT_KIND: Ed.OptAutoIndentKind:= TATEditorAutoIndentKind(ValueInt); PROP_MARKED_RANGE: begin SSplitByChar(Str, ',', Str1, Str2); N1:= StrToIntDef(Str1, -1); N2:= StrToIntDef(Str2, -1); Ed.DoSetMarkedLines(N1, N2); end; PROP_MODERN_SCROLLBAR: begin Ed.OptScrollbarsNew:= ValueBool; Include(Ed.ModifiedOptions, TATEditorModifiedOption.ModernScrollbar); end; PROP_SAVE_HISTORY: begin if Assigned(Frame) then Frame.SaveHistory:= ValueBool; end; PROP_PREVIEW: begin if Assigned(Frame) then Frame.TabIsPreview:= ValueBool; end; PROP_UNDO_GROUPED: Ed.OptUndoGrouped:= ValueBool; PROP_UNDO_LIMIT: Ed.OptUndoLimit:= ValueInt; PROP_UNDO_DATA: Ed.UndoAsString:= Str; PROP_REDO_DATA: Ed.RedoAsString:= Str; PROP_SPLIT: begin if Assigned(Frame) then begin SSplitByChar(Str, ',', Str1, Str2); Frame.Splitted:= Str1<>'-'; Frame.SplitHorz:= Str1='h'; Frame.SplitPos:= StrToIntDef(Str2, 500)/1000; end; end; PROP_SAVING_FORCE_FINAL_EOL: begin Ed.OptSavingForceFinalEol:= ValueBool; Include(Ed.ModifiedOptions, TATEditorModifiedOption.SavingForceFinalEol); end; PROP_SAVING_TRIM_SPACES: begin Ed.OptSavingTrimSpaces:= ValueBool; Include(Ed.ModifiedOptions, TATEditorModifiedOption.SavingTrimSpaces); end; PROP_SAVING_TRIM_FINAL_EMPTY_LINES: begin Ed.OptSavingTrimFinalEmptyLines:= ValueBool; Include(Ed.ModifiedOptions, TATEditorModifiedOption.SavingTrimFinalEmptyLines); end; PROP_FOLD_TOOLTIP_SHOW: Ed.OptFoldTooltipVisible:= ValueBool; PROP_FOLD_ALWAYS: Ed.OptGutterShowFoldAlways:= ValueBool; PROP_FOLD_ICONS: Ed.OptGutterIcons:= TATEditorGutterIcons(ValueInt); PROP_SCROLLSTYLE_HORZ: Ed.OptScrollStyleHorz:= TATEditorScrollbarStyle(ValueInt); PROP_SCROLLSTYLE_VERT: Ed.OptScrollStyleVert:= TATEditorScrollbarStyle(ValueInt); PROP_LINKS_SHOW: Ed.OptShowURLs:= ValueBool; PROP_LINKS_REGEX: Ed.OptShowURLsRegex:= Str; PROP_LINKS_CLICKS: begin Ed.OptMouseClickOpensURL:= ValueInt=1; Ed.OptMouse2ClickOpensURL:= ValueInt=2; end; PROP_THEMED: Ed.OptThemed:= ValueBool; PROP_COMBO_ITEMS: begin if Ed is TATComboEdit then TATComboEdit(Ed).Items.Text:= Str; end; PROP_CODETREE_SUBLEXER: begin if Ed.AdapterForHilite is TATAdapterEControl then (Ed.AdapterForHilite as TATAdapterEControl).EnabledSublexerTreeNodes:= ValueBool; end; PROP_FONT: begin EditorSetFont(Ed.Font, Str); Ed.OptForceSeparateCharSizer:= true; end; PROP_FONT_B: begin EditorSetFont(Ed.FontBold, Str); end; PROP_FONT_I: begin EditorSetFont(Ed.FontItalic, Str); end; PROP_FONT_BI: begin EditorSetFont(Ed.FontBoldItalic, Str); end; PROP_WHEEL_ZOOMS: Ed.OptMouseWheelZooms:= ValueBool; PROP_MASKCHAR: begin if Str<>'' then Ed.OptMaskChar:= UTF8Decode(Str)[1]; end; PROP_MASKCHAR_USED: Ed.OptMaskCharUsed:= ValueBool; PROP_NUMBERS_ONLY: Ed.OptInputNumberOnly:= ValueBool; PROP_NUMBERS_NEGATIVE: Ed.OptInputNumberAllowNegative:= ValueBool; PROP_COMMAND_LOG_LIMIT: Ed.CommandLog.MaxCount:= ValueInt; PROP_DIM_UNFOCUSED: Ed.OptDimUnfocusedBack:= ValueInt; PROP_CARET_MULTI: Ed.OptCaretManyAllowed:= ValueBool; PROP_RULER_TEXT: Ed.OptRulerText:= Str; PROP_LINE_SPACE1: Ed.OptSpacingTop:= ValueInt; PROP_LINE_SPACE2: Ed.OptSpacingBottom:= ValueInt; PROP_CORNER_TEXT: Ed.OptCornerText:= Str; PROP_CORNER_COLOR_FONT: Ed.OptCornerColorFont:= ValueInt; PROP_CORNER_COLOR_BACK: Ed.OptCornerColorBack:= ValueInt; PROP_CORNER_COLOR_BORDER: Ed.OptCornerColorBorder:= ValueInt; PROP_CORNER2_TEXT: Ed.OptCorner2Text:= Str; PROP_CORNER2_COLOR_FONT: Ed.OptCorner2ColorFont:= ValueInt; PROP_CORNER2_COLOR_BACK: Ed.OptCorner2ColorBack:= ValueInt; PROP_CORNER2_COLOR_BORDER: Ed.OptCorner2ColorBorder:= ValueInt; PROP_CORNER_FONT_NAME: Ed.OptCornerFontName:= Str; PROP_CORNER_FONT_SIZE: Ed.OptCornerFontSize:= ValueInt; PROP_CORNER2_FONT_NAME: Ed.OptCorner2FontName:= Str; PROP_CORNER2_FONT_SIZE: Ed.OptCorner2FontSize:= ValueInt; PROP_BORDER_COLOR: Ed.OptBorderColor:= ValueInt; PROP_BORDER_COLOR_WIDTH: Ed.OptBorderWidthWithColor:= ValueInt; PROP_V_MODE: begin if not Assigned(Frame) then exit(ReturnNone); if ValueInt=VMODE_NONE then begin if Frame.FrameKind=TAppFrameKind.BinaryViewer then begin Str:= Frame.FileName; Frame.DoFileClose; Frame.DoFileOpen(Str, '', false, false, true, true, true, false, TAppOpenMode.Editor); end; end else if (ValueInt>=0) and (ValueInt<=Ord(High(TATBinHexMode))) then begin if Frame.FrameKind=TAppFrameKind.BinaryViewer then Frame.Viewer.Mode:= TATBinHexMode(ValueInt) else begin if Frame.EditorsLinked and (Frame.FileName<>'') then begin Str:= Frame.FileName; Frame.DoFileClose; Frame.DoFileOpen_AsBinary(Str, TATBinHexMode(ValueInt)); end; end; end; end; PROP_V_POS: begin if not Assigned(Frame) then exit(ReturnNone); if Frame.FrameKind=TAppFrameKind.BinaryViewer then Frame.Viewer.PosOffset:= ValueInt; end; PROP_V_SEL_START: begin if not Assigned(Frame) then exit(ReturnNone); if Frame.FrameKind=TAppFrameKind.BinaryViewer then Frame.Viewer.SetSelection( ValueInt, Frame.Viewer.SelLength, false); end; PROP_V_SEL_LEN: begin if not Assigned(Frame) then exit(ReturnNone); if Frame.FrameKind=TAppFrameKind.BinaryViewer then Frame.Viewer.SetSelection( Frame.Viewer.SelStart, ValueInt, false); end; PROP_V_WIDTH: begin if not Assigned(Frame) then exit(ReturnNone); if Frame.FrameKind=TAppFrameKind.BinaryViewer then begin Frame.Viewer.TextWidth:= ValueInt; Frame.Viewer.Invalidate; end; end; PROP_V_WIDTH_HEX: begin if not Assigned(Frame) then exit(ReturnNone); if Frame.FrameKind=TAppFrameKind.BinaryViewer then begin Frame.Viewer.TextWidthHex:= ValueInt; Frame.Viewer.Invalidate; end; end; PROP_V_WIDTH_UHEX: begin if not Assigned(Frame) then exit(ReturnNone); if Frame.FrameKind=TAppFrameKind.BinaryViewer then begin Frame.Viewer.TextWidthUHex:= ValueInt; Frame.Viewer.Invalidate; end; end; PROP_V_ENC: begin if not Assigned(Frame) then exit(ReturnNone); if Frame.FrameKind=TAppFrameKind.BinaryViewer then begin Frame.Viewer.TextEncoding:= EncConvFindEncoding(Str); Frame.Viewer.Invalidate; fmMain.UpdateStatusbar; end; end; end; Ed.Update; Result:= ReturnNone; end else Result:= ReturnNone; end; function PyHelper_CommandList: PPyObject; cdecl; var Item, ItemInitial: TATKeymapItem; ItemPlugin: TAppCommandInfo; NLen, i: Integer; SKeyInit1, SKeyInit2: string; begin //AppKeymapInitial must be inited the _same way_ as AppKeymapMain if not Assigned(AppKeymapInitial) then begin AppKeymapInitial:= TATKeymap.Create; InitKeymapFull(AppKeymapInitial); Keymap_AddCudatextItems(AppKeymapInitial); end; with AppPython.Engine do begin NLen:= AppKeymapMain.Count; Result:= PyList_New(NLen); if not Assigned(Result) then raise EPythonError.Create(msgPythonListError); for i:= 0 to NLen-1 do begin Item:= AppKeymapMain[i]; case TPluginHelper.CommandCategory(Item.Command) of TAppCommandCategory.Lexer: begin PyList_SetItem(Result, i, Py_BuildValue('{sssissssssssss}', 'type', 'lexer', 'cmd', Item.Command, 'name', PChar(Item.Name), 'key1', '', 'key2', '', 'key1_init', '', 'key2_init', '' )); end; TAppCommandCategory.Plugin: begin ItemPlugin:= TAppCommandInfo(AppCommandList[Item.Command-cmdFirstPluginCommand]); PyList_SetItem(Result, i, Py_BuildValue('{sssisssssssssssssssOssss}', 'type', 'plugin', 'cmd', Item.Command, 'name', PChar(Item.Name), 'key1', PChar(Item.Keys1.ToString), 'key2', PChar(Item.Keys2.ToString), 'p_module', PChar(ItemPlugin.ItemModule), 'p_method', PChar(ItemPlugin.ItemProc), 'p_method_params', PChar(ItemPlugin.ItemProcParam), 'p_lexers', PChar(ItemPlugin.ItemLexers), 'p_from_api', Py_False, 'p_caption', PChar(ItemPlugin.ItemCaption), 'p_in_menu', PChar(ItemPlugin.ItemInMenu) )); end; TAppCommandCategory.PluginSub: begin ItemPlugin:= TAppCommandInfo(AppCommand2List[Item.Command-cmdFirstPluginSubCommand]); PyList_SetItem(Result, i, Py_BuildValue('{sssisssssssssssssssOssss}', 'type', 'plugin', 'cmd', Item.Command, 'name', PChar(Item.Name), 'key1', PChar(Item.Keys1.ToString), 'key2', PChar(Item.Keys2.ToString), 'p_module', PChar(ItemPlugin.ItemModule), 'p_method', PChar(ItemPlugin.ItemProc), 'p_method_params', PChar(ItemPlugin.ItemProcParam), 'p_lexers', PChar(ItemPlugin.ItemLexers), 'p_from_api', Py_True, 'p_caption', PChar(ItemPlugin.ItemCaption), 'p_in_menu', PChar(ItemPlugin.ItemInMenu) )); end; TAppCommandCategory.Normal: begin SKeyInit1:= ''; SKeyInit2:= ''; if AppKeymapInitial.IsIndexValid(i) then begin ItemInitial:= AppKeymapInitial[i]; SKeyInit1:= ItemInitial.Keys1.ToString; SKeyInit2:= ItemInitial.Keys2.ToString; end; PyList_SetItem(Result, i, Py_BuildValue('{sssissssssssss}', 'type', 'cmd', 'cmd', Item.Command, 'name', PChar(Item.Name), 'key1', PChar(Item.Keys1.ToString), 'key2', PChar(Item.Keys2.ToString), 'key1_init', PChar(SKeyInit1), 'key2_init', PChar(SKeyInit2) )); end; TAppCommandCategory.OpenedFile: begin PyList_SetItem(Result, i, Py_BuildValue('{sssissssssssss}', 'type', 'openedfile', 'cmd', Item.Command, 'name', PChar(Item.Name), 'key1', '', 'key2', '', 'key1_init', '', 'key2_init', '' )); end; TAppCommandCategory.RecentFile: begin PyList_SetItem(Result, i, Py_BuildValue('{sssissssssssss}', 'type', 'recentfile', 'cmd', Item.Command, 'name', PChar(Item.Name), 'key1', '', 'key2', '', 'key1_init', '', 'key2_init', '' )); end; end; end end; end; function PyHelper_EnumSidebar(AToolbar: TATFlatToolbar; APanelHost: TAppPanelHost): PPyObject; var NCount, NPanelIndex, i: integer; NHandle: Int64; SModule, SMethod: string; Btn: TATButton; PanelItem: TAppPanelItem; begin with AppPython.Engine do begin NCount:= AToolbar.ButtonCount; Result:= PyList_New(NCount); for i:= 0 to NCount-1 do begin Btn:= AToolbar.Buttons[i]; SModule:= ''; SMethod:= ''; NHandle:= 0; NPanelIndex:= APanelHost.CaptionToPanelIndex(Btn.Caption); if NPanelIndex>=0 then begin PanelItem:= TAppPanelItem(APanelHost.Panels[NPanelIndex]); SModule:= PanelItem.ItemPyModule; SMethod:= PanelItem.ItemPyMethod; NHandle:= Int64(PtrInt(PanelItem.ItemControl)); end; PyList_SetItem(Result, i, Py_BuildValue('{sssssLsisssssL}', 'cap', PChar(Btn.Caption), 'hint', PChar(Btn.Hint), 'dlg', NHandle, 'img', Btn.ImageIndex, 'module', PChar(SModule), 'method', PChar(SMethod), 'btn_h', Int64(PtrInt(Btn)) )); end; end; end; function api_app_proc_AddPanelDialog(const AStr: string; APanelId: TAppPanelId): boolean; var Sep: TATStringSeparator; StrCaption, StrControl, StrIconFilename: string; PanelObj: TObject; begin Sep.Init(AStr); Sep.GetItemStr(StrCaption); Sep.GetItemStr(StrControl); Sep.GetItemStr(StrIconFilename); PanelObj:= TObject(PtrInt(StrToInt64Def(StrControl, 0))); if PanelObj<>nil then if not (PanelObj is TCustomControl) then exit(false); fmMain.DisableAutoSizing; //fix horizontal twitch of main Groups Result:= AppPanels[APanelId].AddPanel( StrCaption, fmMain.DoSidebar_FilenameToImageIndex(StrCaption, StrIconFilename), TCustomControl(PanelObj), nil ); fmMain.EnableAutoSizing; end; function api_app_proc(Self, Args: PPyObject): PPyObject; cdecl; var Id, i: integer; Ptr: PChar; Str, Str1, Str2, Str3: string; StrCaption, StrFilename, StrCmd, StrIndex: string; SplitVert, SplitVisible, ok: boolean; SplitPos, SplitTotal: integer; ClipExData: TATEditorClipboardExData; Params: TAppVariantArray; ParamBool: boolean; ParamRect: TRect; Num64: Int64; Pnt: TPoint; Sep: TATStringSeparator; SList: TStringList; begin with AppPython.Engine do if Bool(PyArg_ParseTuple(Args, 'is:app_proc', @Id, @Ptr)) then begin Str:= string(Ptr); ParamBool:= AppStrToBool(Str); case Id of APP_PROC_GET_CLIP: begin Str:= Clipboard.AsText; Result:= PyUnicodeFromString(Str); end; APP_PROC_SET_CLIP: begin SClipboardCopy(Str); Result:= ReturnNone; end; APP_PROC_SET_CLIP_ALT: begin SClipboardCopy(Str, PrimarySelection); //for Unix Result:= ReturnNone; end; APP_PROC_SET_CLIP_HTML: begin Clipboard.SetAsHtml(Str); Result:= ReturnNone; end; APP_PROC_GET_CLIP_EX: begin ATEditorGetClipboardExData(ClipExData); //we get more info than ATEditorGetClipboardExData gives, //so always return Dict, even if clipboard is empty Result:= Py_BuildValue('{sOsOsisisisssLsLsL}', 'is_column', PyBool_FromLong(Ord(Clipboard.HasFormat(ATEditorOptions.ClipboardColumnFormat))), 'caret_pos', PyHelper_Rect(ClipExData.CaretPos), 'caret_count', ClipExData.CaretCount, 'indent_chars', ClipExData.FirstLineIndentChars, 'indent_columns', ClipExData.FirstLineIndentColumns, 'file_name', PChar(string(ClipExData.FileName)), 'version', ClipExData.ModifiedVersion, 'tick_on_copy', ClipExData.TickOnCopy, 'tick_current', GetTickCount64 ); end; APP_PROC_CLIP_ENUM: begin Result:= PyUnicodeFromString(AppClipboardFormatsAsString); end; APP_PROC_CLIP_SAVE_PIC: begin ok:= AppClipboardSavePictureToFile(Str); Result:= PyBool_FromLong(Ord(ok)); end; APP_PROC_GET_COMMANDS: begin TKeymapHelperMain.UpdateDynamic(TAppCommandCategory.Lexer); TKeymapHelperMain.UpdateDynamic(TAppCommandCategory.OpenedFile); TKeymapHelperMain.UpdateDynamic(TAppCommandCategory.RecentFile); Result:= PyHelper_CommandList; end; APP_PROC_IDLE: begin Application.ProcessMessages; Application.Idle(ParamBool); Result:= ReturnNone; end; APP_PROC_GET_COMPILER_INFO: begin Result:= Py_BuildValue('{ssssssss}', 'os', PChar(LowerCase({$I %FPCTARGETOS%})), 'cpu', PChar({$I %FPCTARGETCPU%}), 'widgetset', PChar(GetLCLWidgetTypeName), 'fpc', PChar({$I %FPCVersion%}) ); end; APP_PROC_SAVE_SESSION: begin Sep.Init(Str, ';'); Sep.GetItemStr(StrFilename); Sep.GetItemStr(StrCmd); //do session backups, when Auto Save plugin saves _default_ session if IsDefaultSession(StrFilename) then fmMain.DoOps_SaveSessionsBackups(StrFilename); ParamBool:= fmMain.DoOps_SaveSession( StrFilename, Pos('n', StrCmd)=0, //ASaveModifiedFiles Pos('u', StrCmd)=0, //ASaveUntitlesTabs Pos('t', StrCmd)>0 //AByTimer ); Result:= PyBool_FromLong(Ord(ParamBool)); end; APP_PROC_LOAD_SESSION: begin ParamBool:= fmMain.DoOps_LoadSession(Str, true); Result:= PyBool_FromLong(Ord(ParamBool)); end; APP_PROC_SET_SESSION: begin AppSessionName_Set(Str); fmMain.UpdateCaption; fmMain.DoOps_SaveCurrentSessionName; Result:= ReturnNone; end; APP_PROC_SET_FOLDER: begin PyCurrentProjectFolder:= Str; Result:= ReturnNone; end; APP_PROC_SET_SUBCOMMANDS: begin TPluginHelper.CommandUpdateSubcommands(Str); TKeymapHelperMain.UpdateDynamic(TAppCommandCategory.PluginSub); fmMain.FNeedAppState_SubCommands:= true; Result:= ReturnNone; end; APP_PROC_GET_LAST_PLUGIN: begin Str:= AppPython.LastCommandModule+','+AppPython.LastCommandMethod; if AppPython.LastCommandParam<>'' then Str+= ','+AppPython.LastCommandParam; Result:= PyUnicodeFromString(Str); end; APP_PROC_GET_GROUPING: begin Result:= PyLong_FromLong(Ord(fmMain.GroupsMain.Mode)); end; APP_PROC_SET_GROUPING: begin fmMain.UpdateGroupsMode(TATGroupsMode(StrToIntDef(Str, 1))); fmMain.UpdateStatusbar; Result:= ReturnNone; end; APP_PROC_GET_OS_SUFFIX: begin Result:= PyUnicodeFromString(cOptionSystemSuffix); end; APP_PROC_EXEC_PYTHON: begin AppPython.Exec(Str); Result:= ReturnNone; end; APP_PROC_EXEC_PLUGIN: begin Sep.Init(Str); Sep.GetItemStr(Str1); Sep.GetItemStr(Str2); Sep.GetRest(Str3); if Str3<>'' then Params:= [AppVariant(Str3)] else Params:= []; fmMain.DoPyCommand(Str1, Str2, Params, TATCommandInvoke.AppAPI); Result:= ReturnNone; end; APP_PROC_GET_ESCAPE: begin Result:= PyBool_FromLong(Ord(PyEscapeFlag or Application.Terminated)); end; APP_PROC_SET_ESCAPE: begin PyEscapeFlag:= ParamBool; Result:= ReturnNone; end; APP_PROC_PARSE_COMMAND_LINE: begin fmMain.DoLoadCommandLine_FromString(Str); Result:= ReturnNone; end; APP_PROC_EVENTS_SUB: begin TPluginHelper.ApiSub(Str); Result:= ReturnNone; end; APP_PROC_EVENTS_UNSUB: begin TPluginHelper.ApiUnsub(Str); Result:= ReturnNone; end; APP_PROC_EVENTS_ENUM: begin Result:= PyHelper_GetEvents(Str); end; APP_PROC_GET_FINDER_PROP: begin Result:= fmMain.FindDialog_GetOptionsPyDict; end; APP_PROC_SET_FINDER_PROP: begin fmMain.FindDialog_ApplyOptionsString(Str); Result:= ReturnNone; end; APP_PROC_GET_FINDER_HANDLES: begin Result:= fmMain.FindDialog_GetButtonsPyDict; end; APP_PROC_GET_GUI_HEIGHT: begin i:= DoControl_GetAutoHeight(Str); if i>0 then Result:= PyLong_FromLong(i) else Result:= ReturnNone; end; APP_PROC_GET_SYSTEM_PPI: begin Result:= PyLong_FromLong(Screen.PixelsPerInch); end; APP_PROC_PROGRESSBAR: begin Num64:= StrToIntDef(Str, -1); if Num64<0 then fmMain.UpdateGlobalProgressbar(0, false) else fmMain.UpdateGlobalProgressbar(Num64, true); Result:= ReturnNone; end; APP_PROC_GET_TAB_IMAGELIST: begin Result:= PyHelper_ObjectHandle(fmMain.ImageListTabs); end; APP_PROC_GET_CONSOLE_FORM: begin if Assigned(fmConsole) then Result:= PyHelper_ObjectHandle(fmConsole) else Result:= ReturnNone; end; APP_PROC_GET_OUTPUT_FORM: begin if Assigned(fmOutput) then Result:= PyHelper_ObjectHandle(fmOutput) else Result:= ReturnNone; end; APP_PROC_GET_VALIDATE_FORM: begin if Assigned(fmValidate) then Result:= PyHelper_ObjectHandle(fmValidate) else Result:= ReturnNone; end; APP_PROC_GET_CODETREE: begin Result:= PyHelper_ObjectHandle(fmMain.CodeTree); end; APP_PROC_GET_CODETREE_CURRENT_NODE: begin Result:= PyHelper_ObjectHandle(fmMain.CodeTree_CurrentNode); end; APP_PROC_GET_CODETREE_FILTER: begin Result:= PyHelper_ObjectHandle(fmMain.CodeTreeFilterInput); end; APP_PROC_WINDOW_TOPMOST_GET: begin Result:= PyBool_FromLong(Ord(fmMain.FormStyle=fsSystemStayOnTop)); end; APP_PROC_WINDOW_TOPMOST_SET: begin if ParamBool then fmMain.FormStyle:= fsSystemStayOnTop else fmMain.FormStyle:= fsNormal; Result:= ReturnNone; end; APP_PROC_GET_MAIN_TOOLBAR: begin Result:= PyHelper_ObjectHandle(fmMain.ToolbarMain); end; APP_PROC_GET_MAIN_STATUSBAR: begin Result:= PyHelper_ObjectHandle(fmMain.StatusbarMain); end; //------------------- APP_PROC_SIDEPANEL_ADD_DIALOG: begin ok:= api_app_proc_AddPanelDialog(Str, TAppPanelId.Side); Result:= PyBool_FromLong(Ord(ok)); end; APP_PROC_SIDEPANEL_SET_PROP: begin Sep.Init(Str); Sep.GetItemStr(StrCaption); //caption Sep.GetItemInt(i, -1); //imageindex Sep.GetItemStr(StrIndex); //hint ok:= AppPanels[TAppPanelId.Side].SetPanelProps(StrCaption, i, StrIndex); Result:= PyBool_FromLong(Ord(ok)); end; APP_PROC_SIDEPANEL_REMOVE: begin StrCaption:= Str; ok:= AppPanels[TAppPanelId.Side].DeletePanel(StrCaption); Result:= PyBool_FromLong(Ord(ok)); end; APP_PROC_SIDEPANEL_ACTIVATE: begin SSplitByChar(Str, ',', Str1, Str2); ok:= AppPanels[TAppPanelId.Side].UpdatePanels(Str1, AppStrToBool(Str2), true); Result:= PyBool_FromLong(Ord(ok)); end; APP_PROC_SIDEPANEL_ENUM_ALL: begin Result:= PyHelper_EnumSidebar(fmMain.ToolbarSideTop, AppPanels[TAppPanelId.Side]); end; APP_PROC_SIDEPANEL_GET_CONTROL: begin Num64:= AppPanels[TAppPanelId.Side].CaptionToControlHandle(Str); if Num64<>0 then Result:= PyLong_FromLongLong(Num64) else Result:= ReturnNone; end; APP_PROC_SIDEPANEL_GET: begin Str:= AppPanels[TAppPanelId.Side].LastActivePanel; Result:= PyUnicodeFromString(Str); end; APP_PROC_SIDEPANEL_GET_IMAGELIST: begin Result:= PyHelper_ObjectHandle(fmMain.ImageListSide); end; //------------------- APP_PROC_BOTTOMPANEL_GET_CONTROL: begin Num64:= AppPanels[TAppPanelId.Btm].CaptionToControlHandle(Str); if Num64<>0 then Result:= PyLong_FromLongLong(Num64) else Result:= ReturnNone; end; APP_PROC_BOTTOMPANEL_ADD_DIALOG: begin ok:= api_app_proc_AddPanelDialog(Str, TAppPanelId.Btm); Result:= PyBool_FromLong(Ord(ok)); end; APP_PROC_BOTTOMPANEL_SET_PROP: begin Sep.Init(Str); Sep.GetItemStr(StrCaption); //caption Sep.GetItemInt(i, -1); //imageindex Sep.GetItemStr(StrIndex); //hint ok:= AppPanels[TAppPanelId.Btm].SetPanelProps(StrCaption, i, StrIndex); Result:= PyBool_FromLong(Ord(ok)); end; APP_PROC_BOTTOMPANEL_REMOVE: begin StrCaption:= Str; ok:= AppPanels[TAppPanelId.Btm].DeletePanel(StrCaption); Result:= PyBool_FromLong(Ord(ok)); end; APP_PROC_BOTTOMPANEL_ACTIVATE: begin SSplitByChar(Str, ',', Str1, Str2); ok:= AppPanels[TAppPanelId.Btm].UpdatePanels(Str1, AppStrToBool(Str2), true); Result:= PyBool_FromLong(Ord(ok)); end; APP_PROC_BOTTOMPANEL_ENUM_ALL: begin Result:= PyHelper_EnumSidebar(fmMain.ToolbarSideLow, AppPanels[TAppPanelId.Btm]); end; APP_PROC_BOTTOMPANEL_GET: begin Str:= AppPanels[TAppPanelId.Btm].LastActivePanel; Result:= PyUnicodeFromString(Str); end; //------------------- APP_PROC_GET_LANG: begin Str:= UiOps.LangName; Str:= Copy(Str, 1, 5); //trim suffix like '_4' in 'it_IT_4' Result:= PyUnicodeFromString(Str); end; APP_PROC_GET_HOTKEY: begin Result:= PyUnicodeFromString(TKeymapHelper.GetHotkey(AppKeymapMain, Str)); end; APP_PROC_SET_HOTKEY: begin Result:= PyBool_FromLong(Ord(TKeymapHelper.SetHotkey(AppKeymapMain, Str, true))); end; APP_PROC_GET_KEYSTATE: begin Str:= ConvertShiftStateToString(ConvertKeyboardStateToShiftState); Result:= PyUnicodeFromString(Str); end; APP_PROC_THEME_UI_GET: begin Result:= PyUnicodeFromString(UiOps.ThemeUi); end; APP_PROC_THEME_UI_SET: begin fmMain.UpdateThemes(Str, '?'); Result:= ReturnNone; end; APP_PROC_THEME_SYNTAX_GET: begin Result:= PyUnicodeFromString(UiOps.ThemeSyntax); end; APP_PROC_THEME_SYNTAX_SET: begin fmMain.UpdateThemes('?', Str); Result:= ReturnNone; end; APP_PROC_HOTKEY_INT_TO_STR: begin Str:= ShortCutToTextRaw(StrToIntDef(Str, 0)); Result:= PyUnicodeFromString(Str); end; APP_PROC_HOTKEY_STR_TO_INT: begin Str:= IntToStr(TextToShortCutRaw(Str)); Result:= PyUnicodeFromString(Str); end; APP_PROC_GET_MOUSE_POS: begin Pnt:= Mouse.CursorPos; Result:= Py_BuildValue('(ii)', Pnt.X, Pnt.Y); end; APP_PROC_SHOW_STATUSBAR_SET: begin fmMain.ShowStatus:= ParamBool; Result:= ReturnNone; end; APP_PROC_SHOW_STATUSBAR_GET: begin Result:= PyBool_FromLong(Ord(fmMain.ShowStatus)); end; APP_PROC_SHOW_TOOLBAR_SET: begin fmMain.ShowToolbar:= ParamBool; Result:= ReturnNone; end; APP_PROC_SHOW_TOOLBAR_GET: begin Result:= PyBool_FromLong(Ord(fmMain.ShowToolbar)); end; APP_PROC_SHOW_SIDEPANEL_SET: begin AppPanels[TAppPanelId.Side].Visible:= ParamBool; Result:= ReturnNone; end; APP_PROC_SHOW_SIDEPANEL_GET: begin Result:= PyBool_FromLong(Ord(AppPanels[TAppPanelId.Side].Visible)); end; APP_PROC_SHOW_BOTTOMPANEL_SET: begin AppPanels[TAppPanelId.Btm].Visible:= ParamBool; Result:= ReturnNone; end; APP_PROC_SHOW_BOTTOMPANEL_GET: begin Result:= PyBool_FromLong(Ord(AppPanels[TAppPanelId.Btm].Visible)); end; APP_PROC_SHOW_TABS_SET: begin fmMain.ShowTabsMain:= ParamBool; Result:= ReturnNone; end; APP_PROC_SHOW_TABS_GET: begin Result:= PyBool_FromLong(Ord(fmMain.ShowTabsMain)); end; APP_PROC_SHOW_SIDEBAR_SET: begin fmMain.ShowSideBar:= ParamBool; Result:= ReturnNone; end; APP_PROC_SHOW_SIDEBAR_GET: begin Result:= PyBool_FromLong(Ord(fmMain.ShowSideBar)); end; APP_PROC_SHOW_TREEFILTER_SET: begin fmMain.PanelCodeTreeTop.Visible:= ParamBool; Result:= ReturnNone; end; APP_PROC_SHOW_TREEFILTER_GET: begin Result:= PyBool_FromLong(Ord(fmMain.PanelCodeTreeTop.Visible)); end; APP_PROC_SHOW_FLOATGROUP1_SET: begin fmMain.ShowFloatingForm1:= ParamBool; Result:= ReturnNone; end; APP_PROC_SHOW_FLOATGROUP1_GET: begin Result:= PyBool_FromLong(Ord(fmMain.ShowFloatingForm1)); end; APP_PROC_SHOW_FLOATGROUP2_SET: begin fmMain.ShowFloatingForm2:= ParamBool; Result:= ReturnNone; end; APP_PROC_SHOW_FLOATGROUP2_GET: begin Result:= PyBool_FromLong(Ord(fmMain.ShowFloatingForm2)); end; APP_PROC_SHOW_FLOATGROUP3_SET: begin fmMain.ShowFloatingForm3:= ParamBool; Result:= ReturnNone; end; APP_PROC_SHOW_FLOATGROUP3_GET: begin Result:= PyBool_FromLong(Ord(fmMain.ShowFloatingForm3)); end; APP_PROC_FLOAT_SIDE_SET: begin AppPanels[TAppPanelId.Side].Floating:= ParamBool; Result:= ReturnNone; end; APP_PROC_FLOAT_SIDE_GET: begin Result:= PyBool_FromLong(Ord(AppPanels[TAppPanelId.Side].Floating)); end; APP_PROC_FLOAT_BOTTOM_SET: begin AppPanels[TAppPanelId.Btm].Floating:= ParamBool; Result:= ReturnNone; end; APP_PROC_FLOAT_BOTTOM_GET: begin Result:= PyBool_FromLong(Ord(AppPanels[TAppPanelId.Btm].Floating)); end; APP_PROC_COORD_WINDOW_GET: begin Result:= PyHelper_Rect(Application.MainForm.BoundsRect); end; APP_PROC_COORD_WINDOW_SET: begin Sep.Init(Str); Sep.GetItemInt(ParamRect.Left, 0); Sep.GetItemInt(ParamRect.Top, 0); Sep.GetItemInt(ParamRect.Right, 0); Sep.GetItemInt(ParamRect.Bottom, 0); Application.MainForm.BoundsRect:= ParamRect; Result:= ReturnNone; end; APP_PROC_COORD_DESKTOP: Result:= PyHelper_Rect(Screen.DesktopRect); APP_PROC_COORD_MONITOR: Result:= PyHelper_Rect(fmMain.Monitor.BoundsRect); APP_PROC_COORD_MONITOR0: Result:= PyHelper_RectOfMonitor(0); APP_PROC_COORD_MONITOR1: Result:= PyHelper_RectOfMonitor(1); APP_PROC_COORD_MONITOR2: Result:= PyHelper_RectOfMonitor(2); APP_PROC_COORD_MONITOR3: Result:= PyHelper_RectOfMonitor(3); APP_PROC_CONFIG_READ: begin fmMain.DoOps_LoadOptionsFromString(Str); Result:= ReturnNone; end; APP_PROC_SET_PROJECT: begin if PyCurrentProject<>Str then begin PyCurrentProject:= Str; fmMain.DoPyEvent_AppState(APPSTATE_PROJECT); end; Result:= ReturnNone; end; APP_PROC_GET_UNIQUE_TAG: begin Inc(cPyUniqueTag); Result:= PyLong_FromLongLong(cPyUniqueTag); end; APP_PROC_ENUM_FONTS: Result:= StringsToPyList(Screen.Fonts); APP_PROC_ENUM_ENCODINGS: begin SList:= TStringList.Create; try SList.TextLineBreakStyle:= tlbsLF; SList.Text:= AppEncodingListAsString; Result:= StringsToPyList(SList); finally FreeAndNil(SList); end; end; APP_PROC_GET_AUTOCOMPLETION_INVOKE: begin Result:= PyUnicodeFromString(cAppAutocompleteInvokeStr[AppAutocompleteInvoke]); end; APP_PROC_SEND_MESSAGE: Result:= PyLong_FromLong(PyHelper_SendMessageFromString(Str)); APP_PROC_SPLITTER_GET: begin fmMain.DoSplitter_GetInfo( StrToIntDef(Str, -1), SplitVert, SplitVisible, SplitPos, SplitTotal); Result:= Py_BuildValue('(OOii)', PyBool_FromLong(Ord(SplitVert)), PyBool_FromLong(Ord(SplitVisible)), SplitPos, SplitTotal ); end; APP_PROC_SPLITTER_SET: begin SSplitByChar(Str, ',', Str1, Str2); fmMain.DoSplitter_SetInfo( StrToIntDef(Str1, -1), StrToIntDef(Str2, -1) ); Result:= ReturnNone; end; APP_PROC_THEME_UI_DICT_GET: begin Result:= PyHelper_GetThemeDict_UI; end; APP_PROC_THEME_SYNTAX_DICT_GET: begin Result:= PyHelper_GetThemeDict_Syntax; end; APP_PROC_GET_WINDOW_STATE: begin if fmMain.ShowDistractionFree then i:= WND_FULLSCREEN2 else if fmMain.ShowFullscreen then i:= WND_FULLSCREEN {$ifdef windows} // On Windows, the LCL TForm.WindowState property is NOT reliably // updated to wsMinimized when the user minimizes the window // (the LCL Win32 widgetset doesn't update it on SC_MINIMIZE). // So we query the actual OS-level window state via IsIconic/IsZoomed. // https://github.com/Alexey-T/CudaText/issues/6417 else if IsIconic(fmMain.Handle) then i:= WND_MINIMIZED else if IsZoomed(fmMain.Handle) then i:= WND_MAXIMIZED else i:= WND_NORMAL; {$else} else if fmMain.WindowState=wsMaximized then i:= WND_MAXIMIZED else if fmMain.WindowState=wsMinimized then i:= WND_MINIMIZED else i:= WND_NORMAL; {$endif} Result:= PyLong_FromLong(Ord(i)); end; APP_PROC_SET_WINDOW_STATE: begin case StrToIntDef(Str, -1) of WND_NORMAL: begin fmMain.ShowFullscreen:= false; fmMain.ShowDistractionFree:= false; fmMain.WindowState:= wsNormal; end; WND_MINIMIZED: begin fmMain.WindowState:= wsMinimized; end; WND_MAXIMIZED: begin fmMain.ShowFullscreen:= false; fmMain.ShowDistractionFree:= false; fmMain.WindowState:= wsMaximized; end; WND_FULLSCREEN: fmMain.ShowFullscreen:= true; WND_FULLSCREEN2: fmMain.ShowDistractionFree:= true; end; Result:= ReturnNone; end; APP_PROC_SET_FILE_RECENTS: begin AppListRecents.Clear; Sep.Init(Str, #10); while Sep.GetItemStr(Str1) do SAddStringToHistory( AppCollapseHomeDirInFilename(Str1), AppListRecents, UiOps.MaxHistoryMenu); Result:= ReturnNone; end; APP_PROC_CONFIG_NEWDOC_EOL_GET: begin Result:= PyLong_FromLong(Ord(UiOps.NewdocEnds)); end; APP_PROC_CONFIG_NEWDOC_EOL_SET: begin UiOps.NewdocEnds:= StrToIntDef(Str, 0); Result:= ReturnNone; end; APP_PROC_CONFIG_NEWDOC_ENC_GET: begin Result:= PyUnicodeFromString(UiOps.NewdocEnc); end; APP_PROC_CONFIG_NEWDOC_ENC_SET: begin UiOps.NewdocEnc:= Str; Result:= ReturnNone; end; APP_PROC_CONFIG_SCALE_GET: begin Result:= Py_BuildValue('(ii)', ATEditorScalePercents, ATEditorScaleFontPercents); end; APP_PROC_CONFIG_SCALE_SET: begin Sep.Init(Str); Sep.GetItemInt(ATEditorScalePercents, 100, 80, 500); Sep.GetItemInt(ATEditorScaleFontPercents, 100, 80, 500); fmMain.DoApplyUiOps; Result:= ReturnNone; end; APP_PROC_CONFIG_HISTORY_SAVE: begin fmMain.DoOps_SaveHistory(AppFile_History, false, false); Result:= ReturnNone; end; else Result:= ReturnNone; end; end else Result:= ReturnNone; end; function PyHelper_GetLexerProps(An: TecSyntAnalyzer): PPyObject; var Str1, Str2: string; List: TStringList; ObjTypes, ObjTokenKinds, ObjSublex, ObjCommentStr, ObjCommentLined, ObjStyles, ObjStylesCmt, ObjStylesStr: PPyObject; begin with AppPython.Engine do begin Str1:= An.CommentRangeBegin; Str2:= An.CommentRangeEnd; if (Str1<>'') and (Str2<>'') then ObjCommentStr:= Py_BuildValue('(ss)', PChar(Str1), PChar(Str2)) else ObjCommentStr:= ReturnNone; Str1:= An.CommentFullLinesBegin; Str2:= An.CommentFullLinesEnd; if (Str1<>'') and (Str2<>'') then ObjCommentLined:= Py_BuildValue('(ss)', PChar(Str1), PChar(Str2)) else ObjCommentLined:= ReturnNone; List:= TStringList.Create; try List.LineBreak:= ' '; List.Text:= An.Extentions; ObjTypes:= StringsToPyList(List); List.LineBreak:= ','; List.Text:= An.StylesOfComments; ObjStylesCmt:= StringsToPyList(List); List.Text:= An.StylesOfStrings; ObjStylesStr:= StringsToPyList(List); List.LineBreak:= #10; ObjTokenKinds:= StringsToPyList(An.TokenTypeNames); LexerEnumSublexers(An, List); ObjSublex:= StringsToPyList(List); LexerEnumStyles(An, List); ObjStyles:= StringsToPyList(List); finally FreeAndNil(List); end; Result:= Py_BuildValue('{sOsOsssOsOsOsOsOsOsO}', 'typ', ObjTypes, 'en', PyBool_FromLong(Ord(not An.Internal)), 'c_line', PChar(string(An.LineComment)), 'c_str', ObjCommentStr, 'c_lined', ObjCommentLined, 'st', ObjStyles, 'st_c', ObjStylesCmt, 'st_s', ObjStylesStr, 'kinds', ObjTokenKinds, 'sub', ObjSublex ); end; end; function PyHelper_GetLiteLexerProps(An: TATLiteLexer): PPyObject; var Str1, Str2: string; List: TStringList; ObjTypes, ObjTokenKinds, ObjSublex, ObjCommentStr, ObjCommentLined, ObjStyles, ObjStylesCmt, ObjStylesStr: PPyObject; begin with AppPython.Engine do begin Str1:= An.CommentBlockBegin; Str2:= An.CommentBlockEnd; if (Str1<>'') and (Str2<>'') then ObjCommentStr:= Py_BuildValue('(ss)', PChar(Str1), PChar(Str2)) else ObjCommentStr:= ReturnNone; ObjCommentLined:= ReturnNone; List:= TStringList.Create; try List.LineBreak:= ';'; List.Text:= An.FileTypes; ObjTypes:= StringsToPyList(List); ObjTokenKinds:= ReturnNone; ObjStylesCmt:= ReturnNone; ObjStylesStr:= ReturnNone; ObjSublex:= ReturnNone; ObjStyles:= ReturnNone; finally FreeAndNil(List); end; Result:= Py_BuildValue('{sOsOsssOsOsOsOsOsOsO}', 'typ', ObjTypes, 'en', ReturnTrue, 'c_line', PChar(An.CommentLine), 'c_str', ObjCommentStr, 'c_lined', ObjCommentLined, 'st', ObjStyles, 'st_c', ObjStylesCmt, 'st_s', ObjStylesStr, 'kinds', ObjTokenKinds, 'sub', ObjSublex ); end; end; function PyHelper_GetLexerStylesProps(An: TecSyntAnalyzer): PPyObject; var Fmt: TecSyntaxFormat; i: integer; begin with AppPython.Engine do begin Result:= PyDict_New(); for i:= 0 to An.Formats.Count-1 do begin Fmt:= An.Formats[i]; PyDict_SetItemString(Result, PChar(Fmt.DisplayName), Py_BuildValue('{sisisisisisisisissss}', 'type', Ord(Fmt.FormatType), 'color_font', Fmt.Font.Color, 'color_back', Fmt.BgColor, 'color_border', Fmt.BorderColorBottom, 'border_left', Ord(Fmt.BorderTypeLeft), 'border_right', Ord(Fmt.BorderTypeRight), 'border_top', Ord(Fmt.BorderTypeTop), 'border_bottom', Ord(Fmt.BorderTypeBottom), 'tkind', PChar(cPyTokenKind[TATTokenKind(Fmt.TokenKind)]), 'styles', PChar(Lexer_FontStylesToString(Fmt.Font.Style)) )); end; end; end; function api_lexer_proc(Self, Args : PPyObject): PPyObject; cdecl; var Id: integer; PtrValue: PChar; StrValue, SName: string; List: TStringList; Lexer: TecSyntAnalyzer; LexerLite: TATLiteLexer; Sep: TATStringSeparator; PropName, PropTypes, PropCmtLine, PropCmtBlock1, PropCmtBlock2: string; ok: boolean; begin with AppPython.Engine do if Bool(PyArg_ParseTuple(Args, 'is:lexer_proc', @Id, @PtrValue)) then begin StrValue:= string(PtrValue); case Id of LEXER_GET_PROP: begin if SEndsWith(StrValue, msgLiteLexerSuffix) then begin SetLength(StrValue, Length(StrValue)-Length(msgLiteLexerSuffix)); LexerLite:= AppManagerLite.FindLexerByName(StrValue); if Assigned(LexerLite) then Result:= PyHelper_GetLiteLexerProps(LexerLite) else Result:= ReturnNone; end else begin Lexer:= AppManager.FindLexerByName(StrValue); if Assigned(Lexer) then Result:= PyHelper_GetLexerProps(Lexer) else Result:= ReturnNone; end; end; LEXER_GET_STYLES: begin if SEndsWith(StrValue, msgLiteLexerSuffix) then Result:= ReturnNone else begin Lexer:= AppManager.FindLexerByName(StrValue); if Assigned(Lexer) then Result:= PyHelper_GetLexerStylesProps(Lexer) else Result:= ReturnNone; end; end; LEXER_DETECT: begin if Assigned(AppLexersLastDetected) then AppLexersLastDetected.Clear else AppLexersLastDetected:= TStringList.Create; SName:= Lexer_DetectByFilename( StrValue, ok, @fmMain.DoPyLexerDetection); if AppLexersLastDetected.Count>0 then Result:= StringsToPyTuple(AppLexersLastDetected) else if SName<>'' then Result:= PyUnicodeFromString(SName) else Result:= ReturnNone; end; LEXER_GET_LEXERS: begin List:= TStringList.Create; try List.UseLocale:= false; List.Sorted:= true; Lexer_EnumAll(List, AppStrToBool(StrValue)); Result:= StringsToPyList(List); finally FreeAndNil(List); end; end; LEXER_REREAD_LIB: begin fmMain.DoOps_LoadLexerLib(false); Result:= ReturnNone; end; LEXER_ADD_VIRTUAL: begin Sep.Init(StrValue, ','); Sep.GetItemStr(PropName); Sep.GetItemStr(PropTypes); Sep.GetItemStr(PropCmtLine); Sep.GetItemStr(PropCmtBlock1); Sep.GetItemStr(PropCmtBlock2); ok:= AppManagerLite.Add( PropName, PropTypes, PropCmtLine, PropCmtBlock1, PropCmtBlock2 ); Result:= PyBool_FromLong(Ord(ok));; end; else Result:= ReturnNone; end; end; end; function api_ed_convert(Self, Args: PPyObject): PPyObject; cdecl; var H: Int64; Ed: TATSynEdit; Strs: TATStrings; Id, X, Y, NValue: integer; PtrValue: PChar; StrValue: string; StrTemp: UnicodeString; Pnt: TPoint; PntCoord: TATPoint; Details: TATEditorPosDetails; begin with AppPython.Engine do if Bool(PyArg_ParseTuple(Args, 'Liiis:convert', @H, @Id, @X, @Y, @PtrValue)) then begin Ed:= PyHelper_EditorFromHandle(H); Strs:= Ed.Strings; StrValue:= string(PtrValue); case Id of CONVERT_CHAR_TO_COL: begin if (X<0) or (not Strs.IsIndexValid(Y)) then exit(ReturnNone); X:= Strs.CharPosToColumnPos(Y, X, Ed.TabHelper); Result:= Py_BuildValue('(ii)', X, Y); end; CONVERT_COL_TO_CHAR: begin if (X<0) or (not Strs.IsIndexValid(Y)) then exit(ReturnNone); X:= Strs.ColumnPosToCharPos(Y, X, Ed.TabHelper); Result:= Py_BuildValue('(ii)', X, Y); end; CONVERT_LINE_TABS_TO_SPACES: begin StrTemp:= Ed.TabHelper.TabsToSpaces(-1, UTF8Decode(StrValue)); Result:= PyUnicodeFromString(StrTemp); end; CONVERT_SCREEN_TO_LOCAL: begin Pnt:= Ed.ScreenToClient(Point(X, Y)); Result:= Py_BuildValue('(ii)', Pnt.X, Pnt.Y); end; CONVERT_LOCAL_TO_SCREEN: begin Pnt:= Ed.ClientToScreen(Point(X, Y)); Result:= Py_BuildValue('(ii)', Pnt.X, Pnt.Y); end; CONVERT_PIXELS_TO_CARET: begin Pnt:= Ed.ClientPosToCaretPos(ATPoint(X, Y), Details); if Pnt.Y<0 then exit(ReturnNone); Result:= Py_BuildValue('(ii)', Pnt.X, Pnt.Y); end; CONVERT_CARET_TO_PIXELS: begin if (X<0) or (not Strs.IsIndexValid(Y)) then exit(ReturnNone); PntCoord:= Ed.CaretPosToClientPos(Point(X, Y)); if PntCoord.Y<0 then exit(ReturnNone); Result:= Py_BuildValue('(LL)', PntCoord.X, PntCoord.Y); end; CONVERT_OFFSET_TO_CARET: begin Pnt:= Ed.OffsetToCaretPos(X); if Pnt.Y<0 then exit(ReturnNone); Result:= Py_BuildValue('(ii)', Pnt.X, Pnt.Y); end; CONVERT_CARET_TO_OFFSET: begin NValue:= Ed.CaretPosToOffset(Point(X, Y)); if NValue<0 then exit(ReturnNone); Result:= PyLong_FromLong(NValue); end; else Result:= ReturnNone; end; end else Result:= ReturnNone; end; function PyHelper_Folding_Enum(Ed: TATSynEdit; NeedY, NeedY2: integer): PPyObject; cdecl; var ListRanges: TFPList; Range: PATFoldRange; NLen, i: integer; begin ListRanges:= TFPList.Create; try for i:= 0 to Ed.Fold.Count-1 do begin Range:= Ed.Fold.ItemPtr(i); if (NeedY<0) or ((Range^.Y<=NeedY) and (Range^.Y2>=NeedY2)) then ListRanges.Add(Range); end; with AppPython.Engine do begin NLen:= ListRanges.Count; Result:= PyList_New(NLen); if not Assigned(Result) then raise EPythonError.Create(msgPythonListError); for i:= 0 to NLen-1 do begin Range:= PATFoldRange(ListRanges[i]); PyList_SetItem(Result, i, Py_BuildValue('{sisisisisOsOsOsi}', string('x'), Range^.X-1, string('y'), Range^.Y, 'x2', Range^.X2-1, 'y2', Range^.Y2, 'staple', PyBool_FromLong(Ord(Range^.Staple)), 'folded', PyBool_FromLong(Ord(Range^.Folded)), 'hint', PyUnicodeFromString(Range^.Hint), 'tag', Longint(Range^.Tag) )); end; end; finally FreeAndNil(ListRanges); end; end; function api_ed_get_sublexer_ranges(Self, Args: PPyObject): PPyObject; cdecl; //func returns string, and cudatext.py code makes final Py objects from string var H: Int64; Ed: TATSynEdit; NLen, i: Integer; PntStart, PntEnd: TPoint; LexName, Str: string; Adapter: TATAdapterEControl; begin with AppPython.Engine do if Bool(PyArg_ParseTuple(Args, 'L:get_sublexer_ranges', @H)) then begin Ed:= PyHelper_EditorFromHandle(H); if not (Ed.AdapterForHilite is TATAdapterEControl) then exit(ReturnNone); Adapter:= (Ed.AdapterForHilite as TATAdapterEControl); if Adapter.AnClient=nil then exit(ReturnNone); Adapter.AnClient.CriSecForData.Enter; try NLen:= Adapter.SublexerRangeCount; if NLen>0 then begin Str:= ''; for i:= 0 to NLen-1 do if Adapter.SublexerRangeProps(i, PntStart, PntEnd, LexName) then Str:= Str + Format('%d,%d,%d,%d,%s;', [ PntStart.X, PntStart.Y, PntEnd.X, PntEnd.Y, LexName ]); Result:= PyUnicodeFromString(Str); end else Result:= ReturnNone; finally Adapter.AnClient.CriSecForData.Leave; end; end else Result:= ReturnNone; end; //menu_proc(id_menu, id_action, command, caption, index, hotkey, tag) function api_menu_proc(Self, Args: PPyObject): PPyObject; cdecl; var PtrMenu, PtrCaption, PtrCmd, PtrHotkey, PtrTag: PChar; StrMenu, StrCaption, StrCmd, StrHotkey, StrTag, StrResult: string; NAction, NIndex: integer; Popup: TPopupMenu; PopupItem: TMenuItem; NX, NY: integer; ImgList: TImageList; Sep: TATStringSeparator; begin with AppPython.Engine do if Bool(PyArg_ParseTuple(Args, 'sississ:menu_proc', @PtrMenu, @NAction, @PtrCmd, @PtrCaption, @NIndex, @PtrHotkey, @PtrTag)) then begin StrMenu:= string(PtrMenu); StrCaption:= string(PtrCaption); StrCmd:= string(PtrCmd); StrHotkey:= string(PtrHotkey); StrTag:= string(PtrTag); case NAction of MENU_CLEAR: begin fmMain.DoMenuClear(StrMenu); fmMain.FNeedAppState_MenuRemove:= true; Result:= ReturnNone; end; MENU_ENUM: begin Result:= fmMain.DoMenu_PyEnum(StrMenu); end; MENU_ADD: begin StrResult:= fmMain.DoMenuAdd_Params(StrMenu, StrCmd, StrCaption, StrHotkey, StrTag, NIndex); fmMain.FNeedAppState_MenuAdd:= true; Result:= PyUnicodeFromString(StrResult); end; MENU_REMOVE: begin fmMain.DoMenu_Remove(StrMenu); fmMain.FNeedAppState_MenuRemove:= true; Result:= ReturnNone; end; MENU_CREATE: begin Popup:= TPopupMenu.Create(fmMain); StrResult:= IntToStr(PtrInt(Popup.Items)); Result:= PyUnicodeFromString(StrResult); end; MENU_SET_CAPTION: begin PopupItem:= PyHelper_MenuItemFromId(StrMenu); if Assigned(PopupItem) then PopupItem.Caption:= StrCmd; fmMain.FNeedAppState_MenuChange:= true; Result:= ReturnNone; end; MENU_SET_VISIBLE: begin PopupItem:= PyHelper_MenuItemFromId(StrMenu); if Assigned(PopupItem) then PopupItem.Visible:= AppStrToBool(StrCmd); fmMain.FNeedAppState_MenuChange:= true; Result:= ReturnNone; end; MENU_SET_ENABLED: begin PopupItem:= PyHelper_MenuItemFromId(StrMenu); if Assigned(PopupItem) then PopupItem.Enabled:= AppStrToBool(StrCmd); fmMain.FNeedAppState_MenuChange:= true; Result:= ReturnNone; end; MENU_SET_CHECKED: begin PopupItem:= PyHelper_MenuItemFromId(StrMenu); if Assigned(PopupItem) then PopupItem.Checked:= AppStrToBool(StrCmd); fmMain.FNeedAppState_MenuChange:= true; Result:= ReturnNone; end; MENU_SET_RADIOITEM: begin PopupItem:= PyHelper_MenuItemFromId(StrMenu); if Assigned(PopupItem) then PopupItem.RadioItem:= AppStrToBool(StrCmd); fmMain.FNeedAppState_MenuChange:= true; Result:= ReturnNone; end; MENU_SET_GROUPINDEX: begin PopupItem:= PyHelper_MenuItemFromId(StrMenu); if Assigned(PopupItem) then PopupItem.GroupIndex:= NIndex; fmMain.FNeedAppState_MenuChange:= true; Result:= ReturnNone; end; MENU_SET_HOTKEY: begin PopupItem:= PyHelper_MenuItemFromId(StrMenu); if Assigned(PopupItem) then PopupItem.ShortCut:= TextToShortCutRaw(StrCmd); fmMain.FNeedAppState_MenuChange:= true; Result:= ReturnNone; end; MENU_SHOW: begin PopupItem:= PyHelper_MenuItemFromId(StrMenu); if not Assigned(PopupItem) then exit(ReturnNone); Popup:= PopupItem.Owner as TPopupMenu; UpdateMenuTheming_PopupMenu_Win32(Popup); if StrCmd='' then Popup.PopUp //at cursor position else begin Sep.Init(StrCmd); Sep.GetItemInt(NX, 0); Sep.GetItemInt(NY, 0); Popup.PopUp(NX, NY); end; Result:= ReturnNone; end; MENU_GET_PROP: begin PopupItem:= PyHelper_MenuItemFromId(StrMenu); if Assigned(PopupItem) then Result:= fmMain.DoMenu_GetPyProps(PopupItem) else Result:= ReturnNone; end; MENU_SET_IMAGELIST: begin ImgList:= PyHelper_ImagelistFromId(StrCmd); PopupItem:= PyHelper_MenuItemFromId(StrMenu); if PopupItem=nil then exit(ReturnNone); //TPopupMenu - then menuitem.owner is set to popupmenu by Cud, //TMainMenu - then menuitem.owner is fmMain if PopupItem.Owner is TMenu then begin (PopupItem.Owner as TMenu).Images:= ImgList; end else if PopupItem.Owner is TForm then begin (PopupItem.Owner as TForm).Menu.Images:= ImgList; end; Result:= ReturnNone; end; MENU_SET_IMAGEINDEX: begin PopupItem:= PyHelper_MenuItemFromId(StrMenu); if Assigned(PopupItem) then PopupItem.ImageIndex:= NIndex; fmMain.FNeedAppState_MenuChange:= true; Result:= ReturnNone; end; MENU_SET_AUTO_HOTKEY: begin PopupItem:= PyHelper_MenuItemFromId(StrMenu); if Assigned(PopupItem) then fmMain.UpdateMenuItem_SetShortcutFromProps(PopupItem); Result:= ReturnNone; end; MENU_SET_AUTO_HOTKEY_DEEP: begin PopupItem:= PyHelper_MenuItemFromId(StrMenu); if Assigned(PopupItem) then fmMain.UpdateMenuItem_SetShortcutsRecursively(PopupItem, StrToIntDef(StrCmd, 1)); Result:= ReturnNone; end; else Result:= ReturnNone; end; end else Result:= ReturnNone; end; procedure PyHelper_ListboxItem_SetFromString(AItem: TATListboxItemProp; const AText: string); var Sep: TATStringSeparator; SItem, SKey, SValue: string; begin //text is '{key1:value1;key2:value2}' from to_str() Sep.Init(SDeleteCurlyBrackets(AText), #1); repeat if not Sep.GetItemStr(SItem) then Break; SSplitByChar(SItem, ':', SKey, SValue); SValue:= StringReplace(SValue, #2, ',', [rfReplaceAll]); if SKey='datatext' then AItem.DataText:= SValue else if SKey='tag' then AItem.Tag:= StrToInt64Def(SValue, 0) else if SKey='modified' then AItem.Modified:= SValue='1'; until false; end; //listbox_proc(id_listbox, id_action, index, text) function api_listbox_proc(Self, Args: PPyObject): PPyObject; cdecl; var IdList, NTag: Int64; IdAction, NIndex, i: integer; PtrText, PtrTag: PChar; StrText, StrTag: string; Listbox: TATListbox; Obj: TObject; begin with AppPython.Engine do if Bool(PyArg_ParseTuple(Args, 'Liiss:listbox_proc', @IdList, @IdAction, @NIndex, @PtrText, @PtrTag)) then begin if IdList=0 then exit(ReturnNone); Obj:= TObject(PtrInt(IdList)); if not (Obj is TATListbox) then begin MsgLogConsole('ERROR: listbox_proc() gets bad handle, of type '+Obj.ClassName); exit(ReturnNone); end; Listbox:= TATListbox(Obj); Obj:= nil; StrText:= string(PtrText); StrTag:= string(PtrTag); NTag:= StrToInt64Def(StrTag, 0); case IdAction of LISTBOX_GET_COUNT: begin Result:= PyLong_FromLong(Listbox.Items.Count); end; LISTBOX_ADD: begin if NIndex=-1 then begin Listbox.Items.AddObject(StrText, TATListboxItemProp.Create(NTag, false, '')); Listbox.Invalidate; end else if Listbox.IsIndexValid(NIndex) then begin Listbox.Items.InsertObject(NIndex, StrText, TATListboxItemProp.Create(NTag, false, '')); Listbox.Invalidate; end; Result:= PyLong_FromLong(Listbox.Items.Count); end; LISTBOX_DELETE: begin if Listbox.IsIndexValid(NIndex) then begin Obj:= Listbox.Items.Objects[NIndex]; if Assigned(Obj) then Obj.Free; Listbox.Items.Delete(NIndex); if Listbox.ItemIndex>=Listbox.ItemCount then Listbox.ItemIndex:= Listbox.ItemCount-1; Listbox.Invalidate; end; Result:= ReturnNone; end; LISTBOX_DELETE_ALL: begin for i:= Listbox.Items.Count-1 downto 0 do begin Obj:= Listbox.Items.Objects[i]; if Assigned(Obj) then Obj.Free; end; Listbox.Items.Clear; Listbox.ItemIndex:= -1; Listbox.ItemTop:= 0; Listbox.Invalidate; Result:= ReturnNone; end; LISTBOX_GET_SEL: begin Result:= PyLong_FromLong(Listbox.ItemIndex); end; LISTBOX_SET_SEL: begin if Listbox.IsIndexValid(NIndex) then Listbox.ItemIndex:= NIndex; Result:= ReturnNone; end; LISTBOX_GET_ITEM_PROP: begin if Listbox.IsIndexValid(NIndex) then begin Obj:= Listbox.Items.Objects[NIndex]; if Assigned(Obj) then Result:= Py_BuildValue('{sssOsOss}', 'text', PChar(Listbox.Items[NIndex]), 'tag', PyLong_FromLongLong(TATListboxItemProp(Obj).Tag), 'modified', PyBool_FromLong(Ord(TATListboxItemProp(Obj).Modified)), 'datatext', PChar(TATListboxItemProp(Obj).DataText) ) else Result:= ReturnNone; end else Result:= ReturnNone; end; LISTBOX_SET_ITEM_PROP: begin if Listbox.IsIndexValid(NIndex) then begin Listbox.Items[NIndex]:= StrText; Obj:= Listbox.Items.Objects[NIndex]; PyHelper_ListboxItem_SetFromString(Obj as TATListboxItemProp, StrTag); Listbox.Invalidate; end; Result:= ReturnNone; end; LISTBOX_ADD_PROP: begin if (NIndex=-1) or Listbox.IsIndexValid(NIndex) then begin Obj:= TATListboxItemProp.Create(0, false, ''); PyHelper_ListboxItem_SetFromString(Obj as TATListboxItemProp, StrTag); if NIndex=-1 then Listbox.Items.AddObject(StrText, Obj) else Listbox.Items.InsertObject(NIndex, StrText, Obj); Listbox.Invalidate; end; Result:= PyLong_FromLong(Listbox.Items.Count); end; LISTBOX_GET_TOP: begin Result:= PyLong_FromLong(Listbox.ItemTop); end; LISTBOX_SET_TOP: begin if Listbox.IsIndexValid(NIndex) and (Listbox.ItemTop<>NIndex) then begin Listbox.ItemTop:= NIndex; Listbox.Invalidate; end; Result:= ReturnNone; end; LISTBOX_GET_ITEM_H: begin Result:= PyLong_FromLong(Listbox.ItemHeight); end; LISTBOX_SET_ITEM_H: begin if Listbox.ItemHeight<>NIndex then begin Listbox.ItemHeight:= NIndex; Listbox.Invalidate; end; Result:= ReturnNone; end; LISTBOX_GET_HOTTRACK: begin Result:= PyBool_FromLong(Ord(Listbox.HotTrack)); end; LISTBOX_SET_HOTTRACK: begin if Listbox.HotTrack<>(NIndex=1) then begin Listbox.HotTrack:= (NIndex=1); Listbox.Invalidate; end; Result:= ReturnNone; end; LISTBOX_GET_DRAWN: begin Result:= PyBool_FromLong(Ord(Listbox.OwnerDrawn)); end; LISTBOX_SET_DRAWN: begin if Listbox.OwnerDrawn<>(NIndex=1) then begin Listbox.OwnerDrawn:= (NIndex=1); Listbox.Invalidate; end; Result:= ReturnNone; end; LISTBOX_GET_COLUMN_SEP: begin Result:= PyUnicodeFromString(Listbox.ColumnSeparator); end; LISTBOX_SET_COLUMN_SEP: begin if StrText<>'' then begin Listbox.ColumnSeparator:= StrText[1]; Listbox.Invalidate; end; Result:= ReturnNone; end; LISTBOX_GET_COLUMNS: begin Result:= PyList_New(Length(Listbox.ColumnSizes)); if not Assigned(Result) then raise EPythonError.Create(msgPythonListError); for i:= 0 to Length(Listbox.ColumnSizes)-1 do PyList_SetItem(Result, i, PyLong_FromLongLong(Int64(Listbox.ColumnSizes[i]))); end; LISTBOX_SET_COLUMNS: begin Listbox.ColumnSizes:= ConvertStringToIntArray(StrText); Listbox.Invalidate; Result:= ReturnNone; end; LISTBOX_GET_SHOW_X: begin Result:= PyLong_FromLong(Ord(Listbox.ShowXMark)); end; LISTBOX_SET_SHOW_X: begin if Listbox.ShowXMark<>TATListboxShowX(NIndex) then begin Listbox.ShowXMark:= TATListboxShowX(NIndex); Listbox.Invalidate; end; Result:= ReturnNone; end; LISTBOX_GET_SCROLLSTYLE_HORZ: begin Result:= PyLong_FromLong(Ord(Listbox.ScrollStyleHorz)); end; LISTBOX_GET_SCROLLSTYLE_VERT: begin Result:= PyLong_FromLong(Ord(Listbox.ScrollStyleVert)); end; LISTBOX_SET_SCROLLSTYLE_HORZ: begin if Listbox.ScrollStyleHorz<>TATListboxScrollStyle(NIndex) then begin Listbox.ScrollStyleHorz:= TATListboxScrollStyle(NIndex); Listbox.Invalidate; end; Result:= ReturnNone; end; LISTBOX_SET_SCROLLSTYLE_VERT: begin if Listbox.ScrollStyleVert<>TATListboxScrollStyle(NIndex) then begin Listbox.ScrollStyleVert:= TATListboxScrollStyle(NIndex); Listbox.Invalidate; end; Result:= ReturnNone; end; LISTBOX_GET_SCROLLPOS_HORZ: begin Result:= PyLong_FromLong(Listbox.ScrollHorz); end; LISTBOX_SET_SCROLLPOS_HORZ: begin Listbox.ScrollHorz:= NIndex; Result:= ReturnNone; end; LISTBOX_GET_HEADER: begin Result:= PyUnicodeFromString(Listbox.HeaderText); end; LISTBOX_SET_HEADER: begin if Listbox.HeaderText<>StrText then begin Listbox.HeaderText:= StrText; Listbox.Invalidate; end; Result:= ReturnNone; end; LISTBOX_GET_HEADER_IMAGELIST: begin Result:= PyHelper_ObjectHandle(Listbox.HeaderImages); end; LISTBOX_SET_HEADER_IMAGELIST: begin Obj:= TObject(PtrInt(StrToInt64Def(StrText, 0))); if not (Obj is TImageList) then begin MsgLogConsole('ERROR: listbox_proc(LISTBOX_SET_HEADER_IMAGELIST) gets bad handle, of type '+Obj.ClassName); exit(ReturnNone); end; Listbox.HeaderImages:= TImageList(Obj); Result:= ReturnNone; end; LISTBOX_GET_HEADER_IMAGEINDEXES: begin Result:= PyUnicodeFromString( ConvertIntArrayToString(Listbox.HeaderImageIndexes)); end; LISTBOX_SET_HEADER_IMAGEINDEXES: begin Listbox.HeaderImageIndexes:= ConvertStringToIntArray(StrText); Result:= ReturnNone; end; LISTBOX_SET_DISABLING_CHAR: begin if StrText<>'' then Listbox.DisablingChar:= StrText[1]; Result:= ReturnNone; end else Result:= ReturnNone; end; end else Result:= ReturnNone; end; function api_button_proc(Self, Args: PPyObject): PPyObject; cdecl; var Obj: TObject; IdBtn: Int64; IdAction: integer; PtrValue: PChar; StrValue: string; Btn: TATButton; MnuPopup: TPopupMenu; MnuItem: TMenuItem; begin with AppPython.Engine do if Bool(PyArg_ParseTuple(Args, 'Lis:button_proc', @IdBtn, @IdAction, @PtrValue)) then begin StrValue:= string(PtrValue); Obj:= TObject(PtrInt(IdBtn)); if not (Obj is TATButton) then begin MsgLogConsole('ERROR: button_proc() gets bad handle, of type '+Obj.ClassName); exit(ReturnNone); end; Btn:= TATButton(Obj); case IdAction of BTN_UPDATE: begin Btn.Invalidate; Result:= ReturnNone; end; BTN_GET_CHECKED: begin Result:= PyBool_FromLong(Ord(Btn.Checked)); end; BTN_SET_CHECKED: begin Btn.Checked:= AppStrToBool(StrValue); Result:= ReturnNone; end; BTN_GET_IMAGELIST: begin Result:= PyHelper_ObjectHandle(Btn.Images); end; BTN_SET_IMAGELIST: begin Btn.Images:= PyHelper_ImagelistFromId(StrValue); Result:= ReturnNone; end; BTN_GET_IMAGEINDEX: begin Result:= PyLong_FromLongLong(Btn.ImageIndex); end; BTN_SET_IMAGEINDEX: begin Btn.ImageIndex:= StrToIntDef(StrValue, -1); Result:= ReturnNone; end; BTN_GET_KIND: begin Result:= PyLong_FromLong(Ord(Btn.Kind)); end; BTN_SET_KIND: begin Btn.Kind:= TATButtonKind(StrToIntDef(StrValue, 0)); Result:= ReturnNone; end; BTN_GET_BOLD: begin Result:= PyBool_FromLong(Ord(Btn.BoldFont)); end; BTN_SET_BOLD: begin Btn.BoldFont:= AppStrToBool(StrValue); Result:= ReturnNone; end; BTN_GET_ENABLED: begin Result:= PyBool_FromLong(Ord(Btn.Enabled)); end; BTN_SET_ENABLED: begin Btn.Enabled:= AppStrToBool(StrValue); Result:= ReturnNone; end; BTN_GET_VISIBLE: begin Result:= PyBool_FromLong(Ord(Btn.Visible)); end; BTN_SET_VISIBLE: begin Btn.Visible:= AppStrToBool(StrValue); Result:= ReturnNone; end; BTN_GET_TEXT: begin Result:= PyUnicodeFromString(Btn.Caption); end; BTN_SET_TEXT: begin Btn.Caption:= StrValue; Result:= ReturnNone; end; BTN_GET_HINT: begin Result:= PyUnicodeFromString(Btn.Hint); end; BTN_SET_HINT: begin Btn.Hint:= StrValue; Result:= ReturnNone; end; BTN_GET_MENU: begin MnuPopup:= Btn.PopupDropdown; if Assigned(MnuPopup) then Result:= PyHelper_ObjectHandle(MnuPopup.Items) else Result:= ReturnNone; end; BTN_SET_MENU: begin MnuItem:= PyHelper_MenuItemFromId(StrValue, 'button_proc'); if Assigned(MnuItem) then begin if MnuItem.Owner is TPopupMenu then Btn.PopupDropdown:= MnuItem.Owner as TPopupMenu else MsgLogConsole('ERROR: button_proc(..., BTN_SET_MENU, ...) gets bad menuitem owner, of type '+MnuItem.Owner.ClassName); end; Result:= ReturnNone; end; BTN_GET_DATA1: begin Result:= PyUnicodeFromString(Btn.DataString); end; BTN_SET_DATA1: begin Btn.DataString:= StrValue; Result:= ReturnNone; end; BTN_GET_DATA2: begin Result:= PyUnicodeFromString(Btn.DataString2); end; BTN_SET_DATA2: begin Btn.DataString2:= StrValue; Result:= ReturnNone; end; BTN_GET_ARROW: begin Result:= PyBool_FromLong(Ord(Btn.Arrow)); end; BTN_SET_ARROW: begin Btn.Arrow:= AppStrToBool(StrValue); Result:= ReturnNone; end; BTN_GET_ARROW_ALIGN: begin Result:= PyUnicodeFromString(AppAlignmentToString(Btn.ArrowAlign)); end; BTN_SET_ARROW_ALIGN: begin Btn.ArrowAlign:= AppStringToAlignment(StrValue); Result:= ReturnNone; end; BTN_GET_FOCUSABLE: begin Result:= PyBool_FromLong(Ord(Btn.Focusable)); end; BTN_SET_FOCUSABLE: begin Btn.Focusable:= AppStrToBool(StrValue); Result:= ReturnNone; end; BTN_GET_FLAT: begin Result:= PyBool_FromLong(Ord(Btn.Flat)); end; BTN_SET_FLAT: begin Btn.Flat:= AppStrToBool(StrValue); Result:= ReturnNone; end; BTN_GET_WIDTH: begin Result:= PyLong_FromLong(Btn.Width); end; BTN_SET_WIDTH: begin //must set Btn.WidthInitial because it's used in ATFlatToolbar.Update //for Btn.Kind=TextChoice Btn.WidthInitial:= StrToIntDef(StrValue, Btn.WidthInitial); Btn.Width:= Btn.WidthInitial; Result:= ReturnNone; end; BTN_GET_ITEMS: begin Result:= PyUnicodeFromString(Btn.Items.Text); end; BTN_SET_ITEMS: begin Btn.Items.Text:= StrValue; Result:= ReturnNone; end; BTN_GET_ITEMINDEX: begin Result:= PyLong_FromLong(Btn.ItemIndex); end; BTN_SET_ITEMINDEX: begin Btn.ItemIndex:= StrToIntDef(StrValue, -1); Result:= ReturnNone; end; BTN_GET_OVERLAY: begin Result:= PyUnicodeFromString(Btn.TextOverlay); end; BTN_SET_OVERLAY: begin Btn.TextOverlay:= StrValue; Result:= ReturnNone; end; BTN_GET_COLOR_LINE: begin Result:= PyLong_FromLong(Btn.ColorLine); end; BTN_SET_COLOR_LINE: begin Btn.ColorLine:= StrToIntDef(StrValue, clNone); Result:= ReturnNone; end; BTN_GET_COLOR_LINE2: begin Result:= PyLong_FromLong(Btn.ColorLine2); end; BTN_SET_COLOR_LINE2: begin Btn.ColorLine2:= StrToIntDef(StrValue, clNone); Result:= ReturnNone; end; else Result:= ReturnNone; end; end else Result:= ReturnNone; end; function PyHelper_CanvasId_to_CanvasObject(const IdCanvas: Int64): TCanvas; var Obj: TObject; begin if IdCanvas=0 then //support PaintBox for plugins debugging begin fmMain.InitPaintTest; fmMain.PaintTest.Show; Application.ProcessMessages; Result:= fmMain.PaintTest.Canvas; end else begin Obj:= TObject(PtrInt(IdCanvas)); if not (Obj is TCanvas) then Result:= nil //caller will see Nil and will show console message about wrong IdCanvas class else Result:= TCanvas(Obj); end; end; function api_imagelist_proc(Self, Args: PPyObject): PPyObject; cdecl; var IdList, Num64: Int64; IdAction: integer; PtrValue: PChar; StrValue: string; Obj: TComponent; Obj2: TObject; List: TImageList; NX, NY, NIndex: integer; Canvas: TCanvas; Sep: TATStringSeparator; begin with AppPython.Engine do if Bool(PyArg_ParseTuple(Args, 'Lis:imagelist_proc', @IdList, @IdAction, @PtrValue)) then begin StrValue:= string(PtrValue); if IdAction=IMAGELIST_CREATE then begin Num64:= StrToInt64Def(StrValue, 0); if Num64=0 then Obj:= fmMain else begin Obj2:= TObject(PtrInt(Num64)); if not (Obj2 is TComponent) then begin MsgLogConsole('ERROR: imagelist_proc(IMAGELIST_CREATE) gets bad owner handle, of type '+Obj2.ClassName); exit(ReturnNone); end; Obj:= TComponent(Obj2); end; List:= TImageList.Create(Obj); exit(PyHelper_ObjectHandle(List)); end; //other actions require id_list param if IdList=0 then exit(ReturnNone); Obj2:= TObject(PtrInt(IdList)); if not (Obj2 is TImageList) then begin MsgLogConsole('ERROR: imagelist_proc() gets bad handle, of type '+Obj2.ClassName); exit(ReturnNone); end; List:= TImageList(Obj2); case IdAction of IMAGELIST_COUNT: begin Result:= PyLong_FromLong(List.Count); end; IMAGELIST_GET_SIZE: begin Result:= Py_BuildValue('(ii)', List.Width, List.Height); end; IMAGELIST_SET_SIZE: begin Sep.Init(StrValue); Sep.GetItemInt(NX, 0); Sep.GetItemInt(NY, 0); List.Width:= Min(500, Max(4, NX)); List.Height:= Min(500, Max(4, NY)); Result:= Py_BuildValue('(ii)', List.Width, List.Height); end; IMAGELIST_DELETE: begin NIndex:= StrToIntDef(StrValue, -1); if (NIndex>=0) and (NIndex=0 then Result:= PyLong_FromLong(NX) else Result:= ReturnNone; end; IMAGELIST_PAINT: begin Sep.Init(StrValue); Sep.GetItemInt64(Num64, 0); Canvas:= PyHelper_CanvasId_to_CanvasObject(Num64); if Canvas=nil then begin MsgLogConsole('ERROR: imagelist_proc(...IMAGELIST_PAINT...) gets bad canvas handle'); exit(ReturnNone); end; Sep.GetItemInt(NX, 0); Sep.GetItemInt(NY, 0); Sep.GetItemInt(NIndex, 0); if (NIndex>=0) and (NIndexnil then begin Obj:= TObject(Node1.Data); if Obj is TATRangeInCodeTree then StrData:= (Obj as TATRangeInCodeTree).DataString; end; PyList_SetItem(Result, i, Py_BuildValue('{sLsssssisO}', 'id', Int64(PtrInt(Node1)), 'text', PChar(Node1.Text), 'data', PChar(StrData), 'img', Node1.ImageIndex, 'sub_items', PyBool_FromLong(Ord(Node1.HasChildren)) )); end; finally FreeAndNil(ItemList); end; end; TREE_ITEM_ADD: begin Node1:= TreeContainer.Tree.Items.AddChild(TreeNode, StrText); Node1.Text:= StrText; Node1.ImageIndex:= NImageIndex; Node1.SelectedIndex:= NImageIndex; if NIndex>=0 then Node1.Index:= NIndex; if Assigned(PtrData) then begin ObjData:= TATRangeInCodeTree.Create; ObjData.DataString:= string(PtrData); Node1.Data:= ObjData; end; TreeContainer.Tree.Invalidate; Result:= PyHelper_ObjectHandle(Node1); end; TREE_ITEM_DELETE: begin if Assigned(TreeNode) then TreeNode.Free else begin //handle code-tree clearing via API if bStandardCodeTree then fmMain.DoCodetree_Clear else TreeContainer.Tree.Items.Clear; end; TreeContainer.Tree.Invalidate; Result:= ReturnNone; end; TREE_ITEM_SET_TEXT: begin if Assigned(TreeNode) then TreeNode.Text:= StrText; TreeContainer.Tree.Invalidate; Result:= ReturnNone; end; TREE_ITEM_SET_ICON, TREE_ITEM_SET_ICON_2: begin //issue #3400 if bStandardCodeTree then begin fmMain.InitImageListCodetree; fmMain.UpdateTreeImagelistActivity; end; if Assigned(TreeNode) then begin if IdAction=TREE_ITEM_SET_ICON then begin TreeNode.ImageIndex:= NImageIndex; TreeNode.SelectedIndex:= NImageIndex; end else begin TreeContainer.Tree.StateImages:= TreeContainer.Tree.Images; TreeNode.StateIndex:= NImageIndex; end; end; TreeContainer.Tree.Invalidate; Result:= ReturnNone; end; TREE_ITEM_SELECT: begin if Assigned(TreeNode) then begin TreeNode.Selected:= true; TreeNode.MakeVisible; TreeContainer.Tree.Invalidate; end else begin TreeContainer.Tree.Selected:= nil; end; Result:= ReturnNone; end; TREE_ITEM_GET_SELECTED: begin if Assigned(TreeContainer.Tree.Selected) then Result:= PyHelper_ObjectHandle(TreeContainer.Tree.Selected) else Result:= ReturnNone; end; TREE_ITEM_GET_PROPS: begin if Assigned(TreeNode) then begin StrData:= ''; if TreeNode.Data<>nil then begin Obj:= TObject(TreeNode.Data); if Obj is TATRangeInCodeTree then StrData:= (Obj as TATRangeInCodeTree).DataString; end; Result:= Py_BuildValue('{sssisisisisLsOsOsOss}', 'text', PChar(TreeNode.Text), 'index', TreeNode.Index, 'index_abs', TreeNode.AbsoluteIndex, 'icon', TreeNode.ImageIndex, 'level', TreeNode.Level, 'parent', Int64(PtrInt(TreeNode.Parent)), 'folded', PyBool_FromLong(Ord(not TreeNode.Expanded)), 'selected', PyBool_FromLong(Ord(TreeNode.Selected)), 'sub_items', PyBool_FromLong(Ord(TreeNode.HasChildren)), 'data', PChar(StrData) ) end else Result:= ReturnNone; end; TREE_ITEM_FOLD: begin if Assigned(TreeNode) then TreeNode.Collapse(false); TreeContainer.Tree.Invalidate; Result:= ReturnNone; end; TREE_ITEM_FOLD_DEEP: begin if Assigned(TreeNode) then TreeNode.Collapse(true) else TreeContainer.Tree.FullCollapse; TreeContainer.Tree.Invalidate; Result:= ReturnNone; end; TREE_ITEM_FOLD_LEVEL: begin AppTreeviewFoldLevel(TreeContainer.Tree, NIndex); Result:= ReturnNone; end; TREE_ITEM_UNFOLD: begin //if TreeContainer.Owner is TFormDummy then // (TreeContainer.Owner as TFormDummy).BlockedOnUnfold:= true; if Assigned(TreeNode) then TreeNode.Expand(false); //if TreeContainer.Owner is TFormDummy then // (TreeContainer.Owner as TFormDummy).BlockedOnUnfold:= false; TreeContainer.Tree.Invalidate; Result:= ReturnNone; end; TREE_ITEM_UNFOLD_DEEP: begin //if TreeContainer.Owner is TFormDummy then // (TreeContainer.Owner as TFormDummy).BlockedOnUnfold:= true; if Assigned(TreeNode) then TreeNode.Expand(true) else TreeContainer.Tree.FullExpand; //if TreeContainer.Owner is TFormDummy then // (TreeContainer.Owner as TFormDummy).BlockedOnUnfold:= false; TreeContainer.Tree.Invalidate; Result:= ReturnNone; end; TREE_ITEM_GET_RANGE: begin fmMain.DoCodetree_GetSyntaxRange(TreeNode, Pnt1, Pnt2); Result:= Py_BuildValue('(iiii)', Pnt1.X, Pnt1.Y, Pnt2.X, Pnt2.Y); end; TREE_ITEM_SET_RANGE: begin Sep.Init(StrText); Sep.GetItemInt(Pnt1.X, 0); Sep.GetItemInt(Pnt1.Y, 0); Sep.GetItemInt(Pnt2.X, 0); Sep.GetItemInt(Pnt2.Y, 0); fmMain.DoCodetree_SetSyntaxRange(TreeNode, Pnt1, Pnt2); Result:= ReturnNone; end; TREE_ITEM_SHOW: begin TreeNode.MakeVisible; Result:= ReturnNone; end; TREE_GET_SELECTIONS: begin NCount:= TreeContainer.Tree.SelectionCount; Result:= PyList_New(NCount); for i:= 0 to NCount-1 do PyList_SetItem(Result, i, PyHelper_ObjectHandle(TreeContainer.Tree.Selections[i])); end; TREE_FIND_FOR_TEXT_POS: begin Sep.Init(StrText, ','); Sep.GetItemInt(NPosX, -1); Sep.GetItemInt(NPosY, -1); if (NPosX<0) or (NPosY<0) then exit(ReturnNone); TreeNode:= CodetreeFindItemForPosition(TreeContainer.Tree, NPosX, NPosY); Result:= PyHelper_ObjectHandle(TreeNode); end; TREE_GET_IMAGELIST: begin if bStandardCodeTree then fmMain.InitImageListCodetree; Result:= PyHelper_ObjectHandle(TreeContainer.Tree.Images); end; TREE_SET_IMAGELIST: begin IdImgList:= StrToInt64Def(StrText, 0); Obj:= TObject(PtrInt(IdImgList)); if Assigned(Obj) and not (Obj is TImageList) then begin MsgLogConsole('ERROR: tree_proc(...TREE_SET_IMAGELIST...) gets bad handle of image-list, of type '+Obj.ClassName); exit(ReturnNone); end; if bStandardCodeTree then fmMain.InitImageListCodetree; TreeContainer.Tree.Images:= TImageList(Obj); Obj:= nil; Result:= ReturnNone; end; TREE_LOCK: begin TreeContainer.Tree.Items.BeginUpdate; Result:= ReturnNone; end; TREE_UNLOCK: begin TreeContainer.Tree.Items.EndUpdate; TTreeviewAccess(TreeContainer.Tree).DoSelectionChanged; //force update new scrollbars Result:= ReturnNone; end; TREE_GET_MULSELECT: begin if TreeContainer.Tree.MultiSelect then StrText:= ConvertMultiSelectStyleToString(TreeContainer.Tree.MultiSelectStyle) else StrText:= '-'; Result:= PyUnicodeFromString(StrText); end; TREE_SET_MULSELECT: begin if StrText='-' then TreeContainer.Tree.MultiSelect:= false else begin TreeContainer.Tree.MultiSelect:= true; TreeContainer.Tree.MultiSelectStyle:= ConvertStringToMultiSelectStyle(StrText); end; Result:= ReturnFalse; end; TREE_PROP_SHOW_ROOT: begin TreeContainer.Tree.ShowRoot:= AppStrToBool(StrText); TreeContainer.Tree.Invalidate; Result:= ReturnNone; end; TREE_THEME: begin TreeContainer.ThemedColors:= true; TreeContainer.ScrollbarsNew:= UiOps.ScrollbarsNew; ApplyThemeToTreeview(TreeContainer.Tree, true, false); Result:= ReturnNone; end; TREE_GET_SCROLLSTYLE_HORZ: begin Result:= PyLong_FromLong(Ord(TreeContainer.ScrollStyleHorz)); end; TREE_GET_SCROLLSTYLE_VERT: begin Result:= PyLong_FromLong(Ord(TreeContainer.ScrollStyleVert)); end; TREE_SET_SCROLLSTYLE_HORZ: begin i:= StrToIntDef(StrText, -1); if (i>=0) then if TreeContainer.ScrollStyleHorz<>TAppTreeScrollStyle(i) then begin TreeContainer.ScrollStyleHorz:= TAppTreeScrollStyle(i); TreeContainer.UpdateScrollbars; end; Result:= ReturnNone; end; TREE_SET_SCROLLSTYLE_VERT: begin i:= StrToIntDef(StrText, -1); if (i>=0) then if TreeContainer.ScrollStyleVert<>TAppTreeScrollStyle(i) then begin TreeContainer.ScrollStyleVert:= TAppTreeScrollStyle(i); TreeContainer.UpdateScrollbars; end; Result:= ReturnNone; end; else Result:= ReturnNone; end; end; end; function api_ed_dim(Self, Args: PPyObject): PPyObject; cdecl; var H: Int64; Ed: TATSynEdit; DimPtr: PATDimRange; Id, NIndex1, NIndex2, NValue, NLen, i: integer; begin with AppPython.Engine do if Bool(PyArg_ParseTuple(Args, 'Liiii:dim', @H, @Id, @NIndex1, @NIndex2, @NValue)) then begin Ed:= PyHelper_EditorFromHandle(H); case Id of DIM_ADD: begin Ed.DimRanges.Add(NIndex1, NIndex2, NValue); Ed.Update; Result:= ReturnNone; end; DIM_DELETE: begin if Ed.DimRanges.IsIndexValid(NIndex1) then begin Ed.DimRanges.Delete(NIndex1); Ed.Update; end; Result:= ReturnNone; end; DIM_DELETE_ALL: begin if Ed.DimRanges.Count>0 then begin Ed.DimRanges.Clear; Ed.Update; end; Result:= ReturnNone; end; DIM_ENUM: begin NLen:= Ed.DimRanges.Count; Result:= PyList_New(NLen); if not Assigned(Result) then raise EPythonError.Create(msgPythonListError); for i:= 0 to NLen-1 do begin DimPtr:= Ed.DimRanges.ItemPtr(i); PyList_SetItem(Result, i, Py_BuildValue('(iii)', DimPtr^.LineFrom, DimPtr^.LineTo, DimPtr^.DimValue )); end; end; else Result:= ReturnNone; end; end else Result:= ReturnNone; end; procedure PyHelper_FindTokenRange(An: TecClientSyntAnalyzer; ALineFrom, ALineTo: integer; out ATokenIndexFrom, ATokenIndexTo: integer); var NMaxLine, NMaxToken: integer; begin ATokenIndexFrom:= -1; ATokenIndexTo:= -1; if ALineFrom<0 then exit; if ALineFrom>ALineTo then exit; NMaxLine:= High(An.PublicData.TokenIndexer); NMaxToken:= An.PublicData.Tokens.Count-1; if ALineFrom>NMaxLine then exit; if ALineTo>NMaxLine then ALineTo:= NMaxLine; //increase ALineFrom until we get TokenIndexer[]>=0 (ie skip empty lines) while (ALineFrom<=NMaxLine) and (An.PublicData.TokenIndexer[ALineFrom]<0) do Inc(ALineFrom); if ALineFrom>NMaxLine then exit; //decrease ALineTo until we get TokenIndexer[]>=0 (ie skip empty lines) while (ALineTo>ALineFrom) and (An.PublicData.TokenIndexer[ALineTo]<0) do Dec(ALineTo); ATokenIndexFrom:= An.PublicData.TokenIndexer[ALineFrom]; //1st token which touches ALineFrom ATokenIndexTo:= An.PublicData.TokenIndexer[ALineTo]; //1st token which touches ALineTo - not final result ATokenIndexTo:= Min(NMaxToken, ATokenIndexTo); //last token which touches ALineTo while (ATokenIndexTo+1<=NMaxToken) and (An.PublicData.Tokens[ATokenIndexTo+1].Range.PointStart.Y<=ALineTo) do Inc(ATokenIndexTo); end; function PyHelper_GetTokenList(Adapter: TATAdapterEControl; ALineFrom, ALineTo: integer): PPyObject; var An: TecClientSyntAnalyzer; Token: PecSyntToken; TokenStr, TokenStyle: string; TokenKind: TATTokenKind; NIndexFrom, NIndexTo, NCount: integer; iToken: integer; begin with AppPython.Engine do begin An:= Adapter.AnClient; if An=nil then exit(ReturnNone); An.CriSecForData.Enter; try PyHelper_FindTokenRange(An, ALineFrom, ALineTo, NIndexFrom, NIndexTo); if NIndexFrom<0 then exit(PyList_New(0)); NCount:= NIndexTo-NIndexFrom+1; if NCount<=0 then exit(PyList_New(0)); Result:= PyList_New(NCount); if not Assigned(Result) then raise EPythonError.Create(msgPythonListError); for iToken:= NIndexFrom to NIndexTo do begin Token:= An.PublicData.Tokens._GetItemPtr(iToken); TokenStr:= Adapter.GetTokenString(Token); TokenKind:= TATTokenKind.Other; if Assigned(Token^.Style) then begin TokenStyle:= Token^.Style.DisplayName; TokenKind:= TATTokenKind(Token^.Style.TokenKind); end else TokenStyle:= ''; PyList_SetItem(Result, iToken-NIndexFrom, Py_BuildValue('{sssssisisisisiss}', 'str', PChar(TokenStr), 'style', PChar(TokenStyle), 'x1', Token^.Range.PointStart.X, 'y1', Token^.Range.PointStart.Y, 'x2', Token^.Range.PointEnd.X, 'y2', Token^.Range.PointEnd.Y, 'ki', Token^.TokenType, 'ks', PChar(cPyTokenKind[TokenKind]) )); end; finally An.CriSecForData.Leave; end; end; end; function api_ed_get_token(Self, Args: PPyObject): PPyObject; cdecl; var H: Int64; Ed: TATSynEdit; Id, NIndex1, NIndex2: integer; Adapter: TATAdapterEControl; TokenKind: TATTokenKind; begin with AppPython.Engine do if Bool(PyArg_ParseTuple(Args, 'Liii:get_token', @H, @Id, @NIndex1, @NIndex2)) then begin Ed:= PyHelper_EditorFromHandle(H); case Id of TOKEN_GET_KIND: begin TokenKind:= EditorGetTokenKind(Ed, NIndex1, NIndex2); Result:= PyUnicodeFromString(cPyTokenKind[TokenKind]); end; TOKEN_LIST_SUB: begin if not (Ed.AdapterForHilite is TATAdapterEControl) then exit(PyList_New(0)); Adapter:= Ed.AdapterForHilite as TATAdapterEControl; Result:= PyHelper_GetTokenList(Adapter, NIndex1, NIndex2) end; else Result:= ReturnNone; end; end else Result:= ReturnNone; end; function api_bitmap_proc(Self, Args: PPyObject): PPyObject; cdecl; var IdBitmap: Int64; IdAction, NParam1, NParam2: integer; Bmp: TBitmap; Obj: TObject; begin with AppPython.Engine do if Bool(PyArg_ParseTuple(Args, 'Liii:bitmap_proc', @IdBitmap, @IdAction, @NParam1, @NParam2)) then begin Bmp:= nil; if IdBitmap<>0 then begin Obj:= TObject(PtrInt(IdBitmap)); if not (Obj is TBitmap) then begin MsgLogConsole('ERROR: bitmap_proc() gets bad handle, of type '+Obj.ClassName); Result:= ReturnNone; exit; end; Bmp:= TBitmap(Obj); end; if (IdAction<>BITMAP_CREATE) and (Bmp=nil) then begin MsgLogConsole('ERROR: bitmap_proc() gets zero bitmap handle'); Result:= ReturnNone; exit; end; if (IdAction=BITMAP_CREATE) or (IdAction=BITMAP_SET_SIZE) then if (NParam1<=0) or (NParam2<=0) then begin MsgLogConsole(Format('ERROR: bitmap_proc() gets bad w=%d, h=%d', [NParam1, NParam2])); Result:= ReturnNone; exit; end; case IdAction of BITMAP_CREATE: begin Bmp:= TBitmap.Create; Bmp.PixelFormat:= pf24bit; Bmp.SetSize(NParam1, NParam2); Result:= PyHelper_ObjectHandle(Bmp); end; BITMAP_GET_CANVAS: begin Result:= PyHelper_ObjectHandle(Bmp.Canvas); end; BITMAP_FREE: begin FreeAndNil(Bmp); Result:= ReturnNone; end; BITMAP_SET_SIZE: begin if (NParam1>0) and (NParam2>0) then Bmp.SetSize(NParam1, NParam2); Result:= ReturnNone; end; BITMAP_GET_SIZE: begin Result:= Py_BuildValue('(ii)', Bmp.Width, Bmp.Height); end; else Result:= ReturnNone; end; end else Result:= ReturnNone; end; function api_canvas_proc(Self, Args: PPyObject): PPyObject; cdecl; var C: TCanvas; IdCanvas, Num64: Int64; Obj: TObject; IdAction, NColor, NSize, NStyle, NX, NY, NX2, NY2: integer; NP1, NP2: Int64; //param "p1" must be Int64 to pass handle of bitmap/image PtrText: PChar; StrText: string; TempPntArray: TAppPointArray; TempRect: TRect; Sep: TATStringSeparator; begin with AppPython.Engine do if Bool(PyArg_ParseTuple(Args, 'LisiiiiiiiLL:canvas_proc', @IdCanvas, @IdAction, @PtrText, @NColor, @NSize, @NX, @NY, @NX2, @NY2, @NStyle, @NP1, @NP2)) then begin C:= PyHelper_CanvasId_to_CanvasObject(IdCanvas); if C=nil then begin MsgLogConsole('ERROR: canvas_proc() gets bad canvas handle'); exit(ReturnNone); end; StrText:= string(PtrText); case IdAction of CANVAS_SET_FONT: begin if StrText<>'' then C.Font.Name:= StrText; if NSize>0 then C.Font.Size:= NSize; if NColor>=0 then C.Font.Color:= NColor; if NStyle>=0 then C.Font.Style:= Canvas_NumberToFontStyles(NStyle); Result:= ReturnNone; end; CANVAS_SET_PEN: begin if NSize>0 then C.Pen.Width:= NSize; if NColor>=0 then C.Pen.Color:= NColor; if NStyle>=0 then C.Pen.Style:= TPenStyle(NStyle); if NP1>=0 then C.Pen.EndCap:= TPenEndCap(NP1); if NP2>=0 then C.Pen.JoinStyle:= TPenJoinStyle(NP2); Result:= ReturnNone; end; CANVAS_SET_BRUSH: begin if NColor>=0 then C.Brush.Color:= NColor; if NStyle>=0 then C.Brush.Style:= TBrushStyle(NStyle); Result:= ReturnNone; end; CANVAS_SET_ANTIALIAS: begin if NStyle>=0 then C.AntialiasingMode:= TAntialiasingMode(NStyle); Result:= ReturnNone; end; CANVAS_TEXT: begin C.TextOut(NX, NY, StrText); Result:= ReturnNone; end; CANVAS_GET_TEXT_SIZE: begin C.GetTextSize(StrText, NX, NY); Result:= Py_BuildValue('(ii)', NX, NY); end; CANVAS_LINE: begin C.Line(NX, NY, NX2, NY2); Result:= ReturnNone; end; CANVAS_PIXEL: begin C.Pixels[NX, NY]:= NColor; Result:= ReturnNone; end; CANVAS_RECT: begin C.Rectangle(NX, NY, NX2, NY2); Result:= ReturnNone; end; CANVAS_RECT_FRAME: begin C.FrameRect(NX, NY, NX2, NY2); Result:= ReturnNone; end; CANVAS_RECT_FILL: begin CanvasFillRect(C, Rect(NX, NY, NX2, NY2), C.Brush.Color); Result:= ReturnNone; end; CANVAS_RECT_ROUND: begin C.RoundRect(NX, NY, NX2, NY2, NStyle, NStyle{Rx=Ry}); Result:= ReturnNone; end; CANVAS_BITMAP, CANVAS_BITMAP_SIZED: begin Num64:= NP1; if Num64=0 then MsgLogConsole('ERROR: canvas_proc(...CANVAS_BITMAP...) gets bad or zero bitmap handle') else begin Obj:= TObject(PtrInt(Num64)); if not (Obj is TBitmap) then MsgLogConsole('ERROR: canvas_proc(...CANVAS_BITMAP...) gets bad bitmap handle, of type '+Obj.ClassName) else begin if IdAction=CANVAS_BITMAP then C.Draw(NX, NY, TBitmap(Obj)) else C.StretchDraw(Rect(NX, NY, NX2, NY2), TBitmap(Obj)); end; end; Result:= ReturnNone; end; CANVAS_IMAGE, CANVAS_IMAGE_SIZED: begin Num64:= NP1; if Num64=0 then MsgLogConsole('ERROR: canvas_proc(...CANVAS_IMAGE...) gets bad or zero image handle') else begin Obj:= TObject(PtrInt(Num64)); if not (Obj is TImage) then MsgLogConsole('ERROR: canvas_proc(...CANVAS_IMAGE...) gets bad image handle, of type '+Obj.ClassName) else begin if IdAction=CANVAS_IMAGE then C.Draw(NX, NY, TImage(Obj).Picture.Graphic) else C.StretchDraw(Rect(NX, NY, NX2, NY2), TImage(Obj).Picture.Graphic); end; end; Result:= ReturnNone; end; CANVAS_ELLIPSE: begin C.Ellipse(NX, NY, NX2, NY2); Result:= ReturnNone; end; CANVAS_POLYGON: begin TempPntArray:= ConvertStringToPointArray(StrText); if Length(TempPntArray)>2 then C.Polygon(TempPntArray) else MsgLogConsole('ERROR: canvas_proc(...CANVAS_POLYGON...) gets bad coords: '+StrText); Result:= ReturnNone; end; CANVAS_COPY_RECT: begin Num64:= NP1; if Num64=0 then MsgLogConsole('ERROR: canvas_proc(...CANVAS_COPY_RECT...) gets bad or zero source-canvas handle') else begin Obj:= TObject(PtrInt(Num64)); if not (Obj is TCanvas) then MsgLogConsole('ERROR: canvas_proc(...CANVAS_COPY_RECT...) gets bad source-canvas handle, of type '+Obj.ClassName) else begin Sep.Init(StrText, ','); Sep.GetItemInt(TempRect.Left, MaxInt); Sep.GetItemInt(TempRect.Top, MaxInt); Sep.GetItemInt(TempRect.Right, MaxInt); Sep.GetItemInt(TempRect.Bottom, MaxInt); if (TempRect.Left=MaxInt) or (TempRect.Top=MaxInt) or (TempRect.Right=MaxInt) or (TempRect.Bottom=MaxInt) then MsgLogConsole('ERROR: canvas_proc(...CANVAS_COPY_RECT...) gets bad source-rect: '+StrText) else C.CopyRect( Rect(NX, NY, NX2, NY2), TCanvas(Obj), TempRect); end; end; Result:= ReturnNone; end; CANVAS_GRADIENT: begin if not ((NStyle>=0) and (NStyle<=Ord(High(TGradientDirection)))) then MsgLogConsole('ERROR: canvas_proc(...CANVAS_GRADIENT...) gets bad direction') else C.GradientFill( Rect(NX, NY, NX2, NY2), NColor, NSize, TGradientDirection(NStyle) ); Result:= ReturnNone; end; CANVAS_SET_TESTPANEL: begin fmMain.InitPaintTest; if NSize<20 then fmMain.PaintTest.Hide else begin fmMain.PaintTest.Show; fmMain.PaintTest.Height:= Min(NSize, 300); end; with fmMain.PaintTest do Result:= Py_BuildValue('(ii)', Width, Height); end else Result:= ReturnNone; end; end else Result:= ReturnNone; end; function api_image_proc(Self, Args: PPyObject): PPyObject; cdecl; var IdImage, Num64: Int64; IdAction: integer; PtrValue: PChar; StrValue: string; Obj: TComponent; Obj2: TObject; Image: TImage; Gr: TGraphic; NX, NY, NX2, NY2: integer; Canvas: TCanvas; Sep: TATStringSeparator; begin with AppPython.Engine do if Bool(PyArg_ParseTuple(Args, 'Lis:image_proc', @IdImage, @IdAction, @PtrValue)) then begin StrValue:= string(PtrValue); if IdAction=APP_IMAGE_CREATE then begin Num64:= StrToInt64Def(StrValue, 0); if Num64=0 then Obj:= fmMain else begin Obj2:= TObject(PtrInt(Num64)); if not (Obj2 is TComponent) then begin MsgLogConsole('ERROR: image_proc(...IMAGE_CREATE...) gets bad owner handle, of type '+Obj2.ClassName); exit(ReturnNone); end; Obj:= TComponent(Obj2); end; Image:= TImage.Create(Obj); exit(PyHelper_ObjectHandle(Image)); end; //other actions require id_image param if IdImage=0 then exit(ReturnNone); Obj2:= TObject(PtrInt(IdImage)); if not (Obj2 is TImage) then begin MsgLogConsole('ERROR: image_proc() gets bad image handle, of type '+Obj2.ClassName); exit(ReturnNone); end; Image:= TImage(Obj2); case IdAction of APP_IMAGE_GET_SIZE: begin Result:= Py_BuildValue('(ii)', Image.Picture.Width, Image.Picture.Height); end; APP_IMAGE_GET_SIZE_UI: begin Result:= Py_BuildValue('(ii)', Image.Width, Image.Height); end; APP_IMAGE_GET_BITMAP: begin if Assigned(Image.Picture) and Assigned(Image.Picture.Bitmap) then Result:= PyHelper_ObjectHandle(Image.Picture.Bitmap) else Result:= PyLong_FromLong(0); end; APP_IMAGE_LOAD: begin Gr:= AppLoadPictureFromFile(StrValue); try Image.Picture.Assign(Gr); Result:= PyBool_FromLong(Ord(Assigned(Gr))); finally FreeAndNil(Gr); end; end; APP_IMAGE_PAINT: begin Sep.Init(StrValue); Sep.GetItemInt64(Num64, 0); Canvas:= PyHelper_CanvasId_to_CanvasObject(Num64); if Canvas=nil then begin MsgLogConsole('ERROR: image_proc(...IMAGE_PAINT...) gets bad canvas handle'); exit(ReturnNone); end; Sep.GetItemInt(NX, 0); Sep.GetItemInt(NY, 0); Canvas.Draw(NX, NY, Image.Picture.Graphic); Result:= ReturnNone; end; APP_IMAGE_PAINT_SIZED: begin Sep.Init(StrValue); Sep.GetItemInt64(Num64, 0); Canvas:= PyHelper_CanvasId_to_CanvasObject(Num64); if Canvas=nil then begin MsgLogConsole('ERROR: image_proc(...IMAGE_PAINT_SIZED...) gets bad canvas handle'); exit(ReturnNone); end; Sep.GetItemInt(NX, 0); Sep.GetItemInt(NY, 0); Sep.GetItemInt(NX2, 0); Sep.GetItemInt(NY2, 0); Canvas_PaintImageInRect(Canvas, Image.Picture.Graphic, Rect(NX, NY, NX2, NY2)); Result:= ReturnNone; end; else Result:= ReturnNone; end; end else Result:= ReturnNone; end; function PyHelper_GapGetDict(Ed: TATSynEdit): PPyObject; cdecl; var GapItem: TATGapItem; NLen, NSizeX, NSizeY, i: Integer; begin with AppPython.Engine do begin NLen:= Ed.Gaps.Count; Result:= PyList_New(NLen); if not Assigned(Result) then raise EPythonError.Create(msgPythonListError); for i:= 0 to NLen-1 do begin GapItem:= Ed.Gaps[i]; if Assigned(GapItem.Bitmap) then begin NSizeX:= GapItem.Bitmap.Width; NSizeY:= GapItem.Bitmap.Height; end else begin NSizeX:= 0; NSizeY:= 0; end; PyList_SetItem(Result, i, Py_BuildValue('{sisisis(ii)si}', 'line', GapItem.LineIndex, 'tag', GapItem.Tag, 'size', GapItem.Size, 'bitmap', NSizeX, NSizeY, 'color', GapItem.Color )); end; end; end; function api_ed_gap(Self, Args: PPyObject): PPyObject; cdecl; var H, Num1, Num2: Int64; Id, NColor, NSize, NTag, NOnTop: integer; Ed, EdOther: TATSynEdit; Frame: TEditorFrame; Bmp: TBitmap; Form: TCustomForm; GapObject: TObject; ScrollInfo: TATEditorScrollInfo; begin NOnTop:= 0; with AppPython.Engine do if Bool(PyArg_ParseTuple(Args, 'LiLLiii|i:gap', @H, @Id, @Num1, @Num2, @NTag, @NSize, @NColor, @NOnTop)) then begin Ed:= PyHelper_EditorFromHandle(H); case Id of GAP_GET_ALL: begin Result:= PyHelper_GapGetDict(Ed); end; GAP_MAKE_BITMAP: begin Bmp:= TBitmap.Create; Bmp.PixelFormat:= pf24bit; Bmp.SetSize(Num1, Num2); Bmp.Canvas.Brush.Color:= clMoneyGreen; Bmp.Canvas.FillRect(0, 0, Bmp.Width, Bmp.Height); Result:= Py_BuildValue('(LL)', Int64(PtrInt(Bmp)), Int64(PtrInt(Bmp.Canvas))); end; GAP_ADD: begin if Ed.Strings.IsIndexValid(Num1) or (Num1=-1) then begin GapObject:= TObject(PtrInt(Num2)); if GapObject is TBitmap then Bmp:= TBitmap(GapObject) else Bmp:= nil; if GapObject is TCustomForm then Form:= TCustomForm(GapObject) else Form:= nil; if NSize<=0 then begin if Assigned(Bmp) then NSize:= Bmp.Height+2{borders} else if Assigned(Form) then NSize:= Form.Height+2{borders}; end; if Ed.Gaps.Add(Num1, NSize, Bmp, Form, NTag, NColor, true, Bool(NOnTop)) then begin ////better to set OptLastLineOnTop always, to fix [v-scrollbar cannot reach end for many gaps at end] //if Num1=Ed.Strings.Count-1 then Ed.OptLastLineOnTop:= true; Include(Ed.ModifiedOptions, TATEditorModifiedOption.LastLineOnTop); //set OptLastLineOnTop for split-view editor too Frame:= TGroupsHelper.GetEditorFrame(Ed); if Assigned(Frame) and Frame.EditorsLinked then begin EdOther:= TGroupsHelper.GetEditorBrother(Ed); if Assigned(EdOther) then begin EdOther.OptLastLineOnTop:= true; Include(EdOther.ModifiedOptions, TATEditorModifiedOption.LastLineOnTop); end; end; //if added gap before 1st line, scroll editor upper if Num1=-1 then if Ed.ScrollVert.SmoothPos=0 then begin ScrollInfo:= Ed.ScrollVert; ScrollInfo.NPos:= -1; Ed.ScrollVert:= ScrollInfo; end; Ed.Update; Result:= ReturnTrue; end else Result:= ReturnFalse; end else Result:= ReturnFalse; end; GAP_DELETE: begin if Num20 then begin Ed.Gaps.Clear; Ed.Update; end; Result:= ReturnNone; end; GAP_DELETE_BY_TAG: begin if Ed.Gaps.DeleteWithTag(NTag) then Ed.Update; Result:= ReturnNone; end; else Result:= ReturnNone; end; end else Result:= ReturnNone; end; function PyHelper_ExportHtml(Ed: TATSynEdit; const SParams: string; out AToMemory: boolean; out AMemory: string): boolean; var List: TStringList; SItem, SKey, SValue: string; SFileName, STitle, SFontName: string; NFontSize: integer; bWithNums: boolean; NColorBg, NColorNums: TColor; Sep: TATStringSeparator; PosBegin, PosEnd: TPoint; begin AToMemory:= false; AMemory:= ''; SFileName:= ''; STitle:= ''; SFontName:= UiOps.ExportHtmlFontName; NFontSize:= UiOps.ExportHtmlFontSize; bWithNums:= UiOps.ExportHtmlNumbers; NColorBg:= GetAppColor(TAppThemeColor.ExportHtmlBg); NColorNums:= GetAppColor(TAppThemeColor.ExportHtmlNumbers); PosBegin:= Point(0, 0); PosEnd:= Point(0, Ed.Strings.Count); //text is '{key1:value1;key2:value2}' from to_str() Sep.Init(SDeleteCurlyBrackets(SParams), #1); repeat if not Sep.GetItemStr(SItem) then Break; SSplitByChar(SItem, ':', SKey, SValue); SValue:= StringReplace(SValue, #2, ',', [rfReplaceAll]); case SKey of 'file_name': SFileName:= SValue; 'title': STitle:= SValue; 'font_name': SFontName:= SValue; 'font_size': NFontSize:= StrToIntDef(SValue, NFontSize); 'with_numbers': bWithNums:= AppStrToBool(SValue); 'color_back': NColorBg:= StrToIntDef(SValue, NColorBg); 'color_numbers': NColorNums:= StrToIntDef(SValue, NColorNums); 'line_begin': PosBegin.Y:= StrToIntDef(SValue, PosBegin.Y); 'line_end': PosEnd.Y:= StrToIntDef(SValue, PosEnd.Y); 'col_begin': PosBegin.X:= StrToIntDef(SValue, PosBegin.X); 'col_end': PosEnd.X:= StrToIntDef(SValue, PosEnd.X); end; until false; if SFileName='' then exit(false); AToMemory:= SFileName='-'; if not AToMemory and FileExists(SFileName) then DeleteFile(SFileName); List:= TStringList.Create; try List.TrailingLineBreak:= false; EditorExportToHTML(Ed, List, PosBegin, PosEnd, STitle, SFontName, NFontSize, bWithNums, NColorBg, NColorNums ); if AToMemory then begin AMemory:= List.Text; Result:= true; end else begin List.SaveToFile(SFileName); Result:= FileExists(SFileName); end; finally FreeAndNil(List); end; end; function PyHelper_FindOrReplaceOne(Ed: TATSynEdit; const ATextFrom, ATextTo, AOptions: string; AReplace, AUpdateCaret: boolean): PPyObject; var Finder: TATEditorFinder; bChange: boolean; begin Finder:= TATEditorFinder.Create; try Finder.Editor:= Ed; Finder.StrFind:= ATextFrom; Finder.StrReplace:= ATextTo; ConvertFinderOptionsFromString(Finder, AOptions); Finder.OnGetToken:= @fmMain.FinderOnGetToken; with AppPython.Engine do if Finder.DoAction_FindOrReplace(AReplace, false, bChange, AUpdateCaret) then begin Result:= Py_BuildValue('(iiii)', Finder.MatchEdPos.X, Finder.MatchEdPos.Y, Finder.MatchEdEnd.X, Finder.MatchEdEnd.Y); if bChange then begin Ed.Update(true); Ed.DoEventChange(Min( Finder.MatchEdPos.Y, Finder.MatchEdEnd.Y)); end else if AUpdateCaret then Ed.Update; end else begin if Finder.IsRegexBad then Result:= ReturnFalse else Result:= ReturnNone; end; finally FreeAndNil(Finder); end; end; function PyHelper_ReplaceAll(Ed: TATSynEdit; const ATextFrom, ATextTo, AOptions: string): PPyObject; var Finder: TATEditorFinder; NCount: integer; begin Finder:= TATEditorFinder.Create; try Finder.Editor:= Ed; Finder.StrFind:= ATextFrom; Finder.StrReplace:= ATextTo; ConvertFinderOptionsFromString(Finder, AOptions); Finder.OnGetToken:= @fmMain.FinderOnGetToken; with AppPython.Engine do begin NCount:= Finder.DoAction_ReplaceAll; if NCount>0 then Ed.Update(true); if NCount=0 then if Finder.IsRegexBad then exit(ReturnFalse); Result:= PyLong_FromLong(NCount); end; finally FreeAndNil(Finder); end; end; function PyHelper_FindAllMatches(Ed: TATSynEdit; const AText, AOptions: string; AMaxLineLen: integer): PPyObject; var Finder: TATEditorFinder; ResList: TATFinderResults; Res: TATFinderResult; i: integer; begin Finder:= TATEditorFinder.Create; ResList:= TATFinderResults.Create; try Finder.Editor:= Ed; Finder.StrFind:= UTF8Decode(AText); ConvertFinderOptionsFromString(Finder, AOptions); Finder.OnGetToken:= @fmMain.FinderOnGetToken; Finder.MaxLineLen:= AMaxLineLen; Finder.DoAction_FindAll(ResList, false); if ResList.Count=0 then if Finder.IsRegexBad then exit(AppPython.Engine.ReturnFalse); with AppPython.Engine do begin Result:= PyList_New(ResList.Count); if not Assigned(Result) then raise EPythonError.Create(msgPythonListError); for i:= 0 to ResList.Count-1 do begin Res:= ResList[i]; PyList_SetItem(Result, i, Py_BuildValue('(iiii)', Res.PosBegin.X, Res.PosBegin.Y, Res.PosEnd.X, Res.PosEnd.Y)); end; end; finally FreeAndNil(ResList); FreeAndNil(Finder); end; end; function api_ed_action(Self, Args: PPyObject): PPyObject; cdecl; var HEditor: Int64; IdAction: integer; PtrText1, PtrText2, PtrText3: PChar; StrText1, StrText2, StrText3: string; Ed: TATSynEdit; Frame: TEditorFrame; Ada: TATAdapterEControl; NValue: Int64; TreeContainer: TAppTreeContainer; Sep: TATStringSeparator; CharFrom, CharTo: atChar; Kind: TEditorBracketKind; AllowedSymbols: string; Distance: integer; Obj: TObject; Ok, bToMemory: boolean; StrMemory: string; NX, NY, N1, N2: integer; begin with AppPython.Engine do if Bool(PyArg_ParseTuple(Args, 'Lisss:action', @HEditor, @IdAction, @PtrText1, @PtrText2, @PtrText3)) then begin Ed:= PyHelper_EditorFromHandle(HEditor); StrText1:= string(PtrText1); StrText2:= string(PtrText2); StrText3:= string(PtrText3); NValue:= StrToInt64Def(StrText1, 0); case IdAction of EDACTION_UPDATE: begin Ed.Update( AppStrToBool(StrText1), true{AForceRepaint} ); // fix https://github.com/CudaText-addons/cuda_testing_attr/issues/1 // not sure we can call Ed.Repaint on Qt5/macOS {$if defined(windows)} Ed.Repaint; {$endif} Result:= ReturnNone; end; EDACTION_UNDOGROUP_BEGIN: begin Ed.Strings.BeginUndoGroup; Result:= ReturnNone; end; EDACTION_UNDOGROUP_END: begin Ed.Strings.EndUndoGroup; Result:= ReturnNone; end; EDACTION_FIND_ONE: begin Result:= PyHelper_FindOrReplaceOne(Ed, StrText1, '', StrText2, false{Replace}, false); end; EDACTION_REPLACE_ONE: begin Result:= PyHelper_FindOrReplaceOne(Ed, StrText1, StrText2, StrText3, true{Replace}, false); end; EDACTION_FIND_ALL: begin Result:= PyHelper_FindAllMatches(Ed, StrText1, StrText2, StrToIntDef(StrText3, MaxInt)); end; EDACTION_REPLACE_ALL: begin Result:= PyHelper_ReplaceAll(Ed, StrText1, StrText2, StrText3); end; EDACTION_FIND_BRACKETS: begin Sep.Init(StrText1); Sep.GetItemInt(NX, -1); Sep.GetItemInt(NY, -1); AllowedSymbols:= StrText2; Distance:= StrToIntDef(StrText3, MaxInt); EditorBracket_FindBoth(Ed, NX, NY, AllowedSymbols, Distance, N1, N2, CharFrom, CharTo, Kind); Result:= Py_BuildValue('(iiii)', NX, NY, N1, N2); end; EDACTION_SHOW_POS: begin Sep.Init(StrText1); Sep.GetItemInt(NX, -1); Sep.GetItemInt(NY, -1); Sep.Init(StrText2); Sep.GetItemInt(N1, 0); Sep.GetItemInt(N2, 0); if (NX>=0) and Ed.Strings.IsIndexValid(NY) then begin ok:= Ed.DoShowPos(Point(NX, NY), N1, N2, true, true, true); Result:= PyBool_FromLong(Ord(ok)); end else Result:= ReturnNone; end; EDACTION_CODETREE_FILL: begin Frame:= TGroupsHelper.GetEditorFrame(Ed); if Frame=nil then exit(ReturnFalse); if NValue=0 then exit(ReturnFalse); Obj:= TObject(PtrInt(NValue)); if not (Obj is TAppTreeContainer) then begin MsgLogConsole('ERROR: Editor.action(EDACTION_CODETREE_FILL) gets bad handle of tree, of type '+Obj.ClassName); exit(ReturnFalse); end; TreeContainer:= TAppTreeContainer(Obj); if Ed.AdapterForHilite is TATAdapterEControl then begin fmMain.InitImageListCodetree; if not fmMain.RunTreeHelper(Frame, TreeContainer.Tree, true, true) then TATAdapterEControl(Ed.AdapterForHilite).TreeFill( TreeContainer.Tree, UiOps.TreeFillMaxTimeForAPI, UiOps.TreeKeepNodesFolding, Ed.FileName, @MsgLogConsoleOnDuplicateTreeNode ); Result:= ReturnTrue; end else begin Result:= ReturnFalse; end; end; EDACTION_LEXER_SCAN: begin if Ed.Strings.IsIndexValid(NValue) then begin Ada:= nil; if Ed.AdapterForHilite is TATAdapterEControl then Ada:= TATAdapterEControl(Ed.AdapterForHilite); if Ada=nil then begin Frame:= TGroupsHelper.GetEditorFrame(Ed); //maybe frame was not yet shown-> its FInitialLexer is not yet used-> force using it if Assigned(Frame) and not Frame.WasVisible then begin Ada:= Frame.Adapter[Ed]; if Ada=nil then begin AppAllowFrameParsing:= true; Frame.DoShow; Ada:= Frame.Adapter[Ed]; end; end end; if Assigned(Ada) then Ada.ParseFromLine(NValue, true{Wait}); end; Result:= ReturnNone; end; EDACTION_APPLY_THEME: begin EditorApplyTheme(Ed); Result:= ReturnNone; end; EDACTION_LOCK: begin Ed.BeginUpdate; Result:= ReturnNone; end; EDACTION_UNLOCK: begin Ed.EndUpdate; Result:= ReturnNone; end; EDACTION_EXPORT_HTML: begin Ok:= PyHelper_ExportHtml(Ed, StrText1, bToMemory, StrMemory); if bToMemory then Result:= PyUnicodeFromString(StrMemory) else Result:= PyBool_FromLong(Ord(Ok)); end; else Result:= ReturnNone; end; end else Result:= ReturnNone; end; function api_ed_micromap(Self, Args: PPyObject): PPyObject; cdecl; var HEditor: Int64; Ed: TATSynEdit; IdAction, NTag, NWidth, NColor: integer; Column: TATMicromapColumn; NColumnCount, iColumn: integer; Ok: boolean; begin with AppPython.Engine do if Bool(PyArg_ParseTuple(Args, 'Liiii:micromap', @HEditor, @IdAction, @NTag, @NWidth, @NColor)) then begin Ed:= PyHelper_EditorFromHandle(HEditor); case IdAction of MICROMAP_GET: begin NColumnCount:= Length(Ed.Micromap.Columns); Result:= PyList_New(NColumnCount); if not Assigned(Result) then raise EPythonError.Create(msgPythonListError); for iColumn:= 0 to NColumnCount-1 do begin Column:= Ed.Micromap.Columns[iColumn]; PyList_SetItem(Result, iColumn, Py_BuildValue('{sisisisi}', 'size_perc', Column.NWidthUnits, 'size_px', Column.NRight-Column.NLeft, 'tag', Column.NTag, 'color', Column.NColor )); end; end; MICROMAP_ADD: begin Ok:= Ed.Micromap.ColumnAdd(NTag, NWidth, NColor); if Ok then Ed.Update; Result:= PyBool_FromLong(Ord(Ok)); end; MICROMAP_DELETE: begin Ok:= Ed.Micromap.ColumnDelete(NTag); if Ok then Ed.Update; Result:= PyBool_FromLong(Ord(Ok)); end; else Result:= ReturnNone; end; end else Result:= ReturnNone; end; function api_ed_folding(Self, Args: PPyObject): PPyObject; cdecl; var H: Int64; Ed: TATSynEdit; Id, NItem, NX, NY, NX2, NY2, NStaple: integer; NTag: integer; PtrText: PChar; StrText: string; Ok: boolean; begin with AppPython.Engine do if Bool(PyArg_ParseTuple(Args, 'Liiiiiiisi:folding', @H, @Id, @NItem, @NX, @NY, @NX2, @NY2, @NStaple, @PtrText, @NTag)) then begin Ed:= PyHelper_EditorFromHandle(H); StrText:= string(PtrText); case Id of FOLDING_ENUM: begin Result:= PyHelper_Folding_Enum(Ed, NY, NY2); end; FOLDING_FOLD: begin if Ed.Fold.IsIndexValid(NItem) then begin Ed.DoRangeFold(NItem); Ed.Update; end; Result:= ReturnNone; end; FOLDING_UNFOLD: begin if Ed.Fold.IsIndexValid(NItem) then begin Ed.DoRangeUnfold(NItem); Ed.Update; end; Result:= ReturnNone; end; FOLDING_UNFOLD_LINE: begin if Ed.Strings.IsIndexValid(NItem) then if Ed.IsLineFolded(NItem, true) then begin Ed.DoUnfoldLine(NItem); Ed.Update; end; Result:= ReturnNone; end; FOLDING_ADD: begin if Ed.Strings.IsIndexValid(NY) and Ed.Strings.IsIndexValid(NY2) and (NX>=0) then begin if Ed.Fold.IsIndexValid(NItem) then Ed.Fold.Insert(NItem, NX+1, NY, NX2+1, NY2, Bool(NStaple), StrText, NTag) else Ed.Fold.Add(NX+1, NY, NX2+1, NY2, Bool(NStaple), StrText, NTag); Ed.Update(true); Result:= ReturnTrue; end else Result:= ReturnFalse; end; FOLDING_DELETE: begin if Ed.Fold.IsIndexValid(NItem) then begin if Ed.Fold.ItemPtr(NItem)^.Folded then Ed.DoRangeUnfold(NItem); Ed.Fold.Delete(NItem); Ed.Update(true); end; Result:= ReturnNone; end; FOLDING_DELETE_ALL: begin Ed.Fold.Clear; Ed.Fold.ClearLineIndexer(Ed.Strings.Count); //fix #4553 Ed.DoMarkLinesVisible(0, MaxInt); Ed.Update(true); Result:= ReturnNone; end; FOLDING_FIND: begin if Ed.Strings.IsIndexValid(NY) then NX:= Ed.Fold.FindRangeWithPlusAtLine(NY); if NX>=0 then Result:= PyLong_FromLong(NX) else Result:= ReturnNone; end; FOLDING_FOLD_ALL: begin Ed.DoCommand(cCommand_FoldAll, TATCommandInvoke.AppAPI); Result:= ReturnNone; end; FOLDING_UNFOLD_ALL: begin Ed.DoCommand(cCommand_UnfoldAll, TATCommandInvoke.AppAPI); Result:= ReturnNone; end; FOLDING_FOLD_LEVEL: begin Ed.DoFoldForLevel(NItem); Result:= ReturnNone; end; FOLDING_CHECK_RANGE_INSIDE: begin Ok:= Ed.Fold.IsIndexValid(NItem) and Ed.Fold.IsIndexValid(NX) and Ed.Fold.IsRangeInsideOther(Ed.Fold.ItemPtr(NItem), Ed.Fold.ItemPtr(NX)); Result:= PyBool_FromLong(Ord(Ok)); end; FOLDING_CHECK_RANGES_SAME: begin Ok:= Ed.Fold.IsIndexValid(NItem) and Ed.Fold.IsIndexValid(NX) and Ed.Fold.IsRangesSame(Ed.Fold.ItemPtr(NItem), Ed.Fold.ItemPtr(NX)); Result:= PyBool_FromLong(Ord(Ok)); end; else Result:= ReturnNone; end end else Result:= ReturnNone; end; function api_ed_get_char_count(Self, Args: PPyObject): PPyObject; cdecl; var H: Int64; Ed: TATSynEdit; NMaxChars, NMaxTime, NResult: Int64; begin with AppPython.Engine do if Bool(PyArg_ParseTuple(Args, 'LLL:get_char_count', @H, @NMaxChars, @NMaxTime)) then begin Ed:= PyHelper_EditorFromHandle(H); NResult:= EditorGetCharCount(Ed, NMaxChars, NMaxTime); Result:= PyLong_FromLongLong(NResult); end else Result:= ReturnNone; end; type TAppApiTimer = TTimer; //TAppApiTimer = TFPTimer; function api_timer_proc(Self, Args: PPyObject): PPyObject; cdecl; const cMinInterval = 10; var NIdAction, NInterval, N: integer; PtrCallback, PtrTag: PChar; StrCallback, StrTag, StrCallbackWithPipe: string; Timer: TAppApiTimer; begin with AppPython.Engine do begin if Bool(PyArg_ParseTuple(Args, 'isis:timer_proc', @NIdAction, @PtrCallback, @NInterval, @PtrTag)) then begin StrCallback:= string(PtrCallback); StrTag:= string(PtrTag); StrCallbackWithPipe:= StrCallback+'|'; if Application.Terminated then exit(ReturnNone); if AppListTimers=nil then exit(ReturnNone); //find timer by StrCallback Timer:= nil; for N:= 0 to AppListTimers.Count-1 do begin if SBeginsWith(AppListTimers[N], StrCallbackWithPipe) then begin Timer:= TAppApiTimer(AppListTimers.Objects[N]); //timer already exists? update its tag to new value StrTag AppListTimers[N]:= StrCallbackWithPipe+StrTag; Break end; end; case NIdAction of TIMER_START, TIMER_START_ONE: begin if NInterval=0 then AppListTimers.Delete(N); Exit(ReturnTrue); end; else Result:= ReturnNone; end; end else Result:= ReturnNone; end; end; //toolbar_proc(id_toolbar, id_action, text="", text2="", command="", index=-1, index2=-1) function api_toolbar_proc(Self, Args: PPyObject): PPyObject; cdecl; var HBar: Int64; PtrText, PtrText2, PtrCmd: PChar; FToolbar: TATFlatToolbar; NAction: integer; NIndex1, NIndex2: integer; begin with AppPython.Engine do begin if Bool(PyArg_ParseTuple(Args, 'Lisssii:toolbar_proc', @HBar, @NAction, @PtrText, @PtrText2, @PtrCmd, @NIndex1, @NIndex2)) then begin FToolbar:= PyHelper_ToolbarFromId(HBar); if FToolbar=nil then exit(ReturnNone); case NAction of TOOLBAR_UPDATE: begin FToolbar.UpdateControls; Result:= ReturnNone; end; TOOLBAR_GET_BUTTON_HANDLE: begin if FToolbar.IsIndexOk(NIndex1) then Result:= PyHelper_ObjectHandle(FToolbar.Buttons[NIndex1]) else Result:= ReturnNone; end; TOOLBAR_GET_BUTTON_HANDLES: begin Result:= PyList_New(FToolbar.ButtonCount); if not Assigned(Result) then raise EPythonError.Create(msgPythonListError); for NIndex1:= 0 to FToolbar.ButtonCount-1 do PyList_SetItem(Result, NIndex1, PyHelper_ObjectHandle(FToolbar.Buttons[NIndex1])); end; TOOLBAR_GET_INDEX_HOVERED: begin Result:= PyLong_FromLong(FToolbar.ButtonWithMouseOver); end; TOOLBAR_GET_COUNT: begin Result:= PyLong_FromLong(FToolbar.ButtonCount); end; TOOLBAR_DELETE_ALL: begin TAppToolbarHelper.Clear(FToolbar); Result:= ReturnNone; end; TOOLBAR_DELETE_BUTTON: begin TAppToolbarHelper.DeleteButton(FToolbar, NIndex1); Result:= ReturnNone; end; TOOLBAR_ADD_ITEM: begin Result:= PyHelper_ObjectHandle( TAppToolbarHelper.AddButton(FToolbar, '', '', '', NIndex1, -1)); end; TOOLBAR_ADD_MENU: begin Result:= PyHelper_ObjectHandle( TAppToolbarHelper.AddMenu(FToolbar, '', '', '', NIndex1, -1)); end; TOOLBAR_GET_VERTICAL: begin Result:= PyBool_FromLong(Ord(FToolbar.Vertical)); end; TOOLBAR_SET_VERTICAL: begin FToolbar.Vertical:= Bool(NIndex1); Result:= ReturnNone; end; TOOLBAR_GET_WRAP: begin Result:= PyBool_FromLong(Ord(FToolbar.Wrapable)); end; TOOLBAR_SET_WRAP: begin FToolbar.Wrapable:= Bool(NIndex1); Result:= ReturnNone; end; TOOLBAR_GET_IMAGELIST: begin Result:= PyHelper_ObjectHandle(FToolbar.Images); end; TOOLBAR_THEME: begin ApplyThemeToToolbar(FToolbar); FToolbar.Themed:= true; Result:= ReturnNone; end; else Result:= ReturnNone; end; end else Result:= ReturnNone; end; end; //statusbar_proc(id_statusbar, id_action, index=-1, tag=0, value="") function api_statusbar_proc(Self, Args: PPyObject): PPyObject; cdecl; var HBar: Int64; PtrValue: PChar; StrValue: string; FBar: TATStatus; NAction: integer; NIndex: integer; NTag: Int64; ImgList: TImageList; Data: TATStatusData; Rect: TRect; bOk: boolean; begin with AppPython.Engine do begin if Bool(PyArg_ParseTuple(Args, 'LiiLs:statusbar_proc', @HBar, @NAction, @NIndex, @NTag, @PtrValue)) then begin StrValue:= string(PtrValue); FBar:= PyHelper_StatusbarFromId(HBar); if FBar=nil then exit(ReturnNone); if NAction<>STATUSBAR_ADD_CELL then if NTag<>0 then NIndex:= FBar.FindPanel(NTag); case NAction of STATUSBAR_GET_COUNT: Result:= PyLong_FromLong(FBar.PanelCount); STATUSBAR_DELETE_ALL: begin FBar.DeletePanels; Result:= ReturnNone; end; STATUSBAR_DELETE_CELL: begin FBar.DeletePanel(NIndex); Result:= ReturnNone; end; STATUSBAR_ADD_CELL: begin //check that tag is not busy if NTag<>0 then if FBar.FindPanel(NTag)>=0 then exit(ReturnNone); FBar.AddPanel(NIndex, 100, taLeftJustify, '', -1, NTag); if NIndex<0 then Result:= PyLong_FromLong(FBar.PanelCount-1) else Result:= PyLong_FromLong(NIndex); end; STATUSBAR_FIND_CELL: begin NTag:= StrToIntDef(StrValue, -1); NIndex:= FBar.FindPanel(NTag); if NIndex>=0 then Result:= PyLong_FromLong(NIndex) else Result:= ReturnNone; end; STATUSBAR_SET_IMAGELIST: begin ImgList:= PyHelper_ImagelistFromId(StrValue); FBar.Images:= ImgList; FBar.Invalidate; Result:= ReturnNone; end; STATUSBAR_GET_IMAGELIST: begin ImgList:= FBar.Images; Result:= PyHelper_ObjectHandle(ImgList); end; STATUSBAR_SET_PADDING: begin FBar.Padding:= StrToIntDef(StrValue, FBar.Padding); FBar.Invalidate; Result:= ReturnNone; end; STATUSBAR_GET_PADDING: begin Result:= PyLong_FromLong(FBar.Padding); end; STATUSBAR_SET_SEPARATOR: begin FBar.SeparatorString:= StrValue; FBar.Invalidate; Result:= ReturnNone; end; STATUSBAR_GET_SEPARATOR: begin Result:= PyUnicodeFromString(FBar.SeparatorString); end; STATUSBAR_SET_OVERFLOW_LEFT: begin FBar.OverflowLeft:= AppStrToBool(StrValue); FBar.Invalidate; Result:= ReturnNone; end; STATUSBAR_GET_OVERFLOW_LEFT: begin Result:= PyBool_FromLong(Ord(FBar.OverflowLeft)); end; STATUSBAR_SET_CELL_SIZE: begin Data:= FBar.GetPanelData(NIndex); if Assigned(Data) then begin Data.Width:= StrToIntDef(StrValue, 100); FBar.Invalidate; end; Result:= ReturnNone; end; STATUSBAR_SET_CELL_ALIGN: begin Data:= FBar.GetPanelData(NIndex); if Assigned(Data) then begin Data.Align:= AppStringToAlignment(StrValue); FBar.Invalidate; end; Result:= ReturnNone; end; STATUSBAR_SET_CELL_TEXT: begin Data:= FBar.GetPanelData(NIndex); if Assigned(Data) then begin Data.Caption:= StrValue; FBar.Invalidate; end; Result:= ReturnNone; end; STATUSBAR_SET_CELL_HINT: begin Data:= FBar.GetPanelData(NIndex); if Assigned(Data) then begin Data.Hint:= StrValue; end; Result:= ReturnNone; end; STATUSBAR_SET_CELL_IMAGEINDEX: begin Data:= FBar.GetPanelData(NIndex); if Assigned(Data) then begin Data.ImageIndex:= StrToIntDef(StrValue, -1); FBar.Invalidate; end; Result:= ReturnNone; end; STATUSBAR_MOVE_CELL: begin bOk:= FBar.MovePanel( NIndex, StrToIntDef(StrValue, -1) ); Result:= PyBool_FromLong(Ord(bOk)); end; STATUSBAR_SET_CELL_COLOR_BACK: begin Data:= FBar.GetPanelData(NIndex); if Assigned(Data) then begin Data.ColorBack:= StrToIntDef(StrValue, clWhite); FBar.Invalidate; end; Result:= ReturnNone; end; STATUSBAR_SET_CELL_COLOR_FONT: begin Data:= FBar.GetPanelData(NIndex); if Assigned(Data) then begin Data.ColorFont:= StrToIntDef(StrValue, clBlack); FBar.Invalidate; end; Result:= ReturnNone; end; STATUSBAR_SET_CELL_COLOR_LINE: begin Data:= FBar.GetPanelData(NIndex); if Assigned(Data) then begin Data.ColorLine:= StrToIntDef(StrValue, clNone); FBar.Invalidate; end; Result:= ReturnNone; end; STATUSBAR_SET_CELL_COLOR_LINE2: begin Data:= FBar.GetPanelData(NIndex); if Assigned(Data) then begin Data.ColorLine2:= StrToIntDef(StrValue, clNone); FBar.Invalidate; end; Result:= ReturnNone; end; STATUSBAR_SET_CELL_TAG: begin Data:= FBar.GetPanelData(NIndex); if Assigned(Data) then begin Data.Tag:= StrToInt64Def(StrValue, 0); FBar.Invalidate; end; Result:= ReturnNone; end; STATUSBAR_SET_CELL_AUTOSIZE: begin Data:= FBar.GetPanelData(NIndex); if Assigned(Data) then begin Data.AutoSize:= AppStrToBool(StrValue); FBar.Invalidate; end; Result:= ReturnNone; end; STATUSBAR_SET_CELL_AUTOSTRETCH: begin Data:= FBar.GetPanelData(NIndex); if Assigned(Data) then begin Data.AutoStretch:= AppStrToBool(StrValue); FBar.Invalidate; end; Result:= ReturnNone; end; STATUSBAR_SET_CELL_FONT_NAME: begin Data:= FBar.GetPanelData(NIndex); if Assigned(Data) then begin Data.FontName:= StrValue; FBar.Invalidate; end; Result:= ReturnNone; end; STATUSBAR_SET_CELL_FONT_SIZE: begin Data:= FBar.GetPanelData(NIndex); if Assigned(Data) then begin Data.FontSize:= StrToIntDef(StrValue, 0); FBar.Invalidate; end; Result:= ReturnNone; end; STATUSBAR_SET_CELL_CALLBACK: begin Data:= FBar.GetPanelData(NIndex); if Assigned(Data) then begin Data.Callback:= StrValue; Data.HotTrack:= StrValue<>''; end; Result:= ReturnNone; end; STATUSBAR_SET_CELL_OVERLAY: begin Data:= FBar.GetPanelData(NIndex); if Assigned(Data) then begin Data.OverlayText:= StrValue; FBar.Invalidate; end; Result:= ReturnNone; end; STATUSBAR_GET_CELL_SIZE: begin Data:= FBar.GetPanelData(NIndex); if Assigned(Data) then Result:= PyLong_FromLong(Data.Width) else Result:= ReturnNone; end; STATUSBAR_GET_CELL_ALIGN: begin Data:= FBar.GetPanelData(NIndex); if Assigned(Data) then Result:= PyUnicodeFromString(AppAlignmentToString(Data.Align)) else Result:= ReturnNone; end; STATUSBAR_GET_CELL_TEXT: begin Data:= FBar.GetPanelData(NIndex); if Assigned(Data) then Result:= PyUnicodeFromString(Data.Caption) else Result:= ReturnNone; end; STATUSBAR_GET_CELL_HINT: begin Data:= FBar.GetPanelData(NIndex); if Assigned(Data) then Result:= PyUnicodeFromString(Data.Hint) else Result:= ReturnNone; end; STATUSBAR_GET_CELL_IMAGEINDEX: begin Data:= FBar.GetPanelData(NIndex); if Assigned(Data) then Result:= PyLong_FromLong(Data.ImageIndex) else Result:= ReturnNone; end; STATUSBAR_GET_CELL_COLOR_BACK: begin Data:= FBar.GetPanelData(NIndex); if Assigned(Data) then Result:= PyLong_FromLong(Data.ColorBack) else Result:= ReturnNone; end; STATUSBAR_GET_CELL_COLOR_FONT: begin Data:= FBar.GetPanelData(NIndex); if Assigned(Data) then Result:= PyLong_FromLong(Data.ColorFont) else Result:= ReturnNone; end; STATUSBAR_GET_CELL_COLOR_LINE: begin Data:= FBar.GetPanelData(NIndex); if Assigned(Data) then Result:= PyLong_FromLong(Data.ColorLine) else Result:= ReturnNone; end; STATUSBAR_GET_CELL_COLOR_LINE2: begin Data:= FBar.GetPanelData(NIndex); if Assigned(Data) then Result:= PyLong_FromLong(Data.ColorLine2) else Result:= ReturnNone; end; STATUSBAR_GET_CELL_TAG: begin Data:= FBar.GetPanelData(NIndex); if Assigned(Data) then Result:= PyLong_FromLongLong(Data.Tag) else Result:= ReturnNone; end; STATUSBAR_GET_CELL_AUTOSIZE: begin Data:= FBar.GetPanelData(NIndex); if Assigned(Data) then Result:= PyBool_FromLong(Ord(Data.AutoSize)) else Result:= ReturnNone; end; STATUSBAR_GET_CELL_AUTOSTRETCH: begin Data:= FBar.GetPanelData(NIndex); if Assigned(Data) then Result:= PyBool_FromLong(Ord(Data.AutoStretch)) else Result:= ReturnNone; end; STATUSBAR_GET_CELL_FONT_NAME: begin Data:= FBar.GetPanelData(NIndex); if Assigned(Data) then Result:= PyUnicodeFromString(Data.FontName) else Result:= ReturnNone; end; STATUSBAR_GET_CELL_FONT_SIZE: begin Data:= FBar.GetPanelData(NIndex); if Assigned(Data) then Result:= PyLong_FromLong(Data.FontSize) else Result:= ReturnNone; end; STATUSBAR_GET_CELL_CALLBACK: begin Data:= FBar.GetPanelData(NIndex); if Assigned(Data) then Result:= PyUnicodeFromString(Data.Callback) else Result:= ReturnNone; end; STATUSBAR_GET_CELL_OVERLAY: begin Data:= FBar.GetPanelData(NIndex); if Assigned(Data) then Result:= PyUnicodeFromString(Data.OverlayText) else Result:= ReturnNone; end; STATUSBAR_GET_CELL_RECT: begin if FBar.IsIndexOk(NIndex) then begin Rect:= FBar.GetPanelRect(NIndex); Result:= PyHelper_Rect(Rect); end else Result:= ReturnNone; end; //get color STATUSBAR_GET_COLOR_BACK: begin Result:= PyLong_FromLong(FBar.Color); end; STATUSBAR_GET_COLOR_BORDER_TOP: begin Result:= PyLong_FromLong(FBar.ColorBorderTop); end; STATUSBAR_GET_COLOR_BORDER_BOTTOM: begin Result:= PyLong_FromLong(FBar.ColorBorderBottom); end; STATUSBAR_GET_COLOR_BORDER_L: begin Result:= PyLong_FromLong(FBar.ColorBorderL); end; STATUSBAR_GET_COLOR_BORDER_R: begin Result:= PyLong_FromLong(FBar.ColorBorderR); end; STATUSBAR_GET_COLOR_BORDER_U: begin Result:= PyLong_FromLong(FBar.ColorBorderU); end; STATUSBAR_GET_COLOR_BORDER_D: begin Result:= PyLong_FromLong(FBar.ColorBorderD); end; //set color STATUSBAR_SET_COLOR_BACK: begin FBar.Color:= StrToIntDef(StrValue, FBar.Color); FBar.Invalidate; Result:= ReturnNone; end; STATUSBAR_SET_COLOR_BORDER_TOP: begin FBar.ColorBorderTop:= StrToIntDef(StrValue, FBar.ColorBorderTop); FBar.Invalidate; Result:= ReturnNone; end; STATUSBAR_SET_COLOR_BORDER_BOTTOM: begin FBar.ColorBorderBottom:= StrToIntDef(StrValue, FBar.ColorBorderBottom); FBar.Invalidate; Result:= ReturnNone; end; STATUSBAR_SET_COLOR_BORDER_L: begin FBar.ColorBorderL:= StrToIntDef(StrValue, FBar.ColorBorderL); FBar.Invalidate; Result:= ReturnNone; end; STATUSBAR_SET_COLOR_BORDER_R: begin FBar.ColorBorderR:= StrToIntDef(StrValue, FBar.ColorBorderR); FBar.Invalidate; Result:= ReturnNone; end; STATUSBAR_SET_COLOR_BORDER_U: begin FBar.ColorBorderU:= StrToIntDef(StrValue, FBar.ColorBorderU); FBar.Invalidate; Result:= ReturnNone; end; STATUSBAR_SET_COLOR_BORDER_D: begin FBar.ColorBorderD:= StrToIntDef(StrValue, FBar.ColorBorderD); FBar.Invalidate; Result:= ReturnNone; end; else Result:= ReturnNone; end; end else Result:= ReturnNone; end; end; type TFormHack = class(TFormDummy); //dlg_proc(id_dialog, id_action, prop='', index=-1, index2=-1, name='') function api_dlg_proc(Self, Args: PPyObject): PPyObject; cdecl; var FormHandle: Int64; Form: TFormDummy; Obj: TObject; PtrProp, PtrName: PChar; StrProp, StrName: string; NAction: integer; NIndex, NIndex2: Int64; Ctl: TControl; Pnt: TPoint; Num64: Int64; i: integer; begin with AppPython.Engine do begin if Bool(PyArg_ParseTuple(Args, 'LisLLs:dlg_proc', @FormHandle, @NAction, @PtrProp, @NIndex, @NIndex2, @PtrName)) then begin StrProp:= string(PtrProp); StrName:= string(PtrName); Form:= nil; if FormHandle<>0 then begin Obj:= TObject(PtrInt(FormHandle)); if not (Obj is TFormDummy) then begin if Assigned(Obj) then MsgLogConsole('ERROR: dlg_proc() gets bad handle, of type '+Obj.ClassName); exit(ReturnNone); end; Form:= TFormDummy(Obj); Obj:= nil; end else if NAction<>DLG_CREATE then begin MsgLogConsole('ERROR: dlg_proc() gets zero handle'); exit(ReturnNone); end; //find control by name, then by index Ctl:= nil; case NAction of DLG_CTL_PROP_GET, DLG_CTL_PROP_SET, DLG_CTL_DELETE, DLG_CTL_FOCUS, DLG_CTL_HANDLE: begin if StrName<>'' then Ctl:= Form.FindControlByOurName(StrName) else Ctl:= Form.FindControlByIndex(NIndex); end; end; case NAction of DLG_CREATE: begin Form:= TFormDummy.Create(fmMain); Result:= PyHelper_ObjectHandle(Form); end; DLG_FREE: begin if Form.Visible then Form.Hide; Form.Free; Result:= ReturnNone; end; DLG_SHOW_MODAL: begin CloseFormAutoCompletion; //don't do ShowModal for docked forms, this hangs the app if Form.Parent=nil then begin AppFormPutToVisibleArea(Form); Form.DoEmulatedModalShow; Form.ShowInTaskBar:= Form.ShowInTaskbar_Pending; //after xxShow, for #4456 end else MsgLogConsole('ERROR: dlg_proc(...DLG_SHOW_MODAL...) was called for docked form'); Result:= ReturnNone; end; DLG_SHOW_NONMODAL: begin CloseFormAutoCompletion; AppFormPutToVisibleArea(Form); {$ifdef windows} //ifdef for windows is to fix issue #5397, patch by veksha Form.ShowInTaskBar:= Form.ShowInTaskbar_Pending; RecreateWnd(Form); Form.Show; {$else} Form.Show; Form.ShowInTaskBar:= Form.ShowInTaskbar_Pending; //after Show, for #4456 {$endif} Result:= ReturnNone; end; DLG_HIDE: begin //DoForm_CloseDockedForms(Form); //not needed Form.Close; Result:= ReturnNone; end; DLG_LOCK: begin Form.DisableAutoSizing; Result:= ReturnNone; end; DLG_UNLOCK: begin if TFormHack(Form).AutoSizingLockCount>0 then //check to avoid exception if Unlock was called more times Form.EnableAutoSizing; Result:= ReturnNone; end; DLG_PROP_GET: begin Result:= DoForm_GetPropsAsStringDict(Form); end; DLG_PROP_SET: begin DoForm_SetPropsFromStringDict(Form, StrProp); Result:= ReturnNone; end; DLG_CTL_COUNT: begin Result:= PyLong_FromLong(Form.ComponentCount); end; DLG_CTL_ADD: begin DoControl_CreateNew(StrProp, Form, Ctl); if Assigned(Ctl) then begin Ctl.Parent:= Form; DoForm_AdjustLabelForNewControl(Form, Ctl); Result:= PyLong_FromLong(Form.ComponentCount-1); end else Result:= ReturnNone; end; DLG_CTL_PROP_GET: begin if Assigned(Ctl) then Result:= DoControl_GetPropsAsStringDict(Ctl) else Result:= ReturnNone; end; DLG_CTL_PROP_SET: begin if Assigned(Ctl) then begin Form.BlockedOnChange:= true; Form.BlockedOnSelect_Listview:= true; Form.BlockedOnSelect_Treeview:= true; try DoControl_SetPropsFromStringDict(Ctl, StrProp); finally Form.BlockedOnChange:= false; Form.BlockedOnSelect_Listview:= false; Form.BlockedOnSelect_Treeview:= false; end; end; Result:= ReturnNone; end; DLG_CTL_DELETE: begin if Assigned(Ctl) then Ctl.Free; Result:= ReturnNone; end; DLG_CTL_DELETE_ALL: begin for i:= Form.ComponentCount-1 downto 0 do Form.Components[i].Free; Result:= ReturnNone; end; DLG_FOCUS: begin if Form.Visible and Form.Enabled then Form.SetFocus; Result:= ReturnNone; end; DLG_SCALE: begin DoForm_ScaleAuto(Form); Result:= ReturnNone; end; DLG_DOCK: begin Form.PrevBorderStyle:= Form.BorderStyle; Form.BorderStyle:= bsNone; if NIndex=0 then Form.Parent:= fmMain else begin Obj:= TObject(PtrInt(NIndex)); if not (Obj is TForm) and not (Obj is TFrame) then begin MsgLogConsole('ERROR: dlg_proc(...DLG_DOCK...) gets bad form handle, of type '+Obj.ClassName); exit(ReturnNone); end; Form.Parent:= TForm(Obj); end; if StrProp='L' then Form.Align:= alLeft else if StrProp='R' then Form.Align:= alRight else if StrProp='T' then Form.Align:= alTop else Form.Align:= alBottom; Result:= ReturnNone; end; DLG_UNDOCK: begin Form.Parent:= nil; Form.BorderStyle:= Form.PrevBorderStyle; Result:= ReturnNone; end; DLG_TO_FRONT: begin Form.BringToFront; Result:= ReturnNone; end; DLG_CTL_FOCUS: begin if Assigned(Ctl) then DoForm_FocusControl(Form, Ctl); Result:= ReturnNone; end; DLG_CTL_FIND: begin Result:= PyLong_FromLong(Form.FindControlIndexByOurName(StrProp)); end; DLG_CTL_HANDLE: begin if Assigned(Ctl) then Result:= PyHelper_ObjectHandle(Ctl) else Result:= ReturnNone; end; DLG_CTL_TO_FRONT: begin if Assigned(Ctl) then Ctl.BringToFront; Result:= ReturnNone; end; DLG_CTL_TO_BACK: begin if Assigned(Ctl) then Ctl.SendToBack; Result:= ReturnNone; end; DLG_COORD_LOCAL_TO_SCREEN: begin Pnt:= Point(NIndex, NIndex2); Pnt:= Form.ClientToScreen(Pnt); Result:= Py_BuildValue('(ii)', Pnt.X, Pnt.Y); end; DLG_COORD_SCREEN_TO_LOCAL: begin Pnt:= Point(NIndex, NIndex2); Pnt:= Form.ScreenToClient(Pnt); Result:= Py_BuildValue('(ii)', Pnt.X, Pnt.Y); end; else Result:= ReturnNone; end; end; end; end; //finder_proc(id_finder, id_action, value="", setcaret=True) function api_finder_proc(Self, Args: PPyObject): PPyObject; cdecl; const cDefIndent=2; var IdFinder: Int64; IdAction: integer; Finder: TATEditorFinder; PtrValue: PChar; StrValue: string; NSetCaret: integer; NValue: Int64; bSetCaret: boolean; bResult, bChanged: boolean; Pnt1, Pnt2, PntAfter: TPoint; ResList: TATFinderResults; ResItem: TATFinderResult; ResList2: TATFinderResults2; ResItem2: TATFinderResult2; Sep: TATStringSeparator; Caret: TATCaretItem; OldX, OldY: integer; OldFromCaret, OldBack: boolean; Obj: TObject; i: integer; begin with AppPython.Engine do if Bool(PyArg_ParseTuple(Args, 'Lisi:finder_proc', @IdFinder, @IdAction, @PtrValue, @NSetCaret)) then begin StrValue:= string(PtrValue); bSetCaret:= Bool(NSetCaret); if (IdFinder=0) and (IdAction<>FINDER_CREATE) then begin MsgLogConsole('ERROR: finder_proc() gets handle==0'); exit(ReturnNone); end; Obj:= TObject(PtrInt(IdFinder)); if (IdAction<>FINDER_CREATE) and not (Obj is TATEditorFinder) then begin MsgLogConsole('ERROR: finder_proc() gets bad handle, of type '+Obj.ClassName); exit(ReturnNone); end; Finder:= TATEditorFinder(Obj); if IdAction in [ FINDER_FIND, FINDER_FIND_ALL, FINDER_FIND_REP, FINDER_REP_ALL, FINDER_REP_ALL_EX, FINDER_COUNT ] then begin if Finder.Editor=nil then exit(ReturnNone); if Finder.Editor.Carets.Count=0 then exit(ReturnNone); if Finder.StrFind='' then exit(ReturnNone); end; case IdAction of FINDER_CREATE: begin Finder:= TATEditorFinder.Create; Finder.OnConfirmReplace:= @fmMain.FinderOnConfirmReplace_API; Result:= PyHelper_ObjectHandle(Finder); end; FINDER_FREE: begin FreeAndNil(Finder); Result:= ReturnNone; end; FINDER_CLEAR: begin Finder.Clear; Result:= ReturnNone; end; FINDER_SET_FINDTEXT: begin Finder.StrFind:= UTF8Decode(StrValue); Result:= ReturnNone; end; FINDER_GET_FINDTEXT: begin Result:= PyUnicodeFromString(Finder.StrFind); end; FINDER_SET_REPTEXT: begin Finder.StrReplace:= UTF8Decode(StrValue); Result:= ReturnNone; end; FINDER_GET_REPTEXT: begin Result:= PyUnicodeFromString(Finder.StrReplace); end; FINDER_SET_ED: begin NValue:= StrToInt64Def(StrValue, -1); //0 is allowed, ed's handle if NValue=-1 then exit(ReturnNone); Finder.Editor:= PyHelper_EditorFromHandle(NValue); Result:= ReturnNone; end; FINDER_GET_ED: begin Result:= PyHelper_ObjectHandle(Finder.Editor); end; FINDER_SET_OPT: begin ConvertFinderOptionsFromString(Finder, StrValue); Result:= ReturnNone; end; FINDER_GET_OPT: begin Result:= PyUnicodeFromString(ConvertFinderOptionsToString(Finder)); end; FINDER_SET_MAXLEN: begin NValue:= StrToIntDef(StrValue, 0); if NValue>0 then Finder.MaxLineLen:= NValue; Result:= ReturnNone; end; FINDER_GET_MAXLEN: begin Result:= PyLong_FromLong(Finder.MaxLineLen); end; FINDER_SET_CARETS: begin Finder.VirtualCaretsAsString:= StrValue; Result:= ReturnNone; end; FINDER_GET_CARETS: begin Result:= PyUnicodeFromString(Finder.VirtualCaretsAsString); end; FINDER_SET_INDENTS: begin Sep.Init(StrValue); Sep.GetItemInt(i, cDefIndent); Finder.IndentHorz:= i; Sep.GetItemInt(i, cDefIndent); Finder.IndentVert:= i; Result:= ReturnNone; end; FINDER_GET_INDENTS: begin Result:= Py_BuildValue('(ii)', Finder.IndentHorz, Finder.IndentVert); end; FINDER_SET_TAG: begin Finder.DataString:= StrValue; Result:= ReturnNone; end; FINDER_GET_TAG: begin Result:= PyUnicodeFromString(Finder.DataString); end; FINDER_SET_ON_REPLACE: begin Finder.CallbackString:= StrValue; Result:= ReturnNone; end; FINDER_GET_ON_REPLACE: begin Result:= PyUnicodeFromString(Finder.CallbackString); end; FINDER_FIND: begin bResult:= Finder.DoAction_FindOrReplace(false, false, bChanged, bSetCaret); if bResult then begin Pnt1:= Finder.MatchEdPos; Pnt2:= Finder.MatchEdEnd; if bSetCaret then begin Finder.Editor.DoShowPos(Pnt1, Finder.IndentHorz, Finder.IndentVert, true, false, true); Finder.Editor.Update; end; Result:= Py_BuildValue('(iiii)', Pnt1.X, Pnt1.Y, Pnt2.X, Pnt2.Y); end else if Finder.IsRegexBad then Result:= ReturnFalse else Result:= ReturnNone; end; FINDER_FIND_REP: begin bResult:= Finder.DoAction_FindOrReplace(true, false, bChanged, bSetCaret); if bResult then begin Pnt1:= Finder.MatchEdPos; Pnt2:= Finder.MatchEdEnd; if bChanged then PntAfter:= Finder.MatchEdPosAfterRep else PntAfter:= Point(-1, -1); if bSetCaret then Finder.Editor.DoShowPos(Pnt1, Finder.IndentHorz, Finder.IndentVert, true, false, true); if bSetCaret or bChanged then Finder.Editor.Update(bChanged); Result:= Py_BuildValue('(iiiiii)', Pnt1.X, Pnt1.Y, Pnt2.X, Pnt2.Y, PntAfter.X, PntAfter.Y); end else if Finder.IsRegexBad then Result:= ReturnFalse else Result:= ReturnNone; end; FINDER_FIND_ALL: begin ResList:= TATFinderResults.Create; try Finder.DoAction_FindAll(ResList, true); if (ResList.Count=0) and Finder.IsRegexBad then Result:= ReturnFalse else begin Result:= PyList_New(ResList.Count); if not Assigned(Result) then raise EPythonError.Create(msgPythonListError); for i:= 0 to ResList.Count-1 do begin ResItem:= ResList[i]; PyList_SetItem(Result, i, Py_BuildValue('(iiii)', ResItem.PosBegin.X, ResItem.PosBegin.Y, ResItem.PosEnd.X, ResItem.PosEnd.Y )); end; end; finally FreeAndNil(ResList); end; end; FINDER_COUNT: begin i:= Finder.DoAction_CountAll(false); if (i=0) and Finder.IsRegexBad then Result:= ReturnFalse else Result:= PyLong_FromLong(i); end; FINDER_REP_ALL: begin i:= Finder.DoAction_ReplaceAll; if (i=0) and Finder.IsRegexBad then Result:= ReturnFalse else begin Finder.Editor.Update(i>0); Result:= PyLong_FromLong(i); end; end; FINDER_REP_ALL_EX: begin if Finder.Editor.Carets.Count>0 then begin Caret:= Finder.Editor.Carets[0]; OldX:= Caret.PosX; OldY:= Caret.PosY; end else begin OldX:= 0; OldY:= 0; end; OldFromCaret:= Finder.OptFromCaret; OldBack:= Finder.OptBack; Finder.OptFromCaret:= true; Finder.OptBack:= false; ResList2:= TATFinderResults2.Create; try bResult:= Finder.DoAction_FindOrReplace(true, false, bChanged, true); if not bResult then begin if Finder.IsRegexBad then exit(ReturnFalse) else exit(PyList_New(0)); end; repeat ResItem2.Pos:= Finder.MatchEdPos; ResItem2.PosEnd:= Finder.MatchEdEnd; if bChanged then ResItem2.PosAfter:= Finder.MatchEdPosAfterRep else ResItem2.PosAfter:= Point(-1, -1); ResList2.Add(ResItem2); bResult:= Finder.DoAction_FindOrReplace(true, false, bChanged, true); until not bResult; Result:= PyList_New(ResList2.Count); if not Assigned(Result) then raise EPythonError.Create(msgPythonListError); for i:= 0 to ResList2.Count-1 do begin ResItem2:= ResList2[i]; PyList_SetItem(Result, i, Py_BuildValue('(iiiiii)', ResItem2.Pos.X, ResItem2.Pos.Y, ResItem2.PosEnd.X, ResItem2.PosEnd.Y, ResItem2.PosAfter.X, ResItem2.PosAfter.Y )); end; finally FreeAndNil(ResList2); end; Finder.Editor.DoCaretSingle(OldX, OldY); Finder.Editor.Update(true); Finder.OptFromCaret:= OldFromCaret; Finder.OptBack:= OldBack; end; else Result:= ReturnNone; end; end else Result:= ReturnNone; end; //func at end (uses funcs above) procedure TfmMain.PythonModuleInitialization(Sender: TObject); begin with Sender as TPythonModule do begin AddMethod('app_ver', @api_app_ver, ''); AddMethod('app_path', @api_app_path, ''); AddMethod('app_proc', @api_app_proc, ''); AddMethod('app_log', @api_app_log, ''); AddMethod('app_idle', @api_app_idle, ''); AddMethod('emmet', @api_emmet, ''); AddMethod('msg_status', @api_msg_status, ''); AddMethod('msg_status_alt', @api_msg_status_alt, ''); AddMethod('msg_box', @api_msg_box, ''); AddMethod('msg_box_ex', @api_msg_box_ex, ''); AddMethod('dlg_input', @api_dlg_input, ''); AddMethod('dlg_input_ex', @api_dlg_input_ex, ''); AddMethod('dlg_file', @api_dlg_file, ''); AddMethod('dlg_dir', @api_dlg_dir, ''); AddMethod('dlg_menu', @api_dlg_menu, ''); AddMethod('dlg_color', @api_dlg_color, ''); AddMethod('dlg_hotkey', @api_dlg_hotkey, ''); AddMethod('dlg_hotkeys', @api_dlg_hotkeys, ''); AddMethod('dlg_custom', @api_dlg_custom, ''); AddMethod('dlg_commands', @api_dlg_commands, ''); AddMethod('ed_get_carets', @api_ed_get_carets, ''); AddMethod('ed_set_caret', @api_ed_set_caret, ''); AddMethod('ed_get_sel_mode', @api_ed_get_sel_mode, ''); AddMethod('ed_get_sel_rect', @api_ed_get_sel_rect, ''); AddMethod('ed_get_sel_lines', @api_ed_get_sel_lines, ''); AddMethod('ed_set_sel_rect', @api_ed_set_sel_rect, ''); AddMethod('ed_get_text_all', @api_ed_get_text_all, ''); AddMethod('ed_set_text_all', @api_ed_set_text_all, ''); AddMethod('ed_get_text_sel', @api_ed_get_text_sel, ''); AddMethod('ed_get_text_line', @api_ed_get_text_line, ''); AddMethod('ed_set_text_line', @api_ed_set_text_line, ''); AddMethod('ed_get_text_substr', @api_ed_get_text_substr, ''); AddMethod('ed_get_line_len', @api_ed_get_line_len, ''); AddMethod('ed_get_line_count', @api_ed_get_line_count, ''); AddMethod('ed_get_char_count', @api_ed_get_char_count, ''); AddMethod('ed_get_line_end', @api_ed_get_line_end, ''); AddMethod('ed_set_line_end', @api_ed_set_line_end, ''); AddMethod('ed_delete', @api_ed_delete, ''); AddMethod('ed_insert', @api_ed_insert, ''); AddMethod('ed_replace', @api_ed_replace, ''); AddMethod('ed_replace_lines', @api_ed_replace_lines, ''); AddMethod('ed_get_filename', @api_ed_get_filename, ''); AddMethod('ed_get_prop', @api_ed_get_prop, ''); AddMethod('ed_set_prop', @api_ed_set_prop, ''); AddMethod('ed_folding', @api_ed_folding, ''); AddMethod('ed_get_sublexer_ranges', @api_ed_get_sublexer_ranges, ''); AddMethod('ed_get_token', @api_ed_get_token, ''); AddMethod('ed_get_wrapinfo', @api_ed_get_wrapinfo, ''); AddMethod('ed_save', @api_ed_save, ''); AddMethod('ed_load', @api_ed_load, ''); AddMethod('ed_cmd', @api_ed_cmd, ''); AddMethod('ed_bookmark', @api_ed_bookmark, ''); AddMethod('ed_decor', @api_ed_decor, ''); AddMethod('ed_focus', @api_ed_focus, ''); AddMethod('ed_complete', @api_ed_complete, ''); AddMethod('ed_complete_alt', @api_ed_complete_alt, ''); AddMethod('ed_convert', @api_ed_convert, ''); AddMethod('ed_markers', @api_ed_markers, ''); AddMethod('ed_attr', @api_ed_attr, ''); AddMethod('ed_gap', @api_ed_gap, ''); AddMethod('ed_dim', @api_ed_dim, ''); AddMethod('ed_hotspots', @api_ed_hotspots, ''); AddMethod('ed_action', @api_ed_action, ''); AddMethod('ed_micromap', @api_ed_micromap, ''); AddMethod('file_open', @api_file_open, ''); AddMethod('ed_handles', @api_ed_handles, ''); AddMethod('ed_group', @api_ed_group, ''); AddMethod('ini_read', @api_ini_read, ''); AddMethod('ini_write', @api_ini_write, ''); AddMethod('ini_proc', @api_ini_proc, ''); AddMethod('lexer_proc', @api_lexer_proc, ''); AddMethod('tree_proc', @api_tree_proc, ''); AddMethod('menu_proc', @api_menu_proc, ''); AddMethod('toolbar_proc', @api_toolbar_proc, ''); AddMethod('statusbar_proc', @api_statusbar_proc, ''); AddMethod('listbox_proc', @api_listbox_proc, ''); AddMethod('canvas_proc', @api_canvas_proc, ''); AddMethod('bitmap_proc', @api_bitmap_proc, ''); AddMethod('timer_proc', @api_timer_proc, ''); AddMethod('dlg_proc', @api_dlg_proc, ''); AddMethod('imagelist_proc', @api_imagelist_proc, ''); AddMethod('image_proc', @api_image_proc, ''); AddMethod('button_proc', @api_button_proc, ''); AddMethod('finder_proc', @api_finder_proc, ''); end; end; function PyHelper_DialogColorPicker(AColor: integer): integer; var SCaption: string; Par1, Par2, Obj: PPyObject; begin Result:= -1; if not AppPython.Inited then exit; with TIniFile.Create(AppFile_Language) do try SCaption:= ReadString('d_about', '_clr', 'Colors'); finally Free end; with AppPython.Engine do begin Par1:= PyUnicodeFromString(SCaption); Par2:= PyLong_FromLong(AColor); Obj:= AppPython.RunModuleFunction('cuda_palette', 'dlg_color_palette', [Par1, Par2]); if Assigned(Obj) then try if PyLong_Check(Obj) then Result:= PyLong_AsLong(Obj); finally Py_DECREF(Obj); end; end; end;