/* This file contains routines that manipulate single and multi-line * text entry widgets. * * * This code is under the GNU Copyleft. * * Dominic Giampaolo * dbg@sgi.com */ #include #include #include "xstuff.h" #include #include "libsx.h" #include "libsx_private.h" extern WindowState *lsx_curwin; /* global handle to the current window */ /* * this structure maintains some internal state information about each * string entry widget. */ typedef struct StringInfo { Widget str_widget; void (*func)(); void *user_data; struct StringInfo *next; }StringInfo; static StringInfo *string_widgets = NULL; /* * String Entry Widget Creation stuff. */ Widget MakeStringEntry(txt, size, func, data, name) char *txt; int size; StringCB func; void *data; char *name; { static int already_done = FALSE; static XtTranslations trans; int n = 0; Arg wargs[10]; /* Used to set widget resources */ Widget str_entry; StringInfo *stri; if (lsx_curwin->toplevel == NULL && OpenDisplay(0, NULL) == 0) return NULL; if (already_done == FALSE) { already_done = TRUE; trans = XtParseTranslationTable("#override\n\ Return: done_with_text()\n\ Linefeed: done_with_text()\n\ CtrlM: done_with_text()\n\ CtrlJ: done_with_text()\n"); } stri = (StringInfo *)malloc(sizeof(*stri)); if (stri == NULL) return NULL; stri->func = func; stri->user_data = data; n = 0; XtSetArg(wargs[n], XtNeditType, XawtextEdit); n++; XtSetArg(wargs[n], XtNwrap, XawtextWrapNever); n++; XtSetArg(wargs[n], XtNresize, XawtextResizeWidth); n++; XtSetArg(wargs[n], XtNtranslations, trans); n++; XtSetArg(wargs[n], XtNwidth, size); n++; if (txt) { XtSetArg(wargs[n], XtNstring, txt); n++; XtSetArg(wargs[n], XtNinsertPosition, strlen(txt)); n++; } str_entry = XtCreateManagedWidget(name, asciiTextWidgetClass, lsx_curwin->form_widget,wargs,n); if (str_entry) /* only if we got a real widget do we bother */ { stri->str_widget = str_entry; stri->next = string_widgets; string_widgets = stri; } else free(stri); return str_entry; } /* end of MakeStringEntry() */ /* * Private internal callback for string entry widgets. */ void libsx_done_with_text(w, xev, parms, num_parms) Widget w; XEvent *xev; String *parms; Cardinal *num_parms; { int n = 0; Arg wargs[10]; /* Used to get widget resources */ char *txt; StringInfo *stri; n = 0; XtSetArg(wargs[n], XtNstring, &txt); n++; XtGetValues(w, wargs, n); /* * Find the correct ScrollInfo structure. */ for(stri=string_widgets; stri; stri=stri->next) { for(; stri && stri->str_widget != w; stri=stri->next) ; if (stri) /* didn't find it. */ break; if (XtDisplay(stri->str_widget) == XtDisplay(w)) /* did find it */ break; } if (stri == NULL) return; if (stri->func) stri->func(w, txt, stri->user_data); /* call the user's function */ } void SetStringEntry(w, new_text) Widget w; char *new_text; { int n = 0; Arg wargs[2]; /* Used to set widget resources */ if (lsx_curwin->toplevel == NULL || w == NULL) return; n = 0; XtSetArg(wargs[n], XtNstring, new_text); n++; XtSetValues(w, wargs, n); /* * Have to set this resource separately or else it doesn't get * updated in the display. Isn't X a pain in the ass? * * (remember that with X windows, form follows malfunction) */ n = 0; XtSetArg(wargs[n], XtNinsertPosition, strlen(new_text)); n++; XtSetValues(w, wargs, n); } char *GetStringEntry(w) Widget w; { int n = 0; Arg wargs[2]; /* Used to set widget resources */ char *text; if (lsx_curwin->toplevel == NULL || w == NULL) return NULL; n = 0; XtSetArg(wargs[n], XtNstring, &text); n++; XtGetValues(w, wargs, n); return text; } /* * Full Text Widget creation and support routines. */ /* forward prototype */ char *slurp_file(); Widget MakeTextWidget(txt, is_file, editable, w, h, name) char *txt; int is_file, editable, w, h; char *name; { int n; Arg wargs[10]; Widget text; char *real_txt; static int already_done = FALSE; static XtTranslations trans; if (lsx_curwin->toplevel == NULL && OpenDisplay(0, NULL) == 0) return NULL; if (already_done == FALSE) { already_done = TRUE; trans = XtParseTranslationTable("#override\n\ Prior: previous-page()\n\ Next: next-page()\n\ Home: beginning-of-file()\n\ End: end-of-file()\n\ CtrlUp: beginning-of-file()\n\ CtrlDown: end-of-file()\n\ ShiftUp: previous-page()\n\ ShiftDown: next-page()\n"); } n=0; XtSetArg(wargs[n], XtNwidth, w); n++; XtSetArg(wargs[n], XtNheight, h); n++; XtSetArg(wargs[n], XtNscrollHorizontal, XawtextScrollWhenNeeded); n++; XtSetArg(wargs[n], XtNscrollVertical, XawtextScrollWhenNeeded); n++; XtSetArg(wargs[n], XtNautoFill, TRUE); n++; XtSetArg(wargs[n], XtNtranslations, trans); n++; if (is_file && txt) { real_txt = slurp_file(txt); } else real_txt = txt; if (real_txt) { XtSetArg(wargs[n], XtNstring, real_txt); n++; } if (editable) { XtSetArg(wargs[n], XtNeditType, XawtextEdit); n++; } text = XtCreateManagedWidget(name, asciiTextWidgetClass, lsx_curwin->form_widget,wargs,n); if (real_txt != txt && real_txt != NULL) free(real_txt); /* we're done with the buffer */ return text; } void SetTextWidgetText(w, txt, is_file) Widget w; char *txt; int is_file; { int n; Arg wargs[3]; char *real_txt; Widget source; if (lsx_curwin->toplevel == NULL || w == NULL || txt == NULL) return; source = XawTextGetSource(w); if (source == NULL) return; if (is_file) { real_txt = slurp_file(txt); } else real_txt = txt; XtSetArg(wargs[0], XtNstring, real_txt); XtSetValues(source, wargs, 1); if (real_txt != txt && real_txt != NULL) free(real_txt); /* we're done with the buffer */ } char *GetTextWidgetText(w) Widget w; { int n; Arg wargs[4]; char *text=NULL; Widget source; if (lsx_curwin->toplevel == NULL || w == NULL) return NULL; source = XawTextGetSource(w); if (source == NULL) return NULL; n=0; XtSetArg(wargs[n], XtNstring, &text); n++; XtGetValues(source, wargs, n); return text; } #include #include #include char *slurp_file(fname) char *fname; { struct stat st; char *buff; int fd, count; if (stat(fname, &st) < 0) return NULL; if (S_ISDIR(st.st_mode) == TRUE) /* don't want to edit directories */ return NULL; buff = (char *)malloc(sizeof(char)*(st.st_size+1)); if (buff == NULL) return NULL; fd = open(fname, O_RDONLY); if (fd < 0) { free(buff); return NULL; } count = read(fd, buff, st.st_size); buff[count] = '\0'; /* null terminate */ close(fd); return (buff); }