Last year, I wrote a series of blog posts on a Page Break Manager tool for GoFiler. It allowed users to save page breaks into a style template, rename them, and delete them. One feature was conspicuously absent though, the ability to edit a page break. Well, it seems like now would be a good time to rectify that mistake! This blog post is going to go over how to add the edit function to this script. It’s also a really good example of code should be written in a fairly modular fashion, because it makes it a lot easier to come back in and edit things later. I wrote this seven months ago, I don’t really remember how a lot of the functions work exactly. Things like reading the file into a data table, or saving the file back out, are somewhat complicated, and while I’m sure I could figure out how it’s working, there’s really no need to, since those are self-contained functions within the script. I don’t need to know how they work really, as long as they do what they’re supposed to do I can simply re-use them in this new function without a problem.
Friday, April 19. 2019
LDC #132: Adding Edit Functionality to the Page Break Manager
First, before any code is written, I need to decide how editing is going to work. I think the best way to handle this would be for a user to click on the page break they want to edit, click the “Edit” button, and then have the dialog close, and have GoFiler open the page break in a new page view edit window, so the user can change things. Then when they’re done, the user should just be able to click save, and have the page break save to the template file like it should. Sounds easy, but it will actually require some interesting uses of hooked functions, session variables, and a couple of new functions for our file.
New functions that are added to our script to handle this include:
int cancel_edit_break(); /* cancel editing a page break */ int edit(int selected_id); /* edit the page break */ string edgarize_filename(string filename, string ext); /* edgarizes a filename, making it compliant */ int save_edit(int f_id, string mode); /* saves edits to a break */ int validate_file(handle window); /* validate that the file has a valid pagebreak */ /* */
The function cancel_edit_break is going to be called when the user tries to edit a page break while another one is currently being edited. This script is only going to allow one page break to be edited at a time, so if a user tries to edit a second one, this function gets called to clean up the previous page break edit window. The edit function is going to be the main function here, it will kick off the whole editing process. We’re also going to need to hook a function to the “save” button in GoFiler and to validate that our page break is valid, so save_edit and validate_file will handle that. Lastly, edgarize_filename is a utility function I added in to take the name of a page break, and make it a much simpler name so we can use it as a filename. We could name our temporary edit file anything, but I used this function in a previous script, so it was really easy to copy/paste it into here for this to make a nicer looking name for our temporary file.
First, let’s look at some edits we need to make on existing functions to hook in our new functionality, before we talk about those new functions. The functions run_modify and run_save are both going to need this code added in, right after the check to ensure we’re running in preprocess mode.
if(GetSessionString(EDITING_PB_SV)=="true"){ /* if we are already editing a break */ rc = cancel_edit_break(); /* run the cancel edit break function */ } /* */ if(rc == ERROR_EXIT){ /* if the return is an error */ return rc; /* return the error code */ } /* */
A very simple snippet of code, all this is going to do is check our session variable EDITING_PB_SV. If it’s true, we enter the cancel_edit_break function, to ask the user if they want to cancel the page break edit that is currently in process. If that function returns an error, we return the error, otherwise we can continue onward with the way those functions normally work, and nothing else about them needs to be changed for our purposes here.
The modify_action function is also going to need to be edited. At the top of it, there is a large if statement that only allows our action handler to continue if we’re dealing with an expected action and control combination. We need to add our TEMPLATE_EDIT button to that if statement so our function will actually work. We also need to change the behavior of the double-click action to set the c_id variable to TEMPLATE_EDIT instead of TEMPLATE_RENAME, because the double-click action will now enter the edit instead of entering the rename. Finally, we need to add an if statement to catch the edit action, and to actually call our edit function. The new function is shown below, with new code sections marked in bold.
/****************************************/ void modify_action(int c_id, int action){ /* action on the modify dialog */ /****************************************/ string temp[]; /* temp array for data storage */ string selected_nm; /* selected name */ string selected_fn; /* selected full name */ int dir; /* direction we're moving the selection */ int size; /* size of page break table */ int ix; /* loop counter */ int selected; /* selected index value */ string data[][]; /* content of the dialog's list */ int rc; /* result code */ /* */ if( (c_id == ADJ_UP && action == BN_CLICKED) /* if up is pressed */ || (c_id == ADJ_DOWN && action == BN_CLICKED) /* if down is pressed */ || (c_id == TEMPLATE_RENAME && action == BN_CLICKED) /* if rename is pressed */ || (c_id == TEMPLATE_DELETE && action == BN_CLICKED) /* if delete is pressed */ || (c_id == TEMPLATE_LIST && action == DCN_DOUBLE_CLICK || /* if template list is double clicked */ action == DCN_SELECT_CHANGE) /* or the selection changes */ || (c_id == TEMPLATE_EDIT && action == BN_CLICKED)){ /* if edit is clicked */ old_selected = selected; /* set the last item selected */ selected = DataControlGetRowSelection(TEMPLATE_LIST); /* get the selected item from the list */ if (selected <0){ /* if we have no selection */ return; /* nothing to do */ } /* */ data = DataControlGetTable(TEMPLATE_LIST); /* get the data from the list */ toggle_buttons(selected,ArrayGetAxisDepth(data)); /* toggle buttons off and on */ if (c_id == TEMPLATE_LIST && action == DCN_DOUBLE_CLICK){ /* if user double clicked a list item */ c_id = TEMPLATE_EDIT; /* do same thing as if user did rename */ } /* */ selected_nm = TrimPadding(data[selected][0]); /* get the name of the selected row */ selected_fn = FormatString(P_TEMPLATE,selected_nm); /* get full name of renaming template */ selected_id = -1; /* init renaming ID to -1 */ size = ArrayGetAxisDepth(page_breaks); /* get size of page break table */ for(ix=0;ix<size;ix++){ /* for each row in table */ if (selected_fn == TrimPadding(page_breaks[ix][0])){ /* if name matches the row in the db */ selected_id = ix; /* store ID for later */ break; /* break loop */ } /* */ } /* */ if (c_id == ADJ_UP || c_id == ADJ_DOWN){ /* if adjusting the list order */ modified = true; /* flag file as modified */ if (c_id == ADJ_UP){ /* if up button pressed */ dir = -1; /* set direction to move up in list */ } /* */ if (c_id == ADJ_DOWN){ /* if down button pressed */ dir = 1; /* set direction to move down in list */ } /* */ DataControlSwapRows(TEMPLATE_LIST,selected,selected+dir); /* swap row up in list */ DataControlSetRowSelection(TEMPLATE_LIST,selected+dir); /* set the selection */ selected = selected+dir; /* change selection variable */ temp = page_breaks[selected_id]; /* store selection */ page_breaks[selected_id] = page_breaks[selected_id+dir]; /* swap rows */ page_breaks[selected_id+dir] = temp; /* swap rows */ toggle_buttons(selected,ArrayGetAxisDepth(data)); /* toggle buttons off and on */ } /* */ if (c_id == TEMPLATE_RENAME){ /* if rename was pressed */ rc = rename(selected_nm); /* run the rename function */ if (IsError(rc)==false){ /* if rename didn't return an error */ modify_load(); /* reload the list */ } /* */ return; /* return */ } /* */ if (c_id == TEMPLATE_EDIT){ /* if editing a template */ rc = edit(selected_id); /* enter the edit function */ return; /* */ } /* */ if (c_id == TEMPLATE_DELETE){ /* if delete was pressed */ rc = delete(selected_nm); /* run the delete function */ if (IsError(rc)==false){ /* if delete didn't return an error */ DataControlSetRowSelection(TEMPLATE_LIST,-1); /* reset selection */ selected = -1; /* reset selected variable */ modify_load(); /* reload the list */ } /* */ return; /* return */ } /* */ } /* */ /* */ } /* ` */
The last change we actually have to make is to add the edit button to our dialog control. I’m not going to cover how to do that here, but take a look at the dialog in the completed script to see what that change looks like. You can use a dialog editor to make this change, or you can just edit it manually, whichever is easier. Now that our changes are out of the way, lets get into the new functions. First up, we have the edit function, printed below.
/****************************************/ int edit(int selected_id){ /* edit the selected page break */ /****************************************/ int rc; /* return code */ string fn; /* script file name */ string tempfile; /* temp file name */ string temppath; /* path to temp folder */ string filename; /* temp file name */ handle edit_obj; /* handle to edit object */ /* */ filename = page_breaks[selected_id][0]; /* set filename */ filename = ReplaceInString(filename,"<P STYLE=\"margin: 0\">{",""); /* replace the open P tag */ filename = ReplaceInString(filename,"}</P>\r\n",""); /* replace the close P tag */ filename = edgarize_filename(filename,"htm"); /* make filename edgar compliant */ temppath = GetTempFileFolder(); /* get the temp folder path */ tempfile = AddPaths(temppath,filename); /* set new filename */ SetSessionValue(EDITING_PB_SV,"true"); /* set session variable for editing */ SetSessionValue(EDITING_PB_SV_NAME,tempfile); /* set filename we're editing */ SetSessionValue(EDITING_PB_SV_ID, selected_id); /* */
This function begins by grabbing the name of the page break out of the page_breaks table, removing the <P> tags that wrap around it, using the edgarize_filename function to make sure it’s an actual valid file name, and then appending it to the end of the temporary files path so we have a valid path to a valid named file. Then we can go ahead and set the session variables we’re going to need to reference later, saving the name and ID of our template as well as setting the edit status to true.
rc = StringToFile(page_breaks[selected_id][1], tempfile); /* write out temp file */ if(IsError(rc)){ /* if we cannot write out the file */ MessageBox('x',"Cannot edit the page break template selected."); /* display error */ return ERROR_EXIT; /* return */ } /* */ RunMenuFunction("FILE_OPEN", "Filename:"+tempfile); /* open a new page view */ fn = GetScriptFilename(); /* get the filename of the script */ rc = MenuSetHook("FILE_SAVE", fn, "save_edit"); /* set the hook on the save function */ if(IsError(rc)){ /* if we cannot hook save */ MessageBox('x',"Unable to hook to save function, error %0x",rc); /* display error code */ } /* */ DialogPostOK(); /* close the dialog */ return ERROR_NONE; /* return without error */ } /* */
Now that we’ve got a valid file name, we can use StringToFile to dump the contents of the page break we’re editing into our temporary file, and check to make sure that was successful. If so, we can open the file so the user can edit it in the page view. Then we need to get the name of our script file, and hook the save_edit function to the “Save” menu button, so when the user finishes editing the document and presses save, it correctly saves it back into our template file. If the hook was successfully added, we can then post OK to our dialog with DialogPostOK to close it, and then return.
When the user actually presses the save button now, the save_edit function will fire, and it will handle saving our page break for us.
/****************************************/ int save_edit(int f_id, string mode){ /* save any edits made to page break */ /****************************************/ int rc; /* return code */ string id_s; /* string value of ID for table row */ long id; /* ID of the table row editing */ handle window; /* the currently active window */ string template_file; /* template file path */ string pb_fname; /* currently editing pb filename */ string window_fn; /* active edit window filename */ string contents; /* contents of the page break */ /* */ window = GetActiveEditWindow(); /* get the active edit window */ window_fn = GetEditWindowFilename(window); /* get the active window filename */ pb_fname = GetSessionString(EDITING_PB_SV_NAME); /* get the name of the page break */ id_s = GetSessionString(EDITING_PB_SV_ID); /* get ID of page break */ id = TextToInteger(id_s); /* get integer value of ID */ if(window_fn == pb_fname){ /* if this is the current pb file */ if(mode!="postprocess"){ /* only run in postprocess */ return validate_file(window); /* validate the file */ } /* */
The save_edit function begins by grabbing the active edit window, then getting the filename of that window. We also need to get the session variable EDITING_PB_SV_NAME with GetSessionString, as well as EDITING_PB_SV_ID, the ID of the page break we’re editing. Once we have those, we can check to see if the name of the window is the same as the name of the page break we’re supposed to be editing. If not, we don’t need to do anything here, the script can just exit, because the user must have started editing the page break then either closed it or went onto a different file to edit it. If it is the page break though, we can check to see if we’re running in a mode other than postprocess (like preprocess). If so, we need to return the value of the validate_file function. This is done so we don’t trigger a save operation on a page break template that doesn’t meet our format, which is supposed to be a single table.
MenuDeleteHook("FILE_SAVE"); /* delete the hooked function */ RunMenuFunction("FILE_CLOSE", "ForceClose:true;"); /* close the open file */ contents = FileToString(pb_fname); /* get contents of page break */ template_file = GetApplicationDataFolder(); /* Get the appdata directory */ template_file = AddPaths(template_file,"Templates"); /* build path to templates folder */ template_file = AddPaths(template_file,TEMPLATE_FILENAME); /* set path to template file */ rc = read_page_breaks(template_file); /* read the page break template */ page_breaks[id][1] = contents; /* set contents of file into table */ if (rc!=ERROR_NONE){ /* if we have an error */ SetLastError(rc); /* set the last error message */ return ERROR_EXIT; /* return error */ } /* */ modified = true; /* save that the file has been modified */ modify_ok(); /* run the modify OK function to save */ } /* */ return ERROR_NONE; /* return without error */ } /* */
Now that we’ve validated that we have a page break we want to save, we need to first unhook the FILE_SAVE function, since we won’t need to trigger it again. It’s important we unhook it at this point, otherwise it would continue to run every time a user presses the “Save” button, and we really don’t need it to do that after it’s finished its function. We can then close our file since the default “save” function should have already saved it, read the contents of the file to memory with StringToFile, and then call the read_page_breaks function to populate the page_breaks data array. Then we can modify that data array with our file contents, set modified to true, and call our modified_ok function. It was designed to be called after a user finished modifying the table with renames or reorder operations, but all it really does is write the data array back out to our template file, so it will work fine here too. Next, we can take a look at how the validation function works.
/****************************************/ int validate_file(handle window){ /* validate file */ /****************************************/ string next; /* next element */ string tbody; /* body of the table */ string element; /* element token */ handle sgml; /* sgml parser handle */ /* */ sgml = SGMLCreate(window); /* get handle to SGML parser */ next = SGMLNextElement(sgml); /* get first SGML element */ element = SGMLGetElementString(sgml); /* get element type */ if(element == "TABLE"){ /* if it's a table */ tbody = SGMLFindClosingElement(sgml); /* get closing element */ element = SGMLNextElement(sgml); /* get next element */ if(element == ""){ /* if the element is blank */ return ERROR_NONE; /* return no error */ } /* */ else{ /* if there is more after the table */ MessageBox('x',PAGE_BREAK_INVALID_MSG); /* display error */ return ERROR_EXIT; /* return error */ } /* */ } /* */ else{ /* if it's not a table tag */ MessageBox('x',PAGE_BREAK_INVALID_MSG); /* display error */ return ERROR_EXIT; /* return error */ } /* */ return ERROR_NONE; /* return no error by default */ } /* */
This function is actually quite simple. To test if our file consists of a single table, we first need to open an SGML parser. We can use SGMLNextElement to get the first element in the file, and SGMLGetElementString to get the string representation of that. If it’s not a TABLE tag, then we can return an error message about the page break being invalid. Otherwise, we can continue validation. Next, we use SGMLFindClosingElement to move our parser to the end of the table, and use SGMLNextElement again. If the next element was blank, it means there’s nothing after our table, so we’re good to go, and can return no error. If there is something after the table though, we need to display an error message, and return an error code to prevent the save operation from firing. Now let’s take a look at the page break edit cancel function.
/****************************************/ int cancel_edit_break(){ /* cancel editing a page break */ /****************************************/ int ix, size; /* counters */ int rc; /* return code */ handle pb_handle; /* handle to currently open break */ string pb_fname; /* name of page break file */ string windows[][]; /* names of open windows */ /* */ windows = EnumerateEditWindows(); /* get all open window */ size = ArrayGetAxisDepth(windows); /* get the size of the windows array */ pb_fname = GetSessionString(EDITING_PB_SV_NAME); /* get the name of the page break */ for(ix=0;ix<size;ix++){ /* for each open window */ if(windows[ix]["Filename"] == pb_fname){ /* if the page break is still open */ rc = YesNoBox(ALREADY_EDITING_MSG_BOX); /* display message for already editing */ if(rc!=IDYES){ /* if click yes */ return ERROR_EXIT; /* */ } /* */ pb_handle = MakeHandle(windows[ix]["ClientHandle"]); /* get handle to break window */ ActivateEditWindow(pb_handle); /* activate window */ RunMenuFunction("FILE_CLOSE", "ForceClose:true;"); /* close the file */ } /* */ } /* */ SetSessionValue(EDITING_PB_SV,"false"); /* set session variable for editing */ SetSessionValue(EDITING_PB_SV_NAME,""); /* set filename we're editing */ SetSessionValue(EDITING_PB_SV_ID,""); /* */ MenuDeleteHook("FILE_SAVE"); /* unhook save function */ return ERROR_NONE; /* return no error */ } /* */
The cancel_edit_break function is called by the run_modify and run_save functions, when a user tries to run the page break editor script after they’ve started editing a page break, but before they’ve finished. To do that, we need to first get an array of all active edit windows, the number of windows currently open, and the name of the page break we’re currently editing. Then we can iterate over the list of all windows, and check to see if any of them are our page break. If so, we can prompt the user if they want to abandon editing the old page break, since an edit was started but never finished. If they press anything but yes, we return an error to prevent the function from running. Otherwise, we can just activate the page break edit window, and then close it. If we’ve made it to the end of this function, we can then just reset our session variables to blank values, then we can delete our save hook and return no error. If the user started editing a page break, but never made any changes and then closed the file, this will still work, because it will just skip asking the user if they want to cancel and assume they do, and just reset all the variables back to default values anyway.
/****************************************/ string edgarize_filename(string filename, string ext){ /* edgarize a filename */ /****************************************/ /* */ filename = ClipFileExtension(filename); /* clip file extension from name */ filename = ChangeCase(filename,CASE_CHANGE_LOWER); /* downcase name */ filename = ConvertNoPunctuation(filename); /* remove punctuation */ return filename+"."+ext; /* return */ } /* */
The final function we have here is edgarize_filename. I slightly modified it, so it leaves spaces in the file names, but other than that this is just copy/pasted from a different script. It can really do anything, as long as the string it returns is a valid filename for Windows. As it is now, this script will strip the filename, set everything to lower case, remove all punctuation, and return the result.
That should be all we need to do to modify our script to add a much needed function for editing page breaks. This is going to be added to GoFiler in the next release, but I think I’m going to spend some time adding in more validation, and the ability to just disregard any text it finds outside the table instead of just returning an error. It’s a little beyond the scope of a blog post to go that into depth, but it’s an example of how we can expand this functionality even further. The complete script for this function is included below.
/* PageBreakTemplateManager.ms * * Author: Steven Horowitz * * Notes: Allows a user to save and edit page break templates. */ /************************************************/ /* Defined Error / Warning Messages */ /************************************************/ #define EDITING_PB_SV_ID "EditingPageBreakID" #define EDITING_PB_SV_NAME "EditingPageBreakFilename" #define EDITING_PB_SV "EditingPageBreak" #define TEMPLATE_FILENAME "HeaderFooterList.htm" #define P_TEMPLATE "<P STYLE=\"margin: 0\">{%s}</P>" #define SYNTAX_TAG "HTML_TAG_NOT_TITLE" #define P_START "<P STYLE=\"margin: 0\">{" #define P_END "}</P>" #define END_TABLE "</TABLE>" #define END_P_NAME "end" #define ALREADY_EDITING_MSG_BOX "A page break is already being edited. Only one page break may be edited at a time. Cancel editing previous page break?" #define PAGE_BREAK_INVALID_MSG "A page break must contain only a single table, with nothing before or after it. Please correct this, and try to save again." #define TEMPLATE_HTTP_LOC "http://www.novaworkssoftware.com/files/HeaderFooterList.htm" #define TEMPLATE_BODY_LINE "<BODY STYLE=\"font: 11pt Times New Roman, Times, Serif\">" #define TEST_X 0 #define TEST_Y 10 #define TEST_SAVE false #define TEST_MODIFY true /************************************************/ /* Function Signatures */ /************************************************/ void setup(); /* set up the hooks */ int cancel_edit_break(); /* cancel editing a page break */ int edit(int selected_id); /* edit the page break */ int run_save(int f_id, string mode, handle window); /* run the save template script */ int run_modify(int f_id, string mode); /* run the modify template script */ void modify_load(); /* load the modify dialog */ int save_validate(); /* validate if we can save a page break name */ int read_page_breaks(string filename); /* read the page breaks from a given file */ int save_page_breaks(string filename); /* save the page breaks to a given file */ int rename(string selected); /* rename a template */ int delete(string selected); /* delete a template */ int check_template_folder(); /* checks to make sure the template file exists */ void toggle_buttons(int selected, int size); /* enable / disable buttons based on selection */ string edgarize_filename(string filename, string ext); /* edgarizes a filename, making it compliant */ int save_edit(int f_id, string mode); /* saves edits to a break */ int validate_file(handle window); /* validate that the file has a valid pagebreak */ /* */ /* */ /************************************************/ /* global values */ /************************************************/ string table_code; /* code for a table being saved */ int old_selected; /* previously selected item */ string page_breaks[][]; /* array of all page break text */ boolean modified; /* true if we modify the page break template */ string renaming; /* the template we're currently renaming */ int selected_id; /* the id of the template w're renaming */ boolean is_editing; /* true if we're editing a page break */ /****************************************/ void setup() { /* Called from Application Startup */ /****************************************/ string fn; /* file name */ string t_path; /* template path */ string item[10]; /* menu item array */ string settings; /* the settings file location */ /* */ t_path = GetApplicationExecuteFolder(); /* get the execution folder */ t_path = AddPaths(t_path,"Templates"); /* get the templates folder */ if (IsFile(AddPaths(t_path,TEMPLATE_FILENAME))==true){ /* */ return; /* */ } /* */ item["Code"] = "SAVE_PAGE_BREAK"; /* set hook code */ item["Description"] ="Save the current table as page break preset.";/* set hook description */ item["MenuText"] = "Save Page Break Template"; /* set menu text */ item["Class"] = "EditExtension"; /* set class as document */ item["SmallBitmap"] = "PAGE_BREAK_SAVE"; /* set icon */ MenuAddFunction(item); /* add menu item to menu */ fn = GetScriptFilename(); /* get the filename of the script */ MenuSetHook("SAVE_PAGE_BREAK", fn, "run_save"); /* set the hook */ /* add modify function */ item["Code"] = "MANAGE_PAGE_BREAKS"; /* set hook code */ item["Description"] ="Manage the Page Break Templates."; /* set hook description */ item["MenuText"] = "Manage Page Break Templates"; /* set menu text */ item["Class"] = "EditExtension"; /* set class as document */ item["SmallBitmap"] = "PAGE_BREAK_MANAGE"; /* set icon */ MenuAddFunction(item); /* add menu item to menu */ fn = GetScriptFilename(); /* get the filename of the script */ MenuSetHook("MANAGE_PAGE_BREAKS", fn, "run_modify"); /* set the hook */ } /* */ /****************************************/ void main(){ /* main function */ /****************************************/ int ix; /* counter */ int size; /* number of open windows */ string filename; /* filename of a window */ string ext; /* extension of current filename */ string windows[][]; /* array of all available windows */ /* */ if(GetScriptParent()=="LegatoIDE"){ /* if we're in IDE mode */ if (TEST_MODIFY){ /* if we're testing modify */ run_modify(0,"preprocess"); /* run preprocess */ } /* */ if (TEST_SAVE){ /* if we're testing save */ windows = EnumerateEditWindows(); /* get all active edit windows */ size = ArrayGetAxisDepth(windows); /* get the number of open windows */ for(ix=0;ix<size;ix++){ /* for each open edit window */ filename = windows[ix]["Filename"]; /* get the filename of the window open */ ext = GetExtension(filename); /* get the extension to the filename */ if (ext == ".htm"){ /* if the extension is HTML */ MessageBox("running save on file %s",filename); /* display running save */ run_save(0,"preprocess", /* run the save function */ MakeHandle(windows[ix]["ClientHandle"])); /* run the save function on the window */ } /* */ } /* */ } /* */ } /* */ setup(); /* run setup */ } /* */ /****************************************/ int run_modify(int f_id, string mode){ /* run the modify function */ /****************************************/ string template_file; /* the template file */ int rc; /* return code */ /* */ if (mode!="preprocess"){ /* if not preprocess */ SetLastError(ERROR_NONE); /* set the last error */ return ERROR_EXIT; /* return */ } /* */ if(GetSessionString(EDITING_PB_SV)=="true"){ /* if we are already editing a break */ rc = cancel_edit_break(); /* run the cancel edit break function */ } /* */ if(rc == ERROR_EXIT){ /* if the return is an error */ return rc; /* return the error code */ } /* */ selected_id = -1; /* unset renaming id */ renaming = ""; /* reset renaming */ modified = false; /* reset modified */ rc = check_template_folder(); /* check the templates folder */ if (rc!=ERROR_NONE){ /* if we have an error */ return ERROR_EXIT; /* return error */ } /* */ template_file = GetApplicationDataFolder(); /* Get the appdata directory */ template_file = AddPaths(template_file,"Templates"); /* build path to templates folder */ template_file = AddPaths(template_file,TEMPLATE_FILENAME); /* set path to template file */ rc = read_page_breaks(template_file); /* read the page break template */ if (rc!=ERROR_NONE){ /* if we have an error */ SetLastError(rc); /* set the last error message */ return ERROR_EXIT; /* return error */ } /* */ rc = DialogBox(MANAGE_TEMPLATES_DLG, "modify_"); /* enter the save dialog */ SetLastError(rc); /* set the last error */ return ERROR_EXIT; /* return no error */ } /* */ /****************************************/ void modify_load(){ /* load options into the modify dialog */ /****************************************/ string names[]; /* list of names of page breaks */ string name; /* name of a page break */ int selected; /* previously selected value */ int ix; /* loop counter */ int nx; /* name counter */ int size; /* size of page break array */ /* */ ControlChangeFont(ADJ_UP,"Webding"); /* set wingdings */ ControlChangeFont(ADJ_DOWN,"Webding"); /* set wingdings */ size = ArrayGetAxisDepth(page_breaks); /* get size of page breaks array */ selected = DataControlGetRowSelection(TEMPLATE_LIST); /* get the selected item from the list */ toggle_buttons(selected,size); /* toggle buttons off and on */ DataControlResetContent(TEMPLATE_LIST); /* reset contents of the dialog */ DataControlSetColumnHeadings(TEMPLATE_LIST,"Template Name"); /* set the heading for the data control */ DataControlSetColumnPositions(TEMPLATE_LIST, 267); /* set the width of the heading */ for(ix=0;ix<size;ix++){ /* for each page break */ if((page_breaks[ix][0]!=SYNTAX_TAG) && /* if it's not a part of the HTML syntax*/ (page_breaks[ix][0]!="")){ /* if it's not blank */ name = ReplaceInString(page_breaks[ix][0],P_START,""); /* strip out p start tag */ name = ReplaceInString(name,P_END,""); /* strip out p end tag */ DataControlInsertString(TEMPLATE_LIST,ix,name); /* add it to the dialog */ } /* */ } /* */ if (selected > 0){ /* if we had a selected value */ DataControlSetRowSelection(TEMPLATE_LIST,selected); /* reset the previous selection */ } /* */ } /* */ /****************************************/ void modify_ok(){ /* save changes to page breaks */ /****************************************/ string template_file; /* path to template file */ /* */ template_file = GetApplicationDataFolder(); /* Get the appdata directory */ template_file = AddPaths(template_file,"Templates"); /* build path to templates folder */ template_file = AddPaths(template_file,TEMPLATE_FILENAME); /* set path to template file */ if (modified == true){ /* if we changed anything */ save_page_breaks(template_file); /* save the page break template */ } /* */ } /* */ /****************************************/ void modify_action(int c_id, int action){ /* action on the modify dialog */ /****************************************/ string temp[]; /* temp array for data storage */ string selected_nm; /* selected name */ string selected_fn; /* selected full name */ int dir; /* direction we're moving the selection */ int size; /* size of page break table */ int ix; /* loop counter */ int selected; /* selected index value */ string data[][]; /* content of the dialog's list */ int rc; /* result code */ /* */ if( (c_id == ADJ_UP && action == BN_CLICKED) /* if up is pressed */ || (c_id == ADJ_DOWN && action == BN_CLICKED) /* if down is pressed */ || (c_id == TEMPLATE_RENAME && action == BN_CLICKED) /* if rename is pressed */ || (c_id == TEMPLATE_DELETE && action == BN_CLICKED) /* if delete is pressed */ || (c_id == TEMPLATE_LIST && action == DCN_DOUBLE_CLICK || /* if template list is double clicked */ action == DCN_SELECT_CHANGE) /* or the selection changes */ || (c_id == TEMPLATE_EDIT && action == BN_CLICKED)){ /* if edit is clicked */ old_selected = selected; /* set the last item selected */ selected = DataControlGetRowSelection(TEMPLATE_LIST); /* get the selected item from the list */ if (selected <0){ /* if we have no selection */ return; /* nothing to do */ } /* */ data = DataControlGetTable(TEMPLATE_LIST); /* get the data from the list */ toggle_buttons(selected,ArrayGetAxisDepth(data)); /* toggle buttons off and on */ if (c_id == TEMPLATE_LIST && action == DCN_DOUBLE_CLICK){ /* if user double clicked a list item */ c_id = TEMPLATE_EDIT; /* do same thing as if user did rename */ } /* */ selected_nm = TrimPadding(data[selected][0]); /* get the name of the selected row */ selected_fn = FormatString(P_TEMPLATE,selected_nm); /* get full name of renaming template */ selected_id = -1; /* init renaming ID to -1 */ size = ArrayGetAxisDepth(page_breaks); /* get size of page break table */ for(ix=0;ix<size;ix++){ /* for each row in table */ if (selected_fn == TrimPadding(page_breaks[ix][0])){ /* if name matches the row in the db */ selected_id = ix; /* store ID for later */ break; /* break loop */ } /* */ } /* */ if (c_id == ADJ_UP || c_id == ADJ_DOWN){ /* if adjusting the list order */ modified = true; /* flag file as modified */ if (c_id == ADJ_UP){ /* if up button pressed */ dir = -1; /* set direction to move up in list */ } /* */ if (c_id == ADJ_DOWN){ /* if down button pressed */ dir = 1; /* set direction to move down in list */ } /* */ DataControlSwapRows(TEMPLATE_LIST,selected,selected+dir); /* swap row up in list */ DataControlSetRowSelection(TEMPLATE_LIST,selected+dir); /* set the selection */ selected = selected+dir; /* change selection variable */ temp = page_breaks[selected_id]; /* store selection */ page_breaks[selected_id] = page_breaks[selected_id+dir]; /* swap rows */ page_breaks[selected_id+dir] = temp; /* swap rows */ toggle_buttons(selected,ArrayGetAxisDepth(data)); /* toggle buttons off and on */ } /* */ if (c_id == TEMPLATE_RENAME){ /* if rename was pressed */ rc = rename(selected_nm); /* run the rename function */ if (IsError(rc)==false){ /* if rename didn't return an error */ modify_load(); /* reload the list */ } /* */ return; /* return */ } /* */ if (c_id == TEMPLATE_EDIT){ /* if editing a template */ rc = edit(selected_id); /* enter the edit function */ return; /* */ } /* */ if (c_id == TEMPLATE_DELETE){ /* if delete was pressed */ rc = delete(selected_nm); /* run the delete function */ if (IsError(rc)==false){ /* if delete didn't return an error */ DataControlSetRowSelection(TEMPLATE_LIST,-1); /* reset selection */ selected = -1; /* reset selected variable */ modify_load(); /* reload the list */ } /* */ return; /* return */ } /* */ } /* */ /* */ } /* ` */ /****************************************/ void toggle_buttons(int selected, int size){ /* enables or disables buttons */ /****************************************/ if (selected <0){ /* if nothing is selected */ ControlDisable(ADJ_DOWN); /* disable the down button */ ControlDisable(ADJ_UP); /* disable the up button */ ControlDisable(TEMPLATE_RENAME); /* disable the template rename */ ControlDisable(TEMPLATE_DELETE); /* disable template delete */ ControlDisable(TEMPLATE_EDIT); /* disable edit template */ return; /* return, nothing else to do */ } /* */ else{ /* if we have a selection */ ControlEnable(ADJ_DOWN); /* enable the down button */ ControlEnable(ADJ_UP); /* enable the up button */ if (selected == 0){ /* if first item is selected */ ControlDisable(ADJ_UP); /* disable the up button */ } /* */ if (selected == size-1){ /* if last item is selected */ ControlDisable(ADJ_DOWN); /* disable the down button */ } /* */ ControlEnable(TEMPLATE_RENAME); /* enable the control */ ControlEnable(TEMPLATE_DELETE); /* enable the control */ ControlEnable(TEMPLATE_EDIT); /* enable the control */ } /* */ } /* */ /****************************************/ int edit(int selected_id){ /* edit the selected page break */ /****************************************/ int rc; /* return code */ string fn; /* script file name */ string tempfile; /* temp file name */ string temppath; /* path to temp folder */ string filename; /* temp file name */ handle edit_obj; /* handle to edit object */ /* */ filename = page_breaks[selected_id][0]; /* set filename */ filename = ReplaceInString(filename,"<P STYLE=\"margin: 0\">{",""); /* replace the open P tag */ filename = ReplaceInString(filename,"}</P>\r\n",""); /* replace the close P tag */ filename = edgarize_filename(filename,"htm"); /* make filename edgar compliant */ temppath = GetTempFileFolder(); /* get the temp folder path */ tempfile = AddPaths(temppath,filename); /* set new filename */ SetSessionValue(EDITING_PB_SV,"true"); /* set session variable for editing */ SetSessionValue(EDITING_PB_SV_NAME,tempfile); /* set filename we're editing */ SetSessionValue(EDITING_PB_SV_ID, selected_id); /* */ rc = StringToFile(page_breaks[selected_id][1], tempfile); /* write out temp file */ if(IsError(rc)){ /* if we cannot write out the file */ MessageBox('x',"Cannot edit the page break template selected."); /* display error */ return ERROR_EXIT; /* return */ } /* */ RunMenuFunction("FILE_OPEN", "Filename:"+tempfile); /* open a new page view */ fn = GetScriptFilename(); /* get the filename of the script */ rc = MenuSetHook("FILE_SAVE", fn, "save_edit"); /* set the hook on the save function */ if(IsError(rc)){ /* if we cannot hook save */ MessageBox('x',"Unable to hook to save function, error %0x",rc); /* display error code */ } /* */ DialogPostOK(); /* close the dialog */ return ERROR_NONE; /* return without error */ } /* */ /****************************************/ int save_edit(int f_id, string mode){ /* save any edits made to page break */ /****************************************/ int rc; /* return code */ string id_s; /* string value of ID for table row */ long id; /* ID of the table row editing */ handle window; /* the currently active window */ string template_file; /* template file path */ string pb_fname; /* currently editing pb filename */ string window_fn; /* active edit window filename */ string contents; /* contents of the page break */ /* */ window = GetActiveEditWindow(); /* get the active edit window */ window_fn = GetEditWindowFilename(window); /* get the active window filename */ pb_fname = GetSessionString(EDITING_PB_SV_NAME); /* get the name of the page break */ id_s = GetSessionString(EDITING_PB_SV_ID); /* get ID of page break */ id = TextToInteger(id_s); /* get integer value of ID */ if(window_fn == pb_fname){ /* if this is the current pb file */ if(mode!="postprocess"){ /* only run in postprocess */ return validate_file(window); /* validate the file */ } /* */ MenuDeleteHook("FILE_SAVE"); /* delete the hooked function */ RunMenuFunction("FILE_CLOSE", "ForceClose:true;"); /* close the open file */ contents = FileToString(pb_fname); /* get contents of page break */ template_file = GetApplicationDataFolder(); /* Get the appdata directory */ template_file = AddPaths(template_file,"Templates"); /* build path to templates folder */ template_file = AddPaths(template_file,TEMPLATE_FILENAME); /* set path to template file */ rc = read_page_breaks(template_file); /* read the page break template */ page_breaks[id][1] = contents; /* set contents of file into table */ if (rc!=ERROR_NONE){ /* if we have an error */ SetLastError(rc); /* set the last error message */ return ERROR_EXIT; /* return error */ } /* */ modified = true; /* save that the file has been modified */ modify_ok(); /* run the modify OK function to save */ } /* */ return ERROR_NONE; /* return without error */ } /* */ /****************************************/ int validate_file(handle window){ /* validate file */ /****************************************/ string next; /* next element */ string tbody; /* body of the table */ string element; /* element token */ handle sgml; /* sgml parser handle */ /* */ sgml = SGMLCreate(window); /* get handle to SGML parser */ SGMLSetHTMLDTD(sgml,DTD_DEFAULT_EDGAR_HYBRID); /* set DTD to EDGAR */ next = SGMLNextElement(sgml); /* get first SGML element */ element = SGMLGetElementString(sgml); /* get element type */ if(element == "TABLE"){ /* if it's a table */ tbody = SGMLFindClosingElement(sgml); /* get closing element */ element = SGMLNextElement(sgml); /* get next element */ if(element == ""){ /* if the element is blank */ return ERROR_NONE; /* return no error */ } /* */ else{ /* if there is more after the table */ MessageBox('x',PAGE_BREAK_INVALID_MSG); /* display error */ return ERROR_EXIT; /* return error */ } /* */ } /* */ else{ /* if it's not a table tag */ MessageBox('x',PAGE_BREAK_INVALID_MSG); /* display error */ return ERROR_EXIT; /* return error */ } /* */ return ERROR_NONE; /* return no error by default */ } /* */ /****************************************/ int cancel_edit_break(){ /* cancel editing a page break */ /****************************************/ int ix, size; /* counters */ int rc; /* return code */ handle pb_handle; /* handle to currently open break */ string pb_fname; /* name of page break file */ string windows[][]; /* names of open windows */ /* */ windows = EnumerateEditWindows(); /* get all open window */ size = ArrayGetAxisDepth(windows); /* get the size of the windows array */ pb_fname = GetSessionString(EDITING_PB_SV_NAME); /* get the name of the page break */ for(ix=0;ix<size;ix++){ /* for each open window */ if(windows[ix]["Filename"] == pb_fname){ /* if the page break is still open */ rc = YesNoBox(ALREADY_EDITING_MSG_BOX); /* display message for already editing */ if(rc!=IDYES){ /* if click yes */ return ERROR_EXIT; /* */ } /* */ pb_handle = MakeHandle(windows[ix]["ClientHandle"]); /* get handle to break window */ ActivateEditWindow(pb_handle); /* activate window */ RunMenuFunction("FILE_CLOSE", "ForceClose:true;"); /* close the file */ } /* */ } /* */ SetSessionValue(EDITING_PB_SV,"false"); /* set session variable for editing */ SetSessionValue(EDITING_PB_SV_NAME,""); /* set filename we're editing */ SetSessionValue(EDITING_PB_SV_ID,""); /* */ MenuDeleteHook("FILE_SAVE"); /* unhook save function */ return ERROR_NONE; /* return no error */ } /* */ /****************************************/ int rename(string selected){ /* rename selected template */ /****************************************/ string fullname; /* full original name of break */ int rc; /* return code */ int s_pos; /* selected row position */ /* */ renaming = TrimPadding(selected); /* save the page break we're renaming */ rc = DialogBox(PAGEBREAK_TEMPLATES, "rename_"); /* enter the rename dialog */ return ERROR_NONE; /* return no error */ } /* */ /****************************************/ int delete(string selected){ /* delete selected template */ /****************************************/ int rc; /* return code */ /* */ rc= YesNoBox('q',"This will delete '%s', do you want to continue?", /* ask user if they want to delete */ selected); /* ask user to delete */ if (rc==IDYES){ /* if user pressed yes */ page_breaks[selected_id][0] = ""; /* delete page break */ page_breaks[selected_id][1] = ""; /* delete page break */ modified = true; /* set modified flag */ } /* */ return ERROR_NONE; /* */ } /* */ /****************************************/ int rename_load(){ /* load the rename dialog */ /****************************************/ EditSetText(TEMPLATE_NAME,renaming); /* load name of what we're renaming */ } /* */ /****************************************/ int rename_validate(){ /* validate the save name dialog */ /****************************************/ return save_validate(); /* alias to save_validate */ } /* */ /****************************************/ int rename_ok(){ /* process the rename */ /****************************************/ string newname; /* new name of page break */ /* */ if (selected_id>=0){ /* if we're renaming something */ newname = TrimPadding(EditGetText(TEMPLATE_NAME)); /* get the base new name */ newname = FormatString(P_TEMPLATE,newname)+"\r\n"; /* get full new name */ if (page_breaks[selected_id][0] != newname){ /* if we're actually modifying the name */ page_breaks[selected_id][0]=newname; /* set new name */ modified = true; /* set modified flag */ } /* */ modify_load(); /* reload modify dialog */ } /* */ } /* */ /****************************************/ int read_page_breaks(string filename){ /* read the page breaks */ /****************************************/ handle file; /* handle to template file */ handle wp; /* word parser object */ string line; /* individual line from template */ string next_word; /* next word in word parser */ string content; /* the content of the page break */ boolean in_break; /* true if in a page break */ int size; /* number of lines in file */ int ix; /* line counter */ int px; /* page counter */ int rc; /* return code */ /* */ file = OpenMappedTextFile(filename); /* open the template file */ rc = GetLastError(); /* get the last error */ if (IsError(rc)){ /* if we couldn't open the file */ MessageBox('x',"Cannot open template file."); /* display error message */ return ERROR_EXIT; /* return error */ } /* */ size = GetLineCount(file); /* get number of lines in file */ wp = WordParseCreate(WP_SGML_TAG); /* create word parser */ while (ix<size){ /* for each line in file */ line = ReadLine(file,ix); /* read a line from the file */ if (in_break){ /* if we're in a page break */ if (line!=""){ /* if the line has text */ content+=line+"\r\n"; /* add the line to the content */ } /* */ if (FindInString(line,END_TABLE)>=0){ /* if line has a close table */ in_break = false; /* we're not in a page break anymore */ page_breaks[px][1] = content+"\r\n"; /* store the page break in array */ content = ""; /* reset content variable */ px++; /* increment page counter */ } /* */ } /* */ else{ /* if we're not in a page break */ if (FindInString(line,P_START)==0){ /* if line starts with paragraph */ if (FindInString(line,FormatString("{%s}",END_P_NAME))>0){ /* if the paragraph is an end para */ page_breaks[px][0] = SYNTAX_TAG; /* set title to keyword */ page_breaks[px][1] = line+"\r\n"; /* store content of line */ px++; /* increment page break counter */ } /* */ else{ /* if it's not the end para */ in_break = true; /* we're now in a page break */ page_breaks[px][0] = line+"\r\n"; /* get the title */ } /* */ } /* */ else{ /* if we're not starting a page break */ if (line!=""){ /* if the line isn't blank */ page_breaks[px][0] = SYNTAX_TAG; /* set title to keyword */ page_breaks[px][1] = line+"\r\n"; /* store content of line */ px++; /* increment page break counter */ } /* */ } /* */ } /* */ ix++; /* increment counter */ } /* */ CloseHandle(wp); /* close the word parser */ CloseHandle(file); /* close the open file */ return ERROR_NONE; /* return without error */ } /* */ /****************************************/ int save_page_breaks(string filename){ /* save the page breaks to given file */ /****************************************/ handle file; /* the output file */ int rc; /* return code */ int size; /* size of page break array */ int ix; /* counter */ /* */ file = PoolCreate(); /* create a new mapped text file */ rc = GetLastError(); /* */ if (IsError(rc)){ /* if there is an error */ SetLastError(rc); /* set the error code */ return ERROR_EXIT; /* return an error */ } /* */ size = ArrayGetAxisDepth(page_breaks); /* get size of page break array */ for(ix=0;ix<size;ix++){ /* for each page break */ if(page_breaks[ix][0]!=""){ /* if there's something in this row */ if (page_breaks[ix][0]!=SYNTAX_TAG){ /* if it's not just part of template */ PoolAppend(file,page_breaks[ix][0]); /* write the title of the page break */ PoolAppend(file,"\r\n"); /* write a blank line */ } /* */ PoolAppend(file,page_breaks[ix][1]); /* write the content */ } /* */ } /* */ PoolWriteFile(file,filename); /* write output */ CloseHandle(file); /* close handle to the file */ return ERROR_NONE; /* return no error */ } /* */ /****************************************/ int check_template_folder(){ /* ensure the templates folder exists */ /****************************************/ int rc; /* return code */ string template_folder; /* the template folder */ string template_file; /* the template file */ /* */ template_folder = GetApplicationDataFolder(); /* Get the appdata directory */ template_folder = AddPaths(template_folder,"Templates"); /* build path to templates folder */ if (IsFolder(template_folder)==false){ /* if template folder doesn't exist */ rc = CreateFolder(template_folder); /* create the template folder */ if (IsError(rc)){ /* if we cannot create the folder */ MessageBox('x',"Cannot create template folder, error %0x",rc); /* display error */ return rc; /* return error code */ } } /* */ template_file = AddPaths(template_folder,TEMPLATE_FILENAME); /* set path to template file */ if (IsFile(template_file)==false){ /* if template file doesn't exist */ rc = HTTPGetFile(TEMPLATE_HTTP_LOC,template_file); /* get the template file */ if (IsError(rc)){ /* if we couldn't get the template */ MessageBox('x',"Cannot get template file, error %0x",rc); /* display error */ return rc; /* return with error */ } /* */ } /* */ return ERROR_NONE; /* return no error */ } /****************************************/ int run_save(int f_id, string mode, handle window){ /* run the save function */ /****************************************/ int rc; /* return code */ dword window_type; /* get the edit window type */ handle edit_object; /* handle to the edit object */ int caret[]; /* caret positions */ string template_file; /* the template file path */ string tag; /* full text of element tag */ string element; /* the current element */ handle sgml; /* handle to the SGML parser */ /* */ if (mode != "preprocess"){ /* if not preprocess */ SetLastError(ERROR_NONE); /* set last error to nothing */ return ERROR_EXIT; /* bail out */ } /* */ if(GetSessionString(EDITING_PB_SV)=="true"){ /* if we are already editing a break */ rc = cancel_edit_break(); /* run the cancel edit break function */ } /* */ if(rc == ERROR_EXIT){ /* if an exit is returned */ return rc; /* return the error */ } /* */ if (IsWindowHandleValid(window)==false){ /* if we have no valid handle */ window = GetActiveEditWindow(); /* get the active edit window */ window_type = GetEditWindowType(window); /* get the edit window type */ window_type = window_type & EDX_TYPE_ID_MASK; /* mask file type */ if (window_type != EDX_TYPE_PSG_PAGE_VIEW){ /* if we're not in page view */ MessageBox('x',"This function must be used in page view."); /* display error */ return ERROR_EXIT; /* quit running */ } /* */ edit_object = GetEditObject(window); /* get edit object from window */ caret[0] = GetCaretXPosition(window); /* get the caret position in window */ caret[1] = GetCaretYPosition(window); /* get the caret position in window */ } /* */ else{ /* if we were passed a window */ edit_object = GetEditObject(window); /* get edit object from window */ caret[0] = TEST_X; /* set test position x */ caret[1] = TEST_Y; /* set test postion y */ } /* */ sgml = SGMLCreate(edit_object); /* get handle to SGML object */ SGMLSetPosition(sgml,caret[0],caret[1]); /* set position in SGML parser */ tag = "init"; /* initialize element with a value */ while (MakeUpperCase(element)!="TABLE" && tag!=""){ /* while element is not table and exists*/ tag = SGMLPreviousElement(sgml); /* get the previous SGML tag */ element = SGMLGetElementString(sgml); /* get the string value of the element */ } /* */ if (tag == ""){ /* if the element is empty */ MessageBox('x',"This function must be run inside a table."); /* display message */ return ERROR_EXIT; /* quit running */ } /* */ table_code = SGMLFindClosingElement(sgml, /* get the code of the table */ SP_FCE_CODE_AS_IS | SP_FCE_INCLUDE_WRAPPER); /* get the code of the table */ template_file = GetApplicationDataFolder(); /* Get the appdata directory */ template_file = AddPaths(template_file,"Templates"); /* build path to templates folder */ template_file = AddPaths(template_file,TEMPLATE_FILENAME); /* set path to template file */ rc = read_page_breaks(template_file); /* read templates so we can validate */ if (rc!=ERROR_NONE){ /* if we cannot read the templates */ SetLastError(rc); /* set the error */ return ERROR_EXIT; /* return with error */ } /* */ rc = DialogBox(PAGEBREAK_TEMPLATES, "save_"); /* enter the save dialog */ SetLastError(rc); /* set last erorr */ return ERROR_EXIT; /* exit */ } /* */ /****************************************/ int save_validate(){ /* validate the save name dialog */ /****************************************/ string pb_name; /* the name of the page break save */ string renaming_fn; /* full name of the pb we're renaming */ string fullname; /* full name of the page break */ int size; /* size of table */ int n_pos; /* position of name in array */ int ix; /* loop counter */ /* */ pb_name = EditGetText(TEMPLATE_NAME); /* get the template name */ if (pb_name == ""){ /* if page break name is blank */ MessageBox('x',"Template must have a name."); /* display error */ return ERROR_EXIT; /* return error */ } /* */ renaming_fn = FormatString(P_TEMPLATE,renaming); /* get full name of renaming template */ fullname = FormatString(P_TEMPLATE,pb_name); /* get full name of entered template */ size = ArrayGetAxisDepth(page_breaks); /* get the size of the page break array */ n_pos = FindInTable(page_breaks,fullname,0,FIND_NO_CASE); /* check if name already exists */ if (n_pos >= 0 && fullname != renaming_fn){ /* if the name is found */ MessageBox('x',"Name already exists, cannot duplicate."); /* display error */ return ERROR_EXIT; /* return an error */ } /* */ return ERROR_NONE; /* return no error */ } /* */ /****************************************/ int save_ok(){ /* after validating the save dialog */ /****************************************/ int rc; /* return code */ int ix; /* iterator */ int size; /* size of the mapped text file */ string pb_name; /* page break name */ string line; /* content of line of mapped text file */ handle file; /* handle to the template file */ string template_file; /* the template file */ string template_folder; /* templates folder */ /* */ pb_name = EditGetText(TEMPLATE_NAME); /* get the page break template name */ rc = check_template_folder(); /* check the templates folder */ if (rc!=ERROR_NONE){ /* if we have an error */ return ERROR_EXIT; /* return error */ } /* */ template_file = GetApplicationDataFolder(); /* Get the appdata directory */ template_file = AddPaths(template_file,"Templates"); /* build path to templates folder */ template_file = AddPaths(template_file,TEMPLATE_FILENAME); /* set path to template file */ file = OpenMappedTextFile(template_file); /* open the mapped text file */ size = GetLineCount(file); /* get number of lines in mapped text */ while (line != TEMPLATE_BODY_LINE && ix<size){ /* while we haven't found the body */ line = ReadLine(file,ix); /* get the line */ ix++; /* increment line counter */ } /* */ if (line!=TEMPLATE_BODY_LINE){ /* if we couldn't find the body */ MessageBox('x',"Template file is not valid."); /* display an error message */ return ERROR_EXIT; /* return error */ } /* */ line = FormatString(P_TEMPLATE,pb_name); /* build line to insert */ line+= "\r\n\r\n"+table_code+"\r\n"; /* build line to insert */ InsertLine(file,ix,line); /* insert line */ MappedTextSave(file); /* save our modified file */ rc = GetLastError(); /* get the last error */ if (IsError(rc)){ /* if we can't save */ MessageBox('x',"Cannot save template file."); /* display an error */ return ERROR_EXIT; /* return an error */ } /* */ return ERROR_NONE; /* return no error */ } /* */ /****************************************/ string edgarize_filename(string filename, string ext){ /* edgarize a filename */ /****************************************/ /* */ filename = ClipFileExtension(filename); /* clip file extension from name */ filename = ChangeCase(filename,CASE_CHANGE_LOWER); /* downcase name */ filename = ConvertNoPunctuation(filename); /* remove punctuation */ return filename+"."+ext; /* return */ } /* */ /************************************************/ /* dialog controls */ /************************************************/ #beginresource /****************************************/ /* save template dialog */ /****************************************/ #define PAGEBREAK_TEMPLATES 101 #define TEMPLATE_PROPERTIES 102 #define TEMPLATE_NAME 103 PAGEBREAK_TEMPLATES DIALOGEX 0, 0, 240, 76 EXSTYLE WS_EX_DLGMODALFRAME STYLE DS_MODALFRAME | DS_3DLOOK | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU CAPTION "Header / Footer Properties" FONT 8, "MS Sans Serif" { CONTROL "Frame1", -1, "static", SS_ETCHEDFRAME | WS_CHILD | WS_VISIBLE, 14, 50, 216, 1 CONTROL "OK", IDOK, "button", BS_CENTER | WS_CHILD | WS_VISIBLE | WS_TABSTOP, 128, 57, 50, 14 CONTROL "Cancel", IDCANCEL, "BUTTON", BS_PUSHBUTTON | BS_CENTER | WS_CHILD | WS_VISIBLE | WS_TABSTOP, 183, 57, 50, 14 CONTROL "Name:", -1, "static", WS_CHILD | WS_VISIBLE, 16, 27, 40, 13 CONTROL "Template Properties:", -1, "static", SS_LEFT | WS_CHILD | WS_VISIBLE, 10, 8, 86, 13, 0 CONTROL "Frame1", -1, "static", SS_ETCHEDFRAME | WS_CHILD | WS_VISIBLE, 84, 12, 146, 1, 0 CONTROL "", TEMPLATE_NAME, "edit", ES_LEFT | WS_CHILD | WS_VISIBLE | WS_BORDER | WS_TABSTOP | ES_AUTOHSCROLL, 53, 26, 172, 12, 0 } #define MANAGE_TEMPLATES_DLG 200 #define TEMPLATE_LIST 201 #define TEMPLATE_DELETE 202 #define TEMPLATE_RENAME 203 #define ADJ_UP 204 #define ADJ_DOWN 205 #define TEMPLATE_EDIT 206 MANAGE_TEMPLATES_DLG DIALOGEX 0, 0, 359, 149 EXSTYLE WS_EX_DLGMODALFRAME STYLE DS_3DLOOK | DS_MODALFRAME | DS_SETFONT | WS_CAPTION | WS_VISIBLE | WS_POPUP | WS_SYSMENU CAPTION "Manage Header / Footer Templates" FONT 8, "MS Shell Dlg" { CONTROL "Frame1", -1, "static", SS_ETCHEDFRAME | WS_CHILD | WS_VISIBLE, 12, 123, 340, 1 CONTROL "", TEMPLATE_LIST, "data_control", 0x50A10003, 20, 6, 278, 110, 0x00000000 CONTROL "5 &U", ADJ_UP, "button", BS_PUSHBUTTON | BS_LEFT | WS_CHILD | WS_VISIBLE | WS_TABSTOP, 4, 45, 13, 12, 0 CONTROL "6 &D", ADJ_DOWN, "button", BS_PUSHBUTTON | BS_LEFT | WS_CHILD | WS_VISIBLE | WS_TABSTOP, 4, 60, 13, 12, 0 CONTROL "&Delete", TEMPLATE_DELETE, "button", BS_CENTER | WS_TABSTOP, 303, 7, 50, 14, WS_EX_LEFT CONTROL "&Rename", TEMPLATE_RENAME, "button", BS_CENTER | WS_TABSTOP, 303, 24, 50, 14, WS_EX_LEFT CONTROL "&Edit", TEMPLATE_EDIT, "button", BS_CENTER | WS_TABSTOP, 303, 41, 50, 14, WS_EX_LEFT CONTROL "Save", IDOK, "button", BS_PUSHBUTTON |BS_CENTER | WS_TABSTOP, 247, 129, 50, 14, WS_EX_LEFT CONTROL "Cancel", IDCANCEL, "button", BS_PUSHBUTTON |BS_CENTER | WS_TABSTOP, 303, 129, 50, 14, WS_EX_LEFT } PAGE_BREAK_SAVE BITMAP "page_break_template_save.bmp" PAGE_BREAK_MANAGE BITMAP "page_break_template_manager.bmp" #endresource
Steven Horowitz has been working for Novaworks for over five years as a technical expert with a focus on EDGAR HTML and XBRL. Since the creation of the Legato language in 2015, Steven has been developing scripts to improve the GoFiler user experience. He is currently working toward a Bachelor of Sciences in Software Engineering at RIT and MCC. |
Additional Resources
Legato Script Developers LinkedIn Group
Primer: An Introduction to Legato