2 * CDE - Common Desktop Environment
4 * Copyright (c) 1993-2012, The Open Group. All rights reserved.
6 * These libraries and programs are free software; you can
7 * redistribute them and/or modify them under the terms of the GNU
8 * Lesser General Public License as published by the Free Software
9 * Foundation; either version 2 of the License, or (at your option)
12 * These libraries and programs are distributed in the hope that
13 * they will be useful, but WITHOUT ANY WARRANTY; without even the
14 * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
15 * PURPOSE. See the GNU Lesser General Public License for more
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with these librararies and programs; if not, write
20 * to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
21 * Floor, Boston, MA 02110-1301 USA
23 /* $XConsortium: SearchCalls.c /main/13 1996/11/21 20:00:02 drk $ */
24 /**********************************<+>*************************************
25 ***************************************************************************
27 ** File: SearchCalls.c
29 ** Project: DtEditor widget for editing services
31 ** Description: Spell and Find functions
34 *******************************************************************
36 * (c) Copyright 1996 Digital Equipment Corporation.
37 * (c) Copyright 1993, 1994, 1996 Hewlett-Packard Company.
38 * (c) Copyright 1993, 1994, 1996 International Business Machines Corp.
39 * (c) Copyright 1993, 1994, 1996 Sun Microsystems, Inc.
40 * (c) Copyright 1996 Novell, Inc.
41 * (c) Copyright 1996 FUJITSU LIMITED.
42 * (c) Copyright 1996 Hitachi.
43 * (c) Copyright 1993, 1994 Unix System Labs, Inc., a subsidiary of Novell, Inc.
45 ********************************************************************/
50 #include <Xm/MessageB.h>
54 #include <Dt/DtMsgsP.h>
55 #include <Dt/HourGlass.h>
56 #include "DtWidgetI.h"
58 #include <Xm/XmPrivate.h> /* _XmStringSourceGetString */
60 #define X_INCLUDE_STRING_H
61 #define XOS_USE_XT_LOCKING
62 #include <X11/Xos_r.h>
65 _XmStringUngenerate(XmString string,
68 XmTextType output_type);
70 static Boolean DoReplace(
74 static int SearchForString(
76 XmTextPosition startLocation,
78 static Boolean DoSearch(
82 static Boolean IsValidFilter(
83 DtEditorWidget pPriv);
84 static Boolean IsInGroup(
86 static Boolean IsExecutable(
88 static void DestroyThisWidgetCB(
95 DtEditorInvokeSpellDialog(
98 DtEditorWidget pPriv = (DtEditorWidget) widget;
99 char fileName[L_tmpnam], com[L_tmpnam + 7], *string, newline[1];
101 FILE *fp; /* pipe to read words from */
102 int len = 0; /* length of line read in */
103 int maxLen = 0; /* max length of the line buffer */
104 XmString word; /* processed word ready to add to list */
106 DtEditorErrorCode error = DtEDITOR_NO_TMP_FILE;
107 _DtWidgetToAppContext(widget);
112 if (!IsValidFilter(pPriv)) {
113 error = DtEDITOR_SPELL_FILTER_FAILED;
117 _DtTurnOnHourGlass(M_topLevelShell(pPriv));
120 * Write out to a tmp file, getting the name back
122 (void)tmpnam(fileName);
123 if((fp = fopen(fileName, "w")) != (FILE *)NULL)
126 * Temporary file created sucessfully so write out contents of
127 * widget in preparation of feeding it to the 'spell' filter.
129 string = (char *)XmTextGetString(M_text(pPriv));
130 fwrite(string, sizeof(char), strlen(string), fp);
133 * Tack on a final newline (\n) cuz spell(1) does not spell-check
134 * lines which do not terminate with a newline.
136 fwrite(newline, sizeof(char), 1, fp);
140 /* start spell command */
141 sprintf(com, "%s %s", M_spellFilter(pPriv), fileName);
142 fp = popen(com, "r");
144 if ( fp == (FILE *)NULL )
145 error = DtEDITOR_SPELL_FILTER_FAILED;
147 error = DtEDITOR_NO_ERRORS;
150 * The filter was started successfully.
151 * Initialize the Spell dialog and get ready to receive
152 * the list of mispelled words.
154 _DtEditorSearch(pPriv, True, True);
155 _DtTurnOnHourGlass(M_search_dialog(pPriv));
156 /* needed for bug in list */
157 XmListSetPos(M_search_spellList(pPriv), 1);
158 XmListDeleteAllItems(M_search_spellList(pPriv));
164 line = (char *) XtMalloc (sizeof(char) * (maxLen + 1));
168 * Now, get each word and hand it to the list
170 while(fgets(&line[len], maxLen - len, fp))
172 len += strlen(&line[len]);
175 if (line[len - 1] == '\n')
177 line[len - 1] = '\0';
178 word = XmStringCreateLocalized(line);
179 XmListAddItemUnselected(M_search_spellList(pPriv), word, 0);
186 line = (char *) XtRealloc (line, sizeof(char) * (maxLen + 1));
191 /* clean up and display the results */
194 _DtEditorSearch(pPriv, True, False);
195 _DtTurnOffHourGlass(M_search_dialog(pPriv));
196 } /* end start the spell filter */
199 } /* end create temporary file */
201 _DtTurnOffHourGlass(M_topLevelShell(pPriv));
204 if (error != DtEDITOR_NO_ERRORS) {
205 XmString title, msg1, msg2, msg3;
211 buf = XtMalloc((strlen(BAD_FILTER2) +
212 strlen(M_spellFilter(pPriv)) + 1) *
215 sprintf(buf, BAD_FILTER2, M_spellFilter(pPriv));
216 msg1 = XmStringGenerate(BAD_FILTER,
217 XmFONTLIST_DEFAULT_TAG,
218 XmCHARSET_TEXT, NULL);
220 msg2 = XmStringSeparatorCreate();
221 msg3= XmStringConcatAndFree(msg1, msg2);
222 msg1 = XmStringGenerate(buf,
223 XmFONTLIST_DEFAULT_TAG,
224 XmCHARSET_TEXT, NULL);
226 msg2 = XmStringConcatAndFree(msg3, msg1);
229 title = XmStringCreateLocalized(ERROR_TITLE);
232 XtSetArg(al[ac], XmNdialogTitle, title); ac++;
233 XtSetArg(al[ac], XmNdialogType, XmDIALOG_ERROR); ac++;
234 XtSetArg(al[ac], XmNmessageString, msg2); ac++;
235 dialog = XmCreateMessageDialog((Widget)pPriv,
236 "Spell Error", al, ac
239 XtUnmanageChild(XmMessageBoxGetChild(dialog,
240 XmDIALOG_HELP_BUTTON));
241 XtUnmanageChild(XmMessageBoxGetChild(dialog,
242 XmDIALOG_CANCEL_BUTTON));
243 XtAddCallback(dialog, XmNokCallback, DestroyThisWidgetCB, NULL);
244 XtVaSetValues(XtParent(dialog),
245 XmNdeleteResponse, XmDESTROY,
247 XtManageChild(dialog);
256 } /* end DtEditorInvokeSpellDialog */
258 static void DestroyThisWidgetCB (
272 DtEditorWidget editor = (DtEditorWidget) widget;
273 Boolean foundIt = True;
274 _DtWidgetToAppContext(widget);
278 * If we were passed a string to find, then use it. Otherwise,
279 * use the last find string entered in the Find/Change dialog.
281 if ( find != (char *)NULL )
282 foundIt = DoSearch(editor, find, CurrentTime);
286 * If there is no value from the dialog, then post the Find/Change
289 if (!M_search_string(editor))
290 _DtEditorSearch(editor, False, False);
292 foundIt = DoSearch(editor, M_search_string(editor), CurrentTime);
300 /* Count the number of characters represented in the char* str.
301 * By definition, if MB_CUR_MAX == 1 then numBytes == number of characters.
302 * Otherwise, use mblen to calculate.
305 _DtEditor_CountCharacters(
312 int mbCurMax = MB_CUR_MAX; /* invoke the macro just once */
315 return (numBytes < 0)? 0 : numBytes;
316 if (numBytes <=0 || str == NULL || *str == '\0')
319 for(bptr = str; numBytes > 0; count++, bptr+= char_size)
321 char_size = mblen(bptr, mbCurMax);
324 numBytes -= char_size;
330 * SearchForString takes an Editor widget, a position at which
331 * to begin its search, and the string for which it is to search.
332 * It searches first from startLocation to the end of the file, and
333 * then if necessary from the start of the file to startLocation.
334 * It returns an integer indicating the location of the string, or
335 * -1 if the string is not found.
339 DtEditorWidget pPriv,
340 XmTextPosition startLocation,
343 XmTextPosition pos, searchAnchor, topAnchor, cursorLocation,
344 lastPosition = XmTextGetLastPosition(M_text(pPriv));
347 searchAnchor = cursorLocation = startLocation;
349 while((Boolean)XmTextFindString(M_text(pPriv), searchAnchor,
350 searchString, XmTEXT_FORWARD,
352 ((Boolean)XmTextFindString(M_text(pPriv), topAnchor,
353 searchString, XmTEXT_FORWARD, &pos) &&
354 pos < cursorLocation))
356 char *word, leadingChar, trailingChar;
357 XmTextPosition endPos;
360 * Do some extra work for the Spell case, so we find only "words"
362 * Get the word with the leading & trailing characters.
363 * It's a word if it's bounded by:
364 * a. 16-bit characters
372 * 0 (constant) - first character position in the document.
373 * lastPosition - last character position in the document.
375 * pos - Position in the document of the first character
376 * of the word. Does not include leading character.
377 * endPos - Position in the document of the last character
378 * of the word + 1. Points to the trailing character,
381 * word - The string we have matched. Includes the leading
382 * & trailing characters, if any.
383 * word[0] - Leading character, if any, otherwise first
384 * character of the matched string.
385 * word[length] - Trailing character, if any, otherwise last
386 * character of the matched string.
390 endPos = pos + 1 + _DtEditor_CountCharacters(searchString,
391 strlen(searchString));
392 if(pos < cursorLocation)
395 searchAnchor = pos + 1;
398 * If the first character of the word is the first character in
399 * the document there is no leading character. Likewise, if the
400 * last character of the word is the last character in the document
401 * there is no trailing character.
405 * There is a leading character.
408 if (endPos <= lastPosition) {
410 * There is a trailing character.
412 word = (char *)_XmStringSourceGetString(
413 (XmTextWidget) M_text(pPriv),
414 pos - 1, endPos, False);
415 length = strlen(word) - 1;
416 trailingChar = word[length];
421 * There is no trailing character.
423 word = (char *)_XmStringSourceGetString(
424 (XmTextWidget) M_text(pPriv),
425 pos - 1, lastPosition, False);
426 length = strlen(word);
429 leadingChar = word[0];
434 * There is no leading character.
437 if (endPos <= lastPosition) {
439 * There is a trailing character.
441 word = (char *)_XmStringSourceGetString(
442 (XmTextWidget) M_text(pPriv),
444 length = strlen(word) - 1;
445 trailingChar = word[length];
449 * There is no trailing character.
451 word = (char *)_XmStringSourceGetString(
452 (XmTextWidget) M_text(pPriv),
453 0, lastPosition, False);
454 length = strlen(word);
460 if ((M_search_dialogMode(pPriv) != SPELL) ||
462 ((mblen(word, MB_CUR_MAX) > 1) ||
463 ( isascii(leadingChar) &&
464 (isspace(leadingChar) || ispunct(leadingChar))
467 ((mblen(word+length-1, MB_CUR_MAX) > 1) ||
468 ( isascii(trailingChar) &&
469 (isspace(trailingChar) || ispunct(trailingChar))
476 * Either we are not in Spell mode or we have a word
479 if (word != (char *)NULL)
485 if (word != (char *)NULL)
494 DtEditorWidget widget,
499 Boolean foundIt = False;
501 stringPosition = SearchForString(widget,
502 XmTextGetInsertionPosition(M_text(widget)),
505 if(stringPosition == -1) {
507 * If the string was not found unselect everything
509 XmTextClearSelection(M_text(widget), time);
513 * The string was found so highlight the word and scroll the window
514 * if it is not visible.
516 XmTextPosition pos = (XmTextPosition) stringPosition;
517 XmTextWidget tw = (XmTextWidget)M_text(widget);
520 XmTextSetInsertionPosition(M_text(widget), pos);
521 XmTextSetSelection( M_text(widget), pos,
522 pos+_DtEditor_CountCharacters(search_string, strlen(search_string)),
523 XtLastTimestampProcessed(XtDisplay(M_text(widget))) );
526 * Scroll the widget, if necessary
528 if (pos < tw->text.top_character || pos >= tw->text.bottom_position)
537 XtSetArg(al[ac], XmNheight, &height); ac++;
538 XtSetArg(al[ac], XmNrows, &rows); ac++;
539 XtGetValues(M_text(widget), al, ac);
541 if(XmTextPosToXY(M_text(widget), pos, &x, &y) == True)
543 int offset = (int)((y - height/2) * rows) / (int)height;
544 XmTextScroll(M_text(widget), offset);
556 * DtEditorInvokeFindChangeDialog posts the "Find/Change" dialog.
559 DtEditorInvokeFindChangeDialog(
562 DtEditorWidget pPriv = (DtEditorWidget) widget;
563 _DtWidgetToAppContext(widget);
566 _DtEditorSearch(pPriv, False, False);
571 * DoReplace checks that there is a non-null selection, and
572 * if so, replaces the selection with the replace_string argument.
576 DtEditorWidget pPriv,
577 char *replace_string,
580 XmTextPosition first, last;
581 Boolean replaced = False;
584 * Only do a replace if we have a non-null selection.
585 * We could check that the selection == the Find string, but
586 * this allows a little more flexibility for the user.
588 if (XmTextGetSelectionPosition(M_text(pPriv), &first, &last) &&
591 XmTextReplace(M_text(pPriv), first, last, replace_string);
592 XmTextSetSelection(M_text(pPriv), first,
594 _DtEditor_CountCharacters(replace_string, strlen(replace_string)),
603 * ReplaceAll replaces all occurrences of search_string with
604 * replacement_string in widget.
609 DtEditorWidget widget,
611 char *replace_string )
613 int replacementLength, searchLength, lastOccurrence, thisOccurrence;
614 Boolean replaceOK = False;
617 * Make sure there is a string to find. Null replacement strings
620 if( search_string && *search_string )
623 * How long is the string we are searching for?
625 searchLength = _DtEditor_CountCharacters( search_string,
626 strlen(search_string) );
629 * How long is the replacement string?
631 replacementLength = _DtEditor_CountCharacters( replace_string,
632 strlen(replace_string) );
635 * Start at the beginning and search for the string
638 while( ((thisOccurrence = SearchForString(widget,
639 (lastOccurrence > 0)? (XmTextPosition)lastOccurrence : 0,
642 thisOccurrence >= lastOccurrence )
644 XmTextReplace( M_text(widget), (XmTextPosition)thisOccurrence,
645 (XmTextPosition) (thisOccurrence + searchLength),
647 lastOccurrence = thisOccurrence + replacementLength;
650 if (lastOccurrence != -1)
657 } /* end ReplaceAll */
660 * DtEditorChange replaces either the current selection, the next occurrence
661 * of a string, or all occurrences of the string with a replacement string.
662 * If no find or change to strings are passed in, DtEditorFindChange uses
663 * the last find and change to strings from the Find/Change dialog.
668 DtEditorChangeValues *findChangeStrings,
669 unsigned int instanceToChange)
672 Boolean returnVal = False;
673 DtEditorWidget editor = (DtEditorWidget) widget;
674 _DtWidgetToAppContext(widget);
677 switch( instanceToChange )
679 case DtEDITOR_NEXT_OCCURRENCE:
682 * Find the next occurrence and replace it (by treating it as
683 * a current selection).
687 * If we were passed a Find string use it. Otherwise, tell
688 * DtEditorFind to use the last search string value
691 if ( findChangeStrings != (DtEditorChangeValues *) NULL )
692 returnVal = DtEditorFind( widget, findChangeStrings->find );
694 returnVal = DtEditorFind( widget, (char *)NULL );
696 if ( returnVal == False)
700 case DtEDITOR_CURRENT_SELECTION:
703 * Replace whatever is selected.
707 * If we were passed a Change To string use it. Otherwise,
708 * use the last replace string value.
710 if ( findChangeStrings != (DtEditorChangeValues *) NULL )
711 returnVal = DoReplace( editor, findChangeStrings->changeTo,
714 returnVal= DoReplace(editor,M_replace_string(editor),CurrentTime);
719 case DtEDITOR_ALL_OCCURRENCES:
721 _DtTurnOnHourGlass( M_topLevelShell(editor) );
724 if ( findChangeStrings != (DtEditorChangeValues *) NULL )
725 returnVal = ReplaceAll( editor, findChangeStrings->find,
726 findChangeStrings->changeTo );
728 returnVal = ReplaceAll( editor, M_search_string(editor),
729 M_replace_string(editor) );
731 _DtTurnOffHourGlass( M_topLevelShell( editor ) );
734 } /* replace all occurrences */
745 } /* end DtEditorChange */
749 _DtEditorSearchMapCB(
757 Position newX, newY, pY, pX;
758 Dimension pHeight, myHeight, pWidth, myWidth;
759 DtEditorWidget pPriv = (DtEditorWidget) client_data;
761 parent = M_topLevelShell(pPriv);
765 pHeight = XtHeight(parent);
766 pWidth = XtWidth(parent);
767 myHeight = XtHeight(w);
768 myWidth = XtWidth(w);
770 if ((newY = pY - (int)myHeight + 5) < 0)
772 newX = pX + pWidth/2 - ((int)myWidth)/2;
775 XtSetArg(al[ac], XmNx, newX); ac++;
776 XtSetArg(al[ac], XmNy, newY); ac++;
777 XtSetValues(w,al,ac);
783 * _DtEditorDialogSearchCB is called whenever the Find button is pressed
784 * in the Find/Change dialog. If the dialog is displayed in Find/Change
785 * mode, it updates the contents of M_search_string() with the contents
786 * of the "Find" text field, and then invokes DtEditorFind(). If the
787 * find is successful, the Change button is enabled, otherwise the
788 * "String not found" dialog is displayed.
790 * When the dialog is in Spell mode, the selected misspelled word is merely
791 * passed to DtEditorFind(). The Change (and Change All) buttons are left
792 * insentive until the user types something into the Change To field
793 * (too many users were replacing misspelled words with blanks).
799 _DtEditorDialogSearchCB(
805 DtEditorWidget pPriv = (DtEditorWidget) client_data;
808 * Is the dialog in Find/Change or Spell mode?
810 if (M_search_dialogMode(pPriv) == REPLACE) {
813 * Free the existing search string and get the new one.
815 if (M_search_string(pPriv))
816 XtFree(M_search_string(pPriv));
817 M_search_string(pPriv) = XmTextFieldGetString( M_findText(pPriv) );
822 if( DtEditorFind((Widget)pPriv, M_search_string(pPriv)) ) {
824 * If the string was found then enable the Change button.
825 * It will be disabled when it is pressed or a new Find string is
828 _DtEditorSetReplaceSensitivity( pPriv, True );
832 * Post a dialog informing the user the string was not found.
835 char *tempStr = (char *)XtMalloc(strlen(NO_FIND) +
836 strlen(M_search_string(pPriv)) + 1);
837 sprintf(tempStr, NO_FIND, M_search_string(pPriv));
838 _DtEditorWarning(pPriv, tempStr, XmDIALOG_INFORMATION);
849 M_misspelled_found(pPriv) = DtEditorFind((Widget)pPriv,
850 M_misspelled_string(pPriv) );
852 * If the word was found & there is a Change To string then enable
853 * the Change button. If there is no Change To string, Change will
854 * be enabled when a string is entered if M_misspelled_found is True
855 * (see _DtEditorReplaceTextChangedCB)
857 * Change All is enabled in _DtEditorReplaceTextChangedCB()
858 * (ie. anytime there is a Change To string). It is not
859 * dependent upon a sucessful Find because it initiates its own
862 if ( M_misspelled_found(pPriv) == True ) {
865 * Is there a Change To string?
867 pString = XmTextFieldGetString(M_replaceText(pPriv));
869 if( pString != (char *)NULL && *pString != (char)'\0' )
870 _DtEditorSetReplaceSensitivity( pPriv, True );
872 if(pString != (char *)NULL)
877 * Post a dialog informing the user the string was not found.
880 char *tempStr = (char *)XtMalloc(strlen(NO_FIND) +
881 strlen(M_misspelled_string(pPriv)) + 1);
882 sprintf(tempStr, NO_FIND, M_misspelled_string(pPriv));
883 _DtEditorWarning(pPriv, tempStr, XmDIALOG_INFORMATION);
889 } /* end _DtEditorDialogSearchCB */
892 * _DtEditorDialogReplaceCB is called whenever the Change button is pressed
893 * in the Find/Change dialog. If the dialog is displayed in Find/Change
894 * mode, it updates the contents of M_replace_string() with the contents
895 * of the "Change To" text field, and then invokes DtEditorChange().
897 * When the dialog is in Spell mode, the contents of the "Change To" text
898 * field is passed to DtEditorChange() without updating M_replace_string().
900 * In both cases, the Change button is disabled after the change is
906 _DtEditorDialogReplaceCB(
911 DtEditorWidget pPriv = (DtEditorWidget) client_data;
914 * Is the dialog in Find/Change or Spell mode?
916 if (M_search_dialogMode(pPriv) == REPLACE) {
919 * Free the existing Change To string and get the new one.
921 if (M_replace_string(pPriv))
922 XtFree(M_replace_string(pPriv));
923 M_replace_string(pPriv) = XmTextFieldGetString(M_replaceText(pPriv));
925 DtEditorChange( (Widget)pPriv, (DtEditorChangeValues *)NULL,
926 DtEDITOR_CURRENT_SELECTION );
932 DtEditorChangeValues newWord;
934 newWord.changeTo = XmTextFieldGetString(M_replaceText(pPriv));
935 if (newWord.changeTo != (char *)NULL) {
936 /* This field ignored when changing the current selection */
937 newWord.find = (char *)NULL;
938 DtEditorChange( (Widget)pPriv, &newWord, DtEDITOR_CURRENT_SELECTION );
940 XtFree(newWord.changeTo);
945 * Disable the Change button. In Find/Change mode, it will be enabled
946 * when the Find button is pressed and the Find text is successfully
947 * found. In Spell mode, there must also be a value in the Change To
950 _DtEditorSetReplaceSensitivity(pPriv, False );
953 * Want the traversal to be on the Find button, so that the user
954 * can initiate another search.
956 XmProcessTraversal(M_search_findBtn(pPriv), XmTRAVERSE_CURRENT);
960 * _DtEditorDialogReplaceAllCB is attached to the "Change All" button
961 * in the Find/Change dialog. It replaces all occurances of the "Find"
962 * string with the "Change To" string.
967 _DtEditorDialogReplaceAllCB(
972 DtEditorWidget pPriv = (DtEditorWidget) client_data;
975 * Is the dialog in Find/Change or Spell mode?
977 if (M_search_dialogMode(pPriv) == REPLACE) {
980 * Free any existing search string before getting the current one.
982 if (M_search_string(pPriv))
983 XtFree(M_search_string(pPriv));
984 M_search_string(pPriv) = XmTextFieldGetString(M_findText(pPriv));
987 * Free the existing Change To string and get the new one.
989 if (M_replace_string(pPriv))
990 XtFree(M_replace_string(pPriv));
991 M_replace_string(pPriv) = XmTextFieldGetString(M_replaceText(pPriv));
994 * Make the change with the current values (set above).
996 if( !DtEditorChange((Widget)pPriv, (DtEditorChangeValues *)NULL,
997 DtEDITOR_ALL_OCCURRENCES) ) {
999 * If the replace failed, post a dialog informing the user
1000 * the string was not found.
1003 char *tempStr = (char *)XtMalloc(strlen(NO_FIND) +
1004 strlen(M_search_string(pPriv)) + 1);
1005 sprintf(tempStr, NO_FIND, M_search_string(pPriv));
1006 _DtEditorWarning(pPriv, tempStr, XmDIALOG_INFORMATION);
1015 DtEditorChangeValues changeValues;
1017 changeValues.find = M_misspelled_string(pPriv);
1018 changeValues.changeTo = XmTextFieldGetString(M_replaceText(pPriv));
1019 DtEditorChange((Widget)pPriv, &changeValues, DtEDITOR_ALL_OCCURRENCES);
1021 if( changeValues.changeTo != (char *)NULL )
1022 XtFree( changeValues.changeTo );
1027 * Disable the Change button. It will be enabled when the Find
1028 * button is pressed and the Find text is successfully found.
1029 * In Spell mode, there must also be a value in the Change To field.
1031 _DtEditorSetReplaceSensitivity(pPriv, False );
1033 } /* _DtEditorDialogReplaceAllCB */
1037 _DtEditorDialogFindCancelCB(
1039 caddr_t client_data,
1042 DtEditorWidget pPriv = (DtEditorWidget)client_data;
1043 XtUnmanageChild(M_search_dialog(pPriv));
1047 * _DtEditorMisspelledSelectCB is called when a new word has been selected
1048 * from the list of misspelled words.
1052 _DtEditorMisspelledSelectCB(
1054 caddr_t client_data,
1057 XmListCallbackStruct *cb = (XmListCallbackStruct *)call_data;
1058 DtEditorWidget editor = (DtEditorWidget)client_data;
1061 * Get the selected word for use when the Find or Replace All button
1064 if (M_misspelled_string(editor))
1065 XtFree(M_misspelled_string(editor));
1067 M_misspelled_string(editor) =
1068 _XmStringUngenerate(cb->item, NULL, XmCHARSET_TEXT, XmCHARSET_TEXT);
1071 * Mark that it has not been found
1074 M_misspelled_found(editor) = False;
1077 * Enable the Find button
1079 _DtEditorSetFindSensitivity(editor, True );
1082 * Clear the "Change To" text field.
1084 XmTextFieldSetString(M_replaceText(editor), (char *)NULL);
1086 } /* end _DtEditorMisspelledSelectCB */
1089 * _DtEditorMisspelledDblClickCB is called when a word has been double-
1090 * clicked from the list of misspelled words. First, the word will become
1091 * the new misspelled string and, then, a find will be initiated for it.
1095 _DtEditorMisspelledDblClickCB(
1097 caddr_t client_data,
1100 _DtEditorMisspelledSelectCB(w, client_data, call_data );
1101 _DtEditorDialogSearchCB(w, client_data, call_data );
1102 } /* end _DtEditorMisspelledDblClickCB */
1106 * The following functions effectively track whether the user has
1107 * entered or changed the "Find" text. This information is used to make
1108 * the "Find" and "Change All" buttons sensitive/desensitive. The
1109 * "Find" button must be pressed and the Find text found before the
1110 * "Change" button is sensitive. These functions also set the default
1111 * button to either the "Find" or "Close" button.
1115 _DtEditorSetFindSensitivity(
1116 DtEditorWidget widget,
1117 Boolean sensitivity)
1119 XtSetSensitive(M_search_findBtn(widget), sensitivity);
1123 _DtEditorSetReplaceSensitivity(
1124 DtEditorWidget editor,
1125 Boolean sensitivity)
1128 * Cannot enable Change button if widget is read only
1130 if ( M_editable(editor) || !sensitivity )
1131 XtSetSensitive(M_search_replaceBtn(editor), sensitivity);
1135 _DtEditorSetReplaceAllSensitivity(
1136 DtEditorWidget editor,
1137 Boolean sensitivity)
1140 * Cannot enable Change All button if widget is read only
1142 if ( M_editable(editor) || !sensitivity )
1143 XtSetSensitive(M_search_replaceAllBtn(editor), sensitivity);
1148 _DtEditorFindTextChangedCB(
1150 caddr_t client_data,
1153 Arg al[10]; /* arg list */
1154 Widget defaultButton;
1157 DtEditorWidget editor = (DtEditorWidget)client_data;
1160 * Is there a Find string?
1162 pString = XmTextFieldGetString(M_findText(editor));
1165 * Only enable the Find & Change All buttons if there is a
1166 * string to search for (i.e. a Find string).
1168 if(pString == (char *)NULL || *pString == (char)'\0') {
1169 _DtEditorSetFindSensitivity(editor, False );
1170 _DtEditorSetReplaceAllSensitivity(editor, False );
1172 * Make the Close button the default
1174 defaultButton = M_search_closeBtn(editor);
1177 _DtEditorSetFindSensitivity( editor, True );
1178 _DtEditorSetReplaceAllSensitivity(editor, True );
1180 * Make the Find button the default
1182 defaultButton = M_search_findBtn(editor);
1184 if(pString != (char *)NULL)
1188 * Set the default button
1190 XtSetArg(al[0], XmNdefaultButton, defaultButton);
1191 XtSetValues(M_search_dialog(editor), al, 1);
1194 * Disable the Change button. It will be enabled when the Find
1195 * button is pressed and the Find text is successfully found.
1197 _DtEditorSetReplaceSensitivity(editor, False );
1199 } /* end _DtEditorFindTextChangedCB */
1202 * The following functions effectively track whether the user has
1203 * entered or changed the Change To text. This information is used
1204 * in the Spell dialog to make the Change and Change All buttons
1205 * sensitive/desensitive so users cannot replace a misspelled word with
1211 _DtEditorReplaceTextChangedCB(
1213 caddr_t client_data,
1218 DtEditorWidget editor = (DtEditorWidget)client_data;
1221 * Ignore this callback if it is not being called from the Spell
1225 if( M_search_dialogMode(editor) == SPELL ) {
1227 * Is there a Change To string?
1229 pString = XmTextFieldGetString(M_replaceText(editor));
1232 * Disable the Change & Change All buttons if there is
1233 * no Change To string.
1235 if( pString == (char *)NULL || *pString == (char)'\0' ) {
1236 _DtEditorSetReplaceSensitivity(editor, False );
1237 _DtEditorSetReplaceAllSensitivity(editor, False );
1241 * If there is a Change To string enable the Change
1242 * All button, but only enable the Change button if.
1243 * the Find button has been pressed & the misspelled
1244 * word found (see _DtEditorDialogSearchCB()
1246 _DtEditorSetReplaceAllSensitivity(editor, True );
1247 if ( M_misspelled_found(editor) )
1248 _DtEditorSetReplaceSensitivity(editor, True );
1250 if(pString != (char *)NULL)
1257 } /* end _DtEditorReplaceTextChangedCB */
1261 Check to see if the process is in the group, gid.
1263 static Boolean IsInGroup(gid_t gid)
1265 gid_t grps[NGROUPS_MAX];
1269 num_grps = getgroups(NGROUPS_MAX, grps);
1274 for (i=0; i < num_grps; i++) {
1284 Check to see if the process can execute the filter.
1286 static Boolean IsExecutable(struct stat statbuf)
1288 Boolean ingroup = IsInGroup(statbuf.st_gid);
1290 if (geteuid() == 0) { /** if root **/
1291 /** if any execute bit is set, root can execute **/
1292 if ((statbuf.st_mode & S_IXUSR)
1293 || (statbuf.st_mode & S_IXGRP)
1294 || (statbuf.st_mode & S_IXOTH))
1303 * if this process is the user and the user
1304 * does have execute permission, then the
1305 * filter will run, so return false
1307 if ((statbuf.st_uid == geteuid())
1308 && (statbuf.st_mode & S_IXUSR))
1314 * if this process is in the group for the
1315 * filter and group execute is set (and the
1316 * process isn't the user, then return true
1319 && (statbuf.st_mode & S_IXGRP)
1320 && (statbuf.st_uid != geteuid()))
1326 * if this process is not in the group or the user
1327 * for the filter and other execute is set, then
1330 if ((statbuf.st_mode & S_IXOTH)
1331 && (statbuf.st_uid != geteuid())
1343 This function checks to makes sure that this filter
1344 can be found, i.e. is in the current path and istalled.
1346 static Boolean IsValidFilter(DtEditorWidget pPriv)
1352 struct stat statbuf;
1353 _Xstrtokparams strtok_buf;
1355 /** check to see if a full path to the filter is given **/
1356 if (*M_spellFilter(pPriv) == '/') {
1357 if (stat(M_spellFilter(pPriv), &statbuf) != -1)
1358 return(IsExecutable(statbuf));
1365 * get the PATH from the environment and check to see if
1366 * the filter is in the path
1368 pathstr = getenv("PATH");
1369 if (pathstr == NULL)
1372 pathtmp = XtNewString(pathstr);
1373 pathtok = _XStrtok(pathtmp, ":", strtok_buf);
1374 while (pathtok != NULL) {
1375 tmp = (char*)XtMalloc((strlen(pathtok)
1376 + strlen(M_spellFilter(pPriv))
1377 + 2) * sizeof(char));
1378 strcpy(tmp, pathtok);
1380 strcat(tmp, M_spellFilter(pPriv));
1381 if (stat(tmp, &statbuf) != -1) {
1384 return(IsExecutable(statbuf));
1387 pathtok = _XStrtok(NULL,":", strtok_buf);