An Edit Object manages edit transactions being performed. Every change to a file gets placed in an edit transaction group. That transaction group can then be unwound during the undo process or spooled back for redo. Edit transactions are placed in a temporary file in the user’s data area, allowing GoFiler to recover changes made to text files made after a save but before the file is closed. Edit transactions range from moving the caret to deleting a character to changing font attributes in HTML.
For all text windows, positions in an Edit Object are referenced in terms of x and y, with x being the column and y being the line. Edit Objects also keep track of caret and selection data. All of these can be accessed and changed by Legato.
This post is meant to be a broad overview of the functions we can use to interact with Edit Objects. Therefore, today’s script is more of a test script than anything else. The values that will be returned are not guaranteed if you are just going to copy and paste the script, as many of the values depend of the current state of the system. I’ll give a brief overview of each function I use and explain the features of each.
int cursor[];
int caretx;
int carety;
int changeCount;
int totalChangeCount;
int elapsedTime;
string objectFilename;
dword objectFileType;
string objectName;
dword objectType;
int selectCount;
int startSelectX;
int startSelectY;
int endSelectX;
int endSelectY;
int selectMode;
int selectClue;
handle view;
handle log;
log = LogCreate ("Edit Object Properties",
"Edit Object Properties");
view = GetEditObject (-1);
cursor = GetCursorPosition ();
caretx = GetCaretXPosition (view);
carety = GetCaretYPosition (view);
changeCount = GetEditObjectChangeCount (view);
totalChangeCount = GetEditObjectChangeCount (view, TRUE);
elapsedTime = GetEditObjectElapsedTime (view);
objectFilename = GetEditObjectFilename (view);
objectFileType = GetEditObjectFileType (view);
objectName = GetEditObjectName (view);
objectType = GetEditObjectType (view);
selectCount = GetSelectCount (view);
selectMode = GetSelectMode (view);
selectClue = GetSelectClue (view);
if (selectMode > 0) {
startSelectX = GetSelectStartXPosition (view);
startSelectY = GetSelectStartYPosition (view);
endSelectX = GetSelectEndXPosition (view);
endSelectY = GetSelectEndYPosition (view);
}
AddMessage(log, "GetCursorPosition:");
AddMessage(log, "X: %s", cursor["x"]);
AddMessage(log, "Y: %s", cursor["y"]);
AddMessage(log, "GetCaretXPosition: %s", caretx);
AddMessage(log, "GetCaretYPosition: %s", carety);
AddMessage(log, "GetEditObjectChangeCount: %s", changeCount);
AddMessage(log, "GetEditObjectChangeCount (total): %s", totalChangeCount);
AddMessage(log, "GetEditObjectElapsedTime: %s", elapsedTime);
AddMessage(log, "GetEditObjectFilename: %s", objectFilename);
AddMessage(log, "GetEditObjectFileType: 0x%08x", objectFileType);
AddMessage(log, "GetEditObjectName: %s", objectName);
AddMessage(log, "GetEditObjectType: 0x%08x", objectType);
AddMessage(log, "GetSelectCount: %s", selectCount);
AddMessage(log, "GetSelectMode: %s", selectMode);
AddMessage(log, "GetSelectClue: %s", selectClue);
if (selectMode > 0) {
AddMessage(log, "GetSelectStartXPosition: %s", startSelectX);
AddMessage(log, "GetSelectStartYPosition: %s", startSelectY);
AddMessage(log, "GetSelectEndXPosition: %s", endSelectX);
AddMessage(log, "GetSelectEndYPosition: %s", endSelectY);
}
LogDisplay(log);
The first thing I do is create the variables I need. I’ve named them all to match exactly what their data should be in order to be as readable as possible. I then create a log in which I can place all of the final data. Next I run all of the different functions I want to show . Finally I add all of the results to the log file and show the log before ending the file.
My script as defined above ends up returning something similar to this (remember: the values are dictated by the contents of the edit window):
GetCursorPosition:
X: 2322
Y: 572
GetCaretXPosition: 34
GetCaretYPosition: 30
GetEditObjectChangeCount: 0
GetEditObjectChangeCount (total): 255
GetEditObjectElapsedTime: 242176
GetEditObjectFilename: D:\Working\Edit Object Properties.ls
GetEditObjectFileType: 0x00006810
GetEditObjectName: Edit Object Properties.ls
GetEditObjectType: 0x28201090
GetSelectCount: 1
GetSelectMode: 1
GetSelectClue: 0
GetSelectStartXPosition: 0
GetSelectStartYPosition: 0
GetSelectEndXPosition: 20
GetSelectEndYPosition: 60
Let’s look at the functions I’ve used to create this output:
GetEditObject: The GetEditObject function returns the handle of an open edit object. You can pass it either a handle for a view that you’ve gotten previously, an int that is the index of the window you want in the edit manager window index, or a string that is the name of the window that you want. In this case, I wanted the edit object of the active window, so I used a shortcut and passed the function -1 to specify the current active window.
GetCursorPosition: This GetCursorPosition function returns an array with two key values: x and y. These values are the x and y values of the position of the mouse cursor in pixels. If you’ve never dealt with screen positions before, here’s a quick overview. The x value goes from 0 at the leftmost point of your main monitor with positive being to the right and negative to the left. This means that if you have multiple monitors the value can go more positive than your monitor width or go negative. The y value goes from the top of the main monitor with positive being down and negative being up.
GetCaretXPosition, GetCaretYPosition: Each of these functions return an int with the current line and column position of the caret, with x being rows and y being columns.
GetEditObjectChangeCount: The GetEditObjectChangeCount function returns an int with the number of changes since the last save. If you pass TRUE as the optional second parameter, it will instead return the number of changes since you opened the file.
GetEditObjectElapsedTime: The GetEditObjectElaspedTime function returns an int with the number of seconds since the edit window was opened.
GetEditObjectFilename: The GetEditObjectFilename function returns a string with the full path of the script being run. It will be blank if the current object is not saved.
GetEditObjectName: The GetEditObjectName function returns the name of the associated window. This is normally the filename, but if the file is not saved it may be either blank or be “Untitled”.
GetEditObjectFileType, GetEditObjectType: These functions return information about the file and the view in a dword format. You can then do bitwise operations to find if certain flags are set. See the Legato SDK for more detailed information on what is contained in these flags.
GetSelectCount: The GetSelectCount function returns a int with how many objects are selected. For text, the number will be one or zero, but for views that have boxes, such as XBRL View or Data View, a larger number may be returned.
GetSelectMode: The GetSelectMode function returns an int with the current selection mode. This number will be between zero and four, with each integer signifying a different mode. In my example, I check to see if there is anything selected before running any more functions. I do this by checking to see if the GetSelectMode function returns a value greater than zero, as zero means there is just a cursor, nothing selected.
GetSelectClue: The GetSelectClue function returns an int that corresponds with what HTML item is selected. There is a table in the Legato help manual that will help determine what each value means.
GetSelectStartXPosition, GetSelectStartYPosition, GetSelectEndXPosition, GetSelectEndYPosition: These functions will return the start and the end positions of a selection as an int. This is similar to getting the caret position. If you do not have a selection, the function will return a -1 as a failure value. You may want to check yourself to see if there’s a selection before running these functions as that will allow you to preempt failures before running multiple functions.
Finally there are some functions pertaining to moving the caret:
SetCaretPosition: The SetCaretPosition function will move the caret to the specified location. If the caret cannot be placed in that location, it will be placed in the nearest valid alternative.
SetSelectArea: The SetSelectArea function will either set the select area to the values specified in the optional start and end variables, or if those optional parameters are omitted the edit object will clear the current selection.
SetSelectClue, SetSelectMode: These functions will allow you to update the values that GoFiler automatically decides when a selection is changed. Be careful when doing this as changing these values changes what functions are available to use. Keep in mind, however, that just because you can use a function does not mean the function will work as expected. If you change the select mode to table selection and you only have text selected, table functions may be available but they will likely return errors or internal errors.
If you want to modify or act based off what a user can see, an Edit Object is a powerful tool that makes your responses to edit changes simple. These objects are fairly easy to use but give you a large number of options to get exactly the information you need.
Joshua Kwiatkowski is a developer at Novaworks, primarily working on Novaworks’ cloud-based solution, GoFiler Online. He is a graduate of the Rochester Institute of Technology with a Bachelor of Science degree in Game Design and Development. He has been with the company since 2013. |
Additional Resources
Novaworks’ Legato Resources
Legato Script Developers LinkedIn Group
Primer: An Introduction to Legato