LDC #101: Page Break Template Manager, Part 3

Last week, we added a modify dialog for our page break style manager, to let us rename and delete page break styles. This got us to a point where we have what I’d consider “minimal functionality” required to have a useful script, but let’s take it a step further, and add in a re-order function. It’s very useful to be able to shuffle the order around so you can have all styles, for a single client, grouped together. You don’t have to constantly search through a list anymore. While we’re at it, we can add in functionality to disable buttons if they are not applicable to our selection. For example, if we don’t have a selection, everything should be disabled. if we have the top list item selected, the move up button should be disabled, because we obviously can’t move the top item up even higher. The opposite applies to the bottom selection.

Screen shot of Dialog

To do this, we need to add a function, toggle_buttons, and edit the modify_load and modify_action functions a bit. Thetoggle_buttons function is going to handle enabling / disabling buttons, the modify_load function needs to have code for new buttons. The modify_action function needs to actually handle our re-ordering buttons to make sure things are swapped around in the right order. Let’s start by looking at the new modify_load function.

                                                                        /****************************************/
void modify_load(){                                                     /* load options into the modify dialog  */
                                                                        /****************************************/
    ... omitted variable declarations ...
    ControlChangeFont(ADJ_UP,"Wingding");                               /* set wingdings                        */
    ControlChangeFont(ADJ_DOWN,"Wingding");                             /* set wingdings                        */
    size = ArrayGetAxisDepth(page_breaks);                              /* get size of page breaks array        */
    selected = DataControlGetRowSelection(TEMPLATE_LIST);               /* get the selected item from the list  */
    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         */
      }                                                                 /*                                      */
    }                                                                   /*                                      */

The two lines of the modify_load function handle setting the font of the buttons to wingdings. This causes the text to show up and down arrows. I wanted arrow buttons here, and this is the easiest way to achieve this. If you want to use more specific looking arrow buttons, you can always set images as your buttons instead, but using wingdings characters here made sense. Also added to this function was the line to get the selected value from the sheet before clearing it, and after we’ve reset the sheet and added all the items back, if we had a selection to begin with, we set the previously selected row back in. This makes our load function work as both an initial load and a “refresh” function, so we can call it after running a rename and not lose our current selection.

Our modify_action function is pretty heavily modified, so instead of just pointing out modified portions, let’s look at how the whole thing works.

                                                                        /****************************************/
void modify_action(int c_id, int action){                               /* action on the modify dialog          */
                                                                        /****************************************/
    ... omitted variable declarations ...
    if(c_id != ADJ_UP && c_id!= ADJ_DOWN && c_id!=TEMPLATE_RENAME       /* if it's not one of our buttons       */
       && c_id != TEMPLATE_DELETE && action != DCN_DOUBLE_CLICK){       /* or a double click                    */
        return;                                                         /*                                      */
        }                                                               /*              `                       */
    selected = DataControlGetRowSelection(TEMPLATE_LIST);               /* get the selected item from the list  */
    data = DataControlGetTable(TEMPLATE_LIST);                          /* get the data from the list           */
    toggle_buttons(selected,ArrayGetAxisDepth(data));                   /* toggle buttons off and on            */
    if (selected <0){                                                   /* if we have no selection              */
      return;                                                           /* nothing to do                        */
      }                                                                 /*                                      */
    if (c_id == TEMPLATE_LIST && action == DCN_DOUBLE_CLICK){           /* if user double clicked a list item   */
        c_id = TEMPLATE_RENAME;                                         /* do same thing as if user did rename  */
      }                                                                 /*                                      */

The modify_action function starts off by testing to see if the control calling it is one of our buttons, or if it’s a double click action. If it’s not any of these, then it can just return, because there’s nothing to do here. We need to do this because this function is called whenever a user does anything on the dialog, including moving the mouse. If it’s called repeatedly, we need to make sure it’s extremely fast to exit if it doesn’t have to do anything. Then, we can get the selected value and the data table, and running the toggle_buttons function to ensure the available buttons are appropriate for whatever was selected. If there wasn’t a selected value, we can just return here, because there’s nothing else to do. If the control was the TEMPLATE_LIST, and the user double-clicked on it, we can just treat it as though the user pressed the Rename button, so we can change the control id variable c_id to the TEMPLATE_RENAME value, so we can just act like we’re renaming the template.

    
    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                           */
        }                                                               /*                                      */
      }                                                                 /*                                      */

This section of code is copied from the previous version of this function. We need to get the selected template name, format it with our paragraph tags to wrap around it, and then find it in our page breaks array, to get the row number of our selection in the underlying data structure, page_breaks.

    
    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 the user has pressed the ADJ_UP or ADJ_DOWN buttons (our new re-order up or down buttons), then we need to set the direction we’re moving in to either 1 or -1 depending on the button pressed. We can then use the DataControlSwapRows andDataControlSetRowSelection functions to swap our selected row either up or down one, and move our selection onto our new row position. This just changes the display though, so we need to change our data structure that actually holds the page breaks as well, so we can use our temp variable temp to hold our selected row’s value, then swap the value that was previously at the position we’re moving to with our selected value.

    
    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_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                      */
        toggle_buttons(selected,ArrayGetAxisDepth(data));               /* toggle buttons off and on            */
        }                                                               /*                                      */
      return;                                                           /* return                               */
      }                                                                 /*                                      */
    }                                                                   /*                                      */

The last two if statements in this function cover what to do if Rename or Delete buttons are pressed. This is pretty similar to what we had last week, but with some slight differences. Now that our load_modify function restores our last selected value whenever we call it, the Delete button needs to set the selected value to -1 to drop the selection, so that when our list reloads it doesn’t automatically select whatever is now in the position that was previously occupied by our deleted row. We also need to call toggle_buttons, so that it disables all of our dialog buttons until the user selects something else.

                                                                        /****************************************/
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              */
      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                   */
      }                                                                 /*                                      */
    }                                                                   /*                                      */

The toggle_buttons function takes our selected value and the size of the selected array as parameters, and enables or disables buttons based on those values. If nothing is selected, then we can just run ControlDisable to disable all of our buttons, and return, because we’re done. Otherwise, we can enable our up and down buttons, then check to see if they should actually be enabled. If selected is 0, then we’ve selected the first item, so ADJ_UP should be disabled. If the selected value equals the last row, then we need to disable ADJ_DOWN since you can’t press down anymore. Finally we can enable our delete and rename buttons, since the user has selected something.

With these changes, we’ve got a pretty useful little script now. We can save page breaks from our HTML file into a template, and we can go into a manager to rename, delete, or re-order that template file around however we want it. There are more things we could do to make this even fancier and more useful (like an edit button that would open the selected template in an edit window) we always need to keep in mind how long it would take to create that functionality, compared to how much time it would really save. I think where the script is at now is a pretty good balance of useful and quick to write, so this is a good place to leave it.

Here’s the complete script file, with all changes made:

/* PageBreakTemplateManager.ms
 *
 * Author: Steven Horowitz
 *
 * Notes: Allows a user to save and edit page break templates.
 */

                                                                /************************************************/
                                                                /* Defined Error / Warning Messages             */
                                                                /************************************************/
#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         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             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  */
                                                                /*                                              */
                                                                /************************************************/
                                                                /* global values                                */
                                                                /************************************************/
string          table_code;                                     /* code for a table being saved                 */
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         */

                                                                        /****************************************/
void setup() {                                                          /* Called from Application Startup      */
                                                                        /****************************************/
    string              fn;                                             /* file name                            */
    string              item[10];                                       /* menu item array                      */
    string              settings;                                       /* the settings file location           */
                                                                        /*                                      */
    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"] = "DocumentExtension";                                /* set class as document                */
    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"] = "MODIFY_PAGE_BREAK";                                 /* set hook code                        */
    item["Description"] ="Modify the Page Break Templates.";            /* set hook description                 */
    item["MenuText"] = "Modify Page Break Template";                    /* set menu text                        */
    item["Class"] = "DocumentExtension";                                /* set class as document                */
    MenuAddFunction(item);                                              /* add menu item to menu                */
    fn = GetScriptFilename();                                           /* get the filename of the script       */
    MenuSetHook("MODIFY_PAGE_BREAK", 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                               */
      }                                                                 /*                                      */
    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,"Wingding");                               /* set wingdings                        */
    ControlChangeFont(ADJ_DOWN,"Wingding");                             /* set wingdings                        */
    ButtonSetText(ADJ_UP,"é");                                          /* set image icon                       */
    ButtonSetText(ADJ_DOWN,"ê");                                        /* set image icon                       */
    size = ArrayGetAxisDepth(page_breaks);                              /* get size of page breaks array        */
    selected = DataControlGetRowSelection(TEMPLATE_LIST);               /* get the selected item from the list  */
    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 && c_id!= ADJ_DOWN && c_id!=TEMPLATE_RENAME       /* if it's not one of our buttons       */
       && c_id != TEMPLATE_DELETE && action != DCN_DOUBLE_CLICK){       /* or a double click                    */
        return;                                                         /*                                      */
        }                                                               /*              `                       */    
    selected = DataControlGetRowSelection(TEMPLATE_LIST);               /* get the selected item from the list  */
    data = DataControlGetTable(TEMPLATE_LIST);                          /* get the data from the list           */
    toggle_buttons(selected,ArrayGetAxisDepth(data));                   /* toggle buttons off and on            */
    if (selected <0){                                                   /* if we have no selection              */
      return;                                                           /* nothing to do                        */
      }                                                                 /*                                      */
    if (c_id == TEMPLATE_LIST && action == DCN_DOUBLE_CLICK){           /* if user double clicked a list item   */
        c_id = TEMPLATE_RENAME;                                         /* 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_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                      */
        toggle_buttons(selected,ArrayGetAxisDepth(data));               /* toggle buttons off and on            */
        }                                                               /*                                      */
      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              */
      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                   */
      }                                                                 /*                                      */
    }                                                                   /*                                      */
                                                                        /****************************************/
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 (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          */
    element = "init";                                                   /* initialize element with a value      */
    while (element!="TABLE" && element!=""){                            /* 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 (element == ""){                                                 /* 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                      */
    }                                                                   /*                                      */
                                                                /************************************************/
                                                                /* dialog controls                              */
                                                                /************************************************/
#beginresource

                                                                        /****************************************/
                                                                        /* save template dialog                 */
                                                                        /****************************************/
#define PAGEBREAK_TEMPLATES     101
#define TEMPLATE_PROPERTIES     102
#define TEMPLATE_NAME           103

PAGEBREAK_TEMPLATES DIALOGEX 0, 0, 240, 66
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 "OK", IDOK, "BUTTON", BS_PUSHBUTTON | BS_CENTER | WS_CHILD | WS_VISIBLE | WS_TABSTOP, 132, 50, 50, 14
 CONTROL "Cancel", IDCANCEL, "BUTTON", BS_PUSHBUTTON | BS_CENTER | WS_CHILD | WS_VISIBLE | WS_TABSTOP, 187, 50, 50, 14
 CONTROL "Name:", -1, "static", SS_LEFT | WS_CHILD | WS_VISIBLE, 14, 25, 40, 13, 0
 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, 25, 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

MANAGE_TEMPLATES_DLG DIALOGEX 0, 0, 364, 143
EXSTYLE WS_EX_DLGMODALFRAME
STYLE DS_3DLOOK | DS_MODALFRAME | DS_SETFONT | WS_CAPTION | WS_VISIBLE | WS_POPUP | WS_SYSMENU
CAPTION "Manage Preference Templates"
FONT 8, "MS Shell Dlg"
{
 CONTROL "", TEMPLATE_LIST, "data_control", 0x50A10003, 33, 6, 267, 106, 0x00000000
 CONTROL "é    &U", ADJ_UP, "button", BS_PUSHBUTTON | BS_LEFT | WS_CHILD | WS_VISIBLE | WS_TABSTOP, 10, 26, 11, 12, 0
 CONTROL "ê    &D", ADJ_DOWN, "button", BS_PUSHBUTTON | BS_LEFT | WS_CHILD | WS_VISIBLE | WS_TABSTOP, 10, 50, 11, 12, 0
 CONTROL "&Delete", TEMPLATE_DELETE, "button", BS_CENTER, 303, 7, 50, 14, WS_EX_LEFT
 CONTROL "&Rename", TEMPLATE_RENAME, "button", BS_CENTER, 303, 24, 50, 14, WS_EX_LEFT
 CONTROL "", -1, "static", SS_ETCHEDFRAME, 6, 218, 234, 1, WS_EX_LEFT
 CONTROL "Save", IDOK, "button", BS_PUSHBUTTON |BS_CENTER, 247, 123, 50, 14, WS_EX_LEFT
 CONTROL "Cancel", IDCANCEL, "button", BS_PUSHBUTTON |BS_CENTER, 303, 123, 50, 14, WS_EX_LEFT
}

#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.