#ifndef lint static char rcsId[]="$Header: /usr/local/rcs/Newt/XmHTML/RCS/example_3.c,v 1.3 1997/08/30 01:58:42 newt Exp newt $"; #endif /***** * example_3.c : demonstration of the XmHTMLParserObject. * * This file Version $Revision: 1.3 $ * * Creation date: Mon Apr 7 17:42:38 GMT+0100 1997 * Last modification: $Date: 1997/08/30 01:58:42 $ * By: $Author: newt $ * Current State: $State: Exp $ * * Author: newt * * Copyright (C) 1994-1997 by Ripley Software Development * All Rights Reserved * * This file is part of the XmHTML Widget Library. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public * License along with this library; if not, write to the Free * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * *****/ /***** * ChangeLog * $Log: example_3.c,v $ * Revision 1.3 1997/08/30 01:58:42 newt * my_strdup -> strdup changes. * * Revision 1.2 1997/05/28 02:07:04 newt * Changes to reflect the new XmImageCreate proto. * * Revision 1.1 1997/04/29 14:34:12 newt * Initial Revision * *****/ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include /* we want to have a standalone parser */ /***** * Change this to change the application class of the examples *****/ #define APP_CLASS "HTMLDemos" /*** External Function Prototype Declarations ***/ /*** Public Variable Declarations ***/ /*** Private Datatype Declarations ****/ #define FILE_NEW 0 #define FILE_OPEN 1 #define FILE_SAVEAS 2 #define FILE_QUIT 3 #define FILE_SAVETREE 5 /* save parser tree */ #define HTML_VERIFY 0 #define HTML_PROGRESSIVE 1 #define HTML_PREVIEW 2 #define HTML_SAVE 3 #define OPTIONS_SCROLL 0 #define OPTIONS_AUTO 1 #define OPTIONS_NOTIFY 2 #define OK_BUTTON 1 #define APPLY_BUTTON 2 #define CANCEL_BUTTON 3 #define HELP_BUTTON 4 /*** Private Function Prototype Declarations ****/ /* Menu bar callbacks */ static void fileCB(Widget widget, int item); static void htmlCB(Widget widget, int item); static void optionsCB(Widget widget, int item, XmToggleButtonCallbackStruct *cbs); /* text callbacks */ static void modifyCB(Widget widget, XtPointer data, XmTextVerifyPtr cbs); /* various text response routines */ static void cutText(int start_pos, int end_pos); static void insertText(XmHTMLTextBlock text, int start_pos); static void selectText(int start_pos, int end_pos); /* HTML callbacks */ static void modifyHTMLCB(Widget widget, XtPointer data, XmHTMLVerifyPtr cbs); static void parserCB(Widget widget, XtPointer data, XmHTMLParserPtr cbs); static void docCB(Widget widget, XtPointer data, XmHTMLDocumentPtr cbs); static void anchorCB(Widget widget, XtPointer data, XmHTMLAnchorPtr cbs); /* various parser response routines */ static int parserFatal(XmHTMLParserPtr cbs); static int parserBlock(XmHTMLParserPtr cbs); static int parserBadHTML(XmHTMLParserPtr cbs); static int parserUnknownHTML(XmHTMLParserPtr cbs); static int parserOpenElement(XmHTMLParserPtr cbs); static int parserSelectAlias(String unknown); static int addAlias(Widget list, XmHTMLAliasTable global_table, int nglobal, XmHTMLAliasTable parser_table, int nparser, String element); /* Misc. callback routines */ static void dismissCB(Widget widget, XtPointer data); static void readFileCB(Widget widget, Widget dialog, XmFileSelectionBoxCallbackStruct *cbs); static void response(Widget widget, int *answer, XmAnyCallbackStruct *cbs); /* various functions */ static int askUser(String msg); static void setTitle(String title); static void askSave(void); static void tellUser(String msg); static void doPreview(Boolean show); static void parseHTML(void); /* test normal text parsing */ static void parseProgressiveHTML(void); /* test progressive text parsing */ static String loadFile(String filename); /*** Private Variable Declarations ***/ static String use_file, parser_buffer; static Widget toplevel, info_label, html32, verified, balanced, busy_label; static Widget text_w, html_w, preview_dialog; static Boolean file_changed, parser_active; static Boolean scroll_text = False; static Boolean honor_document_cb = False; static XtAppContext context; static XtIntervalId current_id = None; /* progressive timerProc id */ static String working_image_file, ready_image_file; static XmImage *working_image; /* a nice gifAnim */ static XmImage *ready_image; /* a nice gif */ /* and what this example is all about: a html parser */ static Widget parser; /***** * Name: setTitle * Return Type: void * Description: sets the window title. * In: * title: title to set * Returns: * nothing. *****/ static void setTitle(String title) { XtVaSetValues(toplevel, XmNtitle, title, NULL); } /***** * Name: resetBusyLabel * Return Type: void * Description: resets the busy label when we are done processing by * changing the current label text to Ready and by displaying * the ready image * In: * nothing * Returns: * nothing *****/ static void resetBusyLabel(void) { if(working_image && working_image->proc_id) { XtRemoveTimeOut(working_image->proc_id); working_image->proc_id = None; working_image->current_frame = 0; } /* set ready image */ if(ready_image) XtVaSetValues(busy_label, XmNlabelType, XmPIXMAP, XmNlabelPixmap, ready_image->pixmap, NULL); XtVaSetValues(info_label, XtVaTypedArg, XmNlabelString, XmRString, "Ready", 6, NULL); } /***** * Name: modifyCB * Return Type: void * Description: XmNmodifyVerifyCallback handler. Sets the file_changed flag. * In: * widget: widget id * data: client_data, unused * cbs: call_data, unused * Returns: * nothing. *****/ static void modifyCB(Widget w, XtPointer data, XmTextVerifyPtr cbs) { if(!file_changed) { String title; title = (char*)malloc(strlen(use_file) + 12); sprintf(title, "%s (Modified)", use_file); setTitle(title); free(title); } file_changed = True; } /***** * Name: selectText * Return Type: void * Description: selects a portion of text currently displayed in the text * widget. * In: * start_pos: selection start position. * end_pos: selection end position. * Returns: * nothing. *****/ static void selectText(int start_pos, int end_pos) { XmTextSetSelection(text_w, (XmTextPosition)start_pos, (XmTextPosition)end_pos+1, CurrentTime); } /***** * Name: insertText * Return Type: void * Description: inserts text in the document currently displayed in the text * widget. * In: * text: text to be inserted * start_pos: insertion position. * Returns: * nothing. *****/ static void insertText(XmHTMLTextBlock text, int start_pos) { XmTextInsert(text_w, (XmTextPosition)start_pos, text->ptr); } /***** * Name: cutText * Return Type: void * Description: removes text in the document currently displayed in the text * widget. * In: * start_pos: selection start position * end_pos: selection end position * Returns: * nothing. *****/ static void cutText(int start_pos, int end_pos) { /* put text to remove as the primary selection */ XmTextSetSelection(text_w, (XmTextPosition)start_pos, (XmTextPosition)end_pos, CurrentTime); /* cut it */ XmTextCut(text_w, CurrentTime); } /***** * Name: response * Return Type: void * Description: callback routine for all modal message dialogs in this app. * In: * widget: widget id * answer: button pressed, updated upon return; * cbs: call_data. * Returns: * nothing. *****/ static void response(Widget widget, int *answer, XmAnyCallbackStruct *cbs) { switch(cbs->reason) { case XmCR_OK: *answer = OK_BUTTON; break; case XmCR_APPLY: *answer = APPLY_BUTTON; break; case XmCR_CANCEL: *answer = CANCEL_BUTTON; break; case XmCR_HELP: *answer = HELP_BUTTON; break; } } /***** * Name: askUser * Return Type: Boolean * Description: modal question message dialog. * In: * msg: text to display. * Returns: * True when OK has been pressed, False if cancel has been pressed. *****/ static int askUser(String msg) { static Widget msg_box; static int answer; XmString xms; if(msg_box == NULL) { XmString ok_label, cancel_label; msg_box= XmCreateQuestionDialog(toplevel, "Question", NULL, 0); ok_label = XmStringCreateLocalized("Yes"); cancel_label = XmStringCreateLocalized("No"); XtVaSetValues(msg_box, XmNdialogStyle, XmDIALOG_FULL_APPLICATION_MODAL, XmNokLabelString, ok_label, XmNcancelLabelString, cancel_label, NULL); XmStringFree(ok_label); XmStringFree(cancel_label); /* unmanage help button */ XtUnmanageChild(XmMessageBoxGetChild(msg_box, XmDIALOG_HELP_BUTTON)); XtAddCallback(msg_box, XmNokCallback, (XtCallbackProc)response, &answer); XtAddCallback(msg_box, XmNcancelCallback, (XtCallbackProc)response, &answer); XtVaSetValues(XtParent(msg_box), XtNtitle, "Question", NULL); } /* create message string */ xms = XmStringCreateLtoR(msg, XmFONTLIST_DEFAULT_TAG); XtVaSetValues(msg_box, XmNmessageString, xms, XmNdefaultButton, XmDIALOG_OK_BUTTON, NULL); XmStringFree(xms); answer = 0; XtManageChild(msg_box); XtPopup(XtParent(msg_box), XtGrabNone); while(answer == 0) XtAppProcessEvent(context, XtIMAll); XtPopdown(XtParent(msg_box)); return((answer == OK_BUTTON ? True : False)); } /***** * Name: tellUser * Return Type: boolean * Description: modal information message dialog. * In: * msg: text to display. * Returns: * Nothing. *****/ static void tellUser(String msg) { static Widget msg_box; static int answer; XmString xms; if(msg_box == NULL) { XmString ok_label; msg_box= XmCreateInformationDialog(toplevel, "Notice", NULL, 0); ok_label = XmStringCreateLocalized("OK"); XtVaSetValues(msg_box, XmNdialogStyle, XmDIALOG_FULL_APPLICATION_MODAL, XmNokLabelString, ok_label, NULL); XmStringFree(ok_label); /* unmanage help button */ XtUnmanageChild(XmMessageBoxGetChild(msg_box, XmDIALOG_HELP_BUTTON)); /* unmanage cancel button */ XtUnmanageChild(XmMessageBoxGetChild(msg_box, XmDIALOG_CANCEL_BUTTON)); XtAddCallback(msg_box, XmNokCallback, (XtCallbackProc)response, &answer); XtVaSetValues(XtParent(msg_box), XtNtitle, "Notice", NULL); } /* create message string */ xms = XmStringCreateLtoR(msg, XmFONTLIST_DEFAULT_TAG); XtVaSetValues(msg_box, XmNmessageString, xms, NULL); XmStringFree(xms); answer = 0; XtManageChild(msg_box); XtPopup(XtParent(msg_box), XtGrabNone); while(answer == 0) XtAppProcessEvent(context, XtIMAll); XtPopdown(XtParent(msg_box)); } /***** * Name: askSave * Return Type: void * Description: put up a message box asking user if he wants to save changes * to the file. * When changes should be saved, it also puts up a fileSB box, * saves the file and resets file_changed to False. * In: * nothing * Returns: * nothing. *****/ static void askSave(void) { if(!file_changed) return; if(file_changed) { char text[128]; sprintf(text, "%s has been modified.\nDo you wish to save it?", use_file); if(askUser(text)) fileCB(toplevel, FILE_SAVEAS); } /* just reset for now */ file_changed = False; setTitle(use_file); return; } /***** * Name: loadFile * Return Type: String * Description: loads the contents of the given file. * In: * filename: name of the file to load * mime_type: mimetype of file to load, updated upon return. * Returns: * File contents upon success, NULL on failure. *****/ static String loadFile(String filename) { FILE *file; int size; static String buffer; /* open the given file */ if((file = fopen(filename, "r")) == NULL) { perror(filename); return(False); } /* see how large this file is */ fseek(file, 0, SEEK_END); size = ftell(file); rewind(file); /* allocate a buffer large enough to contain the entire file */ if((buffer = malloc(size+1)) == NULL) { fprintf(stderr, "malloc failed for %i bytes\n", size); exit(EXIT_FAILURE); } /* now read the contents of this file */ if((fread(buffer, 1, size, file)) != size) printf("Warning: did not read entire file!\n"); buffer[size] = '\0'; /* sanity */ fclose(file); /* set current file */ if(use_file) free(use_file); use_file = strdup(filename); return(buffer); } /***** * Name: readFileCB * Return Type: void * Description: XmNokCallback handler for the fileSelectionDialog: retrieves * the entered filename and loads it. * In: * w: widget * dialog: widget id of the fileSelectionDialog * cbs: callback data * Returns: * nothing. *****/ static void readFileCB(Widget widget, Widget dialog, XmFileSelectionBoxCallbackStruct *cbs) { String filename; int item; /* remove the fileSelectionDialog */ XtPopdown(XtParent(dialog)); /* get the entered filename */ XmStringGetLtoR(cbs->value, XmSTRING_DEFAULT_CHARSET, &filename); /* sanity check */ if(!filename || !*filename) { if(filename) XtFree(filename); return; } /* get item data */ XtVaGetValues(dialog, XmNuserData, &item, NULL); if(item == FILE_OPEN) { String buf; /* ask to save changes (if any) */ askSave(); /* load the file */ if((buf = loadFile(filename)) != NULL) { /* set text in text widget */ XmTextSetString(text_w, buf); /* reset, TextSetString invokes XmText's modifyVerify callback. */ file_changed = False; setTitle(use_file); /* clear html widget contents */ XmHTMLTextSetString(html_w, NULL); /* reset parser */ XmHTMLParserSetString(parser, NULL); /* clear the labels as well */ docCB(NULL, NULL, NULL); /* and free loaded file */ free(buf); } XtFree(filename); } else if(item == FILE_SAVEAS || item == FILE_SAVETREE) { FILE *fp; String buffer; if(item == FILE_SAVEAS) buffer = XmTextGetString(text_w); else buffer = XmHTMLParserGetString(parser); if(buffer) { if((fp = fopen(filename, "w")) == NULL) perror(filename); else { fputs(buffer, fp); fputs("\n", fp); fclose(fp); } XtFree(buffer); } XtFree(filename); file_changed = False; setTitle(use_file); } } /***** * Name: fileCB * Return Type: void * Description: callback for the File menu. * In: * widget: widget id * item: id of selected menu item. * Returns: * nothing. *****/ static void fileCB(Widget widget, int item) { static Widget dialog; /* first ask if changes should be saved */ askSave(); /* three menu items: Open, Save and Quit */ if(item == FILE_QUIT) { /* Free images. It returns immediatly if the image argument is NULL */ XmImageDestroy(working_image); XmImageDestroy(ready_image); printf("Bye!\n"); exit(EXIT_SUCCESS); } if(item == FILE_NEW) { /* clear contents of the text widget */ XmTextSetString(text_w, NULL); /* clear contents of the html widget */ XmHTMLTextSetString(html_w, NULL); /* reset parser */ XmHTMLParserSetString(parser, NULL); /* and reset all visible flags from the previous document */ file_changed = False; free(use_file); use_file = strdup(""); docCB(NULL, NULL, NULL); return; } if(!dialog) { Arg args[1]; Widget menu = XtParent(widget); XmString xms; /* set the file selection pattern */ xms = XmStringCreateLocalized("*.html"); XtSetArg(args[0], XmNpattern, xms); /* create the dialog */ dialog = XmCreateFileSelectionDialog(menu, "fileOpen", args, 1); /* no longer needed, free it */ XmStringFree(xms); /* * register the dialog itself as callback data, so we can pop it down * when pressed on the OK button. */ XtAddCallback(dialog, XmNokCallback, (XtCallbackProc)readFileCB, dialog); XtAddCallback(dialog, XmNcancelCallback, (XtCallbackProc)XtUnmanageChild, NULL); } /* set appropriate dialog title */ if(item == FILE_SAVEAS) XtVaSetValues(XtParent(dialog), XmNtitle, "Save Document As", NULL); else if(item == FILE_SAVETREE) XtVaSetValues(XtParent(dialog), XmNtitle, "Save HTML Parser Tree", NULL); else XtVaSetValues(XtParent(dialog), XmNtitle, "Open a File", NULL); /* save item no as user data */ XtVaSetValues(dialog, XmNuserData, (XtPointer)item, NULL); XtManageChild(dialog); XtPopup(XtParent(dialog), XtGrabNone); XMapRaised(XtDisplay(dialog), XtWindow(XtParent(dialog))); } /***** * Name: htmlCB * Return Type: void * Description: callback for the HTML menu. * In: * widget: widget id * item: id of selected menu item. * Returns: * nothing. *****/ static void htmlCB(Widget widget, int item) { switch(item) { case HTML_VERIFY: parseHTML(); break; case HTML_PROGRESSIVE: parseProgressiveHTML(); break; case HTML_SAVE: fileCB(toplevel, FILE_SAVETREE); break; case HTML_PREVIEW: doPreview(True); break; default: fprintf(stderr, "htmlCB: impossible menu selection!\n"); } } /***** * Name: optionsCB * Return Type: void * Description: callback for the Options menu * In: * widget: widget id * item: selected menu item * Returns: * nothing *****/ static void optionsCB(Widget widget, int item, XmToggleButtonCallbackStruct *cbs) { switch(item) { case OPTIONS_SCROLL: scroll_text = cbs->set; break; case OPTIONS_AUTO: XmHTMLParserSetAutoMode(parser, !cbs->set); break; case OPTIONS_NOTIFY: honor_document_cb = cbs->set; break; } } /***** * Name: anchorCB * Return Type: void * Description: XmNactivateCallback for the XmHTML widget * In: * widget: widget id, in this case that of the HTML widget * data: data registered with callback, unused * cbs: XmHTML callback structure. * Returns: * nothing. *****/ static void anchorCB(Widget widget, XtPointer data, XmHTMLAnchorPtr cbs) { cbs->doit = True; cbs->visited = True; } /***** * Name: dismissCB * Return Type: void * Description: pops down the HTML previewer dialog * In: * widget: unused; * data: widget to pop down; * Returns: * nothing. *****/ static void dismissCB(Widget widget, XtPointer data) { XtUnmanageChild((Widget)data); } /***** * Name: addParserAliasTable * Return Type: int * Description: gets the selected alias from the given list widget and * adds an alias to the parser alias table. * In: * w: list widget * global_table: global parser table * nglobal: no of items in global parser table; * parser_table: current parser table; * nparser: no of items in parser table; * element: element to be aliased * Returns: * HTML_ALIAS when alias was successfully installed, HTML_REMOVE * otherwise. *****/ static int addAlias(Widget list, XmHTMLAliasTable global_table, int nglobal, XmHTMLAliasTable parser_table, int nparser, String element) { int *pos_list; /* selected list position */ int pos_cnt, selected; /* no of selected items */ htmlEnum alias; if(!(XmListGetSelectedPos(list, &pos_list, &pos_cnt))) { /* no items selected */ return(HTML_REMOVE); } /* * See if the selected item is part of the global alias or the current * parser alias table */ selected = pos_list[0]; /* list positions start at 1 instead of zero, so be sure to adjust */ selected--; if(selected < nglobal) alias = global_table[selected].alias; else { /* current parser alias table */ selected -= nglobal; alias = parser_table[selected].alias; } if(!(XmHTMLParserAddAlias(parser, element, alias))) { char text[128]; sprintf(text, "Could not add an alias for unknown element %s", element); tellUser(text); free(pos_list); return(HTML_REMOVE); } free(pos_list); return(HTML_ALIAS); } /***** * Name: parserAddAlias * Return Type: int * Description: brings up a selection dialog for adding an alias for an unknown * element. * In: * element: element for which to add an alias. * Returns: * HTML_ALIAS when an alias has been inserted, HTML_REMOVE otherwise. *****/ static int parserSelectAlias(String unknown) { static Widget msg_box, def_bttn; static int answer; int ret_val, i, j, nglobal, nparser; XmString xms, *table; char text[128]; XmHTMLAliasTable global_table, parser_table; if(msg_box == NULL) { XmString ok_label, cancel_label; Arg args[10]; int argc = 0; ok_label = XmStringCreateLocalized("OK"); cancel_label = XmStringCreateLocalized("Cancel"); XtSetArg(args[argc], XmNokLabelString, ok_label); argc++; XtSetArg(args[argc], XmNcancelLabelString, cancel_label); argc++; msg_box= XmCreateSelectionDialog(toplevel, "aliasUnknown", args, argc); XmStringFree(ok_label); XmStringFree(cancel_label); /* unmanage apply button */ XtUnmanageChild(XmSelectionBoxGetChild(msg_box, XmDIALOG_APPLY_BUTTON)); /* no need for the text area */ XtUnmanageChild(XmSelectionBoxGetChild(msg_box, XmDIALOG_TEXT)); /* and the selection label */ XtUnmanageChild(XmSelectionBoxGetChild(msg_box, XmDIALOG_SELECTION_LABEL)); def_bttn = XmSelectionBoxGetChild(msg_box, XmDIALOG_OK_BUTTON); XtVaSetValues(XtParent(msg_box), XtNtitle, "Select Element Alias", NULL); XtAddCallback(msg_box, XmNokCallback, (XtCallbackProc)response, &answer); XtAddCallback(msg_box, XmNcancelCallback, (XtCallbackProc)response, &answer); } /* clear current list contents */ XmListDeleteAllItems(XmSelectionBoxGetChild(msg_box, XmDIALOG_LIST)); /* get the global alias table */ global_table = XmHTMLGetGlobalAliasTable(&nglobal); /* get current parser alias table */ parser_table = XmHTMLParserGetAliasTable(parser, &nparser); /* create the XmString table for these aliases */ table = (XmString*)malloc((nglobal+nparser)*sizeof(XmString)); /* add all strings from the global table */ for(i = 0, j = 0; i < nglobal; i++, j++) table[j] = XmStringCreateLocalized(global_table[i].element); /* add all strings from the current parser table */ for(i = 0; i < nparser; i++, j++) table[j] = XmStringCreateLocalized(parser_table[i].element); /* create list label string */ sprintf(text, "Select an alias for %s", unknown); xms = XmStringCreateLocalized(text); /* set everything in one go */ XtVaSetValues(msg_box, XmNlistLabelString, xms, XmNdefaultButton, def_bttn, XmNlistItems, table, XmNlistItemCount, nglobal+nparser, XmNlistVisibleItemCount, 15, NULL); /* and free all strings */ XmStringFree(xms); for(i = 0; i < nparser + nglobal; i++) XmStringFree(table[i]); free(table); /* disable input mode */ XmTextSetEditable(text_w, False); answer = 0; XtManageChild(msg_box); XtPopup(XtParent(msg_box), XtGrabNone); while(answer == 0) XtAppProcessEvent(context, XtIMAll); XtPopdown(XtParent(msg_box)); /* convert pushed button to a valid action code */ switch(answer) { case OK_BUTTON: /* * an alias has been selected, figure out which one it was and * add it. */ ret_val = addAlias(XmSelectionBoxGetChild(msg_box, XmDIALOG_LIST), global_table, nglobal, parser_table, nparser, unknown); break; case CANCEL_BUTTON: default: ret_val = HTML_REMOVE; break; } /* free global alias table */ XmHTMLParserDestroyAliasTable(global_table, nglobal); /* free parser alias table */ XmHTMLParserDestroyAliasTable(parser_table, nparser); /* enable input mode */ XmTextSetEditable(text_w, True); return(ret_val); } /***** * Name: parserUnknownHTML * Return Type: int * Description: handles HTML_UNKNOWN_ELEMENT parser error * In: * cbs: current parserCallbackStruct * Returns: * selected action *****/ static int parserUnknownHTML(XmHTMLParserPtr cbs) { static Widget msg_box, def_bttn; static int answer; int ret_val, len; XmString xms; char msg[1024], tmp[128]; selectText(cbs->start_pos, cbs->end_pos); if(msg_box == NULL) { XmString ok_label, help_label, cancel_label; Arg args[10]; int argc = 0; ok_label = XmStringCreateLocalized("Remove"); cancel_label = XmStringCreateLocalized("Add Alias..."); help_label = XmStringCreateLocalized("Terminate"); XtSetArg(args[argc], XmNokLabelString, ok_label); argc++; XtSetArg(args[argc], XmNcancelLabelString, cancel_label); argc++; XtSetArg(args[argc], XmNhelpLabelString, help_label); argc++; msg_box= XmCreatePromptDialog(toplevel, "parserUnknown", args, argc); XmStringFree(ok_label); XmStringFree(cancel_label); XmStringFree(help_label); /* unmanage apply button */ XtUnmanageChild(XmSelectionBoxGetChild(msg_box, XmDIALOG_APPLY_BUTTON)); XtUnmanageChild(XmSelectionBoxGetChild(msg_box, XmDIALOG_TEXT)); def_bttn = XmSelectionBoxGetChild(msg_box, XmDIALOG_OK_BUTTON); XtVaSetValues(XtParent(msg_box), XtNtitle, "Unknown Element", NULL); XtAddCallback(msg_box, XmNokCallback, (XtCallbackProc)response, &answer); XtAddCallback(msg_box, XmNcancelCallback, (XtCallbackProc)response, &answer); XtAddCallback(msg_box, XmNhelpCallback, (XtCallbackProc)response, &answer); } len = cbs->offender->len > 127 ? 127 : cbs->offender->len; strncpy(tmp, cbs->offender->ptr, len); tmp[len] = '\0'; sprintf(msg, "%s: unknown HTML identifier.", tmp); /* create message string */ xms = XmStringCreateLocalized(msg); XtVaSetValues(msg_box, XmNselectionLabelString, xms, XmNdefaultButton, def_bttn, NULL); XmStringFree(xms); /* disable input mode */ XmTextSetEditable(text_w, False); answer = 0; XtManageChild(msg_box); XtPopup(XtParent(msg_box), XtGrabNone); while(answer == 0) XtAppProcessEvent(context, XtIMAll); XtPopdown(XtParent(msg_box)); /* convert pushed button to a valid action code */ switch(answer) { case HELP_BUTTON: ret_val = HTML_TERMINATE; break; case CANCEL_BUTTON: ret_val = parserSelectAlias(cbs->offender->ptr); break; case OK_BUTTON: default: ret_val = HTML_REMOVE; } /* enable input mode */ XmTextSetEditable(text_w, True); return(ret_val); } /***** * Name: parserBadHTML * Return Type: int * Description: handles HTML_BAD and HTML_VIOLATION parser errors * In: * cbs: current parserCallbackStruct * Returns: * selected action *****/ static int parserBadHTML(XmHTMLParserPtr cbs) { static Widget msg_box, def_bttn; static int answer; int ret_val, ok_val, cancel_val; XmString xms, ok_label, cancel_label; char msg[1024]; selectText(cbs->start_pos, cbs->end_pos); if(msg_box == NULL) { XmString help_label; Arg args[10]; int argc = 0; help_label = XmStringCreateLocalized("Terminate"); XtSetArg(args[argc], XmNhelpLabelString, help_label); argc++; msg_box= XmCreatePromptDialog(toplevel, "parserBadHTML", args, argc); XmStringFree(help_label); XtUnmanageChild(XmSelectionBoxGetChild(msg_box, XmDIALOG_TEXT)); def_bttn = XmSelectionBoxGetChild(msg_box, XmDIALOG_OK_BUTTON); XtVaSetValues(XtParent(msg_box), XtNtitle, "HTML Violation", NULL); XtAddCallback(msg_box, XmNokCallback, (XtCallbackProc)response, &answer); XtAddCallback(msg_box, XmNcancelCallback, (XtCallbackProc)response, &answer); XtAddCallback(msg_box, XmNhelpCallback, (XtCallbackProc)response, &answer); XtAddCallback(msg_box, XmNapplyCallback, (XtCallbackProc)response, &answer); } if(cbs->error == HTML_BAD) { ok_label = XmStringCreateLocalized("Remove"); cancel_label = XmStringCreateLocalized("Ignore"); ok_val = HTML_REMOVE; cancel_val = HTML_IGNORE; sprintf(msg, "Terrible HTML! element %s completely out of balance!", cbs->offender->ptr); } /* * cbs->error == HTML_VIOLATION * default action depends on current state of the XmNstrictHTMLChecking * resource and is provided as the default action in the callback * structure. */ else { /* XmNstrictHTMLChecking == True */ if(cbs->action == HTML_REMOVE) { ok_label = XmStringCreateLocalized("Remove"); cancel_label = XmStringCreateLocalized("Keep"); ok_val = HTML_REMOVE; cancel_val = HTML_KEEP; } else { ok_label = XmStringCreateLocalized("Keep"); cancel_label = XmStringCreateLocalized("Remove"); ok_val = HTML_KEEP; cancel_val = HTML_REMOVE; } sprintf(msg, "HTML 3.2 violation: %s may not occur inside %s", cbs->offender->ptr, cbs->current->ptr); } /* the parser suggested an element which could repair this violation */ if(cbs->repair->len) { char text[128]; XmString apply_label; sprintf(text, "Insert %s", cbs->repair->ptr); apply_label = XmStringCreateLocalized(text); XtManageChild(XmSelectionBoxGetChild(msg_box, XmDIALOG_APPLY_BUTTON)); XtVaSetValues(msg_box, XmNapplyLabelString, apply_label, NULL); XmStringFree(apply_label); } else XtUnmanageChild(XmSelectionBoxGetChild(msg_box, XmDIALOG_APPLY_BUTTON)); xms = XmStringCreateLocalized(msg); XtVaSetValues(msg_box, XmNokLabelString, ok_label, XmNcancelLabelString, cancel_label, XmNselectionLabelString, xms, XmNdefaultButton, def_bttn, NULL); XmStringFree(ok_label); XmStringFree(cancel_label); XmStringFree(xms); /* disable input mode */ XmTextSetEditable(text_w, False); answer = 0; XtManageChild(msg_box); XtPopup(XtParent(msg_box), XtGrabNone); while(answer == 0) XtAppProcessEvent(context, XtIMAll); XtPopdown(XtParent(msg_box)); /* convert pushed button to a valid action code */ switch(answer) { case HELP_BUTTON: ret_val = HTML_TERMINATE; break; case CANCEL_BUTTON: ret_val = cancel_val; break; case APPLY_BUTTON: ret_val = HTML_INSERT; break; case OK_BUTTON: default: ret_val = ok_val; } /* enable input mode */ XmTextSetEditable(text_w, True); return(ret_val); } /***** * Name: parserBlock * Return Type: int * Description: handles HTML_OPEN_BLOCK and HTML_CLOSE_BLOCK parser errors * In: * cbs: current parserCallbackStruct * Returns: * selected action *****/ static int parserBlock(XmHTMLParserPtr cbs) { static Widget msg_box, def_bttn; static int answer; int ret_val, ok_val, apply_val; XmString xms, ok_label, apply_label; char msg[1024]; selectText(cbs->start_pos, cbs->end_pos); if(msg_box == NULL) { XmString cancel_label, help_label; Arg args[10]; int argc = 0; cancel_label = XmStringCreateLocalized("Keep"); help_label = XmStringCreateLocalized("Terminate"); XtSetArg(args[argc], XmNhelpLabelString, help_label); argc++; XtSetArg(args[argc], XmNcancelLabelString, cancel_label); argc++; msg_box= XmCreatePromptDialog(toplevel, "parserBlock", args, argc); XmStringFree(cancel_label); XmStringFree(help_label); /* manage apply button */ XtManageChild(XmSelectionBoxGetChild(msg_box, XmDIALOG_APPLY_BUTTON)); /* unmanage text area */ XtUnmanageChild(XmSelectionBoxGetChild(msg_box, XmDIALOG_TEXT)); def_bttn = XmSelectionBoxGetChild(msg_box, XmDIALOG_OK_BUTTON); XtVaSetValues(XtParent(msg_box), XtNtitle, "Invalid Block Element", NULL); XtAddCallback(msg_box, XmNokCallback, (XtCallbackProc)response, &answer); XtAddCallback(msg_box, XmNapplyCallback, (XtCallbackProc)response, &answer); XtAddCallback(msg_box, XmNcancelCallback, (XtCallbackProc)response, &answer); XtAddCallback(msg_box, XmNhelpCallback, (XtCallbackProc)response, &answer); } if(cbs->error == HTML_OPEN_BLOCK) { char text[128]; sprintf(text, "Insert %s", cbs->repair->ptr); ok_label = XmStringCreateLocalized(text); sprintf(text, "Remove %s", cbs->offender->ptr); apply_label = XmStringCreateLocalized(text); ok_val = HTML_INSERT; apply_val = HTML_REMOVE; sprintf(msg, "A new block level element (%s) was encountered while %s " "is still open.", cbs->offender->ptr, cbs->current->ptr); } else { char text[128]; sprintf(text, "Remove %s", cbs->offender->ptr); ok_label = XmStringCreateLocalized(text); sprintf(text, "Insert %s", cbs->repair->ptr); apply_label = XmStringCreateLocalized(text); ok_val = HTML_REMOVE; apply_val = HTML_INSERT; sprintf(msg, "A closing element (%s) was encountered while it was " "never opened.", cbs->offender->ptr); } xms = XmStringCreateLocalized(msg); XtVaSetValues(msg_box, XmNokLabelString, ok_label, XmNapplyLabelString, apply_label, XmNselectionLabelString, xms, XmNdefaultButton, def_bttn, NULL); XmStringFree(ok_label); XmStringFree(apply_label); XmStringFree(xms); /* disable input mode */ XmTextSetEditable(text_w, False); answer = 0; XtManageChild(msg_box); XtPopup(XtParent(msg_box), XtGrabNone); while(answer == 0) XtAppProcessEvent(context, XtIMAll); XtPopdown(XtParent(msg_box)); switch(answer) { case HELP_BUTTON: ret_val = HTML_TERMINATE; break; case APPLY_BUTTON: ret_val = apply_val; break; case CANCEL_BUTTON: ret_val = HTML_KEEP; case OK_BUTTON: default: ret_val = ok_val; } /* enable input mode */ XmTextSetEditable(text_w, True); return(ret_val); } /***** * Name: parserNestedElement * Return Type: int * Description: handles HTML_NESTED parser errors * In: * cbs: current parserCallbackStruct * Returns: * selected action *****/ static int parserNestedElement(XmHTMLParserPtr cbs) { static Widget msg_box, def_bttn; static int answer; int ret_val; XmString xms; char msg[1024]; selectText(cbs->start_pos, cbs->end_pos); if(msg_box == NULL) { XmString ok_label, apply_label, cancel_label, help_label; Arg args[10]; int argc = 0; ok_label = XmStringCreateLocalized("Ignore"); apply_label = XmStringCreateLocalized("Remove"); cancel_label = XmStringCreateLocalized("Keep"); help_label = XmStringCreateLocalized("Terminate"); XtSetArg(args[argc], XmNokLabelString, ok_label); argc++; XtSetArg(args[argc], XmNapplyLabelString, apply_label); argc++; XtSetArg(args[argc], XmNhelpLabelString, help_label); argc++; XtSetArg(args[argc], XmNcancelLabelString, cancel_label); argc++; msg_box= XmCreatePromptDialog(toplevel, "parserNested", args, argc); XmStringFree(ok_label); XmStringFree(apply_label); XmStringFree(cancel_label); XmStringFree(help_label); /* manage apply button */ XtManageChild(XmSelectionBoxGetChild(msg_box, XmDIALOG_APPLY_BUTTON)); /* unmanage text area */ XtUnmanageChild(XmSelectionBoxGetChild(msg_box, XmDIALOG_TEXT)); def_bttn = XmSelectionBoxGetChild(msg_box, XmDIALOG_OK_BUTTON); XtVaSetValues(XtParent(msg_box), XtNtitle, "Improperly Nested Element", NULL); XtAddCallback(msg_box, XmNokCallback, (XtCallbackProc)response, &answer); XtAddCallback(msg_box, XmNapplyCallback, (XtCallbackProc)response, &answer); XtAddCallback(msg_box, XmNcancelCallback, (XtCallbackProc)response, &answer); XtAddCallback(msg_box, XmNhelpCallback, (XtCallbackProc)response, &answer); } /* current is same as offender */ sprintf(msg, "%s may not be nested", cbs->current->ptr); xms = XmStringCreateLocalized(msg); XtVaSetValues(msg_box, XmNselectionLabelString, xms, NULL); XmStringFree(xms); /* disable input mode */ XmTextSetEditable(text_w, False); answer = 0; XtManageChild(msg_box); XtPopup(XtParent(msg_box), XtGrabNone); while(answer == 0) XtAppProcessEvent(context, XtIMAll); XtPopdown(XtParent(msg_box)); switch(answer) { case HELP_BUTTON: ret_val = HTML_TERMINATE; break; case APPLY_BUTTON: ret_val = HTML_REMOVE; break; case CANCEL_BUTTON: ret_val = HTML_KEEP; case OK_BUTTON: default: ret_val = HTML_IGNORE; } /* enable input mode */ XmTextSetEditable(text_w, True); return(ret_val); } /***** * Name: parserOpenElement * Return Type: int * Description: handles HTML_OPEN_ELEMENT parser error * In: * cbs: current parserCallbackStruct * Returns: * selected action *****/ static int parserOpenElement(XmHTMLParserPtr cbs) { static Widget msg_box, def_bttn; static int answer; int ret_val; XmString xms, ok_label, cancel_label; char text[128]; char msg[1024]; selectText(cbs->start_pos, cbs->end_pos); if(msg_box == NULL) { XmString help_label; Arg args[10]; int argc = 0; help_label = XmStringCreateLocalized("Terminate"); XtSetArg(args[argc], XmNhelpLabelString, help_label); argc++; msg_box= XmCreatePromptDialog(toplevel, "parserOpenElement", args, argc); XmStringFree(help_label); /* unmanage text area */ XtUnmanageChild(XmSelectionBoxGetChild(msg_box, XmDIALOG_TEXT)); def_bttn = XmSelectionBoxGetChild(msg_box, XmDIALOG_OK_BUTTON); XtVaSetValues(XtParent(msg_box), XtNtitle, "Unbalanced Element", NULL); XtAddCallback(msg_box, XmNokCallback, (XtCallbackProc)response, &answer); XtAddCallback(msg_box, XmNcancelCallback, (XtCallbackProc)response, &answer); XtAddCallback(msg_box, XmNhelpCallback, (XtCallbackProc)response, &answer); } /* create message string */ sprintf(msg, "Unbalanced Terminator: %s where %s is required", cbs->offender->ptr, cbs->current->ptr); xms = XmStringCreateLocalized(msg); sprintf(text, "Remove %s", cbs->offender->ptr); ok_label = XmStringCreateLocalized(text); sprintf(text, "Switch %s and %s", cbs->offender->ptr, cbs->repair->ptr); cancel_label = XmStringCreateLocalized(text); XtVaSetValues(msg_box, XmNselectionLabelString, xms, XmNokLabelString, ok_label, XmNcancelLabelString, cancel_label, XmNdefaultButton, def_bttn, NULL); XmStringFree(xms); XmStringFree(ok_label); XmStringFree(cancel_label); /* disable input mode */ XmTextSetEditable(text_w, False); answer = 0; XtManageChild(msg_box); XtPopup(XtParent(msg_box), XtGrabNone); while(answer == 0) XtAppProcessEvent(context, XtIMAll); XtPopdown(XtParent(msg_box)); switch(answer) { case HELP_BUTTON: ret_val = HTML_TERMINATE; break; case CANCEL_BUTTON: ret_val = HTML_SWITCH; break; case OK_BUTTON: default: ret_val = HTML_REMOVE; } /* enable input mode */ XmTextSetEditable(text_w, True); return(ret_val); } /***** * Name: parserFatal * Return Type: int * Description: handles HTML_INTERNAL parser error * In: * cbs: current parserCallbackStruct * Returns: * selected action *****/ static int parserFatal(XmHTMLParserPtr cbs) { static Widget msg_box, def_bttn; static int answer; XmString xms; if(msg_box == NULL) { XmString ok_label, cancel_label; Arg args[10]; int argc = 0; ok_label = XmStringCreateLocalized("Terminate"); cancel_label = XmStringCreateLocalized("Ignore"); XtSetArg(args[argc], XmNokLabelString, ok_label); argc++; XtSetArg(args[argc], XmNcancelLabelString, cancel_label); argc++; msg_box= XmCreatePromptDialog(toplevel, "parserUnbalanced", args, argc); XmStringFree(ok_label); XmStringFree(cancel_label); /* unmanage help button */ XtUnmanageChild(XmSelectionBoxGetChild(msg_box, XmDIALOG_HELP_BUTTON)); /* unmanage text area */ XtUnmanageChild(XmSelectionBoxGetChild(msg_box, XmDIALOG_TEXT)); def_bttn = XmSelectionBoxGetChild(msg_box, XmDIALOG_OK_BUTTON); XtVaSetValues(XtParent(msg_box), XtNtitle, "Fatal Parser Error", NULL); XtAddCallback(msg_box, XmNokCallback, (XtCallbackProc)response, &answer); XtAddCallback(msg_box, XmNcancelCallback, (XtCallbackProc)response, &answer); } /* create message string */ xms = XmStringCreateLocalized("Internal Parser Error!"); XtVaSetValues(msg_box, XmNselectionLabelString, xms, XmNdefaultButton, def_bttn, NULL); XmStringFree(xms); /* disable input mode */ XmTextSetEditable(text_w, False); answer = 0; XtManageChild(msg_box); XtPopup(XtParent(msg_box), XtGrabNone); while(answer == 0) XtAppProcessEvent(context, XtIMAll); XtPopdown(XtParent(msg_box)); /* enable input mode */ XmTextSetEditable(text_w, True); return((answer == OK_BUTTON ? HTML_TERMINATE : HTML_IGNORE)); } /***** * Name: parserCB * Return Type: void * Description: the entire reason for the existance of this example. * Demonstrates a possible handling of the XmNparserCallback * resoure. * In: * widget: owner of this callback * data: client_data, unused * cbs: call_data, parsercallback structure. * Returns: * nothing. *****/ static void parserCB(Widget widget, XtPointer data, XmHTMLParserPtr cbs) { int action; /* * There is also a HTML_NOTIFY error. This is not an error but just * a notification that XmHTML is inserting a missing closing element * on elements that have an optional terminator. These elements are: *
,
,
  • ,

    ,