home *** CD-ROM | disk | FTP | other *** search
- /* SOURCE FILE *****************************************************
- * WTCLIENT.C - Writing Tools API Client Sample Application
- *******************************************************************
- * Copyright (C) 1993 WordPerfect Corp., All Rights Reserved
- *******************************************************************/
-
- #include "wtclient.h"
- #include "wtclient.xbm" /* icon bitmap */
-
- #include <X11/cursorfont.h>
- #include <Xm/Xm.h>
- #include <Xm/CascadeB.h>
- #include <Xm/CutPaste.h>
- #include <Xm/Form.h>
- #include <Xm/Protocols.h>
- #include <Xm/PushB.h>
- #include <Xm/RowColumn.h>
- #include <Xm/Separator.h>
- #include <Xm/Text.h>
- #include <unistd.h>
-
- #include <wtapi.h>
- #include <wtcomm.h>
-
- #define WT_INVOKE_MODE 0
-
- /*----------------------------------------------------------
- External Variables
- ------------------------------------------------------------*/
- extern WTCOMM commHandle; /* conversation/comm. handle */
- extern BOOL Dirty; /* has the file been modified */
-
- /*----------------------------------------------------------
- External Functions
- ------------------------------------------------------------*/
- void quitTool(char *);
- void FileMenuProc(Widget, CL_FILE);
- XmString StringCreate(char *);
- void NormalCursor(Widget);
- void WaitCursor(Widget);
- BOOL MsgBox(MSGBOX, Widget parent, char *, char *);
- void ReportError(char *);
- WTCOMM WtConnect(Widget, char *);
- void WtDisconnect(WTCOMM);
- /* char *getcwd(char *, int); */
- char *getenv(char *);
- WTSTATUS WTCInitSend(WTCOMM comm, WTCINITP msg);
-
- /*----------------------------------------------------------
- Menu Definitions
- ------------------------------------------------------------*/
- /* File menu items */
- static char *ClFileStr[] = {
- "New", "Open...", "Save", "Save As...", "Print", "Exit", 0
- };
- static char ClFileMne[] = {
- 'N', 'O', 'S', 'A', 'P', 'x', 0
- };
-
- /* Edit menu items */
- static char *ClEditStr[] = {
- "Undo", "Cut", "Copy", "Paste", 0
- };
- static char ClEditMne[] = {
- 'U', 't', 'C', 'P', 0
- };
-
- /* Help menu items */
- static char *ClHelpStr[] = {
- "About WTClient...", 0
- };
- static char ClHelpMne[] = {
- 'A', 0
- };
-
- /*----------------------------------------------------------
- Internal Variables
- ------------------------------------------------------------*/
- WTPTR wtsess;
- Widget Client;
- XmFontList FontList;
- static Cursor waitcursor = (Cursor) 0;
- static Cursor normalcursor = (Cursor) 0;
- static Pixmap Icon; /* Icon for sample client application */
- static Widget Text; /* Text widget for client */
- static Widget editButtons[CL_EDIT_CNT]; /* Edit menu buttons */
- static Widget toolButtons[MAXTOOLS]; /* Tool menu buttons */
- static TOOLRECORD toolRecords[MAXTOOLS]; /* writing tool records */
- static int toolCount; /* number of tools on menu */
- static char *prevText; /* text before previous edit */
- static XmTextPosition prevSelLeft = 0xff, /* previous selection */
- prevSelRight = 0;
- static BOOL toolRunning = False; /* is a tool currently running? */
- static WTCONTEXT sessionMem;
-
- /*----------------------------------------------------------
- Internal Functions
- ------------------------------------------------------------*/
- char *GetBuffer();
- WTSTATUS GetText(WTUNIT, WTPOS, WTCOUNT, WTUNIT, WTPOS, WTCOUNT, WTTBQTYPE,
- WTSIZE, WTTBQTYPE *, WTBUFP, WTSIZE *);
- unsigned SelectedLen(void);
- WTSTATUS GoToPos(WTPOS, WTCOUNT, WTPOS, WTCOUNT, unsigned *);
- WTCOUNT ReplaceText(WTCOUNT, WTSIZE, WTBUFP);
- unsigned FindCurrBlock(unsigned);
- void NativeToWord(WTBUFP, WTSIZE *);
- void WordToNative(WTBUFP, WTSIZE *);
-
- static void ClientInit(Widget);
- static void ClientDestroyCB(Widget, XtPointer, XtPointer);
- static void ClientExit();
- static void FileCB(Widget, XtPointer, XtPointer);
- static void EditCB(Widget, XtPointer, XmAnyCallbackStruct *);
- static void SetEditButtons(Widget, XtPointer, XtPointer);
- static void ToolsCB(Widget, XtPointer, XtPointer);
- static void HelpCB(Widget, XtPointer, XtPointer);
- static void TextCB(Widget, XtPointer, XtPointer);
- static void free_cursors(Widget);
- static void SetToolsMenu(BOOL);
- static BOOL launchTool(int);
- static BOOL ClInvokeWritingTool(int, short);
- static void SetCaretPos(int);
- static void updateDeleteCount(unsigned, unsigned, unsigned);
- static void updateInsertCount(unsigned, unsigned);
-
- /*COMMENT***************************************************
- ;main
- Title: WTAPI Sample Client Main Function
- In: argc, argv
- Out: none
- Xin: none
- Xout: none
- Return: exit status
- Notes:
- ***********************************************************/
- main(int argc, char *argv[])
- {
- XtAppContext appcontext;
- Widget toplevel;
-
- toplevel = XtVaAppInitialize(&appcontext, "WTClient",
- NULL, 0, &argc, (char **)argv, NULL,
- XmNallowShellResize, True,
- NULL);
- ClientInit(toplevel);
- XtAppMainLoop(appcontext);
- } /* main */
-
- /*COMMENT***************************************************
- ;ClientInit
- Title: Initialize WTAPI Sample Client Application
- In: toplevel - toplevel widget of application
- Out: none
- Xin: none
- Xout: none
- Return: none
- Notes:
- ***********************************************************/
- static void ClientInit(Widget toplevel)
- {
- Arg args[20];
- Cardinal argcnt;
- Atom deleteWindow; /* for XmAddWMProtocol... */
- XmString xmstr; /* Motif compound string */
- Widget form, /* main Client form */
- menubar, /* menu bar */
- button, /* cascade or push button */
- pd, /* pulldown menu */
- separator; /* separator */
- CL_FILE file; /* loop variable */
- CL_EDIT edit; /* loop variable */
- CL_HELP help; /* loop variable */
- int tool; /* loop variable */
- XFontStruct *font;
-
- /*
- * Set up icon and dialog destroy callbacks for main Client window.
- */
- Client = toplevel;
- Icon = XCreateBitmapFromData(XtDisplay(toplevel),
- RootWindowOfScreen(XtScreen(toplevel)),
- wtclient_bits, wtclient_width, wtclient_height);
- XtVaSetValues(Client,
- XtNtitle, "WTAPI Sample Client Application",
- XmNiconName, "WTClient",
- XmNiconPixmap, Icon,
- XmNdeleteResponse, XmDO_NOTHING,
- NULL);
- XtAddCallback(Client, XmNdestroyCallback, ClientDestroyCB, 0);
- deleteWindow = XmInternAtom(XtDisplay(Client), "WM_DELETE_WINDOW", False);
- XmAddWMProtocols(Client, &deleteWindow, 1);
- XmAddWMProtocolCallback(Client, deleteWindow, ClientDestroyCB, 0);
- /*
- * Create the main Client form.
- */
- FontList = NULL;
- if (font = XLoadQueryFont(XtDisplay(Client),
- "-adobe-helvetica-medium-r-normal--14-100-100-100-p-76-iso8859-1"))
- {
- FontList = XmFontListCreate(font, XmSTRING_DEFAULT_CHARSET);
- }
- form = XtVaCreateManagedWidget("clform", xmFormWidgetClass, Client,
- XmNfontList, FontList,
- NULL);
- /*
- * Create the menu bar.
- */
- menubar = XmCreateMenuBar(form, "clmenu", 0, 0);
- /*
- * Create the File menu.
- */
- button = XtVaCreateManagedWidget("clfile",
- xmCascadeButtonWidgetClass, menubar,
- XmNlabelString, xmstr = StringCreate("File"),
- XmNmnemonic, 'F',
- XmNsubMenuId, pd = XmCreatePulldownMenu(menubar, "clFilePD", 0, 0),
- XmNfontList, FontList,
- NULL);
- XmStringFree(xmstr);
- for (file = CL_FILE_NEW; file < CL_FILE_CNT; file++) {
- if (file == CL_FILE_EXIT) {
- separator = XtVaCreateManagedWidget("sep",
- xmSeparatorWidgetClass, pd,
- NULL);
- }
- button = XtVaCreateManagedWidget(ClFileStr[file],
- xmPushButtonWidgetClass, pd,
- XmNlabelString, xmstr = StringCreate(ClFileStr[file]),
- XmNmnemonic, ClFileMne[file],
- XmNvisibleWhenOff, True,
- XmNsensitive, True,
- XmNfontList, FontList,
- NULL);
- XmStringFree(xmstr);
- XtAddCallback(button, XmNactivateCallback, FileCB, (XtPointer)(int)file);
- }
- /*
- * Create the Edit menu.
- */
- button = XtVaCreateManagedWidget("cledit",
- xmCascadeButtonWidgetClass, menubar,
- XmNlabelString, xmstr = StringCreate("Edit"),
- XmNmnemonic, 'E',
- XmNsubMenuId, pd = XmCreatePulldownMenu(menubar, "clEditPD", 0, 0),
- XmNfontList, FontList,
- NULL);
- XmStringFree(xmstr);
- XtAddCallback(button, XmNcascadingCallback, SetEditButtons, 0);
- for (edit = CL_EDIT_UNDO; edit < CL_EDIT_CNT; edit++) {
- editButtons[edit] = button = XtVaCreateManagedWidget(ClEditStr[edit],
- xmPushButtonWidgetClass, pd,
- XmNlabelString, xmstr = StringCreate(ClEditStr[edit]),
- XmNmnemonic, ClEditMne[edit],
- XmNvisibleWhenOff, True,
- XmNsensitive, True,
- XmNfontList, FontList,
- NULL);
- XmStringFree(xmstr);
- XtAddCallback(button, XmNactivateCallback, (XtCallbackProc)EditCB, (XtPointer)(int)edit);
- if (edit == CL_EDIT_UNDO) {
- separator = XtVaCreateManagedWidget("sep",
- xmSeparatorWidgetClass, pd,
- NULL);
- }
- }
- /*
- * Create the Tools menu.
- */
- button = XtVaCreateManagedWidget("cltools",
- xmCascadeButtonWidgetClass, menubar,
- XmNlabelString, xmstr = StringCreate("Tools"),
- XmNmnemonic, 'T',
- XmNsubMenuId, pd = XmCreatePulldownMenu(menubar, "clToolsPD", 0, 0),
- XmNfontList, FontList,
- NULL);
- XmStringFree(xmstr);
- if (GetToolsInfo(toolRecords, &toolCount)) {
- for (tool = 0; tool < toolCount; tool++) {
- toolButtons[tool] =
- button = XtVaCreateManagedWidget(toolRecords[tool].menu,
- xmPushButtonWidgetClass, pd,
- XmNlabelString, xmstr = StringCreate(toolRecords[tool].menu),
- XmNmnemonic, toolRecords[tool].mne,
- XmNvisibleWhenOff, True,
- XmNsensitive, True,
- XmNfontList, FontList,
- NULL);
- XmStringFree(xmstr);
- XtAddCallback(button, XmNactivateCallback, ToolsCB, (XtPointer)tool);
- }
- }
- /*
- * Create the Help menu.
- */
- button = XtVaCreateManagedWidget("clhelp",
- xmCascadeButtonWidgetClass, menubar,
- XmNlabelString, xmstr = StringCreate("Help"),
- XmNmnemonic, 'H',
- XmNsubMenuId, pd = XmCreatePulldownMenu(menubar, "clHelpPD", 0, 0),
- XmNfontList, FontList,
- NULL);
- XtVaSetValues(menubar,
- XmNmenuHelpWidget, button,
- NULL);
- XmStringFree(xmstr);
- for (help = CL_HELP_ABOUT; help < CL_HELP_CNT; help++) {
- button = XtVaCreateManagedWidget(ClHelpStr[help],
- xmPushButtonWidgetClass, pd,
- XmNlabelString, xmstr = StringCreate(ClHelpStr[help]),
- XmNmnemonic, ClHelpMne[help],
- XmNvisibleWhenOff, True,
- XmNsensitive, True,
- XmNfontList, FontList,
- NULL);
- XmStringFree(xmstr);
- XtAddCallback(button, XmNactivateCallback, HelpCB, (XtPointer)(int)help);
- }
- XtVaSetValues(menubar,
- XmNtopAttachment, XmATTACH_FORM,
- XmNtopOffset, 0,
- XmNleftAttachment, XmATTACH_FORM,
- XmNleftOffset, 0,
- XmNrightAttachment, XmATTACH_FORM,
- XmNrightOffset, 0,
- NULL);
- XtManageChild(menubar);
- /*
- * Create the text box.
- */
- argcnt = 0;
- XtSetArg(args[argcnt], XmNeditMode, XmMULTI_LINE_EDIT); argcnt++;
- XtSetArg(args[argcnt], XmNcolumns, 60); argcnt++;
- XtSetArg(args[argcnt], XmNrows, 15); argcnt++;
- XtSetArg(args[argcnt], XmNbackground,
- WhitePixelOfScreen(XtScreen(form))); argcnt++;
- XtSetArg(args[argcnt], XmNtopAttachment, XmATTACH_WIDGET); argcnt++;
- XtSetArg(args[argcnt], XmNtopWidget, menubar); argcnt++;
- XtSetArg(args[argcnt], XmNtopOffset, 0); argcnt++;
- XtSetArg(args[argcnt], XmNleftAttachment, XmATTACH_FORM); argcnt++;
- XtSetArg(args[argcnt], XmNleftOffset, 0); argcnt++;
- XtSetArg(args[argcnt], XmNrightAttachment, XmATTACH_FORM); argcnt++;
- XtSetArg(args[argcnt], XmNrightOffset, 0); argcnt++;
- XtSetArg(args[argcnt], XmNbottomAttachment, XmATTACH_FORM); argcnt++;
- XtSetArg(args[argcnt], XmNbottomOffset, 0); argcnt++;
- XtSetArg(args[argcnt], XmNfontList, FontList); argcnt ++;
- Text = XmCreateScrolledText(form, "cltext", args, argcnt);
- XtAddCallback(Text, XmNvalueChangedCallback, TextCB, 0);
- XtUnmanageChild(XtParent(Text));
- XtManageChild(Text);
- XtManageChild(XtParent(Text));
- /*
- * Pop up the Client dialog.
- */
- XtPopup(Client, XtGrabNone);
- } /* ClientInit */
-
- /*COMMENT***************************************************
- ;ClientDestroyCB
- Title: Handle destroy of Client dialog.
- In: none
- Out: none
- Xin: none
- Xout: none
- Return: none
- Notes:
- ***********************************************************/
- static void ClientDestroyCB(Widget w, XtPointer cldata, XtPointer cbdata)
- {
- if (toolRunning) {
- WtDisconnect(commHandle);
- }
- if (FontList) {
- XmFontListFree(FontList);
- }
- if (Icon) {
- XFreePixmap(XtDisplayOfObject(Client), Icon); /* free pixmap */
- }
- free_cursors(Client);
- Client = 0;
- ClientExit(); /* clean up and exit client */
- } /* ClientDestroyCB */
-
- /*COMMENT***************************************************
- ;ClientExit
- Title: Clean up and exit WTAPI Sample Application
- In: none
- Out: none
- Xin: none
- Xout: none
- Return: none
- Notes:
- ***********************************************************/
- static void ClientExit()
- {
- exit(0);
- } /* ClientExit */
-
- /*COMMENT***************************************************
- ;StringCreate
- Title: Initialize WTAPI Sample Application
- In: toplevel - toplevel widget of application
- Out: none
- Xin: none
- Xout: none
- Return: none
- Notes:
- ***********************************************************/
- XmString StringCreate(char *str)
- {
- return(XmStringCreateLtoR(str, XmSTRING_DEFAULT_CHARSET));
- } /* StringCreate */
-
- /*COMMENT***************************************************
- ;FileCB
- Title: File menu actions.
- In: cldata - File action to perform
- Out: none
- Xin: Client - toplevel Client widget
- Xout: none
- Return: none
- Notes:
- ***********************************************************/
- static void FileCB(Widget w, XtPointer cldata, XtPointer cbdata)
- {
- CL_FILE file = (CL_FILE)(int)cldata; /* which file action to perform */
- FileMenuProc(Client, file);
- } /* FileCB */
-
- /*COMMENT***************************************************
- ;EditCB
- Title: File menu actions.
- In: cldata - Edit action to perform
- Out: none
- Xin: Client - toplevel Client widget
- Xout: none
- Return: none
- Notes:
- ***********************************************************/
- static void EditCB(Widget w, XtPointer cldata, XmAnyCallbackStruct *cbdata)
- {
- CL_EDIT edit = (CL_EDIT)(int)cldata; /* which edit action to perform */
- Time time = cbdata->event->xbutton.time;
- char *txt, *prevtxt = 0;
- XmTextPosition prevleftsel = 0, prevrightsel = 0;
- int status = 0; /* status of call to clipboard routines */
- int len = 0; /* length of text in clipboard */
- BOOL changed = FALSE; /* did text change? */
-
- /*
- * If UNDO then we need to save the previous text and selection before
- * we update them to be the current text and selection.
- */
- if (edit == CL_EDIT_UNDO) {
- if (prevText) {
- prevtxt = prevText; /* use the same pointer */
- prevText = 0; /* we'll allocate more space for this later */
- }
- prevleftsel = prevSelLeft;
- prevrightsel = prevSelRight;
- }
- /*
- * Save the current text and selection as the previous text and selection
- * for possible use with UNDO later.
- */
- if (prevText) {
- XtFree(prevText);
- }
- prevText = XmTextGetString(Text);
- if (!XmTextGetSelectionPosition(Text, &prevSelLeft, &prevSelRight)) {
- prevSelLeft = prevSelRight = 0;
- }
- /*
- * Perform the Edit action.
- */
- switch (edit) {
- case CL_EDIT_UNDO: /* Undo */
- if (prevtxt) {
- XmTextSetString(Text, prevtxt);
- XtFree(prevtxt);
- if (prevleftsel < prevrightsel) {
- XmTextSetSelection(Text, prevleftsel, prevrightsel, time);
- }
- } else {
- XmTextSetString(Text, "");
- XmTextClearSelection(Text, time);
- }
- break;
- case CL_EDIT_CUT: /* Cut */
- if (!XmTextCut(Text, time)) {
- XBell(XtDisplay(Text), 100); /* beep */
- }
- break;
- case CL_EDIT_COPY: /* Copy */
- if (!XmTextCopy(Text, time)) {
- XBell(XtDisplay(Text), 100); /* beep */
- }
- break;
- case CL_EDIT_PASTE: /* Paste */
- if (!XmTextPaste(Text)) {
- XBell(XtDisplay(Text), 100); /* beep */
- }
- break;
- default: /* unrecognized action */
- break; /* do nothing */
- }
- } /* EditCB */
-
- /*COMMENT***************************************************
- ;SetEditButtons
- Desc: Set the sensitivity on the Edit buttons.
- In: none
- Out: none
- Xin: none
- Xout: none
- Return: none
- ***********************************************************/
- static void SetEditButtons(Widget w, XtPointer cldata, XtPointer cbdata)
- {
- char *sel; /* selected text */
- int status = 0; /* status of call to clipboard routines */
- int length = 0; /* length of text in clipboard */
-
- /*
- * If no edits yet then turn Undo off.
- */
- if (prevSelLeft == 0xff && prevSelRight == 0) {
- XtSetSensitive(editButtons[CL_EDIT_UNDO], False);
- } else {
- XtSetSensitive(editButtons[CL_EDIT_UNDO], True);
- }
- /*
- * If there is selected text in the box then turn on Cut and Copy.
- */
- sel = XmTextGetSelection(Text);
- if (sel && *sel) {
- XtSetSensitive(editButtons[CL_EDIT_CUT], True);
- XtSetSensitive(editButtons[CL_EDIT_COPY], True);
- } else {
- XtSetSensitive(editButtons[CL_EDIT_CUT], False);
- XtSetSensitive(editButtons[CL_EDIT_COPY], False);
- }
- if (sel) {
- XtFree(sel);
- }
- /*
- * Turn Paste on if there is text in the clipboard.
- */
- do {
- status = XmClipboardInquireLength(XtDisplay(w), XtWindow(w),
- "STRING", &length);
- } while (status == ClipboardLocked);
- if ((status != ClipboardNoData) && (length > 0)) {
- XtSetSensitive(editButtons[CL_EDIT_PASTE], True);
- } else {
- XtSetSensitive(editButtons[CL_EDIT_PASTE], False);
- }
- } /* SetEditButtons */
-
- /*COMMENT***************************************************
- ;HelpCB
- Title: Help menu actions.
- In: cldata - Help action to perform
- Out: none
- Xin: Client - toplevel Client widget
- Xout: none
- Return: none
- Notes:
- ***********************************************************/
- static void HelpCB(Widget w, XtPointer cldata, XtPointer cbdata)
- {
- CL_HELP help = (CL_HELP)(int)cldata; /* which help action to perform */
- switch (help) {
- case CL_HELP_ABOUT:
- MsgBox(MB_OK, Client, "About WTClient",
- "Writing Tools API\nSample Client Application\n\nVersion 0.6");
- break;
- default: /* unrecognized action */
- break; /* do nothing */
- }
- } /* HelpCB */
-
- /*COMMENT***************************************************
- ;ToolsCB
- Title: Tools menu actions.
- In: cldata - which Tool to invoke
- Out: none
- Xin: Client - toplevel Client widget
- Xout: none
- Return: none
- Notes:
- ***********************************************************/
- static void ToolsCB(Widget w, XtPointer cldata, XtPointer cbdata)
- {
- int tool = (int)cldata; /* which tool to invoke */
- if (!launchTool(tool)) {
- quitTool(0);
- }
- } /* ToolsCB */
-
- /*COMMENT********************************************************
- ;ReportError
- Title: To report an error that has occurred while allocating memory for
- the CD struct, locking the memory or while trying to load a
- resource string.
- In: wErrorType
- Out: none
- Return: none
- Notes:
- *****************************************************************/
- void ReportError(char *message)
- {
- MsgBox(MB_OK, Client, "WTClient - Error", message);
- } /* ReportError */
-
- /*COMMENT********************************************************
- ;SetToolsMenu
- Title: To report an error that has occurred while allocating memory for
- the CD struct, locking the memory or while trying to load a
- resource string.
- In: wErrorType
- Out: none
- Return: none
- Notes:
- *****************************************************************/
- static void SetToolsMenu(BOOL state)
- {
- int tool;
-
- for (tool = 0; tool < toolCount; tool++) {
- XtSetSensitive(toolButtons[tool], state);
- }
- } /* SetToolsMenu */
-
- /*COMMENT***************************************************
- ;launchTool
- Title: Launch a writing tool
- In: toolPos - tool position in tool record array
- Out: none
- Xin: none
- Xout: Dirty, hEditWnd
- Return: NULL
- Notes:
- ***********************************************************/
- static BOOL launchTool(int tool)
- {
- WTCINIT inmsg;
- WTSTATUS status;
-
- if (!ClInvokeWritingTool(tool, WT_INVOKE_MODE)) {
- return FALSE;
- }
- toolRunning = TRUE;
- SetToolsMenu(FALSE); /* disable tools menu */
- wtsess = &sessionMem;
- wtsess->lastBlock = -1;
- wtsess->currBlock = -1;
- wtsess->absPos = 0;
-
- /* send WTC_INIT message */
- inmsg.msgid = WTC_INIT;
- inmsg.mode = WTM_NORMAL;
- inmsg.version = WTAPI_VERSION;
- inmsg.windowClient = XtWindow(Client);
- status = WTCInitSend(commHandle, &inmsg);
- if (status != WTS_OK) {
- ReportError("Send of WTC_INIT from client to tool FAILED");
- }
- return TRUE;
- } /* launchTool */
-
- /*COMMENT***************************************************
- ;quitTool
- Title: Quit a writing tool
- In: msg - output this message when quitting the tool
- Out: none
- Xin: none
- Xout: none
- Return: NULL
- Notes:
- ***********************************************************/
- void quitTool(char *msg)
- {
- if (toolRunning) {
- WtDisconnect(commHandle);
- toolRunning = FALSE;
- }
- commHandle = 0;
- wtsess = 0x0;
- SetToolsMenu(TRUE); /* enable tools menu */
- if (msg) {
- ReportError(msg);
- }
- return;
- } /* quitTool */
-
- /*COMMENT***************************************************
- ;GetText
- Title: Get text to send to tool
- In: startUnit - text unit to position from
- startPos - type of positioning
- startLoc - distance to desired position
- endUnit - text unit to end at
- endPos - type of positioning
- endLoc - distance to desired position
- type - request type ie. WTB_INIT, WTB_RESUME
- maxSize - maximum size of return buffer
- buffer - return buffer
- Out: endType - end of buffer condition
- Return: size of text in buffer
- Notes:
- ***********************************************************/
- WTSTATUS GetText(WTUNIT startUnit, WTPOS startPos, WTCOUNT startLoc,
- WTUNIT endUnit, WTPOS endPos, WTCOUNT endLoc,
- WTTBQTYPE type, WTSIZE maxSize, WTTBQTYPE *endType,
- WTBUFP buffer, WTSIZE *len)
- {
- XmTextPosition start, end; /* start/end of text to get */
- XmTextPosition left, right; /* left/right position of selection */
- char *editBuffer; /* pointer to edit buffer */
- char c;
-
- editBuffer = GetBuffer(); /* get edit buffer */
- start = 0; /* default - start of buffer */
- end = strlen(editBuffer); /* default - end of buffer */
- left = right = 0; /* default - no selection */
-
- if (type == WTB_RESUME) {
- start = wtsess->textInfo[wtsess->lastBlock].offset +
- wtsess->textInfo[wtsess->lastBlock].len;
- } else {
- switch (startUnit) { /* find starting position */
- case WTU_SELECTION:
- if (XmTextGetSelectionPosition(Text, &left, &right) &&
- (left < right))
- {
- start = left;
- }
- break;
- case WTU_DOCUMENT:
- start = 0;
- break;
- case WTU_CHAR:
- switch(startPos) {
- case WTP_BEG:
- start = 0 + startLoc;
- break;
- case WTP_REL:
- start = wtsess->absPos + startLoc;
- break;
- case WTP_END:
- start = strlen(editBuffer) - startLoc;
- break;
- }
- break;
- case WTU_WORD:
- /*
- * Back up from current position to first non-alphanumeric.
- * Start with character in front of insertion position.
- */
- start = XmTextGetInsertionPosition(Text);
- if (start > 0) {
- start--;
- }
- while (start > 0) {
- c = editBuffer[start];
- if (((c >= 'a') && (c <= 'z')) ||
- ((c >= 'A') && (c <= 'Z')) ||
- ((c >= '0') && (c <= '9')) ||
- (c == '_'))
- {
- start--;
- } else {
- break;
- }
- }
- /*
- * If start is on an alphanumeric then we are done.
- * If start is not on an alphanumeric then search forward
- * in the buffer for an alphanumeric or end of buffer.
- */
- while (start < strlen(editBuffer)) {
- c = editBuffer[start];
- if (((c >= 'a') && (c <= 'z')) ||
- ((c >= 'A') && (c <= 'Z')) ||
- ((c >= '0') && (c <= '9')) ||
- (c == '_'))
- {
- break; /* found an alphanumeric */
- } else {
- start++;
- }
- }
- break;
- default:
- return WTS_NOTSUPPORTED;
- }
- }
-
- switch (endUnit) {
- case WTU_SELECTION:
- if (XmTextGetSelectionPosition(Text, &left, &right) &&
- (left < right))
- {
- end = right;
- }
- break;
- case WTU_DOCUMENT:
- end = strlen(editBuffer);
- break;
- case WTU_CHAR:
- switch(endPos) {
- case WTP_BEG:
- end = 0 + endLoc;
- break;
- case WTP_REL:
- end = wtsess->absPos + endLoc;
- break;
- case WTP_END:
- end = strlen(editBuffer) - endLoc;
- break;
- }
- break;
- case WTU_WORD:
- /*
- * Go forward from start to first non-alphanumeric.
- */
- end = start;
- while (end < strlen(editBuffer)) {
- c = editBuffer[end];
- if (((c >= 'a') && (c <= 'z')) ||
- ((c >= 'A') && (c <= 'Z')) ||
- ((c >= '0') && (c <= '9')) ||
- (c == '_'))
- {
- end++;
- } else {
- break;
- }
- }
- break;
- default:
- return WTS_NOTSUPPORTED;
- }
-
- if ((start > end) || (start < 0) || (end < 0)) {
- return WTS_BADREQUEST;
- }
- if ((end - start) > maxSize) { /* requested length greater than max */
- *endType = WTE_FULL;
- end = start + maxSize; /* back up to beginning of word */
- while (end > start) {
- c = editBuffer[end];
- if (((c >= 'a') && (c <= 'z')) ||
- ((c >= 'A') && (c <= 'Z')) ||
- ((c >= '0') && (c <= '9')) ||
- (c == '_'))
- {
- end--;
- } else {
- break;
- }
- }
- } else {
- *endType = WTE_ENDQUERY; /* text fit in buffer */
- }
- *len = end - start; /* len of requested text */
-
- memcpy(buffer, editBuffer+start, (unsigned)*len);
- free(editBuffer);
-
- wtsess->absPos = (unsigned)start + (unsigned)*len;
-
- /* update blockinfo */
- if (*len == 0) { /* there is no more text */
- return WTS_BADREQUEST;
- }
- if (type == WTB_RESUME) {
- if (wtsess->lastBlock >= MAXBLOCKS) {
- *endType = WTE_ERROR;
- *len = 0;
- return WTS_CLIENTERROR;
- }
- wtsess->lastBlock = wtsess->currBlock = wtsess->lastBlock + 1;
- } else {
- wtsess->tounit = endUnit;
- wtsess->topos = endPos;
- wtsess->toloc = endLoc;
- wtsess->lastBlock = wtsess->currBlock = 0; /* initial block */
- }
- wtsess->textInfo[wtsess->lastBlock].offset = (unsigned)start;
- wtsess->textInfo[wtsess->lastBlock].len = (unsigned)*len;
- return WTS_OK;
- } /* GetText */
-
- /*COMMENT***************************************************
- ;SelectedLen
- Title: Checks if selection is on
- In: none
- Out: none
- Return: 0 if selection is off, else length of selection
- Notes:
- ***********************************************************/
- unsigned SelectedLen(void)
- {
- XmTextPosition start, end;
-
- if (XmTextGetSelectionPosition(Text, &start, &end) &&
- (start < end))
- {
- return (end - start);
- }
- return 0;
- } /* SelectedLen */
-
- /*COMMENT***************************************************
- ;GoToPos
- Title: Goes to specified position in edit buffer
- In: blockPos - block position
- blockOffset - block offset
- offsetPos - offset position
- offset - offset
- Out: position - new position
- Return: WTS_OK or WTS_BADREQUEST
- Notes:
- ***********************************************************/
- WTSTATUS GoToPos(WTPOS blockPos, WTCOUNT blockOffset,
- WTPOS offsetPos, WTCOUNT offset, unsigned *position)
- {
- unsigned min, max;
- int block;
-
- if (wtsess->lastBlock == -1) {
- return WTS_BADREQUEST;
- }
- switch(blockPos) {
- case WTP_BEG:
- if (blockOffset < 0) {
- return WTS_BADREQUEST;
- }
- block = (int)blockOffset;
- break;
- case WTP_REL:
- block = (int)wtsess->currBlock + (int)blockOffset;
- break;
- case WTP_END:
- if (blockOffset < 0) {
- return WTS_BADREQUEST;
- }
- block = (int)wtsess->lastBlock - (int)blockOffset;
- break;
- }
- if ((block < 0)||(block > wtsess->lastBlock)) {
- return WTS_BADREQUEST;
- }
- switch(offsetPos) {
- case WTP_BEG:
- if (offset < 0) {
- return WTS_BADREQUEST;
- }
- *position = (int)wtsess->textInfo[block].offset + (int)offset;
- break;
- case WTP_REL:
- if ((blockPos != WTP_REL) && (blockOffset != 0)) {
- return WTS_BADREQUEST;
- }
- *position = (int)wtsess->textInfo[block].offset + (int)offset;
- break;
- case WTP_END:
- if (offset < 0) {
- return WTS_BADREQUEST;
- }
- *position = wtsess->textInfo[block].offset +
- wtsess->textInfo[block].len - (int)offset;
- break;
- }
-
- min = wtsess->textInfo[0].offset;
- max = wtsess->textInfo[wtsess->lastBlock].offset +
- wtsess->textInfo[wtsess->lastBlock].len;
-
- if ((*position < min) || (*position > max)) {
- return WTS_BADREQUEST;
- }
-
- if (!SelectedLen()) {
- SetCaretPos((int)*position);
- }
- return WTS_OK;
- } /* GoToPos */
-
- /*COMMENT***************************************************
- ;SetCaretPos
- Title: Sets caret to indicated offset
- In: offset - offset to place caret
- Out: none
- Return: none
- Notes: if offset is -1 caret is placed at end of document
- ***********************************************************/
- static void SetCaretPos(int offset)
- {
- XmTextPosition pos;
-
- if (offset == -1) {
- /* set to end of doc */
- pos = XmTextGetLastPosition(Text);
- } else {
- pos = offset;
- }
- XmTextSetInsertionPosition(Text, pos);
- } /* SetCaretPos */
-
- /*COMMENT***************************************************
- ;Hilite
- Title: Highlights a region in the text
- In: count - number of bytes to highlight starting at current position
- Out: none
- Return: number of bytes highlighted
- Notes:
- ***********************************************************/
- long Hilite(long count)
- {
- XmTextPosition start, end;
- Time time = XtLastTimestampProcessed(XtDisplay(Text));
-
- start = wtsess->absPos; /* current position */
- if ((start + count) < 0) {
- end = 0;
- } else {
- end = start + count;
- }
- if (count < 0) { /* backward hilite */
- XmTextSetSelection(Text, end, start, time);
- } else { /* forward hilite */
- XmTextSetSelection(Text, start, end, time);
- }
- return (end - start);
- } /* Hilite */
-
- /*COMMENT***************************************************
- ;DeHilite
- Title: Dehighlights a region in the text
- In: count - number of bytes to dehighlight starting at current position
- Out: none
- Return: number of bytes dehighlighted
- Notes: if count = 0 then dehighlight all
- ***********************************************************/
- long DeHilite(long count)
- {
- XmTextPosition start, end;
- XmTextPosition curStart, curEnd, newStart, newEnd, oldSelected;
- Time time = XtLastTimestampProcessed(XtDisplay(Text));
-
- if (!XmTextGetSelectionPosition(Text, &curStart, &curEnd)) {
- curStart = curEnd = 0;
- }
- oldSelected = curEnd - curStart; /* len of previous highlighted region */
- if ((count == 0) || (oldSelected == 0)) {
- XmTextClearSelection(Text, time); /* deselect all */
- SetCaretPos(wtsess->absPos); /* put caret at current position */
- return (long)oldSelected;
- }
-
- /* locate start & end pos of dehilite region */
- if (count < 0) {
- start = wtsess->absPos + count;
- if (start < 0) {
- start = 0;
- }
- end = wtsess->absPos;
- } else {
- start = wtsess->absPos;
- end = wtsess->absPos + count;
- }
-
- if ((((unsigned)start == curStart) && ((unsigned)end == curEnd)) ||
- (((unsigned)start < curStart) && ((unsigned)end > curEnd)) ||
- (((unsigned)start < curStart) && ((unsigned)end == curEnd)) ||
- (((unsigned)start == curStart) && ((unsigned)end > curEnd))) {
- /* dehilite region covers hilite region */
- XmTextClearSelection(Text, time); /* deselect all */
- SetCaretPos(wtsess->absPos); /* put caret at current position */
- return (long)oldSelected;
- }
-
- /* leading dehighlight*/
- if (((unsigned)start <= curStart) && ((unsigned)end > curStart)) {
- newStart = (unsigned)end;
- newEnd = curEnd;
- XmTextSetSelection(Text, newStart, newEnd, time);
- return (long)oldSelected - (newEnd - newStart);
- }
-
- /* trailing dehighlight */
- if (((unsigned)start < curEnd) && ((unsigned)end >= curEnd)) {
- newStart = curStart;
- newEnd = (unsigned)start;
- XmTextSetSelection(Text, newStart, newEnd, time);
- return (long)oldSelected - (newEnd - newStart);
- }
- return 0; /* dehilight region does not intersect highlight region */
- } /* DeHilite */
-
- /*COMMENT***************************************************
- ;ReplaceText
- Title: sets caret to indicated offset
- In: delete - number of bytes to delete
- insert - number of bytes to insert
- buffer - new text
- Out: none
- Return: 0 if selection is off, else len of selection
- Notes: if offset is -1 caret is placed at end of document
- ***********************************************************/
- WTCOUNT ReplaceText(WTCOUNT delete, WTSIZE insert, WTBUFP buffer)
- {
- XmTextPosition startDel, endDel, selected, delCount;
- char blank=0x0;
-
- /* Find start & end positions of text to be deleted */
- if (delete < 0) {
- startDel = wtsess->absPos + delete; /* delete backward */
- endDel = wtsess->absPos;
- } else {
- startDel = wtsess->absPos; /* delete forward */
- endDel = wtsess->absPos + delete;
- }
- if (startDel < 0) { /* make sure we're not before begining */
- startDel = 0;
- }
- delCount = endDel - startDel; /* actual delete count */
-
- /* Replace text */
- XmTextReplace(Text, startDel, endDel, buffer);
-
- /* Update block(s) where text was deleted */
- updateDeleteCount(FindCurrBlock(startDel), startDel, (unsigned)delCount);
-
- /* Update block where text was inserted */
- updateInsertCount(wtsess->currBlock, (unsigned)insert);
-
- /* Update absolute position */
- if (delete < 0) { /* delete backwards */
- wtsess->absPos = (unsigned)startDel + (unsigned)insert;
- delCount *= -1; /* deleted count is negative */
- } else {
- wtsess->absPos = (unsigned)startDel; /* delete forward */
- }
- /* Make sure caret is in correct position */
- SetCaretPos(wtsess->absPos);
-
- return delCount;
- } /* ReplaceText */
-
- /*COMMENT***************************************************
- ;FindCurrBlock
- Title: Finds the block indicated by position
- In: position - absolute position
- Out: none
- Return: block position is in
- Notes: block is -1 if error
- ***********************************************************/
- unsigned FindCurrBlock(unsigned position)
- {
- int i;
-
- for (i = wtsess->lastBlock; i >= 0; --i) {
- if (position >= wtsess->textInfo[i].offset) {
- break;
- }
- }
- return i;
- } /* FindCurrBlock */
-
- /*COMMENT***************************************************
- ;updateDeletCount
- Title: Deletes chars from indicated block or succeeding blocks
- In: blockNum - blocknumber to delete from
- pos - absolute position where deleting starts
- delcount - number of chars to delete
- Out: none
- Return: none
- Notes: none
- ***********************************************************/
- static
- void updateDeleteCount(unsigned blockNum, unsigned pos, unsigned delCount)
- {
- unsigned blockLen, blockOffset, nextDelCount;
- int i;
-
- blockLen = wtsess->textInfo[blockNum].len;
- blockOffset = wtsess->textInfo[blockNum].offset;
-
- if (((pos-blockOffset) + delCount) > blockLen) { /* in multiple blocks */
- nextDelCount = delCount - /* how much to delete from next block */
- (blockLen - (pos-blockOffset));
- delCount = delCount - nextDelCount; /* how much left to delete */
- updateDeleteCount(blockNum+1, pos + delCount, nextDelCount);
- }
- wtsess->textInfo[blockNum].len -= delCount;
- for (i = blockNum+1; i <= wtsess->lastBlock; ++i) {
- wtsess->textInfo[i].offset -= delCount;
- }
- } /* updateDeleteCount */
-
- /*COMMENT***************************************************
- ;updateInsertCount
- Title: Inserts chars at indicated block
- In: blockNum - blocknumber to insert
- delcount - number of chars to insert
- Out: none
- Return: none
- Notes: none
- ***********************************************************/
- static void updateInsertCount(unsigned blockNum, unsigned insertCount)
- {
- int i;
-
- wtsess->textInfo[blockNum].len += insertCount;
- for (i = blockNum+1; i <= wtsess->lastBlock; ++i) {
- wtsess->textInfo[i].offset += insertCount;
- }
- } /* updateInsertCount */
-
- /*COMMENT********************************************************
- ;NativeToWord
- Title: Convert native string to WP word string
- In: buffer - native string
- size - ptr to buffer size
- Out: buffer - word string
- Return: none
- Notes:
- *****************************************************************/
- void NativeToWord(WTBUFP buffer, WTSIZE *size)
- {
- unsigned long i;
-
- if (*size == 0) {
- buffer[0] = buffer[1] = 0;
- return;
- }
-
- *size = (*size - 1) << 1; /* double (size-1) */
-
- for (i = *size; i <= *size; i -= 2) {
- buffer[i] = buffer[i >> 1]; /* char */
- buffer[i+1] = 0x00; /* char set 0 */
-
- if ((buffer[i] < 32) || (buffer[i] > 126)) {
- buffer[i] = 35; /* undefined char is # */
- }
- }
- *size += 2;
- } /* NativeToWord */
-
- /*COMMENT********************************************************
- ;WordToNative
- Title: convert WP word string to native string
- In: buffer - word string
- size - buffer size
- Out: buffer - native string
- Return: none
- Notes:
- *****************************************************************/
- void WordToNative(WTBUFP buffer, WTSIZE *size)
- {
- unsigned long i;
-
- if (*size == 0) {
- buffer[0] = 0;
- return;
- }
-
- *size >>= 1;
- for (i = 1; i < *size; ++i) {
- buffer[i] = buffer[i << 1]; /* char */
- if ((buffer[i] < 32) || (buffer[i] > 126)) {
- buffer[i] = 35; /* undefined char is # */
- }
- }
- buffer[i] = 0;
- } /* WordToNative */
-
- /*COMMENT***************************************************
- ;SetNewBuffer
- Title: Initialize text buffer from file and update title
- In: buffer - text to put in text box
- filename - filename for title
- Out: none
- Xin: Client, Text
- Xout: none
- Return: none
- Notes:
- ***********************************************************/
- void SetNewBuffer(char *buffer, char *filename)
- {
- char title[80];
-
- XmTextReplace(Text, 0, XmTextGetLastPosition(Text), buffer);
- Dirty = FALSE;
- XmProcessTraversal(Text, XmTRAVERSE_CURRENT); /* focus to text */
-
- sprintf(title, "WTClient - %s", filename);
- XtVaSetValues(Client, XtNtitle, title, NULL);
- } /* SetNewBuffer */
-
- /*COMMENT***************************************************
- ;GetBuffer
- Title: Get text from edit buffer
- In: none
- Out: none
- Xin: Text
- Xout: none
- Return: none
- Notes:
- ***********************************************************/
- char *GetBuffer()
- {
- return(XmTextGetString(Text));
- } /* GetBuffer */
-
- /*COMMENT***************************************************
- ;TextCB
- Title: Text changed, set Dirty flag (XmNvalueChangedCallback for Text)
- In: none
- Out: none
- Xin: none
- Xout: none
- Return: none
- Notes:
- ***********************************************************/
- static void TextCB(Widget w, XtPointer cldata, XtPointer cbdata)
- {
- Dirty = TRUE;
- } /* TextCB */
-
- /*COMMENT***************************************************
- ;change_cursors
- Title: Turn on a cursor for a widget and its ancestors
- In: w = widget
- cursor = the cursor
- Out: none
- Xin: none
- Xout: none
- Ret: none
- Notes:
- ***********************************************************/
- static void change_cursors(Widget w, Cursor cursor)
- {
- while (w) {
- if (XtDisplayOfObject(w) && XtWindowOfObject(w)) {
- XDefineCursor(
- XtDisplayOfObject(w),
- XtWindowOfObject(w),
- cursor);
- XSync(XtDisplayOfObject(w), False);
- }
- w = XtParent(w);
- }
- } /* change_cursors */
-
- /*COMMENT***************************************************
- ;WaitCursor
- Title: Turn on wait cursor (Watch)
- In: w = widget
- Out: none
- Xin: none
- Xout: none
- Ret: none
- Notes:
- ***********************************************************/
- void WaitCursor(Widget w)
- {
- if (!waitcursor) {
- waitcursor = XCreateFontCursor(XtDisplayOfObject(w), XC_watch);
- }
- change_cursors(w, waitcursor);
- } /* WaitCursor */
-
- /*COMMENT***************************************************
- ;NormalCursor
- Title: Turn on normal cursor (Arrow)
- In: w = widget
- Out: none
- Xin: none
- Xout: none
- Ret: none
- Notes:
- ***********************************************************/
- void NormalCursor(Widget w)
- {
- if (!normalcursor) {
- normalcursor = XCreateFontCursor(XtDisplayOfObject(w), XC_left_ptr);
- }
- change_cursors(w, normalcursor);
- } /* NormalCursor */
-
- /*COMMENTS********************************
- ;free_cursors
- Title: Free cursors we created
- In: w - any widget on same display as cursors
- Out: none
- Xin: none
- Xout: none
- Return: none
- Notes:
- *END**************************************/
- static void free_cursors(Widget w)
- {
- if (normalcursor) {
- XFreeCursor(XtDisplay(w), normalcursor);
- }
- if (waitcursor) {
- XFreeCursor(XtDisplay(w), waitcursor);
- }
- normalcursor = 0; /* for safety */
- waitcursor = 0; /* for safety */
- } /* free_cursors */
-
- /*COMMENT***************************************************
- ;ClInvokeWritingTool
- Title: Invoke a writing tool
- In: tool - index of tool in toolRecords
- mode - WT_INVOKE_MODE, WT_SETUP_MODE, WT_HELP_MODE
- Out: none
- Xin: none
- Xout: none
- Return: 1 - success, 0 - error
- Notes: All input parameters are from wtapi.rc
- ***********************************************************/
- static BOOL ClInvokeWritingTool(int tool, short mode)
- {
- extern int errno; /* system errno */
- extern char *sys_errlist[]; /* text for system errors */
- extern int sys_nerr; /* number of system errors in sys_errlist */
- int sv_errno = 0; /* save errno */
- char error[256]; /* error message */
- BOOL found; /* executable found? */
- char **argv; /* arguments for exec of child tool */
- int argc = 0; /* argument count */
- int argcnt; /* number of argv's allocated */
- char *arg; /* pointer to next arg in params */
- char initpath[256]; /* full path to executable */
- char fullpath[256]; /* full path to executable */
- char *p; /* pointer */
- char *cwd; /* pointer to current working directory */
- char buf[256]; /* buffer */
- int try; /* loop variable */
- WTCOMM comm; /* communication handle */
- String app_name = 0; /* application name */
- String app_class = 0; /* application class */
- int pid; /* pid of forked process */
- int i;
-
- /*
- * Make sure the process to be executed exists and is executable. The
- * following searches are done in order. The search ends whenever an
- * executable file is found:
- * Full path in wtapi.rc:
- * 1. Path as given.
- * 2. Find name of current directory. Look for this directory in
- * the given path. If found, strip off path up to and including
- * this dir and use the remainder of the path as a relative path
- * for the relative path searches below. (This handles the case
- * of a directory being remote mounted to a mount point different
- * than the original path.)
- * Relative path in wtapi.rc:
- * 1. Relative to current directory.
- * 2. Relative to $HOME directory.
- * 3. Relative to root directory (/).
- */
- strcpy(initpath, toolRecords[tool].exe);/* exec path from wtapi.rc */
- errno = 0;
- found = FALSE;
- if (initpath[0] == '/') { /* full path given in wtapi.rc */
- if (access(initpath, X_OK) == 0) {
- strcpy(fullpath, initpath);
- found = TRUE;
- } else {
- sv_errno = errno; /* save errno of first try to report */
- /*
- * Check for current directory in path. If found look relative
- * to current directory using remainder of path.
- */
- if (cwd = getcwd(buf, 256)) {
- p = strrchr(cwd, '/'); /* find last '/' in path */
- cwd = p+1; /* get name of directory */
- /* check for current dir in given path */
- if (p = strstr(initpath, cwd)) {
- p = strchr(p, '/'); /* skip to next '/' */
- p++; /* skip past '/' */
- strcpy(initpath, p); /* new relative path */
- /*
- * This new relative path will be checked by the relative
- * path code below.
- */
- }
- }
- }
- }
- if (initpath[0] != '/') { /* relative path */
- for (try = 1; try > 0; try++) {
- switch (try) {
- case 1: /* Look relative to current directory */
- if (cwd = getcwd(buf, 256)) {
- if (cwd[strlen(cwd)-1] != '/') {
- strcat(cwd, "/"); /* append a slash */
- }
- } else {
- continue;
- }
- break;
- case 2: /* Look relative to $HOME directory */
- if (cwd = getenv("HOME")) {
- if (cwd[strlen(cwd)-1] != '/') {
- strcat(cwd, "/"); /* append a slash */
- }
- } else {
- continue;
- }
- break;
- case 3: /* Look relative to root directory */
- cwd = strcpy(buf, "/");
- break;
- default:
- try = -1; /* give up */
- continue;
- }
- strcpy(fullpath, cwd);
- strcat(fullpath, initpath);
- if (access(fullpath, X_OK) == 0) {
- found = TRUE;
- break; /* exit loop, we found an executable path */
- } else {
- if (!sv_errno) {
- sv_errno = errno; /* only save first errno */
- }
- }
- }
- }
- if (!found) { /* all attempts to find the executable failed */
- sprintf(error, "Failed to find executable: %s", toolRecords[tool].exe);
- if (sv_errno < sys_nerr) {
- strcat(error, "\n\nError: ");
- strcat(error, sys_errlist[sv_errno]);
- }
- ReportError(error);
- return FALSE; /* Failed to find tool to bring up */
- }
- /*
- * The full path is needed for communication. Put it in toolRecords if
- * not already there.
- */
- if (strcmp(fullpath, toolRecords[tool].exe) != 0) {
- strcpy(toolRecords[tool].exe, fullpath);
- }
- /*
- * Initialize the WT client communication.
- */
- if (comm = WtConnect(Client, toolRecords[tool].exe)) {
- commHandle = comm; /* successful */
- } else {
- ReportError("Could not initialize communication, tool not loaded.");
- return FALSE;
- }
- /*
- * Allocate space for argv parameters.
- */
- argcnt = 50; /* start with 50, should be plenty */
- argv = (char **)calloc(argcnt, sizeof(char **));
- if (!argv) {
- WtDisconnect(comm);
- ReportError("Not enough memory.");
- return FALSE;
- }
- /*
- * Build the path argument to pass to the child tool process.
- */
- argv[0] = (char *)malloc(strlen(toolRecords[tool].exe)+1);
- if (!argv[0]) {
- free(argv);
- WtDisconnect(comm);
- ReportError("Not enough memory.");
- return FALSE;
- }
- strcpy(argv[0], toolRecords[tool].exe);
- argc = 1;
- /*
- * Build the WTAPI arguments to pass to the child (tool) process.
- */
- argv[argc] = (char *)malloc(strlen("-wtapi")+1);
- strcpy(argv[argc++], "-wtapi");
-
- argv[argc] = (char *)malloc(5);
- sprintf(argv[argc++], "%d", comm->tl_pipe.read);
-
- argv[argc] = (char *)malloc(5);
- sprintf(argv[argc++], "%d", comm->tl_pipe.write);
- /*
- * Add the parameters from the wtapi.rc file.
- */
- strcpy(buf, toolRecords[tool].params); /* make a copy */
- arg = p = buf;
- while (*p) {
- if (argc >= (argcnt-1)) { /* too many args, ignore the rest */
- break;
- }
- if (p = strpbrk(p, " \t\n\r")) { /* find next whitespace */
- if (p == arg) { /* starting on whitespace */
- arg = ++p; /* move to next char */
- continue;
- }
- *p = 0; /* null out white space */
- } else {
- p += strlen(p); /* move p to end of string */
- }
- argv[argc] = (char *)malloc(strlen(arg)+1);
- if (!argv[argc]) {
- for (i = 0; i < argc; i++) {
- if (argv[i]) {
- free(argv[i]);
- }
- }
- free(argv);
- WtDisconnect(comm);
- ReportError("Not enough memory.");
- return FALSE;
- }
- strcpy(argv[argc++], arg);
- arg = ++p; /* move to next char */
- }
- /*
- * Get application class and client's window to pass along.
- * (These are optional and the tool should provide defaults if needed.)
- */
- /* -appClass */
- if ((argc + 3) < argcnt) {
- argv[argc] = (char *)malloc(strlen("-appClass")+1);
- strcpy(argv[argc++], "-appClass");
- XtGetApplicationNameAndClass(XtDisplay(Client), &app_name, &app_class);
- argv[argc] = (char *)malloc(strlen(app_class)+1);
- strcpy(argv[argc++], app_class);
- }
- /* -clwin */
- if ((argc + 3) < argcnt) {
- argv[argc] = (char *)malloc(strlen("-clwin")+1);
- strcpy(argv[argc++], "-clwin");
- sprintf(buf, "0x%x", XtWindow(Client));
- argv[argc] = (char *)malloc(strlen(buf)+1);
- strcpy(argv[argc++], buf);
- }
- argv[argc] = 0; /* null terminate argv list */
- /*
- * Execute the Writing Tool.
- */
- if (pid = fork()) { /* parent process */
- if (pid == -1) { /* fork failed */
- for (i = 0; i < argc; i++) {
- if (argv[i]) {
- free(argv[i]);
- }
- }
- free(argv);
- WtDisconnect(comm);
- sprintf(buf, "Fork failed for exec of: %s", argv[0]);
- ReportError(buf);
- return FALSE;
- }
- } else { /* child process */
- execvp(argv[0], argv);
- exit(1); /* exit of child on exec failure */
- }
- /*
- * Close tool's read/write file descriptors in the parent.
- */
- close(comm->tl_pipe.read);
- close(comm->tl_pipe.write);
- comm->tl_pipe.read = comm->tl_pipe.write = -1; /* mark as closed */
- /*
- * Free memory allocated for argv parameters.
- */
- for (i = 0; i < argc; i++) {
- if (argv[i]) {
- free(argv[i]);
- }
- }
- free(argv);
- return TRUE;
- } /* ClInvokeWritingTool */
-