MSX Editor Access


#1

Hi, I try to do some work with MSX Editor.
1)
–find structure by name in opened script --OK
–go to end of struct --OK
–insert new function like > , fn newFuncrion = ("") --OK
2)
–it will be nice to add a function which will select all word occurences in whole script --TODO

I would like to say thanks to denisT and Serejah, for wery nice examples of Assembly implementation

for now I have some Command ID List

Global mcWinMsg
struct MICRA_WINDOWS_MESSAGES (

	WM_NULL = 0x0000,
	WM_CREATE = 0x0001,
	WM_DESTROY = 0x0002,
	WM_MOVE = 0x0003,
	WM_SIZE = 0x0005,
	WM_ACTIVATE = 0x0006,
	WM_SETFOCUS = 0x0007,
	WM_KILLFOCUS = 0x0008,
	WM_ENABLE = 0x000A,
	WM_SETREDRAW = 0x000B,
	WM_SETTEXT = 0x000C,
	WM_GETTEXT = 0x000D,
	WM_GETTEXTLENGTH = 0x000E,
	WM_PAINT = 0x000F,
	WM_CLOSE = 0x0010,
	WM_QUERYENDSESSION = 0x0011,
	WM_QUERYOPEN = 0x0013,
	WM_ENDSESSION = 0x0016,
	WM_QUIT = 0x0012,
	WM_ERASEBKGND = 0x0014,
	WM_SYSCOLORCHANGE = 0x0015,
	WM_SHOWWINDOW = 0x0018,
	WM_WININICHANGE = 0x001A,
	WM_SETTINGCHANGE = WM_WININICHANGE,
	WM_DEVMODECHANGE = 0x001B,
	WM_ACTIVATEAPP = 0x001C,
	WM_FONTCHANGE = 0x001D,
	WM_TIMECHANGE = 0x001E,
	WM_CANCELMODE = 0x001F,
	WM_SETCURSOR = 0x0020,
	WM_MOUSEACTIVATE = 0x0021,
	WM_CHILDACTIVATE = 0x0022,
	WM_QUEUESYNC = 0x0023,
	WM_GETMINMAXINFO = 0x0024,
	WM_PAINTICON = 0x0026,
	WM_ICONERASEBKGND = 0x0027,
	WM_NEXTDLGCTL = 0x0028,
	WM_SPOOLERSTATUS = 0x002A,
	WM_DRAWITEM = 0x002B,
	WM_MEASUREITEM = 0x002C,
	WM_DELETEITEM = 0x002D,
	WM_VKEYTOITEM = 0x002E,
	WM_CHARTOITEM = 0x002F,
	WM_SETFONT = 0x0030,
	WM_GETFONT = 0x0031,
	WM_SETHOTKEY = 0x0032,
	WM_GETHOTKEY = 0x0033,
	WM_QUERYDRAGICON = 0x0037,
	WM_COMPAREITEM = 0x0039,
	WM_GETOBJECT = 0x003D,
	WM_COMPACTING = 0x0041,
	WM_COMMNOTIFY = 0x0044,
	WM_WINDOWPOSCHANGING = 0x0046,
	WM_WINDOWPOSCHANGED = 0x0047,
	WM_POWER = 0x0048,
	WM_COPYDATA = 0x004A,
	WM_CANCELJOURNAL = 0x004B,
	WM_NOTIFY = 0x004E,
	WM_INPUTLANGCHANGEREQUEST = 0x0050,
	WM_INPUTLANGCHANGE = 0x0051,
	WM_TCARD = 0x0052,
	WM_HELP = 0x0053,
	WM_USERCHANGED = 0x0054,
	WM_NOTIFYFORMAT = 0x0055,
	WM_CONTEXTMENU = 0x007B,
	WM_STYLECHANGING = 0x007C,
	WM_STYLECHANGED = 0x007D,
	WM_DISPLAYCHANGE = 0x007E,
	WM_GETICON = 0x007F,
	WM_SETICON = 0x0080,
	WM_NCCREATE = 0x0081,
	WM_NCDESTROY = 0x0082,
	WM_NCCALCSIZE = 0x0083,
	WM_NCHITTEST = 0x0084,
	WM_NCPAINT = 0x0085,
	WM_NCACTIVATE = 0x0086,
	WM_GETDLGCODE = 0x0087,
	WM_SYNCPAINT = 0x0088,


	WM_NCMOUSEMOVE = 0x00A0,
	WM_NCLBUTTONDOWN = 0x00A1,
	WM_NCLBUTTONUP = 0x00A2,
	WM_NCLBUTTONDBLCLK = 0x00A3,
	WM_NCRBUTTONDOWN = 0x00A4,
	WM_NCRBUTTONUP = 0x00A5,
	WM_NCRBUTTONDBLCLK = 0x00A6,
	WM_NCMBUTTONDOWN = 0x00A7,
	WM_NCMBUTTONUP = 0x00A8,
	WM_NCMBUTTONDBLCLK = 0x00A9,
	WM_NCXBUTTONDOWN = 0x00AB,
	WM_NCXBUTTONUP = 0x00AC,
	WM_NCXBUTTONDBLCLK = 0x00AD,

	WM_INPUT_DEVICE_CHANGE = 0x00FE,
	WM_INPUT = 0x00FF,

	WM_KEYFIRST = 0x0100,
	WM_KEYDOWN = 0x0100,
	WM_KEYUP = 0x0101,
	WM_CHAR = 0x0102,
	WM_DEADCHAR = 0x0103,
	WM_SYSKEYDOWN = 0x0104,
	WM_SYSKEYUP = 0x0105,
	WM_SYSCHAR = 0x0106,
	WM_SYSDEADCHAR = 0x0107,
	WM_UNICHAR = 0x0109,
	WM_KEYLAST = 0x0109,

	WM_IME_STARTCOMPOSITION = 0x010D,
	WM_IME_ENDCOMPOSITION = 0x010E,
	WM_IME_COMPOSITION = 0x010F,
	WM_IME_KEYLAST = 0x010F,

	WM_INITDIALOG = 0x0110,
	WM_COMMAND = 0x0111,
	WM_SYSCOMMAND = 0x0112,
	WM_TIMER = 0x0113,
	WM_HSCROLL = 0x0114,
	WM_VSCROLL = 0x0115,
	WM_INITMENU = 0x0116,
	WM_INITMENUPOPUP = 0x0117,
	WM_MENUSELECT = 0x011F,
	WM_MENUCHAR = 0x0120,
	WM_ENTERIDLE = 0x0121,
	WM_MENURBUTTONUP = 0x0122,
	WM_MENUDRAG = 0x0123,
	WM_MENUGETOBJECT = 0x0124,
	WM_UNINITMENUPOPUP = 0x0125,
	WM_MENUCOMMAND = 0x0126,

	WM_CHANGEUISTATE = 0x0127,
	WM_UPDATEUISTATE = 0x0128,
	WM_QUERYUISTATE = 0x0129,

	WM_CTLCOLORMSGBOX = 0x0132,
	WM_CTLCOLOREDIT = 0x0133,
	WM_CTLCOLORLISTBOX = 0x0134,
	WM_CTLCOLORBTN = 0x0135,
	WM_CTLCOLORDLG = 0x0136,
	WM_CTLCOLORSCROLLBAR = 0x0137,
	WM_CTLCOLORSTATIC = 0x0138,
	MN_GETHMENU = 0x01E1,

	WM_MOUSEFIRST = 0x0200,
	WM_MOUSEMOVE = 0x0200,
	WM_LBUTTONDOWN = 0x0201,
	WM_LBUTTONUP = 0x0202,
	WM_LBUTTONDBLCLK = 0x0203,
	WM_RBUTTONDOWN = 0x0204,
	WM_RBUTTONUP = 0x0205,
	WM_RBUTTONDBLCLK = 0x0206,
	WM_MBUTTONDOWN = 0x0207,
	WM_MBUTTONUP = 0x0208,
	WM_MBUTTONDBLCLK = 0x0209,
	WM_MOUSEWHEEL = 0x020A,
	WM_XBUTTONDOWN = 0x020B,
	WM_XBUTTONUP = 0x020C,
	WM_XBUTTONDBLCLK = 0x020D,
	WM_MOUSEHWHEEL = 0x020E,

	WM_PARENTNOTIFY = 0x0210,
	WM_ENTERMENULOOP = 0x0211,
	WM_EXITMENULOOP = 0x0212,

	WM_NEXTMENU = 0x0213,
	WM_SIZING = 0x0214,
	WM_CAPTURECHANGED = 0x0215,
	WM_MOVING = 0x0216,

	WM_POWERBROADCAST = 0x0218,

	WM_DEVICECHANGE = 0x0219,

	WM_MDICREATE = 0x0220,
	WM_MDIDESTROY = 0x0221,
	WM_MDIACTIVATE = 0x0222,
	WM_MDIRESTORE = 0x0223,
	WM_MDINEXT = 0x0224,
	WM_MDIMAXIMIZE = 0x0225,
	WM_MDITILE = 0x0226,
	WM_MDICASCADE = 0x0227,
	WM_MDIICONARRANGE = 0x0228,
	WM_MDIGETACTIVE = 0x0229,


	WM_MDISETMENU = 0x0230,
	WM_ENTERSIZEMOVE = 0x0231,
	WM_EXITSIZEMOVE = 0x0232,
	WM_DROPFILES = 0x0233,
	WM_MDIREFRESHMENU = 0x0234,

	WM_IME_SETCONTEXT = 0x0281,
	WM_IME_NOTIFY = 0x0282,
	WM_IME_CONTROL = 0x0283,
	WM_IME_COMPOSITIONFULL = 0x0284,
	WM_IME_SELECT = 0x0285,
	WM_IME_CHAR = 0x0286,
	WM_IME_REQUEST = 0x0288,
	WM_IME_KEYDOWN = 0x0290,
	WM_IME_KEYUP = 0x0291,

	WM_MOUSEHOVER = 0x02A1,
	WM_MOUSELEAVE = 0x02A3,
	WM_NCMOUSEHOVER = 0x02A0,
	WM_NCMOUSELEAVE = 0x02A2,

	WM_WTSSESSION_CHANGE = 0x02B1,

	WM_TABLET_FIRST = 0x02c0,
	WM_TABLET_LAST = 0x02df,

	WM_CUT = 0x0300,
	WM_COPY = 0x0301,
	WM_PASTE = 0x0302,
	WM_CLEAR = 0x0303,
	WM_UNDO = 0x0304,
	WM_RENDERFORMAT = 0x0305,
	WM_RENDERALLFORMATS = 0x0306,
	WM_DESTROYCLIPBOARD = 0x0307,
	WM_DRAWCLIPBOARD = 0x0308,
	WM_PAINTCLIPBOARD = 0x0309,
	WM_VSCROLLCLIPBOARD = 0x030A,
	WM_SIZECLIPBOARD = 0x030B,
	WM_ASKCBFORMATNAME = 0x030C,
	WM_CHANGECBCHAIN = 0x030D,
	WM_HSCROLLCLIPBOARD = 0x030E,
	WM_QUERYNEWPALETTE = 0x030F,
	WM_PALETTEISCHANGING = 0x0310,
	WM_PALETTECHANGED = 0x0311,
	WM_HOTKEY = 0x0312,

	WM_PRINT = 0x0317,
	WM_PRINTCLIENT = 0x0318,

	WM_APPCOMMAND = 0x0319,

	WM_THEMECHANGED = 0x031A,

	WM_CLIPBOARDUPDATE = 0x031D,

	WM_DWMCOMPOSITIONCHANGED = 0x031E,
	WM_DWMNCRENDERINGCHANGED = 0x031F,
	WM_DWMCOLORIZATIONCOLORCHANGED = 0x0320,
	WM_DWMWINDOWMAXIMIZEDCHANGE = 0x0321,

	WM_GETTITLEBARINFOEX = 0x033F,

	WM_HANDHELDFIRST = 0x0358,
	WM_HANDHELDLAST = 0x035F,

	WM_AFXFIRST = 0x0360,
	WM_AFXLAST = 0x037F,

	WM_PENWINFIRST = 0x0380,
	WM_PENWINLAST = 0x038F,

	WM_APP = 0x8000,

	WM_USER = 0x0400,

	WM_REFLECT = WM_USER + 0x1C00,
	EM_GETSEL = 0x00B0,
	EM_SETSEL = 0x00B1, --put the caret to the end of the edit window
	EM_REPLACESEL = 0x00C2 --append text at carret pos
)
mcWinMsg = MICRA_WINDOWS_MESSAGES()

denisT win32 assembly

Global mcWin32
Global mcWin32Assembly
fn CreateWin32Assembly forceRecompile:on = (
	if forceRecompile or not iskindof ::mcWin32Assembly dotnetobject or (::mcWin32Assembly.GetType()).name != "Assembly" do (
	
		source = "using System;
"
		source += "using System.Runtime.InteropServices;
"
		source += "using System.Text;
"
		source += "class Win32
"
		source += "{
"
		source += "		[DllImport(\"user32\", CharSet = CharSet.Auto, SetLastError = true)]
"
		source += "		public static extern Int32 SetFocus(Int32 hWnd);
"
		source += "		[DllImport(\"user32\", CharSet = CharSet.Auto, SetLastError = true)]
"
		source += "		internal static extern int GetWindowTextLength(Int32 hWnd);
"
		source += "		[DllImport(\"user32\", CharSet = CharSet.Auto, SetLastError = true)]
"
		source += "		internal static extern int GetWindowText(Int32 hWnd, [Out, MarshalAs(UnmanagedType.LPTStr)] StringBuilder lpString, int nMaxCount);
"
		source += "		public static string GetWindowText(Int32 hWnd)
"
		source += "		{
"
		source += "			int length = GetWindowTextLength(hWnd);
"
		source += "			StringBuilder sb = new StringBuilder(length + 1);
"
		source += "			GetWindowText(hWnd, sb, sb.Capacity);
"
		source += "			return sb.ToString();
"
		source += "		}
"
		source += "}
"
		csharpProvider = dotnetobject "Microsoft.CSharp.CSharpCodeProvider"
		compilerParams = dotnetobject "System.CodeDom.Compiler.CompilerParameters"

		compilerParams.ReferencedAssemblies.Add "System.dll"
		compilerParams.ReferencedAssemblies.Add "System.Drawing.dll"

		compilerParams.GenerateInMemory = true
		compilerResults = csharpProvider.CompileAssemblyFromSource compilerParams #(source)
		
		mcWin32Assembly = compilerResults.CompiledAssembly
		mcWin32Assembly.CreateInstance "Win32"
	)
)
mcWin32 = CreateWin32Assembly()

and main struct with some functions to comunicate with MSX_Scintilla

Global mcMSX
struct MICRA_MSX_EDITOR (
	
	msx_hwnd = (
		
		for c in (windows.getchildrenhwnd 0) where c[4] == "MXS_SciTEWindow" do exit with c[1]
	),
	tb_hwnd = (
		if msx_hwnd == undefined do return undefined
		for c in (windows.getchildrenhwnd msx_hwnd) where c[4] == "MXS_Scintilla" do exit with c[1]
	),
	fn close = (if msx_hwnd == undefined do retrun false; windows.sendmessage msx_hwnd mcWinMsg.WM_CLOSE 0 0), --OK
	fn copySel = (if tb_hwnd == undefined do retrun false; windows.sendmessage tb_hwnd mcWinMsg.WM_COPY 0 0), --OK
	fn paste = (if tb_hwnd == undefined do retrun false; windows.sendmessage tb_hwnd mcWinMsg.WM_PASTE 0 0), --OK
	fn clearAll = (if tb_hwnd == undefined do retrun false; windows.sendmessage tb_hwnd mcWinMsg.WM_CLEAR 0 0), --not works (works like backspace not clear all text)
	fn getSel = (if tb_hwnd == undefined do retrun false; windows.sendmessage tb_hwnd mcWinMsg.EM_GETSEL 0 0), --not works
	fn findStr str = ( --OK
		
		if tb_hwnd == undefined do retrun false
		local current_script_text = mcWin32.GetWindowText tb_hwnd
		local str_pos = findString current_script_text str
		if str_pos != undefined do (
			
			windows.sendmessage tb_hwnd mcWinMsg.EM_SETSEL (str_pos-1) (str_pos+str.count-1)
			mcWin32.SetFocus tb_hwnd
		)
		str_pos
	),
	fn insertAt offset_pos str = (  --need  fix
		
		if tb_hwnd == undefined do retrun false
		local marshal = dotnetclass "System.Runtime.InteropServices.Marshal"
		local ptr = marshal.StringToHGlobalUni str
		windows.sendmessage tb_hwnd mcWinMsg.EM_REPLACESEL offset_pos ptr 
		mcWin32.SetFocus tb_hwnd
	)
)
mcMSX = MICRA_MSX_EDITOR()
/*
mcMSX.close()
mcMSX.copySel()
mcMSX.paste()
mcMSX.clearAll() --not works (works like backspace not clear all text)
mcMSX.getSel() --return integer not String
insert_pos = mcMSX.findStr "MICRA_MSX_EDITOR"
mcMSX.insertAt  insert_pos "here you are :-)" --need  fix
*/

any good idea will be appreciated


#2

It seems you go on with you idea of dinamyc structs… nice! :slight_smile:
To find the end of the struct, the only way will be counting parenthesis (open - close). But you must be careful with parenthesis that may be inside quotes or double quotes. Regex should do the trick.


#3

Hi aaandreas,
dynamic structures must wait for better perspective :smiley:
to find last brace from structure is not easy as you say.
Regex will sure make good work… but I’m not good in it
maybe another scintilla commands ?
|IDM_MATCHBRACE|Match Brace|
|IDM_SELECTTOBRACE|Select to Brace|


#4

This one will insert “fn abc a b = a * b” right before the struct end.
btw You can comment whole struct to see how SCI_BRACEMATCH fails

SCI_BRACEMATCH = 2353
struct test
( /* <--  opening_parenthesis_offset */
	a = 0,
	b = "())",
	fn abc = 111,
		
	on create do ()

)

mxse_hwnd = (dotNetClass "Autodesk.Max.GlobalInterface").Instance.TheMxsEditorInterface.EditorGetEditHWND 
opening_parenthesis_offset = 36
match = windows.sendMessage mxse_hwnd SCI_BRACEMATCH opening_parenthesis_offset 0


fn InsertInMXSE offset str = 
(
	local marshal = dotnetclass "System.Runtime.InteropServices.Marshal"
	local ptr = marshal.StringToHGlobalUni str
	local mxse_hwnd = (dotNetClass "Autodesk.Max.GlobalInterface").Instance.TheMxsEditorInterface.EditorGetEditHWND
	
	local EM_REPLACESEL = 0x00C2	
	local SCI_GETCURRENTPOS = 2008
	local SCI_GOTOPOS = 2025
	local EM_SETSEL = 0x00B1	
	
	local prev_offset = windows.sendmessage mxse_hwnd SCI_GETCURRENTPOS 0 0
	
	windows.sendMessage mxse_hwnd SCI_GOTOPOS offset 0

	windows.sendMessage mxse_hwnd EM_SETSEL offset offset
	windows.sendmessage mxse_hwnd EM_REPLACESEL offset ptr
	windows.sendMessage mxse_hwnd EM_SETSEL offset offset
	
	if prev_offset > (offset + str.count) then
	(
		windows.sendMessage mxse_hwnd SCI_GOTOPOS (prev_offset + str.count) 0
	)
	else
	(
		windows.sendMessage mxse_hwnd SCI_GOTOPOS prev_offset 0
	)
	

)



function_to_insert = "fn abc a b = a * b"


if match != -1 do
(
	codeblock = "\t,\r\n\t" + function_to_insert + "\r\n"
	InsertInMXSE (match-1) codeblock
)

#5

Did you have a look at my MXSEditor Plugin which exposes editor stuff to maxscript ?
It allows to call most of the scintilla based commands via a simple function publishing interface
Problem is that the scintilla component used in Max is pretty old and obsolete and lacks many of the newer features existing nowadays

here’s some more detailed documentation
http://www.frogsinspace.at/?p=2918

UPDATE:
Ahh - i found you already commented on my wordpress post already …
http://www.frogsinspace.at/?p=3232


#6

I would be glad if someone could show how to highlight only the matching words.



fn GetWindowText hwnd =
(
	local marshal = dotnetclass "System.Runtime.InteropServices.Marshal"
	local str = ""
	try (
		
		local len = windows.sendmessage hwnd 0xE 0 0
		local lParam = marshal.AllocHGlobal (marshal.SystemDefaultCharSize*(len+1))
		windows.sendmessage hwnd 0xD (len+1) lParam 
			
		ptr = dotnetobject "System.IntPtr" lParam
		str = marshal.PtrToStringAuto ptr
		marshal.FreeHGlobal ptr
		
	) catch ()
	str
)

fn ClearMXSEHighlights =
(	
-- 	local SCI_MARKERDELETEALL = 2045
	windows.sendMessage (dotNetClass "Autodesk.Max.GlobalInterface").Instance.TheMxsEditorInterface.EditorGetEditHWND 2045 -1 -1
)

fn HighlightLines word matchcase:false keep:false =
(
	if not matchcase do word = toLower word
		
	local mxse_hwnd = (dotNetClass "Autodesk.Max.GlobalInterface").Instance.TheMxsEditorInterface.EditorGetEditHWND
	local src = getWindowText mxse_hwnd
	local doc = (if matchcase then src else toLower src) as StringStream
	local offsets = #()

	while (skipToString doc word) != undefined do
	(
		append offsets (filePos doc)
	)
	
	free doc
	
	if keep == false do
	(
		local SCI_MARKERDELETEALL = 2045
		windows.sendMessage mxse_hwnd SCI_MARKERDELETEALL -1 -1
	)
	
	if offsets.count > 0 do
	(
		local SCI_LINEFROMPOSITION = 2166		
		local SCI_MARKERADDSET = 2466
		
		
		for offset in offsets do
		(
			local line_index = windows.sendMessage mxse_hwnd SCI_LINEFROMPOSITION offset 0
			
			windows.sendMessage mxse_hwnd SCI_MARKERADDSET line_index 2
		)	
	)
	
	offsets
)

-- ClearMXSEHighlights()
HighlightLines "sendM"

#7

Hi Serejah,
very nice way to pick msxe_hwnd , how did you find it :grinning:
After comment whole structure brace match fail as you say ,
Maybe will help other solution. Not to professional, but should be work :wink:
Add one line to end of each structure. After use find function to get exact position, like…

struct test
(
	a = 0,
	b = "())",
	fn abc = 111,
		
	on create do ()
	/*<struct test ends here. Insert you code under this marker>*/
)

mcMSX.findStr “struct test end”

I’m glad for you script Serejah, it is nice to see how can achieve same thinks with different ways


#8

Another nice piece of code Serejah. Also good idea to mark each line with marker :grinning:
Do you think will be posible to get result in MXS like this ?


#9

I tried but without any luck. My editor looks like this after code execution


#10

Use SDK reference or c++ sources to look for that type of things


#11

this one looks nice too :slight_smile:
Many thanks Serejah, you helped me a lot :+1::smiley:


#12

Finlay this part of code is finished :slight_smile:
Is useful during develop tools which is in different structures
here is one example>

part of code here>

	fn replaceText offset_pos str = (
	
		local ptr = marshal.StringToHGlobalUni str
		windows.sendmessage mxse_hwnd mcWinMsg.EM_REPLACESEL offset_pos ptr 
	),
	fn selectText offset str_len = (

		windows.sendmessage mxse_hwnd mcWinMsg.EM_SETSEL (offset-1) (offset+str_len-1)
	),
	fn moveCarretTo offset = (
	
		windows.sendMessage mxse_hwnd mcWinMsg.SCI_GOTOPOS offset 0
	),
	fn findText str = ( --OK
		
		local current_script_text = mcWin32.GetWindowText mxse_hwnd
	        findString current_script_text str
	),
	fn insertFunctionAtStructureEnd fn_str = (
	
		focus()
		fn_str += "\n\t" + struct_end_marker
		format "mcMsx > insertFunction >\n%\n" fn_str
		local end_pos = findText struct_end_marker
		if end_pos == undefined do return false
		format "mcMsx > insertFunction > end_pos:%\n" end_pos
		moveCarretTo (end_pos-1)
		selectText end_pos struct_end_marker.count
		replaceText end_pos fn_str
		focus()
	)

call >

local success = mcMsx.editStrucrure struct_name --edit structure file (in Maxscript Editor)
						if not success do return false
						--define new function as string
						local new_fn = "fn " + fn_name
						if fn_params != "" do new_fn += " " + fn_params
						new_fn += " = (\n\t\t\n\t\tInsert Code Here...\n\t)"
						--append function to current file (in Maxscript Editor)
						mcMsx.insertFunctionAtStructureEnd new_fn 

cheers :wink:


#13

Is it possible all folds to be collapsed separately per fold?
What I mean - int he Maxscript Editor you can click anywhere in the code and then using View-Toggle current fold to collapse/expand the brackets.
There is View-Toggle all folds but its just collapse/expand the first and the last bracked(whole code).


#14

this one will fold only the folds of certain level


(

	fn mxsEditorHWND asdotnet:false = (

		for c in (windows.getchildrenhwnd 0) where c[4] == "MXS_SciTEWindow" do for t in (windows.getchildrenhwnd c[1]) where t[4] == "MXS_Scintilla" do (
		
			if asdotnet then return dotNetObject "system.intptr" t[1] else return t[1]
		
		)
		
	)
	
	hwnd = mxsEditorHWND()
	
	SCI_GETFOLDLEVEL = 2223
	SCI_GETLINECOUNT = 2154
	SCI_TOGGLEFOLD = 2231
	SCI_GETLINEVISIBLE = 2228
	
	for i=0 to (windows.sendMessage hwnd SCI_GETLINECOUNT 0 0) - 1 do
	(
		linefoldlevel = (bit.shift (windows.sendMessage hwnd SCI_GETFOLDLEVEL i 0) -16) - 1024
		foldisexpanded = 1 == windows.sendMessage hwnd SCI_GETLINEVISIBLE i 0
		format "line#% - expaned:%  foldlevel:%\n" (1+i) foldisexpanded linefoldlevel 
		
		if linefoldlevel == 2 and foldisexpanded do windows.sendMessage hwnd SCI_TOGGLEFOLD i 0
		
	)

)

scite_commands.txt (19.2 KB)


#15

Thank you. It works as expected. I have changed the linefoldlevel == 2 to linefoldlevel == 3 to fit my needs.
For folding on deeper level this have to be used, or there are more elegnat solution?

for i=0 to (windows.sendMessage hwnd SCI_GETLINECOUNT 0 0) - 1 do
	(
		linefoldlevel = (bit.shift (windows.sendMessage hwnd SCI_GETFOLDLEVEL i 0) -16) - 1024
		foldisexpanded = 1 == windows.sendMessage hwnd SCI_GETLINEVISIBLE i 0
		format "line#% - expaned:%  foldlevel:%\n" (1+i) foldisexpanded linefoldlevel 
		
		if linefoldlevel == 4 and foldisexpanded do windows.sendMessage hwnd SCI_TOGGLEFOLD i 0
		
	)

for i=0 to (windows.sendMessage hwnd SCI_GETLINECOUNT 0 0) - 1 do
	(
		linefoldlevel = (bit.shift (windows.sendMessage hwnd SCI_GETFOLDLEVEL i 0) -16) - 1024
		foldisexpanded = 1 == windows.sendMessage hwnd SCI_GETLINEVISIBLE i 0
		format "line#% - expaned:%  foldlevel:%\n" (1+i) foldisexpanded linefoldlevel 
		
		if linefoldlevel == 3 and foldisexpanded do windows.sendMessage hwnd SCI_TOGGLEFOLD i 0
		
	)

Any chance this to be used with # User defined key commands inside MaxScript editor like: # Ctrl+Shift+V|IDM_PASTEANDDOWN|\?


#16

I wouldn’t call it elegant :slight_smile:
First we collect all folds data and then sort them by depth and finally toggle


(

	fn mxsEditorHWND asdotnet:false =
	(
		for c in (windows.getchildrenhwnd 0) where c[4] == "MXS_SciTEWindow" do for t in (windows.getchildrenhwnd c[1]) where t[4] == "MXS_Scintilla" do
		(		
			if asdotnet then return dotNetObject "system.intptr" t[1] else return t[1]		
		)
		
	)
	
	global hwnd = mxsEditorHWND()
		
	SCI_GETFOLDLEVEL = 2223
	SCI_GETLINECOUNT = 2154
	SCI_TOGGLEFOLD  = 2231
	SCI_GETLINEVISIBLE = 2228
	SCI_GETLASTCHILD = 2224
	
	
	folds = #()
	
	for i=0 to (windows.sendMessage hwnd SCI_GETLINECOUNT 0 0) - 1 do
	(
		linefoldlevel  = (bit.shift (windows.sendMessage hwnd SCI_GETFOLDLEVEL i 0) -16) - 1024
		foldisexpanded = 1 == windows.sendMessage hwnd SCI_GETLINEVISIBLE i 0
		foldendline    = windows.sendMessage hwnd SCI_GETLASTCHILD i -1
		format "line#% - expaned:%  foldlevel:% foldend:%\n" (1+i) foldisexpanded linefoldlevel foldendline
		
		if linefoldlevel >= 2 and foldisexpanded do 
		(

-- 			windows.sendMessage hwnd SCI_TOGGLEFOLD i 0
			
			(
				(
					
					(
						
						
					)
					
				)
			)
			
			append folds #( i, foldendline, linefoldlevel ) -- fold start line, fold last line, fold level
			
		)
		
	)
	
	fn sortByFoldDepth a b = if a[3] > b[3] then -1 else if a[3] < b[3] then 1 else 0

	qsort folds sortByFoldDepth

	folded = #{}
	for f in folds where not (folded[f[1]] and folded[f[2]]) and f[1] != f[2] do 
	(
		windows.sendMessage hwnd SCI_TOGGLEFOLD f[1] 0
		
		folded[f[1]] = true
		folded[f[2]] = true
	)

)


In short, there’s no easy way.

You can try utilize http://www.scriptspot.com/3ds-max/plugins/mxspycom
Or if you prefer mxs way of doing it (but it tends to break after a while)


#17

Thank you very much.
I will stay with default hotkey that I alrady have assigned.


#18

executeMXS

BS9CyKiN9g

unfortunately it always prompts and shows output pane when script isn’t saved … don’t know if it possible to do something about it
hope somebody find useful :wink: