argv@island.uu.net (Dan Heller) (07/22/89)
Submitted-by: Mark Moraes <moraes@ai.toronto.edu> Posting-number: Volume 4, Issue 80 Archive-name: xpic/part15 #! /bin/sh # This is a shell archive. Remove anything before this line, then unpack # it by saving it into a file and typing "sh file". To overwrite existing # files, type "sh file -c". You can also feed this as standard input via # unshar, or by typing "sh <file", e.g.. If this archive is complete, you # will see the following message at the end: # "End of archive 15 (of 15)." # Contents: xpic/Minibuf.c # Wrapped by moraes@neat.ai on Thu Jul 13 22:36:13 1989 PATH=/bin:/usr/bin:/usr/ucb ; export PATH if test -f 'xpic/Minibuf.c' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'xpic/Minibuf.c'\" else echo shar: Extracting \"'xpic/Minibuf.c'\" \(29988 characters\) sed "s/^X//" >'xpic/Minibuf.c' <<'END_OF_FILE' X/* $Header: Minibuf.c,v 1.5 89/06/30 03:38:22 moraes Exp $ */ X/* X * This file should be edited with 4-column tabs! (:set ts=4 sw=4 in X * vi, set internal-tabstop 4 in Jove, and use edit-tab-stops in Emacs X * to get them X */ X X/* X * This set of routines create and manipulate a simple one-line input X * window. They offer a reasonable subset of EMACS like editing X * capabilities, Like EMACS, the command-key to action bindings can be X * altered. It does no data validation. The minibuffer can be created X * using normal Xt calls, with args, and parsing the resources. Other X * calls allow strings to be displayed or input or both. (prompted X * input). There is no restriction on the length of the input line, X * which will horizontally scroll in the window, EMACS-style, by half X * the "screen" width. It can be used in dialog boxes, or as in xpic, X * for an interaction line. X */ X/* X * Since this is the first (and only) widget I've written, there are X * probably lots of things done wrong. Feel free to fix 'em. This was X * written because the Text widgets available are more powerful than I X * need, but aren't capable of performing the simple function that this X * performs - display a prompt, a default chunk of text, and permit X * editing of the default. MOST important, it must invoke some sort of X * callback when the user hits RETURN or ^G/^C. As a minor point, I X * hate the silly underline ^ cursor that the text widget allows. Give X * me a solid blob anyday. It would be nice if someone could hack this X * capability into the Text widget - after a bit of digging in its X * code, I decided that preserving my sanity (or what's left of it) was X * important, and chose to write this - it was much simpler. X */ X/* Author: Mark Moraes (moraes@csri.toronto.edu) X History: First written for X10 under the X10 tookit, for xpic in X August 1987. X This version was ported to X11, and then tuned and cleaned X up - X11 is so much slower on Suns that the inefficient X redisplay strategy used in the X10 version was unfeasible X June 1988. X */ X/* To do: X Get it to understand the subtleties of reverse video X */ X X#include <strings.h> X#include <ctype.h> X#ifdef DEBUG X#include <stdio.h> X#endif X#include <X11/Xlib.h> X#include <X11/StringDefs.h> X#include <X11/IntrinsicP.h> X#include <X11/Intrinsic.h> X#include <X11/keysymdef.h> X#include <X11/CoreP.h> X#include <X11/Core.h> X#include "MinibufP.h" X#include "Minibuf.h" X X#include "assert.h" X X/* To keep references to data less than six miles long */ X#define mbuf(x) buf->minibuf.x X#define mcore(x) buf->core.x X#define fontwidth(x) ((x)->max_bounds.rbearing - (x)->min_bounds.lbearing) X#define fontheight(x) ((x)->max_bounds.ascent + (x)->max_bounds.descent) X#define fontbaseline(x) ((x)->max_bounds.ascent) X#define CheckMode() if (mbuf(inputMode) == FALSE) return; else ; X X X/* X * This should be larger than the expected filesize - if a XtRealloc X * occurs in insert_s(), add_mess(), bad things will happen because the X * f_complete routines don't expect the string to change while they're X * working - fixing this is work that I don't feel upto right now - one X * day.... X */ X#define BUF_BLOCK 128 X X#define MIN_COLS 5 X#define DEFAULTFONT "8x13" X#define ABORT_MSG "[Aborted]" X#define DELAY 300000 /* X * Microseconds of delay for cursor X * flash in SetMark X */ X X/* The default bindings */ Xstatic char defaultTranslations[] = X "Ctrl<Key>F: forward-character()\n\ X <Key>0xff53: forward-character()\n\ X Ctrl<Key>B: backward-character()\n\ X <Key>0xff51: backward-character()\n\ X Ctrl<Key>A: beginning-of-line()\n\ X Ctrl<Key>E: end-of-line()\n\ X Ctrl<Key>U: universal-argument()\n\ X Ctrl<Key>D: delete-next-character()\n\ X Ctrl<Key>H: delete-previous-character()\n\ X <Key>0xff7f: delete-previous-character()\n\ X <Key>0xffff: delete-previous-character()\n\ X <Key>0xff08: delete-previous-character()\n\ X Ctrl<Key>X: exchange-point-and-mark()\n\ X Ctrl<Key>W: kill-region()\n\ X Ctrl<Key>K: kill-to-end-of-line()\n\ X Meta<Key>D: kill-to-beginning-of-line()\n\ X Ctrl<Key>Y: yank-killed-text()\n\ X Ctrl<Key>J: newline()\n\ X <Key>0xff0a: newline()\n\ X Ctrl<Key>M: newline()\n\ X <Key>0xff0d: newline()\n\ X Ctrl<Key>G: abort()\n\ X Ctrl<Key>C: abort()\n\ X <Btn1Down>: set-cursor-to-mouse()\n\ X <Btn2Down>: get-x-buffer()\n\ X <Btn3Down>: set-mark-to-mouse()\n\ X Ctrl<Key>0x20: make-this-the-mark()\n\ X <Key>0x20: complete-filename()\n\ X Ctrl<Key>I: complete-filename()\n\ X <Key>0xff09: complete-filename()\n\ X Shift<Key>/: list-files()\n\ X <Key>/: insert-char()\n\ X <Key>?: list-files()\n\ X <Key>: insert-char()\n\ X"; X X Xstatic void CursorForward(), CursorBack(), BeginningOfBuf(), EndOfBuf(), X UnivArgument(), DeleteCharForward(), DeleteCharBack(), KillToEnd(), X KillToBeginning(), YankKilledStuff(), MakeMark(), ExchangeMarkAndPoint(), X CutMarkToPoint(), FinishedInput(), QuitInput(), SetCursor(), SetMark(), X GetXBuffer(), CharInsert(), CompleteFilename(), ListFiles(); X X/* Actions Table */ Xstatic XtActionsRec actionsList [] = { X/* motion bindings */ X {"forward-character", CursorForward}, X {"backward-character", CursorBack}, X {"beginning-of-line", BeginningOfBuf}, X {"end-of-line", EndOfBuf}, X {"universal-argument", UnivArgument}, X/* delete bindings */ X {"delete-next-character", DeleteCharForward}, X {"delete-previous-character", DeleteCharBack}, X/* kill bindings */ X {"kill-to-end-of-line", KillToEnd}, X {"kill-to-beginning-of-line", KillToBeginning}, X/* yank bindings */ X {"yank-killed-text", YankKilledStuff}, X {"make-this-the-mark", MakeMark}, X {"exchange-point-and-mark", ExchangeMarkAndPoint}, X {"kill-region", CutMarkToPoint}, X/* new line stuff */ X {"newline", FinishedInput}, X {"abort", QuitInput}, X/* Selection stuff */ X {"set-cursor-to-mouse", SetCursor}, X {"set-mark-to-mouse", SetMark}, X {"get-x-buffer", GetXBuffer}, X/* filename completion and listing of files */ X {"complete-filename", CompleteFilename}, X {"list-files", ListFiles}, X/* Insert character */ X {"insert-char", CharInsert}, X}; X Xstatic int zero = 0; X X#define offset(field) XtOffset(MinibufWidget, field) Xstatic XtResource resources[] = { X {XtNforeground, XtCForeground, XtRPixel, sizeof(Pixel), X offset(minibuf.foreground), XtRString, "Black"}, X {XtNfont, XtCFont, XtRFontStruct, sizeof(XFontStruct *), X offset(minibuf.finfo),XtRString, DEFAULTFONT}, X {XtNcursor, XtCCursor, XtRCursor, sizeof(Cursor), X offset(minibuf.cursor), XtRString, "xterm"}, X {XtNfinishedCallback, XtCCallback, XtRCallback, sizeof(XtProc), X offset(minibuf.finishedCallback), XtRCallback, (caddr_t)NULL}, X#ifdef TYPEOUT X {XtNtypeoutColumns, XtCTypeoutColumns, XtRInt, sizeof(int), X offset(minibuf.typeoutColumns), XtRInt, (caddr_t)&zero}, X {XtNtypeout, XtCtypeout, XtRPointer, sizeof(Widget), X offset(minibuf.typeout), XtRPointer, (caddr_t)NULL}, X#endif X}; X Xstatic void Initialize(), Realize(), Destroy(), Redisplay(), Resize(); X X/* X * ...ClassData must be initialized at compile time. Must initialize X * all substructures. (Actually, last two here need not be initialized X * since not used.) X */ XMinibufClassRec minibufClassRec = { X { X (WidgetClass) &widgetClassRec, /* superclass */ X "Minibuf", /* class_name */ X sizeof(MinibufRec), /* size */ X NULL, /* class_initialize */ X NULL, /* class_part_initialize*/ X FALSE, /* class_inited */ X Initialize, /* initialize */ X NULL, /* initialize_hook */ X Realize, /* realize */ X actionsList, /* actions */ X XtNumber(actionsList), /* num_actions */ X resources, /* resources */ X XtNumber(resources), /* resource_count */ X NULLQUARK, /* xrm_class */ X TRUE, /* compress_motion */ X TRUE, /* compress_exposure */ X TRUE, /* compress_enterleave */ X FALSE, /* visible_interest */ X Destroy, /* destroy */ X Resize, /* resize */ X Redisplay, /* expose */ X NULL, /* set_values */ X NULL, /* set_values_hook */ X XtInheritSetValuesAlmost, /* set_values_almost */ X NULL, /* get_values_hook */ X NULL, /* accept_focus */ X XtVersion, /* version */ X NULL, /* callback_private */ X defaultTranslations, /* tm_table */ X NULL, /* query_geometry */ X#ifdef XtCAccelerators X XtInheritDisplayAccelerator, /* display_accelerator */ X NULL /* extension */ X#endif /* XtCAccelerators */ X }, /* CoreClass fields initialization */ X { X 0, /* field not used */ X }, /* MinibufClass fields initialization */ X}; X X/* for public consumption */ XWidgetClass minibufWidgetClass = (WidgetClass)&minibufClassRec; X X/*ARGSUSED*/ Xstatic void Initialize(request, new) XWidget request, new; X{ X register MinibufWidget buf = (MinibufWidget) new; X XGCValues gcv; X X mbuf(string) = mbuf(killBuffer) = NULL; X mbuf(size) = mbuf(startPos) = mbuf(cursorPos) = mbuf(mark) X = mbuf(killBufferLen) = mbuf(killBufferSize) = mbuf(len) X = mbuf(cols) = mbuf(promptLen) = 0; X mbuf(arg) = 1; X mbuf(cursorX) = 0; X mbuf(inputMode) = FALSE; X gcv.foreground = mbuf(foreground); X gcv.background = mcore(background_pixel); X gcv.font = mbuf(finfo)->fid; X mbuf(normal_gc) = XtGetGC(new, GCForeground | GCBackground | GCFont, X &gcv); X gcv.foreground = mbuf(foreground) ^ mcore(background_pixel); X gcv.function = GXxor; X mbuf(invert_gc) = XtGetGC(new, GCForeground | GCBackground | GCFont | X GCFunction, &gcv); X X /* Compute these correctly */ X if (mcore(height) == 0) X mcore(height) = fontheight(mbuf(finfo)); X X if ((mbuf(cols) = mcore(width) / fontwidth(mbuf(finfo))) < MIN_COLS) { X /* Set it to MIN_COLS */ X mcore(width) = MIN_COLS * fontwidth(mbuf(finfo)); X } X} X X/* Wish the primitive widget had a cursor .. */ Xstatic void Realize(w, valueMask, attributes) Xregister Widget w; XMask *valueMask; XXSetWindowAttributes *attributes; X{ X if ((attributes->cursor = ((MinibufWidget)w)->minibuf.cursor) != None) X *valueMask |= CWCursor; X X XtCreateWindow( w, (unsigned int)InputOutput, (Visual *)CopyFromParent, X *valueMask, attributes ); X} X Xstatic void Destroy(w) XWidget w; X{ X register MinibufWidget buf = (MinibufWidget) w; X X if (mbuf(string) != NULL) X free(mbuf(string)); X if (mbuf(killBuffer) != NULL) X free(mbuf(killBuffer)); X XtDestroyGC(mbuf(normal_gc)); X XtDestroyGC(mbuf(invert_gc)); X} X X X/*ARGSUSED*/ Xstatic void Redisplay(w, event, region) XWidget w; XXEvent *event; XRegion region; X{ X register MinibufWidget buf = (MinibufWidget) w; X static void DisplayBuf(), DisplayCursor(); X X if (!XtIsRealized(w)) X return; X DisplayBuf(buf, TRUE); X if (mbuf(cursorOn) == TRUE) X DisplayCursor(buf); X} X X Xstatic void Resize(w) XWidget w; X{ X register MinibufWidget buf = (MinibufWidget) w; X static void DisplayBuf(), DisplayCursor(); X X /* X * We should probably do some geometry management stuff here, if X * the number of cols is less than MIN_COLS X */ X mbuf(cols) = mcore(width) / fontwidth(mbuf(finfo)); X if (!XtIsRealized(w)) X return; X DisplayBuf(buf, TRUE); X if (mbuf(cursorOn) == TRUE) X DisplayCursor(buf); X} X X/* X * Displays the buffer. When called with redraw = TRUE, it clears the X * entire buffer and redraws it. If redraw = FALSE, then it clears from X * the cursor position to the end of the buffer, and then redraws just X * that section. This allows for fast update when a single character is X * typed, or deleted, usually at the end of the line. If redraw is X * FALSE, teh cursor must be turned off before this is called - X * otherwise it may or may not vanish, causing problems. Typically, we X * hide the cursor, then update the buffer string and data, and then X * call this procedure. Note that for delete-char-forward, char-insert, X * and StrInsert, this gets called AFTER the mbuf(string) is updated X * but before the mbuf(cursorPos) is updated, which in delete-char-back X * and cut-point-to-mark, it is called afetr the cursorPos is updated X * as well, so that the changed region is redrawn. X */ Xstatic void DisplayBuf(buf, redraw) Xregister MinibufWidget buf; Xint redraw; X{ X register int nChars, isLonger; X int start; X register Widget w = (Widget) buf; X X if (redraw) { X start = mbuf(startPos); X XClearWindow(XtDisplay(w), XtWindow(w)); X } else { X start = mbuf(cursorPos); X mbuf(cursorX) = (mbuf(cursorPos) - mbuf(startPos)) * X fontwidth(mbuf(finfo)); X XClearArea(XtDisplay(w), XtWindow(w), mbuf(cursorX), 0, X mcore(width) - mbuf(cursorX), (unsigned) fontheight(mbuf(finfo)), X False); X } X nChars = (mbuf(startPos) + mbuf(cols)); X isLonger = (nChars < mbuf(len)); X if (isLonger) X nChars -= start + 1; X else X nChars = mbuf(len) - start; X X XDrawImageString(XtDisplay(w), XtWindow(w), mbuf(normal_gc), X redraw? 0 : mbuf(cursorX), fontbaseline(mbuf(finfo)), X mbuf(string) + start, nChars); X X if (isLonger) X XDrawImageString(XtDisplay(w), XtWindow(w), mbuf(normal_gc), X (mbuf(cols) - 1) * fontwidth(mbuf(finfo)), X fontbaseline(mbuf(finfo)), "!", 1); X} X X X/* X * Display the buffer cursor. It does the devious computations for X * Horiz scrolling of the minibuffer, back and forward, and does a X * 'hard' redisplay (i.e. with a clear) of the window if a horiz. X * scroll is done. X */ Xstatic void DisplayCursor(buf) Xregister MinibufWidget buf; X{ X register int col; X register Widget w = (Widget) buf; X X if (mbuf(cursorPos) > mbuf(len)) X mbuf(cursorPos) = mbuf(len); X if (mbuf(cursorPos) < mbuf(promptLen)) X mbuf(cursorPos) = mbuf(promptLen); X X col = (mbuf(cursorPos) - mbuf(startPos)); X X if ((col >= mbuf(cols)) || (col < 0)) { X if (mbuf(cursorPos) < mbuf(cols) - 1) { X /* X * The cursor will be seen if the start X * position is 0, which looks nicer than half X * the prompt showing X */ X mbuf(startPos) = 0; X col = mbuf(cursorPos); X } else { X /* X * Horiz scroll the buffer to mbuf(cols)/2 X * before cursorPos. this acounts for both X * forward and backward scrolling. X */ X col = (mbuf(cols)) / 2 - 1; X mbuf(startPos) = mbuf(cursorPos) - col; X if (mbuf(startPos) < 0) { X mbuf(startPos) = 0; X col = (mbuf(cursorPos) - mbuf(startPos)); X } X } X DisplayBuf(buf, TRUE); X } X mbuf(cursorX) = col * fontwidth(mbuf(finfo)); X XFillRectangle(XtDisplay(w), XtWindow(w), mbuf(invert_gc), X mbuf(cursorX), 0, (unsigned) fontwidth(mbuf(finfo)), X (unsigned) fontheight(mbuf(finfo))); X mbuf(cursorOn) = TRUE; X} X X X X/* X * Hide the cursor X */ Xstatic void ConcealCursor(buf) Xregister MinibufWidget buf; X{ X register Widget w = (Widget) buf; X if (mbuf(cursorOn) == TRUE) { X XFillRectangle(XtDisplay(w), XtWindow(w), mbuf(invert_gc), X mbuf(cursorX), 0, (unsigned) fontwidth(mbuf(finfo)), X (unsigned) fontheight(mbuf(finfo))); X mbuf(cursorOn) = FALSE; X } X} X X X X/* X * Inserts len characters of string s into the buffer at the current X * cursor position. Note that it does not re-display the cursor, while X * CharInsert does. X */ X/* The universal argument has no effect on this one */ Xstatic void StrInsert(s, len, buf) Xregister char *s; Xregister int len; Xregister MinibufWidget buf; X{ X register int newLen = mbuf(len) + len; X static void QuitInput(); X X while (newLen > mbuf(size)) { X mbuf(size) += BUF_BLOCK; X if (mbuf(string) == NULL) X mbuf(string) = XtMalloc((unsigned) mbuf(size)); X else X mbuf(string) = XtRealloc(mbuf(string), (unsigned) mbuf(size)); X if ( mbuf(string) == NULL) { X mbuf(size) = 0; X mbuf(len) = 0; X mbuf(inputMode) = FALSE; X QuitInput((Widget) buf, (XEvent *) NULL, (String *) NULL, X (Cardinal *) NULL); X return; X } X } X bcopy(mbuf(string) + mbuf(cursorPos), mbuf(string) + mbuf(cursorPos) + len, X mbuf(len) - mbuf(cursorPos)); X bcopy(s, mbuf(string) + mbuf(cursorPos), len); X mbuf(len) += len; X DisplayBuf(buf, FALSE); X mbuf(cursorPos) += len; X mbuf(arg) = 1; X} X X X X/* X * Inserts c arg times into buffer string at current position and moves X * cursor forward X */ X/*ARGSUSED*/ Xstatic void CharInsert(w, event, params, numparams) XWidget w; XXEvent *event; XString *params; XCardinal *numparams; X{ X register MinibufWidget buf = (MinibufWidget) w; X register int i = mbuf(cursorPos); X register int j = mbuf(arg); X static void QuitInput(); X KeySym keysym; X XComposeStatus compose; X int status; X char c; X X CheckMode(); X status = XLookupString(&event->xkey, &c, 1, &keysym, &compose); X if (!status || !isascii(c) || !isprint(c)) X return; X ConcealCursor(buf); X while (mbuf(size) < mbuf(len) + mbuf(arg)) { /* Need more space */ X mbuf(size) += BUF_BLOCK; X if (mbuf(string) == NULL) X mbuf(string) = XtMalloc((unsigned) mbuf(size)); X else X mbuf(string) = XtRealloc(mbuf(string), (unsigned) mbuf(size)); X if (mbuf(string) == NULL) { X mbuf(size) = 0; X mbuf(len) = 0; X mbuf(inputMode) = FALSE; X QuitInput(w, event, params, numparams); X return; X } X } X X bcopy(mbuf(string) + i, mbuf(string) + i + mbuf(arg), X mbuf(len) - i); X mbuf(len) += mbuf(arg); X for (; j > 0; j--,i++) { X mbuf(string)[i] = c; X } X DisplayBuf(buf, FALSE); X mbuf(cursorPos) += mbuf(arg); X mbuf(arg) = 1; X DisplayCursor(buf); X} X X X/*ARGSUSED*/ Xstatic void CursorBack(w, event, params, numparams) XWidget w; XXEvent *event; XString *params; XCardinal *numparams; X{ X register MinibufWidget buf = (MinibufWidget) w; X register int i; X X CheckMode(); X if ((i = (mbuf(cursorPos) - mbuf(arg))) < mbuf(promptLen)) X i = mbuf(promptLen); X X ConcealCursor(buf); X mbuf(cursorPos) = i; X mbuf(arg) = 1; X DisplayCursor(buf); X} X X X/*ARGSUSED*/ Xstatic void CursorForward(w, event, params, numparams) XWidget w; XXEvent *event; XString *params; XCardinal *numparams; X{ X register MinibufWidget buf = (MinibufWidget) w; X register int i; X X CheckMode(); X if ((i = (mbuf(cursorPos) + mbuf(arg))) > mbuf(len)) X i = mbuf(len); X X ConcealCursor(buf); X mbuf(cursorPos) = i; X mbuf(arg) = 1; X DisplayCursor(buf); X} X X X/*ARGSUSED*/ Xstatic void SetCursor(w, event, params, numparams) XWidget w; XXEvent *event; XString *params; XCardinal *numparams; X{ X register MinibufWidget buf = (MinibufWidget) w; X Window foo1, foo2; X int foo3, foo4; X unsigned int foo5; X int x, y; X register int mCol; X X CheckMode(); X (void) XQueryPointer(XtDisplay(w), XtWindow(w), X &foo1, &foo2, &foo3, &foo4, &x, &y, &foo5); X mCol = x / fontwidth(mbuf(finfo)); X ConcealCursor(buf); X mbuf(cursorPos) = mbuf(startPos) + mCol; X mbuf(arg) = 1; X DisplayCursor(buf); X} X X/* X * Tries to flash the cursor to the mark, and then back to the cursor X * position. This will only be useful when bound to the mouse buttons. X */ X/*ARGSUSED*/ Xstatic void SetMark(w, event, params, numparams) XWidget w; XXEvent *event; XString *params; XCardinal *numparams; X{ X register MinibufWidget buf = (MinibufWidget) w; X register int tmp; X Window foo1, foo2; X int foo3, foo4; X unsigned int foo5; X int x, y; X register int mCol; X X CheckMode(); X tmp = mbuf(cursorPos); X (void) XQueryPointer(XtDisplay(w), XtWindow(w), X &foo1, &foo2, &foo3, &foo4, &x, &y, &foo5); X mCol = x / fontwidth(mbuf(finfo)); X ConcealCursor(buf); X mbuf(cursorPos) = mbuf(mark) = mbuf(startPos) + mCol; X DisplayCursor(buf); X XFlush(XtDisplay(w)); X usleep(DELAY); X ConcealCursor(buf); X mbuf(cursorPos) = tmp; X DisplayCursor(buf); X mbuf(arg) = 1; X} X X X X/* The universal argument has no effect on this one */ X/*ARGSUSED*/ Xstatic void BeginningOfBuf(w, event, params, numparams) XWidget w; XXEvent *event; XString *params; XCardinal *numparams; X{ X register MinibufWidget buf = (MinibufWidget) w; X CheckMode(); X ConcealCursor(buf); X mbuf(cursorPos) = mbuf(promptLen); X DisplayCursor(buf); X} X X X X/* The universal argument has no effect on this one */ X/*ARGSUSED*/ Xstatic void EndOfBuf(w, event, params, numparams) XWidget w; XXEvent *event; XString *params; XCardinal *numparams; X{ X register MinibufWidget buf = (MinibufWidget) w; X X CheckMode(); X ConcealCursor(buf); X mbuf(cursorPos) = mbuf(len); X DisplayCursor(buf); X} X X X X/*ARGSUSED*/ Xstatic void DeleteCharForward(w, event, params, numparams) XWidget w; XXEvent *event; XString *params; XCardinal *numparams; X{ X register MinibufWidget buf = (MinibufWidget) w; X register int i; X X CheckMode(); X if ((i = (mbuf(cursorPos) + mbuf(arg))) > mbuf(len)) X i = mbuf(len); X X ConcealCursor(buf); X bcopy(mbuf(string) + i, mbuf(string) + mbuf(cursorPos), mbuf(len) - i); X mbuf(len) -= i - mbuf(cursorPos); X mbuf(arg) = 1; X DisplayBuf(buf, FALSE); X DisplayCursor(buf); X} X X X/*ARGSUSED*/ Xstatic void DeleteCharBack(w, event, params, numparams) XWidget w; XXEvent *event; XString *params; XCardinal *numparams; X{ X register MinibufWidget buf = (MinibufWidget) w; X register int i; X X CheckMode(); X if ((i = (mbuf(cursorPos) - mbuf(arg))) < mbuf(promptLen)) X i = mbuf(promptLen); X X ConcealCursor(buf); X bcopy(mbuf(string) + mbuf(cursorPos), mbuf(string) + i, mbuf(len) - i); X mbuf(len) += i - mbuf(cursorPos); X mbuf(cursorPos) = i; X mbuf(arg) = 1; X DisplayBuf(buf, FALSE); X DisplayCursor(buf); X} X X X X X/* The universal argument has no effect on this one */ X/* Like Setmark, this flashes the cursor */ X/*ARGSUSED*/ Xstatic void MakeMark(w, event, params, numparams) XWidget w; XXEvent *event; XString *params; XCardinal *numparams; X{ X register MinibufWidget buf = (MinibufWidget) w; X X CheckMode(); X mbuf(mark) = mbuf(cursorPos); X mbuf(arg) = 1; X} X X X X/*ARGSUSED*/ Xstatic void ExchangeMarkAndPoint(w, event, params, numparams) XWidget w; XXEvent *event; XString *params; XCardinal *numparams; X{ X register MinibufWidget buf = (MinibufWidget) w; X register int tmp = mbuf(cursorPos); X X CheckMode(); X if (mbuf(mark) < mbuf(promptLen)) X mbuf(mark) = mbuf(promptLen); X X if (mbuf(mark) > mbuf(len)) X mbuf(mark) = mbuf(len); X X ConcealCursor(buf); X mbuf(cursorPos) = mbuf(mark); X mbuf(mark) = tmp; X mbuf(arg) = 1; X DisplayCursor(buf); X X} X X X X/* The universal argument has no effect on this one */ X/*ARGSUSED*/ Xstatic void CutMarkToPoint(w, event, params, numparams) XWidget w; XXEvent *event; XString *params; XCardinal *numparams; X{ X register MinibufWidget buf = (MinibufWidget) w; X register int lower, upper; X static void QuitInput(); X X CheckMode(); X X if (mbuf(mark) < mbuf(promptLen)) X mbuf(mark) = mbuf(promptLen); X X if (mbuf(mark) > mbuf(len)) X mbuf(mark) = mbuf(len); X X if (mbuf(mark) < mbuf(cursorPos)) { X lower = mbuf(mark); X upper = mbuf(cursorPos); X } else { X lower = mbuf(cursorPos); X upper = mbuf(mark); X } X X mbuf(killBufferLen) = upper - lower; X while (mbuf(killBufferLen) > mbuf(killBufferSize)) { X mbuf(killBufferSize) += BUF_BLOCK; X if (mbuf(killBuffer) == NULL) X mbuf(killBuffer) = XtMalloc((unsigned) mbuf(size)); X else X mbuf(killBuffer) = XtRealloc(mbuf(killBuffer), X (unsigned) mbuf(size)); X if (mbuf(killBuffer) == NULL) { X mbuf(killBufferSize) = 0; X mbuf(killBufferLen) = 0; X mbuf(inputMode) = FALSE; X QuitInput(w, event, params, numparams); X return; X } X } X X ConcealCursor(buf); X bcopy(mbuf(string) + lower, mbuf(killBuffer), mbuf(killBufferLen)); X bcopy(mbuf(string) + upper, mbuf(string) + lower, mbuf(len) - upper); X mbuf(cursorPos) = mbuf(mark) = lower; X mbuf(len) -= mbuf(killBufferLen); X mbuf(arg) = 1; X DisplayBuf(buf, FALSE); X DisplayCursor(buf); X} X X X X/* The universal argument has no effect on this one */ X/*ARGSUSED*/ Xstatic void KillToEnd(w, event, params, numparams) XWidget w; XXEvent *event; XString *params; XCardinal *numparams; X{ X register MinibufWidget buf = (MinibufWidget) w; X register int tmp_mark; X X CheckMode(); X tmp_mark = mbuf(mark); X mbuf(mark) = mbuf(len); X CutMarkToPoint(w, event, params, numparams); X mbuf(mark) = tmp_mark; X} X X X X/* The universal argument has no effect on this one */ X/*ARGSUSED*/ Xstatic void KillToBeginning(w, event, params, numparams) XWidget w; XXEvent *event; XString *params; XCardinal *numparams; X{ X register MinibufWidget buf = (MinibufWidget) w; X register int tmp_mark; X X CheckMode(); X tmp_mark = mbuf(mark); X mbuf(mark) = mbuf(promptLen); X CutMarkToPoint(w, event, params, numparams); X mbuf(mark) = tmp_mark; X} X X X X/*ARGSUSED*/ Xstatic void UnivArgument(w, event, params, numparams) XWidget w; XXEvent *event; XString *params; XCardinal *numparams; X{ X register MinibufWidget buf = (MinibufWidget) w; X X CheckMode(); X mbuf(arg) *= 4; X} X X X/* X * The universal argument has no effect on this one - maybe it should, X * I'm not sure. So I'll take the easy way out X */ X/*ARGSUSED*/ Xstatic void YankKilledStuff(w, event, params, numparams) XWidget w; XXEvent *event; XString *params; XCardinal *numparams; X{ X register MinibufWidget buf = (MinibufWidget) w; X X CheckMode(); X ConcealCursor(buf); X mbuf(mark) = mbuf(cursorPos); X StrInsert(mbuf(killBuffer), mbuf(killBufferLen), buf); X DisplayCursor(buf); X} X X X/*ARGSUSED*/ Xstatic void GetXBuffer(w, event, params, numparams) XWidget w; XXEvent *event; XString *params; XCardinal *numparams; X{ X register MinibufWidget buf = (MinibufWidget) w; X register char *s; X int nBytes; X X CheckMode(); X ConcealCursor(buf); X s = XFetchBytes(XtDisplay(w), &nBytes); X StrInsert(s, nBytes, buf); X DisplayCursor(buf); X} X X X X/*ARGSUSED*/ Xstatic void FinishedInput(w, event, params, numparams) XWidget w; XXEvent *event; XString *params; XCardinal *numparams; X{ X register MinibufWidget buf = (MinibufWidget) w; X register char *s; X register int len = mbuf(len) - mbuf(promptLen); X X CheckMode(); X ConcealCursor(buf); X XFlush(XtDisplay(w)); X mbuf(len) = 0; X mbuf(cursorPos) = mbuf(startPos) = 0; X mbuf(inputMode) = FALSE; X if ((s = XtMalloc((unsigned) (len + 1))) != NULL) { X bcopy(mbuf(string) + mbuf(promptLen), s, len); X s[len] = '\0'; X } X XtCallCallbacks(w, XtNfinishedCallback, s); X} X X X/*ARGSUSED*/ Xstatic void QuitInput(w, event, params, numparams) XWidget w; XXEvent *event; XString *params; XCardinal *numparams; X{ X register MinibufWidget buf = (MinibufWidget) w; X char *savestr; X int savelen; X X CheckMode(); X ConcealCursor(buf); X mbuf(len) = 0; X mbuf(cursorPos) = mbuf(startPos) = 0; X mbuf(inputMode) = FALSE; X X savestr = mbuf(string); X savelen = mbuf(len); X mbuf(string) = ABORT_MSG; X mbuf(len) = strlen(ABORT_MSG); X DisplayBuf(buf, TRUE); X XFlush(XtDisplay(w)); X mbuf(string) = savestr; X mbuf(len) = savelen; X X /* X * We don't redisplay the cursor - we've gone out of input mode, but X * we invoke the callback which tells the user about this X */ X XtCallCallbacks(w, XtNfinishedCallback, (caddr_t) NULL); X} X Xstatic MinibufWidget curbuf = NULL; X X/*ARGSUSED*/ Xstatic void CompleteFilename(w, event, params, numparams) XWidget w; XXEvent *event; XString *params; XCardinal *numparams; X{ X register MinibufWidget buf = (MinibufWidget) w; X X CheckMode(); X if (!mbuf(completion)) { X CharInsert(w, event, params, numparams); X return; X } X ConcealCursor(buf); X mbuf(string)[mbuf(len)] = '\0'; X mbuf(cursorPos) = mbuf(len); X curbuf = buf; X (void) f_complete(mbuf(string) + mbuf(promptLen), X mbuf(cursorPos) - mbuf(promptLen), 0, ' '); X DisplayCursor(buf); X X} X Xvoid rbell() X{ X register MinibufWidget buf = curbuf; X X XBell(XtDisplay(mcore(self)), 0); X} X X/* X * 'at' is somewhere in mbuf(string), and we replace from 'at' to the X * end of the line with the first 'len' chars of string 's' - 'curpos' X * is updated. X */ Xvoid insert_s(at, s, len, curpos) Xchar *at; Xchar *s; Xint *curpos; X{ X register MinibufWidget buf = curbuf; X X mbuf(len) = mbuf(cursorPos) = at - mbuf(string); X *at = '\0'; X StrInsert(s, len, buf); X *curpos = mbuf(cursorPos) - mbuf(promptLen); X mbuf(string)[mbuf(len)] = '\0'; X} X X/* add_mess(s) char *s; X * inserts 's' at the end of the buffer, then waits a respectable X * interval, deletes 's', and returns X */ Xvoid add_mess(s) Xchar *s; X{ X register MinibufWidget buf = curbuf; X int savecursor = mbuf(cursorPos); X X StrInsert(s, strlen(s), buf); X DisplayCursor(buf); X ConcealCursor(buf); X rbell(); X usleep(DELAY); X mbuf(len) = mbuf(cursorPos) = savecursor; X mbuf(string)[savecursor] = '\0'; X DisplayBuf(buf, FALSE); X} X X/*ARGSUSED*/ Xstatic void ListFiles(w, event, params, numparams) XWidget w; XXEvent *event; XString *params; XCardinal *numparams; X{ X register MinibufWidget buf = (MinibufWidget) w; X X CheckMode(); X if (!mbuf(completion)) { X CharInsert(w, event, params, numparams); X return; X } X /* X * We haven't implemented a proper window typeout yet - if I X * can manage it with the Text widget, but right now, it X * redraws twice, and refuses to go away unless you take the X * mouse into that window and click - yech! X */ X curbuf = (MinibufWidget) w; X#ifdef TYPEOUT X if (mbuf(typeout)) { X (void) f_complete(mbuf(string) + mbuf(promptLen), X mbuf(cursorPos) - mbuf(promptLen), mbuf(typeoutColumns), '?'); X } else X#endif TYPEOUT X rbell(); X} X X/* X * Public routines - these should probably be done with XtSetValues() X * but that means more work... Sigh! X */ Xvoid MinibufGetInput(w, prompt, defaultInput, complete) XWidget w; Xregister char *prompt; Xregister char *defaultInput; X{ X register MinibufWidget buf = (MinibufWidget) w; X if (buf == NULL) { X return; X } X X mbuf(cursorPos) = mbuf(len) = 0; X if (prompt != NULL) { X StrInsert(prompt, strlen(prompt), buf); X } X X mbuf(promptLen) = mbuf(cursorPos); X X if (defaultInput != NULL) { X StrInsert(defaultInput, strlen(defaultInput), buf); X mbuf(cursorPos) = mbuf(promptLen); X } X mbuf(inputMode) = TRUE; X mbuf(completion) = complete; X DisplayCursor(buf); X /* X * Focus events on the widget exclusively, not spring loaded - we X * remove the grab in the callback X */ X} X X X/* X * This displays msg in the buffer - since it uses the string passed in X * directly, and does not affect the buffer string (which is saved and X * restored), it should result in no more mallocs. X */ Xvoid MinibufDisplayMessage(w, msg, ringbell) XWidget w; Xregister char *msg; Xint ringbell; /* Do we want bell to sound */ X{ X register MinibufWidget buf = (MinibufWidget) w; X char *savestr; X int savelen; X X if (buf == NULL || msg == NULL) { X return; X } X X mbuf(inputMode) = FALSE; X mbuf(len) = mbuf(cursorPos) = mbuf(startPos) = 0; X savestr = mbuf(string); X savelen = mbuf(len); X mbuf(string) = msg; X mbuf(len) = strlen(msg); X X DisplayBuf(buf, TRUE); X XFlush(XtDisplay(w)); X if (ringbell) /* Maybe a visible bell for fun! One day...*/ X XBell(XtDisplay(w), 0); X mbuf(string) = savestr; X mbuf(len) = savelen; X} X END_OF_FILE if test 29988 -ne `wc -c <'xpic/Minibuf.c'`; then echo shar: \"'xpic/Minibuf.c'\" unpacked with wrong size! fi # end of 'xpic/Minibuf.c' fi echo shar: End of archive 15 \(of 15\). cp /dev/null ark15isdone MISSING="" for I in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 ; do if test ! -f ark${I}isdone ; then MISSING="${MISSING} ${I}" fi done if test "${MISSING}" = "" ; then echo You have unpacked all 15 archives. rm -f ark[1-9]isdone ark[1-9][0-9]isdone else echo You still need to unpack the following archives: echo " " ${MISSING} fi ## End of shell archive. exit 0