xref: /minix3/external/bsd/nvi/dist/motif_l/m_vi.c (revision 0a6a1f1d05b60e214de2f05a7310ddd1f0e590e7)
1*0a6a1f1dSLionel Sambuc /*	$NetBSD: m_vi.c,v 1.3 2014/01/26 21:43:45 christos Exp $ */
284d9c625SLionel Sambuc  * Copyright (c) 1996
384d9c625SLionel Sambuc  *	Rob Zimmermann.  All rights reserved.
484d9c625SLionel Sambuc  * Copyright (c) 1996
584d9c625SLionel Sambuc  *	Keith Bostic.  All rights reserved.
684d9c625SLionel Sambuc  *
784d9c625SLionel Sambuc  * See the LICENSE file for redistribution information.
884d9c625SLionel Sambuc  */
984d9c625SLionel Sambuc 
1084d9c625SLionel Sambuc #include "config.h"
1184d9c625SLionel Sambuc 
12*0a6a1f1dSLionel Sambuc #include <sys/cdefs.h>
13*0a6a1f1dSLionel Sambuc #if 0
1484d9c625SLionel Sambuc #ifndef lint
1584d9c625SLionel Sambuc static const char sccsid[] = "Id: m_vi.c,v 8.41 2003/11/05 17:10:01 skimo Exp  (Berkeley) Date: 2003/11/05 17:10:01 ";
1684d9c625SLionel Sambuc #endif /* not lint */
17*0a6a1f1dSLionel Sambuc #else
18*0a6a1f1dSLionel Sambuc __RCSID("$NetBSD: m_vi.c,v 1.3 2014/01/26 21:43:45 christos Exp $");
19*0a6a1f1dSLionel Sambuc #endif
2084d9c625SLionel Sambuc 
2184d9c625SLionel Sambuc #include <sys/types.h>
2284d9c625SLionel Sambuc #include <sys/queue.h>
2384d9c625SLionel Sambuc 
2484d9c625SLionel Sambuc #include <X11/Intrinsic.h>
2584d9c625SLionel Sambuc #include <X11/StringDefs.h>
2684d9c625SLionel Sambuc #include <X11/cursorfont.h>
2784d9c625SLionel Sambuc #include <Xm/PanedW.h>
2884d9c625SLionel Sambuc #include <Xm/DrawingA.h>
2984d9c625SLionel Sambuc #include <Xm/Form.h>
3084d9c625SLionel Sambuc #include <Xm/Frame.h>
3184d9c625SLionel Sambuc #include <Xm/ScrollBar.h>
3284d9c625SLionel Sambuc 
3384d9c625SLionel Sambuc #include <bitstring.h>
3484d9c625SLionel Sambuc #include <ctype.h>
3584d9c625SLionel Sambuc #include <errno.h>
3684d9c625SLionel Sambuc #include <fcntl.h>
3784d9c625SLionel Sambuc #include <signal.h>
3884d9c625SLionel Sambuc #include <stdio.h>
3984d9c625SLionel Sambuc #include <stdlib.h>
4084d9c625SLionel Sambuc #include <string.h>
4184d9c625SLionel Sambuc #include <unistd.h>
4284d9c625SLionel Sambuc 
4384d9c625SLionel Sambuc #undef LOCK_SUCCESS
4484d9c625SLionel Sambuc #include "../common/common.h"
4584d9c625SLionel Sambuc #include "../ipc/ip.h"
4684d9c625SLionel Sambuc #include "m_motif.h"
4784d9c625SLionel Sambuc #include "vi_mextern.h"
4884d9c625SLionel Sambuc #include "pathnames.h"
4984d9c625SLionel Sambuc 
5084d9c625SLionel Sambuc extern int vi_ofd;
5184d9c625SLionel Sambuc 
5284d9c625SLionel Sambuc static	void	f_copy(String *buffer, int *len);
5384d9c625SLionel Sambuc static	void	f_paste(int widget, int buffer, int length);
5484d9c625SLionel Sambuc static	void	f_clear(Widget widget);
5584d9c625SLionel Sambuc 
5684d9c625SLionel Sambuc 
5784d9c625SLionel Sambuc /*
5884d9c625SLionel Sambuc  * Globals and costants
5984d9c625SLionel Sambuc  */
6084d9c625SLionel Sambuc 
6184d9c625SLionel Sambuc #define	BufferSize	1024
6284d9c625SLionel Sambuc 
6384d9c625SLionel Sambuc static	XFontStruct	*font;
6484d9c625SLionel Sambuc static	GC		gc;
6584d9c625SLionel Sambuc 	GC		__vi_copy_gc;
6684d9c625SLionel Sambuc static	XtAppContext	ctx;
6784d9c625SLionel Sambuc 
6884d9c625SLionel Sambuc 	xvi_screen	*__vi_screen = NULL;
6984d9c625SLionel Sambuc static	Cursor		std_cursor;
7084d9c625SLionel Sambuc static	Cursor		busy_cursor;
7184d9c625SLionel Sambuc static	XtTranslations	area_trans;
7284d9c625SLionel Sambuc static	int		multi_click_length;
7384d9c625SLionel Sambuc 
7484d9c625SLionel Sambuc void (*__vi_exitp)();				/* Exit function. */
7584d9c625SLionel Sambuc 
7684d9c625SLionel Sambuc 
7784d9c625SLionel Sambuc /* hack for drag scrolling...
7884d9c625SLionel Sambuc  * I'm not sure why, but the current protocol gets out of sync when
7984d9c625SLionel Sambuc  * a lot of drag messages get passed around.  Likely, we need to wait
8084d9c625SLionel Sambuc  * for core to finish repainting the screen before sending more drag
8184d9c625SLionel Sambuc  * messages.
8284d9c625SLionel Sambuc  * To that end, we set scroll_block when we receive input from the scrollbar,
8384d9c625SLionel Sambuc  * and we clear it when we process the IPO_REFRESH message from core.
8484d9c625SLionel Sambuc  * A specific SCROLL_COMPLETED message would be better, but this seems to work.
8584d9c625SLionel Sambuc  */
8684d9c625SLionel Sambuc 
8784d9c625SLionel Sambuc static Boolean scroll_block = False;
8884d9c625SLionel Sambuc 
8984d9c625SLionel Sambuc /*
9084d9c625SLionel Sambuc  * PUBLIC: void __vi_set_scroll_block __P((void));
9184d9c625SLionel Sambuc  */
9284d9c625SLionel Sambuc void
__vi_set_scroll_block(void)9384d9c625SLionel Sambuc __vi_set_scroll_block(void)
9484d9c625SLionel Sambuc {
9584d9c625SLionel Sambuc 	scroll_block = True;
9684d9c625SLionel Sambuc }
9784d9c625SLionel Sambuc 
9884d9c625SLionel Sambuc /*
9984d9c625SLionel Sambuc  * PUBLIC: void __vi_clear_scroll_block __P((void));
10084d9c625SLionel Sambuc  */
10184d9c625SLionel Sambuc void
__vi_clear_scroll_block(void)10284d9c625SLionel Sambuc __vi_clear_scroll_block(void)
10384d9c625SLionel Sambuc {
10484d9c625SLionel Sambuc 	scroll_block = False;
10584d9c625SLionel Sambuc }
10684d9c625SLionel Sambuc 
10784d9c625SLionel Sambuc 
10884d9c625SLionel Sambuc #if defined(__STDC__)
set_gc_colors(xvi_screen * this_screen,int val)10984d9c625SLionel Sambuc static	void	set_gc_colors( xvi_screen *this_screen, int val )
11084d9c625SLionel Sambuc #else
11184d9c625SLionel Sambuc static	void	set_gc_colors( this_screen, val )
11284d9c625SLionel Sambuc xvi_screen	*this_screen;
11384d9c625SLionel Sambuc int		val;
11484d9c625SLionel Sambuc #endif
11584d9c625SLionel Sambuc {
11684d9c625SLionel Sambuc     static Pixel	fg, bg, hi, shade;
11784d9c625SLionel Sambuc     static int		prev = COLOR_INVALID;
11884d9c625SLionel Sambuc 
11984d9c625SLionel Sambuc     /* no change? */
12084d9c625SLionel Sambuc     if ( prev == val ) return;
12184d9c625SLionel Sambuc 
12284d9c625SLionel Sambuc     /* init? */
12384d9c625SLionel Sambuc     if ( gc == NULL ) {
12484d9c625SLionel Sambuc 
12584d9c625SLionel Sambuc 	/* what colors are selected for the drawing area? */
12684d9c625SLionel Sambuc 	XtVaGetValues( this_screen->area,
12784d9c625SLionel Sambuc 		       XtNbackground,		&bg,
12884d9c625SLionel Sambuc 		       XtNforeground,		&fg,
12984d9c625SLionel Sambuc 		       XmNhighlightColor,	&hi,
13084d9c625SLionel Sambuc 		       XmNtopShadowColor,	&shade,
13184d9c625SLionel Sambuc 		       0
13284d9c625SLionel Sambuc 		       );
13384d9c625SLionel Sambuc 
13484d9c625SLionel Sambuc 	gc = XCreateGC( XtDisplay(this_screen->area),
13584d9c625SLionel Sambuc 		        DefaultRootWindow(XtDisplay(this_screen->area)),
13684d9c625SLionel Sambuc 			0,
13784d9c625SLionel Sambuc 			0
13884d9c625SLionel Sambuc 			);
13984d9c625SLionel Sambuc 
14084d9c625SLionel Sambuc 	XSetFont( XtDisplay(this_screen->area), gc, font->fid );
14184d9c625SLionel Sambuc     }
14284d9c625SLionel Sambuc 
14384d9c625SLionel Sambuc     /* special colors? */
14484d9c625SLionel Sambuc     if ( val & COLOR_CARET ) {
14584d9c625SLionel Sambuc 	XSetForeground( XtDisplay(this_screen->area), gc, fg );
14684d9c625SLionel Sambuc 	XSetBackground( XtDisplay(this_screen->area), gc, hi );
14784d9c625SLionel Sambuc     }
14884d9c625SLionel Sambuc     else if ( val & COLOR_SELECT ) {
14984d9c625SLionel Sambuc 	XSetForeground( XtDisplay(this_screen->area), gc, fg );
15084d9c625SLionel Sambuc 	XSetBackground( XtDisplay(this_screen->area), gc, shade );
15184d9c625SLionel Sambuc     }
15284d9c625SLionel Sambuc     else switch (val) {
15384d9c625SLionel Sambuc 	case COLOR_STANDARD:
15484d9c625SLionel Sambuc 	    XSetForeground( XtDisplay(this_screen->area), gc, fg );
15584d9c625SLionel Sambuc 	    XSetBackground( XtDisplay(this_screen->area), gc, bg );
15684d9c625SLionel Sambuc 	    break;
15784d9c625SLionel Sambuc 	case COLOR_INVERSE:
15884d9c625SLionel Sambuc 	    XSetForeground( XtDisplay(this_screen->area), gc, bg );
15984d9c625SLionel Sambuc 	    XSetBackground( XtDisplay(this_screen->area), gc, fg );
16084d9c625SLionel Sambuc 	    break;
16184d9c625SLionel Sambuc 	default:	/* implement color map later */
16284d9c625SLionel Sambuc 	    break;
16384d9c625SLionel Sambuc     }
16484d9c625SLionel Sambuc }
16584d9c625SLionel Sambuc 
16684d9c625SLionel Sambuc 
16784d9c625SLionel Sambuc /*
16884d9c625SLionel Sambuc  * Memory utilities
16984d9c625SLionel Sambuc  */
17084d9c625SLionel Sambuc 
17184d9c625SLionel Sambuc #ifdef REALLOC
17284d9c625SLionel Sambuc #undef REALLOC
17384d9c625SLionel Sambuc #endif
17484d9c625SLionel Sambuc 
17584d9c625SLionel Sambuc #define REALLOC( ptr, size )	\
17684d9c625SLionel Sambuc 	((ptr == NULL) ? malloc(size) : realloc(ptr,size))
17784d9c625SLionel Sambuc 
17884d9c625SLionel Sambuc 
17984d9c625SLionel Sambuc /* X windows routines.
18084d9c625SLionel Sambuc  * We currently create a single, top-level shell.  In that is a
18184d9c625SLionel Sambuc  * single drawing area into which we will draw text.  This allows
18284d9c625SLionel Sambuc  * us to put multi-color (and font, but we'll never build that) text
18384d9c625SLionel Sambuc  * into the drawing area.  In the future, we'll add scrollbars to the
18484d9c625SLionel Sambuc  * drawing areas
18584d9c625SLionel Sambuc  */
18684d9c625SLionel Sambuc 
18784d9c625SLionel Sambuc void	select_start();
18884d9c625SLionel Sambuc void	select_extend();
18984d9c625SLionel Sambuc void	select_paste();
19084d9c625SLionel Sambuc void	key_press();
19184d9c625SLionel Sambuc void	insert_string();
19284d9c625SLionel Sambuc void	beep __P((Widget w));
19384d9c625SLionel Sambuc void	find();
19484d9c625SLionel Sambuc void	command();
19584d9c625SLionel Sambuc 
19684d9c625SLionel Sambuc static XtActionsRec	area_actions[] = {
19784d9c625SLionel Sambuc     { "select_start",	select_start	},
19884d9c625SLionel Sambuc     { "select_extend",	select_extend	},
19984d9c625SLionel Sambuc     { "select_paste",	select_paste	},
20084d9c625SLionel Sambuc     { "key_press",	key_press	},
20184d9c625SLionel Sambuc     { "insert_string",	insert_string	},
20284d9c625SLionel Sambuc     { "beep",		beep		},
20384d9c625SLionel Sambuc     { "find",		find		},
20484d9c625SLionel Sambuc     { "command",	command		},
20584d9c625SLionel Sambuc };
20684d9c625SLionel Sambuc 
20784d9c625SLionel Sambuc char	areaTrans[] =
20884d9c625SLionel Sambuc     "<Btn1Down>:	select_start()		\n\
20984d9c625SLionel Sambuc      <Btn1Motion>:	select_extend()		\n\
21084d9c625SLionel Sambuc      <Btn2Down>:	select_paste()		\n\
21184d9c625SLionel Sambuc      <Btn3Down>:	select_extend()		\n\
21284d9c625SLionel Sambuc      <Btn3Motion>:	select_extend()		\n\
21384d9c625SLionel Sambuc      <Key>End:		command(VI_C_BOTTOM)	\n\
21484d9c625SLionel Sambuc      <Key>Escape:	command(EINSERT)	\n\
21584d9c625SLionel Sambuc      <Key>Find:		find()			\n\
21684d9c625SLionel Sambuc      <Key>Home:		command(VI_C_TOP)	\n\
21784d9c625SLionel Sambuc      <Key>Next:		command(VI_C_PGDOWN)	\n\
21884d9c625SLionel Sambuc      <Key>Prior:	command(VI_C_PGUP)	\n\
21984d9c625SLionel Sambuc      <Key>osfBackSpace:	command(VI_C_LEFT)	\n\
22084d9c625SLionel Sambuc      <Key>osfBeginLine:	command(VI_C_BOL)	\n\
22184d9c625SLionel Sambuc      <Key>osfCopy:	beep()			\n\
22284d9c625SLionel Sambuc      <Key>osfCut:	beep()			\n\
22384d9c625SLionel Sambuc      <Key>osfDelete:	command(VI_C_DEL)	\n\
22484d9c625SLionel Sambuc      <Key>osfDown:	command(VI_C_DOWN)	\n\
22584d9c625SLionel Sambuc      <Key>osfEndLine:	command(VI_C_EOL)	\n\
22684d9c625SLionel Sambuc      <Key>osfInsert:	command(VI_C_INSERT)	\n\
22784d9c625SLionel Sambuc      <Key>osfLeft:	command(VI_C_LEFT)	\n\
22884d9c625SLionel Sambuc      <Key>osfPageDown:	command(VI_C_PGDOWN)	\n\
22984d9c625SLionel Sambuc      <Key>osfPageUp:	command(VI_C_PGUP)	\n\
23084d9c625SLionel Sambuc      <Key>osfPaste:	insert_string(p)	\n\
23184d9c625SLionel Sambuc      <Key>osfRight:	command(VI_C_RIGHT)	\n\
23284d9c625SLionel Sambuc      <Key>osfUndo:	command(VI_UNDO)	\n\
23384d9c625SLionel Sambuc      <Key>osfUp:	command(VI_C_UP)	\n\
23484d9c625SLionel Sambuc      Ctrl<Key>C:	command(VI_INTERRUPT)	\n\
23584d9c625SLionel Sambuc      <Key>:		key_press()";
23684d9c625SLionel Sambuc 
23784d9c625SLionel Sambuc 
23884d9c625SLionel Sambuc static  XutResource resource[] = {
23984d9c625SLionel Sambuc     { "font",		XutRKfont,	&font		},
24084d9c625SLionel Sambuc     { "pointerShape",	XutRKcursor,	&std_cursor	},
24184d9c625SLionel Sambuc     { "busyShape",	XutRKcursor,	&busy_cursor	},
24284d9c625SLionel Sambuc };
24384d9c625SLionel Sambuc 
24484d9c625SLionel Sambuc 
24584d9c625SLionel Sambuc /*
24684d9c625SLionel Sambuc  * vi_input_func --
24784d9c625SLionel Sambuc  *	We've received input on the pipe from vi.
24884d9c625SLionel Sambuc  *
24984d9c625SLionel Sambuc  * PUBLIC: void vi_input_func __P((XtPointer, int *, XtInputId *));
25084d9c625SLionel Sambuc  */
25184d9c625SLionel Sambuc void
vi_input_func(XtPointer client_data,int * source,XtInputId * id)25284d9c625SLionel Sambuc vi_input_func(XtPointer client_data, int *source, XtInputId *id)
25384d9c625SLionel Sambuc {
25484d9c625SLionel Sambuc 	/* Parse and dispatch on commands in the queue. */
25584d9c625SLionel Sambuc 	(void)ipvi_motif->input(ipvi_motif, *source);
25684d9c625SLionel Sambuc 
25784d9c625SLionel Sambuc #ifdef notdef
25884d9c625SLionel Sambuc 	/* Check the pipe for unused events when not busy. */
25984d9c625SLionel Sambuc 	XtAppAddWorkProc(ctx, process_pipe_input, NULL);
26084d9c625SLionel Sambuc #endif
26184d9c625SLionel Sambuc }
26284d9c625SLionel Sambuc 
26384d9c625SLionel Sambuc 
26484d9c625SLionel Sambuc 
26584d9c625SLionel Sambuc /* Send the window size. */
26684d9c625SLionel Sambuc #if defined(__STDC__)
send_resize(xvi_screen * this_screen)26784d9c625SLionel Sambuc static	void	send_resize( xvi_screen *this_screen )
26884d9c625SLionel Sambuc #else
26984d9c625SLionel Sambuc static	void	send_resize( this_screen )
27084d9c625SLionel Sambuc xvi_screen	*this_screen;
27184d9c625SLionel Sambuc #endif
27284d9c625SLionel Sambuc {
27384d9c625SLionel Sambuc     IP_BUF	ipb;
27484d9c625SLionel Sambuc 
27584d9c625SLionel Sambuc     ipb.val1 = this_screen->rows;
27684d9c625SLionel Sambuc     ipb.val2 = this_screen->cols;
27784d9c625SLionel Sambuc     ipb.code = VI_RESIZE;
27884d9c625SLionel Sambuc 
27984d9c625SLionel Sambuc #ifdef TRACE
28084d9c625SLionel Sambuc     vtrace("resize_func ( %d x %d )\n", this_screen->rows, this_screen->cols);
28184d9c625SLionel Sambuc #endif
28284d9c625SLionel Sambuc 
28384d9c625SLionel Sambuc     /* send up the pipe */
28484d9c625SLionel Sambuc     vi_send(vi_ofd, "12", &ipb);
28584d9c625SLionel Sambuc }
28684d9c625SLionel Sambuc 
28784d9c625SLionel Sambuc 
28884d9c625SLionel Sambuc #if defined(__STDC__)
resize_backing_store(xvi_screen * this_screen)28984d9c625SLionel Sambuc static	void	resize_backing_store( xvi_screen *this_screen )
29084d9c625SLionel Sambuc #else
29184d9c625SLionel Sambuc static	void	resize_backing_store( this_screen )
29284d9c625SLionel Sambuc xvi_screen	*this_screen;
29384d9c625SLionel Sambuc #endif
29484d9c625SLionel Sambuc {
29584d9c625SLionel Sambuc     int	total_chars = this_screen->rows * this_screen->cols;
29684d9c625SLionel Sambuc 
29784d9c625SLionel Sambuc     this_screen->characters	= REALLOC( this_screen->characters,
29884d9c625SLionel Sambuc 					   total_chars
29984d9c625SLionel Sambuc 					   );
30084d9c625SLionel Sambuc     memset( this_screen->characters, ' ', total_chars );
30184d9c625SLionel Sambuc 
30284d9c625SLionel Sambuc     this_screen->flags		= REALLOC( this_screen->flags,
30384d9c625SLionel Sambuc 					   total_chars
30484d9c625SLionel Sambuc 					   );
30584d9c625SLionel Sambuc     memset( this_screen->flags, 0, total_chars );
30684d9c625SLionel Sambuc }
30784d9c625SLionel Sambuc 
30884d9c625SLionel Sambuc 
30984d9c625SLionel Sambuc 
31084d9c625SLionel Sambuc /* X will call this when we are resized */
31184d9c625SLionel Sambuc #if defined(__STDC__)
resize_func(Widget wid,XtPointer client_data,XtPointer call_data)31284d9c625SLionel Sambuc static	void	resize_func( Widget wid,
31384d9c625SLionel Sambuc 			     XtPointer client_data,
31484d9c625SLionel Sambuc 			     XtPointer call_data
31584d9c625SLionel Sambuc 			     )
31684d9c625SLionel Sambuc #else
31784d9c625SLionel Sambuc static	void	resize_func( wid, client_data, call_data )
31884d9c625SLionel Sambuc Widget		wid;
31984d9c625SLionel Sambuc XtPointer	client_data;
32084d9c625SLionel Sambuc XtPointer	call_data;
32184d9c625SLionel Sambuc #endif
32284d9c625SLionel Sambuc {
32384d9c625SLionel Sambuc     xvi_screen			*this_screen = (xvi_screen *) client_data;
32484d9c625SLionel Sambuc     Dimension			height, width;
32584d9c625SLionel Sambuc 
32684d9c625SLionel Sambuc     XtVaGetValues( wid, XmNheight, &height, XmNwidth, &width, 0 );
32784d9c625SLionel Sambuc 
32884d9c625SLionel Sambuc     /* generate correct sizes when we have font metrics implemented */
32984d9c625SLionel Sambuc     this_screen->cols = width / this_screen->ch_width;
33084d9c625SLionel Sambuc     this_screen->rows = height / this_screen->ch_height;
33184d9c625SLionel Sambuc 
33284d9c625SLionel Sambuc     resize_backing_store( this_screen );
33384d9c625SLionel Sambuc     send_resize( this_screen );
33484d9c625SLionel Sambuc }
33584d9c625SLionel Sambuc 
33684d9c625SLionel Sambuc 
33784d9c625SLionel Sambuc /*
33884d9c625SLionel Sambuc  * __vi_draw_text --
33984d9c625SLionel Sambuc  *	Draw from backing store.
34084d9c625SLionel Sambuc  *
34184d9c625SLionel Sambuc  * PUBLIC: void	__vi_draw_text __P((xvi_screen *, int, int, int));
34284d9c625SLionel Sambuc  */
34384d9c625SLionel Sambuc void
__vi_draw_text(xvi_screen * this_screen,int row,int start_col,int len)34484d9c625SLionel Sambuc __vi_draw_text(xvi_screen *this_screen, int row, int start_col, int len)
34584d9c625SLionel Sambuc {
34684d9c625SLionel Sambuc     int		col, color, xpos;
34784d9c625SLionel Sambuc     char	*start, *end;
34884d9c625SLionel Sambuc 
34984d9c625SLionel Sambuc     start = CharAt( __vi_screen, row, start_col );
35084d9c625SLionel Sambuc     color = *FlagAt( __vi_screen, row, start_col );
35184d9c625SLionel Sambuc     xpos  = XPOS( __vi_screen, start_col );
35284d9c625SLionel Sambuc 
35384d9c625SLionel Sambuc     /* one column at a time */
35484d9c625SLionel Sambuc     for ( col=start_col;
35584d9c625SLionel Sambuc 	  col<this_screen->cols && col<start_col+len;
35684d9c625SLionel Sambuc 	  col++ ) {
35784d9c625SLionel Sambuc 
35884d9c625SLionel Sambuc 	/* has the color changed? */
35984d9c625SLionel Sambuc 	if ( *FlagAt( __vi_screen, row, col ) == color )
36084d9c625SLionel Sambuc 	    continue;
36184d9c625SLionel Sambuc 
36284d9c625SLionel Sambuc 	/* is there anything to write? */
36384d9c625SLionel Sambuc 	end  = CharAt( __vi_screen, row, col );
36484d9c625SLionel Sambuc 	if ( end == start )
36584d9c625SLionel Sambuc 	    continue;
36684d9c625SLionel Sambuc 
36784d9c625SLionel Sambuc 	/* yes. write in the previous color */
36884d9c625SLionel Sambuc 	set_gc_colors( __vi_screen, color );
36984d9c625SLionel Sambuc 
37084d9c625SLionel Sambuc 	/* add to display */
37184d9c625SLionel Sambuc 	XDrawImageString( XtDisplay(__vi_screen->area),
37284d9c625SLionel Sambuc 			  XtWindow(__vi_screen->area),
37384d9c625SLionel Sambuc 			  gc,
37484d9c625SLionel Sambuc 			  xpos,
37584d9c625SLionel Sambuc 			  YPOS( __vi_screen, row ),
37684d9c625SLionel Sambuc 			  start,
37784d9c625SLionel Sambuc 			  end - start
37884d9c625SLionel Sambuc 			  );
37984d9c625SLionel Sambuc 
38084d9c625SLionel Sambuc 	/* this is the new context */
38184d9c625SLionel Sambuc 	color = *FlagAt( __vi_screen, row, col );
38284d9c625SLionel Sambuc 	xpos  = XPOS( __vi_screen, col );
38384d9c625SLionel Sambuc 	start = end;
38484d9c625SLionel Sambuc     }
38584d9c625SLionel Sambuc 
38684d9c625SLionel Sambuc     /* is there anything to write? */
38784d9c625SLionel Sambuc     end = CharAt( __vi_screen, row, col );
38884d9c625SLionel Sambuc     if ( end != start ) {
38984d9c625SLionel Sambuc 	/* yes. write in the previous color */
39084d9c625SLionel Sambuc 	set_gc_colors( __vi_screen, color );
39184d9c625SLionel Sambuc 
39284d9c625SLionel Sambuc 	/* add to display */
39384d9c625SLionel Sambuc 	XDrawImageString( XtDisplay(__vi_screen->area),
39484d9c625SLionel Sambuc 			  XtWindow(__vi_screen->area),
39584d9c625SLionel Sambuc 			  gc,
39684d9c625SLionel Sambuc 			  xpos,
39784d9c625SLionel Sambuc 			  YPOS( __vi_screen, row ),
39884d9c625SLionel Sambuc 			  start,
39984d9c625SLionel Sambuc 			  end - start
40084d9c625SLionel Sambuc 			  );
40184d9c625SLionel Sambuc     }
40284d9c625SLionel Sambuc }
40384d9c625SLionel Sambuc 
40484d9c625SLionel Sambuc 
40584d9c625SLionel Sambuc /* set clipping rectangles accordingly */
40684d9c625SLionel Sambuc #if defined(__STDC__)
add_to_clip(xvi_screen * cur_screen,int x,int y,int width,int height)40784d9c625SLionel Sambuc static	void	add_to_clip( xvi_screen *cur_screen, int x, int y, int width, int height )
40884d9c625SLionel Sambuc #else
40984d9c625SLionel Sambuc static	void	add_to_clip( cur_screen, x, y, width, height )
41084d9c625SLionel Sambuc 	xvi_screen *cur_screen;
41184d9c625SLionel Sambuc 	int	x;
41284d9c625SLionel Sambuc 	int	y;
41384d9c625SLionel Sambuc 	int	width;
41484d9c625SLionel Sambuc 	int	height;
41584d9c625SLionel Sambuc #endif
41684d9c625SLionel Sambuc {
41784d9c625SLionel Sambuc     XRectangle	rect;
41884d9c625SLionel Sambuc     rect.x	= x;
41984d9c625SLionel Sambuc     rect.y	= y;
42084d9c625SLionel Sambuc     rect.height	= height;
42184d9c625SLionel Sambuc     rect.width	= width;
42284d9c625SLionel Sambuc     if ( cur_screen->clip == NULL )
42384d9c625SLionel Sambuc 	cur_screen->clip = XCreateRegion();
42484d9c625SLionel Sambuc     XUnionRectWithRegion( &rect, cur_screen->clip, cur_screen->clip );
42584d9c625SLionel Sambuc }
42684d9c625SLionel Sambuc 
42784d9c625SLionel Sambuc 
42884d9c625SLionel Sambuc /*
42984d9c625SLionel Sambuc  * __vi_expose_func --
43084d9c625SLionel Sambuc  *	Redraw the window's contents.
43184d9c625SLionel Sambuc  *
43284d9c625SLionel Sambuc  * NOTE: When vi wants to force a redraw, we are called with NULL widget
43384d9c625SLionel Sambuc  *	 and call_data.
43484d9c625SLionel Sambuc  *
43584d9c625SLionel Sambuc  * PUBLIC: void	__vi_expose_func __P((Widget, XtPointer, XtPointer));
43684d9c625SLionel Sambuc  */
43784d9c625SLionel Sambuc void
__vi_expose_func(Widget wid,XtPointer client_data,XtPointer call_data)43884d9c625SLionel Sambuc __vi_expose_func(Widget wid, XtPointer client_data, XtPointer call_data)
43984d9c625SLionel Sambuc {
44084d9c625SLionel Sambuc     xvi_screen			*this_screen;
44184d9c625SLionel Sambuc     XmDrawingAreaCallbackStruct	*cbs;
44284d9c625SLionel Sambuc     XExposeEvent		*xev;
44384d9c625SLionel Sambuc     XGraphicsExposeEvent	*gev;
44484d9c625SLionel Sambuc     int				row;
44584d9c625SLionel Sambuc 
44684d9c625SLionel Sambuc     /* convert pointers */
44784d9c625SLionel Sambuc     this_screen = (xvi_screen *) client_data;
44884d9c625SLionel Sambuc     cbs		= (XmDrawingAreaCallbackStruct *) call_data;
44984d9c625SLionel Sambuc 
45084d9c625SLionel Sambuc     /* first exposure? tell vi we are ready... */
45184d9c625SLionel Sambuc     if ( this_screen->init == False ) {
45284d9c625SLionel Sambuc 
45384d9c625SLionel Sambuc 	/* what does the user want to see? */
45484d9c625SLionel Sambuc 	__vi_set_cursor( __vi_screen, False );
45584d9c625SLionel Sambuc 
45684d9c625SLionel Sambuc 	/* vi wants a resize as the first event */
45784d9c625SLionel Sambuc 	send_resize( __vi_screen );
45884d9c625SLionel Sambuc 
45984d9c625SLionel Sambuc 	/* fine for now.  we'll be back */
46084d9c625SLionel Sambuc 	this_screen->init = True;
46184d9c625SLionel Sambuc 	return;
46284d9c625SLionel Sambuc     }
46384d9c625SLionel Sambuc 
46484d9c625SLionel Sambuc     if ( call_data == NULL ) {
46584d9c625SLionel Sambuc 
46684d9c625SLionel Sambuc 	/* vi core calls this when it wants a full refresh */
46784d9c625SLionel Sambuc #ifdef TRACE
46884d9c625SLionel Sambuc 	vtrace("expose_func:  full refresh\n");
46984d9c625SLionel Sambuc #endif
47084d9c625SLionel Sambuc 
47184d9c625SLionel Sambuc 	XClearWindow( XtDisplay(this_screen->area),
47284d9c625SLionel Sambuc 		      XtWindow(this_screen->area)
47384d9c625SLionel Sambuc 		      );
47484d9c625SLionel Sambuc     }
47584d9c625SLionel Sambuc     else {
47684d9c625SLionel Sambuc 	switch ( cbs->event->type ) {
47784d9c625SLionel Sambuc 
47884d9c625SLionel Sambuc 	    case GraphicsExpose:
47984d9c625SLionel Sambuc 		gev = (XGraphicsExposeEvent *) cbs->event;
48084d9c625SLionel Sambuc 
48184d9c625SLionel Sambuc 		/* set clipping rectangles accordingly */
48284d9c625SLionel Sambuc 		add_to_clip( this_screen,
48384d9c625SLionel Sambuc 			     gev->x, gev->y,
48484d9c625SLionel Sambuc 			     gev->width, gev->height
48584d9c625SLionel Sambuc 			     );
48684d9c625SLionel Sambuc 
48784d9c625SLionel Sambuc 		/* X calls here when XCopyArea exposes new bits */
48884d9c625SLionel Sambuc #ifdef TRACE
48984d9c625SLionel Sambuc 		vtrace("expose_func (X):  (x=%d,y=%d,w=%d,h=%d), count=%d\n",
49084d9c625SLionel Sambuc 			     gev->x, gev->y,
49184d9c625SLionel Sambuc 			     gev->width, gev->height,
49284d9c625SLionel Sambuc 			     gev->count);
49384d9c625SLionel Sambuc #endif
49484d9c625SLionel Sambuc 
49584d9c625SLionel Sambuc 		/* more coming?  do it then */
49684d9c625SLionel Sambuc 		if ( gev->count > 0 ) return;
49784d9c625SLionel Sambuc 
49884d9c625SLionel Sambuc 		/* set clipping region */
49984d9c625SLionel Sambuc 		XSetRegion( XtDisplay(wid), gc, this_screen->clip );
50084d9c625SLionel Sambuc 		break;
50184d9c625SLionel Sambuc 
50284d9c625SLionel Sambuc 	    case Expose:
50384d9c625SLionel Sambuc 		xev = (XExposeEvent *) cbs->event;
50484d9c625SLionel Sambuc 
50584d9c625SLionel Sambuc 		/* set clipping rectangles accordingly */
50684d9c625SLionel Sambuc 		add_to_clip( this_screen,
50784d9c625SLionel Sambuc 			     xev->x, xev->y,
50884d9c625SLionel Sambuc 			     xev->width, xev->height
50984d9c625SLionel Sambuc 			     );
51084d9c625SLionel Sambuc 
51184d9c625SLionel Sambuc 		/* Motif calls here when DrawingArea is exposed */
51284d9c625SLionel Sambuc #ifdef TRACE
51384d9c625SLionel Sambuc 		vtrace("expose_func (Motif): (x=%d,y=%d,w=%d,h=%d), count=%d\n",
51484d9c625SLionel Sambuc 			     xev->x, xev->y,
51584d9c625SLionel Sambuc 			     xev->width, xev->height,
51684d9c625SLionel Sambuc 			     xev->count);
51784d9c625SLionel Sambuc #endif
51884d9c625SLionel Sambuc 
51984d9c625SLionel Sambuc 		/* more coming?  do it then */
52084d9c625SLionel Sambuc 		if ( xev->count > 0 ) return;
52184d9c625SLionel Sambuc 
52284d9c625SLionel Sambuc 		/* set clipping region */
52384d9c625SLionel Sambuc 		XSetRegion( XtDisplay(wid), gc, this_screen->clip );
52484d9c625SLionel Sambuc 		break;
52584d9c625SLionel Sambuc 
52684d9c625SLionel Sambuc 	    default:
52784d9c625SLionel Sambuc 		/* don't care? */
52884d9c625SLionel Sambuc 		return;
52984d9c625SLionel Sambuc 	}
53084d9c625SLionel Sambuc     }
53184d9c625SLionel Sambuc 
53284d9c625SLionel Sambuc     /* one row at a time */
53384d9c625SLionel Sambuc     for (row=0; row<this_screen->rows; row++) {
53484d9c625SLionel Sambuc 
53584d9c625SLionel Sambuc 	/* draw from the backing store */
53684d9c625SLionel Sambuc 	__vi_draw_text( this_screen, row, 0, this_screen->cols );
53784d9c625SLionel Sambuc     }
53884d9c625SLionel Sambuc 
53984d9c625SLionel Sambuc     /* clear clipping region */
54084d9c625SLionel Sambuc     XSetClipMask( XtDisplay(this_screen->area), gc, None );
54184d9c625SLionel Sambuc     if ( this_screen->clip != NULL ) {
54284d9c625SLionel Sambuc 	XDestroyRegion( this_screen->clip );
54384d9c625SLionel Sambuc 	this_screen->clip = NULL;
54484d9c625SLionel Sambuc     }
54584d9c625SLionel Sambuc 
54684d9c625SLionel Sambuc }
54784d9c625SLionel Sambuc 
54884d9c625SLionel Sambuc 
54984d9c625SLionel Sambuc #if defined(__STDC__)
xexpose(Widget w,XtPointer client_data,XEvent * ev,Boolean * cont)55084d9c625SLionel Sambuc static void	xexpose	( Widget w,
55184d9c625SLionel Sambuc 			  XtPointer client_data,
55284d9c625SLionel Sambuc 			  XEvent *ev,
55384d9c625SLionel Sambuc 			  Boolean *cont
55484d9c625SLionel Sambuc 			  )
55584d9c625SLionel Sambuc #else
55684d9c625SLionel Sambuc static void	xexpose	( w, client_data, ev, cont )
55784d9c625SLionel Sambuc Widget		w;
55884d9c625SLionel Sambuc XtPointer	client_data;
55984d9c625SLionel Sambuc XEvent		*ev;
56084d9c625SLionel Sambuc Boolean		*cont;
56184d9c625SLionel Sambuc #endif
56284d9c625SLionel Sambuc {
56384d9c625SLionel Sambuc     XmDrawingAreaCallbackStruct	cbs;
56484d9c625SLionel Sambuc 
56584d9c625SLionel Sambuc     switch ( ev->type ) {
56684d9c625SLionel Sambuc 	case GraphicsExpose:
56784d9c625SLionel Sambuc 	    cbs.event	= ev;
56884d9c625SLionel Sambuc 	    cbs.window	= XtWindow(w);
56984d9c625SLionel Sambuc 	    cbs.reason	= XmCR_EXPOSE;
57084d9c625SLionel Sambuc 	    __vi_expose_func( w, client_data, (XtPointer) &cbs );
57184d9c625SLionel Sambuc 	    *cont	= False;	/* we took care of it */
57284d9c625SLionel Sambuc 	    break;
57384d9c625SLionel Sambuc 	default:
57484d9c625SLionel Sambuc 	    /* don't care */
57584d9c625SLionel Sambuc 	    break;
57684d9c625SLionel Sambuc     }
57784d9c625SLionel Sambuc }
57884d9c625SLionel Sambuc 
57984d9c625SLionel Sambuc 
58084d9c625SLionel Sambuc /* unimplemented keystroke or command */
58184d9c625SLionel Sambuc #if defined(__STDC__)
beep(Widget w)58284d9c625SLionel Sambuc static void	beep( Widget w )
58384d9c625SLionel Sambuc #else
58484d9c625SLionel Sambuc static void	beep( w )
58584d9c625SLionel Sambuc Widget	w;
58684d9c625SLionel Sambuc #endif
58784d9c625SLionel Sambuc {
58884d9c625SLionel Sambuc     XBell(XtDisplay(w),0);
58984d9c625SLionel Sambuc }
59084d9c625SLionel Sambuc 
59184d9c625SLionel Sambuc 
59284d9c625SLionel Sambuc /* give me a search dialog */
59384d9c625SLionel Sambuc #if defined(__STDC__)
find(Widget w)59484d9c625SLionel Sambuc static void	find( Widget w )
59584d9c625SLionel Sambuc #else
59684d9c625SLionel Sambuc static void	find( w )
59784d9c625SLionel Sambuc Widget	w;
59884d9c625SLionel Sambuc #endif
59984d9c625SLionel Sambuc {
60084d9c625SLionel Sambuc     __vi_show_search_dialog( w, "Find" );
60184d9c625SLionel Sambuc }
60284d9c625SLionel Sambuc 
60384d9c625SLionel Sambuc /*
60484d9c625SLionel Sambuc  * command --
60584d9c625SLionel Sambuc  *	Translate simple keyboard input into vi protocol commands.
60684d9c625SLionel Sambuc  */
60784d9c625SLionel Sambuc static	void
command(Widget widget,XKeyEvent * event,String * str,Cardinal * cardinal)60884d9c625SLionel Sambuc command(Widget widget, XKeyEvent *event, String *str, Cardinal *cardinal)
60984d9c625SLionel Sambuc {
61084d9c625SLionel Sambuc 	static struct {
61184d9c625SLionel Sambuc 		String	name;
61284d9c625SLionel Sambuc 		int	code;
61384d9c625SLionel Sambuc 		int	count;
61484d9c625SLionel Sambuc 	} table[] = {
61584d9c625SLionel Sambuc 		{ "VI_C_BOL",		VI_C_BOL,	0 },
61684d9c625SLionel Sambuc 		{ "VI_C_BOTTOM",	VI_C_BOTTOM,	0 },
61784d9c625SLionel Sambuc 		{ "VI_C_DEL",		VI_C_DEL,	0 },
61884d9c625SLionel Sambuc 		{ "VI_C_DOWN",		VI_C_DOWN,	1 },
61984d9c625SLionel Sambuc 		{ "VI_C_EOL",		VI_C_EOL,	0 },
62084d9c625SLionel Sambuc 		{ "VI_C_INSERT",	VI_C_INSERT,	0 },
62184d9c625SLionel Sambuc 		{ "VI_C_LEFT",		VI_C_LEFT,	0 },
62284d9c625SLionel Sambuc 		{ "VI_C_PGDOWN",	VI_C_PGDOWN,	1 },
62384d9c625SLionel Sambuc 		{ "VI_C_PGUP",		VI_C_PGUP,	1 },
62484d9c625SLionel Sambuc 		{ "VI_C_RIGHT",		VI_C_RIGHT,	0 },
62584d9c625SLionel Sambuc 		{ "VI_C_TOP",		VI_C_TOP,	0 },
62684d9c625SLionel Sambuc 		{ "VI_C_UP",		VI_C_UP,	1 },
62784d9c625SLionel Sambuc 		{ "VI_INTERRUPT",	VI_INTERRUPT,	0 },
62884d9c625SLionel Sambuc 	};
62984d9c625SLionel Sambuc 	IP_BUF ipb;
63084d9c625SLionel Sambuc 	int i;
63184d9c625SLionel Sambuc 
63284d9c625SLionel Sambuc 	/*
63384d9c625SLionel Sambuc 	 * XXX
63484d9c625SLionel Sambuc 	 * Do fast lookup based on character #6 -- sleazy, but I don't
63584d9c625SLionel Sambuc 	 * want to do 10 strcmp's per keystroke.
63684d9c625SLionel Sambuc 	 */
63784d9c625SLionel Sambuc 	ipb.val1 = 1;
63884d9c625SLionel Sambuc 	for (i = 0; i < XtNumber(table); i++)
63984d9c625SLionel Sambuc 		if (table[i].name[6] == (*str)[6] &&
64084d9c625SLionel Sambuc 		    strcmp(table[i].name, *str) == 0) {
64184d9c625SLionel Sambuc 			ipb.code = table[i].code;
64284d9c625SLionel Sambuc 			vi_send(vi_ofd, table[i].count ? "1" : NULL, &ipb);
64384d9c625SLionel Sambuc 			return;
64484d9c625SLionel Sambuc 		}
64584d9c625SLionel Sambuc 
64684d9c625SLionel Sambuc 	/* oops. */
64784d9c625SLionel Sambuc 	beep(widget);
64884d9c625SLionel Sambuc }
64984d9c625SLionel Sambuc 
65084d9c625SLionel Sambuc /* mouse or keyboard input. */
65184d9c625SLionel Sambuc #if defined(__STDC__)
insert_string(Widget widget,XKeyEvent * event,String * str,Cardinal * cardinal)65284d9c625SLionel Sambuc static	void	insert_string( Widget widget,
65384d9c625SLionel Sambuc 			       XKeyEvent *event,
65484d9c625SLionel Sambuc 			       String *str,
65584d9c625SLionel Sambuc 			       Cardinal *cardinal
65684d9c625SLionel Sambuc 			       )
65784d9c625SLionel Sambuc #else
65884d9c625SLionel Sambuc static	void	insert_string( widget, event, str, cardinal )
65984d9c625SLionel Sambuc Widget          widget;
66084d9c625SLionel Sambuc XKeyEvent       *event;
66184d9c625SLionel Sambuc String          *str;
66284d9c625SLionel Sambuc Cardinal        *cardinal;
66384d9c625SLionel Sambuc #endif
66484d9c625SLionel Sambuc {
66584d9c625SLionel Sambuc     IP_BUF	ipb;
66684d9c625SLionel Sambuc 
66784d9c625SLionel Sambuc     ipb.len1 = strlen( *str );
66884d9c625SLionel Sambuc     if ( ipb.len1 != 0 ) {
66984d9c625SLionel Sambuc 	ipb.code = VI_STRING;
67084d9c625SLionel Sambuc 	ipb.str1 = *str;
67184d9c625SLionel Sambuc 	vi_send(vi_ofd, "a", &ipb);
67284d9c625SLionel Sambuc     }
67384d9c625SLionel Sambuc 
67484d9c625SLionel Sambuc #ifdef TRACE
67584d9c625SLionel Sambuc     vtrace("insert_string {%.*s}\n", strlen( *str ), *str );
67684d9c625SLionel Sambuc #endif
67784d9c625SLionel Sambuc }
67884d9c625SLionel Sambuc 
67984d9c625SLionel Sambuc 
68084d9c625SLionel Sambuc /* mouse or keyboard input. */
68184d9c625SLionel Sambuc #if defined(__STDC__)
key_press(Widget widget,XKeyEvent * event,String str,Cardinal * cardinal)68284d9c625SLionel Sambuc static	void	key_press( Widget widget,
68384d9c625SLionel Sambuc 			   XKeyEvent *event,
68484d9c625SLionel Sambuc 			   String str,
68584d9c625SLionel Sambuc 			   Cardinal *cardinal
68684d9c625SLionel Sambuc 			   )
68784d9c625SLionel Sambuc #else
68884d9c625SLionel Sambuc static	void	key_press( widget, event, str, cardinal )
68984d9c625SLionel Sambuc Widget          widget;
69084d9c625SLionel Sambuc XKeyEvent       *event;
69184d9c625SLionel Sambuc String          str;
69284d9c625SLionel Sambuc Cardinal        *cardinal;
69384d9c625SLionel Sambuc #endif
69484d9c625SLionel Sambuc {
69584d9c625SLionel Sambuc     IP_BUF	ipb;
69684d9c625SLionel Sambuc     char	bp[BufferSize];
69784d9c625SLionel Sambuc 
69884d9c625SLionel Sambuc     ipb.len1 = XLookupString( event, bp, BufferSize, NULL, NULL );
69984d9c625SLionel Sambuc     if ( ipb.len1 != 0 ) {
70084d9c625SLionel Sambuc 	ipb.code = VI_STRING;
70184d9c625SLionel Sambuc 	ipb.str1 = bp;
70284d9c625SLionel Sambuc #ifdef TRACE
70384d9c625SLionel Sambuc 	vtrace("key_press {%.*s}\n", ipb.len1, bp );
70484d9c625SLionel Sambuc #endif
70584d9c625SLionel Sambuc 	vi_send(vi_ofd, "a", &ipb);
70684d9c625SLionel Sambuc     }
70784d9c625SLionel Sambuc 
70884d9c625SLionel Sambuc }
70984d9c625SLionel Sambuc 
71084d9c625SLionel Sambuc 
71184d9c625SLionel Sambuc #if defined(__STDC__)
scrollbar_moved(Widget widget,XtPointer ptr,XmScrollBarCallbackStruct * cbs)71284d9c625SLionel Sambuc static	void	scrollbar_moved( Widget widget,
71384d9c625SLionel Sambuc 				 XtPointer ptr,
71484d9c625SLionel Sambuc 				 XmScrollBarCallbackStruct *cbs
71584d9c625SLionel Sambuc 				 )
71684d9c625SLionel Sambuc #else
71784d9c625SLionel Sambuc static	void				scrollbar_moved( widget, ptr, cbs )
71884d9c625SLionel Sambuc 	Widget				widget;
71984d9c625SLionel Sambuc 	XtPointer			ptr;
72084d9c625SLionel Sambuc 	XmScrollBarCallbackStruct	*cbs;
72184d9c625SLionel Sambuc #endif
72284d9c625SLionel Sambuc {
72384d9c625SLionel Sambuc     /* Future:  Need to scroll the correct screen! */
72484d9c625SLionel Sambuc     xvi_screen	*cur_screen = (xvi_screen *) ptr;
72584d9c625SLionel Sambuc     IP_BUF	ipb;
72684d9c625SLionel Sambuc 
72784d9c625SLionel Sambuc     /* if we are still processing messages from core, skip this event
72884d9c625SLionel Sambuc      * (see comments near __vi_set_scroll_block())
72984d9c625SLionel Sambuc      */
73084d9c625SLionel Sambuc     if ( scroll_block ) {
73184d9c625SLionel Sambuc 	return;
73284d9c625SLionel Sambuc     }
73384d9c625SLionel Sambuc     __vi_set_scroll_block();
73484d9c625SLionel Sambuc 
73584d9c625SLionel Sambuc #ifdef TRACE
73684d9c625SLionel Sambuc     switch ( cbs->reason ) {
73784d9c625SLionel Sambuc 	case XmCR_VALUE_CHANGED:
73884d9c625SLionel Sambuc 	    vtrace( "scrollbar VALUE_CHANGED %d\n", cbs->value );
73984d9c625SLionel Sambuc 	    break;
74084d9c625SLionel Sambuc 	case XmCR_DRAG:
74184d9c625SLionel Sambuc 	    vtrace( "scrollbar DRAG %d\n", cbs->value );
74284d9c625SLionel Sambuc 	    break;
74384d9c625SLionel Sambuc 	default:
74484d9c625SLionel Sambuc 	    vtrace( "scrollbar <default> %d\n", cbs->value );
74584d9c625SLionel Sambuc 	    break;
74684d9c625SLionel Sambuc     }
74784d9c625SLionel Sambuc     vtrace("scrollto {%d}\n", cbs->value );
74884d9c625SLionel Sambuc #endif
74984d9c625SLionel Sambuc 
75084d9c625SLionel Sambuc     /* Send the new cursor position. */
75184d9c625SLionel Sambuc     ipb.code = VI_C_SETTOP;
75284d9c625SLionel Sambuc     ipb.val1 = cbs->value;
75384d9c625SLionel Sambuc     (void)vi_send(vi_ofd, "1", &ipb);
75484d9c625SLionel Sambuc }
75584d9c625SLionel Sambuc 
75684d9c625SLionel Sambuc 
75784d9c625SLionel Sambuc #if defined(__STDC__)
create_screen(Widget parent,int rows,int cols)75884d9c625SLionel Sambuc static	xvi_screen	*create_screen( Widget parent, int rows, int cols )
75984d9c625SLionel Sambuc #else
76084d9c625SLionel Sambuc static	xvi_screen	*create_screen( parent, rows, cols )
76184d9c625SLionel Sambuc 	Widget		parent;
76284d9c625SLionel Sambuc 	int		rows, cols;
76384d9c625SLionel Sambuc #endif
76484d9c625SLionel Sambuc {
76584d9c625SLionel Sambuc     xvi_screen	*new_screen = (xvi_screen *) calloc( 1, sizeof(xvi_screen) );
76684d9c625SLionel Sambuc     Widget	frame;
76784d9c625SLionel Sambuc 
76884d9c625SLionel Sambuc     /* init... */
76984d9c625SLionel Sambuc     new_screen->color		= COLOR_STANDARD;
77084d9c625SLionel Sambuc     new_screen->parent		= parent;
77184d9c625SLionel Sambuc 
77284d9c625SLionel Sambuc     /* figure out the sizes */
77384d9c625SLionel Sambuc     new_screen->rows		= rows;
77484d9c625SLionel Sambuc     new_screen->cols		= cols;
77584d9c625SLionel Sambuc     new_screen->ch_width	= font->max_bounds.width;
77684d9c625SLionel Sambuc     new_screen->ch_height	= font->descent + font->ascent;
77784d9c625SLionel Sambuc     new_screen->ch_descent	= font->descent;
77884d9c625SLionel Sambuc     new_screen->clip		= NULL;
77984d9c625SLionel Sambuc 
78084d9c625SLionel Sambuc     /* allocate and init the backing stores */
78184d9c625SLionel Sambuc     resize_backing_store( new_screen );
78284d9c625SLionel Sambuc 
78384d9c625SLionel Sambuc     /* set up a translation table for the X toolkit */
78484d9c625SLionel Sambuc     if ( area_trans == NULL )
78584d9c625SLionel Sambuc 	area_trans = XtParseTranslationTable(areaTrans);
78684d9c625SLionel Sambuc 
78784d9c625SLionel Sambuc     /* future, new screen gets inserted into the parent sash
78884d9c625SLionel Sambuc      * immediately after the current screen.  Default Pane action is
78984d9c625SLionel Sambuc      * to add it to the end
79084d9c625SLionel Sambuc      */
79184d9c625SLionel Sambuc 
79284d9c625SLionel Sambuc     /* use a form to hold the drawing area and the scrollbar */
79384d9c625SLionel Sambuc     new_screen->form = XtVaCreateManagedWidget( "form",
79484d9c625SLionel Sambuc 	    xmFormWidgetClass,
79584d9c625SLionel Sambuc 	    parent,
79684d9c625SLionel Sambuc 	    XmNpaneMinimum,		2*new_screen->ch_height,
79784d9c625SLionel Sambuc 	    XmNallowResize,		True,
79884d9c625SLionel Sambuc 	    NULL
79984d9c625SLionel Sambuc 	    );
80084d9c625SLionel Sambuc 
80184d9c625SLionel Sambuc     /* create a scrollbar. */
80284d9c625SLionel Sambuc     new_screen->scroll = XtVaCreateManagedWidget( "scroll",
80384d9c625SLionel Sambuc 	    xmScrollBarWidgetClass,
80484d9c625SLionel Sambuc 	    new_screen->form,
80584d9c625SLionel Sambuc 	    XmNtopAttachment,		XmATTACH_FORM,
80684d9c625SLionel Sambuc 	    XmNbottomAttachment,	XmATTACH_FORM,
80784d9c625SLionel Sambuc 	    XmNrightAttachment,		XmATTACH_FORM,
80884d9c625SLionel Sambuc 	    XmNminimum,			1,
80984d9c625SLionel Sambuc 	    XmNmaximum,			2,
81084d9c625SLionel Sambuc 	    XmNsliderSize,		1,
81184d9c625SLionel Sambuc 	    NULL
81284d9c625SLionel Sambuc 	    );
81384d9c625SLionel Sambuc     XtAddCallback( new_screen->scroll,
81484d9c625SLionel Sambuc 		   XmNvalueChangedCallback,
81584d9c625SLionel Sambuc 		   scrollbar_moved,
81684d9c625SLionel Sambuc 		   new_screen
81784d9c625SLionel Sambuc 		   );
81884d9c625SLionel Sambuc     XtAddCallback( new_screen->scroll,
81984d9c625SLionel Sambuc 		   XmNdragCallback,
82084d9c625SLionel Sambuc 		   scrollbar_moved,
82184d9c625SLionel Sambuc 		   new_screen
82284d9c625SLionel Sambuc 		   );
82384d9c625SLionel Sambuc 
82484d9c625SLionel Sambuc     /* create a frame because they look nice */
82584d9c625SLionel Sambuc     frame = XtVaCreateManagedWidget( "frame",
82684d9c625SLionel Sambuc 	    xmFrameWidgetClass,
82784d9c625SLionel Sambuc 	    new_screen->form,
82884d9c625SLionel Sambuc 	    XmNshadowType,		XmSHADOW_ETCHED_IN,
82984d9c625SLionel Sambuc 	    XmNtopAttachment,		XmATTACH_FORM,
83084d9c625SLionel Sambuc 	    XmNbottomAttachment,	XmATTACH_FORM,
83184d9c625SLionel Sambuc 	    XmNleftAttachment,		XmATTACH_FORM,
83284d9c625SLionel Sambuc 	    XmNrightAttachment,		XmATTACH_WIDGET,
83384d9c625SLionel Sambuc 	    XmNrightWidget,		new_screen->scroll,
83484d9c625SLionel Sambuc 	    NULL
83584d9c625SLionel Sambuc 	    );
83684d9c625SLionel Sambuc 
83784d9c625SLionel Sambuc     /* create a drawing area into which we will put text */
83884d9c625SLionel Sambuc     new_screen->area = XtVaCreateManagedWidget( "screen",
83984d9c625SLionel Sambuc 	    xmDrawingAreaWidgetClass,
84084d9c625SLionel Sambuc 	    frame,
84184d9c625SLionel Sambuc 	    XmNheight,		new_screen->ch_height * new_screen->rows,
84284d9c625SLionel Sambuc 	    XmNwidth,		new_screen->ch_width * new_screen->cols,
84384d9c625SLionel Sambuc 	    XmNtranslations,	area_trans,
84484d9c625SLionel Sambuc 	    XmNuserData,	new_screen,
84584d9c625SLionel Sambuc 	    XmNnavigationType,	XmNONE,
84684d9c625SLionel Sambuc 	    XmNtraversalOn,	False,
84784d9c625SLionel Sambuc 	    NULL
84884d9c625SLionel Sambuc 	    );
84984d9c625SLionel Sambuc 
85084d9c625SLionel Sambuc     /* this callback is for when the drawing area is resized */
85184d9c625SLionel Sambuc     XtAddCallback( new_screen->area,
85284d9c625SLionel Sambuc 		   XmNresizeCallback,
85384d9c625SLionel Sambuc 		   resize_func,
85484d9c625SLionel Sambuc 		   new_screen
85584d9c625SLionel Sambuc 		   );
85684d9c625SLionel Sambuc 
85784d9c625SLionel Sambuc     /* this callback is for when the drawing area is exposed */
85884d9c625SLionel Sambuc     XtAddCallback( new_screen->area,
85984d9c625SLionel Sambuc 		   XmNexposeCallback,
86084d9c625SLionel Sambuc 		   __vi_expose_func,
86184d9c625SLionel Sambuc 		   new_screen
86284d9c625SLionel Sambuc 		   );
86384d9c625SLionel Sambuc 
86484d9c625SLionel Sambuc     /* this callback is for when we expose obscured bits
86584d9c625SLionel Sambuc      * (e.g. there is a window over part of our drawing area
86684d9c625SLionel Sambuc      */
86784d9c625SLionel Sambuc     XtAddEventHandler( new_screen->area,
86884d9c625SLionel Sambuc 		       0,	/* no standard events */
86984d9c625SLionel Sambuc 		       True,	/* we *WANT* GraphicsExpose */
87084d9c625SLionel Sambuc 		       xexpose,	/* what to do */
87184d9c625SLionel Sambuc 		       new_screen
87284d9c625SLionel Sambuc 		       );
87384d9c625SLionel Sambuc 
87484d9c625SLionel Sambuc     return new_screen;
87584d9c625SLionel Sambuc }
87684d9c625SLionel Sambuc 
87784d9c625SLionel Sambuc 
split_screen(void)87884d9c625SLionel Sambuc static	xvi_screen	*split_screen(void)
87984d9c625SLionel Sambuc {
88084d9c625SLionel Sambuc     Cardinal	num;
88184d9c625SLionel Sambuc     WidgetList	c;
88284d9c625SLionel Sambuc     int		rows = __vi_screen->rows / 2;
88384d9c625SLionel Sambuc     xvi_screen	*new_screen;
88484d9c625SLionel Sambuc 
88584d9c625SLionel Sambuc     /* Note that (global) cur_screen needs to be correctly set so that
88684d9c625SLionel Sambuc      * insert_here knows which screen to put the new one after
88784d9c625SLionel Sambuc      */
88884d9c625SLionel Sambuc     new_screen = create_screen( __vi_screen->parent,
88984d9c625SLionel Sambuc 				rows,
89084d9c625SLionel Sambuc 				__vi_screen->cols
89184d9c625SLionel Sambuc 				);
89284d9c625SLionel Sambuc 
89384d9c625SLionel Sambuc     /* what are the screens? */
89484d9c625SLionel Sambuc     XtVaGetValues( __vi_screen->parent,
89584d9c625SLionel Sambuc 		   XmNnumChildren,	&num,
89684d9c625SLionel Sambuc 		   XmNchildren,		&c,
89784d9c625SLionel Sambuc 		   NULL
89884d9c625SLionel Sambuc 		   );
89984d9c625SLionel Sambuc 
90084d9c625SLionel Sambuc     /* unmanage all children in preparation for resizing */
90184d9c625SLionel Sambuc     XtUnmanageChildren( c, num );
90284d9c625SLionel Sambuc 
90384d9c625SLionel Sambuc     /* force resize of the affected screens */
90484d9c625SLionel Sambuc     XtVaSetValues( new_screen->form,
90584d9c625SLionel Sambuc 		   XmNheight,	new_screen->ch_height * rows,
90684d9c625SLionel Sambuc 		   NULL
90784d9c625SLionel Sambuc 		   );
90884d9c625SLionel Sambuc     XtVaSetValues( __vi_screen->form,
90984d9c625SLionel Sambuc 		   XmNheight,	__vi_screen->ch_height * rows,
91084d9c625SLionel Sambuc 		   NULL
91184d9c625SLionel Sambuc 		   );
91284d9c625SLionel Sambuc 
91384d9c625SLionel Sambuc     /* re-manage */
91484d9c625SLionel Sambuc     XtManageChildren( c, num );
91584d9c625SLionel Sambuc 
91684d9c625SLionel Sambuc     /* done */
91784d9c625SLionel Sambuc     return new_screen;
91884d9c625SLionel Sambuc }
91984d9c625SLionel Sambuc 
92084d9c625SLionel Sambuc 
92184d9c625SLionel Sambuc /* Tell me where to insert the next subpane */
92284d9c625SLionel Sambuc #if defined(__STDC__)
insert_here(Widget wid)92384d9c625SLionel Sambuc static	Cardinal	insert_here( Widget wid )
92484d9c625SLionel Sambuc #else
92584d9c625SLionel Sambuc static	Cardinal	insert_here( wid )
92684d9c625SLionel Sambuc 	Widget		wid;
92784d9c625SLionel Sambuc #endif
92884d9c625SLionel Sambuc {
92984d9c625SLionel Sambuc     Cardinal	i, num;
93084d9c625SLionel Sambuc     WidgetList	c;
93184d9c625SLionel Sambuc 
93284d9c625SLionel Sambuc     XtVaGetValues( XtParent(wid),
93384d9c625SLionel Sambuc 		   XmNnumChildren,	&num,
93484d9c625SLionel Sambuc 		   XmNchildren,		&c,
93584d9c625SLionel Sambuc 		   NULL
93684d9c625SLionel Sambuc 		   );
93784d9c625SLionel Sambuc 
93884d9c625SLionel Sambuc     /* The  default  XmNinsertPosition  procedure  for  PanedWindow
93984d9c625SLionel Sambuc      * causes sashes to be inserted at the end of the list of children
94084d9c625SLionel Sambuc      * and causes non-sash widgets to be inserted after  other
94184d9c625SLionel Sambuc      * non-sash children but before any sashes.
94284d9c625SLionel Sambuc      */
94384d9c625SLionel Sambuc     if ( ! XmIsForm( wid ) )
94484d9c625SLionel Sambuc 	return num;
94584d9c625SLionel Sambuc 
94684d9c625SLionel Sambuc     /* We will put the widget after the one with the current screen */
94784d9c625SLionel Sambuc     for (i=0; i<num && XmIsForm(c[i]); i++) {
94884d9c625SLionel Sambuc 	if ( __vi_screen == NULL || __vi_screen->form == c[i] )
94984d9c625SLionel Sambuc 	    return i+1;	/* after the i-th */
95084d9c625SLionel Sambuc     }
95184d9c625SLionel Sambuc 
95284d9c625SLionel Sambuc     /* could not find it?  this should never happen */
95384d9c625SLionel Sambuc     return num;
95484d9c625SLionel Sambuc }
95584d9c625SLionel Sambuc 
95684d9c625SLionel Sambuc 
95784d9c625SLionel Sambuc /*
95884d9c625SLionel Sambuc  * vi_create_editor --
95984d9c625SLionel Sambuc  *	Create the necessary widgetry.
96084d9c625SLionel Sambuc  *
96184d9c625SLionel Sambuc  * PUBLIC: Widget vi_create_editor __P((String, Widget, void (*)(void)));
96284d9c625SLionel Sambuc  */
96384d9c625SLionel Sambuc Widget
vi_create_editor(String name,Widget parent,void (* exitp)(void))96484d9c625SLionel Sambuc vi_create_editor(String name, Widget parent, void (*exitp) (void))
96584d9c625SLionel Sambuc {
96684d9c625SLionel Sambuc     Widget	pane_w;
96784d9c625SLionel Sambuc     Display	*display = XtDisplay( parent );
96884d9c625SLionel Sambuc 
96984d9c625SLionel Sambuc     __vi_exitp = exitp;
97084d9c625SLionel Sambuc 
97184d9c625SLionel Sambuc     /* first time through? */
97284d9c625SLionel Sambuc     if ( ctx == NULL ) {
97384d9c625SLionel Sambuc 
97484d9c625SLionel Sambuc 	/* save this for later */
97584d9c625SLionel Sambuc 	ctx = XtWidgetToApplicationContext( parent );
97684d9c625SLionel Sambuc 
97784d9c625SLionel Sambuc 	/* add our own special actions */
97884d9c625SLionel Sambuc 	XtAppAddActions( ctx, area_actions, XtNumber(area_actions) );
97984d9c625SLionel Sambuc 
98084d9c625SLionel Sambuc 	/* how long is double-click? */
98184d9c625SLionel Sambuc 	multi_click_length = XtGetMultiClickTime( display );
98284d9c625SLionel Sambuc 
98384d9c625SLionel Sambuc 	/* check the resource database for interesting resources */
98484d9c625SLionel Sambuc 	__XutConvertResources( parent,
98584d9c625SLionel Sambuc 			     vi_progname,
98684d9c625SLionel Sambuc 			     resource,
98784d9c625SLionel Sambuc 			     XtNumber(resource)
98884d9c625SLionel Sambuc 			     );
98984d9c625SLionel Sambuc 
99084d9c625SLionel Sambuc 	/* we need a context for moving bits around in the windows */
99184d9c625SLionel Sambuc 	__vi_copy_gc = XCreateGC( display,
99284d9c625SLionel Sambuc 				 DefaultRootWindow(display),
99384d9c625SLionel Sambuc 				 0,
99484d9c625SLionel Sambuc 				 0
99584d9c625SLionel Sambuc 				 );
99684d9c625SLionel Sambuc 
99784d9c625SLionel Sambuc 	/* routines for inter client communications conventions */
99884d9c625SLionel Sambuc 	__vi_InitCopyPaste( f_copy, f_paste, f_clear, fprintf );
99984d9c625SLionel Sambuc     }
100084d9c625SLionel Sambuc 
100184d9c625SLionel Sambuc     /* create the paned window */
100284d9c625SLionel Sambuc     pane_w = XtVaCreateManagedWidget( "pane",
100384d9c625SLionel Sambuc 				      xmPanedWindowWidgetClass,
100484d9c625SLionel Sambuc 				      parent,
100584d9c625SLionel Sambuc 				      XmNinsertPosition,	insert_here,
100684d9c625SLionel Sambuc 				      NULL
100784d9c625SLionel Sambuc 				      );
100884d9c625SLionel Sambuc 
100984d9c625SLionel Sambuc     /* allocate our data structure.  in the future we will have several
101084d9c625SLionel Sambuc      * screens running around at the same time
101184d9c625SLionel Sambuc      */
101284d9c625SLionel Sambuc     __vi_screen = create_screen( pane_w, 24, 80 );
101384d9c625SLionel Sambuc 
101484d9c625SLionel Sambuc     /* force creation of our color text context */
101584d9c625SLionel Sambuc     set_gc_colors( __vi_screen, COLOR_STANDARD );
101684d9c625SLionel Sambuc 
101784d9c625SLionel Sambuc     /* done */
101884d9c625SLionel Sambuc     return pane_w;
101984d9c625SLionel Sambuc }
102084d9c625SLionel Sambuc 
102184d9c625SLionel Sambuc 
102284d9c625SLionel Sambuc /* These routines deal with the selection buffer */
102384d9c625SLionel Sambuc 
102484d9c625SLionel Sambuc static	int	selection_start, selection_end, selection_anchor;
102584d9c625SLionel Sambuc static	enum	select_enum {
102684d9c625SLionel Sambuc 	    select_char, select_word, select_line
102784d9c625SLionel Sambuc 	}	select_type = select_char;
102884d9c625SLionel Sambuc static	int	last_click;
102984d9c625SLionel Sambuc 
103084d9c625SLionel Sambuc static	char	*clipboard = NULL;
103184d9c625SLionel Sambuc static	int	clipboard_size = 0,
103284d9c625SLionel Sambuc 		clipboard_length;
103384d9c625SLionel Sambuc 
103484d9c625SLionel Sambuc 
103584d9c625SLionel Sambuc #if defined(__STDC__)
copy_to_clipboard(xvi_screen * cur_screen)103684d9c625SLionel Sambuc static	void	copy_to_clipboard( xvi_screen *cur_screen )
103784d9c625SLionel Sambuc #else
103884d9c625SLionel Sambuc static	void	copy_to_clipboard( cur_screen )
103984d9c625SLionel Sambuc xvi_screen	*cur_screen;
104084d9c625SLionel Sambuc #endif
104184d9c625SLionel Sambuc {
104284d9c625SLionel Sambuc     /* for now, copy from the backing store.  in the future,
104384d9c625SLionel Sambuc      * vi core will tell us exactly what the selection buffer contains
104484d9c625SLionel Sambuc      */
104584d9c625SLionel Sambuc     clipboard_length = 1 + selection_end - selection_start;
104684d9c625SLionel Sambuc 
104784d9c625SLionel Sambuc     if ( clipboard == NULL )
104884d9c625SLionel Sambuc 	clipboard = (char *) malloc( clipboard_length );
104984d9c625SLionel Sambuc     else if ( clipboard_size < clipboard_length )
105084d9c625SLionel Sambuc 	clipboard = (char *) realloc( clipboard, clipboard_length );
105184d9c625SLionel Sambuc 
105284d9c625SLionel Sambuc     memcpy( clipboard,
105384d9c625SLionel Sambuc 	    cur_screen->characters + selection_start,
105484d9c625SLionel Sambuc 	    clipboard_length
105584d9c625SLionel Sambuc 	    );
105684d9c625SLionel Sambuc }
105784d9c625SLionel Sambuc 
105884d9c625SLionel Sambuc 
105984d9c625SLionel Sambuc #if defined(__STDC__)
mark_selection(xvi_screen * cur_screen,int start,int end)106084d9c625SLionel Sambuc static	void	mark_selection( xvi_screen *cur_screen, int start, int end )
106184d9c625SLionel Sambuc #else
106284d9c625SLionel Sambuc static	void	mark_selection( cur_screen, start, end )
106384d9c625SLionel Sambuc xvi_screen	*cur_screen;
106484d9c625SLionel Sambuc int		start;
106584d9c625SLionel Sambuc int		end;
106684d9c625SLionel Sambuc #endif
106784d9c625SLionel Sambuc {
106884d9c625SLionel Sambuc     int	row, col, i;
106984d9c625SLionel Sambuc 
107084d9c625SLionel Sambuc     for ( i=start; i<=end; i++ ) {
107184d9c625SLionel Sambuc 	if ( !( cur_screen->flags[i] & COLOR_SELECT ) ) {
107284d9c625SLionel Sambuc 	    cur_screen->flags[i] |= COLOR_SELECT;
107384d9c625SLionel Sambuc 	    ToRowCol( cur_screen, i, row, col );
107484d9c625SLionel Sambuc 	    __vi_draw_text( cur_screen, row, col, 1 );
107584d9c625SLionel Sambuc 	}
107684d9c625SLionel Sambuc     }
107784d9c625SLionel Sambuc }
107884d9c625SLionel Sambuc 
107984d9c625SLionel Sambuc 
108084d9c625SLionel Sambuc #if defined(__STDC__)
erase_selection(xvi_screen * cur_screen,int start,int end)108184d9c625SLionel Sambuc static	void	erase_selection( xvi_screen *cur_screen, int start, int end )
108284d9c625SLionel Sambuc #else
108384d9c625SLionel Sambuc static	void	erase_selection( cur_screen, start, end )
108484d9c625SLionel Sambuc xvi_screen	*cur_screen;
108584d9c625SLionel Sambuc int		start;
108684d9c625SLionel Sambuc int		end;
108784d9c625SLionel Sambuc #endif
108884d9c625SLionel Sambuc {
108984d9c625SLionel Sambuc     int	row, col, i;
109084d9c625SLionel Sambuc 
109184d9c625SLionel Sambuc     for ( i=start; i<=end; i++ ) {
109284d9c625SLionel Sambuc 	if ( cur_screen->flags[i] & COLOR_SELECT ) {
109384d9c625SLionel Sambuc 	    cur_screen->flags[i] &= ~COLOR_SELECT;
109484d9c625SLionel Sambuc 	    ToRowCol( cur_screen, i, row, col );
109584d9c625SLionel Sambuc 	    __vi_draw_text( cur_screen, row, col, 1 );
109684d9c625SLionel Sambuc 	}
109784d9c625SLionel Sambuc     }
109884d9c625SLionel Sambuc }
109984d9c625SLionel Sambuc 
110084d9c625SLionel Sambuc 
110184d9c625SLionel Sambuc #if defined(__STDC__)
left_expand_selection(xvi_screen * cur_screen,int * start)110284d9c625SLionel Sambuc static	void	left_expand_selection( xvi_screen *cur_screen, int *start )
110384d9c625SLionel Sambuc #else
110484d9c625SLionel Sambuc static	void	left_expand_selection( cur_screen, start )
110584d9c625SLionel Sambuc xvi_screen	*cur_screen;
110684d9c625SLionel Sambuc int		*start;
110784d9c625SLionel Sambuc #endif
110884d9c625SLionel Sambuc {
110984d9c625SLionel Sambuc     int row, col;
111084d9c625SLionel Sambuc 
111184d9c625SLionel Sambuc     switch ( select_type ) {
111284d9c625SLionel Sambuc 	case select_word:
111384d9c625SLionel Sambuc 	    if ( *start == 0 || isspace( (unsigned char)cur_screen->characters[*start] ) )
111484d9c625SLionel Sambuc 		return;
111584d9c625SLionel Sambuc 	    for (;;) {
111684d9c625SLionel Sambuc 		if ( isspace( (unsigned char)cur_screen->characters[*start-1] ) )
111784d9c625SLionel Sambuc 		    return;
111884d9c625SLionel Sambuc 		if ( --(*start) == 0 )
111984d9c625SLionel Sambuc 		   return;
112084d9c625SLionel Sambuc 	    }
112184d9c625SLionel Sambuc 	case select_line:
112284d9c625SLionel Sambuc 	    ToRowCol( cur_screen, *start, row, col );
112384d9c625SLionel Sambuc 	    col = 0;
112484d9c625SLionel Sambuc 	    *start = Linear( cur_screen, row, col );
112584d9c625SLionel Sambuc 	    break;
112684d9c625SLionel Sambuc     }
112784d9c625SLionel Sambuc }
112884d9c625SLionel Sambuc 
112984d9c625SLionel Sambuc 
113084d9c625SLionel Sambuc #if defined(__STDC__)
right_expand_selection(xvi_screen * cur_screen,int * end)113184d9c625SLionel Sambuc static	void	right_expand_selection( xvi_screen *cur_screen, int *end )
113284d9c625SLionel Sambuc #else
113384d9c625SLionel Sambuc static	void	right_expand_selection( cur_screen, end )
113484d9c625SLionel Sambuc xvi_screen	*cur_screen;
113584d9c625SLionel Sambuc int		*end;
113684d9c625SLionel Sambuc #endif
113784d9c625SLionel Sambuc {
113884d9c625SLionel Sambuc     int row, col, last = cur_screen->cols * cur_screen->rows - 1;
113984d9c625SLionel Sambuc 
114084d9c625SLionel Sambuc     switch ( select_type ) {
114184d9c625SLionel Sambuc 	case select_word:
114284d9c625SLionel Sambuc 	    if ( *end == last || isspace( (unsigned char)cur_screen->characters[*end] ) )
114384d9c625SLionel Sambuc 		return;
114484d9c625SLionel Sambuc 	    for (;;) {
114584d9c625SLionel Sambuc 		if ( isspace( (unsigned char)cur_screen->characters[*end+1] ) )
114684d9c625SLionel Sambuc 		    return;
114784d9c625SLionel Sambuc 		if ( ++(*end) == last )
114884d9c625SLionel Sambuc 		   return;
114984d9c625SLionel Sambuc 	    }
115084d9c625SLionel Sambuc 	case select_line:
115184d9c625SLionel Sambuc 	    ToRowCol( cur_screen, *end, row, col );
115284d9c625SLionel Sambuc 	    col = cur_screen->cols -1;
115384d9c625SLionel Sambuc 	    *end = Linear( cur_screen, row, col );
115484d9c625SLionel Sambuc 	    break;
115584d9c625SLionel Sambuc     }
115684d9c625SLionel Sambuc }
115784d9c625SLionel Sambuc 
115884d9c625SLionel Sambuc 
115984d9c625SLionel Sambuc #if defined(__STDC__)
select_start(Widget widget,XEvent * event,String str,Cardinal * cardinal)116084d9c625SLionel Sambuc static	void	select_start( Widget widget,
116184d9c625SLionel Sambuc 			      XEvent *event,
116284d9c625SLionel Sambuc 			      String str,
116384d9c625SLionel Sambuc 			      Cardinal *cardinal
116484d9c625SLionel Sambuc 			      )
116584d9c625SLionel Sambuc #else
116684d9c625SLionel Sambuc static	void	select_start( widget, event, str, cardinal )
116784d9c625SLionel Sambuc Widget		widget;
116884d9c625SLionel Sambuc XEvent		*event;
116984d9c625SLionel Sambuc String		str;
117084d9c625SLionel Sambuc Cardinal        *cardinal;
117184d9c625SLionel Sambuc #endif
117284d9c625SLionel Sambuc {
117384d9c625SLionel Sambuc     IP_BUF		ipb;
117484d9c625SLionel Sambuc     int			xpos, ypos;
117584d9c625SLionel Sambuc     XPointerMovedEvent	*ev = (XPointerMovedEvent *) event;
117684d9c625SLionel Sambuc     static int		last_click;
117784d9c625SLionel Sambuc 
117884d9c625SLionel Sambuc     /*
117984d9c625SLionel Sambuc      * NOTE: when multiple panes are implemented, we need to find the correct
118084d9c625SLionel Sambuc      * screen.  For now, there is only one.
118184d9c625SLionel Sambuc      */
118284d9c625SLionel Sambuc     xpos = COLUMN( __vi_screen, ev->x );
118384d9c625SLionel Sambuc     ypos = ROW( __vi_screen, ev->y );
118484d9c625SLionel Sambuc 
118584d9c625SLionel Sambuc     /* Remove the old one. */
118684d9c625SLionel Sambuc     erase_selection( __vi_screen, selection_start, selection_end );
118784d9c625SLionel Sambuc 
118884d9c625SLionel Sambuc     /* Send the new cursor position. */
118984d9c625SLionel Sambuc     ipb.code = VI_MOUSE_MOVE;
119084d9c625SLionel Sambuc     ipb.val1 = ypos;
119184d9c625SLionel Sambuc     ipb.val2 = xpos;
119284d9c625SLionel Sambuc     (void)vi_send(vi_ofd, "12", &ipb);
119384d9c625SLionel Sambuc 
119484d9c625SLionel Sambuc     /* click-click, and we go for words, lines, etc */
119584d9c625SLionel Sambuc     if ( ev->time - last_click < multi_click_length )
119684d9c625SLionel Sambuc 	select_type = (enum select_enum) ((((int)select_type)+1)%3);
119784d9c625SLionel Sambuc     else
119884d9c625SLionel Sambuc 	select_type = select_char;
119984d9c625SLionel Sambuc     last_click = ev->time;
120084d9c625SLionel Sambuc 
120184d9c625SLionel Sambuc     /* put the selection here */
120284d9c625SLionel Sambuc     selection_anchor	= Linear( __vi_screen, ypos, xpos );
120384d9c625SLionel Sambuc     selection_start	= selection_anchor;
120484d9c625SLionel Sambuc     selection_end	= selection_anchor;
120584d9c625SLionel Sambuc 
120684d9c625SLionel Sambuc     /* expand to include words, line, etc */
120784d9c625SLionel Sambuc     left_expand_selection( __vi_screen, &selection_start );
120884d9c625SLionel Sambuc     right_expand_selection( __vi_screen, &selection_end );
120984d9c625SLionel Sambuc 
121084d9c625SLionel Sambuc     /* draw the new one */
121184d9c625SLionel Sambuc     mark_selection( __vi_screen, selection_start, selection_end );
121284d9c625SLionel Sambuc 
121384d9c625SLionel Sambuc     /* and tell the window manager we own the selection */
121484d9c625SLionel Sambuc     if ( select_type != select_char ) {
121584d9c625SLionel Sambuc 	__vi_AcquirePrimary( widget );
121684d9c625SLionel Sambuc 	copy_to_clipboard( __vi_screen );
121784d9c625SLionel Sambuc     }
121884d9c625SLionel Sambuc }
121984d9c625SLionel Sambuc 
122084d9c625SLionel Sambuc 
122184d9c625SLionel Sambuc #if defined(__STDC__)
select_extend(Widget widget,XEvent * event,String str,Cardinal * cardinal)122284d9c625SLionel Sambuc static	void	select_extend( Widget widget,
122384d9c625SLionel Sambuc 			       XEvent *event,
122484d9c625SLionel Sambuc 			       String str,
122584d9c625SLionel Sambuc 			       Cardinal *cardinal
122684d9c625SLionel Sambuc 			       )
122784d9c625SLionel Sambuc #else
122884d9c625SLionel Sambuc static	void	select_extend( widget, event, str, cardinal )
122984d9c625SLionel Sambuc Widget		widget;
123084d9c625SLionel Sambuc XEvent		*event;
123184d9c625SLionel Sambuc String		str;
123284d9c625SLionel Sambuc Cardinal        *cardinal;
123384d9c625SLionel Sambuc #endif
123484d9c625SLionel Sambuc {
123584d9c625SLionel Sambuc     int			xpos, ypos, pos;
123684d9c625SLionel Sambuc     XPointerMovedEvent	*ev = (XPointerMovedEvent *) event;
123784d9c625SLionel Sambuc 
123884d9c625SLionel Sambuc     /* NOTE:  when multiple panes are implemented, we need to find
123984d9c625SLionel Sambuc      * the correct screen.  For now, there is only one.
124084d9c625SLionel Sambuc      */
124184d9c625SLionel Sambuc     xpos = COLUMN( __vi_screen, ev->x );
124284d9c625SLionel Sambuc     ypos = ROW( __vi_screen, ev->y );
124384d9c625SLionel Sambuc 
124484d9c625SLionel Sambuc     /* deal with words, lines, etc */
124584d9c625SLionel Sambuc     pos = Linear( __vi_screen, ypos, xpos );
124684d9c625SLionel Sambuc     if ( pos < selection_anchor )
124784d9c625SLionel Sambuc 	left_expand_selection( __vi_screen, &pos );
124884d9c625SLionel Sambuc     else
124984d9c625SLionel Sambuc 	right_expand_selection( __vi_screen, &pos );
125084d9c625SLionel Sambuc 
125184d9c625SLionel Sambuc     /* extend from before the start? */
125284d9c625SLionel Sambuc     if ( pos < selection_start ) {
125384d9c625SLionel Sambuc 	mark_selection( __vi_screen, pos, selection_start-1 );
125484d9c625SLionel Sambuc 	selection_start = pos;
125584d9c625SLionel Sambuc     }
125684d9c625SLionel Sambuc 
125784d9c625SLionel Sambuc     /* extend past the end? */
125884d9c625SLionel Sambuc     else if ( pos > selection_end ) {
125984d9c625SLionel Sambuc 	mark_selection( __vi_screen, selection_end+1, pos );
126084d9c625SLionel Sambuc 	selection_end = pos;
126184d9c625SLionel Sambuc     }
126284d9c625SLionel Sambuc 
126384d9c625SLionel Sambuc     /* between the anchor and the start? */
126484d9c625SLionel Sambuc     else if ( pos < selection_anchor ) {
126584d9c625SLionel Sambuc 	erase_selection( __vi_screen, selection_start, pos-1 );
126684d9c625SLionel Sambuc 	selection_start = pos;
126784d9c625SLionel Sambuc     }
126884d9c625SLionel Sambuc 
126984d9c625SLionel Sambuc     /* between the anchor and the end? */
127084d9c625SLionel Sambuc     else {
127184d9c625SLionel Sambuc 	erase_selection( __vi_screen, pos+1, selection_end );
127284d9c625SLionel Sambuc 	selection_end = pos;
127384d9c625SLionel Sambuc     }
127484d9c625SLionel Sambuc 
127584d9c625SLionel Sambuc     /* and tell the window manager we own the selection */
127684d9c625SLionel Sambuc     __vi_AcquirePrimary( widget );
127784d9c625SLionel Sambuc     copy_to_clipboard( __vi_screen );
127884d9c625SLionel Sambuc }
127984d9c625SLionel Sambuc 
128084d9c625SLionel Sambuc 
128184d9c625SLionel Sambuc #if defined(__STDC__)
select_paste(Widget widget,XEvent * event,String str,Cardinal * cardinal)128284d9c625SLionel Sambuc static	void	select_paste( Widget widget,
128384d9c625SLionel Sambuc 			      XEvent *event,
128484d9c625SLionel Sambuc 			      String str,
128584d9c625SLionel Sambuc 			      Cardinal *cardinal
128684d9c625SLionel Sambuc 			      )
128784d9c625SLionel Sambuc #else
128884d9c625SLionel Sambuc static	void	select_paste( widget, event, str, cardinal )
128984d9c625SLionel Sambuc Widget		widget;
129084d9c625SLionel Sambuc XEvent		*event;
129184d9c625SLionel Sambuc String		str;
129284d9c625SLionel Sambuc Cardinal        *cardinal;
129384d9c625SLionel Sambuc #endif
129484d9c625SLionel Sambuc {
129584d9c625SLionel Sambuc     __vi_PasteFromClipboard( widget );
129684d9c625SLionel Sambuc }
129784d9c625SLionel Sambuc 
129884d9c625SLionel Sambuc 
129984d9c625SLionel Sambuc /* Interface to copy and paste
130084d9c625SLionel Sambuc  * (a) callbacks from the window manager
130184d9c625SLionel Sambuc  *	f_copy	-	it wants our buffer
130284d9c625SLionel Sambuc  *	f_paste	-	it wants us to paste some text
130384d9c625SLionel Sambuc  *	f_clear	-	we've lost the selection, clear it
130484d9c625SLionel Sambuc  */
130584d9c625SLionel Sambuc 
130684d9c625SLionel Sambuc #if defined(__STDC__)
f_copy(String * buffer,int * len)130784d9c625SLionel Sambuc static	void	f_copy( String *buffer, int *len )
130884d9c625SLionel Sambuc #else
130984d9c625SLionel Sambuc static	void	f_copy( buffer, len )
131084d9c625SLionel Sambuc 	String	*buffer;
131184d9c625SLionel Sambuc 	int	*len;
131284d9c625SLionel Sambuc #endif
131384d9c625SLionel Sambuc {
131484d9c625SLionel Sambuc #ifdef TRACE
131584d9c625SLionel Sambuc     vtrace("f_copy() called");
131684d9c625SLionel Sambuc #endif
131784d9c625SLionel Sambuc     *buffer	= clipboard;
131884d9c625SLionel Sambuc     *len	= clipboard_length;
131984d9c625SLionel Sambuc }
132084d9c625SLionel Sambuc 
132184d9c625SLionel Sambuc 
132284d9c625SLionel Sambuc 
f_paste(int widget,int buffer,int length)132384d9c625SLionel Sambuc static	void	f_paste(int widget, int buffer, int length)
132484d9c625SLionel Sambuc {
132584d9c625SLionel Sambuc     /* NOTE:  when multiple panes are implemented, we need to find
132684d9c625SLionel Sambuc      * the correct screen.  For now, there is only one.
132784d9c625SLionel Sambuc      */
132884d9c625SLionel Sambuc #ifdef TRACE
132984d9c625SLionel Sambuc     vtrace("f_paste() called with '%*.*s'\n", length, length, buffer);
133084d9c625SLionel Sambuc #endif
133184d9c625SLionel Sambuc }
133284d9c625SLionel Sambuc 
133384d9c625SLionel Sambuc 
133484d9c625SLionel Sambuc #if defined(__STDC__)
f_clear(Widget widget)133584d9c625SLionel Sambuc static	void	f_clear( Widget widget )
133684d9c625SLionel Sambuc #else
133784d9c625SLionel Sambuc static	void	f_clear( widget )
133884d9c625SLionel Sambuc Widget	widget;
133984d9c625SLionel Sambuc #endif
134084d9c625SLionel Sambuc {
134184d9c625SLionel Sambuc     xvi_screen	*cur_screen;
134284d9c625SLionel Sambuc 
134384d9c625SLionel Sambuc #ifdef TRACE
134484d9c625SLionel Sambuc     vtrace("f_clear() called");
134584d9c625SLionel Sambuc #endif
134684d9c625SLionel Sambuc 
134784d9c625SLionel Sambuc     XtVaGetValues( widget, XmNuserData, &cur_screen, 0 );
134884d9c625SLionel Sambuc 
134984d9c625SLionel Sambuc     erase_selection( cur_screen, selection_start, selection_end );
135084d9c625SLionel Sambuc }
135184d9c625SLionel Sambuc 
135284d9c625SLionel Sambuc 
135384d9c625SLionel Sambuc /*
135484d9c625SLionel Sambuc  * These routines deal with the cursor.
135584d9c625SLionel Sambuc  *
135684d9c625SLionel Sambuc  * PUBLIC: void __vi_set_cursor __P((xvi_screen *, int));
135784d9c625SLionel Sambuc  */
135884d9c625SLionel Sambuc void
__vi_set_cursor(xvi_screen * cur_screen,int is_busy)135984d9c625SLionel Sambuc __vi_set_cursor(xvi_screen *cur_screen, int is_busy)
136084d9c625SLionel Sambuc {
136184d9c625SLionel Sambuc     XDefineCursor( XtDisplay(cur_screen->area),
136284d9c625SLionel Sambuc 		   XtWindow(cur_screen->area),
136384d9c625SLionel Sambuc 		   (is_busy) ? busy_cursor : std_cursor
136484d9c625SLionel Sambuc 		   );
136584d9c625SLionel Sambuc }
136684d9c625SLionel Sambuc 
136784d9c625SLionel Sambuc 
136884d9c625SLionel Sambuc 
136984d9c625SLionel Sambuc /* hooks for the tags widget */
137084d9c625SLionel Sambuc 
137184d9c625SLionel Sambuc static	String	cur_word = NULL;
137284d9c625SLionel Sambuc 
137384d9c625SLionel Sambuc /*
137484d9c625SLionel Sambuc  * PUBLIC: void __vi_set_word_at_caret __P((xvi_screen *));
137584d9c625SLionel Sambuc  */
137684d9c625SLionel Sambuc void
__vi_set_word_at_caret(xvi_screen * this_screen)137784d9c625SLionel Sambuc __vi_set_word_at_caret(xvi_screen *this_screen)
137884d9c625SLionel Sambuc {
137984d9c625SLionel Sambuc     char	*start, *end, save;
138084d9c625SLionel Sambuc     int		newx, newy;
138184d9c625SLionel Sambuc 
138284d9c625SLionel Sambuc     newx = this_screen->curx;
138384d9c625SLionel Sambuc     newy = this_screen->cury;
138484d9c625SLionel Sambuc 
138584d9c625SLionel Sambuc     /* Note that this really ought to be done by core due to wrapping issues */
138684d9c625SLionel Sambuc     for ( end = start = CharAt( this_screen, newy, newx );
138784d9c625SLionel Sambuc 	  (isalnum( (unsigned char)*end ) || *end == '_') && (newx < this_screen->cols);
138884d9c625SLionel Sambuc 	  end++, newx++
138984d9c625SLionel Sambuc 	  );
139084d9c625SLionel Sambuc     save = *end;
139184d9c625SLionel Sambuc     *end = '\0';
139284d9c625SLionel Sambuc     if ( cur_word != NULL ) free( cur_word );
139384d9c625SLionel Sambuc     cur_word = strdup( start );
139484d9c625SLionel Sambuc     *end = save;
139584d9c625SLionel Sambuc 
139684d9c625SLionel Sambuc     /* if the tag stack widget is active, set the text field there
139784d9c625SLionel Sambuc      * to agree with the current caret position.
139884d9c625SLionel Sambuc      */
139984d9c625SLionel Sambuc     __vi_set_tag_text( cur_word );
140084d9c625SLionel Sambuc }
140184d9c625SLionel Sambuc 
140284d9c625SLionel Sambuc 
__vi_get_word_at_caret(xvi_screen * this_screen)140384d9c625SLionel Sambuc String	__vi_get_word_at_caret(xvi_screen *this_screen)
140484d9c625SLionel Sambuc {
140584d9c625SLionel Sambuc     return (cur_word) ? cur_word : "";
140684d9c625SLionel Sambuc }
140784d9c625SLionel Sambuc 
140884d9c625SLionel Sambuc 
140984d9c625SLionel Sambuc /*
141084d9c625SLionel Sambuc  * These routines deal with the caret.
141184d9c625SLionel Sambuc  *
141284d9c625SLionel Sambuc  * PUBLIC: void draw_caret __P((xvi_screen *));
141384d9c625SLionel Sambuc  */
141484d9c625SLionel Sambuc static void
draw_caret(xvi_screen * this_screen)141584d9c625SLionel Sambuc draw_caret(xvi_screen *this_screen)
141684d9c625SLionel Sambuc {
141784d9c625SLionel Sambuc     /* draw the caret by drawing the text in highlight color */
141884d9c625SLionel Sambuc     *FlagAt( this_screen, this_screen->cury, this_screen->curx ) |= COLOR_CARET;
141984d9c625SLionel Sambuc     __vi_draw_text( this_screen, this_screen->cury, this_screen->curx, 1 );
142084d9c625SLionel Sambuc }
142184d9c625SLionel Sambuc 
142284d9c625SLionel Sambuc /*
142384d9c625SLionel Sambuc  * PUBLIC: void __vi_erase_caret __P((xvi_screen *));
142484d9c625SLionel Sambuc  */
142584d9c625SLionel Sambuc void
__vi_erase_caret(xvi_screen * this_screen)142684d9c625SLionel Sambuc __vi_erase_caret(xvi_screen *this_screen)
142784d9c625SLionel Sambuc {
142884d9c625SLionel Sambuc     /* erase the caret by drawing the text in normal video */
142984d9c625SLionel Sambuc     *FlagAt( this_screen, this_screen->cury, this_screen->curx ) &= ~COLOR_CARET;
143084d9c625SLionel Sambuc     __vi_draw_text( this_screen, this_screen->cury, this_screen->curx, 1 );
143184d9c625SLionel Sambuc }
143284d9c625SLionel Sambuc 
143384d9c625SLionel Sambuc /*
143484d9c625SLionel Sambuc  * PUBLIC: void	__vi_move_caret __P((xvi_screen *, int, int));
143584d9c625SLionel Sambuc  */
143684d9c625SLionel Sambuc void
__vi_move_caret(xvi_screen * this_screen,int newy,int newx)143784d9c625SLionel Sambuc __vi_move_caret(xvi_screen *this_screen, int newy, int newx)
143884d9c625SLionel Sambuc {
143984d9c625SLionel Sambuc     /* remove the old caret */
144084d9c625SLionel Sambuc     __vi_erase_caret( this_screen );
144184d9c625SLionel Sambuc 
144284d9c625SLionel Sambuc     /* caret is now here */
144384d9c625SLionel Sambuc     this_screen->curx = newx;
144484d9c625SLionel Sambuc     this_screen->cury = newy;
144584d9c625SLionel Sambuc     draw_caret( this_screen );
144684d9c625SLionel Sambuc }
1447