home *** CD-ROM | disk | FTP | other *** search
/ WordPerfect for Linux Bible / WP4LinuxBible.iso / sdk / wpx / code / wt / server / wtserver.c < prev    next >
Encoding:
C/C++ Source or Header  |  1999-06-25  |  54.3 KB  |  1,968 lines

  1. /* SOURCE FILE *****************************************************
  2.  * WTSERVER.C  -  Writing Tools API Server Sample Application
  3.  *                This is a sample writing tool which translates
  4.  *                to and from pig latin.
  5.  *******************************************************************
  6.  *  Copyright (C) 1993 WordPerfect Corp., All Rights Reserved
  7.  *******************************************************************/
  8.  
  9. #include "wtserver.h" 
  10. #include "wtserver.xbm"     /* icon bitmap */
  11.  
  12. #include <X11/cursorfont.h>
  13. #include <Xm/Xm.h>
  14. #include <Xm/CascadeB.h>
  15. #include <Xm/CutPaste.h>
  16. #include <Xm/Form.h>
  17. #include <Xm/Label.h>
  18. #include <Xm/List.h>
  19. #include <Xm/MessageB.h>
  20. #include <Xm/Protocols.h>
  21. #include <Xm/PushB.h>
  22. #include <Xm/RowColumn.h>
  23. #include <Xm/Separator.h>
  24. #include <Xm/Text.h>
  25. #include <Xm/ToggleB.h>
  26.  
  27. #include <unistd.h>
  28. #include <wtcomm.h>
  29.  
  30.  
  31. /*----------------------------------------------------------
  32.         External Functions
  33. ------------------------------------------------------------*/
  34. extern void TermSession();
  35. extern WTCOMM WTInitComm(Widget, char *, int, int);
  36. extern void WTCloseComm(WTCOMM);
  37.  
  38. /*----------------------------------------------------------
  39.         External Variables
  40. ------------------------------------------------------------*/
  41.  
  42. /*----------------------------------------------------------
  43.         Menu Definitions
  44. ------------------------------------------------------------*/
  45. /* Translate menu items */
  46. static char *TlTransStr[] = {
  47.     "Native to Pig Latin", "Pig Latin to Native",
  48.     "Word", "Document", "To End of Document", "Selection", 0
  49. };
  50. static char TlTransMne[] = {
  51.     'P', 'N', 'W', 'D', 'E', 'S', 0
  52. };
  53.  
  54. /* Edit menu items */
  55. static char *TlEditStr[] = {
  56.     "Undo", "Cut", "Copy", "Paste", 0
  57. };
  58. static char TlEditMne[] = {
  59.     'U', 't', 'C', 'P', 0
  60. };
  61.  
  62. /* Help menu items */
  63. static char *TlHelpStr[] = {
  64.     "About WTServer...", 0
  65. };
  66. static char TlHelpMne[] = {
  67.     'A', 0
  68. };
  69.  
  70. /* Push buttons */
  71. static char *TlButtons[] = {
  72.     "Start", "Skip", "ReTranslate", "Translate All", "Close", 0
  73. };
  74.  
  75. /*----------------------------------------------------------
  76.         Internal Variables
  77. ------------------------------------------------------------*/
  78. BOOL inAPI = FALSE;                    /* in a WT Session? */
  79. TL_TRANS CurSel = TL_TRANS_DOC;        /* Default in API is translate Doc */
  80. BOOL inBlock = FALSE;                /* is the client in a selected block? */
  81. WTCOMM comm_id;                        /* conversation handle */
  82. WTBUF sndbuf[BUFSIZE];                /* buffer for outgoing messages */
  83. WTBUF rcvbuf[BUFSIZE];                /* buffer for return messages */
  84. WTBUF winbuf[BUFSIZE];                /* buffer for client window name */
  85. Widget Server;
  86. static XmFontList FontList;
  87. static Cursor waitcursor = (Cursor) 0;
  88. static Cursor normalcursor = (Cursor) 0;
  89. static Pixmap Icon;            /* Icon for sample server application */
  90. static Widget Text;            /* Text widget for server (for Edit) */
  91. static Widget TransMode;    /* Label for translation mode */
  92. static Widget TransScope;    /* Label for translation scope */
  93. static Widget Word;            /* Text box for Word */
  94. static Widget Translation;    /* Text box for Translation */
  95. static Widget editButtons[TL_EDIT_CNT];        /* Edit menu buttons */
  96. static Widget transButtons[TL_TRANS_CNT];    /* Translate menu buttons */
  97. static Widget Buttons[TL_BUT_CNT];            /* Push buttons */
  98. static Widget TransOpts;    /* Translation options dialog */
  99. static Widget TransList;    /* List of possible translations */
  100. static char *prevText;                        /* text before previous edit */
  101. static XmTextPosition    prevSelLeft = 0xff,    /* previous selection */
  102.                         prevSelRight = 0;
  103. static Widget msgDialog;
  104. static BOOL MsgBoxRet = FALSE;
  105. static TL_TRANS Mode = TL_TRANS_NATPIG;        /* Translation mode */
  106. static BOOL inLoop = FALSE;            /* has the user decided what to check? */ 
  107.  
  108. static WTBUF txtbuf[TEXTSIZE+WORDSIZE];    /* buffer for client text */
  109. static int txtsize;                        /* total size of the text in the buffer */
  110. static int txtbeg;                        /* offset of the current word */
  111. static int txtend;                        /* end offset of the word */
  112. static WTENDBLOCK endflag;                /* reason for end of last text block */
  113. static char gbuf[BUFSIZE];                /* global buffer */
  114.  
  115. /*----------------------------------------------------------
  116.         Internal Functions
  117. ------------------------------------------------------------*/
  118. XmString StringCreate(char *);
  119. char *XmStringToString(XmString str);
  120. void NormalCursor(Widget);
  121. void WaitCursor(Widget);
  122. void SetDialogState();
  123. void quitTool(char *);
  124. BOOL MsgBox(MSGBOX, Widget, char *, char *);
  125. static void ServerInit(Widget);
  126. static void ServerDestroyCB(Widget, XtPointer, XtPointer);
  127. static void ServerExit();
  128. static void TransCB(Widget, XtPointer, XtPointer);
  129. static void EditCB(Widget, XtPointer, XmAnyCallbackStruct *);
  130. static void SetEditButtons(Widget, XtPointer, XtPointer);
  131. static void HelpCB(Widget, XtPointer, XtPointer);
  132. static void ButtonCB(Widget, XtPointer, XtPointer);
  133. static void free_cursors(Widget);
  134. static void change_cursors(Widget, Cursor);
  135. static void MsgBoxCB(Widget, XtPointer, XtPointer);
  136. static void SetTranslateText();
  137. static void TextFocusCB(Widget, XtPointer, XtPointer);
  138. static BOOL NatToPig(char *, char *);
  139. static BOOL PigToNat(char *, char *);
  140. static void InitText(void);
  141. static void SetButtons();
  142. static void DeHilite();
  143. static BOOL NextWord(char *);
  144. static void NextBlock(int);
  145. static void PutWords(char *, char *);
  146. static void XLateAll(char *, char *);
  147. static void ReplaceWord(char *);
  148. static void PromptTranslateOptions(char *);
  149. static void TransOptCB(Widget, XtPointer, XtPointer);
  150. static BOOL isvowel(char);
  151.  
  152. /*COMMENT***************************************************
  153. ;main
  154. Title:    WTAPI Sample Server Main Function
  155. In:        argc, argv
  156. Out:    none
  157. Xin:    none
  158. Xout:    none
  159. Return:    exit status
  160. Notes:
  161. ***********************************************************/
  162. main(int argc, char *argv[])
  163. {
  164.     XtAppContext appcontext;
  165.     Widget toplevel;
  166.     int read_fd, write_fd;    /* pipe read/write file descriptors */
  167.     String app_class;        /* parent's application class */
  168.     int arg;
  169.  
  170. #ifdef DEBUG    
  171.     /*
  172.      * Wait when invoked to give time to attach debugger.
  173.      * Loop until file "/tmp/debugloop" no longer exists or until
  174.      * the loop is exited using the debugger.
  175.      */
  176.     while (access("/tmp/debugloop", F_OK) == 0) {
  177.         sleep(10);
  178.     }
  179. #endif /* DEBUG */
  180.     /*
  181.      * We need to check for -wtapi and the application class
  182.      * (-appClass) in the command-line arguments.
  183.      */
  184.     app_class = "WTServer";        /* default */
  185.     read_fd = write_fd = -1;    /* defaults */
  186.     for (arg = 0; arg < argc; arg++) {
  187.         if (strcmp(argv[arg], "-wtapi") == 0) {
  188.             inAPI = TRUE;
  189.             if ((arg + 2) < argc) {
  190.                 read_fd = atoi(argv[arg+1]);
  191.                 write_fd = atoi(argv[arg+2]);
  192.             }
  193.             arg += 2;
  194.         }
  195.         if ((strcmp(argv[arg], "-appClass") == 0) && ((arg + 1) < argc)) {
  196.             app_class = argv[arg+1];
  197.             arg++;
  198.         }
  199.     }
  200.     toplevel = XtVaAppInitialize(&appcontext, app_class,
  201.         NULL, 0, &argc, (char **)argv, NULL,
  202.         XmNallowShellResize, True,
  203.         NULL);
  204.     Server = toplevel;
  205.     if (inAPI) {
  206.         comm_id = WTInitComm(toplevel, argv[0], read_fd, write_fd);
  207.         if (!comm_id) {
  208.             MsgBox(MB_OK, Server, "WTServer Error",
  209.                 "Unable to Establish Writing Tools API Communication!");
  210.             inAPI = FALSE;
  211.         }
  212.     }
  213.     ServerInit(toplevel);
  214.     XtAppMainLoop(appcontext);
  215. } /* main */
  216.  
  217. /*COMMENT***************************************************
  218. ;ServerInit
  219. Title:    Initialize WTAPI Sample Server Application
  220. In:        toplevel - toplevel widget of application
  221. Out:    none
  222. Xin:    none
  223. Xout:    none
  224. Return:    none
  225. Notes:
  226. ***********************************************************/
  227. static void ServerInit(Widget toplevel)
  228. {
  229.     Atom deleteWindow;        /* for XmAddWMProtocol... */
  230.     XmString xmstr;            /* Motif compound string */
  231.     Widget    form,            /* main Server form */
  232.             menubar,        /* menu bar */
  233.             button,            /* cascade or push button */
  234.             label, label2,    /* labels */
  235.             pd,                /* pulldown menu */
  236.             rowcol,            /* rowcolumn */
  237.             separator;        /* separator */
  238.     TL_TRANS trans;            /* loop variable */
  239.     TL_EDIT edit;            /* loop variable */
  240.     TL_HELP help;            /* loop variable */
  241.     TL_BUT but;                /* loop variable */
  242.     XFontStruct *font;
  243.     char *str;
  244.  
  245.     /*
  246.      * Set up icon and dialog destroy callbacks for main Server window.
  247.      */
  248.     Server = toplevel;
  249.     Icon = XCreateBitmapFromData(XtDisplay(toplevel),
  250.         RootWindowOfScreen(XtScreen(toplevel)),
  251.         wtserver_bits, wtserver_width, wtserver_height);
  252.     XtVaSetValues(Server,
  253.         XtNtitle, "WTAPI Sample Server Application",
  254.         XmNiconName, "WTServer",
  255.         XmNiconPixmap, Icon,
  256.         XmNdeleteResponse, XmDO_NOTHING,
  257.         NULL);
  258.     XtAddCallback(Server, XmNdestroyCallback, ServerDestroyCB, 0);
  259.     deleteWindow = XmInternAtom(XtDisplay(Server), "WM_DELETE_WINDOW", False);
  260.     XmAddWMProtocols(Server, &deleteWindow, 1);
  261.     XmAddWMProtocolCallback(Server, deleteWindow, ServerDestroyCB, 0);
  262.     /*
  263.      * Create the main Server form.
  264.      */
  265.     FontList = NULL;
  266.     if (font = XLoadQueryFont(XtDisplay(Server),
  267.         "-adobe-helvetica-medium-r-normal--14-100-100-100-p-76-iso8859-1"))
  268.     {
  269.         FontList = XmFontListCreate(font, XmSTRING_DEFAULT_CHARSET);
  270.     }
  271.     form = XtVaCreateManagedWidget("tlform", xmFormWidgetClass, Server,
  272.         XmNfontList, FontList,
  273.         NULL);
  274.     /*
  275.      * Create the menu bar.
  276.      */
  277.     menubar = XmCreateMenuBar(form, "tlmenu", 0, 0);
  278.     /*
  279.      * Create the Translate menu.
  280.      */
  281.     button = XtVaCreateManagedWidget("tltranslate",
  282.         xmCascadeButtonWidgetClass, menubar,
  283.         XmNlabelString, xmstr = StringCreate("Translate"),
  284.         XmNmnemonic, 'T',
  285.         XmNsubMenuId, pd = XmCreatePulldownMenu(menubar, "tlTransPD", 0, 0),
  286.         XmNfontList, FontList,
  287.         NULL);
  288.     XmStringFree(xmstr);
  289.     if (!inAPI) {
  290.         CurSel = TL_TRANS_WORD;
  291.     } else {
  292.         CurSel = TL_TRANS_DOC;
  293.     }
  294.     for (trans = TL_TRANS_NATPIG; trans < TL_TRANS_CNT; trans++) {
  295.         if (trans == TL_TRANS_WORD) {
  296.             separator = XtVaCreateManagedWidget("sep",
  297.                 xmSeparatorWidgetClass, pd,
  298.                 NULL);
  299.         }
  300.         transButtons[trans] =
  301.         button = XtVaCreateManagedWidget(TlTransStr[trans],
  302.             xmToggleButtonWidgetClass, pd,
  303.             XmNlabelString, xmstr = StringCreate(TlTransStr[trans]),
  304.             XmNmnemonic, TlTransMne[trans],
  305.             XmNindicatorType, XmONE_OF_MANY,
  306.             XmNvisibleWhenOff, True,
  307.             XmNsensitive, True,
  308.             XmNfontList, FontList,
  309.             NULL);
  310.         if ((trans == Mode) || (trans == CurSel)) {
  311.             XtVaSetValues(button, XmNset, True, NULL);
  312.         }
  313.         XmStringFree(xmstr);
  314.         XtAddCallback(button, XmNvalueChangedCallback, TransCB, (XtPointer)(int)trans);
  315.     }
  316.     /*
  317.      * Create the Edit menu.
  318.      */
  319.     button = XtVaCreateManagedWidget("tledit",
  320.         xmCascadeButtonWidgetClass, menubar,
  321.         XmNlabelString, xmstr = StringCreate("Edit"),
  322.         XmNmnemonic, 'E',
  323.         XmNsubMenuId, pd = XmCreatePulldownMenu(menubar, "tlEditPD", 0, 0),
  324.         XmNfontList, FontList,
  325.         NULL);
  326.     XmStringFree(xmstr);
  327.     XtAddCallback(button, XmNcascadingCallback, SetEditButtons, 0);
  328.     for (edit = TL_EDIT_UNDO; edit < TL_EDIT_CNT; edit++) {
  329.         editButtons[edit] = button = XtVaCreateManagedWidget(TlEditStr[edit],
  330.             xmPushButtonWidgetClass, pd,
  331.             XmNlabelString, xmstr = StringCreate(TlEditStr[edit]),
  332.             XmNmnemonic, TlEditMne[edit],
  333.             XmNvisibleWhenOff, True,
  334.             XmNsensitive, True,
  335.             XmNfontList, FontList,
  336.             NULL);
  337.         XmStringFree(xmstr);
  338.         XtAddCallback(button, XmNactivateCallback, (XtCallbackProc)EditCB, (XtPointer)(int)edit);
  339.         if (edit == TL_EDIT_UNDO) {
  340.             separator = XtVaCreateManagedWidget("sep",
  341.                 xmSeparatorWidgetClass, pd,
  342.                 NULL);
  343.         }
  344.     }
  345.     /*
  346.      * Create the Help menu.
  347.      */
  348.     button = XtVaCreateManagedWidget("clhelp",
  349.         xmCascadeButtonWidgetClass, menubar,
  350.         XmNlabelString, xmstr = StringCreate("Help"),
  351.         XmNmnemonic, 'H',
  352.         XmNsubMenuId, pd = XmCreatePulldownMenu(menubar, "clHelpPD", 0, 0),
  353.         XmNfontList, FontList,
  354.         NULL);
  355.     XtVaSetValues(menubar,
  356.         XmNmenuHelpWidget, button,
  357.         NULL);
  358.     XmStringFree(xmstr);
  359.     for (help = TL_HELP_ABOUT; help < TL_HELP_CNT; help++) {
  360.         button = XtVaCreateManagedWidget(TlHelpStr[help],
  361.             xmPushButtonWidgetClass, pd,
  362.             XmNlabelString, xmstr = StringCreate(TlHelpStr[help]),
  363.             XmNmnemonic, TlHelpMne[help],
  364.             XmNvisibleWhenOff, True,
  365.             XmNsensitive, True,
  366.             XmNfontList, FontList,
  367.             NULL);
  368.         XmStringFree(xmstr);
  369.         XtAddCallback(button, XmNactivateCallback, HelpCB, (XtPointer)(int)help);
  370.     }
  371.     XtVaSetValues(menubar,
  372.         XmNtopAttachment, XmATTACH_FORM,
  373.         XmNtopOffset, 0,
  374.         XmNleftAttachment, XmATTACH_FORM,
  375.         XmNleftOffset, 0,
  376.         XmNrightAttachment, XmATTACH_FORM,
  377.         XmNrightOffset, 0,
  378.         NULL);
  379.     XtManageChild(menubar);
  380.     /*
  381.      * Create the Translation Mode labels.
  382.      */
  383.     label = XtVaCreateManagedWidget("modelabel",
  384.         xmLabelWidgetClass, form,
  385.         XmNlabelString, xmstr = StringCreate("Translation Mode:"),
  386.         XmNtopAttachment, XmATTACH_WIDGET,
  387.         XmNtopWidget, menubar,
  388.         XmNtopOffset, 10,
  389.         XmNleftAttachment, XmATTACH_FORM,
  390.         XmNleftOffset, 10,
  391.         XmNfontList, FontList,
  392.         NULL);
  393.     XmStringFree(xmstr);
  394.     TransMode = XtVaCreateManagedWidget("mode",
  395.         xmLabelWidgetClass, form,
  396.         XmNlabelString, xmstr = StringCreate(TlTransStr[Mode]),
  397.         XmNtopAttachment, XmATTACH_WIDGET,
  398.         XmNtopWidget, menubar,
  399.         XmNtopOffset, 10,
  400.         XmNleftAttachment, XmATTACH_WIDGET,
  401.         XmNleftWidget, label,
  402.         XmNleftOffset, 10,
  403.         XmNfontList, FontList,
  404.         NULL);
  405.     XmStringFree(xmstr);
  406.     /*
  407.      * Create the Translation Mode labels.
  408.      */
  409.     TransScope = XtVaCreateManagedWidget("scope",
  410.         xmLabelWidgetClass, form,
  411.         XmNlabelString, xmstr = StringCreate(TlTransStr[CurSel]),
  412.         XmNtopAttachment, XmATTACH_WIDGET,
  413.         XmNtopWidget, TransMode,
  414.         XmNtopOffset, 10,
  415.         XmNleftAttachment, XmATTACH_OPPOSITE_WIDGET,
  416.         XmNleftWidget, TransMode,
  417.         XmNleftOffset, 0,
  418.         XmNfontList, FontList,
  419.         NULL);
  420.     XmStringFree(xmstr);
  421.     label2 = XtVaCreateManagedWidget("scopelabel",
  422.         xmLabelWidgetClass, form,
  423.         XmNlabelString, xmstr = StringCreate("Translate:"),
  424.         XmNtopAttachment, XmATTACH_OPPOSITE_WIDGET,
  425.         XmNtopWidget, TransScope,
  426.         XmNtopOffset, 0,
  427.         XmNrightAttachment, XmATTACH_WIDGET,
  428.         XmNrightWidget, TransScope,
  429.         XmNrightOffset, 10,
  430.         XmNfontList, FontList,
  431.         NULL);
  432.     XmStringFree(xmstr);
  433.     /*
  434.      * Create Word box label and text box.
  435.      */
  436.     Word = XtVaCreateManagedWidget("word",
  437.         xmTextWidgetClass, form,
  438.         XmNcolumns, 25,
  439.         XmNbackground, WhitePixelOfScreen(XtScreen(form)),
  440.         XmNtopAttachment, XmATTACH_WIDGET,
  441.         XmNtopWidget, TransScope,
  442.         XmNtopOffset, 10,
  443.         XmNleftAttachment, XmATTACH_OPPOSITE_WIDGET,
  444.         XmNleftWidget, TransScope,
  445.         XmNleftOffset, 0,
  446.         XmNfontList, FontList,
  447.         NULL);
  448.     XtAddCallback(Word, XmNfocusCallback, TextFocusCB, 0);
  449.     label = XtVaCreateManagedWidget("wordlabel",
  450.         xmLabelWidgetClass, form,
  451.         XmNlabelString, xmstr = StringCreate("Word:"),
  452.         XmNtopAttachment, XmATTACH_OPPOSITE_WIDGET,
  453.         XmNtopWidget, Word,
  454.         XmNtopOffset, 7,
  455.         XmNrightAttachment, XmATTACH_WIDGET,
  456.         XmNrightWidget, Word,
  457.         XmNrightOffset, 10,
  458.         XmNfontList, FontList,
  459.         NULL);
  460.     XmStringFree(xmstr);
  461.     /*
  462.      * Create Word box label and text box.
  463.      */
  464.     Translation = XtVaCreateManagedWidget("translation",
  465.         xmTextWidgetClass, form,
  466.         XmNcolumns, 25,
  467.         XmNbackground, WhitePixelOfScreen(XtScreen(form)),
  468.         XmNtopAttachment, XmATTACH_WIDGET,
  469.         XmNtopWidget, Word,
  470.         XmNtopOffset, 10,
  471.         XmNleftAttachment, XmATTACH_OPPOSITE_WIDGET,
  472.         XmNleftWidget, Word,
  473.         XmNleftOffset, 0,
  474.         XmNfontList, FontList,
  475.         NULL);
  476.     XtAddCallback(Translation, XmNfocusCallback, TextFocusCB, 0);
  477.     label2 = XtVaCreateManagedWidget("translabel",
  478.         xmLabelWidgetClass, form,
  479.         XmNlabelString, xmstr = StringCreate("Translation:"),
  480.         XmNtopAttachment, XmATTACH_OPPOSITE_WIDGET,
  481.         XmNtopWidget, Translation,
  482.         XmNtopOffset, 7,
  483.         XmNrightAttachment, XmATTACH_WIDGET,
  484.         XmNrightWidget, Translation,
  485.         XmNrightOffset, 10,
  486.         XmNfontList, FontList,
  487.         NULL);
  488.     XmStringFree(xmstr);
  489.     /*
  490.      * Create the push buttons.
  491.      */
  492.     rowcol = XtVaCreateWidget("rowcol",
  493.         xmRowColumnWidgetClass, form,
  494.         XmNpacking, XmPACK_COLUMN,
  495.         XmNnumColumns, 1,
  496.         XmNorientation, XmVERTICAL,
  497.         XmNentryAlignment, XmALIGNMENT_CENTER,
  498.         XmNleftAttachment, XmATTACH_WIDGET,
  499.         XmNleftWidget, Translation,
  500.         XmNleftOffset, 10,
  501.         XmNtopAttachment, XmATTACH_WIDGET,
  502.         XmNtopWidget, menubar,
  503.         XmNtopOffset, 5,
  504.         XmNrightAttachment, XmATTACH_FORM,
  505.         XmNrightOffset, 10,
  506.         XmNbottomAttachment, XmATTACH_FORM,
  507.         XmNbottomOffset, 10,
  508.         XmNfontList, FontList,
  509.         NULL);
  510.     for (but = TL_BUT_START; but < TL_BUT_CNT; but++) {
  511.         if (!inAPI && (but == TL_BUT_TRANSLATE)) {
  512.             str = "Translate";
  513.         } else {
  514.             str = TlButtons[but];
  515.         }
  516.         Buttons[but] = button = XtVaCreateManagedWidget(TlButtons[but],
  517.             xmPushButtonWidgetClass, rowcol,
  518.             XmNlabelString, xmstr = StringCreate(TlButtons[but]),
  519.             XmNmarginLeft, 4,
  520.             XmNmarginRight, 4,
  521.             XmNfontList, FontList,
  522.             NULL);
  523.         XmStringFree(xmstr);
  524.         XtAddCallback(button, XmNactivateCallback, ButtonCB, (XtPointer)(int)but);
  525.     }
  526.     XtManageChild(rowcol);
  527.     /*
  528.      * Set initial dialog state.
  529.      */
  530.     SetDialogState();
  531.     /*
  532.      * Pop up the Server dialog.
  533.      */
  534.     XtPopup(Server, XtGrabNone);
  535. } /* ServerInit */
  536.  
  537. /*COMMENT***************************************************
  538. ;ServerDestroyCB
  539. Title:    Handle destroy of Server dialog.
  540. In:        none
  541. Out:    none
  542. Xin:    none
  543. Xout:    none
  544. Return:    none
  545. Notes:
  546. ***********************************************************/
  547. static void ServerDestroyCB(Widget w, XtPointer cldata, XtPointer cbdata)
  548. {
  549.     if (inAPI) {
  550.         if (comm_id) {
  551.             TermSession();
  552.             WTCloseComm(comm_id);
  553.         }
  554.         comm_id = 0;
  555.     }
  556.     if (FontList) {
  557.         XmFontListFree(FontList);
  558.     }
  559.     if (Icon) {
  560.         XFreePixmap(XtDisplayOfObject(Server), Icon);    /* free pixmap */
  561.     }
  562.     free_cursors(Server);
  563.     Server = 0;
  564.     ServerExit();        /* clean up and exit server */
  565. } /* ServerDestroyCB */
  566.  
  567. /*COMMENT***************************************************
  568. ;ServerExit
  569. Title:    Clean up and exit WTAPI Sample Application
  570. In:        none
  571. Out:    none
  572. Xin:    none
  573. Xout:    none
  574. Return:    none
  575. Notes:
  576. ***********************************************************/
  577. static void ServerExit()
  578. {
  579.     exit(0);
  580. } /* ServerExit */
  581.  
  582. /*COMMENT***************************************************
  583. ;TextFocusCB
  584. Title:    Clean up and exit WTAPI Sample Application
  585. In:        none
  586. Out:    none
  587. Xin:    none
  588. Xout:    none
  589. Return:    none
  590. Notes:
  591. ***********************************************************/
  592. static void TextFocusCB(Widget w, XtPointer cldata, XtPointer cbdata)
  593. {
  594.     Text = w;    /* which text box has last had focus */
  595. } /* TextFocusCB */
  596.  
  597. /*COMMENT***************************************************
  598. ;ButtonCB
  599. Title:    Perform button action
  600. In:        cldata - which button was pushed
  601. Out:    none
  602. Xin:    none
  603. Xout:    none
  604. Return:    none
  605. Notes:
  606. ***********************************************************/
  607. static void ButtonCB(Widget w, XtPointer cldata, XtPointer cbdata)
  608. {
  609.     TL_BUT but = (TL_BUT) cldata;
  610.     char *word;
  611.     char oldword[BUFSIZE];
  612.     char newword[BUFSIZE];
  613.  
  614.     switch (but) {
  615.         case TL_BUT_START:
  616.             if (!inAPI) {
  617.                 word = XmTextGetString(Word);
  618.                 if (word) {
  619.                     strncpy(oldword, word, BUFSIZE-1);
  620.                     oldword[BUFSIZE-1] = 0;
  621.                     XtFree(word);
  622.                 } else {
  623.                     oldword[0] = 0;
  624.                 }
  625.                 if (Mode == TL_TRANS_NATPIG) {
  626.                     NatToPig(oldword, newword);
  627.                 } else {
  628.                     PigToNat(oldword, newword);
  629.                 }
  630.                 XtVaSetValues(Translation, XmNvalue, newword, NULL);
  631.                 break;
  632.             } else {
  633.                 if (!inLoop) {
  634.                     InitText();
  635.                     inLoop = TRUE;
  636.                     SetButtons();
  637.                 } else {    /* Replace */
  638.                     word = XmTextGetString(Translation);
  639.                     if (word) {
  640.                         strncpy(newword, word, BUFSIZE-1);
  641.                         newword[BUFSIZE-1] = 0;
  642.                         XtFree(word);
  643.                     } else {
  644.                         newword[0] = 0;
  645.                     }
  646.                     ReplaceWord(newword);
  647.                 }
  648.             }
  649.             /* fall through to go to the next word */
  650.         case TL_BUT_SKIP:
  651.             if (but == TL_BUT_SKIP) {    /* not just falling through */
  652.                 DeHilite();
  653.             }
  654.             if (!NextWord(oldword)) {
  655.                 MsgBox(MB_OK, Server, "About WTServer", "Translation Complete");
  656.                 inLoop = FALSE;
  657.                 SetButtons();
  658.             } else {
  659.                 if (Mode == TL_TRANS_NATPIG) {
  660.                     NatToPig(oldword, newword);
  661.                 } else {
  662.                     PigToNat(oldword, newword);
  663.                 }
  664.                 PutWords(oldword, newword);
  665.             }
  666.             break;
  667.         case TL_BUT_RETRANS:
  668.             word = XmTextGetString(Word);
  669.             if (word) {
  670.                 strncpy(oldword, word, BUFSIZE-1);
  671.                 oldword[BUFSIZE-1] = 0;
  672.                 XtFree(word);
  673.             } else {
  674.                 oldword[0] = 0;
  675.             }
  676.             if (Mode == TL_TRANS_NATPIG) {
  677.                 NatToPig(oldword, newword);
  678.             } else {
  679.                 PigToNat(oldword, newword);
  680.             }
  681.             XtVaSetValues(Translation, XmNvalue, newword, NULL);
  682.             break;
  683.         case TL_BUT_TRANSALL:
  684.             if (!inLoop) {
  685.                 InitText();
  686.                 inLoop = TRUE;
  687.                 SetButtons();
  688.                 if (!NextWord(oldword)) {
  689.                     MsgBox(MB_OK, Server, "WTServer", "Translation Complete");
  690.                 } else {
  691.                     if (Mode == TL_TRANS_NATPIG) {
  692.                         NatToPig(oldword, newword);
  693.                     } else {
  694.                         PigToNat(oldword, newword);
  695.                     }
  696.                 }
  697.             } else {
  698.                 word = XmTextGetString(Translation);
  699.                 if (word) {
  700.                     strncpy(newword, word, BUFSIZE-1);
  701.                     newword[BUFSIZE-1] = 0;
  702.                     XtFree(word);
  703.                 } else {
  704.                     newword[0] = 0;
  705.                 }
  706.             }
  707.             XLateAll(oldword, newword);
  708.             MsgBox(MB_OK, Server, "WTServer", "Translation Complete");
  709.             inLoop = FALSE;
  710.             SetButtons();
  711.             break;
  712.         case TL_BUT_CLOSE:
  713.             XtDestroyWidget(Server);
  714.             break;
  715.         default:
  716.             break;
  717.     }
  718. } /* ButtonCB */
  719.  
  720. /*COMMENT***************************************************
  721. ;quitTool
  722. Title:    Quit the writing tool
  723. In:        msg - optional message to output before quitting the tool
  724. Out:    none
  725. Xin:    none
  726. Xout:    none
  727. Return:    none
  728. Notes:
  729. ***********************************************************/
  730. void quitTool(char *msg)
  731. {
  732.     if (msg) {
  733.         MsgBox(MB_OK, Server, "WTServer", msg);
  734.     }
  735.     XtDestroyWidget(Server);
  736. } /* quitTool */
  737.  
  738. /*COMMENT***************************************************
  739. ;StringCreate
  740. Title:    Initialize WTAPI Sample Application
  741. In:        toplevel - toplevel widget of application
  742. Out:    none
  743. Xin:    none
  744. Xout:    none
  745. Return:    none
  746. Notes:
  747. ***********************************************************/
  748. XmString StringCreate(char *str)
  749. {
  750.     return(XmStringCreateLtoR(str, XmSTRING_DEFAULT_CHARSET));
  751. } /* StringCreate */
  752.  
  753. /* FUNCTION ********************************************************
  754. ;XmStringToString
  755. Title:    Converts an XmString to a native string
  756. In:        str - XmString to convert
  757. Out:    none
  758. Return:    pointer to native string (needs to be freed)
  759. Notes:
  760. *******************************************************************/
  761. char *XmStringToString(XmString str)
  762. {
  763.     Boolean separator;
  764.     char *ptr = 0, *tmp;
  765.     XmStringContext context;
  766.     XmStringCharSet charset;
  767.     XmStringDirection direction;
  768.  
  769.     if (XmStringInitContext(&context, str)) {
  770.         tmp = charset = 0;
  771.         while (XmStringGetNextSegment(context,
  772.             &tmp, &charset, &direction, &separator))
  773.         {
  774.             if (!strcmp((char *)charset,(char *)_XmStringGetCurrentCharset()) ||
  775.                 !strcmp((char *)charset,
  776.                     (char *)"FONTLIST_DEFAULT_TAG_STRING"))
  777.             {
  778.                 int i;
  779.  
  780.                 if (!ptr) {
  781.                     ptr = (char *)calloc(strlen(tmp)+1, 1);
  782.                 } else {
  783.                     ptr = (char *)realloc(ptr, strlen(tmp)+strlen(ptr)+1);
  784.                 }
  785.                 if (ptr) {
  786.                     char *sptr;
  787.  
  788.                     for (i = strlen(ptr), sptr = tmp; *sptr; sptr++) {
  789.                         ptr[i++] = *sptr;
  790.                     }
  791.                     ptr[i] = 0;
  792.                 }
  793.                 else break;
  794.             }
  795.             XtFree(tmp);
  796.             XtFree(charset);
  797.             tmp = charset = 0;
  798.         }
  799.         XmStringFreeContext(context);
  800.         if (tmp) {
  801.             XtFree(tmp);
  802.         }
  803.         if (charset) {
  804.             XtFree(charset);
  805.         }
  806.     }
  807.     return ptr;
  808. } /* XmStringToString */
  809.  
  810. /*COMMENT***************************************************
  811. ;TransCB
  812. Title:    Translate menu actions.
  813. In:        cldata - Translate action to perform
  814. Out:    none
  815. Xin:    Client - toplevel Client widget
  816. Xout:    none
  817. Return:    none
  818. Notes:
  819. ***********************************************************/
  820. static void TransCB(Widget w, XtPointer cldata, XtPointer cbdata)
  821. {
  822.     TL_TRANS trans = (TL_TRANS)(int)cldata;
  823.     XmToggleButtonCallbackStruct *cb = (XmToggleButtonCallbackStruct *)cbdata;
  824.  
  825.     /*
  826.      * To enforce radio behavior among the two sets of buttons on the
  827.      * Translate menu we only allow the user to select which option they
  828.      * want.  If the click on an option that is already toggled on we don't
  829.      * allow it to be toggled off.
  830.      */
  831.     if (!cb->set) {
  832.         XtVaSetValues(transButtons[trans], XmNset, True, NULL);
  833.         return;
  834.     }
  835.  
  836.     switch (trans) {
  837.         case TL_TRANS_NATPIG:    /* Native to Pig Latin */
  838.             Mode = trans;
  839.             XtVaSetValues(transButtons[TL_TRANS_PIGNAT], XmNset, False, NULL);
  840.             SetTranslateText();
  841.             break;
  842.         case TL_TRANS_PIGNAT:    /* Pig Latin to Native */
  843.             Mode = trans;
  844.             XtVaSetValues(transButtons[TL_TRANS_NATPIG], XmNset, False, NULL);
  845.             SetTranslateText();
  846.             break;
  847.         case TL_TRANS_WORD:
  848.         case TL_TRANS_DOC:
  849.         case TL_TRANS_ENDDOC:
  850.         case TL_TRANS_SELECT:
  851.             XtVaSetValues(transButtons[CurSel], XmNset, False, NULL);
  852.             CurSel = trans;
  853.             XtVaSetValues(transButtons[CurSel], XmNset, True, NULL);
  854.             SetTranslateText();
  855.             break;
  856.         default:
  857.             break;    /* invalid trans, do nothing */
  858.     }
  859. } /* TransCB */
  860.  
  861. /*COMMENT***************************************************
  862. ;EditCB
  863. Title:    File menu actions.
  864. In:        cldata - Edit action to perform
  865. Out:    none
  866. Xin:    Server - toplevel Server widget
  867. Xout:    none
  868. Return:    none
  869. Notes:
  870. ***********************************************************/
  871. static void EditCB(Widget w, XtPointer cldata, XmAnyCallbackStruct *cbdata)
  872. {
  873.     TL_EDIT edit = (TL_EDIT)(int)cldata;    /* which edit action to perform */
  874.     Time time = cbdata->event->xbutton.time;
  875.     char *txt, *prevtxt = 0;
  876.     XmTextPosition prevleftsel = 0, prevrightsel = 0;
  877.     int status = 0;            /* status of call to clipboard routines */
  878.     int len = 0;            /* length of text in clipboard */
  879.     BOOL changed = FALSE;    /* did text change? */
  880.     static Widget oldText;    /* for Undo, text widget last changed */
  881.  
  882.     /*
  883.      * If UNDO then we need to save the previous text and selection before
  884.      * we update them to be the current text and selection.
  885.      */
  886.     if (edit == TL_EDIT_UNDO) {
  887.         if (prevText) {
  888.             prevtxt = prevText;    /* use the same pointer */
  889.             prevText = 0;        /* we'll allocate more space for this later */
  890.         }
  891.         prevleftsel = prevSelLeft;
  892.         prevrightsel = prevSelRight;
  893.         Text = oldText;
  894.     }
  895.     if (!Text) {
  896.         return;
  897.     }
  898.     oldText = Text;
  899.     /*
  900.      * Save the current text and selection as the previous text and selection
  901.      * for possible use with UNDO later.
  902.      */
  903.     if (prevText) {
  904.         XtFree(prevText);
  905.     }
  906.     prevText = XmTextGetString(Text);
  907.     if (!XmTextGetSelectionPosition(Text, &prevSelLeft, &prevSelRight)) {
  908.         prevSelLeft = prevSelRight = 0;
  909.     }
  910.     /*
  911.      * Perform the Edit action.
  912.      */
  913.     switch (edit) {
  914.         case TL_EDIT_UNDO:        /* Undo */
  915.             if (prevtxt) {
  916.                 XmTextSetString(Text, prevtxt);
  917.                 XtFree(prevtxt);
  918.                 if (prevleftsel < prevrightsel) {
  919.                     XmTextSetSelection(Text, prevleftsel, prevrightsel, time);
  920.                 }
  921.             } else {
  922.                 XmTextSetString(Text, "");
  923.                 XmTextClearSelection(Text, time);
  924.             }
  925.             break;
  926.         case TL_EDIT_CUT:        /* Cut */
  927.             if (!XmTextCut(Text, time)) {
  928.                 XBell(XtDisplay(Text), 100);    /* beep */
  929.             }
  930.             break;
  931.         case TL_EDIT_COPY:        /* Copy */
  932.             if (!XmTextCopy(Text, time)) {
  933.                 XBell(XtDisplay(Text), 100);    /* beep */
  934.             }
  935.             break;
  936.         case TL_EDIT_PASTE:        /* Paste */
  937.             if (!XmTextPaste(Text)) {
  938.                 XBell(XtDisplay(Text), 100);    /* beep */
  939.             }
  940.             break;
  941.         default:                /* unrecognized action */
  942.             break;                /* do nothing */
  943.     }
  944. } /* EditCB */
  945.  
  946. /*COMMENT***************************************************
  947. ;SetEditButtons
  948. Desc:    Set the sensitivity on the Edit buttons.
  949. In:        none
  950. Out:    none
  951. Xin:    none
  952. Xout:    none
  953. Return:    none
  954. ***********************************************************/
  955. static void SetEditButtons(Widget w, XtPointer cldata, XtPointer cbdata)
  956. {
  957.     char *sel;            /* selected text */
  958.     int status = 0;        /* status of call to clipboard routines */
  959.     int length = 0;        /* length of text in clipboard */
  960.     
  961.     if (!Text) {
  962.         return;
  963.     }
  964.     /*
  965.      * If no edits yet then turn Undo off.
  966.      */
  967.     if (prevSelLeft == 0xff && prevSelRight == 0) {
  968.         XtSetSensitive(editButtons[TL_EDIT_UNDO], False);
  969.     } else {
  970.         XtSetSensitive(editButtons[TL_EDIT_UNDO], True);
  971.     }
  972.     /*
  973.      * If there is selected text in the box then turn on Cut and Copy.
  974.      */
  975.     sel = XmTextGetSelection(Text);
  976.     if (sel && *sel) {
  977.         XtSetSensitive(editButtons[TL_EDIT_CUT], True);
  978.         XtSetSensitive(editButtons[TL_EDIT_COPY], True);
  979.     } else {
  980.         XtSetSensitive(editButtons[TL_EDIT_CUT], False);
  981.         XtSetSensitive(editButtons[TL_EDIT_COPY], False);
  982.     }
  983.     if (sel) {
  984.         XtFree(sel);
  985.     }
  986.     /*
  987.      * Turn Paste on if there is text in the clipboard.
  988.      */
  989.     do {
  990.         status = XmClipboardInquireLength(XtDisplay(w), XtWindow(w),
  991.             "STRING", &length);
  992.     } while (status == ClipboardLocked);
  993.     if ((status != ClipboardNoData) && (length > 0)) {
  994.         XtSetSensitive(editButtons[TL_EDIT_PASTE], True);
  995.     } else {
  996.         XtSetSensitive(editButtons[TL_EDIT_PASTE], False);
  997.     }
  998. } /* SetEditButtons */
  999.  
  1000. /*COMMENT***************************************************
  1001. ;HelpCB
  1002. Title:    Help menu actions.
  1003. In:        cldata - Help action to perform
  1004. Out:    none
  1005. Xin:    Server - toplevel Server widget
  1006. Xout:    none
  1007. Return:    none
  1008. Notes:
  1009. ***********************************************************/
  1010. static void HelpCB(Widget w, XtPointer cldata, XtPointer cbdata)
  1011. {
  1012.     TL_HELP help = (TL_HELP)(int)cldata;    /* which help action to perform */
  1013.     switch (help) {
  1014.         case TL_HELP_ABOUT:
  1015.             MsgBox(MB_OK, Server, "About WTServer",
  1016.               "Writing Tools API\nSample Server Application\n\nVersion 0.6");
  1017.             break;
  1018.         default:                /* unrecognized action */
  1019.             break;                /* do nothing */
  1020.     }
  1021. } /* HelpCB */
  1022.  
  1023. /*COMMENT***************************************************
  1024. ;change_cursors
  1025. Title:    Turn on a cursor for a widget and its ancestors
  1026. In:        w = widget
  1027.         cursor = the cursor
  1028. Out:    none
  1029. Xin:    none
  1030. Xout:    none
  1031. Ret:    none
  1032. Notes:
  1033. ***********************************************************/
  1034. static void change_cursors(Widget w, Cursor cursor)
  1035. {
  1036.     while (w) {
  1037.         if (XtDisplayOfObject(w) && XtWindowOfObject(w)) {
  1038.             XDefineCursor(
  1039.                 XtDisplayOfObject(w), 
  1040.                 XtWindowOfObject(w), 
  1041.                 cursor);
  1042.             XSync(XtDisplayOfObject(w), False);
  1043.         }
  1044.         w = XtParent(w);
  1045.     }
  1046. } /* change_cursors */
  1047.  
  1048. /*COMMENT***************************************************
  1049. ;WaitCursor
  1050. Title:    Turn on wait cursor (Watch)
  1051. In:        w = widget
  1052. Out:    none
  1053. Xin:    none
  1054. Xout:    none
  1055. Ret:    none
  1056. Notes:
  1057. ***********************************************************/
  1058. void WaitCursor(Widget w)
  1059. {
  1060.     if (!waitcursor) {
  1061.         waitcursor = XCreateFontCursor(XtDisplayOfObject(w), XC_watch);
  1062.     }
  1063.     change_cursors(w, waitcursor);
  1064. } /* WaitCursor */
  1065.  
  1066. /*COMMENT***************************************************
  1067. ;NormalCursor
  1068. Title:    Turn on normal cursor (Arrow)
  1069. In:        w = widget
  1070. Out:    none
  1071. Xin:    none
  1072. Xout:    none
  1073. Ret:    none
  1074. Notes:
  1075. ***********************************************************/
  1076. void NormalCursor(Widget w)
  1077. {
  1078.     if (!normalcursor) {
  1079.         normalcursor = XCreateFontCursor(XtDisplayOfObject(w), XC_left_ptr);
  1080.     }
  1081.     change_cursors(w, normalcursor);
  1082. } /* NormalCursor */
  1083.  
  1084. /*COMMENTS********************************
  1085. ;free_cursors
  1086. Title:    Free cursors we created
  1087. In:        w - any widget on same display as cursors
  1088. Out:    none
  1089. Xin:    none
  1090. Xout:    none
  1091. Return:    none
  1092. Notes:
  1093. *END**************************************/
  1094. static void free_cursors(Widget w)
  1095. {
  1096.     if (normalcursor) {
  1097.         XFreeCursor(XtDisplay(w), normalcursor);
  1098.     }
  1099.     if (waitcursor) {
  1100.         XFreeCursor(XtDisplay(w), waitcursor);
  1101.     }
  1102.     normalcursor = 0;        /* for safety */
  1103.     waitcursor = 0;            /* for safety */
  1104. } /* free_cursors */
  1105.  
  1106. /*COMMENT***************************************************
  1107. ;MsgBoxCB
  1108. Title:     MsgBox dialog callback
  1109. In:        cldata - 1 = Yes, 0 = No
  1110. Out:    none
  1111. Return:    none
  1112. Xin:    none
  1113. Xout:    none
  1114. Notes:
  1115. ***********************************************************/
  1116. static void MsgBoxCB(Widget w, XtPointer cldata, XtPointer cbdata)
  1117. {
  1118.     MsgBoxRet = ((int)cldata == 1);
  1119.     if (msgDialog) {
  1120.         XtDestroyWidget(msgDialog);
  1121.     }
  1122.     msgDialog = 0;
  1123. } /* MsgBoxCB */
  1124.  
  1125. /*COMMENT***************************************************
  1126. ;MsgBox
  1127. Title:    Bring up an OK or Yes/No message dialog.
  1128. In:        type - type of message box
  1129.         parent - parent widget
  1130.         title - dialog title
  1131.         message - message/question for dialog
  1132. Out:    none
  1133. Xin:    none
  1134. Xout:    none
  1135. Return:    TRUE - Yes, FALSE - No
  1136. Notes:
  1137. ***********************************************************/
  1138. BOOL MsgBox(MSGBOX type, Widget parent, char *title, char *message)
  1139. {
  1140.     Arg args[14];            /* Args for XtSetArg() */
  1141.     Cardinal argcnt = 0;    /* number of Args set */
  1142.     XmString titleStr, messageStr, yesStr, noStr;
  1143.     XEvent event;
  1144.  
  1145.     MsgBoxRet = False;
  1146.     titleStr = StringCreate(title);
  1147.     messageStr = StringCreate(message);
  1148.     if (type == MB_YESNO) {
  1149.         yesStr = StringCreate("Yes");
  1150.         noStr = StringCreate("No");
  1151.     } else {
  1152.         yesStr = StringCreate("OK");
  1153.     }
  1154.     argcnt = 0;
  1155.     XtSetArg(args[argcnt], XmNdialogTitle, titleStr);  argcnt++;
  1156.     XtSetArg(args[argcnt], XmNmessageString, messageStr);  argcnt++;
  1157.     XtSetArg(args[argcnt], XmNokLabelString, yesStr);  argcnt++;
  1158.     XtSetArg(args[argcnt], XmNtextFontList, FontList);  argcnt++;
  1159.     XtSetArg(args[argcnt], XmNbuttonFontList, FontList);  argcnt++;
  1160.     XtSetArg(args[argcnt], XmNlabelFontList, FontList);  argcnt++;
  1161.     XtSetArg(args[argcnt], XmNdialogStyle,
  1162.                             XmDIALOG_PRIMARY_APPLICATION_MODAL);  argcnt++;
  1163.     XtSetArg(args[argcnt], XmNmessageAlignment, XmALIGNMENT_CENTER);  argcnt++;
  1164.     if (type == MB_YESNO) {
  1165.         XtSetArg(args[argcnt], XmNcancelLabelString, noStr);  argcnt++;
  1166.         msgDialog = XmCreateQuestionDialog(parent, "quesDialog", args, argcnt);
  1167.     } else {
  1168.         msgDialog = XmCreateInformationDialog(parent, "infoDialog", args, argcnt);
  1169.     }
  1170.     XmStringFree(titleStr);
  1171.     XmStringFree(messageStr);
  1172.     XmStringFree(yesStr);
  1173.     if (type == MB_YESNO) {
  1174.         XmStringFree(noStr);
  1175.         XtAddCallback(msgDialog, XmNcancelCallback, MsgBoxCB, 0);
  1176.     } else {
  1177.         XtUnmanageChild(XmMessageBoxGetChild(msgDialog,XmDIALOG_CANCEL_BUTTON));
  1178.     }
  1179.     XtAddCallback(msgDialog, XmNokCallback, MsgBoxCB, (XtPointer) 1);
  1180.     XtUnmanageChild(XmMessageBoxGetChild(msgDialog, XmDIALOG_HELP_BUTTON));
  1181.     XtManageChild(msgDialog);
  1182.     /*
  1183.      * Process events until dialog is closed.
  1184.      */
  1185.     for (;;) {
  1186.         XtAppNextEvent(XtWidgetToApplicationContext(parent), &event);
  1187.         XtDispatchEvent(&event);
  1188.         if (!msgDialog) {
  1189.             break;
  1190.         }
  1191.     }
  1192.     return(MsgBoxRet);
  1193. } /* MsgBox */
  1194.  
  1195. /*COMMENT***************************************************
  1196. ;NatToPig
  1197. Title:    Convert a native word to pig latin
  1198. In:        natword - native word
  1199. Out:    pigword - word in pig latin
  1200. Xin:    none
  1201. Xout:    none
  1202. Return:    TRUE - success, FALSE - didn't translate word
  1203. Notes:    natword must be null terminated
  1204. ***********************************************************/
  1205. static BOOL NatToPig(char *natword, char *pigword)
  1206. {
  1207.     int length, vowlen;
  1208.     
  1209.     length = strlen(natword);         /* length of whole word */
  1210.     for (vowlen = 0; vowlen < length; ++vowlen) {    /* locate first vowel */
  1211.         if (isvowel(natword[vowlen])) {
  1212.             break;
  1213.         }
  1214.         if ( (vowlen > 0) && 
  1215.             ((natword[vowlen] == 'y') || (natword[vowlen] == 'Y')))
  1216.                 break;
  1217.     }    
  1218.     if (vowlen == length) {
  1219.         if (length >= BUFSIZE-1) {
  1220.             natword[BUFSIZE-1] = 0;
  1221.         }
  1222.         strcpy(pigword, natword);
  1223.         return FALSE;        /* no vowels, don't change the word */
  1224.     } else if (vowlen == 0) {
  1225.         if (length >= BUFSIZE-4) {
  1226.             natword[BUFSIZE-4] = 0;
  1227.         }
  1228.         strcpy(pigword, natword);
  1229.         strcat(pigword, "hay");        /* starts with vowel, copy 'hay' to end */
  1230.     } else {
  1231.         if (length >= BUFSIZE-3) {
  1232.             natword[BUFSIZE-3] = 0;
  1233.         }
  1234.         strcpy(pigword, natword + vowlen);  /* rearrange to piglatin format */
  1235.         strncat(pigword, natword, vowlen);  
  1236.         strcat(pigword, "ay");                  /* add piglatin suffix */
  1237.     }
  1238.     return TRUE;
  1239. } /* NatToPig */
  1240.  
  1241. /*COMMENT***************************************************
  1242. ;PigToNat
  1243. Title:    Convert a pig latin word to native
  1244. In:        pigword - native word
  1245. Out:    natword - word in pig latin
  1246. Xin:    none
  1247. Xout:    none
  1248. Return:    TRUE - success, FALSE - didn't translate word
  1249. Notes:    pigword must be null terminated
  1250. ***********************************************************/
  1251. static BOOL PigToNat(char *pigword, char *natword)
  1252. {   
  1253.     int length = strlen(pigword);
  1254.  
  1255.     /* check for a valid pig latin word */ 
  1256.     if (((pigword[length-1] != 'y') && (pigword[length-1] != 'Y')) ||
  1257.         ((pigword[length-2] != 'a') && (pigword[length-2] != 'A')))
  1258.     {
  1259.         MsgBox(MB_OK, Server, "WTServer Error", "Not a Valid Pig Latin Word!");
  1260.         natword[0] = 0;
  1261.         return FALSE;
  1262.     }
  1263.     if (!isvowel(pigword[0]) &&
  1264.         (pigword[0] != 'y') && (pigword[0] != 'Y'))
  1265.     {
  1266.         MsgBox(MB_OK, Server, "WTServer Error", "Not a Valid Pig Latin Word!");
  1267.         natword[0] = 0;
  1268.         return FALSE;
  1269.     }
  1270.     /* it was a valid word, go ahead and offer translation possiblities */
  1271.     PromptTranslateOptions(pigword);
  1272.     strcpy(natword, gbuf);            /* copy the new word */
  1273.     return TRUE;
  1274. } /* PigToNat */
  1275.  
  1276. /*COMMENT***************************************************
  1277. ;InitText
  1278. Title:    Initialize the text buffers
  1279. In:        none
  1280. Out:    none
  1281. Xin:    none
  1282. Xout:    none
  1283. Return:    none
  1284. Notes:    none
  1285. ***********************************************************/
  1286. static void InitText(void)
  1287. {
  1288.     WTQTEXTBLOCKP inmsg;
  1289.     WTRTEXTBLOCKP rtmsg;
  1290.     WTSTATUS status;
  1291.     
  1292.     /* load parms into query parm table */
  1293.     inmsg = (WTQTEXTBLOCKP)sndbuf;
  1294.     inmsg->msgid = WTQ_TEXTBLOCK;
  1295.     inmsg->frompos = WTP_REL;
  1296.     inmsg->fromloc = 0;
  1297.     inmsg->topos = WTP_REL;
  1298.     inmsg->toloc = 0;
  1299.     inmsg->qtype = WTB_INIT;
  1300.     inmsg->containers = WT_FALSE;
  1301.     inmsg->tracking = WT_FALSE;
  1302.     inmsg->size = TEXTSIZE;
  1303.     inmsg->windowTool = XtWindow(Server);
  1304.     /* figure out units from CurSel */
  1305.     switch (CurSel) {
  1306.         case TL_TRANS_WORD:
  1307.             inmsg->fromunit = WTU_WORD;
  1308.             inmsg->tounit = WTU_WORD;
  1309.             break;
  1310.         case TL_TRANS_DOC:
  1311.             inmsg->fromunit = WTU_DOCUMENT;
  1312.             inmsg->tounit = WTU_DOCUMENT;
  1313.             break;
  1314.         case TL_TRANS_ENDDOC:
  1315.             inmsg->fromunit = WTU_WORD;
  1316.             inmsg->tounit = WTU_DOCUMENT;
  1317.             break;
  1318.         case TL_TRANS_SELECT:
  1319.             inmsg->fromunit = WTU_SELECTION;
  1320.             inmsg->tounit = WTU_SELECTION;
  1321.             break;
  1322.         default:
  1323.             break;
  1324.     }
  1325.     rtmsg = (WTRTEXTBLOCKP)rcvbuf;
  1326.     status = wtqTlSend(comm_id, WTQ_TEXTBLOCK, sndbuf, sizeof(WTQTEXTBLOCK),
  1327.         NULL, 0, WTR_TEXTBLOCK, rcvbuf, sizeof(WTRTEXTBLOCK), txtbuf, TEXTSIZE);
  1328.     switch (status) {
  1329.         case WTS_OK:
  1330.             break;
  1331.         case WTS_COMERROR:
  1332.             XBell(XtDisplay(Server), 100);
  1333.             MsgBox(MB_OK, Server, "WTServer Error",
  1334.                 "Writing Tools API communication error!");
  1335.             ServerDestroyCB(0, 0, 0);
  1336.             break;
  1337.         default:
  1338.             XBell(XtDisplay(Server), 100);
  1339.             MsgBox(MB_OK, Server, "WTServer Error",
  1340.                 "Action could not be completed.");
  1341.             break;
  1342.     }        
  1343.     txtsize = (int)rtmsg->size;
  1344.     txtbeg = txtend = 0;
  1345.     endflag = rtmsg->endblock; 
  1346.     return;
  1347. } /* InitText */
  1348.  
  1349. /*COMMENT***************************************************
  1350. ;SetTranslateText
  1351. Title:    Update the Translation Mode and Translate text.
  1352. In:        cldata - Translate action to perform
  1353. Out:    none
  1354. Xin:    TransMode, TransScope
  1355. Xout:    none
  1356. Return:    none
  1357. Notes:
  1358. ***********************************************************/
  1359. static void SetTranslateText()
  1360. {
  1361.     XmString xmstr;
  1362.  
  1363.     xmstr = StringCreate(TlTransStr[Mode]);
  1364.     XtVaSetValues(TransMode, XmNlabelString, xmstr, NULL);
  1365.     XmStringFree(xmstr);
  1366.     xmstr = StringCreate(TlTransStr[CurSel]);
  1367.     XtVaSetValues(TransScope, XmNlabelString, xmstr, NULL);
  1368.     XmStringFree(xmstr);
  1369. }/* SetTranslateText */
  1370.  
  1371. /*COMMENT***************************************************
  1372. ;SetButtons
  1373. Title:    Set the state of the buttons in the dialog
  1374. In:        none
  1375. Out:    none
  1376. Xin:    none
  1377. Xout:    none
  1378. Return:    none
  1379. Notes:    none
  1380. ***********************************************************/
  1381. static void SetButtons()
  1382. {
  1383.     XmString xmstr;
  1384.  
  1385.     if (inAPI) {
  1386.         if (inLoop) {
  1387.             xmstr = StringCreate("Replace");
  1388.             XtVaSetValues(Buttons[TL_BUT_START], XmNlabelString, xmstr, NULL);
  1389.             XmStringFree(xmstr);
  1390.             XtSetSensitive(Buttons[TL_BUT_SKIP], True);
  1391.         } else {
  1392.             xmstr = StringCreate("Start");
  1393.             XtVaSetValues(Buttons[TL_BUT_START], XmNlabelString, xmstr, NULL);
  1394.             XmStringFree(xmstr);
  1395.             XtSetSensitive(Buttons[TL_BUT_SKIP], False);
  1396.         }
  1397.         XtSetSensitive(Buttons[TL_BUT_RETRANS], True);
  1398.         XtSetSensitive(Buttons[TL_BUT_TRANSALL], True);
  1399.         XtSetSensitive(Buttons[TL_BUT_CLOSE], True);
  1400.     } else {
  1401.         xmstr = StringCreate("Translate");
  1402.         XtVaSetValues(Buttons[TL_BUT_START], XmNlabelString, xmstr, NULL);
  1403.         XmStringFree(xmstr);
  1404.         XtSetSensitive(Buttons[TL_BUT_SKIP], False);
  1405.         XtSetSensitive(Buttons[TL_BUT_RETRANS], False);
  1406.         XtSetSensitive(Buttons[TL_BUT_TRANSALL], False);
  1407.         XtSetSensitive(Buttons[TL_BUT_CLOSE], True);
  1408.     }
  1409. } /* SetButtons */
  1410.  
  1411. /*COMMENT***************************************************
  1412. ;SetDialogState
  1413. Title:    Set the initial state of the main dialog
  1414. In:        none
  1415. Out:    none
  1416. Xin:    none
  1417. Xout:    none
  1418. Return:    none
  1419. Notes:    none
  1420. ***********************************************************/
  1421. void SetDialogState()
  1422. {
  1423.     if (inAPI) {
  1424.         XtSetSensitive(transButtons[TL_TRANS_WORD], True);
  1425.         XtSetSensitive(transButtons[TL_TRANS_DOC], True);
  1426.         XtSetSensitive(transButtons[TL_TRANS_ENDDOC], True);
  1427.         if (inBlock) {
  1428.             XtSetSensitive(transButtons[TL_TRANS_SELECT], True);
  1429.             XtVaSetValues(transButtons[CurSel], XmNset, False, NULL);
  1430.             CurSel = TL_TRANS_SELECT;
  1431.             XtVaSetValues(transButtons[CurSel], XmNset, True, NULL);
  1432.             SetTranslateText();
  1433.         } else {
  1434.             XtSetSensitive(transButtons[TL_TRANS_SELECT], False);
  1435.         }
  1436.     } else {
  1437.         XtSetSensitive(transButtons[TL_TRANS_WORD], True);
  1438.         XtSetSensitive(transButtons[TL_TRANS_DOC], False);
  1439.         XtSetSensitive(transButtons[TL_TRANS_ENDDOC], False);
  1440.         XtSetSensitive(transButtons[TL_TRANS_SELECT], False);
  1441.     }
  1442.     SetButtons();            /* set the buttons too */
  1443.     SetTranslateText();        /* set translation mode and scope */
  1444.     return;
  1445. } /* SetDialogState */
  1446.  
  1447. /*COMMENT***************************************************
  1448. ;DeHilite
  1449. Title:    Dehighlights the text in the client buffer
  1450. In:        none
  1451. Out:    none
  1452. Xin:    none
  1453. Xout:    none
  1454. Return:    none
  1455. Notes:    none
  1456. ***********************************************************/
  1457. static void DeHilite()
  1458. {
  1459.     WTQDEHILITEP inmsg = (WTQDEHILITEP)sndbuf;
  1460.     WTSTATUS status;
  1461.     
  1462.     inmsg->msgid = WTQ_DEHILITE;
  1463.     inmsg->count = 0;                    /* dehilite all */
  1464.     status = wtqTlSend(comm_id, WTQ_DEHILITE, sndbuf, sizeof(WTQ_DEHILITE),
  1465.         NULL, 0, WTR_DEHILITE, rcvbuf, sizeof(WTR_DEHILITE), NULL, 0);
  1466.     switch (status) {
  1467.         case WTS_OK:
  1468.             break;
  1469.         case WTS_COMERROR:
  1470.             XBell(XtDisplay(Server), 100);
  1471.             MsgBox(MB_OK, Server, "WTServer Error",
  1472.                 "Writing Tools API communication error!");
  1473.             ServerDestroyCB(0, 0, 0);
  1474.             break;
  1475.         default :
  1476.             XBell(XtDisplay(Server), 100);
  1477.             MsgBox(MB_OK, Server, "WTServer Error",
  1478.                 "Action could not be completed.");
  1479.             break;
  1480.     }
  1481.     return;
  1482. } /* DeHilite */
  1483.  
  1484. /*COMMENT***************************************************
  1485. ;NextWord
  1486. Title:    Get the next word from a phrase and increment pointer
  1487. In:        none
  1488. Out:    word - retrieved word
  1489. Xin:    none
  1490. Xout:    none
  1491. Return:    TRUE - another word was available, FALSE - no more words
  1492. Notes:    none
  1493. ***********************************************************/
  1494. static BOOL NextWord(char *word)
  1495. {
  1496.     WTQGOTOP ingoto;
  1497.     WTQHILITEP inlite;
  1498.     WTSTATUS status;
  1499.     
  1500.     for (;;) {                            /* loop until we get a word */
  1501.         for (txtbeg = txtend;            /* start at end of last word */
  1502.             (txtbeg < txtsize) && !isalpha(txtbuf[txtbeg]);
  1503.             txtbeg++) /* empty */;        /* locate start position of next word */
  1504.         if (txtbeg == txtsize) {        /* reached end of block */
  1505.             if (endflag == WTE_ENDQUERY) {
  1506.                 return FALSE;            /* no more text */
  1507.             } else {
  1508.                 NextBlock(0);            /* put next block at txtbuf[0] */
  1509.             }
  1510. #if 0
  1511. /*
  1512.  * This code handles the case where the client may send a partial word that
  1513.  * was truncated because it wouldn't fit in the block being sent.  If
  1514.  * this type of checking is desired then the server must keep track of
  1515.  * which block the text is in when identifying goto, highlight, and replacement
  1516.  * positions.
  1517.  */
  1518.         } else if ((endflag == WTE_FULL) && (txtsize - txtbeg) < WORDSIZE) {
  1519.             NextBlock(txtsize - txtbeg);
  1520. #endif
  1521.         } else {
  1522.             break;                        /* word is OK */
  1523.         }
  1524.     }
  1525.     for (txtend = txtbeg;
  1526.         (txtend < txtsize) && isalpha(txtbuf[txtend]);
  1527.         txtend++) /* empty */;            /* locate end postion of word */
  1528.     /* save word found */
  1529.     memcpy((char *)word, (char *)&txtbuf[txtbeg], (txtend - txtbeg));
  1530.     word[txtend - txtbeg] = 0x0;        /* null terminate word */
  1531.     /* goto the word in the client buffer and highlight it */
  1532.     ingoto = (WTQGOTOP)sndbuf;
  1533.     ingoto->msgid = WTQ_GOTO;
  1534.     ingoto->blockpos = WTP_REL;
  1535.     ingoto->blocknum = 0;                /* the current block */
  1536.     ingoto->offsetpos = WTP_END;
  1537.     ingoto->offsetloc = txtsize - txtbeg;
  1538.     status = wtqTlSend(comm_id, WTQ_GOTO, sndbuf, sizeof(WTQGOTO), NULL, 0,
  1539.                         WTR_GOTO, rcvbuf, sizeof(WTRGOTO), NULL, 0);
  1540.     switch (status) {
  1541.         case WTS_OK:
  1542.             break;
  1543.         case WTS_COMERROR:
  1544.             XBell(XtDisplay(Server), 100);
  1545.             MsgBox(MB_OK, Server, "WTServer Error",
  1546.                 "Writing Tools API communication error!");
  1547.             ServerDestroyCB(0, 0, 0);
  1548.             break;
  1549.         default :
  1550.             XBell(XtDisplay(Server), 100);
  1551.             MsgBox(MB_OK, Server, "WTServer Error",
  1552.                 "Action could not be completed.");
  1553.             break;
  1554.     }
  1555.     inlite = (WTQHILITEP)sndbuf;
  1556.     inlite->msgid = WTQ_HILITE;
  1557.     inlite->count = txtend - txtbeg;
  1558.     status = wtqTlSend(comm_id, WTQ_HILITE, sndbuf, sizeof(WTQHILITE), NULL, 0,
  1559.                         WTR_HILITE, rcvbuf, sizeof(WTRHILITE), NULL, 0);
  1560.     switch (status) {
  1561.         case WTS_OK:
  1562.             break;
  1563.         case WTS_COMERROR:
  1564.             XBell(XtDisplay(Server), 100);
  1565.             MsgBox(MB_OK, Server, "WTServer Error",
  1566.                 "Writing Tools API communication error!");
  1567.             ServerDestroyCB(0, 0, 0);
  1568.             break;
  1569.         default :
  1570.             XBell(XtDisplay(Server), 100);
  1571.             MsgBox(MB_OK, Server, "WTServer Error",
  1572.                 "Action could not be completed.");
  1573.             break;
  1574.     }
  1575.     return TRUE;
  1576. } /* NextWord */
  1577.  
  1578. /*COMMENT***************************************************
  1579. ;NextBlock
  1580. Title:    Retrieves the next block of text from the client.
  1581. In:        loc - location in current txtbuf to place the text
  1582. Out:    none
  1583. Xin:    none
  1584. Xout:    none
  1585. Return:    none
  1586. Notes:    none
  1587. ***********************************************************/
  1588. static void NextBlock(int loc)
  1589. {
  1590.     WTQNEXTTEXTBLOCKP inmsg;
  1591.     WTRTEXTBLOCKP rtmsg;
  1592.     WTSTATUS status;
  1593.     
  1594.     inmsg = (WTQNEXTTEXTBLOCKP)sndbuf;
  1595.     rtmsg = (WTRTEXTBLOCKP)rcvbuf;
  1596.     inmsg->msgid = WTQ_NEXTTEXTBLOCK;
  1597.     inmsg->size = TEXTSIZE;
  1598.     if (loc) {
  1599.         memcpy((char *)txtbuf, (char *)&txtbuf[txtsize - loc], loc);
  1600.     }
  1601.     status = wtqTlSend(comm_id, WTQ_NEXTTEXTBLOCK,
  1602.         sndbuf, sizeof(WTQNEXTTEXTBLOCK), NULL, 0, WTR_TEXTBLOCK,
  1603.         rcvbuf, sizeof(WTRTEXTBLOCK), txtbuf + loc, TEXTSIZE);
  1604.     switch (status) {
  1605.         case WTS_OK:
  1606.             break;
  1607.         case WTS_COMERROR:
  1608.             XBell(XtDisplay(Server), 100);
  1609.             MsgBox(MB_OK, Server, "WTServer Error",
  1610.                 "Writing Tools API communication error!");
  1611.             ServerDestroyCB(0, 0, 0);
  1612.             break;
  1613.         default :
  1614.             XBell(XtDisplay(Server), 100);
  1615.             MsgBox(MB_OK, Server, "WTServer Error",
  1616.                 "Action could not be completed.");
  1617.             break;
  1618.     }
  1619.     endflag = rtmsg->endblock;
  1620.     txtsize = (int)rtmsg->size + loc;
  1621.     txtbeg = txtend = 0;
  1622.     return;
  1623. } /* NextBlock */
  1624.  
  1625. /*COMMENT***************************************************
  1626. ;PutWords
  1627. Title:    Output the native and pig latin words to dialog
  1628. In:        natword = the native word
  1629.         pigword = the pig latin translation
  1630. Out:    none
  1631. Xin:    none
  1632. Xout:    none
  1633. Return:    none
  1634. Notes:    none
  1635. ***********************************************************/
  1636. static void PutWords(char *natword, char *pigword)
  1637. {
  1638.     XtVaSetValues(Word, XmNvalue, natword, NULL);
  1639.     XtVaSetValues(Translation, XmNvalue, pigword, NULL);
  1640. } /* PutWords */
  1641.  
  1642. /* FUNCTION ********************************************************
  1643. ;XLateAll
  1644. Title:    Translate a block of text
  1645. In:        oldword - old word
  1646.         newword - new word
  1647. Out:    none
  1648. Return:    none
  1649. Notes:
  1650. *******************************************************************/
  1651. static void XLateAll(char *oldword, char *newword)
  1652. {
  1653.     for (;;) {
  1654.         ReplaceWord(newword);            /* replace the current word */
  1655.         if (!NextWord(oldword)) {        /* get next word */
  1656.             break;
  1657.         }
  1658.         if (Mode == TL_TRANS_NATPIG) {
  1659.             NatToPig(oldword, newword);
  1660.         } else {
  1661.             PigToNat(oldword, newword);
  1662.         }
  1663.     }
  1664.     return;
  1665. } /* XLateAll */
  1666.  
  1667. /* FUNCTION ********************************************************
  1668. ;ReplaceWord
  1669. Title:    Replace inWord with outWord
  1670. In:        none
  1671. Out:    newword - the word you want placed in the document
  1672. Return:
  1673. Notes:    the document in the cursor must be positioned on the old word
  1674. *******************************************************************/
  1675. static void ReplaceWord(char *newword)
  1676. {
  1677.     WTQREPLACEP inmsg;
  1678.     WTSTATUS status;
  1679.     int oldlen, newlen;
  1680.     
  1681.     oldlen = txtend - txtbeg;            /* len of oldword */
  1682.     newlen = strlen(newword);            /* len of newword */
  1683.     /* wtapi replace */              
  1684.     inmsg = (WTQREPLACEP)sndbuf;
  1685.     inmsg->msgid = WTQ_REPLACE;            /* message id */
  1686.     inmsg->language.script = 0x00;       /* Roman */
  1687.     inmsg->language.language = 0x00;       /* English */
  1688.     inmsg->language.region = 0x0001;       /* U.S.A. */
  1689.     inmsg->depth = 0;                     /* relative depth of insertion */
  1690.     inmsg->count = oldlen;                 /* len of deleted word */
  1691.     inmsg->newblock = WT_FALSE;         
  1692.     inmsg->size = newlen;                /* len of inserted word */
  1693.     status = wtqTlSend(comm_id, WTQ_REPLACE, sndbuf, sizeof(WTQREPLACE),
  1694.                         (WTBUFP)newword, (WTSIZE)newlen,
  1695.                         WTR_REPLACE, rcvbuf, sizeof(WTRREPLACE),
  1696.                         NULL, 0);
  1697.     switch (status) {
  1698.         case WTS_OK:
  1699.             break;
  1700.         case WTS_COMERROR:
  1701.             XBell(XtDisplay(Server), 100);
  1702.             MsgBox(MB_OK, Server, "WTServer Error",
  1703.                 "Writing Tools API communication error!");
  1704.             ServerDestroyCB(0, 0, 0);
  1705.             break;
  1706.         default :
  1707.             XBell(XtDisplay(Server), 100);
  1708.             MsgBox(MB_OK, Server, "WTServer Error",
  1709.                 "Action could not be completed.");
  1710.             break;
  1711.     }
  1712.     return;
  1713. } /* ReplaceWord */
  1714.  
  1715. /* FUNCTION ********************************************************
  1716. ;PromptTranslateOptions
  1717. Title:    Translate a block of text
  1718. In:        pigword - pig latin word
  1719. Out:    none
  1720. Return:    none
  1721. Notes:    Assumes a valid pig latin word
  1722. *******************************************************************/
  1723. static void PromptTranslateOptions(char *pigword)
  1724. {
  1725.     Arg args[10];
  1726.     Cardinal argcnt;
  1727.     XmString xmstr;
  1728.     Atom deleteWindow;        /* for XmAddWMProtocol... */
  1729.     Widget    form,            /* form */
  1730.             wordlabel,        /* label for pig latin word box */
  1731.             wordbox,        /* box to display pig latin word */
  1732.             translabel,        /* label for list of translations */
  1733.             separator,        /* separator */
  1734.             button;            /* OK button */
  1735.     int cons;                /* position of consonant for start of option word */
  1736.     int len;                /* length of pigword */
  1737.     char *p, *q;            /* pointers */
  1738.     char oldword[BUFSIZE];    /* copy of pigword */
  1739.     char newword[BUFSIZE];    /* possible translation word */
  1740.     int cnt;                /* number of option words */
  1741.     XEvent event;
  1742.  
  1743.     len = strlen(pigword);
  1744.     if (len < 3) {
  1745.         return;        /* can't be a valid pig latin word */
  1746.     }
  1747.  
  1748.     argcnt = 0;
  1749.     XtSetArg(args[argcnt], XtNtitle, "Select a Translation");
  1750.     argcnt++;
  1751.     form = XmCreateFormDialog(Server, "trform", args, argcnt);
  1752.     TransOpts = XtParent(form);
  1753.     XtAddCallback(TransOpts, XmNdestroyCallback, TransOptCB, 0);
  1754.     deleteWindow = XmInternAtom(XtDisplay(TransOpts), "WM_DELETE_WINDOW",False);
  1755.     XmAddWMProtocols(TransOpts, &deleteWindow, 1);
  1756.     XmAddWMProtocolCallback(TransOpts, deleteWindow, TransOptCB, 0);
  1757.     /*
  1758.      * Create the Pig Latin Word label and box.
  1759.      */
  1760.     wordlabel = XtVaCreateManagedWidget("wordlabel",
  1761.         xmLabelWidgetClass, form,
  1762.         XmNlabelString, xmstr = StringCreate("Pig Latin Word:"),
  1763.         XmNtopAttachment, XmATTACH_FORM,
  1764.         XmNtopOffset, 10,
  1765.         XmNleftAttachment, XmATTACH_FORM,
  1766.         XmNleftOffset, 10,
  1767.         XmNfontList, FontList,
  1768.         NULL);
  1769.     XmStringFree(xmstr);
  1770.     wordbox = XtVaCreateManagedWidget("wordbox",
  1771.         xmTextWidgetClass, form,
  1772.         XmNrows, 1,
  1773.         XmNcolumns, 25,
  1774.         XmNvalue, pigword,
  1775.         XmNeditable, False,
  1776.         XmNbackground, WhitePixelOfScreen(XtScreen(form)),
  1777.         XmNtopAttachment, XmATTACH_WIDGET,
  1778.         XmNtopWidget, wordlabel,
  1779.         XmNtopOffset, 2,
  1780.         XmNleftAttachment, XmATTACH_FORM,
  1781.         XmNleftOffset, 10,
  1782.         XmNrightAttachment, XmATTACH_FORM,
  1783.         XmNrightOffset, 10,
  1784.         XmNfontList, FontList,
  1785.         NULL);
  1786.     /*
  1787.      * Create the Translation label and list.
  1788.      */
  1789.     translabel = XtVaCreateManagedWidget("translabel",
  1790.         xmLabelWidgetClass, form,
  1791.         XmNlabelString, xmstr = StringCreate("Select a Translation:"),
  1792.         XmNtopAttachment, XmATTACH_WIDGET,
  1793.         XmNtopWidget, wordbox,
  1794.         XmNtopOffset, 10,
  1795.         XmNleftAttachment, XmATTACH_FORM,
  1796.         XmNleftOffset, 10,
  1797.         XmNfontList, FontList,
  1798.         NULL);
  1799.     XmStringFree(xmstr);
  1800.     TransList = XtVaCreateManagedWidget("translist",
  1801.         xmListWidgetClass, form,
  1802.         XmNvisibleItemCount, 5,
  1803.         XmNcolumns, 25,
  1804.         XmNvalue, pigword,
  1805.         XmNeditable, False,
  1806.         XmNbackground, WhitePixelOfScreen(XtScreen(form)),
  1807.         XmNtopAttachment, XmATTACH_WIDGET,
  1808.         XmNtopWidget, translabel,
  1809.         XmNtopOffset, 2,
  1810.         XmNleftAttachment, XmATTACH_FORM,
  1811.         XmNleftOffset, 10,
  1812.         XmNrightAttachment, XmATTACH_OPPOSITE_WIDGET,
  1813.         XmNrightWidget, wordbox,
  1814.         XmNrightOffset, 0,
  1815.         XmNfontList, FontList,
  1816.         NULL);
  1817.     XtAddCallback(TransList, XmNdefaultActionCallback, TransOptCB, (XtPointer)1);
  1818.     /*
  1819.      * Create separator.
  1820.      */
  1821.     separator = XtVaCreateManagedWidget("sep",
  1822.         xmSeparatorWidgetClass, form,
  1823.         XmNtopAttachment, XmATTACH_WIDGET,
  1824.         XmNtopWidget, TransList,
  1825.         XmNtopOffset, 10,
  1826.         XmNleftAttachment, XmATTACH_FORM,
  1827.         XmNleftOffset, 0,
  1828.         XmNrightAttachment, XmATTACH_FORM,
  1829.         XmNrightOffset, 0,
  1830.         NULL);
  1831.     /*
  1832.      * Create the OK button.
  1833.      */
  1834.     button = XtVaCreateManagedWidget("OK",
  1835.         xmPushButtonWidgetClass, form,
  1836.         XmNlabelString, xmstr = StringCreate("OK"),
  1837.         XmNmarginLeft, 40,
  1838.         XmNmarginRight, 40,
  1839.         XmNtopAttachment, XmATTACH_WIDGET,
  1840.         XmNtopWidget, separator,
  1841.         XmNtopOffset, 10,
  1842.         XmNleftAttachment, XmATTACH_FORM,
  1843.         XmNleftOffset, 60,
  1844.         XmNbottomAttachment, XmATTACH_FORM,
  1845.         XmNbottomOffset, 10,
  1846.         XmNfontList, FontList,
  1847.         NULL);
  1848.     XmStringFree(xmstr);
  1849.     XtAddCallback(button, XmNactivateCallback, TransOptCB, (XtPointer)1);
  1850.     /*
  1851.      * Build the options list.  The alogrithm is:
  1852.      *    1. If the consonant immediately preceding "ay" is an 'h', then include
  1853.      *        the word created by simply stripping "hay" from the end.
  1854.      *    2. For each consonant before the trailing "ay" up to previous vowel:
  1855.      *      a. Put consonant and any trailing consonants up to "ay" at
  1856.      *            beginning of word.
  1857.      *        b. Concatenate the remainder of word (from beginning up to the
  1858.      *            beginning consonant being used) after these initial consonants.
  1859.      *        c. Add word to list.
  1860.      */
  1861.     cnt = 0;
  1862.     if (pigword[len-3] == 'h') {
  1863.         strcpy(newword, pigword);
  1864.         newword[len-3] = 0;
  1865.         XmListAddItem(TransList, xmstr = StringCreate(newword), 0);
  1866.         XmStringFree(xmstr);
  1867.         cnt++;
  1868.     }
  1869.     for (cons = len-3; !isvowel(pigword[cons]); cons--) {
  1870.         strcpy(oldword, pigword);
  1871.         q = &oldword[cons];
  1872.         p = newword;
  1873.         while (*q && !isvowel(*q)) {
  1874.             *p++ = *q++;
  1875.         }
  1876.         *p = 0;
  1877.         oldword[cons] = 0;
  1878.         strcat(newword, oldword);
  1879.         XmListAddItem(TransList, xmstr = StringCreate(newword), 0);
  1880.         XmStringFree(xmstr);
  1881.         cnt++;
  1882.     }
  1883.     /* select first item in list */
  1884.     if (cnt < 1) {
  1885.         MsgBox(MB_OK, Server, "WTServer Error", "Not a Valid Pig Latin Word!");
  1886.         XtDestroyWidget(TransOpts);
  1887.         return;
  1888.     } else {
  1889.         XmListSelectPos(TransList, 1, True);    /* select first item */
  1890.     }
  1891.     /*
  1892.      * Pop up the dialog.
  1893.      */
  1894.     XtManageChild(form);
  1895.     /*
  1896.      *  Loop processing events until the user is finished with this dialog.
  1897.      */
  1898.     for (;;) {
  1899.         XtAppNextEvent(XtWidgetToApplicationContext(Server), &event);
  1900.         XtDispatchEvent(&event);
  1901.         if (!TransOpts) {
  1902.             break;
  1903.         }
  1904.     }
  1905. } /* PromptTranslateOptions */
  1906.  
  1907. /*COMMENT***************************************************
  1908. ;TransOptCB
  1909. Title:     OK callback for Translation Options dialog
  1910. In:        cldata - 0 = destroy callback, 1 = OK or default action callback
  1911. Out:    none
  1912. Return:    none
  1913. Xin:    none
  1914. Xout:    gbuf - selected translation word
  1915. Notes:
  1916. ***********************************************************/
  1917. static void TransOptCB(Widget w, XtPointer cldata, XtPointer cbdata)
  1918. {
  1919.     int *lst = 0;    /* list of selected items in list */
  1920.     int cnt = 0;    /* number of selected items in list */
  1921.     XmStringTable items = 0;    /* items in list */
  1922.     char *word;        /* selected word from list */
  1923.  
  1924.     if (TransOpts) {
  1925.         /*
  1926.          * Get selected item.
  1927.          */
  1928.         if (!XmListGetSelectedPos(TransList, &lst, &cnt) ||
  1929.             !lst || (cnt != 1))
  1930.         {
  1931.             if (lst) {
  1932.                 XtFree((char *)lst);
  1933.             }
  1934.             gbuf[0] = 0;
  1935.             return;        /* no item selected */
  1936.         }
  1937.         XtVaGetValues(TransList, XmNitems, &items, NULL);
  1938.         word = XmStringToString(items[lst[0]-1]);
  1939.         XtFree((char *)lst);
  1940.         if (word) {
  1941.             strcpy(gbuf, word);
  1942.             free(word);
  1943.         } else {
  1944.             gbuf[0] = 0;
  1945.         }
  1946.  
  1947.         XtDestroyWidget(TransOpts);
  1948.     }
  1949.     TransOpts = 0;
  1950. } /* TransOptCB */
  1951.  
  1952. /* FUNCTION ********************************************************
  1953. ;isvowel
  1954. Title:    Check if a character is a vowel (not including 'y')
  1955. In:        c - character to check
  1956. Out:    none
  1957. Return:    none
  1958. Notes:
  1959. *******************************************************************/
  1960. static BOOL isvowel(char c)
  1961. {
  1962.     return ((c == 'a') || (c == 'A') || 
  1963.         (c == 'e') || (c == 'E') || 
  1964.         (c == 'i') || (c == 'I') || 
  1965.         (c == 'o') || (c == 'O') || 
  1966.         (c == 'u') || (c == 'U'));
  1967. } /* isvowel */
  1968.