/* * @OPENGROUP_COPYRIGHT@ * COPYRIGHT NOTICE * Copyright (c) 1990, 1991, 1992, 1993 Open Software Foundation, Inc. * Copyright (c) 1996, 1997, 1998, 1999, 2000 The Open Group * ALL RIGHTS RESERVED (MOTIF). See the file named COPYRIGHT.MOTIF for * the full copyright text. * * This software is subject to an open license. It may only be * used on, with or for operating systems which are themselves open * source systems. You must contact The Open Group for a license * allowing distribution and sublicensing of this software on, with, * or for operating systems which are not Open Source programs. * * See http://www.opengroup.org/openmotif/license for full * details of the license agreement. Any use, reproduction, or * distribution of the program constitutes recipient's acceptance of * this agreement. * * EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, THE PROGRAM IS * PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY * WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY * OR FITNESS FOR A PARTICULAR PURPOSE * * EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, NEITHER RECIPIENT * NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY DIRECT, * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN * ANY WAY OUT OF THE USE OR DISTRIBUTION OF THE PROGRAM OR THE * EXERCISE OF ANY RIGHTS GRANTED HEREUNDER, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGES. */ /* * HISTORY */ #ifdef REV_INFO #ifndef lint static char rcsid[] = "$XConsortium: text.c /main/7 1996/10/30 10:28:07 cde-osf $" #endif #endif #include "text.h" /* =================================================================== * The OK callback for FSB. Check the selected file can be opened. * If so, close the old file, read the new file. * Create an unmapped text source with the contents of the file. */ void FileOKCallback(Widget fsb, ViewPtr this, XmFileSelectionBoxCallbackStruct *call_data) { FILE * file; char * path; char *buffer; static char no_file[] = "no_file" ; static XmString no_file_msg = NULL; XmPushButtonCallbackStruct dummy; int filesize; XmStringContext ctxt; XmStringCharSet charset; XmStringDirection dir; Boolean sep; XmStringInitContext(&ctxt, call_data->value); XmStringGetNextSegment(ctxt, &path, &charset, &dir, &sep); XmStringFreeContext(ctxt); XtFree((char *)charset); if (((file = OpenFile(path)) == NULL) || (buffer = ReadFile(file, &filesize)) == NULL) { if (no_file_msg == NULL) no_file_msg = FetchString(this, no_file); ViewError(this, no_file_msg, call_data->value); } else { PanePtr pane = this->panes, tmp; XtPopdown(XtParent(fsb)); while ( pane != NULL) { /* destroy all panes */ XtDestroyWidget(pane->text); tmp = pane; pane = pane->next; XtFree((char *)tmp); --this->n_panes; } this->panes = NULL; this->current_pane = NULL; /* Set the new source text */ XmTextSetString(this->text_source, buffer); XtFree(buffer); XtFree(path); CloseFile(file); NewPaneCallback(this->paned_window, this, &dummy); XtVaSetValues(this->path, XmNlabelString, call_data->value, NULL); } } /* =================================================================== * The new pane callback. Create a new pane in the pane window. * Alloc a pane structure, initialize it. * Set focus to the new pane. * Allow menu items on panes. */ void NewPaneCallback(Widget widget, ViewPtr this, XmPushButtonCallbackStruct *call_data) { PanePtr new; Arg args[10]; int n = 0; Dimension height; short index ; Widget target = NULL; new = (PanePtr) XtCalloc(sizeof(Pane), 1); if (this->panes != NULL) this->panes->previous = new; new->next = this->panes; this->panes = new; /* * If not first time, split current pane in 2 to create the new pane */ if (this->n_panes == 0) { /* first time, just load the file */ SetSensitive(this->view_cascade, new_pane, True); SetSensitive(this->view_cascade, search, True); } else { target = XtParent(this->current_pane->text); } ++this->n_panes; n = 0; XtSetArg(args[n], XmNeditMode, XmMULTI_LINE_EDIT); n++; XtSetArg(args[n], XmNallowResize, True); n++; new->text = XmCreateScrolledText(this->paned_window, "pane", args, n); /* XtAddCallback(new->text, XmNmodifyVerifyCallback, (XtCallbackProc) NoInsert, this); */ XtAddCallback(new->text, XmNfocusCallback, (XtCallbackProc) ChangeCurrentPane, this); XmTextSetSource(new->text, XmTextGetSource(this->text_source), 0, 0); if (target != NULL) { /* this is not the first pane */ n = 0; XtSetArg(args[n], XmNpositionIndex, &index); n++; XtSetArg(args[n], XmNheight, &height); n++; XtGetValues(target, args, n); ++index; printf("set source text\n"); n = 0; XtSetArg(args[n], XmNpositionIndex, index); n++; XtSetArg(args[n], XmNheight, (Dimension) height/2); n++; XtSetValues(XtParent(new->text), args, n); XmTextSetTopCharacter(new->text, XmTextGetTopCharacter(this->current_pane->text)); XtVaSetValues(target, XmNheight, (Dimension) height/2); } printf("source text set\n"); XtManageChild(new->text); if (this->n_panes == 2) SetSensitive(this->view_cascade, kill_pane, True); XmProcessTraversal(new->text, XmTRAVERSE_CURRENT); this->current_pane = new; } /* =================================================================== * The kill pane callback. Delete a pane in the pane window. * Free pane structure. */ void KillPaneCallback(Widget button, ViewPtr this, XmPushButtonCallbackStruct *call_data) { PanePtr *pane, tmp; /* printf("%d panes left\n", this->n_panes-1); */ for (pane = &this->panes; *pane != this->current_pane; ) pane = &((*pane)->next); /* * Destroy the old one, free memory. * Do not allow the last pane to be destroyed * Make destroy command unavailable if last pane. * Make next or previous pane become current and traverse to it. */ tmp = *pane; *pane = (*pane)->next; XtDestroyWidget(tmp->text); XtFree((char *)tmp); this->current_pane = (*pane == NULL) ? this->panes : *pane; if ( --this->n_panes < 2 ) SetSensitive(this->view_cascade, kill_pane, False); XmProcessTraversal(this->current_pane->text, XmTRAVERSE_CURRENT); } /* ===================================================================== * Focus has moved. Change current pane. */ static void ChangeCurrentPane(Widget text, ViewPtr this, XmAnyCallbackStruct verify) { PanePtr pane = this->panes; while (pane != NULL) { if (pane->text == text) break; pane = pane->next; } this->current_pane = pane; } /* =============================================================== * The Find Callback. The parent widget is passed as client data. * */ void FindCallback(Widget button, ViewPtr this, XmPushButtonCallbackStruct *call_data) { Widget template; XtCallbackRec ok[2], cancel[2]; #define NUMBOXES 4 #define NUMBUTTONS 2 #define TITLEDFRAME 2 Widget framed[TITLEDFRAME]; Widget frame; Widget forward, backward; if ( this->search_box == NULL ) { Arg args[10]; int n = 0; search_msg = FetchString(this, search_prompt); XtSetArg(args[n], XmNautoUnmanage, False); n++; XtSetArg(args[n], XmNmessageString, search_msg); n++; ok[0].callback = (XtCallbackProc) SearchSubstring; ok[0].closure = (XtPointer) this; ok[1].callback = cancel[1].callback = NULL; ok[1].closure = cancel[1].closure = NULL; cancel[0].callback = (XtCallbackProc) CancelSearch; cancel[0].closure = (XtPointer) this; XtSetArg(args[n], XmNokCallback, (XtCallbackList) ok); n++; XtSetArg(args[n], XmNcancelCallback, (XtCallbackList) cancel); n++; this->search_box = XmCreateTemplateDialog(this->shell, "search_box", args, n); n = 0; template = XmCreateForm(this->search_box, "form", args, n); n = 0; XtSetArg(args[n], XmNbottomAttachment, XmATTACH_FORM); n++; XtSetArg(args[n], XmNrightAttachment, XmATTACH_FORM) ; n++; XtSetArg(args[n], XmNleftAttachment, XmATTACH_FORM) ; n++; this->search_entry = XmCreateTextField(template, "entry", args, n); n = 0; XtSetArg(args[n], XmNtopAttachment, XmATTACH_FORM); n++; XtSetArg(args[n], XmNbottomAttachment,XmATTACH_WIDGET); n++; XtSetArg(args[n], XmNbottomWidget, this->search_entry); n++; XtSetArg(args[n], XmNrightAttachment, XmATTACH_FORM) ; n++; XtSetArg(args[n], XmNleftAttachment, XmATTACH_FORM) ; n++; frame = XmCreateFrame(template, "dir_frame", args, n); n = 0; XtSetArg(args[n], XmNframeChildType, XmFRAME_TITLE_CHILD); n++; framed[0] = XmCreateLabel(frame, "title", args, n); n = 0; XtSetArg(args[n], XmNframeChildType, XmFRAME_WORKAREA_CHILD); n++; XtSetArg(args[n], XmNisAligned, True); n++; XtSetArg(args[n], XmNradioAlwaysOne, True); n++; XtSetArg(args[n], XmNentryAlignment, XmALIGNMENT_END); n++; XtSetArg(args[n], XmNentryClass, xmToggleButtonWidgetClass); n++; XtSetArg(args[n], XmNorientation, XmVERTICAL); n++; this->direction = framed[1] = XmCreateRadioBox(frame, "direction", args, n); n = 0; XtSetArg(args[n], XmNuserData, XmTEXT_FORWARD); n++; forward = XmCreateToggleButton(framed[1], "forward", args, n); n = 0; XtSetArg(args[n], XmNuserData, XmTEXT_BACKWARD); n++; backward = XmCreateToggleButton(framed[1], "backward", args, n); XtManageChild(forward); XtManageChild(backward); XtManageChildren(framed, TITLEDFRAME); XmToggleButtonSetState(forward, True, True); XtManageChild(this->search_entry); XtManageChild(frame); XtManageChild(template); } if (XtIsManaged(this->search_box)) XtPopup(XtParent(this->search_box), XtGrabNone); else XtManageChild(this->search_box); XmProcessTraversal(this->search_entry, XmTRAVERSE_CURRENT); #undef NUMBUTTONS #undef NUMBOXES #undef TITLEDFRAME } /* =============================================================== * The Find Callback. The View object is passed as client data. * */ static void CancelSearch(Widget button, ViewPtr this, XmPushButtonCallbackStruct *call_data) { XtPopdown(XtParent(this->search_box)); } /* =============================================================== * The Find Callback. The parent widget is passed as client data. * */ static void SearchSubstring(Widget button, ViewPtr this, XmPushButtonCallbackStruct *call_data) { #define STRING_MAX_CHARS 1024 char *substring; /* int status; */ XmTextPosition pos; /* int last = XmTextFieldGetLastPosition(this->search_entry); */ XmString search = NULL; XmTextDirection direction; Widget toggle; /* status = XmTextFieldGetSubstring(this->search_entry, 0, last, STRING_MAX_CHARS, substring); if (status == XmCOPY_FAILED || status == XmCOPY_TRUNCATED) { if (no_search_msg == NULL) no_search_msg = FetchString(this, no_search); search = XmStringCreateLocalized(substring); ViewWarning(this, no_search_msg, search); return; } */ substring = XmTextFieldGetString(this->search_entry); if (substring == NULL) { if (no_pattern_msg == NULL) no_pattern_msg = FetchString(this, no_pattern); ViewWarning(this, no_pattern_msg, (XmString) NULL); return; } XtVaGetValues(this->direction, XmNmenuHistory, &toggle, NULL); XtVaGetValues(toggle, XmNuserData, &direction, NULL); if (XmTextFindString(this->current_pane->text, XmTextGetInsertionPosition(this->current_pane->text), substring, direction, &pos)) { XmTextSetTopCharacter(this->current_pane->text, pos); XmTextSetInsertionPosition(this->current_pane->text, pos); XtPopdown(XtParent(this->search_box)); } else { if (not_found_msg == NULL) not_found_msg = FetchString(this, not_found); search = XmStringCreateLocalized(substring); ViewWarning(this, not_found_msg, search); XmStringFree(search); } XtFree(substring); } /* ===================================================================== * Reject text insertion */ static void NoInsert(Widget text, ViewPtr this, XmTextVerifyPtr verify) { /* if (verify->startPos != verify->endPos) printf("deleting text %d %d\n", verify->startPos, verify->endPos); if (verify->text != NULL && verify->text->length > 0) printf("inserting %d characters: '%s'\n", verify->text->length, verify->text->ptr); */ }