Function-Key Transitions for Selection Service

Martin Boyer ireq-robot!gamin at larry.mcrcim.mcgill.edu
Thu Mar 1 10:08:00 AEST 1990


I am working on a replacement for shelltool with the following
capabilities:

    - dynamic font selection (change font after tool creation)
    - cursor attributes (block/underline, solid/blinking)
    - control over highlighting (bold, reverse video, underscore, color)
    - color (background, foreground, mouse, etc.)

It's in a pretty good shape now; I still have to add color, which will be
no trouble (I've done it for emacs), and the interface to the selection
service.  The latter is causing me great pains; it seems that this is
handled by default by the panel and tty windows, but I can't get it to
work with a canvas window (which I need in order to have full control over
the rendering of text).  I am using SunOS 4.0.3 on a Sun 3.

The problem is:

Although I can set and retrieve the primary selection with the selection
service, I can't do anything with the left function keys (COPY, PASTE,
FIND, and CUT) because I can't register them properly with the selection
service.  The first subsection in section 9.5 of the May 88 version of the
SunView System Programmer's Guide discusses `Reporting Function-Key
Transitions'.  I believe I am using seln_report_event() properly, but the
key transitions do not seem to affect the state of the selection service
(I verified with seln_get_function_state()).  This prevents me from
implementing the very common COPY and PASTE sequence of operations with
the L6 and L8 keys.  This also prevents the implementation of secondary
selections (not that they are very useful in a terminal emulator, but I
want it to be complete).  What's more, it seems that my application
somehow retains the caret too long since if I hit COPY in *another*
window, my application's primary selection gets shelved.  This reinforces
my suspicion; my function key transitions are not reported properly to the
selection service.

By the way, I tried seln_dump_service(SELN_UNSPECIFIED), as described on
page 114 of the Guide, but I keep getting core dumps in that function.

Has anybody used the selection library?  Can anybody give me a hint?  I
suppose that I am just trying to reinvent the wheel because the
functionality is already standard for certain windows; perhaps some kind
soul at Sun would care to send me the relevant portions of the code.

In return, you'll be the first one to receive my sources once it is
completed (it will make a very nice emacstool: ever dreamed about cursor,
mouse, and modelines in color?).

For starters, here's what I believe to be relevant portions of the code.
The selection handlers (func_key_proc() and reply_proc()) are pretty much
standard, adapted from seln_demo.c

  canvas = window_create(topwin, CANVAS,
                         CANVAS_FIXED_IMAGE, FALSE,
                         CANVAS_RETAINED, FALSE,
                         CANVAS_REPAINT_PROC, canvas_repaint,
                         CANVAS_RESIZE_PROC, canvas_resize,
                         WIN_CONSUME_KBD_EVENTS,
                         WIN_ASCII_EVENTS, WIN_LEFT_KEYS, WIN_UP_EVENTS, 0,
                         WIN_CONSUME_PICK_EVENT, LOC_DRAG,
                         WIN_IGNORE_PICK_EVENT, LOC_MOVE,
                         WIN_EVENT_PROC, canvas_event_handler,
                         0);

void
init_selection()
{
  int i;

  s_client = seln_create(func_key_proc, reply_proc, (caddr_t)NULL);
  if (s_client == NULL) {
    fprintf(stderr, "%s: seln_create failed!\n", Progname);
    exit(1);
  }
}

/* These event_ids are not standard SunView event_ids.
 * In my opinion, they should be; it would make mouse tracking SO much simpler.
 */
#define DRAG_LEFT   1000
#define DRAG_MIDDLE 1001

void
canvas_event_handler(window, event, arg)
     Window window;
     Event *event;
     caddr_t arg;
{
  static int      left_pressed = FALSE;
  static int      middle_pressed = FALSE;
  static int 	  start_x, start_y;
  int 	    	  action;

  action = event_action(event);

  /* User ASCII keystrokes. */
  if (action <= 256) {
    char c;

    c = (char) action;
    typein(&c, 1);
    return;
  }

  if (event_is_up(event) && event_is_button(event)) {
    switch (action) {
    case MS_LEFT:
      if (left_pressed) {
	left_pressed = FALSE;
	start_x = event_x(event);
	start_y = event_y(event);
	set_selection(PRIMARY_SELECTION);
      }
      break;
    case MS_MIDDLE:
      if (middle_pressed) {
	middle_pressed = FALSE;
	set_selection(PRIMARY_SELECTION);
      }
      break;
    default:
      break;
    }
    return;
  }

  if (action == LOC_DRAG) {
    if (left_pressed)
      action = DRAG_LEFT;
    if (middle_pressed)
      action = DRAG_MIDDLE;
  }

  /* On left button down, track the beginning of the selection,
   * on middle button down, track the end of the selection,
   * clean up on exiting the window if button wasn't released.
   */
    switch (action) {
    case MS_LEFT:
      left_pressed = TRUE;
    case DRAG_LEFT:
      select_region(event_x(event), event_y(event),
		    event_x(event), event_y(event), PRIMARY_SELECTION);
      break;

    case MS_MIDDLE:
      middle_pressed = TRUE;
    case DRAG_MIDDLE:
      select_region(start_x, start_y,
		    event_x(event), event_y(event), PRIMARY_SELECTION);
      break;

    case MS_RIGHT:
      insert_selection(PRIMARY_SELECTION);
      break;

    case LOC_RGNEXIT:
      break;
    case LOC_RGNENTER:
      seln_acquire(s_client, SELN_CARET);
      break;

    default:

      if (event_is_key_left(event))
	printf("COPY is %s",
	       seln_get_function_state(SELN_FN_PUT) ? "down" : "up");

      seln_report_event(s_client, event);

      if (event_is_key_left(event))
	printf(" then %s.\n",
	       seln_get_function_state(SELN_FN_PUT) ? "down" : "up");

      break;
    }
}


Thanks,

Martin Boyer                         ireq-robot!mboyer at Larry.McRCIM.McGILL.EDU
Institut de recherche d'Hydro-Quebec mboyer at ireq-robot.uucp
Varennes, QC, Canada   J3X 1S1
+1 514 652-8136



More information about the Comp.sys.sun mailing list