v04i061: xtroff -- troff previewer for X11, Part16/18

Dan Heller argv at island.uu.net
Wed Jul 19 19:13:51 AEST 1989


Submitted-by: Mark Moraes <moraes at ai.toronto.edu>
Posting-number: Volume 4, Issue 61
Archive-name: xtroff/part16



#! /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 16 (of 18)."
# Contents:  xtroff/XtStuff/Minibuf.c
# Wrapped by moraes at neat.ai on Thu Jul 13 20:55:23 1989
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
if test -f 'xtroff/XtStuff/Minibuf.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'xtroff/XtStuff/Minibuf.c'\"
else
echo shar: Extracting \"'xtroff/XtStuff/Minibuf.c'\" \(29958 characters\)
sed "s/^X//" >'xtroff/XtStuff/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 at 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.width)
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 29958 -ne `wc -c <'xtroff/XtStuff/Minibuf.c'`; then
    echo shar: \"'xtroff/XtStuff/Minibuf.c'\" unpacked with wrong size!
fi
# end of 'xtroff/XtStuff/Minibuf.c'
fi
echo shar: End of archive 16 \(of 18\).
cp /dev/null ark16isdone
MISSING=""
for I in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 ; do
    if test ! -f ark${I}isdone ; then
	MISSING="${MISSING} ${I}"
    fi
done
if test "${MISSING}" = "" ; then
    echo You have unpacked all 18 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



More information about the Comp.sources.x mailing list