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